* [PATCH 1/8] net/ntnic: initial commit which adds register defines
@ 2023-08-16 13:25 Mykola Kostenok
2023-08-16 13:25 ` [PATCH 2/8] net/ntnic: adds core registers and fpga functionality Mykola Kostenok
` (20 more replies)
0 siblings, 21 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
The NTNIC PMD does not rely on a kernel space Napatech driver,
thus all defines related to the register layout is part of the PMD
code, which will be added in later commits.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/meson.build | 1 +
drivers/net/ntnic/include/fpga_model.h | 99 +
drivers/net/ntnic/meson.build | 29 +
drivers/net/ntnic/nthw/nthw_register.h | 19 +
.../supported/nthw_fpga_9563_055_024_0000.c | 4190 ++++++++++
.../nthw/supported/nthw_fpga_instances.h | 14 +
.../nthw/supported/nthw_fpga_modules_defs.h | 166 +
.../supported/nthw_fpga_parameters_defs.h | 209 +
.../nthw/supported/nthw_fpga_registers_defs.h | 7277 +++++++++++++++++
9 files changed, 12004 insertions(+)
create mode 100644 drivers/net/ntnic/include/fpga_model.h
create mode 100644 drivers/net/ntnic/meson.build
create mode 100644 drivers/net/ntnic/nthw/nthw_register.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h
diff --git a/drivers/net/meson.build b/drivers/net/meson.build
index bd38b533c5..fb6d34b782 100644
--- a/drivers/net/meson.build
+++ b/drivers/net/meson.build
@@ -45,6 +45,7 @@ drivers = [
'nfb',
'nfp',
'ngbe',
+ 'ntnic',
'null',
'octeontx',
'octeon_ep',
diff --git a/drivers/net/ntnic/include/fpga_model.h b/drivers/net/ntnic/include/fpga_model.h
new file mode 100644
index 0000000000..89f1ae9736
--- /dev/null
+++ b/drivers/net/ntnic/include/fpga_model.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef FPGA_MODEL_H_
+#define FPGA_MODEL_H_
+
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+enum nt_fpga_bus_type {
+ BUS_TYPE_UNKNOWN =
+ 0, /* Unknown/uninitialized - keep this as the first enum element */
+ BUS_TYPE_BAR,
+ BUS_TYPE_PCI,
+ BUS_TYPE_CCIP,
+ BUS_TYPE_RAB0,
+ BUS_TYPE_RAB1,
+ BUS_TYPE_RAB2,
+ BUS_TYPE_NMB,
+ BUS_TYPE_NDM,
+ BUS_TYPE_SPI0,
+ BUS_TYPE_SPI = BUS_TYPE_SPI0,
+};
+
+typedef enum nt_fpga_bus_type nt_fpga_bus_type_t;
+
+enum nt_fpga_register_type {
+ REGISTER_TYPE_UNKNOWN =
+ 0, /* Unknown/uninitialized - keep this as the first enum element */
+ REGISTER_TYPE_RW,
+ REGISTER_TYPE_RO,
+ REGISTER_TYPE_WO,
+ REGISTER_TYPE_RC1,
+ REGISTER_TYPE_MIXED,
+};
+
+typedef enum nt_fpga_register_type nt_fpga_register_type_t;
+
+struct nt_fpga_field_init {
+ int id;
+ uint16_t bw;
+ uint16_t low;
+ uint64_t reset_val;
+};
+
+typedef struct nt_fpga_field_init nt_fpga_field_init_t;
+
+struct nt_fpga_register_init {
+ int id;
+ uint32_t addr_rel;
+ uint16_t bw;
+ nt_fpga_register_type_t type;
+ uint64_t reset_val;
+ int nb_fields;
+ struct nt_fpga_field_init *fields;
+};
+
+typedef struct nt_fpga_register_init nt_fpga_register_init_t;
+
+struct nt_fpga_module_init {
+ int id;
+ int instance;
+ int def_id;
+ int major_version;
+ int minor_version;
+ nt_fpga_bus_type_t bus_id;
+ uint32_t addr_base;
+ int nb_registers;
+ struct nt_fpga_register_init *registers;
+};
+
+typedef struct nt_fpga_module_init nt_fpga_module_init_t;
+
+struct nt_fpga_prod_param {
+ const int param_id;
+ const int param_value;
+};
+
+typedef struct nt_fpga_prod_param nt_fpga_prod_param_t;
+
+struct nt_fpga_prod_init {
+ int fpga_item_id;
+ int fpga_product_id;
+ int fpga_version;
+ int fpga_revision;
+ int fpga_patch_no;
+ int fpga_build_no;
+ uint32_t fpga_build_time;
+ int nb_prod_params;
+ struct nt_fpga_prod_param *product_params;
+ int nb_modules;
+ struct nt_fpga_module_init *modules;
+};
+
+typedef struct nt_fpga_prod_init nt_fpga_prod_init_t;
+
+#endif /* FPGA_MODEL_H_ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
new file mode 100644
index 0000000000..99569c2843
--- /dev/null
+++ b/drivers/net/ntnic/meson.build
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020-2023 Napatech A/S
+
+# cflags
+cflags += [
+ '-std=c11',
+]
+
+# includes
+includes = [
+ include_directories('.'),
+ include_directories('include'),
+ include_directories('nthw'),
+ include_directories('nthw/supported'),
+]
+
+# all sources
+sources = files(
+ 'nthw/supported/nthw_fpga_9563_055_024_0000.c',
+)
+
+if is_variable('default_cflags')
+ cflags += default_cflags
+else
+ cflags += machine_args
+ cflags += ['-DALLOW_INTERNAL_API']
+endif
+
+# END
diff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h
new file mode 100644
index 0000000000..5cdbd9fc5d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_register.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_REGISTER_H_
+#define NTHW_REGISTER_H_
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "fpga_model.h"
+
+#include "nthw_fpga_modules_defs.h"
+#include "nthw_fpga_parameters_defs.h"
+#include "nthw_fpga_registers_defs.h"
+
+#endif /* NTHW_REGISTER_H_ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c b/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c
new file mode 100644
index 0000000000..b8113b40da
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c
@@ -0,0 +1,4190 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_register.h"
+
+static nt_fpga_field_init_t cat_cct_ctrl_fields[] = {
+ { CAT_CCT_CTRL_ADR, 8, 0, 0x0000 },
+ { CAT_CCT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cct_data_fields[] = {
+ { CAT_CCT_DATA_COLOR, 32, 0, 0x0000 },
+ { CAT_CCT_DATA_KM, 4, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cfn_ctrl_fields[] = {
+ { CAT_CFN_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_CFN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cfn_data_fields[] = {
+ { CAT_CFN_DATA_ENABLE, 1, 0, 0x0000 },
+ { CAT_CFN_DATA_ERR_CV, 2, 99, 0x0000 },
+ { CAT_CFN_DATA_ERR_FCS, 2, 101, 0x0000 },
+ { CAT_CFN_DATA_ERR_INV, 1, 98, 0x0000 },
+ { CAT_CFN_DATA_ERR_L3_CS, 2, 105, 0x0000 },
+ { CAT_CFN_DATA_ERR_L4_CS, 2, 107, 0x0000 },
+ { CAT_CFN_DATA_ERR_TNL_L3_CS, 2, 109, 0x0000 },
+ { CAT_CFN_DATA_ERR_TNL_L4_CS, 2, 111, 0x0000 },
+ { CAT_CFN_DATA_ERR_TNL_TTL_EXP, 2, 115, 0x0000 },
+ { CAT_CFN_DATA_ERR_TRUNC, 2, 103, 0x0000 },
+ { CAT_CFN_DATA_ERR_TTL_EXP, 2, 113, 0x0000 },
+ { CAT_CFN_DATA_INV, 1, 1, 0x0000 },
+ { CAT_CFN_DATA_KM0_OR, 3, 173, 0x0000 },
+ { CAT_CFN_DATA_KM1_OR, 3, 176, 0x0000 },
+ { CAT_CFN_DATA_LC, 8, 164, 0x0000 },
+ { CAT_CFN_DATA_LC_INV, 1, 172, 0x0000 },
+ { CAT_CFN_DATA_MAC_PORT, 2, 117, 0x0000 },
+ { CAT_CFN_DATA_PM_AND_INV, 1, 161, 0x0000 },
+ { CAT_CFN_DATA_PM_CMB, 4, 157, 0x0000 },
+ { CAT_CFN_DATA_PM_CMP, 32, 119, 0x0000 },
+ { CAT_CFN_DATA_PM_DCT, 2, 151, 0x0000 },
+ { CAT_CFN_DATA_PM_EXT_INV, 4, 153, 0x0000 },
+ { CAT_CFN_DATA_PM_INV, 1, 163, 0x0000 },
+ { CAT_CFN_DATA_PM_OR_INV, 1, 162, 0x0000 },
+ { CAT_CFN_DATA_PTC_CFP, 2, 5, 0x0000 },
+ { CAT_CFN_DATA_PTC_FRAG, 4, 36, 0x0000 },
+ { CAT_CFN_DATA_PTC_INV, 1, 2, 0x0000 },
+ { CAT_CFN_DATA_PTC_IP_PROT, 8, 40, 0x0000 },
+ { CAT_CFN_DATA_PTC_ISL, 2, 3, 0x0000 },
+ { CAT_CFN_DATA_PTC_L2, 7, 12, 0x0000 },
+ { CAT_CFN_DATA_PTC_L3, 3, 33, 0x0000 },
+ { CAT_CFN_DATA_PTC_L4, 5, 48, 0x0000 },
+ { CAT_CFN_DATA_PTC_MAC, 5, 7, 0x0000 },
+ { CAT_CFN_DATA_PTC_MPLS, 8, 25, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_FRAG, 4, 81, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_IP_PROT, 8, 85, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_L2, 2, 64, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_L3, 3, 78, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_L4, 5, 93, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_MPLS, 8, 70, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_VLAN, 4, 66, 0x0000 },
+ { CAT_CFN_DATA_PTC_TUNNEL, 11, 53, 0x0000 },
+ { CAT_CFN_DATA_PTC_VLAN, 4, 21, 0x0000 },
+ { CAT_CFN_DATA_PTC_VNTAG, 2, 19, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cot_ctrl_fields[] = {
+ { CAT_COT_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_COT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cot_data_fields[] = {
+ { CAT_COT_DATA_COLOR, 32, 0, 0x0000 },
+ { CAT_COT_DATA_KM, 4, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cte_ctrl_fields[] = {
+ { CAT_CTE_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_CTE_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cte_data_fields[] = {
+ { CAT_CTE_DATA_COL_ENABLE, 1, 0, 0x0000 },
+ { CAT_CTE_DATA_COR_ENABLE, 1, 1, 0x0000 },
+ { CAT_CTE_DATA_EPP_ENABLE, 1, 9, 0x0000 },
+ { CAT_CTE_DATA_HSH_ENABLE, 1, 2, 0x0000 },
+ { CAT_CTE_DATA_HST_ENABLE, 1, 8, 0x0000 },
+ { CAT_CTE_DATA_IPF_ENABLE, 1, 4, 0x0000 },
+ { CAT_CTE_DATA_MSK_ENABLE, 1, 7, 0x0000 },
+ { CAT_CTE_DATA_PDB_ENABLE, 1, 6, 0x0000 },
+ { CAT_CTE_DATA_QSL_ENABLE, 1, 3, 0x0000 },
+ { CAT_CTE_DATA_SLC_ENABLE, 1, 5, 0x0000 },
+ { CAT_CTE_DATA_TPE_ENABLE, 1, 10, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cts_ctrl_fields[] = {
+ { CAT_CTS_CTRL_ADR, 9, 0, 0x0000 },
+ { CAT_CTS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cts_data_fields[] = {
+ { CAT_CTS_DATA_CAT_A, 6, 0, 0x0000 },
+ { CAT_CTS_DATA_CAT_B, 6, 6, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_dct_ctrl_fields[] = {
+ { CAT_DCT_CTRL_ADR, 13, 0, 0x0000 },
+ { CAT_DCT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_dct_data_fields[] = {
+ { CAT_DCT_DATA_RES, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_dct_sel_fields[] = {
+ { CAT_DCT_SEL_LU, 2, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_exo_ctrl_fields[] = {
+ { CAT_EXO_CTRL_ADR, 2, 0, 0x0000 },
+ { CAT_EXO_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_exo_data_fields[] = {
+ { CAT_EXO_DATA_DYN, 5, 0, 0x0000 },
+ { CAT_EXO_DATA_OFS, 11, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte0_ctrl_fields[] = {
+ { CAT_FTE0_CTRL_ADR, 9, 0, 0x0000 },
+ { CAT_FTE0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte0_data_fields[] = {
+ { CAT_FTE0_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte1_ctrl_fields[] = {
+ { CAT_FTE1_CTRL_ADR, 9, 0, 0x0000 },
+ { CAT_FTE1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte1_data_fields[] = {
+ { CAT_FTE1_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_join_fields[] = {
+ { CAT_JOIN_J1, 2, 0, 0x0000 },
+ { CAT_JOIN_J2, 1, 8, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcc_ctrl_fields[] = {
+ { CAT_KCC_CTRL_ADR, 11, 0, 0x0000 },
+ { CAT_KCC_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcc_data_fields[] = {
+ { CAT_KCC_DATA_CATEGORY, 8, 64, 0x0000 },
+ { CAT_KCC_DATA_ID, 12, 72, 0x0000 },
+ { CAT_KCC_DATA_KEY, 64, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce0_ctrl_fields[] = {
+ { CAT_KCE0_CTRL_ADR, 3, 0, 0x0000 },
+ { CAT_KCE0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce0_data_fields[] = {
+ { CAT_KCE0_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce1_ctrl_fields[] = {
+ { CAT_KCE1_CTRL_ADR, 3, 0, 0x0000 },
+ { CAT_KCE1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce1_data_fields[] = {
+ { CAT_KCE1_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs0_ctrl_fields[] = {
+ { CAT_KCS0_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_KCS0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs0_data_fields[] = {
+ { CAT_KCS0_DATA_CATEGORY, 6, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs1_ctrl_fields[] = {
+ { CAT_KCS1_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_KCS1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs1_data_fields[] = {
+ { CAT_KCS1_DATA_CATEGORY, 6, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_len_ctrl_fields[] = {
+ { CAT_LEN_CTRL_ADR, 3, 0, 0x0000 },
+ { CAT_LEN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_len_data_fields[] = {
+ { CAT_LEN_DATA_DYN1, 5, 28, 0x0000 },
+ { CAT_LEN_DATA_DYN2, 5, 33, 0x0000 },
+ { CAT_LEN_DATA_INV, 1, 38, 0x0000 },
+ { CAT_LEN_DATA_LOWER, 14, 0, 0x0000 },
+ { CAT_LEN_DATA_UPPER, 14, 14, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_rck_ctrl_fields[] = {
+ { CAT_RCK_CTRL_ADR, 8, 0, 0x0000 },
+ { CAT_RCK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_rck_data_fields[] = {
+ { CAT_RCK_DATA_CM0U, 1, 1, 0x0000 },
+ { CAT_RCK_DATA_CM1U, 1, 5, 0x0000 },
+ { CAT_RCK_DATA_CM2U, 1, 9, 0x0000 },
+ { CAT_RCK_DATA_CM3U, 1, 13, 0x0000 },
+ { CAT_RCK_DATA_CM4U, 1, 17, 0x0000 },
+ { CAT_RCK_DATA_CM5U, 1, 21, 0x0000 },
+ { CAT_RCK_DATA_CM6U, 1, 25, 0x0000 },
+ { CAT_RCK_DATA_CM7U, 1, 29, 0x0000 },
+ { CAT_RCK_DATA_CML0, 1, 0, 0x0000 },
+ { CAT_RCK_DATA_CML1, 1, 4, 0x0000 },
+ { CAT_RCK_DATA_CML2, 1, 8, 0x0000 },
+ { CAT_RCK_DATA_CML3, 1, 12, 0x0000 },
+ { CAT_RCK_DATA_CML4, 1, 16, 0x0000 },
+ { CAT_RCK_DATA_CML5, 1, 20, 0x0000 },
+ { CAT_RCK_DATA_CML6, 1, 24, 0x0000 },
+ { CAT_RCK_DATA_CML7, 1, 28, 0x0000 },
+ { CAT_RCK_DATA_SEL0, 1, 2, 0x0000 },
+ { CAT_RCK_DATA_SEL1, 1, 6, 0x0000 },
+ { CAT_RCK_DATA_SEL2, 1, 10, 0x0000 },
+ { CAT_RCK_DATA_SEL3, 1, 14, 0x0000 },
+ { CAT_RCK_DATA_SEL4, 1, 18, 0x0000 },
+ { CAT_RCK_DATA_SEL5, 1, 22, 0x0000 },
+ { CAT_RCK_DATA_SEL6, 1, 26, 0x0000 },
+ { CAT_RCK_DATA_SEL7, 1, 30, 0x0000 },
+ { CAT_RCK_DATA_SEU0, 1, 3, 0x0000 },
+ { CAT_RCK_DATA_SEU1, 1, 7, 0x0000 },
+ { CAT_RCK_DATA_SEU2, 1, 11, 0x0000 },
+ { CAT_RCK_DATA_SEU3, 1, 15, 0x0000 },
+ { CAT_RCK_DATA_SEU4, 1, 19, 0x0000 },
+ { CAT_RCK_DATA_SEU5, 1, 23, 0x0000 },
+ { CAT_RCK_DATA_SEU6, 1, 27, 0x0000 },
+ { CAT_RCK_DATA_SEU7, 1, 31, 0x0000 },
+};
+
+static nt_fpga_register_init_t cat_registers[] = {
+ { CAT_CCT_CTRL, 30, 32, REGISTER_TYPE_WO, 0, 2, cat_cct_ctrl_fields },
+ { CAT_CCT_DATA, 31, 36, REGISTER_TYPE_WO, 0, 2, cat_cct_data_fields },
+ { CAT_CFN_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, cat_cfn_ctrl_fields },
+ { CAT_CFN_DATA, 11, 179, REGISTER_TYPE_WO, 0, 44, cat_cfn_data_fields },
+ { CAT_COT_CTRL, 28, 32, REGISTER_TYPE_WO, 0, 2, cat_cot_ctrl_fields },
+ { CAT_COT_DATA, 29, 36, REGISTER_TYPE_WO, 0, 2, cat_cot_data_fields },
+ { CAT_CTE_CTRL, 24, 32, REGISTER_TYPE_WO, 0, 2, cat_cte_ctrl_fields },
+ { CAT_CTE_DATA, 25, 11, REGISTER_TYPE_WO, 0, 11, cat_cte_data_fields },
+ { CAT_CTS_CTRL, 26, 32, REGISTER_TYPE_WO, 0, 2, cat_cts_ctrl_fields },
+ { CAT_CTS_DATA, 27, 12, REGISTER_TYPE_WO, 0, 2, cat_cts_data_fields },
+ { CAT_DCT_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, cat_dct_ctrl_fields },
+ { CAT_DCT_DATA, 7, 16, REGISTER_TYPE_WO, 0, 1, cat_dct_data_fields },
+ { CAT_DCT_SEL, 4, 2, REGISTER_TYPE_WO, 0, 1, cat_dct_sel_fields },
+ { CAT_EXO_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, cat_exo_ctrl_fields },
+ { CAT_EXO_DATA, 1, 27, REGISTER_TYPE_WO, 0, 2, cat_exo_data_fields },
+ { CAT_FTE0_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2, cat_fte0_ctrl_fields },
+ { CAT_FTE0_DATA, 17, 8, REGISTER_TYPE_WO, 0, 1, cat_fte0_data_fields },
+ { CAT_FTE1_CTRL, 22, 32, REGISTER_TYPE_WO, 0, 2, cat_fte1_ctrl_fields },
+ { CAT_FTE1_DATA, 23, 8, REGISTER_TYPE_WO, 0, 1, cat_fte1_data_fields },
+ { CAT_JOIN, 5, 9, REGISTER_TYPE_WO, 0, 2, cat_join_fields },
+ { CAT_KCC_CTRL, 32, 32, REGISTER_TYPE_WO, 0, 2, cat_kcc_ctrl_fields },
+ { CAT_KCC_DATA, 33, 84, REGISTER_TYPE_WO, 0, 3, cat_kcc_data_fields },
+ { CAT_KCE0_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, cat_kce0_ctrl_fields },
+ { CAT_KCE0_DATA, 13, 8, REGISTER_TYPE_WO, 0, 1, cat_kce0_data_fields },
+ { CAT_KCE1_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2, cat_kce1_ctrl_fields },
+ { CAT_KCE1_DATA, 19, 8, REGISTER_TYPE_WO, 0, 1, cat_kce1_data_fields },
+ { CAT_KCS0_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2, cat_kcs0_ctrl_fields },
+ { CAT_KCS0_DATA, 15, 6, REGISTER_TYPE_WO, 0, 1, cat_kcs0_data_fields },
+ { CAT_KCS1_CTRL, 20, 32, REGISTER_TYPE_WO, 0, 2, cat_kcs1_ctrl_fields },
+ { CAT_KCS1_DATA, 21, 6, REGISTER_TYPE_WO, 0, 1, cat_kcs1_data_fields },
+ { CAT_LEN_CTRL, 8, 32, REGISTER_TYPE_WO, 0, 2, cat_len_ctrl_fields },
+ { CAT_LEN_DATA, 9, 39, REGISTER_TYPE_WO, 0, 5, cat_len_data_fields },
+ { CAT_RCK_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, cat_rck_ctrl_fields },
+ { CAT_RCK_DATA, 3, 32, REGISTER_TYPE_WO, 0, 32, cat_rck_data_fields },
+};
+
+static nt_fpga_field_init_t cpy_writer0_ctrl_fields[] = {
+ { CPY_WRITER0_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer0_data_fields[] = {
+ { CPY_WRITER0_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER0_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER0_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER0_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER0_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer0_mask_ctrl_fields[] = {
+ { CPY_WRITER0_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER0_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer0_mask_data_fields[] = {
+ { CPY_WRITER0_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_ctrl_fields[] = {
+ { CPY_WRITER1_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_data_fields[] = {
+ { CPY_WRITER1_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER1_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER1_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER1_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER1_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_mask_ctrl_fields[] = {
+ { CPY_WRITER1_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER1_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_mask_data_fields[] = {
+ { CPY_WRITER1_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_ctrl_fields[] = {
+ { CPY_WRITER2_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER2_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_data_fields[] = {
+ { CPY_WRITER2_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER2_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER2_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER2_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER2_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_mask_ctrl_fields[] = {
+ { CPY_WRITER2_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER2_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_mask_data_fields[] = {
+ { CPY_WRITER2_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_ctrl_fields[] = {
+ { CPY_WRITER3_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER3_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_data_fields[] = {
+ { CPY_WRITER3_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER3_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER3_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER3_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER3_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_mask_ctrl_fields[] = {
+ { CPY_WRITER3_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER3_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_mask_data_fields[] = {
+ { CPY_WRITER3_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_ctrl_fields[] = {
+ { CPY_WRITER4_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER4_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_data_fields[] = {
+ { CPY_WRITER4_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER4_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER4_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER4_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER4_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_mask_ctrl_fields[] = {
+ { CPY_WRITER4_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER4_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_mask_data_fields[] = {
+ { CPY_WRITER4_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t cpy_registers[] = {
+ { CPY_WRITER0_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer0_ctrl_fields
+ },
+ { CPY_WRITER0_DATA, 1, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer0_data_fields
+ },
+ { CPY_WRITER0_MASK_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer0_mask_ctrl_fields
+ },
+ { CPY_WRITER0_MASK_DATA, 3, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer0_mask_data_fields
+ },
+ { CPY_WRITER1_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer1_ctrl_fields
+ },
+ { CPY_WRITER1_DATA, 5, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer1_data_fields
+ },
+ { CPY_WRITER1_MASK_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer1_mask_ctrl_fields
+ },
+ { CPY_WRITER1_MASK_DATA, 7, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer1_mask_data_fields
+ },
+ { CPY_WRITER2_CTRL, 8, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer2_ctrl_fields
+ },
+ { CPY_WRITER2_DATA, 9, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer2_data_fields
+ },
+ { CPY_WRITER2_MASK_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer2_mask_ctrl_fields
+ },
+ { CPY_WRITER2_MASK_DATA, 11, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer2_mask_data_fields
+ },
+ { CPY_WRITER3_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer3_ctrl_fields
+ },
+ { CPY_WRITER3_DATA, 13, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer3_data_fields
+ },
+ { CPY_WRITER3_MASK_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer3_mask_ctrl_fields
+ },
+ { CPY_WRITER3_MASK_DATA, 15, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer3_mask_data_fields
+ },
+ { CPY_WRITER4_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer4_ctrl_fields
+ },
+ { CPY_WRITER4_DATA, 17, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer4_data_fields
+ },
+ { CPY_WRITER4_MASK_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer4_mask_ctrl_fields
+ },
+ { CPY_WRITER4_MASK_DATA, 19, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer4_mask_data_fields
+ },
+};
+
+static nt_fpga_field_init_t csu_rcp_ctrl_fields[] = {
+ { CSU_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { CSU_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t csu_rcp_data_fields[] = {
+ { CSU_RCP_DATA_IL3_CMD, 2, 5, 0x0000 },
+ { CSU_RCP_DATA_IL4_CMD, 3, 7, 0x0000 },
+ { CSU_RCP_DATA_OL3_CMD, 2, 0, 0x0000 },
+ { CSU_RCP_DATA_OL4_CMD, 3, 2, 0x0000 },
+};
+
+static nt_fpga_register_init_t csu_registers[] = {
+ { CSU_RCP_CTRL, 1, 32, REGISTER_TYPE_WO, 0, 2, csu_rcp_ctrl_fields },
+ { CSU_RCP_DATA, 2, 10, REGISTER_TYPE_WO, 0, 4, csu_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t dbs_rx_am_ctrl_fields[] = {
+ { DBS_RX_AM_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_RX_AM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_am_data_fields[] = {
+ { DBS_RX_AM_DATA_ENABLE, 1, 72, 0x0000 },
+ { DBS_RX_AM_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_RX_AM_DATA_HID, 8, 64, 0x0000 },
+ { DBS_RX_AM_DATA_INT, 1, 74, 0x0000 },
+ { DBS_RX_AM_DATA_PCKED, 1, 73, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_control_fields[] = {
+ { DBS_RX_CONTROL_AME, 1, 7, 0 }, { DBS_RX_CONTROL_AMS, 4, 8, 8 },
+ { DBS_RX_CONTROL_LQ, 7, 0, 0 }, { DBS_RX_CONTROL_QE, 1, 17, 0 },
+ { DBS_RX_CONTROL_UWE, 1, 12, 0 }, { DBS_RX_CONTROL_UWS, 4, 13, 5 },
+};
+
+static nt_fpga_field_init_t dbs_rx_dr_ctrl_fields[] = {
+ { DBS_RX_DR_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_RX_DR_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_dr_data_fields[] = {
+ { DBS_RX_DR_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_RX_DR_DATA_HDR, 1, 88, 0x0000 },
+ { DBS_RX_DR_DATA_HID, 8, 64, 0x0000 },
+ { DBS_RX_DR_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_RX_DR_DATA_QS, 15, 72, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_idle_fields[] = {
+ { DBS_RX_IDLE_BUSY, 1, 8, 0 },
+ { DBS_RX_IDLE_IDLE, 1, 0, 0x0000 },
+ { DBS_RX_IDLE_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_init_fields[] = {
+ { DBS_RX_INIT_BUSY, 1, 8, 0 },
+ { DBS_RX_INIT_INIT, 1, 0, 0x0000 },
+ { DBS_RX_INIT_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_init_val_fields[] = {
+ { DBS_RX_INIT_VAL_IDX, 16, 0, 0x0000 },
+ { DBS_RX_INIT_VAL_PTR, 15, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_ptr_fields[] = {
+ { DBS_RX_PTR_PTR, 16, 0, 0x0000 },
+ { DBS_RX_PTR_QUEUE, 7, 16, 0x0000 },
+ { DBS_RX_PTR_VALID, 1, 23, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_uw_ctrl_fields[] = {
+ { DBS_RX_UW_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_RX_UW_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_uw_data_fields[] = {
+ { DBS_RX_UW_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_RX_UW_DATA_HID, 8, 64, 0x0000 },
+ { DBS_RX_UW_DATA_INT, 1, 88, 0x0000 },
+ { DBS_RX_UW_DATA_ISTK, 1, 92, 0x0000 },
+ { DBS_RX_UW_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_RX_UW_DATA_QS, 15, 72, 0x0000 },
+ { DBS_RX_UW_DATA_VEC, 3, 89, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_am_ctrl_fields[] = {
+ { DBS_TX_AM_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_AM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_am_data_fields[] = {
+ { DBS_TX_AM_DATA_ENABLE, 1, 72, 0x0000 },
+ { DBS_TX_AM_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_TX_AM_DATA_HID, 8, 64, 0x0000 },
+ { DBS_TX_AM_DATA_INT, 1, 74, 0x0000 },
+ { DBS_TX_AM_DATA_PCKED, 1, 73, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_control_fields[] = {
+ { DBS_TX_CONTROL_AME, 1, 7, 0 }, { DBS_TX_CONTROL_AMS, 4, 8, 5 },
+ { DBS_TX_CONTROL_LQ, 7, 0, 0 }, { DBS_TX_CONTROL_QE, 1, 17, 0 },
+ { DBS_TX_CONTROL_UWE, 1, 12, 0 }, { DBS_TX_CONTROL_UWS, 4, 13, 8 },
+};
+
+static nt_fpga_field_init_t dbs_tx_dr_ctrl_fields[] = {
+ { DBS_TX_DR_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_DR_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_dr_data_fields[] = {
+ { DBS_TX_DR_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_TX_DR_DATA_HDR, 1, 88, 0x0000 },
+ { DBS_TX_DR_DATA_HID, 8, 64, 0x0000 },
+ { DBS_TX_DR_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_TX_DR_DATA_PORT, 1, 89, 0x0000 },
+ { DBS_TX_DR_DATA_QS, 15, 72, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_idle_fields[] = {
+ { DBS_TX_IDLE_BUSY, 1, 8, 0 },
+ { DBS_TX_IDLE_IDLE, 1, 0, 0x0000 },
+ { DBS_TX_IDLE_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_init_fields[] = {
+ { DBS_TX_INIT_BUSY, 1, 8, 0 },
+ { DBS_TX_INIT_INIT, 1, 0, 0x0000 },
+ { DBS_TX_INIT_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_init_val_fields[] = {
+ { DBS_TX_INIT_VAL_IDX, 16, 0, 0x0000 },
+ { DBS_TX_INIT_VAL_PTR, 15, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_ptr_fields[] = {
+ { DBS_TX_PTR_PTR, 16, 0, 0x0000 },
+ { DBS_TX_PTR_QUEUE, 7, 16, 0x0000 },
+ { DBS_TX_PTR_VALID, 1, 23, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qos_ctrl_fields[] = {
+ { DBS_TX_QOS_CTRL_ADR, 1, 0, 0x0000 },
+ { DBS_TX_QOS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qos_data_fields[] = {
+ { DBS_TX_QOS_DATA_BS, 27, 17, 0x0000 },
+ { DBS_TX_QOS_DATA_EN, 1, 0, 0x0000 },
+ { DBS_TX_QOS_DATA_IR, 16, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qos_rate_fields[] = {
+ { DBS_TX_QOS_RATE_DIV, 19, 16, 2 },
+ { DBS_TX_QOS_RATE_MUL, 16, 0, 1 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qp_ctrl_fields[] = {
+ { DBS_TX_QP_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_QP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qp_data_fields[] = {
+ { DBS_TX_QP_DATA_VPORT, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_uw_ctrl_fields[] = {
+ { DBS_TX_UW_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_UW_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_uw_data_fields[] = {
+ { DBS_TX_UW_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_TX_UW_DATA_HID, 8, 64, 0x0000 },
+ { DBS_TX_UW_DATA_INO, 1, 93, 0x0000 },
+ { DBS_TX_UW_DATA_INT, 1, 88, 0x0000 },
+ { DBS_TX_UW_DATA_ISTK, 1, 92, 0x0000 },
+ { DBS_TX_UW_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_TX_UW_DATA_QS, 15, 72, 0x0000 },
+ { DBS_TX_UW_DATA_VEC, 3, 89, 0x0000 },
+};
+
+static nt_fpga_register_init_t dbs_registers[] = {
+ { DBS_RX_AM_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_am_ctrl_fields
+ },
+ { DBS_RX_AM_DATA, 11, 75, REGISTER_TYPE_WO, 0, 5,
+ dbs_rx_am_data_fields
+ },
+ { DBS_RX_CONTROL, 0, 18, REGISTER_TYPE_RW, 43008, 6,
+ dbs_rx_control_fields
+ },
+ { DBS_RX_DR_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_dr_ctrl_fields
+ },
+ { DBS_RX_DR_DATA, 19, 89, REGISTER_TYPE_WO, 0, 5,
+ dbs_rx_dr_data_fields
+ },
+ { DBS_RX_IDLE, 8, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_idle_fields },
+ { DBS_RX_INIT, 2, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_init_fields },
+ { DBS_RX_INIT_VAL, 3, 31, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_init_val_fields
+ },
+ { DBS_RX_PTR, 4, 24, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_ptr_fields },
+ { DBS_RX_UW_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_uw_ctrl_fields
+ },
+ { DBS_RX_UW_DATA, 15, 93, REGISTER_TYPE_WO, 0, 7,
+ dbs_rx_uw_data_fields
+ },
+ { DBS_TX_AM_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_am_ctrl_fields
+ },
+ { DBS_TX_AM_DATA, 13, 75, REGISTER_TYPE_WO, 0, 5,
+ dbs_tx_am_data_fields
+ },
+ { DBS_TX_CONTROL, 1, 18, REGISTER_TYPE_RW, 66816, 6,
+ dbs_tx_control_fields
+ },
+ { DBS_TX_DR_CTRL, 20, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_dr_ctrl_fields
+ },
+ { DBS_TX_DR_DATA, 21, 90, REGISTER_TYPE_WO, 0, 6,
+ dbs_tx_dr_data_fields
+ },
+ { DBS_TX_IDLE, 9, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_idle_fields },
+ { DBS_TX_INIT, 5, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_init_fields },
+ { DBS_TX_INIT_VAL, 6, 31, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_init_val_fields
+ },
+ { DBS_TX_PTR, 7, 24, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_ptr_fields },
+ { DBS_TX_QOS_CTRL, 24, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_qos_ctrl_fields
+ },
+ { DBS_TX_QOS_DATA, 25, 44, REGISTER_TYPE_WO, 0, 3,
+ dbs_tx_qos_data_fields
+ },
+ { DBS_TX_QOS_RATE, 26, 35, REGISTER_TYPE_RW, 131073, 2,
+ dbs_tx_qos_rate_fields
+ },
+ { DBS_TX_QP_CTRL, 22, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_qp_ctrl_fields
+ },
+ { DBS_TX_QP_DATA, 23, 1, REGISTER_TYPE_WO, 0, 1,
+ dbs_tx_qp_data_fields
+ },
+ { DBS_TX_UW_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_uw_ctrl_fields
+ },
+ { DBS_TX_UW_DATA, 17, 94, REGISTER_TYPE_WO, 0, 8,
+ dbs_tx_uw_data_fields
+ },
+};
+
+static nt_fpga_field_init_t flm_buf_ctrl_fields[] = {
+ { FLM_BUF_CTRL_INF_AVAIL, 16, 16, 0x0000 },
+ { FLM_BUF_CTRL_LRN_FREE, 16, 0, 0x0000 },
+ { FLM_BUF_CTRL_STA_AVAIL, 16, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_control_fields[] = {
+ { FLM_CONTROL_CRCRD, 1, 12, 0x0000 },
+ { FLM_CONTROL_CRCWR, 1, 11, 0x0000 },
+ { FLM_CONTROL_EAB, 5, 18, 0 },
+ { FLM_CONTROL_ENABLE, 1, 0, 0 },
+ { FLM_CONTROL_INIT, 1, 1, 0x0000 },
+ { FLM_CONTROL_LDS, 1, 2, 0x0000 },
+ { FLM_CONTROL_LFS, 1, 3, 0x0000 },
+ { FLM_CONTROL_LIS, 1, 4, 0x0000 },
+ { FLM_CONTROL_PDS, 1, 9, 0x0000 },
+ { FLM_CONTROL_PIS, 1, 10, 0x0000 },
+ { FLM_CONTROL_RBL, 4, 13, 0 },
+ { FLM_CONTROL_RDS, 1, 7, 0x0000 },
+ { FLM_CONTROL_RIS, 1, 8, 0x0000 },
+ { FLM_CONTROL_SPLIT_SDRAM_USAGE, 5, 23, 16 },
+ { FLM_CONTROL_UDS, 1, 5, 0x0000 },
+ { FLM_CONTROL_UIS, 1, 6, 0x0000 },
+ { FLM_CONTROL_WPD, 1, 17, 0 },
+};
+
+static nt_fpga_field_init_t flm_inf_data_fields[] = {
+ { FLM_INF_DATA_BYTES, 64, 0, 0x0000 },
+ { FLM_INF_DATA_CAUSE, 3, 264, 0x0000 },
+ { FLM_INF_DATA_EOR, 1, 287, 0x0000 },
+ { FLM_INF_DATA_ID, 72, 192, 0x0000 },
+ { FLM_INF_DATA_PACKETS, 64, 64, 0x0000 },
+ { FLM_INF_DATA_TS, 64, 128, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_load_aps_fields[] = {
+ { FLM_LOAD_APS_APS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_load_bin_fields[] = {
+ { FLM_LOAD_BIN_BIN, 30, 0, 8388607 },
+};
+
+static nt_fpga_field_init_t flm_load_lps_fields[] = {
+ { FLM_LOAD_LPS_LPS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_load_pps_fields[] = {
+ { FLM_LOAD_PPS_PPS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_lrn_data_fields[] = {
+ { FLM_LRN_DATA_ADJ, 32, 480, 0x0000 },
+ { FLM_LRN_DATA_COLOR, 32, 448, 0x0000 },
+ { FLM_LRN_DATA_DSCP, 6, 734, 0x0000 },
+ { FLM_LRN_DATA_ENT, 1, 729, 0x0000 },
+ { FLM_LRN_DATA_EOR, 1, 767, 0x0000 },
+ { FLM_LRN_DATA_FILL, 12, 584, 0x0000 },
+ { FLM_LRN_DATA_FT, 4, 596, 0x0000 },
+ { FLM_LRN_DATA_FT_MBR, 4, 600, 0x0000 },
+ { FLM_LRN_DATA_FT_MISS, 4, 604, 0x0000 },
+ { FLM_LRN_DATA_ID, 72, 512, 0x0000 },
+ { FLM_LRN_DATA_KID, 8, 328, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID1, 28, 608, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID2, 28, 636, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID3, 28, 664, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID4, 28, 692, 0x0000 },
+ { FLM_LRN_DATA_NAT_EN, 1, 747, 0x0000 },
+ { FLM_LRN_DATA_NAT_IP, 32, 336, 0x0000 },
+ { FLM_LRN_DATA_NAT_PORT, 16, 400, 0x0000 },
+ { FLM_LRN_DATA_OP, 4, 730, 0x0000 },
+ { FLM_LRN_DATA_PRIO, 2, 727, 0x0000 },
+ { FLM_LRN_DATA_PROT, 8, 320, 0x0000 },
+ { FLM_LRN_DATA_QFI, 6, 740, 0x0000 },
+ { FLM_LRN_DATA_QW0, 128, 192, 0x0000 },
+ { FLM_LRN_DATA_QW4, 128, 64, 0x0000 },
+ { FLM_LRN_DATA_RATE, 16, 416, 0x0000 },
+ { FLM_LRN_DATA_RQI, 1, 746, 0x0000 },
+ { FLM_LRN_DATA_SIZE, 16, 432, 0x0000 },
+ { FLM_LRN_DATA_STAT_PROF, 4, 723, 0x0000 },
+ { FLM_LRN_DATA_SW8, 32, 32, 0x0000 },
+ { FLM_LRN_DATA_SW9, 32, 0, 0x0000 },
+ { FLM_LRN_DATA_TEID, 32, 368, 0x0000 },
+ { FLM_LRN_DATA_VOL_IDX, 3, 720, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_prio_fields[] = {
+ { FLM_PRIO_FT0, 4, 4, 1 }, { FLM_PRIO_FT1, 4, 12, 1 },
+ { FLM_PRIO_FT2, 4, 20, 1 }, { FLM_PRIO_FT3, 4, 28, 1 },
+ { FLM_PRIO_LIMIT0, 4, 0, 0 }, { FLM_PRIO_LIMIT1, 4, 8, 0 },
+ { FLM_PRIO_LIMIT2, 4, 16, 0 }, { FLM_PRIO_LIMIT3, 4, 24, 0 },
+};
+
+static nt_fpga_field_init_t flm_pst_ctrl_fields[] = {
+ { FLM_PST_CTRL_ADR, 4, 0, 0x0000 },
+ { FLM_PST_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_pst_data_fields[] = {
+ { FLM_PST_DATA_BP, 5, 0, 0x0000 },
+ { FLM_PST_DATA_PP, 5, 5, 0x0000 },
+ { FLM_PST_DATA_TP, 5, 10, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_rcp_ctrl_fields[] = {
+ { FLM_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { FLM_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_rcp_data_fields[] = {
+ { FLM_RCP_DATA_AUTO_IPV4_MASK, 1, 402, 0x0000 },
+ { FLM_RCP_DATA_BYT_DYN, 5, 387, 0x0000 },
+ { FLM_RCP_DATA_BYT_OFS, 8, 392, 0x0000 },
+ { FLM_RCP_DATA_IPN, 1, 386, 0x0000 },
+ { FLM_RCP_DATA_KID, 8, 377, 0x0000 },
+ { FLM_RCP_DATA_LOOKUP, 1, 0, 0x0000 },
+ { FLM_RCP_DATA_MASK, 320, 57, 0x0000 },
+ { FLM_RCP_DATA_OPN, 1, 385, 0x0000 },
+ { FLM_RCP_DATA_QW0_DYN, 5, 1, 0x0000 },
+ { FLM_RCP_DATA_QW0_OFS, 8, 6, 0x0000 },
+ { FLM_RCP_DATA_QW0_SEL, 2, 14, 0x0000 },
+ { FLM_RCP_DATA_QW4_DYN, 5, 16, 0x0000 },
+ { FLM_RCP_DATA_QW4_OFS, 8, 21, 0x0000 },
+ { FLM_RCP_DATA_SW8_DYN, 5, 29, 0x0000 },
+ { FLM_RCP_DATA_SW8_OFS, 8, 34, 0x0000 },
+ { FLM_RCP_DATA_SW8_SEL, 2, 42, 0x0000 },
+ { FLM_RCP_DATA_SW9_DYN, 5, 44, 0x0000 },
+ { FLM_RCP_DATA_SW9_OFS, 8, 49, 0x0000 },
+ { FLM_RCP_DATA_TXPLM, 2, 400, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_scrub_fields[] = {
+ { FLM_SCRUB_I, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t flm_status_fields[] = {
+ { FLM_STATUS_CALIBDONE, 1, 0, 0x0000 },
+ { FLM_STATUS_CRCERR, 1, 5, 0x0000 },
+ { FLM_STATUS_CRITICAL, 1, 3, 0x0000 },
+ { FLM_STATUS_EFT_BP, 1, 6, 0x0000 },
+ { FLM_STATUS_IDLE, 1, 2, 0x0000 },
+ { FLM_STATUS_INITDONE, 1, 1, 0x0000 },
+ { FLM_STATUS_PANIC, 1, 4, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_aul_done_fields[] = {
+ { FLM_STAT_AUL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_aul_fail_fields[] = {
+ { FLM_STAT_AUL_FAIL_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_aul_ignore_fields[] = {
+ { FLM_STAT_AUL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_csh_hit_fields[] = {
+ { FLM_STAT_CSH_HIT_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_csh_miss_fields[] = {
+ { FLM_STAT_CSH_MISS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_csh_unh_fields[] = {
+ { FLM_STAT_CSH_UNH_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_cuc_move_fields[] = {
+ { FLM_STAT_CUC_MOVE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_cuc_start_fields[] = {
+ { FLM_STAT_CUC_START_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_flows_fields[] = {
+ { FLM_STAT_FLOWS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_inf_done_fields[] = {
+ { FLM_STAT_INF_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_inf_skip_fields[] = {
+ { FLM_STAT_INF_SKIP_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_lrn_done_fields[] = {
+ { FLM_STAT_LRN_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_lrn_fail_fields[] = {
+ { FLM_STAT_LRN_FAIL_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_lrn_ignore_fields[] = {
+ { FLM_STAT_LRN_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_dis_fields[] = {
+ { FLM_STAT_PCK_DIS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_hit_fields[] = {
+ { FLM_STAT_PCK_HIT_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_miss_fields[] = {
+ { FLM_STAT_PCK_MISS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_unh_fields[] = {
+ { FLM_STAT_PCK_UNH_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_prb_done_fields[] = {
+ { FLM_STAT_PRB_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_prb_ignore_fields[] = {
+ { FLM_STAT_PRB_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_rel_done_fields[] = {
+ { FLM_STAT_REL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_rel_ignore_fields[] = {
+ { FLM_STAT_REL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_sta_done_fields[] = {
+ { FLM_STAT_STA_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_tul_done_fields[] = {
+ { FLM_STAT_TUL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_unl_done_fields[] = {
+ { FLM_STAT_UNL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_unl_ignore_fields[] = {
+ { FLM_STAT_UNL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_sta_data_fields[] = {
+ { FLM_STA_DATA_EOR, 1, 95, 0x0000 },
+ { FLM_STA_DATA_ID, 72, 0, 0x0000 },
+ { FLM_STA_DATA_LDS, 1, 72, 0x0000 },
+ { FLM_STA_DATA_LFS, 1, 73, 0x0000 },
+ { FLM_STA_DATA_LIS, 1, 74, 0x0000 },
+ { FLM_STA_DATA_PDS, 1, 79, 0x0000 },
+ { FLM_STA_DATA_PIS, 1, 80, 0x0000 },
+ { FLM_STA_DATA_RDS, 1, 77, 0x0000 },
+ { FLM_STA_DATA_RIS, 1, 78, 0x0000 },
+ { FLM_STA_DATA_UDS, 1, 75, 0x0000 },
+ { FLM_STA_DATA_UIS, 1, 76, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_timeout_fields[] = {
+ { FLM_TIMEOUT_T, 32, 0, 0 },
+};
+
+static nt_fpga_register_init_t flm_registers[] = {
+ { FLM_BUF_CTRL, 14, 48, REGISTER_TYPE_RW, 0, 3, flm_buf_ctrl_fields },
+ { FLM_CONTROL, 0, 28, REGISTER_TYPE_MIXED, 134217728, 17,
+ flm_control_fields
+ },
+ { FLM_INF_DATA, 16, 288, REGISTER_TYPE_RO, 0, 6, flm_inf_data_fields },
+ { FLM_LOAD_APS, 7, 32, REGISTER_TYPE_RO, 0, 1, flm_load_aps_fields },
+ { FLM_LOAD_BIN, 4, 30, REGISTER_TYPE_WO, 8388607, 1,
+ flm_load_bin_fields
+ },
+ { FLM_LOAD_LPS, 6, 32, REGISTER_TYPE_RO, 0, 1, flm_load_lps_fields },
+ { FLM_LOAD_PPS, 5, 32, REGISTER_TYPE_RO, 0, 1, flm_load_pps_fields },
+ { FLM_LRN_DATA, 15, 768, REGISTER_TYPE_WO, 0, 32, flm_lrn_data_fields },
+ { FLM_PRIO, 8, 32, REGISTER_TYPE_WO, 269488144, 8, flm_prio_fields },
+ { FLM_PST_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, flm_pst_ctrl_fields },
+ { FLM_PST_DATA, 11, 15, REGISTER_TYPE_WO, 0, 3, flm_pst_data_fields },
+ { FLM_RCP_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, flm_rcp_ctrl_fields },
+ { FLM_RCP_DATA, 13, 403, REGISTER_TYPE_WO, 0, 19, flm_rcp_data_fields },
+ { FLM_SCRUB, 3, 16, REGISTER_TYPE_WO, 0, 1, flm_scrub_fields },
+ { FLM_STATUS, 1, 12, REGISTER_TYPE_MIXED, 0, 7, flm_status_fields },
+ { FLM_STAT_AUL_DONE, 41, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_aul_done_fields
+ },
+ { FLM_STAT_AUL_FAIL, 43, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_aul_fail_fields
+ },
+ { FLM_STAT_AUL_IGNORE, 42, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_aul_ignore_fields
+ },
+ { FLM_STAT_CSH_HIT, 52, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_csh_hit_fields
+ },
+ { FLM_STAT_CSH_MISS, 53, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_csh_miss_fields
+ },
+ { FLM_STAT_CSH_UNH, 54, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_csh_unh_fields
+ },
+ { FLM_STAT_CUC_MOVE, 57, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_cuc_move_fields
+ },
+ { FLM_STAT_CUC_START, 56, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_cuc_start_fields
+ },
+ { FLM_STAT_FLOWS, 18, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_flows_fields
+ },
+ { FLM_STAT_INF_DONE, 46, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_inf_done_fields
+ },
+ { FLM_STAT_INF_SKIP, 47, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_inf_skip_fields
+ },
+ { FLM_STAT_LRN_DONE, 32, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_lrn_done_fields
+ },
+ { FLM_STAT_LRN_FAIL, 34, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_lrn_fail_fields
+ },
+ { FLM_STAT_LRN_IGNORE, 33, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_lrn_ignore_fields
+ },
+ { FLM_STAT_PCK_DIS, 51, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_dis_fields
+ },
+ { FLM_STAT_PCK_HIT, 48, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_hit_fields
+ },
+ { FLM_STAT_PCK_MISS, 49, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_miss_fields
+ },
+ { FLM_STAT_PCK_UNH, 50, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_unh_fields
+ },
+ { FLM_STAT_PRB_DONE, 39, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_prb_done_fields
+ },
+ { FLM_STAT_PRB_IGNORE, 40, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_prb_ignore_fields
+ },
+ { FLM_STAT_REL_DONE, 37, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_rel_done_fields
+ },
+ { FLM_STAT_REL_IGNORE, 38, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_rel_ignore_fields
+ },
+ { FLM_STAT_STA_DONE, 45, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_sta_done_fields
+ },
+ { FLM_STAT_TUL_DONE, 44, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_tul_done_fields
+ },
+ { FLM_STAT_UNL_DONE, 35, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_unl_done_fields
+ },
+ { FLM_STAT_UNL_IGNORE, 36, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_unl_ignore_fields
+ },
+ { FLM_STA_DATA, 17, 96, REGISTER_TYPE_RO, 0, 11, flm_sta_data_fields },
+ { FLM_TIMEOUT, 2, 32, REGISTER_TYPE_WO, 0, 1, flm_timeout_fields },
+};
+
+static nt_fpga_field_init_t gfg_burstsize0_fields[] = {
+ { GFG_BURSTSIZE0_VAL, 24, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_burstsize1_fields[] = {
+ { GFG_BURSTSIZE1_VAL, 24, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_ctrl0_fields[] = {
+ { GFG_CTRL0_ENABLE, 1, 0, 0 },
+ { GFG_CTRL0_MODE, 3, 1, 0 },
+ { GFG_CTRL0_PRBS_EN, 1, 4, 0 },
+ { GFG_CTRL0_SIZE, 14, 16, 64 },
+};
+
+static nt_fpga_field_init_t gfg_ctrl1_fields[] = {
+ { GFG_CTRL1_ENABLE, 1, 0, 0 },
+ { GFG_CTRL1_MODE, 3, 1, 0 },
+ { GFG_CTRL1_PRBS_EN, 1, 4, 0 },
+ { GFG_CTRL1_SIZE, 14, 16, 64 },
+};
+
+static nt_fpga_field_init_t gfg_run0_fields[] = {
+ { GFG_RUN0_RUN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_run1_fields[] = {
+ { GFG_RUN1_RUN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_sizemask0_fields[] = {
+ { GFG_SIZEMASK0_VAL, 14, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_sizemask1_fields[] = {
+ { GFG_SIZEMASK1_VAL, 14, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_streamid0_fields[] = {
+ { GFG_STREAMID0_VAL, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_streamid1_fields[] = {
+ { GFG_STREAMID1_VAL, 8, 0, 1 },
+};
+
+static nt_fpga_register_init_t gfg_registers[] = {
+ { GFG_BURSTSIZE0, 3, 24, REGISTER_TYPE_WO, 0, 1,
+ gfg_burstsize0_fields
+ },
+ { GFG_BURSTSIZE1, 8, 24, REGISTER_TYPE_WO, 0, 1,
+ gfg_burstsize1_fields
+ },
+ { GFG_CTRL0, 0, 30, REGISTER_TYPE_WO, 4194304, 4, gfg_ctrl0_fields },
+ { GFG_CTRL1, 5, 30, REGISTER_TYPE_WO, 4194304, 4, gfg_ctrl1_fields },
+ { GFG_RUN0, 1, 1, REGISTER_TYPE_WO, 0, 1, gfg_run0_fields },
+ { GFG_RUN1, 6, 1, REGISTER_TYPE_WO, 0, 1, gfg_run1_fields },
+ { GFG_SIZEMASK0, 4, 14, REGISTER_TYPE_WO, 0, 1, gfg_sizemask0_fields },
+ { GFG_SIZEMASK1, 9, 14, REGISTER_TYPE_WO, 0, 1, gfg_sizemask1_fields },
+ { GFG_STREAMID0, 2, 8, REGISTER_TYPE_WO, 0, 1, gfg_streamid0_fields },
+ { GFG_STREAMID1, 7, 8, REGISTER_TYPE_WO, 1, 1, gfg_streamid1_fields },
+};
+
+static nt_fpga_field_init_t gmf_ctrl_fields[] = {
+ { GMF_CTRL_ENABLE, 1, 0, 0 },
+ { GMF_CTRL_FCS_ALWAYS, 1, 1, 0 },
+ { GMF_CTRL_IFG_AUTO_ADJUST_ENABLE, 1, 7, 0 },
+ { GMF_CTRL_IFG_ENABLE, 1, 2, 0 },
+ { GMF_CTRL_IFG_TX_NOW_ALWAYS, 1, 3, 0 },
+ { GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE, 1, 5, 0 },
+ { GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK, 1, 6, 0 },
+ { GMF_CTRL_IFG_TX_ON_TS_ALWAYS, 1, 4, 0 },
+ { GMF_CTRL_TS_INJECT_ALWAYS, 1, 8, 0 },
+ { GMF_CTRL_TS_INJECT_DUAL_STEP, 1, 9, 0 },
+};
+
+static nt_fpga_field_init_t gmf_debug_lane_marker_fields[] = {
+ { GMF_DEBUG_LANE_MARKER_COMPENSATION, 16, 0, 16384 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_max_adjust_slack_fields[] = {
+ { GMF_IFG_MAX_ADJUST_SLACK_SLACK, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_set_clock_delta_fields[] = {
+ { GMF_IFG_SET_CLOCK_DELTA_DELTA, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_set_clock_delta_adjust_fields[] = {
+ { GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_tx_now_on_ts_fields[] = {
+ { GMF_IFG_TX_NOW_ON_TS_TS, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_speed_fields[] = {
+ { GMF_SPEED_IFG_SPEED, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_stat_data_buffer_fields[] = {
+ { GMF_STAT_DATA_BUFFER_USED, 15, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t gmf_stat_max_delayed_pkt_fields[] = {
+ { GMF_STAT_MAX_DELAYED_PKT_NS, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_stat_next_pkt_fields[] = {
+ { GMF_STAT_NEXT_PKT_NS, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_stat_sticky_fields[] = {
+ { GMF_STAT_STICKY_DATA_UNDERFLOWED, 1, 0, 0 },
+ { GMF_STAT_STICKY_IFG_ADJUSTED, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ts_inject_fields[] = {
+ { GMF_TS_INJECT_OFFSET, 14, 0, 0 },
+ { GMF_TS_INJECT_POS, 2, 14, 0 },
+};
+
+static nt_fpga_register_init_t gmf_registers[] = {
+ { GMF_CTRL, 0, 10, REGISTER_TYPE_WO, 0, 10, gmf_ctrl_fields },
+ { GMF_DEBUG_LANE_MARKER, 7, 16, REGISTER_TYPE_WO, 16384, 1,
+ gmf_debug_lane_marker_fields
+ },
+ { GMF_IFG_MAX_ADJUST_SLACK, 4, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_max_adjust_slack_fields
+ },
+ { GMF_IFG_SET_CLOCK_DELTA, 2, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_set_clock_delta_fields
+ },
+ { GMF_IFG_SET_CLOCK_DELTA_ADJUST, 3, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_set_clock_delta_adjust_fields
+ },
+ { GMF_IFG_TX_NOW_ON_TS, 5, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_tx_now_on_ts_fields
+ },
+ { GMF_SPEED, 1, 64, REGISTER_TYPE_WO, 0, 1, gmf_speed_fields },
+ { GMF_STAT_DATA_BUFFER, 9, 15, REGISTER_TYPE_RO, 0, 1,
+ gmf_stat_data_buffer_fields
+ },
+ { GMF_STAT_MAX_DELAYED_PKT, 11, 64, REGISTER_TYPE_RC1, 0, 1,
+ gmf_stat_max_delayed_pkt_fields
+ },
+ { GMF_STAT_NEXT_PKT, 10, 64, REGISTER_TYPE_RO, 0, 1,
+ gmf_stat_next_pkt_fields
+ },
+ { GMF_STAT_STICKY, 8, 2, REGISTER_TYPE_RC1, 0, 2,
+ gmf_stat_sticky_fields
+ },
+ { GMF_TS_INJECT, 6, 16, REGISTER_TYPE_WO, 0, 2, gmf_ts_inject_fields },
+};
+
+static nt_fpga_field_init_t gpio_phy_cfg_fields[] = {
+ { GPIO_PHY_CFG_E_PORT0_RXLOS, 1, 8, 0 },
+ { GPIO_PHY_CFG_E_PORT1_RXLOS, 1, 9, 0 },
+ { GPIO_PHY_CFG_PORT0_INT_B, 1, 1, 1 },
+ { GPIO_PHY_CFG_PORT0_LPMODE, 1, 0, 0 },
+ { GPIO_PHY_CFG_PORT0_MODPRS_B, 1, 3, 1 },
+ { GPIO_PHY_CFG_PORT0_RESET_B, 1, 2, 0 },
+ { GPIO_PHY_CFG_PORT1_INT_B, 1, 5, 1 },
+ { GPIO_PHY_CFG_PORT1_LPMODE, 1, 4, 0 },
+ { GPIO_PHY_CFG_PORT1_MODPRS_B, 1, 7, 1 },
+ { GPIO_PHY_CFG_PORT1_RESET_B, 1, 6, 0 },
+};
+
+static nt_fpga_field_init_t gpio_phy_gpio_fields[] = {
+ { GPIO_PHY_GPIO_E_PORT0_RXLOS, 1, 8, 0 },
+ { GPIO_PHY_GPIO_E_PORT1_RXLOS, 1, 9, 0 },
+ { GPIO_PHY_GPIO_PORT0_INT_B, 1, 1, 0x0000 },
+ { GPIO_PHY_GPIO_PORT0_LPMODE, 1, 0, 1 },
+ { GPIO_PHY_GPIO_PORT0_MODPRS_B, 1, 3, 0x0000 },
+ { GPIO_PHY_GPIO_PORT0_RESET_B, 1, 2, 0 },
+ { GPIO_PHY_GPIO_PORT1_INT_B, 1, 5, 0x0000 },
+ { GPIO_PHY_GPIO_PORT1_LPMODE, 1, 4, 1 },
+ { GPIO_PHY_GPIO_PORT1_MODPRS_B, 1, 7, 0x0000 },
+ { GPIO_PHY_GPIO_PORT1_RESET_B, 1, 6, 0 },
+};
+
+static nt_fpga_register_init_t gpio_phy_registers[] = {
+ { GPIO_PHY_CFG, 0, 10, REGISTER_TYPE_RW, 170, 10, gpio_phy_cfg_fields },
+ { GPIO_PHY_GPIO, 1, 10, REGISTER_TYPE_RW, 17, 10,
+ gpio_phy_gpio_fields
+ },
+};
+
+static nt_fpga_field_init_t hfu_rcp_ctrl_fields[] = {
+ { HFU_RCP_CTRL_ADR, 6, 0, 0x0000 },
+ { HFU_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t hfu_rcp_data_fields[] = {
+ { HFU_RCP_DATA_CSINF, 1, 111, 0x0000 },
+ { HFU_RCP_DATA_IL3OFS, 8, 139, 0x0000 },
+ { HFU_RCP_DATA_IL4OFS, 8, 147, 0x0000 },
+ { HFU_RCP_DATA_L3FRAG, 2, 114, 0x0000 },
+ { HFU_RCP_DATA_L3PRT, 2, 112, 0x0000 },
+ { HFU_RCP_DATA_L4PRT, 3, 120, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_ADD_DYN, 5, 15, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_ADD_OFS, 8, 20, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_OL4LEN, 1, 1, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_POS_DYN, 5, 2, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_POS_OFS, 8, 7, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_SUB_DYN, 5, 28, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_WR, 1, 0, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_ADD_DYN, 5, 47, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_ADD_OFS, 8, 52, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_POS_DYN, 5, 34, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_POS_OFS, 8, 39, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_SUB_DYN, 5, 60, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_WR, 1, 33, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_ADD_DYN, 5, 79, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_ADD_OFS, 8, 84, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_POS_DYN, 5, 66, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_POS_OFS, 8, 71, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_SUB_DYN, 5, 92, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_WR, 1, 65, 0x0000 },
+ { HFU_RCP_DATA_OL3OFS, 8, 123, 0x0000 },
+ { HFU_RCP_DATA_OL4OFS, 8, 131, 0x0000 },
+ { HFU_RCP_DATA_TTL_POS_DYN, 5, 98, 0x0000 },
+ { HFU_RCP_DATA_TTL_POS_OFS, 8, 103, 0x0000 },
+ { HFU_RCP_DATA_TTL_WR, 1, 97, 0x0000 },
+ { HFU_RCP_DATA_TUNNEL, 4, 116, 0x0000 },
+};
+
+static nt_fpga_register_init_t hfu_registers[] = {
+ { HFU_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hfu_rcp_ctrl_fields },
+ { HFU_RCP_DATA, 1, 155, REGISTER_TYPE_WO, 0, 31, hfu_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t hif_build_time_fields[] = {
+ { HIF_BUILD_TIME_TIME, 32, 0, 1689706895 },
+};
+
+static nt_fpga_field_init_t hif_config_fields[] = {
+ { HIF_CONFIG_EXT_TAG, 1, 6, 0x0000 },
+ { HIF_CONFIG_MAX_READ, 3, 3, 0x0000 },
+ { HIF_CONFIG_MAX_TLP, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t hif_control_fields[] = {
+ { HIF_CONTROL_BLESSED, 8, 4, 0 },
+ { HIF_CONTROL_WRAW, 4, 0, 1 },
+};
+
+static nt_fpga_field_init_t hif_prod_id_ex_fields[] = {
+ { HIF_PROD_ID_EX_LAYOUT, 1, 31, 0 },
+ { HIF_PROD_ID_EX_LAYOUT_VERSION, 8, 0, 1 },
+ { HIF_PROD_ID_EX_RESERVED, 23, 8, 0 },
+};
+
+static nt_fpga_field_init_t hif_prod_id_lsb_fields[] = {
+ { HIF_PROD_ID_LSB_GROUP_ID, 16, 16, 9563 },
+ { HIF_PROD_ID_LSB_REV_ID, 8, 0, 24 },
+ { HIF_PROD_ID_LSB_VER_ID, 8, 8, 55 },
+};
+
+static nt_fpga_field_init_t hif_prod_id_msb_fields[] = {
+ { HIF_PROD_ID_MSB_BUILD_NO, 10, 12, 0 },
+ { HIF_PROD_ID_MSB_TYPE_ID, 12, 0, 200 },
+};
+
+static nt_fpga_field_init_t hif_sample_time_fields[] = {
+ { HIF_SAMPLE_TIME_SAMPLE_TIME, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t hif_status_fields[] = {
+ { HIF_STATUS_RD_ERR, 1, 9, 0 },
+ { HIF_STATUS_TAGS_IN_USE, 8, 0, 0 },
+ { HIF_STATUS_WR_ERR, 1, 8, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_ctrl_fields[] = {
+ { HIF_STAT_CTRL_STAT_ENA, 1, 1, 0 },
+ { HIF_STAT_CTRL_STAT_REQ, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_refclk_fields[] = {
+ { HIF_STAT_REFCLK_REFCLK250, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_rx_fields[] = {
+ { HIF_STAT_RX_COUNTER, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_tx_fields[] = {
+ { HIF_STAT_TX_COUNTER, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_test0_fields[] = {
+ { HIF_TEST0_DATA, 32, 0, 287454020 },
+};
+
+static nt_fpga_field_init_t hif_test1_fields[] = {
+ { HIF_TEST1_DATA, 32, 0, 2864434397 },
+};
+
+static nt_fpga_field_init_t hif_uuid0_fields[] = {
+ { HIF_UUID0_UUID0, 32, 0, 456073826 },
+};
+
+static nt_fpga_field_init_t hif_uuid1_fields[] = {
+ { HIF_UUID1_UUID1, 32, 0, 3051597623 },
+};
+
+static nt_fpga_field_init_t hif_uuid2_fields[] = {
+ { HIF_UUID2_UUID2, 32, 0, 3265543206 },
+};
+
+static nt_fpga_field_init_t hif_uuid3_fields[] = {
+ { HIF_UUID3_UUID3, 32, 0, 599637710 },
+};
+
+static nt_fpga_register_init_t hif_registers[] = {
+ { HIF_BUILD_TIME, 16, 32, REGISTER_TYPE_RO, 1689706895, 1,
+ hif_build_time_fields
+ },
+ { HIF_CONFIG, 24, 7, REGISTER_TYPE_RW, 0, 3, hif_config_fields },
+ { HIF_CONTROL, 40, 12, REGISTER_TYPE_RW, 1, 2, hif_control_fields },
+ { HIF_PROD_ID_EX, 112, 32, REGISTER_TYPE_RO, 1, 3,
+ hif_prod_id_ex_fields
+ },
+ { HIF_PROD_ID_LSB, 0, 32, REGISTER_TYPE_RO, 626734872, 3,
+ hif_prod_id_lsb_fields
+ },
+ { HIF_PROD_ID_MSB, 8, 22, REGISTER_TYPE_RO, 200, 2,
+ hif_prod_id_msb_fields
+ },
+ { HIF_SAMPLE_TIME, 96, 1, REGISTER_TYPE_WO, 0, 1,
+ hif_sample_time_fields
+ },
+ { HIF_STATUS, 32, 10, REGISTER_TYPE_MIXED, 0, 3, hif_status_fields },
+ { HIF_STAT_CTRL, 64, 2, REGISTER_TYPE_WO, 0, 2, hif_stat_ctrl_fields },
+ { HIF_STAT_REFCLK, 72, 32, REGISTER_TYPE_RO, 0, 1,
+ hif_stat_refclk_fields
+ },
+ { HIF_STAT_RX, 88, 32, REGISTER_TYPE_RO, 0, 1, hif_stat_rx_fields },
+ { HIF_STAT_TX, 80, 32, REGISTER_TYPE_RO, 0, 1, hif_stat_tx_fields },
+ { HIF_TEST0, 48, 32, REGISTER_TYPE_RW, 287454020, 1, hif_test0_fields },
+ { HIF_TEST1, 56, 32, REGISTER_TYPE_RW, 2864434397, 1,
+ hif_test1_fields
+ },
+ { HIF_UUID0, 128, 32, REGISTER_TYPE_RO, 456073826, 1,
+ hif_uuid0_fields
+ },
+ { HIF_UUID1, 144, 32, REGISTER_TYPE_RO, 3051597623, 1,
+ hif_uuid1_fields
+ },
+ { HIF_UUID2, 160, 32, REGISTER_TYPE_RO, 3265543206, 1,
+ hif_uuid2_fields
+ },
+ { HIF_UUID3, 176, 32, REGISTER_TYPE_RO, 599637710, 1,
+ hif_uuid3_fields
+ },
+};
+
+static nt_fpga_field_init_t hsh_rcp_ctrl_fields[] = {
+ { HSH_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { HSH_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t hsh_rcp_data_fields[] = {
+ { HSH_RCP_DATA_AUTO_IPV4_MASK, 1, 742, 0x0000 },
+ { HSH_RCP_DATA_HSH_TYPE, 5, 416, 0x0000 },
+ { HSH_RCP_DATA_HSH_VALID, 1, 415, 0x0000 },
+ { HSH_RCP_DATA_K, 320, 422, 0x0000 },
+ { HSH_RCP_DATA_LOAD_DIST_TYPE, 2, 0, 0x0000 },
+ { HSH_RCP_DATA_MAC_PORT_MASK, 2, 2, 0x0000 },
+ { HSH_RCP_DATA_P_MASK, 1, 61, 0x0000 },
+ { HSH_RCP_DATA_QW0_OFS, 8, 11, 0x0000 },
+ { HSH_RCP_DATA_QW0_PE, 5, 6, 0x0000 },
+ { HSH_RCP_DATA_QW4_OFS, 8, 24, 0x0000 },
+ { HSH_RCP_DATA_QW4_PE, 5, 19, 0x0000 },
+ { HSH_RCP_DATA_SEED, 32, 382, 0x0000 },
+ { HSH_RCP_DATA_SORT, 2, 4, 0x0000 },
+ { HSH_RCP_DATA_TNL_P, 1, 414, 0x0000 },
+ { HSH_RCP_DATA_TOEPLITZ, 1, 421, 0x0000 },
+ { HSH_RCP_DATA_W8_OFS, 8, 37, 0x0000 },
+ { HSH_RCP_DATA_W8_PE, 5, 32, 0x0000 },
+ { HSH_RCP_DATA_W8_SORT, 1, 45, 0x0000 },
+ { HSH_RCP_DATA_W9_OFS, 8, 51, 0x0000 },
+ { HSH_RCP_DATA_W9_P, 1, 60, 0x0000 },
+ { HSH_RCP_DATA_W9_PE, 5, 46, 0x0000 },
+ { HSH_RCP_DATA_W9_SORT, 1, 59, 0x0000 },
+ { HSH_RCP_DATA_WORD_MASK, 320, 62, 0x0000 },
+};
+
+static nt_fpga_register_init_t hsh_registers[] = {
+ { HSH_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hsh_rcp_ctrl_fields },
+ { HSH_RCP_DATA, 1, 743, REGISTER_TYPE_WO, 0, 23, hsh_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t hst_rcp_ctrl_fields[] = {
+ { HST_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { HST_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t hst_rcp_data_fields[] = {
+ { HST_RCP_DATA_END_DYN, 5, 16, 0x0000 },
+ { HST_RCP_DATA_END_OFS, 10, 21, 0x0000 },
+ { HST_RCP_DATA_MODIF0_CMD, 3, 31, 0x0000 },
+ { HST_RCP_DATA_MODIF0_DYN, 5, 34, 0x0000 },
+ { HST_RCP_DATA_MODIF0_OFS, 10, 39, 0x0000 },
+ { HST_RCP_DATA_MODIF0_VALUE, 16, 49, 0x0000 },
+ { HST_RCP_DATA_MODIF1_CMD, 3, 65, 0x0000 },
+ { HST_RCP_DATA_MODIF1_DYN, 5, 68, 0x0000 },
+ { HST_RCP_DATA_MODIF1_OFS, 10, 73, 0x0000 },
+ { HST_RCP_DATA_MODIF1_VALUE, 16, 83, 0x0000 },
+ { HST_RCP_DATA_MODIF2_CMD, 3, 99, 0x0000 },
+ { HST_RCP_DATA_MODIF2_DYN, 5, 102, 0x0000 },
+ { HST_RCP_DATA_MODIF2_OFS, 10, 107, 0x0000 },
+ { HST_RCP_DATA_MODIF2_VALUE, 16, 117, 0x0000 },
+ { HST_RCP_DATA_START_DYN, 5, 1, 0x0000 },
+ { HST_RCP_DATA_START_OFS, 10, 6, 0x0000 },
+ { HST_RCP_DATA_STRIP_MODE, 1, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t hst_registers[] = {
+ { HST_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hst_rcp_ctrl_fields },
+ { HST_RCP_DATA, 1, 133, REGISTER_TYPE_WO, 0, 17, hst_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t ifr_rcp_ctrl_fields[] = {
+ { IFR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { IFR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t ifr_rcp_data_fields[] = {
+ { IFR_RCP_DATA_EN, 1, 0, 0x0000 },
+ { IFR_RCP_DATA_MTU, 14, 1, 0x0000 },
+};
+
+static nt_fpga_register_init_t ifr_registers[] = {
+ { IFR_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, ifr_rcp_ctrl_fields },
+ { IFR_RCP_DATA, 1, 15, REGISTER_TYPE_WO, 0, 2, ifr_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t iic_adr_fields[] = {
+ { IIC_ADR_SLV_ADR, 7, 1, 0 },
+};
+
+static nt_fpga_field_init_t iic_cr_fields[] = {
+ { IIC_CR_EN, 1, 0, 0 }, { IIC_CR_GC_EN, 1, 6, 0 },
+ { IIC_CR_MSMS, 1, 2, 0 }, { IIC_CR_RST, 1, 7, 0 },
+ { IIC_CR_RSTA, 1, 5, 0 }, { IIC_CR_TX, 1, 3, 0 },
+ { IIC_CR_TXAK, 1, 4, 0 }, { IIC_CR_TXFIFO_RESET, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t iic_dgie_fields[] = {
+ { IIC_DGIE_GIE, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t iic_gpo_fields[] = {
+ { IIC_GPO_GPO_VAL, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_ier_fields[] = {
+ { IIC_IER_INT0, 1, 0, 0 }, { IIC_IER_INT1, 1, 1, 0 },
+ { IIC_IER_INT2, 1, 2, 0 }, { IIC_IER_INT3, 1, 3, 0 },
+ { IIC_IER_INT4, 1, 4, 0 }, { IIC_IER_INT5, 1, 5, 0 },
+ { IIC_IER_INT6, 1, 6, 0 }, { IIC_IER_INT7, 1, 7, 0 },
+};
+
+static nt_fpga_field_init_t iic_isr_fields[] = {
+ { IIC_ISR_INT0, 1, 0, 0 }, { IIC_ISR_INT1, 1, 1, 0 },
+ { IIC_ISR_INT2, 1, 2, 0 }, { IIC_ISR_INT3, 1, 3, 0 },
+ { IIC_ISR_INT4, 1, 4, 0 }, { IIC_ISR_INT5, 1, 5, 0 },
+ { IIC_ISR_INT6, 1, 6, 0 }, { IIC_ISR_INT7, 1, 7, 0 },
+};
+
+static nt_fpga_field_init_t iic_rx_fifo_fields[] = {
+ { IIC_RX_FIFO_RXDATA, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_rx_fifo_ocy_fields[] = {
+ { IIC_RX_FIFO_OCY_OCY_VAL, 4, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_rx_fifo_pirq_fields[] = {
+ { IIC_RX_FIFO_PIRQ_CMP_VAL, 4, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_softr_fields[] = {
+ { IIC_SOFTR_RKEY, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t iic_sr_fields[] = {
+ { IIC_SR_AAS, 1, 1, 0 }, { IIC_SR_ABGC, 1, 0, 0 },
+ { IIC_SR_BB, 1, 2, 0 }, { IIC_SR_RXFIFO_EMPTY, 1, 6, 1 },
+ { IIC_SR_RXFIFO_FULL, 1, 5, 0 }, { IIC_SR_SRW, 1, 3, 0 },
+ { IIC_SR_TXFIFO_EMPTY, 1, 7, 1 }, { IIC_SR_TXFIFO_FULL, 1, 4, 0 },
+};
+
+static nt_fpga_field_init_t iic_tbuf_fields[] = {
+ { IIC_TBUF_TBUF_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_ten_adr_fields[] = {
+ { IIC_TEN_ADR_MSB_SLV_ADR, 3, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_thddat_fields[] = {
+ { IIC_THDDAT_THDDAT_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_thdsta_fields[] = {
+ { IIC_THDSTA_THDSTA_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_thigh_fields[] = {
+ { IIC_THIGH_THIGH_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tlow_fields[] = {
+ { IIC_TLOW_TLOW_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tsudat_fields[] = {
+ { IIC_TSUDAT_TSUDAT_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tsusta_fields[] = {
+ { IIC_TSUSTA_TSUSTA_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tsusto_fields[] = {
+ { IIC_TSUSTO_TSUSTO_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tx_fifo_fields[] = {
+ { IIC_TX_FIFO_START, 1, 8, 0 },
+ { IIC_TX_FIFO_STOP, 1, 9, 0 },
+ { IIC_TX_FIFO_TXDATA, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tx_fifo_ocy_fields[] = {
+ { IIC_TX_FIFO_OCY_OCY_VAL, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t iic_registers[] = {
+ { IIC_ADR, 68, 8, REGISTER_TYPE_RW, 0, 1, iic_adr_fields },
+ { IIC_CR, 64, 8, REGISTER_TYPE_RW, 0, 8, iic_cr_fields },
+ { IIC_DGIE, 7, 32, REGISTER_TYPE_RW, 0, 1, iic_dgie_fields },
+ { IIC_GPO, 73, 1, REGISTER_TYPE_RW, 0, 1, iic_gpo_fields },
+ { IIC_IER, 10, 8, REGISTER_TYPE_RW, 0, 8, iic_ier_fields },
+ { IIC_ISR, 8, 8, REGISTER_TYPE_RW, 0, 8, iic_isr_fields },
+ { IIC_RX_FIFO, 67, 8, REGISTER_TYPE_RO, 0, 1, iic_rx_fifo_fields },
+ { IIC_RX_FIFO_OCY, 70, 4, REGISTER_TYPE_RO, 0, 1,
+ iic_rx_fifo_ocy_fields
+ },
+ { IIC_RX_FIFO_PIRQ, 72, 4, REGISTER_TYPE_RW, 0, 1,
+ iic_rx_fifo_pirq_fields
+ },
+ { IIC_SOFTR, 16, 4, REGISTER_TYPE_WO, 0, 1, iic_softr_fields },
+ { IIC_SR, 65, 8, REGISTER_TYPE_RO, 192, 8, iic_sr_fields },
+ { IIC_TBUF, 78, 32, REGISTER_TYPE_RW, 0, 1, iic_tbuf_fields },
+ { IIC_TEN_ADR, 71, 3, REGISTER_TYPE_RO, 0, 1, iic_ten_adr_fields },
+ { IIC_THDDAT, 81, 32, REGISTER_TYPE_RW, 0, 1, iic_thddat_fields },
+ { IIC_THDSTA, 76, 32, REGISTER_TYPE_RW, 0, 1, iic_thdsta_fields },
+ { IIC_THIGH, 79, 32, REGISTER_TYPE_RW, 0, 1, iic_thigh_fields },
+ { IIC_TLOW, 80, 32, REGISTER_TYPE_RW, 0, 1, iic_tlow_fields },
+ { IIC_TSUDAT, 77, 32, REGISTER_TYPE_RW, 0, 1, iic_tsudat_fields },
+ { IIC_TSUSTA, 74, 32, REGISTER_TYPE_RW, 0, 1, iic_tsusta_fields },
+ { IIC_TSUSTO, 75, 32, REGISTER_TYPE_RW, 0, 1, iic_tsusto_fields },
+ { IIC_TX_FIFO, 66, 10, REGISTER_TYPE_WO, 0, 3, iic_tx_fifo_fields },
+ { IIC_TX_FIFO_OCY, 69, 4, REGISTER_TYPE_RO, 0, 1,
+ iic_tx_fifo_ocy_fields
+ },
+};
+
+static nt_fpga_field_init_t ins_rcp_ctrl_fields[] = {
+ { INS_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { INS_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t ins_rcp_data_fields[] = {
+ { INS_RCP_DATA_DYN, 5, 0, 0x0000 },
+ { INS_RCP_DATA_LEN, 8, 15, 0x0000 },
+ { INS_RCP_DATA_OFS, 10, 5, 0x0000 },
+};
+
+static nt_fpga_register_init_t ins_registers[] = {
+ { INS_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, ins_rcp_ctrl_fields },
+ { INS_RCP_DATA, 1, 23, REGISTER_TYPE_WO, 0, 3, ins_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t km_cam_ctrl_fields[] = {
+ { KM_CAM_CTRL_ADR, 13, 0, 0x0000 },
+ { KM_CAM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_cam_data_fields[] = {
+ { KM_CAM_DATA_FT0, 4, 192, 0x0000 },
+ { KM_CAM_DATA_FT1, 4, 196, 0x0000 },
+ { KM_CAM_DATA_FT2, 4, 200, 0x0000 },
+ { KM_CAM_DATA_FT3, 4, 204, 0x0000 },
+ { KM_CAM_DATA_FT4, 4, 208, 0x0000 },
+ { KM_CAM_DATA_FT5, 4, 212, 0x0000 },
+ { KM_CAM_DATA_W0, 32, 0, 0x0000 },
+ { KM_CAM_DATA_W1, 32, 32, 0x0000 },
+ { KM_CAM_DATA_W2, 32, 64, 0x0000 },
+ { KM_CAM_DATA_W3, 32, 96, 0x0000 },
+ { KM_CAM_DATA_W4, 32, 128, 0x0000 },
+ { KM_CAM_DATA_W5, 32, 160, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_rcp_ctrl_fields[] = {
+ { KM_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { KM_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_rcp_data_fields[] = {
+ { KM_RCP_DATA_BANK_A, 12, 694, 0x0000 },
+ { KM_RCP_DATA_BANK_B, 12, 706, 0x0000 },
+ { KM_RCP_DATA_DUAL, 1, 651, 0x0000 },
+ { KM_RCP_DATA_DW0_B_DYN, 5, 729, 0x0000 },
+ { KM_RCP_DATA_DW0_B_OFS, 8, 734, 0x0000 },
+ { KM_RCP_DATA_DW10_DYN, 5, 55, 0x0000 },
+ { KM_RCP_DATA_DW10_OFS, 8, 60, 0x0000 },
+ { KM_RCP_DATA_DW10_SEL_A, 2, 68, 0x0000 },
+ { KM_RCP_DATA_DW10_SEL_B, 2, 70, 0x0000 },
+ { KM_RCP_DATA_DW2_B_DYN, 5, 742, 0x0000 },
+ { KM_RCP_DATA_DW2_B_OFS, 8, 747, 0x0000 },
+ { KM_RCP_DATA_DW8_DYN, 5, 36, 0x0000 },
+ { KM_RCP_DATA_DW8_OFS, 8, 41, 0x0000 },
+ { KM_RCP_DATA_DW8_SEL_A, 3, 49, 0x0000 },
+ { KM_RCP_DATA_DW8_SEL_B, 3, 52, 0x0000 },
+ { KM_RCP_DATA_EL_A, 4, 653, 0x0000 },
+ { KM_RCP_DATA_EL_B, 3, 657, 0x0000 },
+ { KM_RCP_DATA_FTM_A, 16, 662, 0x0000 },
+ { KM_RCP_DATA_FTM_B, 16, 678, 0x0000 },
+ { KM_RCP_DATA_INFO_A, 1, 660, 0x0000 },
+ { KM_RCP_DATA_INFO_B, 1, 661, 0x0000 },
+ { KM_RCP_DATA_KEYWAY_A, 1, 725, 0x0000 },
+ { KM_RCP_DATA_KEYWAY_B, 1, 726, 0x0000 },
+ { KM_RCP_DATA_KL_A, 4, 718, 0x0000 },
+ { KM_RCP_DATA_KL_B, 3, 722, 0x0000 },
+ { KM_RCP_DATA_MASK_A, 384, 75, 0x0000 },
+ { KM_RCP_DATA_MASK_B, 192, 459, 0x0000 },
+ { KM_RCP_DATA_PAIRED, 1, 652, 0x0000 },
+ { KM_RCP_DATA_QW0_DYN, 5, 0, 0x0000 },
+ { KM_RCP_DATA_QW0_OFS, 8, 5, 0x0000 },
+ { KM_RCP_DATA_QW0_SEL_A, 3, 13, 0x0000 },
+ { KM_RCP_DATA_QW0_SEL_B, 3, 16, 0x0000 },
+ { KM_RCP_DATA_QW4_DYN, 5, 19, 0x0000 },
+ { KM_RCP_DATA_QW4_OFS, 8, 24, 0x0000 },
+ { KM_RCP_DATA_QW4_SEL_A, 2, 32, 0x0000 },
+ { KM_RCP_DATA_QW4_SEL_B, 2, 34, 0x0000 },
+ { KM_RCP_DATA_SW4_B_DYN, 5, 755, 0x0000 },
+ { KM_RCP_DATA_SW4_B_OFS, 8, 760, 0x0000 },
+ { KM_RCP_DATA_SW5_B_DYN, 5, 768, 0x0000 },
+ { KM_RCP_DATA_SW5_B_OFS, 8, 773, 0x0000 },
+ { KM_RCP_DATA_SWX_CCH, 1, 72, 0x0000 },
+ { KM_RCP_DATA_SWX_SEL_A, 1, 73, 0x0000 },
+ { KM_RCP_DATA_SWX_SEL_B, 1, 74, 0x0000 },
+ { KM_RCP_DATA_SYNERGY_MODE, 2, 727, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_status_fields[] = {
+ { KM_STATUS_TCQ_RDY, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcam_ctrl_fields[] = {
+ { KM_TCAM_CTRL_ADR, 14, 0, 0x0000 },
+ { KM_TCAM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcam_data_fields[] = {
+ { KM_TCAM_DATA_T, 72, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tci_ctrl_fields[] = {
+ { KM_TCI_CTRL_ADR, 10, 0, 0x0000 },
+ { KM_TCI_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tci_data_fields[] = {
+ { KM_TCI_DATA_COLOR, 32, 0, 0x0000 },
+ { KM_TCI_DATA_FT, 4, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcq_ctrl_fields[] = {
+ { KM_TCQ_CTRL_ADR, 7, 0, 0x0000 },
+ { KM_TCQ_CTRL_CNT, 5, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcq_data_fields[] = {
+ { KM_TCQ_DATA_BANK_MASK, 12, 0, 0x0000 },
+ { KM_TCQ_DATA_QUAL, 3, 12, 0x0000 },
+};
+
+static nt_fpga_register_init_t km_registers[] = {
+ { KM_CAM_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, km_cam_ctrl_fields },
+ { KM_CAM_DATA, 3, 216, REGISTER_TYPE_WO, 0, 12, km_cam_data_fields },
+ { KM_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, km_rcp_ctrl_fields },
+ { KM_RCP_DATA, 1, 781, REGISTER_TYPE_WO, 0, 44, km_rcp_data_fields },
+ { KM_STATUS, 10, 1, REGISTER_TYPE_RO, 0, 1, km_status_fields },
+ { KM_TCAM_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, km_tcam_ctrl_fields },
+ { KM_TCAM_DATA, 5, 72, REGISTER_TYPE_WO, 0, 1, km_tcam_data_fields },
+ { KM_TCI_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, km_tci_ctrl_fields },
+ { KM_TCI_DATA, 7, 36, REGISTER_TYPE_WO, 0, 2, km_tci_data_fields },
+ { KM_TCQ_CTRL, 8, 21, REGISTER_TYPE_WO, 0, 2, km_tcq_ctrl_fields },
+ { KM_TCQ_DATA, 9, 15, REGISTER_TYPE_WO, 0, 2, km_tcq_data_fields },
+};
+
+static nt_fpga_field_init_t mac_pcs_bad_code_fields[] = {
+ { MAC_PCS_BAD_CODE_CODE_ERR, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_bip_err_fields[] = {
+ { MAC_PCS_BIP_ERR_BIP_ERR, 640, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_block_lock_fields[] = {
+ { MAC_PCS_BLOCK_LOCK_LOCK, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_block_lock_chg_fields[] = {
+ { MAC_PCS_BLOCK_LOCK_CHG_LOCK_CHG, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_debounce_ctrl_fields[] = {
+ { MAC_PCS_DEBOUNCE_CTRL_NT_DEBOUNCE_LATENCY, 8, 8, 10 },
+ { MAC_PCS_DEBOUNCE_CTRL_NT_FORCE_LINK_DOWN, 1, 16, 0 },
+ { MAC_PCS_DEBOUNCE_CTRL_NT_LINKUP_LATENCY, 8, 0, 10 },
+ { MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL, 2, 17, 2 },
+};
+
+static nt_fpga_field_init_t mac_pcs_drp_ctrl_fields[] = {
+ { MAC_PCS_DRP_CTRL_ADR, 10, 16, 0 },
+ { MAC_PCS_DRP_CTRL_DATA, 16, 0, 0 },
+ { MAC_PCS_DRP_CTRL_DBG_BUSY, 1, 30, 0x0000 },
+ { MAC_PCS_DRP_CTRL_DONE, 1, 31, 0x0000 },
+ { MAC_PCS_DRP_CTRL_MOD_ADR, 3, 26, 0 },
+ { MAC_PCS_DRP_CTRL_WREN, 1, 29, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_ctrl_fields[] = {
+ { MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN, 5, 0, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_cw_cnt_fields[] = {
+ { MAC_PCS_FEC_CW_CNT_CW_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_0_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_0_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_1_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_1_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_2_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_2_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_3_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_3_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_0_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_0_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_1_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_1_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_2_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_2_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_3_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_3_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_map_fields[] = {
+ { MAC_PCS_FEC_LANE_MAP_MAPPING, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_stat_fields[] = {
+ { MAC_PCS_FEC_STAT_AM_LOCK, 1, 10, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_0, 1, 3, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_1, 1, 4, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_2, 1, 5, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_3, 1, 6, 0x0000 },
+ { MAC_PCS_FEC_STAT_BLOCK_LOCK, 1, 9, 0x0000 },
+ { MAC_PCS_FEC_STAT_BYPASS, 1, 0, 0x0000 },
+ { MAC_PCS_FEC_STAT_FEC_LANE_ALGN, 1, 7, 0x0000 },
+ { MAC_PCS_FEC_STAT_HI_SER, 1, 2, 0x0000 },
+ { MAC_PCS_FEC_STAT_PCS_LANE_ALGN, 1, 8, 0x0000 },
+ { MAC_PCS_FEC_STAT_VALID, 1, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_ucw_cnt_fields[] = {
+ { MAC_PCS_FEC_UCW_CNT_UCW_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_ctl_rx_fields[] = {
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_0, 1, 24, 0 },
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_1, 1, 25, 0 },
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_2, 1, 26, 0 },
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_3, 1, 27, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_0, 1, 20, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_1, 1, 21, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_2, 1, 22, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_3, 1, 23, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_0, 1, 16, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_1, 1, 17, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_2, 1, 18, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_3, 1, 19, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_0, 1, 0, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_1, 1, 1, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_2, 1, 2, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_3, 1, 3, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_0, 3, 4, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_1, 3, 7, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_2, 3, 10, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_3, 3, 13, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_ctl_tx_fields[] = {
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_0, 1, 4, 0 },
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_1, 1, 5, 0 },
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_2, 1, 6, 0 },
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_3, 1, 7, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_0, 1, 0, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_1, 1, 1, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_2, 1, 2, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_3, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_diff_ctl_fields[] = {
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0, 5, 0, 24 },
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1, 5, 5, 24 },
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2, 5, 10, 24 },
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3, 5, 15, 24 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_loop_fields[] = {
+ { MAC_PCS_GTY_LOOP_GT_LOOP_0, 3, 0, 0 },
+ { MAC_PCS_GTY_LOOP_GT_LOOP_1, 3, 3, 0 },
+ { MAC_PCS_GTY_LOOP_GT_LOOP_2, 3, 6, 0 },
+ { MAC_PCS_GTY_LOOP_GT_LOOP_3, 3, 9, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_post_cursor_fields[] = {
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0, 5, 0, 20 },
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1, 5, 5, 20 },
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2, 5, 10, 20 },
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3, 5, 15, 20 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_prbs_sel_fields[] = {
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_0, 4, 16, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_1, 4, 20, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_2, 4, 24, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_3, 4, 28, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_0, 4, 0, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_1, 4, 4, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_2, 4, 8, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_3, 4, 12, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_pre_cursor_fields[] = {
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0, 5, 0, 0 },
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1, 5, 5, 0 },
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2, 5, 10, 0 },
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3, 5, 15, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_rx_buf_stat_fields[] = {
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0, 3, 0, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1, 3, 3, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2, 3, 6, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3, 3, 9, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0, 3, 12, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1, 3, 15, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2, 3, 18, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3, 3, 21, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_scan_ctl_fields[] = {
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_0, 1, 0, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_1, 1, 1, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_2, 1, 2, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_3, 1, 3, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_0, 1, 4, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_1, 1, 5, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_2, 1, 6, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_3, 1, 7, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_0, 1, 12, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_1, 1, 13, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_2, 1, 14, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_3, 1, 15, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_0, 1, 8, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_1, 1, 9, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_2, 1, 10, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_3, 1, 11, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_scan_stat_fields[] = {
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_0, 1, 0, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_1, 1, 1, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_2, 1, 2, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_3, 1, 3, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_0, 1, 4, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_1, 1, 5, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_2, 1, 6, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_3, 1, 7, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_stat_fields[] = {
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_0, 1, 4, 0x0000 },
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_1, 1, 5, 0x0000 },
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_2, 1, 6, 0x0000 },
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_3, 1, 7, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_0, 2, 8, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_1, 2, 10, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_2, 2, 12, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_3, 2, 14, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_0, 1, 0, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_1, 1, 1, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_2, 1, 2, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_3, 1, 3, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_link_summary_fields[] = {
+ { MAC_PCS_LINK_SUMMARY_ABS, 1, 0, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_LH_ABS, 1, 2, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT, 1, 13, 0 },
+ { MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT, 1, 14, 0 },
+ { MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT, 8, 4, 0 },
+ { MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE, 1, 3, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_LOCAL_FAULT, 1, 17, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_NIM_INTERR, 1, 12, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE, 1, 1, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_REMOTE_FAULT, 1, 18, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_RESERVED, 2, 15, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_mac_pcs_config_fields[] = {
+ { MAC_PCS_MAC_PCS_CONFIG_RX_CORE_RST, 1, 3, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE, 1, 5, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC, 1, 6, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST, 1, 1, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN, 1, 7, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_CORE_RST, 1, 2, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE, 1, 8, 1 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_FCS_REMOVE, 1, 4, 1 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST, 1, 0, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE, 1, 9, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI, 1, 10, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN, 1, 11, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_max_pkt_len_fields[] = {
+ { MAC_PCS_MAX_PKT_LEN_MAX_LEN, 14, 0, 10000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_phymac_misc_fields[] = {
+ { MAC_PCS_PHYMAC_MISC_TS_EOP, 1, 3, 1 },
+ { MAC_PCS_PHYMAC_MISC_TX_MUX_STATE, 4, 4, 0x0000 },
+ { MAC_PCS_PHYMAC_MISC_TX_SEL_HOST, 1, 0, 1 },
+ { MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP, 1, 2, 0 },
+ { MAC_PCS_PHYMAC_MISC_TX_SEL_TFG, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_phy_stat_fields[] = {
+ { MAC_PCS_PHY_STAT_ALARM, 1, 2, 0x0000 },
+ { MAC_PCS_PHY_STAT_MOD_PRS, 1, 1, 0x0000 },
+ { MAC_PCS_PHY_STAT_RX_LOS, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_stat_pcs_rx_fields[] = {
+ { MAC_PCS_STAT_PCS_RX_ALIGNED, 1, 1, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_ALIGNED_ERR, 1, 2, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_GOT_SIGNAL_OS, 1, 9, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_HI_BER, 1, 8, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT, 1, 4, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LOCAL_FAULT, 1, 6, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_MISALIGNED, 1, 3, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT, 1, 5, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_REMOTE_FAULT, 1, 7, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_STATUS, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_stat_pcs_rx_latch_fields[] = {
+ { MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED, 1, 1, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED_ERR, 1, 2, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_GOT_SIGNAL_OS, 1, 9, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_HI_BER, 1, 8, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_INTERNAL_LOCAL_FAULT, 1, 4, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_LOCAL_FAULT, 1, 6, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_MISALIGNED, 1, 3, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_RECEIVED_LOCAL_FAULT, 1, 5, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_REMOTE_FAULT, 1, 7, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_STATUS, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_stat_pcs_tx_fields[] = {
+ { MAC_PCS_STAT_PCS_TX_LOCAL_FAULT, 1, 0, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_LOCAL_FAULT_CHANGED, 1, 5, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR, 1, 4, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR_CHANGED, 1, 9, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR, 1, 3, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR_CHANGED, 1, 8, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_OVFOUT, 1, 2, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_OVFOUT_CHANGED, 1, 7, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_UNFOUT, 1, 1, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_UNFOUT_CHANGED, 1, 6, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_synced_fields[] = {
+ { MAC_PCS_SYNCED_SYNC, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_synced_err_fields[] = {
+ { MAC_PCS_SYNCED_ERR_SYNC_ERROR, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_test_err_fields[] = {
+ { MAC_PCS_TEST_ERR_CODE_ERR, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_timestamp_comp_fields[] = {
+ { MAC_PCS_TIMESTAMP_COMP_RX_DLY, 16, 0, 1451 },
+ { MAC_PCS_TIMESTAMP_COMP_TX_DLY, 16, 16, 1440 },
+};
+
+static nt_fpga_field_init_t mac_pcs_vl_demuxed_fields[] = {
+ { MAC_PCS_VL_DEMUXED_LOCK, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_vl_demuxed_chg_fields[] = {
+ { MAC_PCS_VL_DEMUXED_CHG_LOCK_CHG, 20, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t mac_pcs_registers[] = {
+ { MAC_PCS_BAD_CODE, 26, 16, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_bad_code_fields
+ },
+ { MAC_PCS_BIP_ERR, 31, 640, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_bip_err_fields
+ },
+ { MAC_PCS_BLOCK_LOCK, 27, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_block_lock_fields
+ },
+ { MAC_PCS_BLOCK_LOCK_CHG, 28, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_block_lock_chg_fields
+ },
+ { MAC_PCS_DEBOUNCE_CTRL, 1, 19, REGISTER_TYPE_RW, 264714, 4,
+ mac_pcs_debounce_ctrl_fields
+ },
+ { MAC_PCS_DRP_CTRL, 43, 32, REGISTER_TYPE_MIXED, 0, 6,
+ mac_pcs_drp_ctrl_fields
+ },
+ { MAC_PCS_FEC_CTRL, 2, 5, REGISTER_TYPE_RW, 0, 1,
+ mac_pcs_fec_ctrl_fields
+ },
+ { MAC_PCS_FEC_CW_CNT, 9, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_cw_cnt_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_0, 11, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_0_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_1, 12, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_1_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_2, 13, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_2_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_3, 14, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_3_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_0, 5, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_0_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_1, 6, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_1_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_2, 7, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_2_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_3, 8, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_3_fields
+ },
+ { MAC_PCS_FEC_LANE_MAP, 4, 8, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_map_fields
+ },
+ { MAC_PCS_FEC_STAT, 3, 11, REGISTER_TYPE_RO, 0, 11,
+ mac_pcs_fec_stat_fields
+ },
+ { MAC_PCS_FEC_UCW_CNT, 10, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_ucw_cnt_fields
+ },
+ { MAC_PCS_GTY_CTL_RX, 38, 28, REGISTER_TYPE_RW, 0, 20,
+ mac_pcs_gty_ctl_rx_fields
+ },
+ { MAC_PCS_GTY_CTL_TX, 39, 8, REGISTER_TYPE_RW, 0, 8,
+ mac_pcs_gty_ctl_tx_fields
+ },
+ { MAC_PCS_GTY_DIFF_CTL, 35, 20, REGISTER_TYPE_RW, 811800, 4,
+ mac_pcs_gty_diff_ctl_fields
+ },
+ { MAC_PCS_GTY_LOOP, 20, 12, REGISTER_TYPE_RW, 0, 4,
+ mac_pcs_gty_loop_fields
+ },
+ { MAC_PCS_GTY_POST_CURSOR, 36, 20, REGISTER_TYPE_RW, 676500, 4,
+ mac_pcs_gty_post_cursor_fields
+ },
+ { MAC_PCS_GTY_PRBS_SEL, 40, 32, REGISTER_TYPE_RW, 0, 8,
+ mac_pcs_gty_prbs_sel_fields
+ },
+ { MAC_PCS_GTY_PRE_CURSOR, 37, 20, REGISTER_TYPE_RW, 0, 4,
+ mac_pcs_gty_pre_cursor_fields
+ },
+ { MAC_PCS_GTY_RX_BUF_STAT, 34, 24, REGISTER_TYPE_RO, 0, 8,
+ mac_pcs_gty_rx_buf_stat_fields
+ },
+ { MAC_PCS_GTY_SCAN_CTL, 41, 16, REGISTER_TYPE_RW, 0, 16,
+ mac_pcs_gty_scan_ctl_fields
+ },
+ { MAC_PCS_GTY_SCAN_STAT, 42, 8, REGISTER_TYPE_RO, 0, 8,
+ mac_pcs_gty_scan_stat_fields
+ },
+ { MAC_PCS_GTY_STAT, 33, 16, REGISTER_TYPE_RO, 0, 12,
+ mac_pcs_gty_stat_fields
+ },
+ { MAC_PCS_LINK_SUMMARY, 0, 19, REGISTER_TYPE_RO, 0, 11,
+ mac_pcs_link_summary_fields
+ },
+ { MAC_PCS_MAC_PCS_CONFIG, 19, 12, REGISTER_TYPE_RW, 272, 12,
+ mac_pcs_mac_pcs_config_fields
+ },
+ { MAC_PCS_MAX_PKT_LEN, 17, 14, REGISTER_TYPE_RW, 10000, 1,
+ mac_pcs_max_pkt_len_fields
+ },
+ { MAC_PCS_PHYMAC_MISC, 16, 8, REGISTER_TYPE_MIXED, 9, 5,
+ mac_pcs_phymac_misc_fields
+ },
+ { MAC_PCS_PHY_STAT, 15, 3, REGISTER_TYPE_RO, 0, 3,
+ mac_pcs_phy_stat_fields
+ },
+ { MAC_PCS_STAT_PCS_RX, 21, 10, REGISTER_TYPE_RO, 0, 10,
+ mac_pcs_stat_pcs_rx_fields
+ },
+ { MAC_PCS_STAT_PCS_RX_LATCH, 22, 10, REGISTER_TYPE_RO, 0, 10,
+ mac_pcs_stat_pcs_rx_latch_fields
+ },
+ { MAC_PCS_STAT_PCS_TX, 23, 10, REGISTER_TYPE_RO, 0, 10,
+ mac_pcs_stat_pcs_tx_fields
+ },
+ { MAC_PCS_SYNCED, 24, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_synced_fields
+ },
+ { MAC_PCS_SYNCED_ERR, 25, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_synced_err_fields
+ },
+ { MAC_PCS_TEST_ERR, 32, 16, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_test_err_fields
+ },
+ { MAC_PCS_TIMESTAMP_COMP, 18, 32, REGISTER_TYPE_RW, 94373291, 2,
+ mac_pcs_timestamp_comp_fields
+ },
+ { MAC_PCS_VL_DEMUXED, 29, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_vl_demuxed_fields
+ },
+ { MAC_PCS_VL_DEMUXED_CHG, 30, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_vl_demuxed_chg_fields
+ },
+};
+
+static nt_fpga_field_init_t mac_rx_bad_fcs_fields[] = {
+ { MAC_RX_BAD_FCS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_fragment_fields[] = {
+ { MAC_RX_FRAGMENT_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_packet_bad_fcs_fields[] = {
+ { MAC_RX_PACKET_BAD_FCS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_packet_small_fields[] = {
+ { MAC_RX_PACKET_SMALL_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_bytes_fields[] = {
+ { MAC_RX_TOTAL_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_good_bytes_fields[] = {
+ { MAC_RX_TOTAL_GOOD_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_good_packets_fields[] = {
+ { MAC_RX_TOTAL_GOOD_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_packets_fields[] = {
+ { MAC_RX_TOTAL_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_undersize_fields[] = {
+ { MAC_RX_UNDERSIZE_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t mac_rx_registers[] = {
+ { MAC_RX_BAD_FCS, 0, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_bad_fcs_fields
+ },
+ { MAC_RX_FRAGMENT, 6, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_fragment_fields
+ },
+ { MAC_RX_PACKET_BAD_FCS, 7, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_packet_bad_fcs_fields
+ },
+ { MAC_RX_PACKET_SMALL, 3, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_packet_small_fields
+ },
+ { MAC_RX_TOTAL_BYTES, 4, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_bytes_fields
+ },
+ { MAC_RX_TOTAL_GOOD_BYTES, 5, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_good_bytes_fields
+ },
+ { MAC_RX_TOTAL_GOOD_PACKETS, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_good_packets_fields
+ },
+ { MAC_RX_TOTAL_PACKETS, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_packets_fields
+ },
+ { MAC_RX_UNDERSIZE, 8, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_undersize_fields
+ },
+};
+
+static nt_fpga_field_init_t mac_tx_packet_small_fields[] = {
+ { MAC_TX_PACKET_SMALL_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_bytes_fields[] = {
+ { MAC_TX_TOTAL_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_good_bytes_fields[] = {
+ { MAC_TX_TOTAL_GOOD_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_good_packets_fields[] = {
+ { MAC_TX_TOTAL_GOOD_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_packets_fields[] = {
+ { MAC_TX_TOTAL_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t mac_tx_registers[] = {
+ { MAC_TX_PACKET_SMALL, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_packet_small_fields
+ },
+ { MAC_TX_TOTAL_BYTES, 3, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_bytes_fields
+ },
+ { MAC_TX_TOTAL_GOOD_BYTES, 4, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_good_bytes_fields
+ },
+ { MAC_TX_TOTAL_GOOD_PACKETS, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_good_packets_fields
+ },
+ { MAC_TX_TOTAL_PACKETS, 0, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_packets_fields
+ },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_ctrl_fields[] = {
+ { PCI_RD_TG_TG_CTRL_TG_RD_RDY, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rdaddr_fields[] = {
+ { PCI_RD_TG_TG_RDADDR_RAM_ADDR, 9, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rddata0_fields[] = {
+ { PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rddata1_fields[] = {
+ { PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rddata2_fields[] = {
+ { PCI_RD_TG_TG_RDDATA2_REQ_HID, 6, 22, 0 },
+ { PCI_RD_TG_TG_RDDATA2_REQ_SIZE, 22, 0, 0 },
+ { PCI_RD_TG_TG_RDDATA2_WAIT, 1, 30, 0 },
+ { PCI_RD_TG_TG_RDDATA2_WRAP, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rd_run_fields[] = {
+ { PCI_RD_TG_TG_RD_RUN_RD_ITERATION, 16, 0, 0 },
+};
+
+static nt_fpga_register_init_t pci_rd_tg_registers[] = {
+ { PCI_RD_TG_TG_CTRL, 5, 1, REGISTER_TYPE_RO, 0, 1,
+ pci_rd_tg_tg_ctrl_fields
+ },
+ { PCI_RD_TG_TG_RDADDR, 3, 9, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rdaddr_fields
+ },
+ { PCI_RD_TG_TG_RDDATA0, 0, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rddata0_fields
+ },
+ { PCI_RD_TG_TG_RDDATA1, 1, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rddata1_fields
+ },
+ { PCI_RD_TG_TG_RDDATA2, 2, 32, REGISTER_TYPE_WO, 0, 4,
+ pci_rd_tg_tg_rddata2_fields
+ },
+ { PCI_RD_TG_TG_RD_RUN, 4, 16, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rd_run_fields
+ },
+};
+
+static nt_fpga_field_init_t pci_ta_control_fields[] = {
+ { PCI_TA_CONTROL_ENABLE, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_ta_length_error_fields[] = {
+ { PCI_TA_LENGTH_ERROR_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t pci_ta_packet_bad_fields[] = {
+ { PCI_TA_PACKET_BAD_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t pci_ta_packet_good_fields[] = {
+ { PCI_TA_PACKET_GOOD_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t pci_ta_payload_error_fields[] = {
+ { PCI_TA_PAYLOAD_ERROR_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t pci_ta_registers[] = {
+ { PCI_TA_CONTROL, 0, 1, REGISTER_TYPE_WO, 0, 1, pci_ta_control_fields },
+ { PCI_TA_LENGTH_ERROR, 3, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_length_error_fields
+ },
+ { PCI_TA_PACKET_BAD, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_packet_bad_fields
+ },
+ { PCI_TA_PACKET_GOOD, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_packet_good_fields
+ },
+ { PCI_TA_PAYLOAD_ERROR, 4, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_payload_error_fields
+ },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_ctrl_fields[] = {
+ { PCI_WR_TG_TG_CTRL_TG_WR_RDY, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_seq_fields[] = {
+ { PCI_WR_TG_TG_SEQ_SEQUENCE, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wraddr_fields[] = {
+ { PCI_WR_TG_TG_WRADDR_RAM_ADDR, 9, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wrdata0_fields[] = {
+ { PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wrdata1_fields[] = {
+ { PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wrdata2_fields[] = {
+ { PCI_WR_TG_TG_WRDATA2_INC_MODE, 1, 29, 0 },
+ { PCI_WR_TG_TG_WRDATA2_REQ_HID, 6, 22, 0 },
+ { PCI_WR_TG_TG_WRDATA2_REQ_SIZE, 22, 0, 0 },
+ { PCI_WR_TG_TG_WRDATA2_WAIT, 1, 30, 0 },
+ { PCI_WR_TG_TG_WRDATA2_WRAP, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wr_run_fields[] = {
+ { PCI_WR_TG_TG_WR_RUN_WR_ITERATION, 16, 0, 0 },
+};
+
+static nt_fpga_register_init_t pci_wr_tg_registers[] = {
+ { PCI_WR_TG_TG_CTRL, 5, 1, REGISTER_TYPE_RO, 0, 1,
+ pci_wr_tg_tg_ctrl_fields
+ },
+ { PCI_WR_TG_TG_SEQ, 6, 16, REGISTER_TYPE_RW, 0, 1,
+ pci_wr_tg_tg_seq_fields
+ },
+ { PCI_WR_TG_TG_WRADDR, 3, 9, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wraddr_fields
+ },
+ { PCI_WR_TG_TG_WRDATA0, 0, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wrdata0_fields
+ },
+ { PCI_WR_TG_TG_WRDATA1, 1, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wrdata1_fields
+ },
+ { PCI_WR_TG_TG_WRDATA2, 2, 32, REGISTER_TYPE_WO, 0, 5,
+ pci_wr_tg_tg_wrdata2_fields
+ },
+ { PCI_WR_TG_TG_WR_RUN, 4, 16, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wr_run_fields
+ },
+};
+
+static nt_fpga_field_init_t pdb_config_fields[] = {
+ { PDB_CONFIG_PORT_OFS, 6, 3, 0 },
+ { PDB_CONFIG_TS_FORMAT, 3, 0, 0 },
+};
+
+static nt_fpga_field_init_t pdb_rcp_ctrl_fields[] = {
+ { PDB_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { PDB_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t pdb_rcp_data_fields[] = {
+ { PDB_RCP_DATA_ALIGN, 1, 17, 0x0000 },
+ { PDB_RCP_DATA_CRC_OVERWRITE, 1, 16, 0x0000 },
+ { PDB_RCP_DATA_DESCRIPTOR, 4, 0, 0x0000 },
+ { PDB_RCP_DATA_DESC_LEN, 5, 4, 0 },
+ { PDB_RCP_DATA_DUPLICATE_BIT, 5, 61, 0x0000 },
+ { PDB_RCP_DATA_DUPLICATE_EN, 1, 60, 0x0000 },
+ { PDB_RCP_DATA_IP_PROT_TNL, 1, 57, 0x0000 },
+ { PDB_RCP_DATA_OFS0_DYN, 5, 18, 0x0000 },
+ { PDB_RCP_DATA_OFS0_REL, 8, 23, 0x0000 },
+ { PDB_RCP_DATA_OFS1_DYN, 5, 31, 0x0000 },
+ { PDB_RCP_DATA_OFS1_REL, 8, 36, 0x0000 },
+ { PDB_RCP_DATA_OFS2_DYN, 5, 44, 0x0000 },
+ { PDB_RCP_DATA_OFS2_REL, 8, 49, 0x0000 },
+ { PDB_RCP_DATA_PCAP_KEEP_FCS, 1, 66, 0x0000 },
+ { PDB_RCP_DATA_PPC_HSH, 2, 58, 0x0000 },
+ { PDB_RCP_DATA_TX_IGNORE, 1, 14, 0x0000 },
+ { PDB_RCP_DATA_TX_NOW, 1, 15, 0x0000 },
+ { PDB_RCP_DATA_TX_PORT, 5, 9, 0x0000 },
+};
+
+static nt_fpga_register_init_t pdb_registers[] = {
+ { PDB_CONFIG, 2, 10, REGISTER_TYPE_WO, 0, 2, pdb_config_fields },
+ { PDB_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, pdb_rcp_ctrl_fields },
+ { PDB_RCP_DATA, 1, 67, REGISTER_TYPE_WO, 0, 18, pdb_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t pdi_cr_fields[] = {
+ { PDI_CR_EN, 1, 0, 0 }, { PDI_CR_PARITY, 1, 4, 0 },
+ { PDI_CR_RST, 1, 1, 0 }, { PDI_CR_RXRST, 1, 2, 0 },
+ { PDI_CR_STOP, 1, 5, 0 }, { PDI_CR_TXRST, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t pdi_drr_fields[] = {
+ { PDI_DRR_DRR, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t pdi_dtr_fields[] = {
+ { PDI_DTR_DTR, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t pdi_pre_fields[] = {
+ { PDI_PRE_PRE, 7, 0, 3 },
+};
+
+static nt_fpga_field_init_t pdi_sr_fields[] = {
+ { PDI_SR_DISABLE_BUSY, 1, 2, 0 }, { PDI_SR_DONE, 1, 0, 0 },
+ { PDI_SR_ENABLE_BUSY, 1, 1, 0 }, { PDI_SR_FRAME_ERR, 1, 5, 0 },
+ { PDI_SR_OVERRUN_ERR, 1, 7, 0 }, { PDI_SR_PARITY_ERR, 1, 6, 0 },
+ { PDI_SR_RXLVL, 7, 8, 0 }, { PDI_SR_RX_BUSY, 1, 4, 0 },
+ { PDI_SR_TXLVL, 7, 15, 0 }, { PDI_SR_TX_BUSY, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t pdi_srr_fields[] = {
+ { PDI_SRR_RST, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t pdi_registers[] = {
+ { PDI_CR, 1, 6, REGISTER_TYPE_WO, 0, 6, pdi_cr_fields },
+ { PDI_DRR, 4, 8, REGISTER_TYPE_RO, 0, 1, pdi_drr_fields },
+ { PDI_DTR, 3, 8, REGISTER_TYPE_WO, 0, 1, pdi_dtr_fields },
+ { PDI_PRE, 5, 7, REGISTER_TYPE_WO, 3, 1, pdi_pre_fields },
+ { PDI_SR, 2, 22, REGISTER_TYPE_RO, 0, 10, pdi_sr_fields },
+ { PDI_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, pdi_srr_fields },
+};
+
+static nt_fpga_field_init_t ptp1588_conf_fields[] = {
+ { PTP1588_CONF_MII_RX_TX_LOOP, 1, 0, 0 },
+ { PTP1588_CONF_MII_TX_RX_LOOP, 1, 1, 0 },
+ { PTP1588_CONF_PHY_RST1, 1, 10, 1 },
+ { PTP1588_CONF_PHY_RST2, 1, 11, 1 },
+ { PTP1588_CONF_PTP_CTRL_LOCAL, 1, 24, 0 },
+ { PTP1588_CONF_PTP_RX_CTRL, 2, 19, 0 },
+ { PTP1588_CONF_PTP_TX_CTRL, 2, 21, 0 },
+ { PTP1588_CONF_PTP_TX_CTRL_OS, 1, 23, 0 },
+ { PTP1588_CONF_RX_IGNORE_DEST_ADDR, 1, 25, 0 },
+ { PTP1588_CONF_TG_CMD, 2, 13, 0 },
+ { PTP1588_CONF_TG_MODE, 1, 12, 0 },
+ { PTP1588_CONF_TSM_MI_ACK, 1, 16, 0 },
+ { PTP1588_CONF_TSM_MI_BUSY, 1, 15, 0 },
+ { PTP1588_CONF_TSM_MI_ENA, 1, 18, 0 },
+ { PTP1588_CONF_TSM_MI_REQ, 1, 17, 0 },
+ { PTP1588_CONF_TX_IFG, 8, 2, 0 },
+ { PTP1588_CONF_TX_IGNORE_DEST_ADDR, 1, 26, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_data_fields[] = {
+ { PTP1588_GP_DATA_GPIO, 9, 1, 0 },
+ { PTP1588_GP_DATA_PWRDOWN_INTN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_data_lh_fields[] = {
+ { PTP1588_GP_DATA_LH_GPIO, 9, 1, 0 },
+ { PTP1588_GP_DATA_LH_PWRDOWN_INTN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_data_ll_fields[] = {
+ { PTP1588_GP_DATA_LL_GPIO, 9, 1, 511 },
+ { PTP1588_GP_DATA_LL_PWRDOWN_INTN, 1, 0, 1 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_oe_fields[] = {
+ { PTP1588_GP_OE_GPIO, 9, 1, 0 },
+ { PTP1588_GP_OE_PWRDOWN_INTN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_mac_inband_stat_fields[] = {
+ { PTP1588_MAC_INBAND_STAT_DUPLEX, 1, 3, 0x0000 },
+ { PTP1588_MAC_INBAND_STAT_LINK, 1, 0, 0x0000 },
+ { PTP1588_MAC_INBAND_STAT_SPEED, 2, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_mac_mi_conf_fields[] = {
+ { PTP1588_MAC_MI_CONF_ACCESS_TYPE, 1, 16, 0 },
+ { PTP1588_MAC_MI_CONF_ADDRESS, 16, 0, 0 },
+ { PTP1588_MAC_MI_CONF_RDY, 1, 17, 1 },
+};
+
+static nt_fpga_field_init_t ptp1588_mac_mi_data_fields[] = {
+ { PTP1588_MAC_MI_DATA_DATA, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_rx_host_adr_lsb_fields[] = {
+ { PTP1588_RX_HOST_ADR_LSB_LSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_rx_host_adr_msb_fields[] = {
+ { PTP1588_RX_HOST_ADR_MSB_MSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_rx_host_conf_fields[] = {
+ { PTP1588_RX_HOST_CONF_ENA, 1, 11, 0 },
+ { PTP1588_RX_HOST_CONF_RDPTR, 11, 0, 0 },
+ { PTP1588_RX_HOST_CONF_REDUCED, 1, 12, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_stat_fields[] = {
+ { PTP1588_STAT_DATA, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_stat_conf_fields[] = {
+ { PTP1588_STAT_CONF_INDEX, 5, 0, 0 },
+ { PTP1588_STAT_CONF_LOCK, 1, 5, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_first_dat_fields[] = {
+ { PTP1588_TX_FIRST_DAT_DAT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last1_dat_fields[] = {
+ { PTP1588_TX_LAST1_DAT_DAT, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last2_dat_fields[] = {
+ { PTP1588_TX_LAST2_DAT_DAT, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last3_dat_fields[] = {
+ { PTP1588_TX_LAST3_DAT_DAT, 24, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last4_dat_fields[] = {
+ { PTP1588_TX_LAST4_DAT_DAT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_mid_dat_fields[] = {
+ { PTP1588_TX_MID_DAT_DAT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_packet_state_fields[] = {
+ { PTP1588_TX_PACKET_STATE_MSG_TYPE, 4, 16, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_PCK_TYPE, 3, 20, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_SEQ_ID, 16, 0, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_TEST_MARGIN, 7, 23, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_VALID, 1, 30, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_status_fields[] = {
+ { PTP1588_TX_STATUS_DB_ERR, 1, 10, 1 },
+ { PTP1588_TX_STATUS_DB_FULL, 1, 9, 1 },
+ { PTP1588_TX_STATUS_FIFO_STATUS, 9, 0, 0 },
+ { PTP1588_TX_STATUS_RDY, 1, 11, 1 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_timestamp_ns_fields[] = {
+ { PTP1588_TX_TIMESTAMP_NS_TIMESTAMP, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_timestamp_sec_fields[] = {
+ { PTP1588_TX_TIMESTAMP_SEC_TIMESTAMP, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t ptp1588_registers[] = {
+ { PTP1588_CONF, 0, 27, REGISTER_TYPE_MIXED, 3072, 17,
+ ptp1588_conf_fields
+ },
+ { PTP1588_GP_DATA, 20, 10, REGISTER_TYPE_RW, 0, 2,
+ ptp1588_gp_data_fields
+ },
+ { PTP1588_GP_DATA_LH, 22, 10, REGISTER_TYPE_RO, 0, 2,
+ ptp1588_gp_data_lh_fields
+ },
+ { PTP1588_GP_DATA_LL, 21, 10, REGISTER_TYPE_RO, 1023, 2,
+ ptp1588_gp_data_ll_fields
+ },
+ { PTP1588_GP_OE, 19, 10, REGISTER_TYPE_WO, 0, 2, ptp1588_gp_oe_fields },
+ { PTP1588_MAC_INBAND_STAT, 3, 4, REGISTER_TYPE_RO, 0, 3,
+ ptp1588_mac_inband_stat_fields
+ },
+ { PTP1588_MAC_MI_CONF, 17, 18, REGISTER_TYPE_MIXED, 131072, 3,
+ ptp1588_mac_mi_conf_fields
+ },
+ { PTP1588_MAC_MI_DATA, 18, 32, REGISTER_TYPE_RW, 0, 1,
+ ptp1588_mac_mi_data_fields
+ },
+ { PTP1588_RX_HOST_ADR_LSB, 8, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_rx_host_adr_lsb_fields
+ },
+ { PTP1588_RX_HOST_ADR_MSB, 9, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_rx_host_adr_msb_fields
+ },
+ { PTP1588_RX_HOST_CONF, 7, 13, REGISTER_TYPE_RW, 0, 3,
+ ptp1588_rx_host_conf_fields
+ },
+ { PTP1588_STAT, 6, 32, REGISTER_TYPE_RO, 0, 1, ptp1588_stat_fields },
+ { PTP1588_STAT_CONF, 5, 6, REGISTER_TYPE_WO, 0, 2,
+ ptp1588_stat_conf_fields
+ },
+ { PTP1588_TX_FIRST_DAT, 10, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_first_dat_fields
+ },
+ { PTP1588_TX_LAST1_DAT, 12, 8, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last1_dat_fields
+ },
+ { PTP1588_TX_LAST2_DAT, 13, 16, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last2_dat_fields
+ },
+ { PTP1588_TX_LAST3_DAT, 14, 24, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last3_dat_fields
+ },
+ { PTP1588_TX_LAST4_DAT, 15, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last4_dat_fields
+ },
+ { PTP1588_TX_MID_DAT, 11, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_mid_dat_fields
+ },
+ { PTP1588_TX_PACKET_STATE, 4, 31, REGISTER_TYPE_RO, 0, 5,
+ ptp1588_tx_packet_state_fields
+ },
+ { PTP1588_TX_STATUS, 16, 12, REGISTER_TYPE_RO, 3584, 4,
+ ptp1588_tx_status_fields
+ },
+ { PTP1588_TX_TIMESTAMP_NS, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ ptp1588_tx_timestamp_ns_fields
+ },
+ { PTP1588_TX_TIMESTAMP_SEC, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ ptp1588_tx_timestamp_sec_fields
+ },
+};
+
+static nt_fpga_field_init_t qsl_qen_ctrl_fields[] = {
+ { QSL_QEN_CTRL_ADR, 5, 0, 0x0000 },
+ { QSL_QEN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_qen_data_fields[] = {
+ { QSL_QEN_DATA_EN, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_qst_ctrl_fields[] = {
+ { QSL_QST_CTRL_ADR, 12, 0, 0x0000 },
+ { QSL_QST_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_qst_data_fields[] = {
+ { QSL_QST_DATA_LRE, 1, 9, 0x0000 },
+ { QSL_QST_DATA_QEN, 1, 7, 0x0000 },
+ { QSL_QST_DATA_QUEUE, 7, 0, 0x0000 },
+ { QSL_QST_DATA_TCI, 16, 10, 0x0000 },
+ { QSL_QST_DATA_TX_PORT, 1, 8, 0x0000 },
+ { QSL_QST_DATA_VEN, 1, 26, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_rcp_ctrl_fields[] = {
+ { QSL_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { QSL_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_rcp_data_fields[] = {
+ { QSL_RCP_DATA_DISCARD, 1, 0, 0x0000 },
+ { QSL_RCP_DATA_DROP, 2, 1, 0x0000 },
+ { QSL_RCP_DATA_LR, 2, 51, 0x0000 },
+ { QSL_RCP_DATA_TBL_HI, 12, 15, 0x0000 },
+ { QSL_RCP_DATA_TBL_IDX, 12, 27, 0x0000 },
+ { QSL_RCP_DATA_TBL_LO, 12, 3, 0x0000 },
+ { QSL_RCP_DATA_TBL_MSK, 12, 39, 0x0000 },
+ { QSL_RCP_DATA_TSA, 1, 53, 0x0000 },
+ { QSL_RCP_DATA_VLI, 2, 54, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_unmq_ctrl_fields[] = {
+ { QSL_UNMQ_CTRL_ADR, 1, 0, 0x0000 },
+ { QSL_UNMQ_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_unmq_data_fields[] = {
+ { QSL_UNMQ_DATA_DEST_QUEUE, 7, 0, 0x0000 },
+ { QSL_UNMQ_DATA_EN, 1, 7, 0x0000 },
+};
+
+static nt_fpga_register_init_t qsl_registers[] = {
+ { QSL_QEN_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, qsl_qen_ctrl_fields },
+ { QSL_QEN_DATA, 5, 4, REGISTER_TYPE_WO, 0, 1, qsl_qen_data_fields },
+ { QSL_QST_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, qsl_qst_ctrl_fields },
+ { QSL_QST_DATA, 3, 27, REGISTER_TYPE_WO, 0, 6, qsl_qst_data_fields },
+ { QSL_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, qsl_rcp_ctrl_fields },
+ { QSL_RCP_DATA, 1, 56, REGISTER_TYPE_WO, 0, 9, qsl_rcp_data_fields },
+ { QSL_UNMQ_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, qsl_unmq_ctrl_fields },
+ { QSL_UNMQ_DATA, 7, 8, REGISTER_TYPE_WO, 0, 2, qsl_unmq_data_fields },
+};
+
+static nt_fpga_field_init_t qspi_cr_fields[] = {
+ { QSPI_CR_CPHA, 1, 4, 0 }, { QSPI_CR_CPOL, 1, 3, 0 },
+ { QSPI_CR_LOOP, 1, 0, 0 }, { QSPI_CR_LSBF, 1, 9, 0 },
+ { QSPI_CR_MSSAE, 1, 7, 1 }, { QSPI_CR_MST, 1, 2, 0 },
+ { QSPI_CR_MTI, 1, 8, 1 }, { QSPI_CR_RXFIFO_RST, 1, 6, 0 },
+ { QSPI_CR_SPE, 1, 1, 0 }, { QSPI_CR_TXFIFO_RST, 1, 5, 0 },
+};
+
+static nt_fpga_field_init_t qspi_dgie_fields[] = {
+ { QSPI_DGIE_GIE, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t qspi_drr_fields[] = {
+ { QSPI_DRR_DATA_VAL, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t qspi_dtr_fields[] = {
+ { QSPI_DTR_DATA_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t qspi_ier_fields[] = {
+ { QSPI_IER_CMD_ERR, 1, 13, 0 }, { QSPI_IER_CPOL_CPHA_ERR, 1, 9, 0 },
+ { QSPI_IER_DRR_FULL, 1, 4, 0 }, { QSPI_IER_DRR_NEMPTY, 1, 8, 0 },
+ { QSPI_IER_DRR_OR, 1, 5, 0 }, { QSPI_IER_DTR_EMPTY, 1, 2, 0 },
+ { QSPI_IER_DTR_UR, 1, 3, 0 }, { QSPI_IER_LOOP_ERR, 1, 12, 0 },
+ { QSPI_IER_MODF, 1, 0, 0 }, { QSPI_IER_MSB_ERR, 1, 11, 0 },
+ { QSPI_IER_SLV_ERR, 1, 10, 0 }, { QSPI_IER_SLV_MODF, 1, 1, 0 },
+ { QSPI_IER_SLV_MS, 1, 7, 0 }, { QSPI_IER_TXFIFO_HEMPTY, 1, 6, 0 },
+};
+
+static nt_fpga_field_init_t qspi_isr_fields[] = {
+ { QSPI_ISR_CMD_ERR, 1, 13, 0 }, { QSPI_ISR_CPOL_CPHA_ERR, 1, 9, 0 },
+ { QSPI_ISR_DRR_FULL, 1, 4, 0 }, { QSPI_ISR_DRR_NEMPTY, 1, 8, 0 },
+ { QSPI_ISR_DRR_OR, 1, 5, 0 }, { QSPI_ISR_DTR_EMPTY, 1, 2, 0 },
+ { QSPI_ISR_DTR_UR, 1, 3, 0 }, { QSPI_ISR_LOOP_ERR, 1, 12, 0 },
+ { QSPI_ISR_MODF, 1, 0, 0 }, { QSPI_ISR_MSB_ERR, 1, 11, 0 },
+ { QSPI_ISR_SLV_ERR, 1, 10, 0 }, { QSPI_ISR_SLV_MODF, 1, 1, 0 },
+ { QSPI_ISR_SLV_MS, 1, 7, 0 }, { QSPI_ISR_TXFIFO_HEMPTY, 1, 6, 0 },
+};
+
+static nt_fpga_field_init_t qspi_rx_fifo_ocy_fields[] = {
+ { QSPI_RX_FIFO_OCY_OCY_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t qspi_sr_fields[] = {
+ { QSPI_SR_CMD_ERR, 1, 10, 0 }, { QSPI_SR_CPOL_CPHA_ERR, 1, 6, 0 },
+ { QSPI_SR_LOOP_ERR, 1, 9, 0 }, { QSPI_SR_MODF, 1, 4, 0 },
+ { QSPI_SR_MSB_ERR, 1, 8, 0 }, { QSPI_SR_RXEMPTY, 1, 0, 1 },
+ { QSPI_SR_RXFULL, 1, 1, 0 }, { QSPI_SR_SLVMS, 1, 5, 1 },
+ { QSPI_SR_SLV_ERR, 1, 7, 0 }, { QSPI_SR_TXEMPTY, 1, 2, 1 },
+ { QSPI_SR_TXFULL, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t qspi_srr_fields[] = {
+ { QSPI_SRR_RST, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t qspi_ssr_fields[] = {
+ { QSPI_SSR_SEL_SLV, 32, 0, 4294967295 },
+};
+
+static nt_fpga_field_init_t qspi_tx_fifo_ocy_fields[] = {
+ { QSPI_TX_FIFO_OCY_OCY_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_register_init_t qspi_registers[] = {
+ { QSPI_CR, 24, 10, REGISTER_TYPE_RW, 384, 10, qspi_cr_fields },
+ { QSPI_DGIE, 7, 32, REGISTER_TYPE_RW, 0, 1, qspi_dgie_fields },
+ { QSPI_DRR, 27, 32, REGISTER_TYPE_RO, 0, 1, qspi_drr_fields },
+ { QSPI_DTR, 26, 32, REGISTER_TYPE_WO, 0, 1, qspi_dtr_fields },
+ { QSPI_IER, 10, 14, REGISTER_TYPE_RW, 0, 14, qspi_ier_fields },
+ { QSPI_ISR, 8, 14, REGISTER_TYPE_RW, 0, 14, qspi_isr_fields },
+ { QSPI_RX_FIFO_OCY, 30, 32, REGISTER_TYPE_RO, 0, 1,
+ qspi_rx_fifo_ocy_fields
+ },
+ { QSPI_SR, 25, 11, REGISTER_TYPE_RO, 37, 11, qspi_sr_fields },
+ { QSPI_SRR, 16, 4, REGISTER_TYPE_WO, 0, 1, qspi_srr_fields },
+ { QSPI_SSR, 28, 32, REGISTER_TYPE_RW, 4294967295, 1, qspi_ssr_fields },
+ { QSPI_TX_FIFO_OCY, 29, 32, REGISTER_TYPE_RO, 0, 1,
+ qspi_tx_fifo_ocy_fields
+ },
+};
+
+static nt_fpga_field_init_t rac_dbg_ctrl_fields[] = {
+ { RAC_DBG_CTRL_C, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rac_dbg_data_fields[] = {
+ { RAC_DBG_DATA_D, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rac_rab_buf_free_fields[] = {
+ { RAC_RAB_BUF_FREE_IB_FREE, 9, 0, 511 },
+ { RAC_RAB_BUF_FREE_IB_OVF, 1, 12, 0 },
+ { RAC_RAB_BUF_FREE_OB_FREE, 9, 16, 511 },
+ { RAC_RAB_BUF_FREE_OB_OVF, 1, 28, 0 },
+ { RAC_RAB_BUF_FREE_TIMEOUT, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_buf_used_fields[] = {
+ { RAC_RAB_BUF_USED_FLUSH, 1, 31, 0 },
+ { RAC_RAB_BUF_USED_IB_USED, 9, 0, 0 },
+ { RAC_RAB_BUF_USED_OB_USED, 9, 16, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_hi_fields[] = {
+ { RAC_RAB_DMA_IB_HI_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_lo_fields[] = {
+ { RAC_RAB_DMA_IB_LO_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_rd_fields[] = {
+ { RAC_RAB_DMA_IB_RD_PTR, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_wr_fields[] = {
+ { RAC_RAB_DMA_IB_WR_PTR, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ob_hi_fields[] = {
+ { RAC_RAB_DMA_OB_HI_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ob_lo_fields[] = {
+ { RAC_RAB_DMA_OB_LO_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ob_wr_fields[] = {
+ { RAC_RAB_DMA_OB_WR_PTR, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_ib_data_fields[] = {
+ { RAC_RAB_IB_DATA_D, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rac_rab_init_fields[] = {
+ { RAC_RAB_INIT_RAB, 3, 0, 7 },
+};
+
+static nt_fpga_field_init_t rac_rab_ob_data_fields[] = {
+ { RAC_RAB_OB_DATA_D, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t rac_registers[] = {
+ { RAC_DBG_CTRL, 4200, 32, REGISTER_TYPE_RW, 0, 1, rac_dbg_ctrl_fields },
+ { RAC_DBG_DATA, 4208, 32, REGISTER_TYPE_RW, 0, 1, rac_dbg_data_fields },
+ { RAC_RAB_BUF_FREE, 4176, 32, REGISTER_TYPE_MIXED, 33489407, 5,
+ rac_rab_buf_free_fields
+ },
+ { RAC_RAB_BUF_USED, 4184, 32, REGISTER_TYPE_MIXED, 0, 3,
+ rac_rab_buf_used_fields
+ },
+ { RAC_RAB_DMA_IB_HI, 4360, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ib_hi_fields
+ },
+ { RAC_RAB_DMA_IB_LO, 4352, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ib_lo_fields
+ },
+ { RAC_RAB_DMA_IB_RD, 4424, 16, REGISTER_TYPE_RO, 0, 1,
+ rac_rab_dma_ib_rd_fields
+ },
+ { RAC_RAB_DMA_IB_WR, 4416, 16, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ib_wr_fields
+ },
+ { RAC_RAB_DMA_OB_HI, 4376, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ob_hi_fields
+ },
+ { RAC_RAB_DMA_OB_LO, 4368, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ob_lo_fields
+ },
+ { RAC_RAB_DMA_OB_WR, 4480, 16, REGISTER_TYPE_RO, 0, 1,
+ rac_rab_dma_ob_wr_fields
+ },
+ { RAC_RAB_IB_DATA, 4160, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_ib_data_fields
+ },
+ { RAC_RAB_INIT, 4192, 3, REGISTER_TYPE_RW, 7, 1, rac_rab_init_fields },
+ { RAC_RAB_OB_DATA, 4168, 32, REGISTER_TYPE_RC1, 0, 1,
+ rac_rab_ob_data_fields
+ },
+};
+
+static nt_fpga_field_init_t rfd_ctrl_fields[] = {
+ { RFD_CTRL_CFP, 1, 2, 1 },
+ { RFD_CTRL_ISL, 1, 0, 1 },
+ { RFD_CTRL_PWMCW, 1, 1, 1 },
+};
+
+static nt_fpga_field_init_t rfd_max_frame_size_fields[] = {
+ { RFD_MAX_FRAME_SIZE_MAX, 14, 0, 9018 },
+};
+
+static nt_fpga_field_init_t rfd_tnl_vlan_fields[] = {
+ { RFD_TNL_VLAN_TPID0, 16, 0, 33024 },
+ { RFD_TNL_VLAN_TPID1, 16, 16, 33024 },
+};
+
+static nt_fpga_field_init_t rfd_vlan_fields[] = {
+ { RFD_VLAN_TPID0, 16, 0, 33024 },
+ { RFD_VLAN_TPID1, 16, 16, 33024 },
+};
+
+static nt_fpga_field_init_t rfd_vxlan_fields[] = {
+ { RFD_VXLAN_DP0, 16, 0, 4789 },
+ { RFD_VXLAN_DP1, 16, 16, 4789 },
+};
+
+static nt_fpga_register_init_t rfd_registers[] = {
+ { RFD_CTRL, 0, 3, REGISTER_TYPE_WO, 7, 3, rfd_ctrl_fields },
+ { RFD_MAX_FRAME_SIZE, 1, 14, REGISTER_TYPE_WO, 9018, 1,
+ rfd_max_frame_size_fields
+ },
+ { RFD_TNL_VLAN, 3, 32, REGISTER_TYPE_WO, 2164293888, 2,
+ rfd_tnl_vlan_fields
+ },
+ { RFD_VLAN, 2, 32, REGISTER_TYPE_WO, 2164293888, 2, rfd_vlan_fields },
+ { RFD_VXLAN, 4, 32, REGISTER_TYPE_WO, 313856693, 2, rfd_vxlan_fields },
+};
+
+static nt_fpga_field_init_t rmc_ctrl_fields[] = {
+ { RMC_CTRL_BLOCK_KEEPA, 1, 1, 1 },
+ { RMC_CTRL_BLOCK_MAC_PORT, 2, 8, 3 },
+ { RMC_CTRL_BLOCK_RPP_SLICE, 8, 10, 0 },
+ { RMC_CTRL_BLOCK_STATT, 1, 0, 1 },
+ { RMC_CTRL_LAG_PHY_ODD_EVEN, 1, 24, 0 },
+};
+
+static nt_fpga_field_init_t rmc_dbg_fields[] = {
+ { RMC_DBG_MERGE, 31, 0, 0 },
+};
+
+static nt_fpga_field_init_t rmc_mac_if_fields[] = {
+ { RMC_MAC_IF_ERR, 31, 0, 0 },
+};
+
+static nt_fpga_field_init_t rmc_status_fields[] = {
+ { RMC_STATUS_DESCR_FIFO_OF, 1, 16, 0 },
+ { RMC_STATUS_SF_RAM_OF, 1, 0, 0 },
+};
+
+static nt_fpga_register_init_t rmc_registers[] = {
+ { RMC_CTRL, 0, 25, REGISTER_TYPE_RW, 771, 5, rmc_ctrl_fields },
+ { RMC_DBG, 2, 31, REGISTER_TYPE_RO, 0, 1, rmc_dbg_fields },
+ { RMC_MAC_IF, 3, 31, REGISTER_TYPE_RO, 0, 1, rmc_mac_if_fields },
+ { RMC_STATUS, 1, 17, REGISTER_TYPE_RO, 0, 2, rmc_status_fields },
+};
+
+static nt_fpga_field_init_t rpl_ext_ctrl_fields[] = {
+ { RPL_EXT_CTRL_ADR, 10, 0, 0x0000 },
+ { RPL_EXT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_ext_data_fields[] = {
+ { RPL_EXT_DATA_RPL_PTR, 12, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rcp_ctrl_fields[] = {
+ { RPL_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { RPL_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rcp_data_fields[] = {
+ { RPL_RCP_DATA_DYN, 5, 0, 0x0000 },
+ { RPL_RCP_DATA_EXT_PRIO, 1, 35, 0x0000 },
+ { RPL_RCP_DATA_LEN, 8, 15, 0x0000 },
+ { RPL_RCP_DATA_OFS, 10, 5, 0x0000 },
+ { RPL_RCP_DATA_RPL_PTR, 12, 23, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rpl_ctrl_fields[] = {
+ { RPL_RPL_CTRL_ADR, 12, 0, 0x0000 },
+ { RPL_RPL_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rpl_data_fields[] = {
+ { RPL_RPL_DATA_VALUE, 128, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t rpl_registers[] = {
+ { RPL_EXT_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, rpl_ext_ctrl_fields },
+ { RPL_EXT_DATA, 3, 12, REGISTER_TYPE_WO, 0, 1, rpl_ext_data_fields },
+ { RPL_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, rpl_rcp_ctrl_fields },
+ { RPL_RCP_DATA, 1, 36, REGISTER_TYPE_WO, 0, 5, rpl_rcp_data_fields },
+ { RPL_RPL_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, rpl_rpl_ctrl_fields },
+ { RPL_RPL_DATA, 5, 128, REGISTER_TYPE_WO, 0, 1, rpl_rpl_data_fields },
+};
+
+static nt_fpga_field_init_t rpp_lr_ifr_rcp_ctrl_fields[] = {
+ { RPP_LR_IFR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { RPP_LR_IFR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpp_lr_ifr_rcp_data_fields[] = {
+ { RPP_LR_IFR_RCP_DATA_EN, 1, 0, 0x0000 },
+ { RPP_LR_IFR_RCP_DATA_MTU, 14, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpp_lr_rcp_ctrl_fields[] = {
+ { RPP_LR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { RPP_LR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpp_lr_rcp_data_fields[] = {
+ { RPP_LR_RCP_DATA_EXP, 14, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t rpp_lr_registers[] = {
+ { RPP_LR_IFR_RCP_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2,
+ rpp_lr_ifr_rcp_ctrl_fields
+ },
+ { RPP_LR_IFR_RCP_DATA, 3, 15, REGISTER_TYPE_WO, 0, 2,
+ rpp_lr_ifr_rcp_data_fields
+ },
+ { RPP_LR_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2,
+ rpp_lr_rcp_ctrl_fields
+ },
+ { RPP_LR_RCP_DATA, 1, 14, REGISTER_TYPE_WO, 0, 1,
+ rpp_lr_rcp_data_fields
+ },
+};
+
+static nt_fpga_field_init_t rst9563_ctrl_fields[] = {
+ { RST9563_CTRL_PTP_MMCM_CLKSEL, 1, 2, 1 },
+ { RST9563_CTRL_TS_CLKSEL, 1, 1, 1 },
+ { RST9563_CTRL_TS_CLKSEL_OVERRIDE, 1, 0, 1 },
+};
+
+static nt_fpga_field_init_t rst9563_power_fields[] = {
+ { RST9563_POWER_PU_NSEB, 1, 1, 0 },
+ { RST9563_POWER_PU_PHY, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t rst9563_rst_fields[] = {
+ { RST9563_RST_CORE_MMCM, 1, 15, 0 }, { RST9563_RST_DDR4, 3, 3, 7 },
+ { RST9563_RST_MAC_RX, 2, 9, 3 }, { RST9563_RST_PERIPH, 1, 13, 0 },
+ { RST9563_RST_PHY, 2, 7, 3 }, { RST9563_RST_PTP, 1, 11, 1 },
+ { RST9563_RST_PTP_MMCM, 1, 16, 0 }, { RST9563_RST_RPP, 1, 2, 1 },
+ { RST9563_RST_SDC, 1, 6, 1 }, { RST9563_RST_SYS, 1, 0, 1 },
+ { RST9563_RST_SYS_MMCM, 1, 14, 0 }, { RST9563_RST_TMC, 1, 1, 1 },
+ { RST9563_RST_TS, 1, 12, 1 }, { RST9563_RST_TS_MMCM, 1, 17, 0 },
+};
+
+static nt_fpga_field_init_t rst9563_stat_fields[] = {
+ { RST9563_STAT_CORE_MMCM_LOCKED, 1, 5, 0x0000 },
+ { RST9563_STAT_DDR4_MMCM_LOCKED, 1, 2, 0x0000 },
+ { RST9563_STAT_DDR4_PLL_LOCKED, 1, 3, 0x0000 },
+ { RST9563_STAT_PTP_MMCM_LOCKED, 1, 0, 0x0000 },
+ { RST9563_STAT_SYS_MMCM_LOCKED, 1, 4, 0x0000 },
+ { RST9563_STAT_TS_MMCM_LOCKED, 1, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t rst9563_sticky_fields[] = {
+ { RST9563_STICKY_CORE_MMCM_UNLOCKED, 1, 5, 0x0000 },
+ { RST9563_STICKY_DDR4_MMCM_UNLOCKED, 1, 2, 0x0000 },
+ { RST9563_STICKY_DDR4_PLL_UNLOCKED, 1, 3, 0x0000 },
+ { RST9563_STICKY_PTP_MMCM_UNLOCKED, 1, 0, 0x0000 },
+ { RST9563_STICKY_SYS_MMCM_UNLOCKED, 1, 4, 0x0000 },
+ { RST9563_STICKY_TS_MMCM_UNLOCKED, 1, 1, 0x0000 },
+};
+
+static nt_fpga_register_init_t rst9563_registers[] = {
+ { RST9563_CTRL, 1, 3, REGISTER_TYPE_RW, 7, 3, rst9563_ctrl_fields },
+ { RST9563_POWER, 4, 2, REGISTER_TYPE_RW, 0, 2, rst9563_power_fields },
+ { RST9563_RST, 0, 18, REGISTER_TYPE_RW, 8191, 14, rst9563_rst_fields },
+ { RST9563_STAT, 2, 6, REGISTER_TYPE_RO, 0, 6, rst9563_stat_fields },
+ { RST9563_STICKY, 3, 6, REGISTER_TYPE_RC1, 0, 6,
+ rst9563_sticky_fields
+ },
+};
+
+static nt_fpga_field_init_t slc_rcp_ctrl_fields[] = {
+ { SLC_RCP_CTRL_ADR, 6, 0, 0x0000 },
+ { SLC_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t slc_rcp_data_fields[] = {
+ { SLC_RCP_DATA_PCAP, 1, 35, 0x0000 },
+ { SLC_RCP_DATA_TAIL_DYN, 5, 15, 0x0000 },
+ { SLC_RCP_DATA_TAIL_OFS, 15, 20, 0x0000 },
+ { SLC_RCP_DATA_TAIL_SLC_EN, 1, 14, 0x0000 },
+};
+
+static nt_fpga_register_init_t slc_registers[] = {
+ { SLC_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, slc_rcp_ctrl_fields },
+ { SLC_RCP_DATA, 1, 36, REGISTER_TYPE_WO, 0, 4, slc_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t spim_cfg_fields[] = {
+ { SPIM_CFG_PRE, 3, 0, 5 },
+};
+
+static nt_fpga_field_init_t spim_cr_fields[] = {
+ { SPIM_CR_EN, 1, 1, 0 },
+ { SPIM_CR_LOOP, 1, 0, 0 },
+ { SPIM_CR_RXRST, 1, 3, 0 },
+ { SPIM_CR_TXRST, 1, 2, 0 },
+};
+
+static nt_fpga_field_init_t spim_drr_fields[] = {
+ { SPIM_DRR_DRR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spim_dtr_fields[] = {
+ { SPIM_DTR_DTR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spim_sr_fields[] = {
+ { SPIM_SR_DONE, 1, 0, 0 }, { SPIM_SR_RXEMPTY, 1, 2, 1 },
+ { SPIM_SR_RXFULL, 1, 4, 0 }, { SPIM_SR_RXLVL, 8, 16, 0 },
+ { SPIM_SR_TXEMPTY, 1, 1, 1 }, { SPIM_SR_TXFULL, 1, 3, 0 },
+ { SPIM_SR_TXLVL, 8, 8, 0 },
+};
+
+static nt_fpga_field_init_t spim_srr_fields[] = {
+ { SPIM_SRR_RST, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t spim_registers[] = {
+ { SPIM_CFG, 5, 3, REGISTER_TYPE_WO, 5, 1, spim_cfg_fields },
+ { SPIM_CR, 1, 4, REGISTER_TYPE_WO, 0, 4, spim_cr_fields },
+ { SPIM_DRR, 4, 32, REGISTER_TYPE_RO, 0, 1, spim_drr_fields },
+ { SPIM_DTR, 3, 32, REGISTER_TYPE_WO, 0, 1, spim_dtr_fields },
+ { SPIM_SR, 2, 24, REGISTER_TYPE_RO, 6, 7, spim_sr_fields },
+ { SPIM_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, spim_srr_fields },
+};
+
+static nt_fpga_field_init_t spis_cr_fields[] = {
+ { SPIS_CR_DEBUG, 1, 4, 0 }, { SPIS_CR_EN, 1, 1, 0 },
+ { SPIS_CR_LOOP, 1, 0, 0 }, { SPIS_CR_RXRST, 1, 3, 0 },
+ { SPIS_CR_TXRST, 1, 2, 0 },
+};
+
+static nt_fpga_field_init_t spis_drr_fields[] = {
+ { SPIS_DRR_DRR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spis_dtr_fields[] = {
+ { SPIS_DTR_DTR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spis_ram_ctrl_fields[] = {
+ { SPIS_RAM_CTRL_ADR, 6, 0, 0 },
+ { SPIS_RAM_CTRL_CNT, 6, 6, 0 },
+};
+
+static nt_fpga_field_init_t spis_ram_data_fields[] = {
+ { SPIS_RAM_DATA_DATA, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spis_sr_fields[] = {
+ { SPIS_SR_DONE, 1, 0, 0 }, { SPIS_SR_FRAME_ERR, 1, 24, 0 },
+ { SPIS_SR_READ_ERR, 1, 25, 0 }, { SPIS_SR_RXEMPTY, 1, 2, 1 },
+ { SPIS_SR_RXFULL, 1, 4, 0 }, { SPIS_SR_RXLVL, 8, 16, 0 },
+ { SPIS_SR_TXEMPTY, 1, 1, 1 }, { SPIS_SR_TXFULL, 1, 3, 0 },
+ { SPIS_SR_TXLVL, 8, 8, 0 }, { SPIS_SR_WRITE_ERR, 1, 26, 0 },
+};
+
+static nt_fpga_field_init_t spis_srr_fields[] = {
+ { SPIS_SRR_RST, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t spis_registers[] = {
+ { SPIS_CR, 1, 5, REGISTER_TYPE_WO, 0, 5, spis_cr_fields },
+ { SPIS_DRR, 4, 32, REGISTER_TYPE_RO, 0, 1, spis_drr_fields },
+ { SPIS_DTR, 3, 32, REGISTER_TYPE_WO, 0, 1, spis_dtr_fields },
+ { SPIS_RAM_CTRL, 5, 12, REGISTER_TYPE_RW, 0, 2, spis_ram_ctrl_fields },
+ { SPIS_RAM_DATA, 6, 32, REGISTER_TYPE_RW, 0, 1, spis_ram_data_fields },
+ { SPIS_SR, 2, 27, REGISTER_TYPE_RO, 6, 10, spis_sr_fields },
+ { SPIS_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, spis_srr_fields },
+};
+
+static nt_fpga_field_init_t sta_byte_fields[] = {
+ { STA_BYTE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_cfg_fields[] = {
+ { STA_CFG_CNT_CLEAR, 1, 1, 0 },
+ { STA_CFG_DMA_ENA, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t sta_cv_err_fields[] = {
+ { STA_CV_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_fcs_err_fields[] = {
+ { STA_FCS_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_host_adr_lsb_fields[] = {
+ { STA_HOST_ADR_LSB_LSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t sta_host_adr_msb_fields[] = {
+ { STA_HOST_ADR_MSB_MSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t sta_pckt_fields[] = {
+ { STA_PCKT_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_status_fields[] = {
+ { STA_STATUS_STAT_TOGGLE_MISSED, 1, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t sta_registers[] = {
+ { STA_BYTE, 4, 32, REGISTER_TYPE_RO, 0, 1, sta_byte_fields },
+ { STA_CFG, 0, 2, REGISTER_TYPE_RW, 0, 2, sta_cfg_fields },
+ { STA_CV_ERR, 5, 32, REGISTER_TYPE_RO, 0, 1, sta_cv_err_fields },
+ { STA_FCS_ERR, 6, 32, REGISTER_TYPE_RO, 0, 1, sta_fcs_err_fields },
+ { STA_HOST_ADR_LSB, 1, 32, REGISTER_TYPE_WO, 0, 1,
+ sta_host_adr_lsb_fields
+ },
+ { STA_HOST_ADR_MSB, 2, 32, REGISTER_TYPE_WO, 0, 1,
+ sta_host_adr_msb_fields
+ },
+ { STA_PCKT, 3, 32, REGISTER_TYPE_RO, 0, 1, sta_pckt_fields },
+ { STA_STATUS, 7, 1, REGISTER_TYPE_RC1, 0, 1, sta_status_fields },
+};
+
+static nt_fpga_field_init_t tempmon_alarms_fields[] = {
+ { TEMPMON_ALARMS_OT, 1, 1, 0x0000 },
+ { TEMPMON_ALARMS_OT_OVERWR, 1, 2, 0 },
+ { TEMPMON_ALARMS_OT_OVERWRVAL, 1, 3, 0 },
+ { TEMPMON_ALARMS_TEMP, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tempmon_stat_fields[] = {
+ { TEMPMON_STAT_TEMP, 12, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t tempmon_registers[] = {
+ { TEMPMON_ALARMS, 1, 4, REGISTER_TYPE_MIXED, 0, 4,
+ tempmon_alarms_fields
+ },
+ { TEMPMON_STAT, 0, 12, REGISTER_TYPE_RO, 0, 1, tempmon_stat_fields },
+};
+
+static nt_fpga_field_init_t tint_ctrl_fields[] = {
+ { TINT_CTRL_INTERVAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tint_status_fields[] = {
+ { TINT_STATUS_DELAYED, 8, 8, 0 },
+ { TINT_STATUS_SKIPPED, 8, 0, 0 },
+};
+
+static nt_fpga_register_init_t tint_registers[] = {
+ { TINT_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 1, tint_ctrl_fields },
+ { TINT_STATUS, 1, 16, REGISTER_TYPE_RC1, 0, 2, tint_status_fields },
+};
+
+static nt_fpga_field_init_t tmc_port_rpl_fields[] = {
+ { TMC_PORT_RPL_P0, 1, 0, 0 },
+ { TMC_PORT_RPL_P1, 1, 1, 1 },
+};
+
+static nt_fpga_register_init_t tmc_registers[] = {
+ { TMC_PORT_RPL, 0, 2, REGISTER_TYPE_WO, 2, 2, tmc_port_rpl_fields },
+};
+
+static nt_fpga_field_init_t tsm_con0_config_fields[] = {
+ { TSM_CON0_CONFIG_BLIND, 5, 8, 9 },
+ { TSM_CON0_CONFIG_DC_SRC, 3, 5, 0 },
+ { TSM_CON0_CONFIG_PORT, 3, 0, 0 },
+ { TSM_CON0_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+ { TSM_CON0_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nt_fpga_field_init_t tsm_con0_interface_fields[] = {
+ { TSM_CON0_INTERFACE_EX_TERM, 2, 0, 3 },
+ { TSM_CON0_INTERFACE_IN_REF_PWM, 8, 12, 128 },
+ { TSM_CON0_INTERFACE_PWM_ENA, 1, 2, 0 },
+ { TSM_CON0_INTERFACE_RESERVED, 1, 3, 0 },
+ { TSM_CON0_INTERFACE_VTERM_PWM, 8, 4, 0 },
+};
+
+static nt_fpga_field_init_t tsm_con0_sample_hi_fields[] = {
+ { TSM_CON0_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con0_sample_lo_fields[] = {
+ { TSM_CON0_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con1_config_fields[] = {
+ { TSM_CON1_CONFIG_BLIND, 5, 8, 9 },
+ { TSM_CON1_CONFIG_DC_SRC, 3, 5, 0 },
+ { TSM_CON1_CONFIG_PORT, 3, 0, 0 },
+ { TSM_CON1_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+ { TSM_CON1_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nt_fpga_field_init_t tsm_con1_sample_hi_fields[] = {
+ { TSM_CON1_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con1_sample_lo_fields[] = {
+ { TSM_CON1_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con2_config_fields[] = {
+ { TSM_CON2_CONFIG_BLIND, 5, 8, 9 },
+ { TSM_CON2_CONFIG_DC_SRC, 3, 5, 0 },
+ { TSM_CON2_CONFIG_PORT, 3, 0, 0 },
+ { TSM_CON2_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+ { TSM_CON2_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nt_fpga_field_init_t tsm_con2_sample_hi_fields[] = {
+ { TSM_CON2_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con2_sample_lo_fields[] = {
+ { TSM_CON2_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con3_config_fields[] = {
+ { TSM_CON3_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON3_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON3_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con3_sample_hi_fields[] = {
+ { TSM_CON3_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con3_sample_lo_fields[] = {
+ { TSM_CON3_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con4_config_fields[] = {
+ { TSM_CON4_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON4_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON4_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con4_sample_hi_fields[] = {
+ { TSM_CON4_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con4_sample_lo_fields[] = {
+ { TSM_CON4_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con5_config_fields[] = {
+ { TSM_CON5_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON5_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON5_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con5_sample_hi_fields[] = {
+ { TSM_CON5_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con5_sample_lo_fields[] = {
+ { TSM_CON5_SAMPLE_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con6_config_fields[] = {
+ { TSM_CON6_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON6_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON6_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con6_sample_hi_fields[] = {
+ { TSM_CON6_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con6_sample_lo_fields[] = {
+ { TSM_CON6_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con7_host_sample_hi_fields[] = {
+ { TSM_CON7_HOST_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con7_host_sample_lo_fields[] = {
+ { TSM_CON7_HOST_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_config_fields[] = {
+ { TSM_CONFIG_NTTS_SRC, 2, 5, 0 },
+ { TSM_CONFIG_NTTS_SYNC, 1, 4, 0 },
+ { TSM_CONFIG_TIMESET_EDGE, 2, 8, 1 },
+ { TSM_CONFIG_TIMESET_SRC, 3, 10, 0 },
+ { TSM_CONFIG_TIMESET_UP, 1, 7, 0 },
+ { TSM_CONFIG_TS_FORMAT, 4, 0, 1 },
+};
+
+static nt_fpga_field_init_t tsm_int_config_fields[] = {
+ { TSM_INT_CONFIG_AUTO_DISABLE, 1, 0, 0 },
+ { TSM_INT_CONFIG_MASK, 19, 1, 0 },
+};
+
+static nt_fpga_field_init_t tsm_int_stat_fields[] = {
+ { TSM_INT_STAT_CAUSE, 19, 1, 0 },
+ { TSM_INT_STAT_ENABLE, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_led_fields[] = {
+ { TSM_LED_LED0_BG_COLOR, 2, 3, 0 }, { TSM_LED_LED0_COLOR, 2, 1, 0 },
+ { TSM_LED_LED0_MODE, 1, 0, 0 }, { TSM_LED_LED0_SRC, 4, 5, 0 },
+ { TSM_LED_LED1_BG_COLOR, 2, 12, 0 }, { TSM_LED_LED1_COLOR, 2, 10, 0 },
+ { TSM_LED_LED1_MODE, 1, 9, 0 }, { TSM_LED_LED1_SRC, 4, 14, 1 },
+ { TSM_LED_LED2_BG_COLOR, 2, 21, 0 }, { TSM_LED_LED2_COLOR, 2, 19, 0 },
+ { TSM_LED_LED2_MODE, 1, 18, 0 }, { TSM_LED_LED2_SRC, 4, 23, 2 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_config_fields[] = {
+ { TSM_NTTS_CONFIG_AUTO_HARDSET, 1, 5, 1 },
+ { TSM_NTTS_CONFIG_EXT_CLK_ADJ, 1, 6, 0 },
+ { TSM_NTTS_CONFIG_HIGH_SAMPLE, 1, 4, 0 },
+ { TSM_NTTS_CONFIG_TS_SRC_FORMAT, 4, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ext_stat_fields[] = {
+ { TSM_NTTS_EXT_STAT_MASTER_ID, 8, 16, 0x0000 },
+ { TSM_NTTS_EXT_STAT_MASTER_REV, 8, 24, 0x0000 },
+ { TSM_NTTS_EXT_STAT_MASTER_STAT, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_limit_hi_fields[] = {
+ { TSM_NTTS_LIMIT_HI_SEC, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_limit_lo_fields[] = {
+ { TSM_NTTS_LIMIT_LO_NS, 32, 0, 100000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_offset_fields[] = {
+ { TSM_NTTS_OFFSET_NS, 30, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_sample_hi_fields[] = {
+ { TSM_NTTS_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_sample_lo_fields[] = {
+ { TSM_NTTS_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_stat_fields[] = {
+ { TSM_NTTS_STAT_NTTS_VALID, 1, 0, 0 },
+ { TSM_NTTS_STAT_SIGNAL_LOST, 8, 1, 0 },
+ { TSM_NTTS_STAT_SYNC_LOST, 8, 9, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ts_t0_hi_fields[] = {
+ { TSM_NTTS_TS_T0_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ts_t0_lo_fields[] = {
+ { TSM_NTTS_TS_T0_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ts_t0_offset_fields[] = {
+ { TSM_NTTS_TS_T0_OFFSET_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_pb_ctrl_fields[] = {
+ { TSM_PB_CTRL_INSTMEM_WR, 1, 1, 0 },
+ { TSM_PB_CTRL_RST, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_pb_instmem_fields[] = {
+ { TSM_PB_INSTMEM_MEM_ADDR, 14, 0, 0 },
+ { TSM_PB_INSTMEM_MEM_DATA, 18, 14, 0 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_i_fields[] = {
+ { TSM_PI_CTRL_I_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_ki_fields[] = {
+ { TSM_PI_CTRL_KI_GAIN, 24, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_kp_fields[] = {
+ { TSM_PI_CTRL_KP_GAIN, 24, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_shl_fields[] = {
+ { TSM_PI_CTRL_SHL_VAL, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_stat_fields[] = {
+ { TSM_STAT_HARD_SYNC, 8, 8, 0 }, { TSM_STAT_LINK_CON0, 1, 0, 0 },
+ { TSM_STAT_LINK_CON1, 1, 1, 0 }, { TSM_STAT_LINK_CON2, 1, 2, 0 },
+ { TSM_STAT_LINK_CON3, 1, 3, 0 }, { TSM_STAT_LINK_CON4, 1, 4, 0 },
+ { TSM_STAT_LINK_CON5, 1, 5, 0 }, { TSM_STAT_NTTS_INSYNC, 1, 6, 0 },
+ { TSM_STAT_PTP_MI_PRESENT, 1, 7, 0 },
+};
+
+static nt_fpga_field_init_t tsm_timer_ctrl_fields[] = {
+ { TSM_TIMER_CTRL_TIMER_EN_T0, 1, 0, 0 },
+ { TSM_TIMER_CTRL_TIMER_EN_T1, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t tsm_timer_t0_fields[] = {
+ { TSM_TIMER_T0_MAX_COUNT, 30, 0, 50000 },
+};
+
+static nt_fpga_field_init_t tsm_timer_t1_fields[] = {
+ { TSM_TIMER_T1_MAX_COUNT, 30, 0, 50000 },
+};
+
+static nt_fpga_field_init_t tsm_time_hardset_hi_fields[] = {
+ { TSM_TIME_HARDSET_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_hardset_lo_fields[] = {
+ { TSM_TIME_HARDSET_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_hi_fields[] = {
+ { TSM_TIME_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_lo_fields[] = {
+ { TSM_TIME_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_rate_adj_fields[] = {
+ { TSM_TIME_RATE_ADJ_FRACTION, 29, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_hi_fields[] = {
+ { TSM_TS_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ts_lo_fields[] = {
+ { TSM_TS_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ts_offset_fields[] = {
+ { TSM_TS_OFFSET_NS, 30, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_fields[] = {
+ { TSM_TS_STAT_OVERRUN, 1, 16, 0 },
+ { TSM_TS_STAT_SAMPLES, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_hi_offset_fields[] = {
+ { TSM_TS_STAT_HI_OFFSET_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_lo_offset_fields[] = {
+ { TSM_TS_STAT_LO_OFFSET_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_tar_hi_fields[] = {
+ { TSM_TS_STAT_TAR_HI_SEC, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_tar_lo_fields[] = {
+ { TSM_TS_STAT_TAR_LO_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_x_fields[] = {
+ { TSM_TS_STAT_X_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_x2_hi_fields[] = {
+ { TSM_TS_STAT_X2_HI_NS, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_x2_lo_fields[] = {
+ { TSM_TS_STAT_X2_LO_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_utc_offset_fields[] = {
+ { TSM_UTC_OFFSET_SEC, 8, 0, 0 },
+};
+
+static nt_fpga_register_init_t tsm_registers[] = {
+ { TSM_CON0_CONFIG, 24, 14, REGISTER_TYPE_RW, 2320, 5,
+ tsm_con0_config_fields
+ },
+ { TSM_CON0_INTERFACE, 25, 20, REGISTER_TYPE_RW, 524291, 5,
+ tsm_con0_interface_fields
+ },
+ { TSM_CON0_SAMPLE_HI, 27, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con0_sample_hi_fields
+ },
+ { TSM_CON0_SAMPLE_LO, 26, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con0_sample_lo_fields
+ },
+ { TSM_CON1_CONFIG, 28, 14, REGISTER_TYPE_RW, 2320, 5,
+ tsm_con1_config_fields
+ },
+ { TSM_CON1_SAMPLE_HI, 30, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con1_sample_hi_fields
+ },
+ { TSM_CON1_SAMPLE_LO, 29, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con1_sample_lo_fields
+ },
+ { TSM_CON2_CONFIG, 31, 14, REGISTER_TYPE_RW, 2320, 5,
+ tsm_con2_config_fields
+ },
+ { TSM_CON2_SAMPLE_HI, 33, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con2_sample_hi_fields
+ },
+ { TSM_CON2_SAMPLE_LO, 32, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con2_sample_lo_fields
+ },
+ { TSM_CON3_CONFIG, 34, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con3_config_fields
+ },
+ { TSM_CON3_SAMPLE_HI, 36, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con3_sample_hi_fields
+ },
+ { TSM_CON3_SAMPLE_LO, 35, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con3_sample_lo_fields
+ },
+ { TSM_CON4_CONFIG, 37, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con4_config_fields
+ },
+ { TSM_CON4_SAMPLE_HI, 39, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con4_sample_hi_fields
+ },
+ { TSM_CON4_SAMPLE_LO, 38, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con4_sample_lo_fields
+ },
+ { TSM_CON5_CONFIG, 40, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con5_config_fields
+ },
+ { TSM_CON5_SAMPLE_HI, 42, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con5_sample_hi_fields
+ },
+ { TSM_CON5_SAMPLE_LO, 41, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con5_sample_lo_fields
+ },
+ { TSM_CON6_CONFIG, 43, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con6_config_fields
+ },
+ { TSM_CON6_SAMPLE_HI, 45, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con6_sample_hi_fields
+ },
+ { TSM_CON6_SAMPLE_LO, 44, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con6_sample_lo_fields
+ },
+ { TSM_CON7_HOST_SAMPLE_HI, 47, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con7_host_sample_hi_fields
+ },
+ { TSM_CON7_HOST_SAMPLE_LO, 46, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con7_host_sample_lo_fields
+ },
+ { TSM_CONFIG, 0, 13, REGISTER_TYPE_RW, 257, 6, tsm_config_fields },
+ { TSM_INT_CONFIG, 2, 20, REGISTER_TYPE_RW, 0, 2,
+ tsm_int_config_fields
+ },
+ { TSM_INT_STAT, 3, 20, REGISTER_TYPE_MIXED, 0, 2, tsm_int_stat_fields },
+ { TSM_LED, 4, 27, REGISTER_TYPE_RW, 16793600, 12, tsm_led_fields },
+ { TSM_NTTS_CONFIG, 13, 7, REGISTER_TYPE_RW, 32, 4,
+ tsm_ntts_config_fields
+ },
+ { TSM_NTTS_EXT_STAT, 15, 32, REGISTER_TYPE_MIXED, 0, 3,
+ tsm_ntts_ext_stat_fields
+ },
+ { TSM_NTTS_LIMIT_HI, 23, 16, REGISTER_TYPE_RW, 0, 1,
+ tsm_ntts_limit_hi_fields
+ },
+ { TSM_NTTS_LIMIT_LO, 22, 32, REGISTER_TYPE_RW, 100000, 1,
+ tsm_ntts_limit_lo_fields
+ },
+ { TSM_NTTS_OFFSET, 21, 30, REGISTER_TYPE_RW, 0, 1,
+ tsm_ntts_offset_fields
+ },
+ { TSM_NTTS_SAMPLE_HI, 19, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_sample_hi_fields
+ },
+ { TSM_NTTS_SAMPLE_LO, 18, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_sample_lo_fields
+ },
+ { TSM_NTTS_STAT, 14, 17, REGISTER_TYPE_RO, 0, 3, tsm_ntts_stat_fields },
+ { TSM_NTTS_TS_T0_HI, 17, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_ts_t0_hi_fields
+ },
+ { TSM_NTTS_TS_T0_LO, 16, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_ts_t0_lo_fields
+ },
+ { TSM_NTTS_TS_T0_OFFSET, 20, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_ts_t0_offset_fields
+ },
+ { TSM_PB_CTRL, 63, 2, REGISTER_TYPE_WO, 0, 2, tsm_pb_ctrl_fields },
+ { TSM_PB_INSTMEM, 64, 32, REGISTER_TYPE_WO, 0, 2,
+ tsm_pb_instmem_fields
+ },
+ { TSM_PI_CTRL_I, 54, 32, REGISTER_TYPE_WO, 0, 1, tsm_pi_ctrl_i_fields },
+ { TSM_PI_CTRL_KI, 52, 24, REGISTER_TYPE_RW, 0, 1,
+ tsm_pi_ctrl_ki_fields
+ },
+ { TSM_PI_CTRL_KP, 51, 24, REGISTER_TYPE_RW, 0, 1,
+ tsm_pi_ctrl_kp_fields
+ },
+ { TSM_PI_CTRL_SHL, 53, 4, REGISTER_TYPE_WO, 0, 1,
+ tsm_pi_ctrl_shl_fields
+ },
+ { TSM_STAT, 1, 16, REGISTER_TYPE_RO, 0, 9, tsm_stat_fields },
+ { TSM_TIMER_CTRL, 48, 2, REGISTER_TYPE_RW, 0, 2,
+ tsm_timer_ctrl_fields
+ },
+ { TSM_TIMER_T0, 49, 30, REGISTER_TYPE_RW, 50000, 1,
+ tsm_timer_t0_fields
+ },
+ { TSM_TIMER_T1, 50, 30, REGISTER_TYPE_RW, 50000, 1,
+ tsm_timer_t1_fields
+ },
+ { TSM_TIME_HARDSET_HI, 12, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_time_hardset_hi_fields
+ },
+ { TSM_TIME_HARDSET_LO, 11, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_time_hardset_lo_fields
+ },
+ { TSM_TIME_HI, 9, 32, REGISTER_TYPE_RW, 0, 1, tsm_time_hi_fields },
+ { TSM_TIME_LO, 8, 32, REGISTER_TYPE_RW, 0, 1, tsm_time_lo_fields },
+ { TSM_TIME_RATE_ADJ, 10, 29, REGISTER_TYPE_RW, 0, 1,
+ tsm_time_rate_adj_fields
+ },
+ { TSM_TS_HI, 6, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_hi_fields },
+ { TSM_TS_LO, 5, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_lo_fields },
+ { TSM_TS_OFFSET, 7, 30, REGISTER_TYPE_RW, 0, 1, tsm_ts_offset_fields },
+ { TSM_TS_STAT, 55, 17, REGISTER_TYPE_RO, 0, 2, tsm_ts_stat_fields },
+ { TSM_TS_STAT_HI_OFFSET, 62, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_hi_offset_fields
+ },
+ { TSM_TS_STAT_LO_OFFSET, 61, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_lo_offset_fields
+ },
+ { TSM_TS_STAT_TAR_HI, 57, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_tar_hi_fields
+ },
+ { TSM_TS_STAT_TAR_LO, 56, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_tar_lo_fields
+ },
+ { TSM_TS_STAT_X, 58, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_stat_x_fields },
+ { TSM_TS_STAT_X2_HI, 60, 16, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_x2_hi_fields
+ },
+ { TSM_TS_STAT_X2_LO, 59, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_x2_lo_fields
+ },
+ { TSM_UTC_OFFSET, 65, 8, REGISTER_TYPE_RW, 0, 1,
+ tsm_utc_offset_fields
+ },
+};
+
+static nt_fpga_module_init_t fpga_modules[] = {
+ { MOD_CAT, 0, MOD_CAT, 0, 21, BUS_TYPE_RAB1, 768, 34,
+ cat_registers
+ }, /* CAT:0 CAT v0.21: CAT @ RAB1,768 (CAT CAT CAT) */
+ { MOD_CSU, 0, MOD_CSU, 0, 0, BUS_TYPE_RAB1, 9728, 2,
+ csu_registers
+ }, /* CSU:0 CSU v0.0: CSU @ RAB1,9728 (CSU CSU CSU) */
+ { MOD_DBS, 0, MOD_DBS, 0, 11, BUS_TYPE_RAB2, 12832, 27,
+ dbs_registers
+ }, /* DBS:0 DBS v0.11: DBS @ RAB2,12832 (DBS DBS DBS) */
+ { MOD_FLM, 0, MOD_FLM, 0, 20, BUS_TYPE_RAB1, 1280, 43,
+ flm_registers
+ }, /* FLM:0 FLM v0.20: FLM @ RAB1,1280 (FLM FLM FLM) */
+ { MOD_GFG, 0, MOD_GFG, 1, 1, BUS_TYPE_RAB2, 8704, 10,
+ gfg_registers
+ }, /* GFG:0 GFG v1.1: GFG @ RAB2,8704 (GFG GFG GFG) */
+ { MOD_GMF, 0, MOD_GMF, 2, 5, BUS_TYPE_RAB2, 9216, 12,
+ gmf_registers
+ }, /* GMF:0 GMF v2.5: GMF_0 @ RAB2,9216 (GMF GMF_0 GMF) */
+ { MOD_GMF, 1, MOD_GMF, 2, 5, BUS_TYPE_RAB2, 9728, 12,
+ gmf_registers
+ }, /* GMF:1 GMF v2.5: GMF_1 @ RAB2,9728 (GMF GMF_1 GMF) */
+ { MOD_GPIO_PHY, 0, MOD_GPIO_PHY, 1, 0, BUS_TYPE_RAB0, 16386, 2,
+ gpio_phy_registers
+ }, /* GPIO_PHY:0 GPIO_PHY v1.0: GPIO_PHY @ RAB0,16386 (GPIO_PHY GPIO_PHY GPIO_PHY) */
+ { MOD_HFU, 0, MOD_HFU, 0, 1, BUS_TYPE_RAB1, 9472, 2,
+ hfu_registers
+ }, /* HFU:0 HFU v0.1: HFU @ RAB1,9472 (HFU HFU HFU) */
+ { MOD_HIF, 0, MOD_HIF, 0, 0, BUS_TYPE_PCI, 0, 18,
+ hif_registers
+ }, /* HIF:0 HIF v0.0: HIF @ PCI,0 (HIF HIF HIF) */
+ { MOD_HSH, 0, MOD_HSH, 0, 5, BUS_TYPE_RAB1, 1536, 2,
+ hsh_registers
+ }, /* HSH:0 HSH v0.5: HSH @ RAB1,1536 (HSH HSH HSH) */
+ { MOD_HST, 0, MOD_HST, 0, 2, BUS_TYPE_RAB1, 2048, 2,
+ hst_registers
+ }, /* HST:0 HST v0.2: HST @ RAB1,2048 (HST HST HST) */
+ { MOD_IFR, 0, MOD_IFR, 0, 1, BUS_TYPE_RAB1, 9984, 2,
+ ifr_registers
+ }, /* IFR:0 IFR v0.1: IFR @ RAB1,9984 (IFR IFR IFR) */
+ { MOD_IIC, 0, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 768, 22,
+ iic_registers
+ }, /* IIC:0 IIC v0.1: IIC0 @ RAB0,768 (IIC IIC0 IIC) */
+ { MOD_IIC, 1, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 896, 22,
+ iic_registers
+ }, /* IIC:1 IIC v0.1: IIC1 @ RAB0,896 (IIC IIC1 IIC) */
+ { MOD_IIC, 2, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 24832, 22,
+ iic_registers
+ }, /* IIC:2 IIC v0.1: IIC2 @ RAB0,24832 (IIC IIC2 IIC) */
+ { MOD_IIC, 3, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 24960, 22,
+ iic_registers
+ }, /* IIC:3 IIC v0.1: IIC3 @ RAB0,24960 (IIC IIC3 IIC) */
+ { MOD_KM, 0, MOD_KM, 0, 7, BUS_TYPE_RAB1, 1024, 11,
+ km_registers
+ }, /* KM:0 KM v0.7: KM @ RAB1,1024 (KM KM KM) */
+ { MOD_MAC_PCS, 0, MOD_MAC_PCS, 0, 2, BUS_TYPE_RAB2, 10240, 44,
+ mac_pcs_registers
+ }, /* MAC_PCS:0 MAC_PCS v0.2: MAC_PCS_0 @ RAB2,10240 (MAC_PCS MAC_PCS_0 MAC_PCS) */
+ { MOD_MAC_PCS, 1, MOD_MAC_PCS, 0, 2, BUS_TYPE_RAB2, 11776, 44,
+ mac_pcs_registers
+ }, /* MAC_PCS:1 MAC_PCS v0.2: MAC_PCS_1 @ RAB2,11776 (MAC_PCS MAC_PCS_1 MAC_PCS) */
+ { MOD_MAC_RX, 0, MOD_MAC_RX, 0, 0, BUS_TYPE_RAB2, 10752, 9,
+ mac_rx_registers
+ }, /* MAC_RX:0 MAC_RX v0.0: MAC_RX_0 @ RAB2,10752 (MAC_RX MAC_RX_0 MAC_RX) */
+ { MOD_MAC_RX, 1, MOD_MAC_RX, 0, 0, BUS_TYPE_RAB2, 12288, 9,
+ mac_rx_registers
+ }, /* MAC_RX:1 MAC_RX v0.0: MAC_RX_1 @ RAB2,12288 (MAC_RX MAC_RX_1 MAC_RX) */
+ { MOD_MAC_TX, 0, MOD_MAC_TX, 0, 0, BUS_TYPE_RAB2, 11264, 5,
+ mac_tx_registers
+ }, /* MAC_TX:0 MAC_TX v0.0: MAC_TX_0 @ RAB2,11264 (MAC_TX MAC_TX_0 MAC_TX) */
+ { MOD_MAC_TX, 1, MOD_MAC_TX, 0, 0, BUS_TYPE_RAB2, 12800, 5,
+ mac_tx_registers
+ }, /* MAC_TX:1 MAC_TX v0.0: MAC_TX_1 @ RAB2,12800 (MAC_TX MAC_TX_1 MAC_TX) */
+ { MOD_PCI_RD_TG, 0, MOD_PCI_RD_TG, 0, 1, BUS_TYPE_RAB0, 2320, 6,
+ pci_rd_tg_registers
+ }, /* PCI_RD_TG:0 PCI_RD_TG v0.1: PCI_RD_TG @ RAB0,2320 (PCI_RD_TG PCI_RD_TG PCI_RD_TG) */
+ { MOD_PCI_TA, 0, MOD_PCI_TA, 0, 0, BUS_TYPE_RAB0, 2336, 5,
+ pci_ta_registers
+ }, /* PCI_TA:0 PCI_TA v0.0: PCI_TA @ RAB0,2336 (PCI_TA PCI_TA PCI_TA) */
+ { MOD_PCI_WR_TG, 0, MOD_PCI_WR_TG, 0, 1, BUS_TYPE_RAB0, 2304, 7,
+ pci_wr_tg_registers
+ }, /* PCI_WR_TG:0 PCI_WR_TG v0.1: PCI_WR_TG @ RAB0,2304 (PCI_WR_TG PCI_WR_TG PCI_WR_TG) */
+ { MOD_PDB, 0, MOD_PDB, 0, 9, BUS_TYPE_RAB1, 2816, 3,
+ pdb_registers
+ }, /* PDB:0 PDB v0.9: PDB @ RAB1,2816 (PDB PDB PDB) */
+ { MOD_PDI, 0, MOD_PDI, 1, 1, BUS_TYPE_RAB0, 64, 6,
+ pdi_registers
+ }, /* PDI:0 PDI v1.1: PDI @ RAB0,64 (PDI PDI PDI) */
+ { MOD_PTP1588, 0, MOD_PTP1588, 2, 1, BUS_TYPE_RAB2, 512, 23,
+ ptp1588_registers
+ }, /* PTP1588:0 PTP1588 v2.1: PTP1588 @ RAB2,512 (PTP1588 PTP1588 PTP1588) */
+ { MOD_QSL, 0, MOD_QSL, 0, 7, BUS_TYPE_RAB1, 1792, 8,
+ qsl_registers
+ }, /* QSL:0 QSL v0.7: QSL @ RAB1,1792 (QSL QSL QSL) */
+ { MOD_QSPI, 0, MOD_QSPI, 0, 0, BUS_TYPE_RAB0, 512, 11,
+ qspi_registers
+ }, /* QSPI:0 QSPI v0.0: QSPI @ RAB0,512 (QSPI QSPI QSPI) */
+ { MOD_RAC, 0, MOD_RAC, 3, 0, BUS_TYPE_PCI, 8192, 14,
+ rac_registers
+ }, /* RAC:0 RAC v3.0: RAC @ PCI,8192 (RAC RAC RAC) */
+ { MOD_RFD, 0, MOD_RFD, 0, 4, BUS_TYPE_RAB1, 256, 5,
+ rfd_registers
+ }, /* RFD:0 RFD v0.4: RFD @ RAB1,256 (RFD RFD RFD) */
+ { MOD_RMC, 0, MOD_RMC, 1, 3, BUS_TYPE_RAB0, 12288, 4,
+ rmc_registers
+ }, /* RMC:0 RMC v1.3: RMC @ RAB0,12288 (RMC RMC RMC) */
+ { MOD_RPP_LR, 0, MOD_RPP_LR, 0, 1, BUS_TYPE_RAB1, 2560, 4,
+ rpp_lr_registers
+ }, /* RPP_LR:0 RPP_LR v0.1: RPP_LR @ RAB1,2560 (RPP_LR RPP_LR RPP_LR) */
+ { MOD_RST9563, 0, MOD_RST9563, 0, 5, BUS_TYPE_RAB0, 1024, 5,
+ rst9563_registers
+ }, /* RST9563:0 RST9563 v0.5: RST9563 @ RAB0,1024 (RST9563 RST9563 RST9563) */
+ { MOD_SLC_LR, 0, MOD_SLC, 0, 2, BUS_TYPE_RAB1, 2304, 2,
+ slc_registers
+ }, /* SLC_LR:0 SLC v0.2: SLC_LR @ RAB1,2304 (SLC SLC_LR SLC_LR) */
+ { MOD_SPIM, 0, MOD_SPIM, 1, 0, BUS_TYPE_RAB0, 80, 6,
+ spim_registers
+ }, /* SPIM:0 SPIM v1.0: SPIM @ RAB0,80 (SPIM SPIM SPIM) */
+ { MOD_SPIS, 0, MOD_SPIS, 1, 0, BUS_TYPE_RAB0, 256, 7,
+ spis_registers
+ }, /* SPIS:0 SPIS v1.0: SPIS @ RAB0,256 (SPIS SPIS SPIS) */
+ { MOD_STA, 0, MOD_STA, 0, 8, BUS_TYPE_RAB0, 2048, 8,
+ sta_registers
+ }, /* STA:0 STA v0.8: STA @ RAB0,2048 (STA STA STA) */
+ { MOD_TEMPMON, 0, MOD_TEMPMON, 0, 0, BUS_TYPE_RAB0, 16384, 2,
+ tempmon_registers
+ }, /* TEMPMON:0 TEMPMON v0.0: TEMPMON @ RAB0,16384 (TEMPMON TEMPMON TEMPMON) */
+ { MOD_TINT, 0, MOD_TINT, 0, 0, BUS_TYPE_RAB0, 1280, 2,
+ tint_registers
+ }, /* TINT:0 TINT v0.0: TINT @ RAB0,1280 (TINT TINT TINT) */
+ { MOD_TMC, 0, MOD_TMC, 0, 1, BUS_TYPE_RAB2, 8192, 1,
+ tmc_registers
+ }, /* TMC:0 TMC v0.1: TMC @ RAB2,8192 (TMC TMC TMC) */
+ { MOD_TSM, 0, MOD_TSM, 0, 8, BUS_TYPE_RAB2, 1024, 66,
+ tsm_registers
+ }, /* TSM:0 TSM v0.8: TSM @ RAB2,1024 (TSM TSM TSM) */
+ { MOD_TX_CPY, 0, MOD_CPY, 0, 1, BUS_TYPE_RAB1, 9216, 20,
+ cpy_registers
+ }, /* TX_CPY:0 CPY v0.1: TX_CPY @ RAB1,9216 (CPY TX_CPY TX_CPY) */
+ { MOD_TX_INS, 0, MOD_INS, 0, 1, BUS_TYPE_RAB1, 8704, 2,
+ ins_registers
+ }, /* TX_INS:0 INS v0.1: TX_INS @ RAB1,8704 (INS TX_INS TX_INS) */
+ { MOD_TX_RPL, 0, MOD_RPL, 0, 2, BUS_TYPE_RAB1, 8960, 6,
+ rpl_registers
+ }, /* TX_RPL:0 RPL v0.2: TX_RPL @ RAB1,8960 (RPL TX_RPL TX_RPL) */
+};
+
+static nt_fpga_prod_param_t product_parameters[] = {
+ { NT_BUILD_NUMBER, 0 },
+ { NT_BUILD_TIME, 1689706895 },
+ { NT_CATEGORIES, 64 },
+ { NT_CAT_DCT_PRESENT, 0 },
+ { NT_CAT_END_OFS_SUPPORT, 0 },
+ { NT_CAT_FUNCS, 64 },
+ { NT_CAT_KCC_BANKS, 3 },
+ { NT_CAT_KCC_PRESENT, 0 },
+ { NT_CAT_KCC_SIZE, 1536 },
+ { NT_CAT_KM_IF_CNT, 2 },
+ { NT_CAT_KM_IF_M0, 0 },
+ { NT_CAT_KM_IF_M1, 1 },
+ { NT_CAT_N_CMP, 8 },
+ { NT_CAT_N_EXT, 4 },
+ { NT_CAT_N_LEN, 8 },
+ { NT_CB_DEBUG, 0 },
+ { NT_COR_CATEGORIES, 16 },
+ { NT_COR_PRESENT, 0 },
+ { NT_CSU_PRESENT, 1 },
+ { NT_DBS_PRESENT, 1 },
+ { NT_DBS_RX_QUEUES, 128 },
+ { NT_DBS_TX_PORTS, 2 },
+ { NT_DBS_TX_QUEUES, 128 },
+ { NT_DDP_PRESENT, 0 },
+ { NT_DDP_TBL_DEPTH, 4096 },
+ { NT_EMI_SPLIT_STEPS, 16 },
+ { NT_EOF_TIMESTAMP_ONLY, 1 },
+ { NT_EPP_CATEGORIES, 32 },
+ { NT_FLM_CACHE, 1 },
+ { NT_FLM_CATEGORIES, 32 },
+ { NT_FLM_ENTRY_SIZE, 64 },
+ { NT_FLM_PRESENT, 1 },
+ { NT_FLM_PRIOS, 4 },
+ { NT_FLM_PST_PROFILES, 16 },
+ { NT_FLM_SIZE_MB, 12288 },
+ { NT_FLM_STATEFUL, 1 },
+ { NT_FLM_VARIANT, 2 },
+ { NT_GFG_PRESENT, 1 },
+ { NT_GFG_TX_LIVE_RECONFIG_SUPPORT, 1 },
+ { NT_GMF_FCS_PRESENT, 0 },
+ { NT_GMF_IFG_SPEED_DIV, 33 },
+ { NT_GMF_IFG_SPEED_DIV100G, 33 },
+ { NT_GMF_IFG_SPEED_MUL, 20 },
+ { NT_GMF_IFG_SPEED_MUL100G, 20 },
+ { NT_GROUP_ID, 9563 },
+ { NT_HFU_PRESENT, 1 },
+ { NT_HIF_MSIX_BAR, 1 },
+ { NT_HIF_MSIX_PBA_OFS, 8192 },
+ { NT_HIF_MSIX_PRESENT, 1 },
+ { NT_HIF_MSIX_TBL_OFS, 0 },
+ { NT_HIF_MSIX_TBL_SIZE, 8 },
+ { NT_HIF_PER_PS, 4000 },
+ { NT_HIF_SRIOV_PRESENT, 1 },
+ { NT_HSH_CATEGORIES, 16 },
+ { NT_HSH_TOEPLITZ, 1 },
+ { NT_HST_CATEGORIES, 32 },
+ { NT_HST_PRESENT, 1 },
+ { NT_IOA_CATEGORIES, 1024 },
+ { NT_IOA_PRESENT, 0 },
+ { NT_IPF_PRESENT, 0 },
+ { NT_KM_CAM_BANKS, 3 },
+ { NT_KM_CAM_RECORDS, 2048 },
+ { NT_KM_CAM_REC_WORDS, 6 },
+ { NT_KM_CATEGORIES, 32 },
+ { NT_KM_END_OFS_SUPPORT, 0 },
+ { NT_KM_EXT_EXTRACTORS, 0 },
+ { NT_KM_FLOW_TYPES, 16 },
+ { NT_KM_PRESENT, 1 },
+ { NT_KM_SWX_PRESENT, 0 },
+ { NT_KM_SYNERGY_MATCH, 0 },
+ { NT_KM_TCAM_BANKS, 12 },
+ { NT_KM_TCAM_BANK_WIDTH, 72 },
+ { NT_KM_TCAM_HIT_QUAL, 0 },
+ { NT_KM_TCAM_KEYWAY, 1 },
+ { NT_KM_WIDE, 1 },
+ { NT_LR_PRESENT, 1 },
+ { NT_MCU_PRESENT, 0 },
+ { NT_MDG_DEBUG_FLOW_CONTROL, 0 },
+ { NT_MDG_DEBUG_REG_READ_BACK, 0 },
+ { NT_MSK_CATEGORIES, 32 },
+ { NT_MSK_PRESENT, 0 },
+ { NT_NFV_OVS_PRODUCT, 0 },
+ { NT_NIMS, 2 },
+ { NT_PCI_DEVICE_ID, 453 },
+ { NT_PCI_TA_TG_PRESENT, 1 },
+ { NT_PCI_VENDOR_ID, 6388 },
+ { NT_PDB_CATEGORIES, 16 },
+ { NT_PHY_ANEG_PRESENT, 0 },
+ { NT_PHY_KRFEC_PRESENT, 0 },
+ { NT_PHY_PORTS, 2 },
+ { NT_PHY_PORTS_PER_QUAD, 1 },
+ { NT_PHY_QUADS, 2 },
+ { NT_PHY_RSFEC_PRESENT, 1 },
+ { NT_QM_CELLS, 2097152 },
+ { NT_QM_CELL_SIZE, 6144 },
+ { NT_QM_PRESENT, 0 },
+ { NT_QSL_CATEGORIES, 32 },
+ { NT_QSL_COLOR_SEL_BW, 7 },
+ { NT_QSL_QST_SIZE, 4096 },
+ { NT_QUEUES, 128 },
+ { NT_RAC_RAB_INTERFACES, 3 },
+ { NT_RAC_RAB_OB_UPDATE, 0 },
+ { NT_REVISION_ID, 24 },
+ { NT_RMC_LAG_GROUPS, 1 },
+ { NT_ROA_CATEGORIES, 1024 },
+ { NT_ROA_PRESENT, 0 },
+ { NT_RPP_PER_PS, 3333 },
+ { NT_RTX_PRESENT, 0 },
+ { NT_RX_HOST_BUFFERS, 128 },
+ { NT_RX_PORTS, 2 },
+ { NT_RX_PORT_REPLICATE, 0 },
+ { NT_SLB_PRESENT, 0 },
+ { NT_SLC_LR_PRESENT, 1 },
+ { NT_STA_COLORS, 64 },
+ { NT_STA_RX_PORTS, 2 },
+ { NT_TBH_DEBUG_DLN, 1 },
+ { NT_TBH_PRESENT, 0 },
+ { NT_TFD_PRESENT, 1 },
+ { NT_TPE_CATEGORIES, 16 },
+ { NT_TSM_OST_ONLY, 0 },
+ { NT_TS_APPEND, 0 },
+ { NT_TS_INJECT_PRESENT, 0 },
+ { NT_TX_CPY_PACKET_READERS, 0 },
+ { NT_TX_CPY_PRESENT, 1 },
+ { NT_TX_CPY_SIDEBAND_READERS, 6 },
+ { NT_TX_CPY_VARIANT, 0 },
+ { NT_TX_CPY_WRITERS, 5 },
+ { NT_TX_HOST_BUFFERS, 128 },
+ { NT_TX_INS_PRESENT, 1 },
+ { NT_TX_MTU_PROFILE_IFR, 16 },
+ { NT_TX_ON_TIMESTAMP, 1 },
+ { NT_TX_PORTS, 2 },
+ { NT_TX_PORT_REPLICATE, 1 },
+ { NT_TX_RPL_DEPTH, 4096 },
+ { NT_TX_RPL_EXT_CATEGORIES, 1024 },
+ { NT_TX_RPL_PRESENT, 1 },
+ { NT_TYPE_ID, 200 },
+ { NT_USE_TRIPLE_SPEED, 0 },
+ { NT_VERSION_ID, 55 },
+ { NT_VLI_PRESENT, 0 },
+ { 0, -1 }, /* END */
+};
+
+nt_fpga_prod_init_t nthw_fpga_9563_055_024_0000 = {
+ 200, /* fpgaTypeId */
+ 9563, /* fpga_product_id */
+ 55, /* fpga_version */
+ 24, /* fpga_revision */
+ 0, /* fpga_patch_no */
+ 0, /* fpga_build_no */
+ 1689706895, /* fpga_build_time */
+ 140, product_parameters, 48, fpga_modules,
+};
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
new file mode 100644
index 0000000000..1d707d6925
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_FPGA_INSTANCES_H
+#define NTHW_FPGA_INSTANCES_H
+
+#include "fpga_model.h"
+
+extern nt_fpga_prod_init_t *nthw_fpga_instances[];
+
+extern nt_fpga_prod_init_t nthw_fpga_9563_055_024_0000;
+
+#endif /* NTHW_FPGA_INSTANCES_H */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h
new file mode 100644
index 0000000000..38a15bec87
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTHW_FPGA_MODULES_DEFS_H_
+#define _NTHW_FPGA_MODULES_DEFS_H_
+
+/* Unknown/uninitialized - keep this as the first element */
+#define MOD_UNKNOWN (0L)
+#define MOD_CAT (1L)
+#define MOD_CB (2L)
+#define MOD_CCIP (3L)
+#define MOD_CFP4_CTRL_GBOX (4L)
+#define MOD_COR (5L)
+#define MOD_CPY (6L)
+#define MOD_CSU (7L)
+#define MOD_DBS (8L)
+#define MOD_DDP (9L)
+#define MOD_EPP (10L)
+#define MOD_EQM (11L)
+#define MOD_FHM (12L)
+#define MOD_FLM (13L)
+#define MOD_GFG (14L)
+#define MOD_GMF (15L)
+#define MOD_GPIO_PHY (16L)
+#define MOD_GPIO_PHY_PORTS (17L)
+#define MOD_GPIO_SFPP (18L)
+#define MOD_HFU (19L)
+#define MOD_HIF (20L)
+#define MOD_HSH (21L)
+#define MOD_HST (22L)
+#define MOD_ICORE_10G (23L)
+#define MOD_IFR (24L)
+#define MOD_IIC (25L)
+#define MOD_INS (26L)
+#define MOD_IOA (27L)
+#define MOD_IPF (28L)
+#define MOD_KM (29L)
+#define MOD_LAO (30L)
+#define MOD_MAC (31L)
+#define MOD_MAC100 (33L)
+#define MOD_MAC10G (34L)
+#define MOD_MAC1G (35L)
+#define MOD_MAC_PCS (36L)
+#define MOD_MAC_PCS_XXV (37L)
+#define MOD_MAC_RX (38L)
+#define MOD_MAC_TFG (39L)
+#define MOD_MAC_TX (40L)
+#define MOD_MCU (41L)
+#define MOD_MDG (42L)
+#define MOD_MSK (43L)
+#define MOD_NIF (44L)
+#define MOD_PCIE3 (45L)
+#define MOD_PCI_RD_TG (46L)
+#define MOD_PCI_TA (47L)
+#define MOD_PCI_WR_TG (48L)
+#define MOD_PCM_NT100A01_01 (49L)
+#define MOD_PCM_NT50B01_01 (50L)
+#define MOD_PCS (51L)
+#define MOD_PCS100 (52L)
+#define MOD_PDB (53L)
+#define MOD_PDI (54L)
+#define MOD_PHY10G (55L)
+#define MOD_PHY3S10G (56L)
+#define MOD_PM (57L)
+#define MOD_PRM_NT100A01_01 (58L)
+#define MOD_PRM_NT50B01_01 (59L)
+#define MOD_PTP1588 (60L)
+#define MOD_QM (61L)
+#define MOD_QSL (62L)
+#define MOD_QSPI (63L)
+#define MOD_R2DRP (64L)
+#define MOD_RAC (65L)
+#define MOD_RBH (66L)
+#define MOD_RFD (67L)
+#define MOD_RMC (68L)
+#define MOD_RNTC (69L)
+#define MOD_ROA (70L)
+#define MOD_RPL (71L)
+#define MOD_RPP_LR (72L)
+#define MOD_RST7000 (73L)
+#define MOD_RST7001 (74L)
+#define MOD_RST9500 (75L)
+#define MOD_RST9501 (76L)
+#define MOD_RST9502 (77L)
+#define MOD_RST9503 (78L)
+#define MOD_RST9504 (79L)
+#define MOD_RST9505 (80L)
+#define MOD_RST9506 (81L)
+#define MOD_RST9507 (82L)
+#define MOD_RST9508 (83L)
+#define MOD_RST9509 (84L)
+#define MOD_RST9510 (85L)
+#define MOD_RST9512 (86L)
+#define MOD_RST9513 (87L)
+#define MOD_RST9515 (88L)
+#define MOD_RST9516 (89L)
+#define MOD_RST9517 (90L)
+#define MOD_RST9519 (91L)
+#define MOD_RST9520 (92L)
+#define MOD_RST9521 (93L)
+#define MOD_RST9522 (94L)
+#define MOD_RST9523 (95L)
+#define MOD_RST9524 (96L)
+#define MOD_RST9525 (97L)
+#define MOD_RST9526 (98L)
+#define MOD_RST9527 (99L)
+#define MOD_RST9528 (100L)
+#define MOD_RST9529 (101L)
+#define MOD_RST9530 (102L)
+#define MOD_RST9531 (103L)
+#define MOD_RST9532 (104L)
+#define MOD_RST9533 (105L)
+#define MOD_RST9534 (106L)
+#define MOD_RST9535 (107L)
+#define MOD_RST9536 (108L)
+#define MOD_RST9537 (109L)
+#define MOD_RST9538 (110L)
+#define MOD_RST9539 (111L)
+#define MOD_RST9540 (112L)
+#define MOD_RST9541 (113L)
+#define MOD_RST9542 (114L)
+#define MOD_RST9543 (115L)
+#define MOD_RST9544 (116L)
+#define MOD_RST9545 (117L)
+#define MOD_RST9546 (118L)
+#define MOD_RST9547 (119L)
+#define MOD_RST9548 (120L)
+#define MOD_RST9549 (121L)
+#define MOD_RST9553 (122L)
+#define MOD_RST9555 (123L)
+#define MOD_RST9559 (124L)
+#define MOD_RST9563 (125L)
+#define MOD_RTD (126L)
+#define MOD_RTD_HMP (127L)
+#define MOD_RTX (128L)
+#define MOD_SDC (129L)
+#define MOD_SLC (130L)
+#define MOD_SLC_LR (131L)
+#define MOD_SMM (132L)
+#define MOD_SMM_RX (133L)
+#define MOD_SMM_TX (134L)
+#define MOD_SPIM (135L)
+#define MOD_SPIS (136L)
+#define MOD_STA (137L)
+#define MOD_TBH (138L)
+#define MOD_TEMPMON (139L)
+#define MOD_TINT (140L)
+#define MOD_TMC (141L)
+#define MOD_TSM (142L)
+#define MOD_TX_CPY (143L)
+#define MOD_TX_CSI (144L)
+#define MOD_TX_CSO (145L)
+#define MOD_TX_INS (146L)
+#define MOD_TX_RPL (147L)
+/*
+ * NOTE: Keep this as the last element!
+ * End indicator - keep this as the last element - only aliases go below this point
+ */
+#define MOD_UNKNOWN_MAX (148L)
+/* End indicator - keep this as the last element - only aliases go below this point */
+#define MOD_COUNT_MAX (148L)
+/* aliases */
+#define MOD_MAC10 (MOD_MAC10G) /* alias */
+
+#endif /* _NTHW_FPGA_MODULES_DEFS_H_ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h
new file mode 100644
index 0000000000..b6187a257f
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTHW_FPGA_PARAMETERS_DEFS_
+#define _NTHW_FPGA_PARAMETERS_DEFS_
+
+#define NT_PARAM_UNKNOWN (0L)
+#define NT_BUILD_NUMBER (1L)
+#define NT_BUILD_TIME (2L)
+#define NT_CATEGORIES (3L)
+#define NT_CAT_CCT_SIZE (4L)
+#define NT_CAT_CTE_SIZE (5L)
+#define NT_CAT_CTS_SIZE (6L)
+#define NT_CAT_DCT_PRESENT (7L)
+#define NT_CAT_DCT_SIZE (8L)
+#define NT_CAT_END_OFS_SUPPORT (9L)
+#define NT_CAT_FPC (10L)
+#define NT_CAT_FTE_SIZE (11L)
+#define NT_CAT_FUNCS (12L)
+#define NT_CAT_KCC_BANKS (13L)
+#define NT_CAT_KCC_PRESENT (14L)
+#define NT_CAT_KCC_SIZE (15L)
+#define NT_CAT_KCE_SIZE (16L)
+#define NT_CAT_KM_IF_CNT (17L)
+#define NT_CAT_KM_IF_M0 (18L)
+#define NT_CAT_KM_IF_M1 (19L)
+#define NT_CAT_N_CMP (20L)
+#define NT_CAT_N_EXT (21L)
+#define NT_CAT_N_LEN (22L)
+#define NT_CAT_RCK_SIZE (23L)
+#define NT_CAT_VALUES (24L)
+#define NT_CB_DEBUG (25L)
+#define NT_COR_CATEGORIES (26L)
+#define NT_COR_PRESENT (27L)
+#define NT_CPY_MASK_MEM (28L)
+#define NT_CSU_PRESENT (29L)
+#define NT_DBS_PRESENT (30L)
+#define NT_DBS_RX_QUEUES (31L)
+#define NT_DBS_TX_PORTS (32L)
+#define NT_DBS_TX_QUEUES (33L)
+#define NT_DDP_PRESENT (34L)
+#define NT_DDP_TBL_DEPTH (35L)
+#define NT_EMI_SPLIT_STEPS (36L)
+#define NT_EOF_TIMESTAMP_ONLY (37L)
+#define NT_EPP_CATEGORIES (38L)
+#define NT_EXT_MEM_NUM (39L)
+#define NT_EXT_MEM_SINGLE_SIZE_GB (40L)
+#define NT_FLM_CACHE (41L)
+#define NT_FLM_CATEGORIES (42L)
+#define NT_FLM_ENTRY_SIZE (43L)
+#define NT_FLM_PRESENT (44L)
+#define NT_FLM_PRIOS (45L)
+#define NT_FLM_PST_PROFILES (46L)
+#define NT_FLM_SIZE_MB (47L)
+#define NT_FLM_STATEFUL (48L)
+#define NT_FLM_VARIANT (49L)
+#define NT_GFG_PRESENT (50L)
+#define NT_GFG_TX_LIVE_RECONFIG_SUPPORT (51L)
+#define NT_GMF_FCS_PRESENT (52L)
+#define NT_GMF_IFG_SPEED_DIV (53L)
+#define NT_GMF_IFG_SPEED_DIV100G (54L)
+#define NT_GMF_IFG_SPEED_DIV100M (55L)
+#define NT_GMF_IFG_SPEED_DIV10G (56L)
+#define NT_GMF_IFG_SPEED_DIV1G (57L)
+#define NT_GMF_IFG_SPEED_DIV2 (58L)
+#define NT_GMF_IFG_SPEED_DIV25G (59L)
+#define NT_GMF_IFG_SPEED_DIV3 (60L)
+#define NT_GMF_IFG_SPEED_DIV4 (61L)
+#define NT_GMF_IFG_SPEED_DIV40G (62L)
+#define NT_GMF_IFG_SPEED_DIV50G (63L)
+#define NT_GMF_IFG_SPEED_MUL (64L)
+#define NT_GMF_IFG_SPEED_MUL100G (65L)
+#define NT_GMF_IFG_SPEED_MUL100M (66L)
+#define NT_GMF_IFG_SPEED_MUL10G (67L)
+#define NT_GMF_IFG_SPEED_MUL1G (68L)
+#define NT_GMF_IFG_SPEED_MUL2 (69L)
+#define NT_GMF_IFG_SPEED_MUL25G (70L)
+#define NT_GMF_IFG_SPEED_MUL3 (71L)
+#define NT_GMF_IFG_SPEED_MUL4 (72L)
+#define NT_GMF_IFG_SPEED_MUL40G (73L)
+#define NT_GMF_IFG_SPEED_MUL50G (74L)
+#define NT_GROUP_ID (75L)
+#define NT_HFU_PRESENT (76L)
+#define NT_HIF_MSIX_BAR (77L)
+#define NT_HIF_MSIX_PBA_OFS (78L)
+#define NT_HIF_MSIX_PRESENT (79L)
+#define NT_HIF_MSIX_TBL_OFS (80L)
+#define NT_HIF_MSIX_TBL_SIZE (81L)
+#define NT_HIF_PER_PS (82L)
+#define NT_HIF_SRIOV_PRESENT (83L)
+#define NT_HSH_CATEGORIES (84L)
+#define NT_HSH_TOEPLITZ (85L)
+#define NT_HST_CATEGORIES (86L)
+#define NT_HST_PRESENT (87L)
+#define NT_IOA_CATEGORIES (88L)
+#define NT_IOA_PRESENT (89L)
+#define NT_IPF_PRESENT (90L)
+#define NT_KM_CAM_BANKS (91L)
+#define NT_KM_CAM_RECORDS (92L)
+#define NT_KM_CAM_REC_WORDS (93L)
+#define NT_KM_CATEGORIES (94L)
+#define NT_KM_END_OFS_SUPPORT (95L)
+#define NT_KM_EXT_EXTRACTORS (96L)
+#define NT_KM_FLOW_SETS (97L)
+#define NT_KM_FLOW_TYPES (98L)
+#define NT_KM_PRESENT (99L)
+#define NT_KM_SWX_PRESENT (100L)
+#define NT_KM_SYNERGY_MATCH (101L)
+#define NT_KM_TCAM_BANKS (102L)
+#define NT_KM_TCAM_BANK_WIDTH (103L)
+#define NT_KM_TCAM_HIT_QUAL (104L)
+#define NT_KM_TCAM_KEYWAY (105L)
+#define NT_KM_WIDE (106L)
+#define NT_LR_PRESENT (107L)
+#define NT_LTX_CATEGORIES (108L)
+#define NT_MCU_DRAM_SIZE (109L)
+#define NT_MCU_PRESENT (110L)
+#define NT_MCU_TYPE (111L)
+#define NT_MDG_DEBUG_FLOW_CONTROL (112L)
+#define NT_MDG_DEBUG_REG_READ_BACK (113L)
+#define NT_MSK_CATEGORIES (114L)
+#define NT_MSK_PRESENT (115L)
+#define NT_NAME (116L)
+#define NT_NFV_OVS_PRODUCT (117L)
+#define NT_NIMS (118L)
+#define NT_PATCH_NUMBER (119L)
+#define NT_PCI_DEVICE_ID (120L)
+#define NT_PCI_INT_AVR (121L)
+#define NT_PCI_INT_EQM (122L)
+#define NT_PCI_INT_IIC0 (123L)
+#define NT_PCI_INT_IIC1 (124L)
+#define NT_PCI_INT_IIC2 (125L)
+#define NT_PCI_INT_IIC3 (126L)
+#define NT_PCI_INT_IIC4 (127L)
+#define NT_PCI_INT_IIC5 (128L)
+#define NT_PCI_INT_PORT (129L)
+#define NT_PCI_INT_PORT0 (130L)
+#define NT_PCI_INT_PORT1 (131L)
+#define NT_PCI_INT_PPS (132L)
+#define NT_PCI_INT_QSPI (133L)
+#define NT_PCI_INT_SPIM (134L)
+#define NT_PCI_INT_SPIS (135L)
+#define NT_PCI_INT_STA (136L)
+#define NT_PCI_INT_TIMER (137L)
+#define NT_PCI_INT_TINT (138L)
+#define NT_PCI_TA_TG_PRESENT (139L)
+#define NT_PCI_VENDOR_ID (140L)
+#define NT_PDB_CATEGORIES (141L)
+#define NT_PHY_ANEG_PRESENT (142L)
+#define NT_PHY_KRFEC_PRESENT (143L)
+#define NT_PHY_PORTS (144L)
+#define NT_PHY_PORTS_PER_QUAD (145L)
+#define NT_PHY_QUADS (146L)
+#define NT_PHY_RSFEC_PRESENT (147L)
+#define NT_PORTS (148L)
+#define NT_PROD_ID_LAYOUT_VERSION (149L)
+#define NT_QM_BLOCKS (150L)
+#define NT_QM_CELLS (151L)
+#define NT_QM_CELL_SIZE (152L)
+#define NT_QM_PRESENT (153L)
+#define NT_QSL_CATEGORIES (154L)
+#define NT_QSL_COLOR_SEL_BW (155L)
+#define NT_QSL_QST_SIZE (156L)
+#define NT_QUEUES (157L)
+#define NT_RAC_RAB_INTERFACES (158L)
+#define NT_RAC_RAB_OB_UPDATE (159L)
+#define NT_REVISION_ID (160L)
+#define NT_RMC_LAG_GROUPS (161L)
+#define NT_ROA_CATEGORIES (162L)
+#define NT_ROA_PRESENT (163L)
+#define NT_RPP_PER_PS (164L)
+#define NT_RTX_PRESENT (165L)
+#define NT_RX_HOST_BUFFERS (166L)
+#define NT_RX_PORTS (167L)
+#define NT_RX_PORT_REPLICATE (168L)
+#define NT_SLB_PRESENT (169L)
+#define NT_SLC_LR_PRESENT (170L)
+#define NT_STA_COLORS (171L)
+#define NT_STA_RX_PORTS (172L)
+#define NT_TBH_DEBUG_DLN (173L)
+#define NT_TBH_PRESENT (174L)
+#define NT_TFD_PRESENT (175L)
+#define NT_TPE_CATEGORIES (176L)
+#define NT_TSM_OST_ONLY (177L)
+#define NT_TS_APPEND (178L)
+#define NT_TS_INJECT_PRESENT (179L)
+#define NT_TX_CPY_PACKET_READERS (180L)
+#define NT_TX_CPY_PRESENT (181L)
+#define NT_TX_CPY_SIDEBAND_READERS (182L)
+#define NT_TX_CPY_VARIANT (183L)
+#define NT_TX_CPY_WRITERS (184L)
+#define NT_TX_HOST_BUFFERS (185L)
+#define NT_TX_INS_PRESENT (186L)
+#define NT_TX_MTU_PROFILE_IFR (187L)
+#define NT_TX_ON_TIMESTAMP (188L)
+#define NT_TX_PORTS (189L)
+#define NT_TX_PORT_REPLICATE (190L)
+#define NT_TX_RPL_DEPTH (191L)
+#define NT_TX_RPL_EXT_CATEGORIES (192L)
+#define NT_TX_RPL_PRESENT (193L)
+#define NT_TYPE_ID (194L)
+#define NT_USE_TRIPLE_SPEED (195L)
+#define NT_UUID (196L)
+#define NT_VERSION (197L)
+#define NT_VERSION_ID (198L)
+#define NT_VLI_PRESENT (199L)
+
+#endif /* _NTHW_FPGA_PARAMETERS_DEFS_ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h
new file mode 100644
index 0000000000..3948ed3ae3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h
@@ -0,0 +1,7277 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTHW_FPGA_REGISTERS_DEFS_
+#define _NTHW_FPGA_REGISTERS_DEFS_
+
+/* CAT */
+#define CAT_CCE_CTRL (1000L)
+#define CAT_CCE_CTRL_ADR (1001L)
+#define CAT_CCE_CTRL_CNT (1002L)
+#define CAT_CCE_DATA (1003L)
+#define CAT_CCE_DATA_IMM (1004L)
+#define CAT_CCE_DATA_IND (1005L)
+#define CAT_CCS_CTRL (1006L)
+#define CAT_CCS_CTRL_ADR (1007L)
+#define CAT_CCS_CTRL_CNT (1008L)
+#define CAT_CCS_DATA (1009L)
+#define CAT_CCS_DATA_COR (1010L)
+#define CAT_CCS_DATA_COR_EN (1011L)
+#define CAT_CCS_DATA_EPP (1012L)
+#define CAT_CCS_DATA_EPP_EN (1013L)
+#define CAT_CCS_DATA_HSH (1014L)
+#define CAT_CCS_DATA_HSH_EN (1015L)
+#define CAT_CCS_DATA_HST (1016L)
+#define CAT_CCS_DATA_HST_EN (1017L)
+#define CAT_CCS_DATA_IPF (1018L)
+#define CAT_CCS_DATA_IPF_EN (1019L)
+#define CAT_CCS_DATA_MSK (1020L)
+#define CAT_CCS_DATA_MSK_EN (1021L)
+#define CAT_CCS_DATA_PDB (1022L)
+#define CAT_CCS_DATA_PDB_EN (1023L)
+#define CAT_CCS_DATA_QSL (1024L)
+#define CAT_CCS_DATA_QSL_EN (1025L)
+#define CAT_CCS_DATA_RRB (1026L)
+#define CAT_CCS_DATA_RRB_EN (1027L)
+#define CAT_CCS_DATA_SB0_DATA (1028L)
+#define CAT_CCS_DATA_SB0_TYPE (1029L)
+#define CAT_CCS_DATA_SB1_DATA (1030L)
+#define CAT_CCS_DATA_SB1_TYPE (1031L)
+#define CAT_CCS_DATA_SB2_DATA (1032L)
+#define CAT_CCS_DATA_SB2_TYPE (1033L)
+#define CAT_CCS_DATA_SLC (1034L)
+#define CAT_CCS_DATA_SLC_EN (1035L)
+#define CAT_CCS_DATA_TPE (1036L)
+#define CAT_CCS_DATA_TPE_EN (1037L)
+#define CAT_CCT_CTRL (1038L)
+#define CAT_CCT_CTRL_ADR (1039L)
+#define CAT_CCT_CTRL_CNT (1040L)
+#define CAT_CCT_DATA (1041L)
+#define CAT_CCT_DATA_COLOR (1042L)
+#define CAT_CCT_DATA_KM (1043L)
+#define CAT_CFN_CTRL (1044L)
+#define CAT_CFN_CTRL_ADR (1045L)
+#define CAT_CFN_CTRL_CNT (1046L)
+#define CAT_CFN_DATA (1047L)
+#define CAT_CFN_DATA_ENABLE (1048L)
+#define CAT_CFN_DATA_ERR_CV (1049L)
+#define CAT_CFN_DATA_ERR_FCS (1050L)
+#define CAT_CFN_DATA_ERR_INV (1051L)
+#define CAT_CFN_DATA_ERR_L3_CS (1052L)
+#define CAT_CFN_DATA_ERR_L4_CS (1053L)
+#define CAT_CFN_DATA_ERR_TNL_L3_CS (1054L)
+#define CAT_CFN_DATA_ERR_TNL_L4_CS (1055L)
+#define CAT_CFN_DATA_ERR_TNL_TTL_EXP (1056L)
+#define CAT_CFN_DATA_ERR_TRUNC (1057L)
+#define CAT_CFN_DATA_ERR_TTL_EXP (1058L)
+#define CAT_CFN_DATA_FLM_OR (1059L)
+#define CAT_CFN_DATA_INV (1060L)
+#define CAT_CFN_DATA_KM0_OR (1061L)
+#define CAT_CFN_DATA_KM1_OR (1062L)
+#define CAT_CFN_DATA_KM_OR (1063L)
+#define CAT_CFN_DATA_LC (1064L)
+#define CAT_CFN_DATA_LC_INV (1065L)
+#define CAT_CFN_DATA_MAC_PORT (1066L)
+#define CAT_CFN_DATA_PM_AND_INV (1067L)
+#define CAT_CFN_DATA_PM_CMB (1068L)
+#define CAT_CFN_DATA_PM_CMP (1069L)
+#define CAT_CFN_DATA_PM_DCT (1070L)
+#define CAT_CFN_DATA_PM_EXT_INV (1071L)
+#define CAT_CFN_DATA_PM_INV (1072L)
+#define CAT_CFN_DATA_PM_OR_INV (1073L)
+#define CAT_CFN_DATA_PTC_CFP (1074L)
+#define CAT_CFN_DATA_PTC_FRAG (1075L)
+#define CAT_CFN_DATA_PTC_INV (1076L)
+#define CAT_CFN_DATA_PTC_IP_PROT (1077L)
+#define CAT_CFN_DATA_PTC_ISL (1078L)
+#define CAT_CFN_DATA_PTC_L2 (1079L)
+#define CAT_CFN_DATA_PTC_L3 (1080L)
+#define CAT_CFN_DATA_PTC_L4 (1081L)
+#define CAT_CFN_DATA_PTC_MAC (1082L)
+#define CAT_CFN_DATA_PTC_MPLS (1083L)
+#define CAT_CFN_DATA_PTC_TNL_FRAG (1084L)
+#define CAT_CFN_DATA_PTC_TNL_IP_PROT (1085L)
+#define CAT_CFN_DATA_PTC_TNL_L2 (1086L)
+#define CAT_CFN_DATA_PTC_TNL_L3 (1087L)
+#define CAT_CFN_DATA_PTC_TNL_L4 (1088L)
+#define CAT_CFN_DATA_PTC_TNL_MPLS (1089L)
+#define CAT_CFN_DATA_PTC_TNL_VLAN (1090L)
+#define CAT_CFN_DATA_PTC_TUNNEL (1091L)
+#define CAT_CFN_DATA_PTC_VLAN (1092L)
+#define CAT_CFN_DATA_PTC_VNTAG (1093L)
+#define CAT_COT_CTRL (1094L)
+#define CAT_COT_CTRL_ADR (1095L)
+#define CAT_COT_CTRL_CNT (1096L)
+#define CAT_COT_DATA (1097L)
+#define CAT_COT_DATA_COLOR (1098L)
+#define CAT_COT_DATA_KM (1099L)
+#define CAT_COT_DATA_NFV_SB (1100L)
+#define CAT_CTE_CTRL (1101L)
+#define CAT_CTE_CTRL_ADR (1102L)
+#define CAT_CTE_CTRL_CNT (1103L)
+#define CAT_CTE_DATA (1104L)
+#define CAT_CTE_DATA_COL_ENABLE (1105L)
+#define CAT_CTE_DATA_COR_ENABLE (1106L)
+#define CAT_CTE_DATA_EPP_ENABLE (1107L)
+#define CAT_CTE_DATA_HSH_ENABLE (1108L)
+#define CAT_CTE_DATA_HST_ENABLE (1109L)
+#define CAT_CTE_DATA_IPF_ENABLE (1110L)
+#define CAT_CTE_DATA_MSK_ENABLE (1111L)
+#define CAT_CTE_DATA_PDB_ENABLE (1112L)
+#define CAT_CTE_DATA_QSL_ENABLE (1113L)
+#define CAT_CTE_DATA_RRB_ENABLE (1114L)
+#define CAT_CTE_DATA_SLC_ENABLE (1115L)
+#define CAT_CTE_DATA_TPE_ENABLE (1116L)
+#define CAT_CTE_DATA_TX_INS_ENABLE (1117L)
+#define CAT_CTE_DATA_TX_RPL_ENABLE (1118L)
+#define CAT_CTS_CTRL (1119L)
+#define CAT_CTS_CTRL_ADR (1120L)
+#define CAT_CTS_CTRL_CNT (1121L)
+#define CAT_CTS_DATA (1122L)
+#define CAT_CTS_DATA_CAT_A (1123L)
+#define CAT_CTS_DATA_CAT_B (1124L)
+#define CAT_DCT_CTRL (1125L)
+#define CAT_DCT_CTRL_ADR (1126L)
+#define CAT_DCT_CTRL_CNT (1127L)
+#define CAT_DCT_DATA (1128L)
+#define CAT_DCT_DATA_RES (1129L)
+#define CAT_DCT_SEL (1130L)
+#define CAT_DCT_SEL_LU (1131L)
+#define CAT_EXO_CTRL (1132L)
+#define CAT_EXO_CTRL_ADR (1133L)
+#define CAT_EXO_CTRL_CNT (1134L)
+#define CAT_EXO_DATA (1135L)
+#define CAT_EXO_DATA_DYN (1136L)
+#define CAT_EXO_DATA_OFS (1137L)
+#define CAT_FCE_CTRL (1138L)
+#define CAT_FCE_CTRL_ADR (1139L)
+#define CAT_FCE_CTRL_CNT (1140L)
+#define CAT_FCE_DATA (1141L)
+#define CAT_FCE_DATA_ENABLE (1142L)
+#define CAT_FCS_CTRL (1143L)
+#define CAT_FCS_CTRL_ADR (1144L)
+#define CAT_FCS_CTRL_CNT (1145L)
+#define CAT_FCS_DATA (1146L)
+#define CAT_FCS_DATA_CATEGORY (1147L)
+#define CAT_FTE0_CTRL (1148L)
+#define CAT_FTE0_CTRL_ADR (1149L)
+#define CAT_FTE0_CTRL_CNT (1150L)
+#define CAT_FTE0_DATA (1151L)
+#define CAT_FTE0_DATA_ENABLE (1152L)
+#define CAT_FTE1_CTRL (1153L)
+#define CAT_FTE1_CTRL_ADR (1154L)
+#define CAT_FTE1_CTRL_CNT (1155L)
+#define CAT_FTE1_DATA (1156L)
+#define CAT_FTE1_DATA_ENABLE (1157L)
+#define CAT_FTE_CTRL (1158L)
+#define CAT_FTE_CTRL_ADR (1159L)
+#define CAT_FTE_CTRL_CNT (1160L)
+#define CAT_FTE_DATA (1161L)
+#define CAT_FTE_DATA_ENABLE (1162L)
+#define CAT_FTE_FLM_CTRL (1163L)
+#define CAT_FTE_FLM_CTRL_ADR (1164L)
+#define CAT_FTE_FLM_CTRL_CNT (1165L)
+#define CAT_FTE_FLM_DATA (1166L)
+#define CAT_FTE_FLM_DATA_ENABLE (1167L)
+#define CAT_JOIN (1168L)
+#define CAT_JOIN_J1 (1169L)
+#define CAT_JOIN_J2 (1170L)
+#define CAT_KCC (1171L)
+#define CAT_KCC_CTRL (1172L)
+#define CAT_KCC_CTRL_ADR (1173L)
+#define CAT_KCC_CTRL_CNT (1174L)
+#define CAT_KCC_DATA (1175L)
+#define CAT_KCC_DATA_CATEGORY (1176L)
+#define CAT_KCC_DATA_ID (1177L)
+#define CAT_KCC_DATA_KEY (1178L)
+#define CAT_KCE0_CTRL (1179L)
+#define CAT_KCE0_CTRL_ADR (1180L)
+#define CAT_KCE0_CTRL_CNT (1181L)
+#define CAT_KCE0_DATA (1182L)
+#define CAT_KCE0_DATA_ENABLE (1183L)
+#define CAT_KCE1_CTRL (1184L)
+#define CAT_KCE1_CTRL_ADR (1185L)
+#define CAT_KCE1_CTRL_CNT (1186L)
+#define CAT_KCE1_DATA (1187L)
+#define CAT_KCE1_DATA_ENABLE (1188L)
+#define CAT_KCE_CTRL (1189L)
+#define CAT_KCE_CTRL_ADR (1190L)
+#define CAT_KCE_CTRL_CNT (1191L)
+#define CAT_KCE_DATA (1192L)
+#define CAT_KCE_DATA_ENABLE (1193L)
+#define CAT_KCS0_CTRL (1194L)
+#define CAT_KCS0_CTRL_ADR (1195L)
+#define CAT_KCS0_CTRL_CNT (1196L)
+#define CAT_KCS0_DATA (1197L)
+#define CAT_KCS0_DATA_CATEGORY (1198L)
+#define CAT_KCS1_CTRL (1199L)
+#define CAT_KCS1_CTRL_ADR (1200L)
+#define CAT_KCS1_CTRL_CNT (1201L)
+#define CAT_KCS1_DATA (1202L)
+#define CAT_KCS1_DATA_CATEGORY (1203L)
+#define CAT_KCS_CTRL (1204L)
+#define CAT_KCS_CTRL_ADR (1205L)
+#define CAT_KCS_CTRL_CNT (1206L)
+#define CAT_KCS_DATA (1207L)
+#define CAT_KCS_DATA_CATEGORY (1208L)
+#define CAT_LEN_CTRL (1209L)
+#define CAT_LEN_CTRL_ADR (1210L)
+#define CAT_LEN_CTRL_CNT (1211L)
+#define CAT_LEN_DATA (1212L)
+#define CAT_LEN_DATA_DYN1 (1213L)
+#define CAT_LEN_DATA_DYN2 (1214L)
+#define CAT_LEN_DATA_INV (1215L)
+#define CAT_LEN_DATA_LOWER (1216L)
+#define CAT_LEN_DATA_UPPER (1217L)
+#define CAT_RCK_CTRL (1218L)
+#define CAT_RCK_CTRL_ADR (1219L)
+#define CAT_RCK_CTRL_CNT (1220L)
+#define CAT_RCK_DATA (1221L)
+#define CAT_RCK_DATA_CM0U (1222L)
+#define CAT_RCK_DATA_CM1U (1223L)
+#define CAT_RCK_DATA_CM2U (1224L)
+#define CAT_RCK_DATA_CM3U (1225L)
+#define CAT_RCK_DATA_CM4U (1226L)
+#define CAT_RCK_DATA_CM5U (1227L)
+#define CAT_RCK_DATA_CM6U (1228L)
+#define CAT_RCK_DATA_CM7U (1229L)
+#define CAT_RCK_DATA_CML0 (1230L)
+#define CAT_RCK_DATA_CML1 (1231L)
+#define CAT_RCK_DATA_CML2 (1232L)
+#define CAT_RCK_DATA_CML3 (1233L)
+#define CAT_RCK_DATA_CML4 (1234L)
+#define CAT_RCK_DATA_CML5 (1235L)
+#define CAT_RCK_DATA_CML6 (1236L)
+#define CAT_RCK_DATA_CML7 (1237L)
+#define CAT_RCK_DATA_SEL0 (1238L)
+#define CAT_RCK_DATA_SEL1 (1239L)
+#define CAT_RCK_DATA_SEL2 (1240L)
+#define CAT_RCK_DATA_SEL3 (1241L)
+#define CAT_RCK_DATA_SEL4 (1242L)
+#define CAT_RCK_DATA_SEL5 (1243L)
+#define CAT_RCK_DATA_SEL6 (1244L)
+#define CAT_RCK_DATA_SEL7 (1245L)
+#define CAT_RCK_DATA_SEU0 (1246L)
+#define CAT_RCK_DATA_SEU1 (1247L)
+#define CAT_RCK_DATA_SEU2 (1248L)
+#define CAT_RCK_DATA_SEU3 (1249L)
+#define CAT_RCK_DATA_SEU4 (1250L)
+#define CAT_RCK_DATA_SEU5 (1251L)
+#define CAT_RCK_DATA_SEU6 (1252L)
+#define CAT_RCK_DATA_SEU7 (1253L)
+/* CB */
+#define CB_CTRL (1254L)
+#define CB_CTRL_BP (1255L)
+#define CB_CTRL_BYPASS (1256L)
+#define CB_CTRL_ENABLE (1257L)
+#define CB_CTRL_QMA (1258L)
+#define CB_CTRL_QME (1259L)
+#define CB_DBG_BP (1260L)
+#define CB_DBG_BP_CNT (1261L)
+#define CB_DBG_DQ (1262L)
+#define CB_DBG_DQ_MAX (1263L)
+#define CB_DBG_EGS_QUEUE (1264L)
+#define CB_DBG_EGS_QUEUE_ADD (1265L)
+#define CB_DBG_EGS_QUEUE_AND (1266L)
+#define CB_DBG_FREE1200 (1267L)
+#define CB_DBG_FREE1200_CNT (1268L)
+#define CB_DBG_FREE1800 (1269L)
+#define CB_DBG_FREE1800_CNT (1270L)
+#define CB_DBG_FREE600 (1271L)
+#define CB_DBG_FREE600_CNT (1272L)
+#define CB_DBG_H16 (1273L)
+#define CB_DBG_H16_CNT (1274L)
+#define CB_DBG_H32 (1275L)
+#define CB_DBG_H32_CNT (1276L)
+#define CB_DBG_H64 (1277L)
+#define CB_DBG_H64_CNT (1278L)
+#define CB_DBG_HAVE (1279L)
+#define CB_DBG_HAVE_CNT (1280L)
+#define CB_DBG_IGS_QUEUE (1281L)
+#define CB_DBG_IGS_QUEUE_ADD (1282L)
+#define CB_DBG_IGS_QUEUE_AND (1283L)
+#define CB_DBG_QM_CELL_CNT (1284L)
+#define CB_DBG_QM_CELL_CNT_CNT (1285L)
+#define CB_DBG_QM_CELL_XOR (1286L)
+#define CB_DBG_QM_CELL_XOR_XOR (1287L)
+#define CB_QPM_CTRL (1288L)
+#define CB_QPM_CTRL_ADR (1289L)
+#define CB_QPM_CTRL_CNT (1290L)
+#define CB_QPM_DATA (1291L)
+#define CB_QPM_DATA_P (1292L)
+#define CB_QUEUE_MAX (1293L)
+#define CB_QUEUE_MAX_MAX (1294L)
+#define CB_STATUS (1295L)
+#define CB_STATUS_BP (1296L)
+#define CB_STATUS_DB (1297L)
+#define CB_STATUS_EMPTY (1298L)
+#define CB_STATUS_IDLE (1299L)
+#define CB_STATUS_OVF (1300L)
+#define CB_TS_RATE (1301L)
+#define CB_TS_RATE_CNT (1302L)
+#define CB_TS_SAVE (1303L)
+#define CB_TS_SAVE_MAX (1304L)
+/* CCIP */
+#define CCIP_AFU_ID_L (1305L)
+#define CCIP_AFU_ID_L_ID (1306L)
+#define CCIP_AFU_ID_U (1307L)
+#define CCIP_AFU_ID_U_ID (1308L)
+#define CCIP_CONTROL (1309L)
+#define CCIP_CONTROL_FENCE (1310L)
+#define CCIP_DFH (1311L)
+#define CCIP_DFH_AFU_VER_MAJOR (1312L)
+#define CCIP_DFH_AFU_VER_MINOR (1313L)
+#define CCIP_DFH_CCIP_VER (1314L)
+#define CCIP_DFH_END (1315L)
+#define CCIP_DFH_FEATURE_TYPE (1316L)
+#define CCIP_DFH_NEXT (1317L)
+#define CCIP_RSVD0 (1318L)
+#define CCIP_RSVD0_RSVD (1319L)
+#define CCIP_RSVD1 (1320L)
+#define CCIP_RSVD1_RSVD (1321L)
+#define CCIP_STATUS (1322L)
+#define CCIP_STATUS_ERR (1323L)
+#define CCIP_STATUS_PWR (1324L)
+/* CFP4_CTRL_GBOX */
+#define CFP4_CTRL_GBOX_CFG (1325L)
+#define CFP4_CTRL_GBOX_CFG_GLB_ALARMN (1326L)
+#define CFP4_CTRL_GBOX_CFG_INTERR (1327L)
+#define CFP4_CTRL_GBOX_CFG_MOD_ABS (1328L)
+#define CFP4_CTRL_GBOX_CFG_MOD_LOPWR (1329L)
+#define CFP4_CTRL_GBOX_CFG_MOD_RSTN (1330L)
+#define CFP4_CTRL_GBOX_CFG_NRESET (1331L)
+#define CFP4_CTRL_GBOX_CFG_RXLOS (1332L)
+#define CFP4_CTRL_GBOX_CFG_TXDIS (1333L)
+#define CFP4_CTRL_GBOX_CFP4 (1334L)
+#define CFP4_CTRL_GBOX_CFP4_GLB_ALARMN (1335L)
+#define CFP4_CTRL_GBOX_CFP4_MOD_ABS (1336L)
+#define CFP4_CTRL_GBOX_CFP4_MOD_LOPWR (1337L)
+#define CFP4_CTRL_GBOX_CFP4_MOD_RSTN (1338L)
+#define CFP4_CTRL_GBOX_CFP4_RXLOS (1339L)
+#define CFP4_CTRL_GBOX_CFP4_TXDIS (1340L)
+#define CFP4_CTRL_GBOX_GBOX (1341L)
+#define CFP4_CTRL_GBOX_GBOX_INTERR (1342L)
+#define CFP4_CTRL_GBOX_GBOX_NRESET (1343L)
+#define CFP4_CTRL_GBOX_GPIO (1344L)
+#define CFP4_CTRL_GBOX_GPIO_GLB_ALARMN (1345L)
+#define CFP4_CTRL_GBOX_GPIO_INTERR (1346L)
+#define CFP4_CTRL_GBOX_GPIO_MOD_ABS (1347L)
+#define CFP4_CTRL_GBOX_GPIO_MOD_LOPWR (1348L)
+#define CFP4_CTRL_GBOX_GPIO_MOD_RSTN (1349L)
+#define CFP4_CTRL_GBOX_GPIO_NRESET (1350L)
+#define CFP4_CTRL_GBOX_GPIO_RXLOS (1351L)
+#define CFP4_CTRL_GBOX_GPIO_TXDIS (1352L)
+/* COR */
+#define COR_CTRL (1393L)
+#define COR_CTRL_EN (1394L)
+#define COR_DBG_COR_CNT (1395L)
+#define COR_DBG_COR_CNT_VAL (1396L)
+#define COR_DBG_COR_ID (1397L)
+#define COR_DBG_COR_ID_VAL (1398L)
+#define COR_DBG_COR_LO (1399L)
+#define COR_DBG_COR_LO_VAL (1400L)
+#define COR_DBG_COR_UP (1401L)
+#define COR_DBG_COR_UP_VAL (1402L)
+#define COR_DCEO (1403L)
+#define COR_DCEO_VAL (1404L)
+#define COR_DCSO (1405L)
+#define COR_DCSO_VAL (1406L)
+#define COR_DEEO (1407L)
+#define COR_DEEO_VAL (1408L)
+#define COR_DEO (1409L)
+#define COR_DEO_VAL (1410L)
+#define COR_DESO (1411L)
+#define COR_DESO_VAL (1412L)
+#define COR_DSEO (1413L)
+#define COR_DSEO_VAL (1414L)
+#define COR_DSO (1415L)
+#define COR_DSO_VAL (1416L)
+#define COR_DSSO (1417L)
+#define COR_DSSO_VAL (1418L)
+#define COR_RCP_CTRL (1419L)
+#define COR_RCP_CTRL_ADR (1420L)
+#define COR_RCP_CTRL_CNT (1421L)
+#define COR_RCP_DATA (1422L)
+#define COR_RCP_DATA_CBM1 (1423L)
+#define COR_RCP_DATA_EN (1424L)
+#define COR_RCP_DATA_END_PROT (1425L)
+#define COR_RCP_DATA_END_STATIC (1426L)
+#define COR_RCP_DATA_IP_CHK (1427L)
+#define COR_RCP_DATA_IP_DSCP (1428L)
+#define COR_RCP_DATA_IP_DST (1429L)
+#define COR_RCP_DATA_IP_ECN (1430L)
+#define COR_RCP_DATA_IP_FLAGS (1431L)
+#define COR_RCP_DATA_IP_FLOW (1432L)
+#define COR_RCP_DATA_IP_HOP (1433L)
+#define COR_RCP_DATA_IP_IDENT (1434L)
+#define COR_RCP_DATA_IP_NXTHDR (1435L)
+#define COR_RCP_DATA_IP_SRC (1436L)
+#define COR_RCP_DATA_IP_TC (1437L)
+#define COR_RCP_DATA_IP_TTL (1438L)
+#define COR_RCP_DATA_MAX_LEN (1439L)
+#define COR_RCP_DATA_PROT_OFS1 (1440L)
+#define COR_RCP_DATA_START_PROT (1441L)
+#define COR_RCP_DATA_START_STATIC (1442L)
+#define COR_RCP_DATA_STTC_OFS1 (1443L)
+#define COR_RCP_DATA_TCP_CHK (1444L)
+#define COR_RCP_DATA_TCP_DST (1445L)
+#define COR_RCP_DATA_TCP_SEQ (1446L)
+#define COR_RCP_DATA_TCP_SRC (1447L)
+#define COR_RCP_DATA_TNL (1448L)
+#define COR_RCP_DATA_UDP_CHK (1449L)
+#define COR_RCP_DATA_UDP_DST (1450L)
+#define COR_RCP_DATA_UDP_SRC (1451L)
+/* CPY */
+#define CPY_WRITER0_CTRL (1452L)
+#define CPY_WRITER0_CTRL_ADR (1453L)
+#define CPY_WRITER0_CTRL_CNT (1454L)
+#define CPY_WRITER0_DATA (1455L)
+#define CPY_WRITER0_DATA_DYN (1456L)
+#define CPY_WRITER0_DATA_LEN (1457L)
+#define CPY_WRITER0_DATA_MASK_POINTER (1458L)
+#define CPY_WRITER0_DATA_OFS (1459L)
+#define CPY_WRITER0_DATA_READER_SELECT (1460L)
+#define CPY_WRITER0_MASK_CTRL (1461L)
+#define CPY_WRITER0_MASK_CTRL_ADR (1462L)
+#define CPY_WRITER0_MASK_CTRL_CNT (1463L)
+#define CPY_WRITER0_MASK_DATA (1464L)
+#define CPY_WRITER0_MASK_DATA_BYTE_MASK (1465L)
+#define CPY_WRITER1_CTRL (1466L)
+#define CPY_WRITER1_CTRL_ADR (1467L)
+#define CPY_WRITER1_CTRL_CNT (1468L)
+#define CPY_WRITER1_DATA (1469L)
+#define CPY_WRITER1_DATA_DYN (1470L)
+#define CPY_WRITER1_DATA_LEN (1471L)
+#define CPY_WRITER1_DATA_MASK_POINTER (1472L)
+#define CPY_WRITER1_DATA_OFS (1473L)
+#define CPY_WRITER1_DATA_READER_SELECT (1474L)
+#define CPY_WRITER1_MASK_CTRL (1475L)
+#define CPY_WRITER1_MASK_CTRL_ADR (1476L)
+#define CPY_WRITER1_MASK_CTRL_CNT (1477L)
+#define CPY_WRITER1_MASK_DATA (1478L)
+#define CPY_WRITER1_MASK_DATA_BYTE_MASK (1479L)
+#define CPY_WRITER2_CTRL (1480L)
+#define CPY_WRITER2_CTRL_ADR (1481L)
+#define CPY_WRITER2_CTRL_CNT (1482L)
+#define CPY_WRITER2_DATA (1483L)
+#define CPY_WRITER2_DATA_DYN (1484L)
+#define CPY_WRITER2_DATA_LEN (1485L)
+#define CPY_WRITER2_DATA_MASK_POINTER (1486L)
+#define CPY_WRITER2_DATA_OFS (1487L)
+#define CPY_WRITER2_DATA_READER_SELECT (1488L)
+#define CPY_WRITER2_MASK_CTRL (1489L)
+#define CPY_WRITER2_MASK_CTRL_ADR (1490L)
+#define CPY_WRITER2_MASK_CTRL_CNT (1491L)
+#define CPY_WRITER2_MASK_DATA (1492L)
+#define CPY_WRITER2_MASK_DATA_BYTE_MASK (1493L)
+#define CPY_WRITER3_CTRL (1494L)
+#define CPY_WRITER3_CTRL_ADR (1495L)
+#define CPY_WRITER3_CTRL_CNT (1496L)
+#define CPY_WRITER3_DATA (1497L)
+#define CPY_WRITER3_DATA_DYN (1498L)
+#define CPY_WRITER3_DATA_LEN (1499L)
+#define CPY_WRITER3_DATA_MASK_POINTER (1500L)
+#define CPY_WRITER3_DATA_OFS (1501L)
+#define CPY_WRITER3_DATA_READER_SELECT (1502L)
+#define CPY_WRITER3_MASK_CTRL (1503L)
+#define CPY_WRITER3_MASK_CTRL_ADR (1504L)
+#define CPY_WRITER3_MASK_CTRL_CNT (1505L)
+#define CPY_WRITER3_MASK_DATA (1506L)
+#define CPY_WRITER3_MASK_DATA_BYTE_MASK (1507L)
+#define CPY_WRITER4_CTRL (1508L)
+#define CPY_WRITER4_CTRL_ADR (1509L)
+#define CPY_WRITER4_CTRL_CNT (1510L)
+#define CPY_WRITER4_DATA (1511L)
+#define CPY_WRITER4_DATA_DYN (1512L)
+#define CPY_WRITER4_DATA_LEN (1513L)
+#define CPY_WRITER4_DATA_MASK_POINTER (1514L)
+#define CPY_WRITER4_DATA_OFS (1515L)
+#define CPY_WRITER4_DATA_READER_SELECT (1516L)
+#define CPY_WRITER4_MASK_CTRL (1517L)
+#define CPY_WRITER4_MASK_CTRL_ADR (1518L)
+#define CPY_WRITER4_MASK_CTRL_CNT (1519L)
+#define CPY_WRITER4_MASK_DATA (1520L)
+#define CPY_WRITER4_MASK_DATA_BYTE_MASK (1521L)
+#define CPY_WRITER5_CTRL (1522L)
+#define CPY_WRITER5_CTRL_ADR (1523L)
+#define CPY_WRITER5_CTRL_CNT (1524L)
+#define CPY_WRITER5_DATA (1525L)
+#define CPY_WRITER5_DATA_DYN (1526L)
+#define CPY_WRITER5_DATA_LEN (1527L)
+#define CPY_WRITER5_DATA_MASK_POINTER (1528L)
+#define CPY_WRITER5_DATA_OFS (1529L)
+#define CPY_WRITER5_DATA_READER_SELECT (1530L)
+#define CPY_WRITER5_MASK_CTRL (1531L)
+#define CPY_WRITER5_MASK_CTRL_ADR (1532L)
+#define CPY_WRITER5_MASK_CTRL_CNT (1533L)
+#define CPY_WRITER5_MASK_DATA (1534L)
+#define CPY_WRITER5_MASK_DATA_BYTE_MASK (1535L)
+/* CSU */
+#define CSU_RCP_CTRL (1536L)
+#define CSU_RCP_CTRL_ADR (1537L)
+#define CSU_RCP_CTRL_CNT (1538L)
+#define CSU_RCP_DATA (1539L)
+#define CSU_RCP_DATA_IL3_CMD (1540L)
+#define CSU_RCP_DATA_IL4_CMD (1541L)
+#define CSU_RCP_DATA_OL3_CMD (1542L)
+#define CSU_RCP_DATA_OL4_CMD (1543L)
+/* DBS */
+#define DBS_RX_AM_CTRL (1544L)
+#define DBS_RX_AM_CTRL_ADR (1545L)
+#define DBS_RX_AM_CTRL_CNT (1546L)
+#define DBS_RX_AM_DATA (1547L)
+#define DBS_RX_AM_DATA_ENABLE (1548L)
+#define DBS_RX_AM_DATA_GPA (1549L)
+#define DBS_RX_AM_DATA_HID (1550L)
+#define DBS_RX_AM_DATA_INT (1551L)
+#define DBS_RX_AM_DATA_PCKED (1552L)
+#define DBS_RX_CONTROL (1553L)
+#define DBS_RX_CONTROL_AME (1554L)
+#define DBS_RX_CONTROL_AMS (1555L)
+#define DBS_RX_CONTROL_LQ (1556L)
+#define DBS_RX_CONTROL_QE (1557L)
+#define DBS_RX_CONTROL_UWE (1558L)
+#define DBS_RX_CONTROL_UWS (1559L)
+#define DBS_RX_DR_CTRL (1560L)
+#define DBS_RX_DR_CTRL_ADR (1561L)
+#define DBS_RX_DR_CTRL_CNT (1562L)
+#define DBS_RX_DR_DATA (1563L)
+#define DBS_RX_DR_DATA_GPA (1564L)
+#define DBS_RX_DR_DATA_HDR (1565L)
+#define DBS_RX_DR_DATA_HID (1566L)
+#define DBS_RX_DR_DATA_PCKED (1567L)
+#define DBS_RX_DR_DATA_QS (1568L)
+#define DBS_RX_IDLE (1569L)
+#define DBS_RX_IDLE_BUSY (1570L)
+#define DBS_RX_IDLE_IDLE (1571L)
+#define DBS_RX_IDLE_QUEUE (1572L)
+#define DBS_RX_INIT (1573L)
+#define DBS_RX_INIT_BUSY (1574L)
+#define DBS_RX_INIT_INIT (1575L)
+#define DBS_RX_INIT_QUEUE (1576L)
+#define DBS_RX_INIT_VAL (1577L)
+#define DBS_RX_INIT_VAL_IDX (1578L)
+#define DBS_RX_INIT_VAL_PTR (1579L)
+#define DBS_RX_PTR (1580L)
+#define DBS_RX_PTR_PTR (1581L)
+#define DBS_RX_PTR_QUEUE (1582L)
+#define DBS_RX_PTR_VALID (1583L)
+#define DBS_RX_UW_CTRL (1584L)
+#define DBS_RX_UW_CTRL_ADR (1585L)
+#define DBS_RX_UW_CTRL_CNT (1586L)
+#define DBS_RX_UW_DATA (1587L)
+#define DBS_RX_UW_DATA_GPA (1588L)
+#define DBS_RX_UW_DATA_HID (1589L)
+#define DBS_RX_UW_DATA_INT (1590L)
+#define DBS_RX_UW_DATA_ISTK (1591L)
+#define DBS_RX_UW_DATA_PCKED (1592L)
+#define DBS_RX_UW_DATA_QS (1593L)
+#define DBS_RX_UW_DATA_VEC (1594L)
+#define DBS_STATUS (1595L)
+#define DBS_STATUS_OK (1596L)
+#define DBS_TX_AM_CTRL (1597L)
+#define DBS_TX_AM_CTRL_ADR (1598L)
+#define DBS_TX_AM_CTRL_CNT (1599L)
+#define DBS_TX_AM_DATA (1600L)
+#define DBS_TX_AM_DATA_ENABLE (1601L)
+#define DBS_TX_AM_DATA_GPA (1602L)
+#define DBS_TX_AM_DATA_HID (1603L)
+#define DBS_TX_AM_DATA_INT (1604L)
+#define DBS_TX_AM_DATA_PCKED (1605L)
+#define DBS_TX_CONTROL (1606L)
+#define DBS_TX_CONTROL_AME (1607L)
+#define DBS_TX_CONTROL_AMS (1608L)
+#define DBS_TX_CONTROL_LQ (1609L)
+#define DBS_TX_CONTROL_QE (1610L)
+#define DBS_TX_CONTROL_UWE (1611L)
+#define DBS_TX_CONTROL_UWS (1612L)
+#define DBS_TX_DR_CTRL (1613L)
+#define DBS_TX_DR_CTRL_ADR (1614L)
+#define DBS_TX_DR_CTRL_CNT (1615L)
+#define DBS_TX_DR_DATA (1616L)
+#define DBS_TX_DR_DATA_GPA (1617L)
+#define DBS_TX_DR_DATA_HDR (1618L)
+#define DBS_TX_DR_DATA_HID (1619L)
+#define DBS_TX_DR_DATA_PCKED (1620L)
+#define DBS_TX_DR_DATA_PORT (1621L)
+#define DBS_TX_DR_DATA_QS (1622L)
+#define DBS_TX_IDLE (1623L)
+#define DBS_TX_IDLE_BUSY (1624L)
+#define DBS_TX_IDLE_IDLE (1625L)
+#define DBS_TX_IDLE_QUEUE (1626L)
+#define DBS_TX_INIT (1627L)
+#define DBS_TX_INIT_BUSY (1628L)
+#define DBS_TX_INIT_INIT (1629L)
+#define DBS_TX_INIT_QUEUE (1630L)
+#define DBS_TX_INIT_VAL (1631L)
+#define DBS_TX_INIT_VAL_IDX (1632L)
+#define DBS_TX_INIT_VAL_PTR (1633L)
+#define DBS_TX_PTR (1634L)
+#define DBS_TX_PTR_PTR (1635L)
+#define DBS_TX_PTR_QUEUE (1636L)
+#define DBS_TX_PTR_VALID (1637L)
+#define DBS_TX_QOS_CTRL (1638L)
+#define DBS_TX_QOS_CTRL_ADR (1639L)
+#define DBS_TX_QOS_CTRL_CNT (1640L)
+#define DBS_TX_QOS_DATA (1641L)
+#define DBS_TX_QOS_DATA_BS (1642L)
+#define DBS_TX_QOS_DATA_EN (1643L)
+#define DBS_TX_QOS_DATA_IR (1644L)
+#define DBS_TX_QOS_DATA_MUL (1645L)
+#define DBS_TX_QOS_RATE (1646L)
+#define DBS_TX_QOS_RATE_DIV (1647L)
+#define DBS_TX_QOS_RATE_MUL (1648L)
+#define DBS_TX_QP_CTRL (1649L)
+#define DBS_TX_QP_CTRL_ADR (1650L)
+#define DBS_TX_QP_CTRL_CNT (1651L)
+#define DBS_TX_QP_DATA (1652L)
+#define DBS_TX_QP_DATA_VPORT (1653L)
+#define DBS_TX_UW_CTRL (1654L)
+#define DBS_TX_UW_CTRL_ADR (1655L)
+#define DBS_TX_UW_CTRL_CNT (1656L)
+#define DBS_TX_UW_DATA (1657L)
+#define DBS_TX_UW_DATA_GPA (1658L)
+#define DBS_TX_UW_DATA_HID (1659L)
+#define DBS_TX_UW_DATA_INO (1660L)
+#define DBS_TX_UW_DATA_INT (1661L)
+#define DBS_TX_UW_DATA_ISTK (1662L)
+#define DBS_TX_UW_DATA_PCKED (1663L)
+#define DBS_TX_UW_DATA_QS (1664L)
+#define DBS_TX_UW_DATA_VEC (1665L)
+/* DDP */
+#define DDP_AGING_CTRL (1666L)
+#define DDP_AGING_CTRL_AGING_RATE (1667L)
+#define DDP_AGING_CTRL_MAX_CNT (1668L)
+#define DDP_CTRL (1669L)
+#define DDP_CTRL_INIT (1670L)
+#define DDP_CTRL_INIT_DONE (1671L)
+#define DDP_RCP_CTRL (1672L)
+#define DDP_RCP_CTRL_ADR (1673L)
+#define DDP_RCP_CTRL_CNT (1674L)
+#define DDP_RCP_DATA (1675L)
+#define DDP_RCP_DATA_EN (1676L)
+#define DDP_RCP_DATA_GROUPID (1677L)
+/* EPP */
+#define EPP_QUEUE_MTU_CTRL (1755L)
+#define EPP_QUEUE_MTU_CTRL_ADR (1756L)
+#define EPP_QUEUE_MTU_CTRL_CNT (1757L)
+#define EPP_QUEUE_MTU_DATA (1758L)
+#define EPP_QUEUE_MTU_DATA_MAX_MTU (1759L)
+#define EPP_QUEUE_VPORT_CTRL (1760L)
+#define EPP_QUEUE_VPORT_CTRL_ADR (1761L)
+#define EPP_QUEUE_VPORT_CTRL_CNT (1762L)
+#define EPP_QUEUE_VPORT_DATA (1763L)
+#define EPP_QUEUE_VPORT_DATA_VPORT (1764L)
+#define EPP_RCP_CTRL (1765L)
+#define EPP_RCP_CTRL_ADR (1766L)
+#define EPP_RCP_CTRL_CNT (1767L)
+#define EPP_RCP_DATA (1768L)
+#define EPP_RCP_DATA_FIXED_18B_L2_MTU (1769L)
+#define EPP_RCP_DATA_QUEUE_MTU_EPP_EN (1770L)
+#define EPP_RCP_DATA_QUEUE_QOS_EPP_EN (1771L)
+#define EPP_RCP_DATA_SIZE_ADJUST_TXP (1772L)
+#define EPP_RCP_DATA_SIZE_ADJUST_VPORT (1773L)
+#define EPP_RCP_DATA_TX_MTU_EPP_EN (1774L)
+#define EPP_RCP_DATA_TX_QOS_EPP_EN (1775L)
+#define EPP_TXP_MTU_CTRL (1776L)
+#define EPP_TXP_MTU_CTRL_ADR (1777L)
+#define EPP_TXP_MTU_CTRL_CNT (1778L)
+#define EPP_TXP_MTU_DATA (1779L)
+#define EPP_TXP_MTU_DATA_MAX_MTU (1780L)
+#define EPP_TXP_QOS_CTRL (1781L)
+#define EPP_TXP_QOS_CTRL_ADR (1782L)
+#define EPP_TXP_QOS_CTRL_CNT (1783L)
+#define EPP_TXP_QOS_DATA (1784L)
+#define EPP_TXP_QOS_DATA_BS (1785L)
+#define EPP_TXP_QOS_DATA_EN (1786L)
+#define EPP_TXP_QOS_DATA_IR (1787L)
+#define EPP_TXP_QOS_DATA_IR_FRACTION (1788L)
+#define EPP_VPORT_QOS_CTRL (1789L)
+#define EPP_VPORT_QOS_CTRL_ADR (1790L)
+#define EPP_VPORT_QOS_CTRL_CNT (1791L)
+#define EPP_VPORT_QOS_DATA (1792L)
+#define EPP_VPORT_QOS_DATA_BS (1793L)
+#define EPP_VPORT_QOS_DATA_EN (1794L)
+#define EPP_VPORT_QOS_DATA_IR (1795L)
+#define EPP_VPORT_QOS_DATA_IR_FRACTION (1796L)
+/* EQM */
+#define EQM_CTRL (1797L)
+#define EQM_CTRL_DBG_CRC_ERR (1798L)
+#define EQM_CTRL_DBG_FORCE_ERR (1799L)
+#define EQM_CTRL_DBG_RMT_ERR (1800L)
+#define EQM_CTRL_DBG_SYNC_ERR (1801L)
+#define EQM_CTRL_ENABLE (1802L)
+#define EQM_CTRL_MODE (1803L)
+#define EQM_CTRL_PP_RST (1804L)
+#define EQM_DBG (1805L)
+#define EQM_DBG_FIFO_OF (1806L)
+#define EQM_DBG_LCL_EGS_QKA_OF (1807L)
+#define EQM_DBG_LCL_EGS_QLVL_OF (1808L)
+#define EQM_DBG_QBLK_CREDITS (1809L)
+#define EQM_STATUS (1810L)
+#define EQM_STATUS_LCL_EGS_OF_ERR (1811L)
+#define EQM_STATUS_NIF_CRC_ERR (1812L)
+#define EQM_STATUS_NIF_PP_LOOP_LCK (1813L)
+#define EQM_STATUS_NIF_RX_OF_ERR (1814L)
+#define EQM_STATUS_NIF_SYNC_ERR (1815L)
+#define EQM_STATUS_QM_CRC_ERR (1816L)
+#define EQM_STATUS_RMT_EGS_OF_ERR (1817L)
+#define EQM_STATUS_RMT_ERR (1818L)
+#define EQM_STATUS_RMT_IGS_OF_ERR (1819L)
+/* FHM */
+#define FHM_BACK_PRESSURE (1820L)
+#define FHM_BACK_PRESSURE_NIF (1821L)
+#define FHM_BACK_PRESSURE_RMC (1822L)
+#define FHM_BACK_PRESSURE_RMC_S (1823L)
+#define FHM_CRC_ERROR_NIF (1824L)
+#define FHM_CRC_ERROR_NIF_CNT (1825L)
+#define FHM_CRC_ERROR_SDC (1826L)
+#define FHM_CRC_ERROR_SDC_CNT (1827L)
+#define FHM_CTRL (1828L)
+#define FHM_CTRL_CNT_CLR (1829L)
+#define FHM_CTRL_ENABLE (1830L)
+#define FHM_CTRL_MODE (1831L)
+#define FHM_DEBUG_CRC (1832L)
+#define FHM_DEBUG_CRC_FORCE_ERROR (1833L)
+#define FHM_DEBUG_SDRAM_SIZE (1834L)
+#define FHM_DEBUG_SDRAM_SIZE_MASK (1835L)
+#define FHM_FILL_LEVEL (1836L)
+#define FHM_FILL_LEVEL_CELLS (1837L)
+#define FHM_MAC_MICRO_DROP (1838L)
+#define FHM_MAC_MICRO_DROP_CNT (1839L)
+#define FHM_MAX_FILL_LEVEL (1840L)
+#define FHM_MAX_FILL_LEVEL_CELLS (1841L)
+#define FHM_PKT_DROP (1842L)
+#define FHM_PKT_DROP_CNT (1843L)
+#define FHM_PKT_DROP_BYTES (1844L)
+#define FHM_PKT_DROP_BYTES_CNT (1845L)
+/* FLM */
+#define FLM_BUF_CTRL (1855L)
+#define FLM_BUF_CTRL_INF_AVAIL (1856L)
+#define FLM_BUF_CTRL_LRN_FREE (1857L)
+#define FLM_BUF_CTRL_STA_AVAIL (1858L)
+#define FLM_CONTROL (1859L)
+#define FLM_CONTROL_CRCRD (1860L)
+#define FLM_CONTROL_CRCWR (1861L)
+#define FLM_CONTROL_EAB (1862L)
+#define FLM_CONTROL_ENABLE (1863L)
+#define FLM_CONTROL_INIT (1864L)
+#define FLM_CONTROL_LDS (1865L)
+#define FLM_CONTROL_LFS (1866L)
+#define FLM_CONTROL_LIS (1867L)
+#define FLM_CONTROL_PDS (1868L)
+#define FLM_CONTROL_PIS (1869L)
+#define FLM_CONTROL_RBL (1870L)
+#define FLM_CONTROL_RDS (1871L)
+#define FLM_CONTROL_RIS (1872L)
+#define FLM_CONTROL_SPLIT_SDRAM_USAGE (1873L)
+#define FLM_CONTROL_UDS (1874L)
+#define FLM_CONTROL_UIS (1875L)
+#define FLM_CONTROL_WPD (1876L)
+#define FLM_INF_DATA (1877L)
+#define FLM_INF_DATA_BYTES (1878L)
+#define FLM_INF_DATA_BYT_A (1879L)
+#define FLM_INF_DATA_BYT_B (1880L)
+#define FLM_INF_DATA_CAUSE (1881L)
+#define FLM_INF_DATA_EOR (1882L)
+#define FLM_INF_DATA_ID (1883L)
+#define FLM_INF_DATA_PACKETS (1884L)
+#define FLM_INF_DATA_PCK_A (1885L)
+#define FLM_INF_DATA_PCK_B (1886L)
+#define FLM_INF_DATA_RTX_A (1887L)
+#define FLM_INF_DATA_RTX_B (1888L)
+#define FLM_INF_DATA_TCP_A (1889L)
+#define FLM_INF_DATA_TCP_B (1890L)
+#define FLM_INF_DATA_TS (1891L)
+#define FLM_LOAD_APS (1892L)
+#define FLM_LOAD_APS_APS (1893L)
+#define FLM_LOAD_BIN (1894L)
+#define FLM_LOAD_BIN_BIN (1895L)
+#define FLM_LOAD_LPS (1896L)
+#define FLM_LOAD_LPS_LPS (1897L)
+#define FLM_LOAD_PPS (1898L)
+#define FLM_LOAD_PPS_PPS (1899L)
+#define FLM_LRN_CTRL (1900L)
+#define FLM_LRN_CTRL_FREE (1901L)
+#define FLM_LRN_DATA (1902L)
+#define FLM_LRN_DATA_ADJ (1903L)
+#define FLM_LRN_DATA_COLOR (1904L)
+#define FLM_LRN_DATA_DSCP (1905L)
+#define FLM_LRN_DATA_ENT (1906L)
+#define FLM_LRN_DATA_EOR (1907L)
+#define FLM_LRN_DATA_FILL (1908L)
+#define FLM_LRN_DATA_FT (1909L)
+#define FLM_LRN_DATA_FT_MBR (1910L)
+#define FLM_LRN_DATA_FT_MISS (1911L)
+#define FLM_LRN_DATA_GFI (1912L)
+#define FLM_LRN_DATA_ID (1913L)
+#define FLM_LRN_DATA_KID (1914L)
+#define FLM_LRN_DATA_MBR_ID1 (1915L)
+#define FLM_LRN_DATA_MBR_ID2 (1916L)
+#define FLM_LRN_DATA_MBR_ID3 (1917L)
+#define FLM_LRN_DATA_MBR_ID4 (1918L)
+#define FLM_LRN_DATA_NAT_EN (1919L)
+#define FLM_LRN_DATA_NAT_IP (1920L)
+#define FLM_LRN_DATA_NAT_PORT (1921L)
+#define FLM_LRN_DATA_OP (1922L)
+#define FLM_LRN_DATA_PRIO (1923L)
+#define FLM_LRN_DATA_PROT (1924L)
+#define FLM_LRN_DATA_QFI (1925L)
+#define FLM_LRN_DATA_QW0 (1926L)
+#define FLM_LRN_DATA_QW4 (1927L)
+#define FLM_LRN_DATA_RATE (1928L)
+#define FLM_LRN_DATA_RQI (1929L)
+#define FLM_LRN_DATA_SIZE (1930L)
+#define FLM_LRN_DATA_STAT_PROF (1931L)
+#define FLM_LRN_DATA_SW8 (1932L)
+#define FLM_LRN_DATA_SW9 (1933L)
+#define FLM_LRN_DATA_TAU (1934L)
+#define FLM_LRN_DATA_TEID (1935L)
+#define FLM_LRN_DATA_TTL (1936L)
+#define FLM_LRN_DATA_VOL_IDX (1937L)
+#define FLM_PRIO (1938L)
+#define FLM_PRIO_FT0 (1939L)
+#define FLM_PRIO_FT1 (1940L)
+#define FLM_PRIO_FT2 (1941L)
+#define FLM_PRIO_FT3 (1942L)
+#define FLM_PRIO_LIMIT0 (1943L)
+#define FLM_PRIO_LIMIT1 (1944L)
+#define FLM_PRIO_LIMIT2 (1945L)
+#define FLM_PRIO_LIMIT3 (1946L)
+#define FLM_PST_CTRL (1947L)
+#define FLM_PST_CTRL_ADR (1948L)
+#define FLM_PST_CTRL_CNT (1949L)
+#define FLM_PST_DATA (1950L)
+#define FLM_PST_DATA_BP (1951L)
+#define FLM_PST_DATA_PP (1952L)
+#define FLM_PST_DATA_TP (1953L)
+#define FLM_RCP_CTRL (1954L)
+#define FLM_RCP_CTRL_ADR (1955L)
+#define FLM_RCP_CTRL_CNT (1956L)
+#define FLM_RCP_DATA (1957L)
+#define FLM_RCP_DATA_A (1958L)
+#define FLM_RCP_DATA_AUTO_IPV4_MASK (1959L)
+#define FLM_RCP_DATA_B (1960L)
+#define FLM_RCP_DATA_BYT_DYN (1961L)
+#define FLM_RCP_DATA_BYT_OFS (1962L)
+#define FLM_RCP_DATA_IPN (1963L)
+#define FLM_RCP_DATA_ITF (1964L)
+#define FLM_RCP_DATA_KID (1965L)
+#define FLM_RCP_DATA_LOOKUP (1966L)
+#define FLM_RCP_DATA_MASK (1967L)
+#define FLM_RCP_DATA_OPN (1968L)
+#define FLM_RCP_DATA_QW0_DYN (1969L)
+#define FLM_RCP_DATA_QW0_OFS (1970L)
+#define FLM_RCP_DATA_QW0_SEL (1971L)
+#define FLM_RCP_DATA_QW4_DYN (1972L)
+#define FLM_RCP_DATA_QW4_OFS (1973L)
+#define FLM_RCP_DATA_SW8_DYN (1974L)
+#define FLM_RCP_DATA_SW8_OFS (1975L)
+#define FLM_RCP_DATA_SW8_SEL (1976L)
+#define FLM_RCP_DATA_SW9_DYN (1977L)
+#define FLM_RCP_DATA_SW9_OFS (1978L)
+#define FLM_RCP_DATA_TXPLM (1979L)
+#define FLM_SCRUB (1980L)
+#define FLM_SCRUB_I (1981L)
+#define FLM_STATUS (1982L)
+#define FLM_STATUS_CALIBDONE (1983L)
+#define FLM_STATUS_CRCERR (1984L)
+#define FLM_STATUS_CRITICAL (1985L)
+#define FLM_STATUS_EFT_BP (1986L)
+#define FLM_STATUS_EFT_EVICT_BP (1987L)
+#define FLM_STATUS_IDLE (1988L)
+#define FLM_STATUS_INITDONE (1989L)
+#define FLM_STATUS_PANIC (1990L)
+#define FLM_STAT_AUL_DONE (1991L)
+#define FLM_STAT_AUL_DONE_CNT (1992L)
+#define FLM_STAT_AUL_FAIL (1993L)
+#define FLM_STAT_AUL_FAIL_CNT (1994L)
+#define FLM_STAT_AUL_IGNORE (1995L)
+#define FLM_STAT_AUL_IGNORE_CNT (1996L)
+#define FLM_STAT_CSH_HIT (1997L)
+#define FLM_STAT_CSH_HIT_CNT (1998L)
+#define FLM_STAT_CSH_MISS (1999L)
+#define FLM_STAT_CSH_MISS_CNT (2000L)
+#define FLM_STAT_CSH_UNH (2001L)
+#define FLM_STAT_CSH_UNH_CNT (2002L)
+#define FLM_STAT_CUC_MOVE (2003L)
+#define FLM_STAT_CUC_MOVE_CNT (2004L)
+#define FLM_STAT_CUC_START (2005L)
+#define FLM_STAT_CUC_START_CNT (2006L)
+#define FLM_STAT_FLOWS (2007L)
+#define FLM_STAT_FLOWS_CNT (2008L)
+#define FLM_STAT_INF_DONE (2009L)
+#define FLM_STAT_INF_DONE_CNT (2010L)
+#define FLM_STAT_INF_SKIP (2011L)
+#define FLM_STAT_INF_SKIP_CNT (2012L)
+#define FLM_STAT_LRN_DONE (2013L)
+#define FLM_STAT_LRN_DONE_CNT (2014L)
+#define FLM_STAT_LRN_FAIL (2015L)
+#define FLM_STAT_LRN_FAIL_CNT (2016L)
+#define FLM_STAT_LRN_IGNORE (2017L)
+#define FLM_STAT_LRN_IGNORE_CNT (2018L)
+#define FLM_STAT_PCK_DIS (2019L)
+#define FLM_STAT_PCK_DIS_CNT (2020L)
+#define FLM_STAT_PCK_HIT (2021L)
+#define FLM_STAT_PCK_HIT_CNT (2022L)
+#define FLM_STAT_PCK_MISS (2023L)
+#define FLM_STAT_PCK_MISS_CNT (2024L)
+#define FLM_STAT_PCK_UNH (2025L)
+#define FLM_STAT_PCK_UNH_CNT (2026L)
+#define FLM_STAT_PRB_DONE (2027L)
+#define FLM_STAT_PRB_DONE_CNT (2028L)
+#define FLM_STAT_PRB_IGNORE (2029L)
+#define FLM_STAT_PRB_IGNORE_CNT (2030L)
+#define FLM_STAT_REL_DONE (2031L)
+#define FLM_STAT_REL_DONE_CNT (2032L)
+#define FLM_STAT_REL_IGNORE (2033L)
+#define FLM_STAT_REL_IGNORE_CNT (2034L)
+#define FLM_STAT_STA_DONE (2035L)
+#define FLM_STAT_STA_DONE_CNT (2036L)
+#define FLM_STAT_TUL_DONE (2037L)
+#define FLM_STAT_TUL_DONE_CNT (2038L)
+#define FLM_STAT_UNL_DONE (2039L)
+#define FLM_STAT_UNL_DONE_CNT (2040L)
+#define FLM_STAT_UNL_IGNORE (2041L)
+#define FLM_STAT_UNL_IGNORE_CNT (2042L)
+#define FLM_STA_DATA (2043L)
+#define FLM_STA_DATA_EOR (2044L)
+#define FLM_STA_DATA_ID (2045L)
+#define FLM_STA_DATA_LDS (2046L)
+#define FLM_STA_DATA_LFS (2047L)
+#define FLM_STA_DATA_LIS (2048L)
+#define FLM_STA_DATA_PDS (2049L)
+#define FLM_STA_DATA_PIS (2050L)
+#define FLM_STA_DATA_RDS (2051L)
+#define FLM_STA_DATA_RIS (2052L)
+#define FLM_STA_DATA_UDS (2053L)
+#define FLM_STA_DATA_UIS (2054L)
+#define FLM_TIMEOUT (2055L)
+#define FLM_TIMEOUT_T (2056L)
+#define FLM_TRSWIN (2057L)
+#define FLM_TRSWIN_S (2058L)
+#define FLM_TRTWIN (2059L)
+#define FLM_TRTWIN_T (2060L)
+/* GFG */
+#define GFG_BURSTSIZE0 (2061L)
+#define GFG_BURSTSIZE0_VAL (2062L)
+#define GFG_BURSTSIZE1 (2063L)
+#define GFG_BURSTSIZE1_VAL (2064L)
+#define GFG_BURSTSIZE2 (2065L)
+#define GFG_BURSTSIZE2_VAL (2066L)
+#define GFG_BURSTSIZE3 (2067L)
+#define GFG_BURSTSIZE3_VAL (2068L)
+#define GFG_BURSTSIZE4 (2069L)
+#define GFG_BURSTSIZE4_VAL (2070L)
+#define GFG_BURSTSIZE5 (2071L)
+#define GFG_BURSTSIZE5_VAL (2072L)
+#define GFG_BURSTSIZE6 (2073L)
+#define GFG_BURSTSIZE6_VAL (2074L)
+#define GFG_BURSTSIZE7 (2075L)
+#define GFG_BURSTSIZE7_VAL (2076L)
+#define GFG_CTRL0 (2077L)
+#define GFG_CTRL0_ENABLE (2078L)
+#define GFG_CTRL0_MODE (2079L)
+#define GFG_CTRL0_PRBS_EN (2080L)
+#define GFG_CTRL0_SIZE (2081L)
+#define GFG_CTRL1 (2082L)
+#define GFG_CTRL1_ENABLE (2083L)
+#define GFG_CTRL1_MODE (2084L)
+#define GFG_CTRL1_PRBS_EN (2085L)
+#define GFG_CTRL1_SIZE (2086L)
+#define GFG_CTRL2 (2087L)
+#define GFG_CTRL2_ENABLE (2088L)
+#define GFG_CTRL2_MODE (2089L)
+#define GFG_CTRL2_PRBS_EN (2090L)
+#define GFG_CTRL2_SIZE (2091L)
+#define GFG_CTRL3 (2092L)
+#define GFG_CTRL3_ENABLE (2093L)
+#define GFG_CTRL3_MODE (2094L)
+#define GFG_CTRL3_PRBS_EN (2095L)
+#define GFG_CTRL3_SIZE (2096L)
+#define GFG_CTRL4 (2097L)
+#define GFG_CTRL4_ENABLE (2098L)
+#define GFG_CTRL4_MODE (2099L)
+#define GFG_CTRL4_PRBS_EN (2100L)
+#define GFG_CTRL4_SIZE (2101L)
+#define GFG_CTRL5 (2102L)
+#define GFG_CTRL5_ENABLE (2103L)
+#define GFG_CTRL5_MODE (2104L)
+#define GFG_CTRL5_PRBS_EN (2105L)
+#define GFG_CTRL5_SIZE (2106L)
+#define GFG_CTRL6 (2107L)
+#define GFG_CTRL6_ENABLE (2108L)
+#define GFG_CTRL6_MODE (2109L)
+#define GFG_CTRL6_PRBS_EN (2110L)
+#define GFG_CTRL6_SIZE (2111L)
+#define GFG_CTRL7 (2112L)
+#define GFG_CTRL7_ENABLE (2113L)
+#define GFG_CTRL7_MODE (2114L)
+#define GFG_CTRL7_PRBS_EN (2115L)
+#define GFG_CTRL7_SIZE (2116L)
+#define GFG_RUN0 (2117L)
+#define GFG_RUN0_RUN (2118L)
+#define GFG_RUN1 (2119L)
+#define GFG_RUN1_RUN (2120L)
+#define GFG_RUN2 (2121L)
+#define GFG_RUN2_RUN (2122L)
+#define GFG_RUN3 (2123L)
+#define GFG_RUN3_RUN (2124L)
+#define GFG_RUN4 (2125L)
+#define GFG_RUN4_RUN (2126L)
+#define GFG_RUN5 (2127L)
+#define GFG_RUN5_RUN (2128L)
+#define GFG_RUN6 (2129L)
+#define GFG_RUN6_RUN (2130L)
+#define GFG_RUN7 (2131L)
+#define GFG_RUN7_RUN (2132L)
+#define GFG_SIZEMASK0 (2133L)
+#define GFG_SIZEMASK0_VAL (2134L)
+#define GFG_SIZEMASK1 (2135L)
+#define GFG_SIZEMASK1_VAL (2136L)
+#define GFG_SIZEMASK2 (2137L)
+#define GFG_SIZEMASK2_VAL (2138L)
+#define GFG_SIZEMASK3 (2139L)
+#define GFG_SIZEMASK3_VAL (2140L)
+#define GFG_SIZEMASK4 (2141L)
+#define GFG_SIZEMASK4_VAL (2142L)
+#define GFG_SIZEMASK5 (2143L)
+#define GFG_SIZEMASK5_VAL (2144L)
+#define GFG_SIZEMASK6 (2145L)
+#define GFG_SIZEMASK6_VAL (2146L)
+#define GFG_SIZEMASK7 (2147L)
+#define GFG_SIZEMASK7_VAL (2148L)
+#define GFG_STREAMID0 (2149L)
+#define GFG_STREAMID0_VAL (2150L)
+#define GFG_STREAMID1 (2151L)
+#define GFG_STREAMID1_VAL (2152L)
+#define GFG_STREAMID2 (2153L)
+#define GFG_STREAMID2_VAL (2154L)
+#define GFG_STREAMID3 (2155L)
+#define GFG_STREAMID3_VAL (2156L)
+#define GFG_STREAMID4 (2157L)
+#define GFG_STREAMID4_VAL (2158L)
+#define GFG_STREAMID5 (2159L)
+#define GFG_STREAMID5_VAL (2160L)
+#define GFG_STREAMID6 (2161L)
+#define GFG_STREAMID6_VAL (2162L)
+#define GFG_STREAMID7 (2163L)
+#define GFG_STREAMID7_VAL (2164L)
+/* GMF */
+#define GMF_CTRL (2165L)
+#define GMF_CTRL_ENABLE (2166L)
+#define GMF_CTRL_FCS_ALWAYS (2167L)
+#define GMF_CTRL_IFG_AUTO_ADJUST_ENABLE (2168L)
+#define GMF_CTRL_IFG_ENABLE (2169L)
+#define GMF_CTRL_IFG_TX_NOW_ALWAYS (2170L)
+#define GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE (2171L)
+#define GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK (2172L)
+#define GMF_CTRL_IFG_TX_ON_TS_ALWAYS (2173L)
+#define GMF_CTRL_TS_INJECT_ALWAYS (2174L)
+#define GMF_CTRL_TS_INJECT_DUAL_STEP (2175L)
+#define GMF_DEBUG_LANE_MARKER (2176L)
+#define GMF_DEBUG_LANE_MARKER_COMPENSATION (2177L)
+#define GMF_IFG_MAX_ADJUST_SLACK (2178L)
+#define GMF_IFG_MAX_ADJUST_SLACK_SLACK (2179L)
+#define GMF_IFG_SET_CLOCK_DELTA (2180L)
+#define GMF_IFG_SET_CLOCK_DELTA_DELTA (2181L)
+#define GMF_IFG_SET_CLOCK_DELTA_ADJUST (2182L)
+#define GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA (2183L)
+#define GMF_IFG_TX_NOW_ON_TS (2184L)
+#define GMF_IFG_TX_NOW_ON_TS_TS (2185L)
+#define GMF_SPEED (2186L)
+#define GMF_SPEED_IFG_SPEED (2187L)
+#define GMF_STAT (2188L)
+#define GMF_STAT_CTRL_EMPTY (2189L)
+#define GMF_STAT_DATA_CTRL_EMPTY (2190L)
+#define GMF_STAT_SB_EMPTY (2191L)
+#define GMF_STAT_CTRL (2192L)
+#define GMF_STAT_CTRL_FILL_LEVEL (2193L)
+#define GMF_STAT_DATA0 (2194L)
+#define GMF_STAT_DATA0_EMPTY (2195L)
+#define GMF_STAT_DATA1 (2196L)
+#define GMF_STAT_DATA1_EMPTY (2197L)
+#define GMF_STAT_DATA_BUFFER (2198L)
+#define GMF_STAT_DATA_BUFFER_FREE (2199L)
+#define GMF_STAT_DATA_BUFFER_USED (2200L)
+#define GMF_STAT_MAX_DELAYED_PKT (2201L)
+#define GMF_STAT_MAX_DELAYED_PKT_NS (2202L)
+#define GMF_STAT_NEXT_PKT (2203L)
+#define GMF_STAT_NEXT_PKT_NS (2204L)
+#define GMF_STAT_STICKY (2205L)
+#define GMF_STAT_STICKY_DATA_UNDERFLOWED (2206L)
+#define GMF_STAT_STICKY_IFG_ADJUSTED (2207L)
+#define GMF_TS_INJECT (2208L)
+#define GMF_TS_INJECT_OFFSET (2209L)
+#define GMF_TS_INJECT_POS (2210L)
+/* GPIO_PHY */
+#define GPIO_PHY_CFG (2211L)
+#define GPIO_PHY_CFG_E_PORT0_RXLOS (2212L)
+#define GPIO_PHY_CFG_E_PORT1_RXLOS (2213L)
+#define GPIO_PHY_CFG_PORT0_INT_B (2214L)
+#define GPIO_PHY_CFG_PORT0_LPMODE (2215L)
+#define GPIO_PHY_CFG_PORT0_MODPRS_B (2216L)
+#define GPIO_PHY_CFG_PORT0_PLL_INTR (2217L)
+#define GPIO_PHY_CFG_PORT0_RESET_B (2218L)
+#define GPIO_PHY_CFG_PORT1_INT_B (2219L)
+#define GPIO_PHY_CFG_PORT1_LPMODE (2220L)
+#define GPIO_PHY_CFG_PORT1_MODPRS_B (2221L)
+#define GPIO_PHY_CFG_PORT1_PLL_INTR (2222L)
+#define GPIO_PHY_CFG_PORT1_RESET_B (2223L)
+#define GPIO_PHY_GPIO (2224L)
+#define GPIO_PHY_GPIO_E_PORT0_RXLOS (2225L)
+#define GPIO_PHY_GPIO_E_PORT1_RXLOS (2226L)
+#define GPIO_PHY_GPIO_PORT0_INT_B (2227L)
+#define GPIO_PHY_GPIO_PORT0_LPMODE (2228L)
+#define GPIO_PHY_GPIO_PORT0_MODPRS_B (2229L)
+#define GPIO_PHY_GPIO_PORT0_PLL_INTR (2230L)
+#define GPIO_PHY_GPIO_PORT0_RESET_B (2231L)
+#define GPIO_PHY_GPIO_PORT1_INT_B (2232L)
+#define GPIO_PHY_GPIO_PORT1_LPMODE (2233L)
+#define GPIO_PHY_GPIO_PORT1_MODPRS_B (2234L)
+#define GPIO_PHY_GPIO_PORT1_PLL_INTR (2235L)
+#define GPIO_PHY_GPIO_PORT1_RESET_B (2236L)
+/* GPIO_PHY_PORTS */
+#define GPIO_PHY_PORTS_CFG (2237L)
+#define GPIO_PHY_PORTS_CFG_E_PORT0_RXLOS (2238L)
+#define GPIO_PHY_PORTS_CFG_E_PORT0_TXDISABLE (2239L)
+#define GPIO_PHY_PORTS_CFG_E_PORT0_TXFAULT (2240L)
+#define GPIO_PHY_PORTS_CFG_E_PORT1_RXLOS (2241L)
+#define GPIO_PHY_PORTS_CFG_E_PORT1_TXDISABLE (2242L)
+#define GPIO_PHY_PORTS_CFG_E_PORT1_TXFAULT (2243L)
+#define GPIO_PHY_PORTS_CFG_E_PORT2_RXLOS (2244L)
+#define GPIO_PHY_PORTS_CFG_E_PORT2_TXDISABLE (2245L)
+#define GPIO_PHY_PORTS_CFG_E_PORT2_TXFAULT (2246L)
+#define GPIO_PHY_PORTS_CFG_E_PORT3_RXLOS (2247L)
+#define GPIO_PHY_PORTS_CFG_E_PORT3_TXDISABLE (2248L)
+#define GPIO_PHY_PORTS_CFG_E_PORT3_TXFAULT (2249L)
+#define GPIO_PHY_PORTS_CFG_E_PORT4_RXLOS (2250L)
+#define GPIO_PHY_PORTS_CFG_E_PORT4_TXDISABLE (2251L)
+#define GPIO_PHY_PORTS_CFG_E_PORT4_TXFAULT (2252L)
+#define GPIO_PHY_PORTS_CFG_E_PORT5_RXLOS (2253L)
+#define GPIO_PHY_PORTS_CFG_E_PORT5_TXDISABLE (2254L)
+#define GPIO_PHY_PORTS_CFG_E_PORT5_TXFAULT (2255L)
+#define GPIO_PHY_PORTS_CFG_E_PORT6_RXLOS (2256L)
+#define GPIO_PHY_PORTS_CFG_E_PORT6_TXDISABLE (2257L)
+#define GPIO_PHY_PORTS_CFG_E_PORT6_TXFAULT (2258L)
+#define GPIO_PHY_PORTS_CFG_E_PORT7_RXLOS (2259L)
+#define GPIO_PHY_PORTS_CFG_E_PORT7_TXDISABLE (2260L)
+#define GPIO_PHY_PORTS_CFG_E_PORT7_TXFAULT (2261L)
+#define GPIO_PHY_PORTS_GPIO (2262L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT0_RXLOS (2263L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT0_TXDISABLE (2264L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT0_TXFAULT (2265L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT1_RXLOS (2266L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT1_TXDISABLE (2267L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT1_TXFAULT (2268L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT2_RXLOS (2269L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT2_TXDISABLE (2270L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT2_TXFAULT (2271L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT3_RXLOS (2272L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT3_TXDISABLE (2273L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT3_TXFAULT (2274L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT4_RXLOS (2275L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT4_TXDISABLE (2276L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT4_TXFAULT (2277L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT5_RXLOS (2278L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT5_TXDISABLE (2279L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT5_TXFAULT (2280L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT6_RXLOS (2281L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT6_TXDISABLE (2282L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT6_TXFAULT (2283L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT7_RXLOS (2284L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT7_TXDISABLE (2285L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT7_TXFAULT (2286L)
+/* GPIO_SFPP */
+#define GPIO_SFPP_CFG (2287L)
+#define GPIO_SFPP_CFG_ABS (2288L)
+#define GPIO_SFPP_CFG_RS (2289L)
+#define GPIO_SFPP_CFG_RXLOS (2290L)
+#define GPIO_SFPP_CFG_TXDISABLE (2291L)
+#define GPIO_SFPP_CFG_TXFAULT (2292L)
+#define GPIO_SFPP_GPIO (2293L)
+#define GPIO_SFPP_GPIO_ABS (2294L)
+#define GPIO_SFPP_GPIO_RS (2295L)
+#define GPIO_SFPP_GPIO_RXLOS (2296L)
+#define GPIO_SFPP_GPIO_TXDISABLE (2297L)
+#define GPIO_SFPP_GPIO_TXFAULT (2298L)
+/* HFU */
+#define HFU_RCP_CTRL (2381L)
+#define HFU_RCP_CTRL_ADR (2382L)
+#define HFU_RCP_CTRL_CNT (2383L)
+#define HFU_RCP_DATA (2384L)
+#define HFU_RCP_DATA_CSINF (2385L)
+#define HFU_RCP_DATA_IL3OFS (2386L)
+#define HFU_RCP_DATA_IL4OFS (2387L)
+#define HFU_RCP_DATA_L3FRAG (2388L)
+#define HFU_RCP_DATA_L3PRT (2389L)
+#define HFU_RCP_DATA_L4PRT (2390L)
+#define HFU_RCP_DATA_LEN_A_ADD_DYN (2391L)
+#define HFU_RCP_DATA_LEN_A_ADD_OFS (2392L)
+#define HFU_RCP_DATA_LEN_A_OL4LEN (2393L)
+#define HFU_RCP_DATA_LEN_A_POS_DYN (2394L)
+#define HFU_RCP_DATA_LEN_A_POS_OFS (2395L)
+#define HFU_RCP_DATA_LEN_A_SUB_DYN (2396L)
+#define HFU_RCP_DATA_LEN_A_WR (2397L)
+#define HFU_RCP_DATA_LEN_B_ADD_DYN (2398L)
+#define HFU_RCP_DATA_LEN_B_ADD_OFS (2399L)
+#define HFU_RCP_DATA_LEN_B_POS_DYN (2400L)
+#define HFU_RCP_DATA_LEN_B_POS_OFS (2401L)
+#define HFU_RCP_DATA_LEN_B_SUB_DYN (2402L)
+#define HFU_RCP_DATA_LEN_B_WR (2403L)
+#define HFU_RCP_DATA_LEN_C_ADD_DYN (2404L)
+#define HFU_RCP_DATA_LEN_C_ADD_OFS (2405L)
+#define HFU_RCP_DATA_LEN_C_POS_DYN (2406L)
+#define HFU_RCP_DATA_LEN_C_POS_OFS (2407L)
+#define HFU_RCP_DATA_LEN_C_SUB_DYN (2408L)
+#define HFU_RCP_DATA_LEN_C_WR (2409L)
+#define HFU_RCP_DATA_OL3OFS (2410L)
+#define HFU_RCP_DATA_OL4OFS (2411L)
+#define HFU_RCP_DATA_TTL_POS_DYN (2412L)
+#define HFU_RCP_DATA_TTL_POS_OFS (2413L)
+#define HFU_RCP_DATA_TTL_WR (2414L)
+#define HFU_RCP_DATA_TUNNEL (2415L)
+/* HIF */
+#define HIF_BUILD_TIME (2416L)
+#define HIF_BUILD_TIME_TIME (2417L)
+#define HIF_CONFIG (2418L)
+#define HIF_CONFIG_EXT_TAG (2419L)
+#define HIF_CONFIG_MAX_READ (2420L)
+#define HIF_CONFIG_MAX_TLP (2421L)
+#define HIF_CONTROL (2422L)
+#define HIF_CONTROL_BLESSED (2423L)
+#define HIF_CONTROL_WRAW (2424L)
+#define HIF_PROD_ID_EX (2425L)
+#define HIF_PROD_ID_EX_LAYOUT (2426L)
+#define HIF_PROD_ID_EX_LAYOUT_VERSION (2427L)
+#define HIF_PROD_ID_EX_RESERVED (2428L)
+#define HIF_PROD_ID_EXT (2429L)
+#define HIF_PROD_ID_EXT_LAYOUT (2430L)
+#define HIF_PROD_ID_EXT_LAYOUT_VERSION (2431L)
+#define HIF_PROD_ID_EXT_RESERVED (2432L)
+#define HIF_PROD_ID_LSB (2433L)
+#define HIF_PROD_ID_LSB_GROUP_ID (2434L)
+#define HIF_PROD_ID_LSB_REV_ID (2435L)
+#define HIF_PROD_ID_LSB_VER_ID (2436L)
+#define HIF_PROD_ID_MSB (2437L)
+#define HIF_PROD_ID_MSB_BUILD_NO (2438L)
+#define HIF_PROD_ID_MSB_PATCH_NO (2439L)
+#define HIF_PROD_ID_MSB_TYPE_ID (2440L)
+#define HIF_SAMPLE_TIME (2441L)
+#define HIF_SAMPLE_TIME_SAMPLE_TIME (2442L)
+#define HIF_STATUS (2443L)
+#define HIF_STATUS_RD_ERR (2444L)
+#define HIF_STATUS_TAGS_IN_USE (2445L)
+#define HIF_STATUS_WR_ERR (2446L)
+#define HIF_STAT_CTRL (2447L)
+#define HIF_STAT_CTRL_STAT_ENA (2448L)
+#define HIF_STAT_CTRL_STAT_REQ (2449L)
+#define HIF_STAT_REFCLK (2450L)
+#define HIF_STAT_REFCLK_REFCLK250 (2451L)
+#define HIF_STAT_RX (2452L)
+#define HIF_STAT_RX_COUNTER (2453L)
+#define HIF_STAT_TX (2454L)
+#define HIF_STAT_TX_COUNTER (2455L)
+#define HIF_TEST0 (2456L)
+#define HIF_TEST0_DATA (2457L)
+#define HIF_TEST1 (2458L)
+#define HIF_TEST1_DATA (2459L)
+#define HIF_TEST2 (2460L)
+#define HIF_TEST2_DATA (2461L)
+#define HIF_TEST3 (2462L)
+#define HIF_TEST3_DATA (2463L)
+#define HIF_UUID0 (2464L)
+#define HIF_UUID0_UUID0 (2465L)
+#define HIF_UUID1 (2466L)
+#define HIF_UUID1_UUID1 (2467L)
+#define HIF_UUID2 (2468L)
+#define HIF_UUID2_UUID2 (2469L)
+#define HIF_UUID3 (2470L)
+#define HIF_UUID3_UUID3 (2471L)
+/* HSH */
+#define HSH_RCP_CTRL (2472L)
+#define HSH_RCP_CTRL_ADR (2473L)
+#define HSH_RCP_CTRL_CNT (2474L)
+#define HSH_RCP_DATA (2475L)
+#define HSH_RCP_DATA_AUTO_IPV4_MASK (2476L)
+#define HSH_RCP_DATA_HSH_TYPE (2477L)
+#define HSH_RCP_DATA_HSH_VALID (2478L)
+#define HSH_RCP_DATA_K (2479L)
+#define HSH_RCP_DATA_LOAD_DIST_TYPE (2480L)
+#define HSH_RCP_DATA_MAC_PORT_MASK (2481L)
+#define HSH_RCP_DATA_P_MASK (2482L)
+#define HSH_RCP_DATA_QW0_OFS (2483L)
+#define HSH_RCP_DATA_QW0_PE (2484L)
+#define HSH_RCP_DATA_QW4_OFS (2485L)
+#define HSH_RCP_DATA_QW4_PE (2486L)
+#define HSH_RCP_DATA_SEED (2487L)
+#define HSH_RCP_DATA_SORT (2488L)
+#define HSH_RCP_DATA_TNL_P (2489L)
+#define HSH_RCP_DATA_TOEPLITZ (2490L)
+#define HSH_RCP_DATA_W8_OFS (2491L)
+#define HSH_RCP_DATA_W8_PE (2492L)
+#define HSH_RCP_DATA_W8_SORT (2493L)
+#define HSH_RCP_DATA_W9_OFS (2494L)
+#define HSH_RCP_DATA_W9_P (2495L)
+#define HSH_RCP_DATA_W9_PE (2496L)
+#define HSH_RCP_DATA_W9_SORT (2497L)
+#define HSH_RCP_DATA_WORD_MASK (2498L)
+/* HST */
+#define HST_RCP_CTRL (2499L)
+#define HST_RCP_CTRL_ADR (2500L)
+#define HST_RCP_CTRL_CNT (2501L)
+#define HST_RCP_DATA (2502L)
+#define HST_RCP_DATA_END_DYN (2503L)
+#define HST_RCP_DATA_END_OFS (2504L)
+#define HST_RCP_DATA_MODIF0_CMD (2505L)
+#define HST_RCP_DATA_MODIF0_DYN (2506L)
+#define HST_RCP_DATA_MODIF0_OFS (2507L)
+#define HST_RCP_DATA_MODIF0_VALUE (2508L)
+#define HST_RCP_DATA_MODIF1_CMD (2509L)
+#define HST_RCP_DATA_MODIF1_DYN (2510L)
+#define HST_RCP_DATA_MODIF1_OFS (2511L)
+#define HST_RCP_DATA_MODIF1_VALUE (2512L)
+#define HST_RCP_DATA_MODIF2_CMD (2513L)
+#define HST_RCP_DATA_MODIF2_DYN (2514L)
+#define HST_RCP_DATA_MODIF2_OFS (2515L)
+#define HST_RCP_DATA_MODIF2_VALUE (2516L)
+#define HST_RCP_DATA_START_DYN (2517L)
+#define HST_RCP_DATA_START_OFS (2518L)
+#define HST_RCP_DATA_STRIP_MODE (2519L)
+/* ICORE_10G */
+#define ICORE_10G_INDIR_CTRL (2549L)
+#define ICORE_10G_INDIR_CTRL_RD_ENABLE (2550L)
+#define ICORE_10G_INDIR_CTRL_RD_READY (2551L)
+#define ICORE_10G_INDIR_CTRL_SUB_ADDR (2552L)
+#define ICORE_10G_INDIR_DATA (2553L)
+#define ICORE_10G_INDIR_DATA_DATA (2554L)
+#define ICORE_10G_MISC_CTRL (2555L)
+#define ICORE_10G_MISC_CTRL_LINE_LOOP (2556L)
+#define ICORE_10G_MISC_CTRL_LINK_LATENCY (2557L)
+#define ICORE_10G_MISC_CTRL_RES_MAC_RX (2558L)
+#define ICORE_10G_MISC_CTRL_RES_MAC_TX (2559L)
+#define ICORE_10G_MISC_CTRL_SERIAL_LOOP (2560L)
+#define ICORE_10G_MISC_CTRL_SET_LOCK2DATA (2561L)
+#define ICORE_10G_MISC_CTRL_SET_LOCK2REF (2562L)
+#define ICORE_10G_PHY_STATUS (2563L)
+#define ICORE_10G_PHY_STATUS_BLOCK_LOCK (2564L)
+#define ICORE_10G_PHY_STATUS_HI_BER (2565L)
+#define ICORE_10G_PHY_STATUS_HI_BER_CHANGED (2566L)
+#define ICORE_10G_PHY_STATUS_LINK_STATE (2567L)
+#define ICORE_10G_PHY_STATUS_LINK_STATE_CHANGED (2568L)
+#define ICORE_10G_PHY_STATUS_RXCLK_LOCKED (2569L)
+#define ICORE_10G_PHY_STATUS_RXCLK_LOCKED2DATA (2570L)
+#define ICORE_10G_PHY_STATUS_RX_CAL_BUSY (2571L)
+#define ICORE_10G_PHY_STATUS_TXCLK_LOCKED (2572L)
+#define ICORE_10G_PHY_STATUS_TX_CAL_BUSY (2573L)
+#define ICORE_10G_TFG_ADDR (2574L)
+#define ICORE_10G_TFG_ADDR_ADR (2575L)
+#define ICORE_10G_TFG_ADDR_RDENA (2576L)
+#define ICORE_10G_TFG_ADDR_RD_DONE (2577L)
+#define ICORE_10G_TFG_CTRL (2578L)
+#define ICORE_10G_TFG_CTRL_ID_ENA (2579L)
+#define ICORE_10G_TFG_CTRL_ID_POS (2580L)
+#define ICORE_10G_TFG_CTRL_RESTART (2581L)
+#define ICORE_10G_TFG_CTRL_TG_ACT (2582L)
+#define ICORE_10G_TFG_CTRL_TG_ENA (2583L)
+#define ICORE_10G_TFG_CTRL_TIME_MODE (2584L)
+#define ICORE_10G_TFG_CTRL_WRAP (2585L)
+#define ICORE_10G_TFG_DATA (2586L)
+#define ICORE_10G_TFG_DATA_ID (2587L)
+#define ICORE_10G_TFG_DATA_LENGTH (2588L)
+#define ICORE_10G_TFG_FRAME_HDR_0 (2589L)
+#define ICORE_10G_TFG_FRAME_HDR_0_HDR (2590L)
+#define ICORE_10G_TFG_FRAME_HDR_1 (2591L)
+#define ICORE_10G_TFG_FRAME_HDR_1_HDR (2592L)
+#define ICORE_10G_TFG_FRAME_HDR_2 (2593L)
+#define ICORE_10G_TFG_FRAME_HDR_2_HDR (2594L)
+#define ICORE_10G_TFG_FRAME_HDR_3 (2595L)
+#define ICORE_10G_TFG_FRAME_HDR_3_HDR (2596L)
+#define ICORE_10G_TFG_REPETITION (2597L)
+#define ICORE_10G_TFG_REPETITION_CNT (2598L)
+/* IFR */
+#define IFR_RCP_CTRL (2642L)
+#define IFR_RCP_CTRL_ADR (2643L)
+#define IFR_RCP_CTRL_CNT (2644L)
+#define IFR_RCP_DATA (2645L)
+#define IFR_RCP_DATA_EN (2646L)
+#define IFR_RCP_DATA_MTU (2647L)
+/* IIC */
+#define IIC_ADR (2648L)
+#define IIC_ADR_SLV_ADR (2649L)
+#define IIC_CR (2650L)
+#define IIC_CR_EN (2651L)
+#define IIC_CR_GC_EN (2652L)
+#define IIC_CR_MSMS (2653L)
+#define IIC_CR_RST (2654L)
+#define IIC_CR_RSTA (2655L)
+#define IIC_CR_TX (2656L)
+#define IIC_CR_TXAK (2657L)
+#define IIC_CR_TXFIFO_RESET (2658L)
+#define IIC_DGIE (2659L)
+#define IIC_DGIE_GIE (2660L)
+#define IIC_GPO (2661L)
+#define IIC_GPO_GPO_VAL (2662L)
+#define IIC_IER (2663L)
+#define IIC_IER_INT0 (2664L)
+#define IIC_IER_INT1 (2665L)
+#define IIC_IER_INT2 (2666L)
+#define IIC_IER_INT3 (2667L)
+#define IIC_IER_INT4 (2668L)
+#define IIC_IER_INT5 (2669L)
+#define IIC_IER_INT6 (2670L)
+#define IIC_IER_INT7 (2671L)
+#define IIC_ISR (2672L)
+#define IIC_ISR_INT0 (2673L)
+#define IIC_ISR_INT1 (2674L)
+#define IIC_ISR_INT2 (2675L)
+#define IIC_ISR_INT3 (2676L)
+#define IIC_ISR_INT4 (2677L)
+#define IIC_ISR_INT5 (2678L)
+#define IIC_ISR_INT6 (2679L)
+#define IIC_ISR_INT7 (2680L)
+#define IIC_RX_FIFO (2681L)
+#define IIC_RX_FIFO_RXDATA (2682L)
+#define IIC_RX_FIFO_OCY (2683L)
+#define IIC_RX_FIFO_OCY_OCY_VAL (2684L)
+#define IIC_RX_FIFO_PIRQ (2685L)
+#define IIC_RX_FIFO_PIRQ_CMP_VAL (2686L)
+#define IIC_SOFTR (2687L)
+#define IIC_SOFTR_RKEY (2688L)
+#define IIC_SR (2689L)
+#define IIC_SR_AAS (2690L)
+#define IIC_SR_ABGC (2691L)
+#define IIC_SR_BB (2692L)
+#define IIC_SR_RXFIFO_EMPTY (2693L)
+#define IIC_SR_RXFIFO_FULL (2694L)
+#define IIC_SR_SRW (2695L)
+#define IIC_SR_TXFIFO_EMPTY (2696L)
+#define IIC_SR_TXFIFO_FULL (2697L)
+#define IIC_TBUF (2698L)
+#define IIC_TBUF_TBUF_VAL (2699L)
+#define IIC_TEN_ADR (2700L)
+#define IIC_TEN_ADR_MSB_SLV_ADR (2701L)
+#define IIC_THDDAT (2702L)
+#define IIC_THDDAT_THDDAT_VAL (2703L)
+#define IIC_THDSTA (2704L)
+#define IIC_THDSTA_THDSTA_VAL (2705L)
+#define IIC_THIGH (2706L)
+#define IIC_THIGH_THIGH_VAL (2707L)
+#define IIC_TLOW (2708L)
+#define IIC_TLOW_TLOW_VAL (2709L)
+#define IIC_TSUDAT (2710L)
+#define IIC_TSUDAT_TSUDAT_VAL (2711L)
+#define IIC_TSUSTA (2712L)
+#define IIC_TSUSTA_TSUSTA_VAL (2713L)
+#define IIC_TSUSTO (2714L)
+#define IIC_TSUSTO_TSUSTO_VAL (2715L)
+#define IIC_TX_FIFO (2716L)
+#define IIC_TX_FIFO_START (2717L)
+#define IIC_TX_FIFO_STOP (2718L)
+#define IIC_TX_FIFO_TXDATA (2719L)
+#define IIC_TX_FIFO_OCY (2720L)
+#define IIC_TX_FIFO_OCY_OCY_VAL (2721L)
+/* INS */
+#define INS_RCP_CTRL (2722L)
+#define INS_RCP_CTRL_ADR (2723L)
+#define INS_RCP_CTRL_CNT (2724L)
+#define INS_RCP_DATA (2725L)
+#define INS_RCP_DATA_DYN (2726L)
+#define INS_RCP_DATA_LEN (2727L)
+#define INS_RCP_DATA_OFS (2728L)
+/* IOA */
+#define IOA_RECIPE_CTRL (2778L)
+#define IOA_RECIPE_CTRL_ADR (2779L)
+#define IOA_RECIPE_CTRL_CNT (2780L)
+#define IOA_RECIPE_DATA (2781L)
+#define IOA_RECIPE_DATA_QUEUE_ID (2782L)
+#define IOA_RECIPE_DATA_QUEUE_OVERRIDE_EN (2783L)
+#define IOA_RECIPE_DATA_TUNNEL_POP (2784L)
+#define IOA_RECIPE_DATA_VLAN_DEI (2785L)
+#define IOA_RECIPE_DATA_VLAN_PCP (2786L)
+#define IOA_RECIPE_DATA_VLAN_POP (2787L)
+#define IOA_RECIPE_DATA_VLAN_PUSH (2788L)
+#define IOA_RECIPE_DATA_VLAN_TPID_SEL (2789L)
+#define IOA_RECIPE_DATA_VLAN_VID (2790L)
+#define IOA_ROA_EPP_CTRL (2791L)
+#define IOA_ROA_EPP_CTRL_ADR (2792L)
+#define IOA_ROA_EPP_CTRL_CNT (2793L)
+#define IOA_ROA_EPP_DATA (2794L)
+#define IOA_ROA_EPP_DATA_PUSH_TUNNEL (2795L)
+#define IOA_ROA_EPP_DATA_TX_PORT (2796L)
+#define IOA_VLAN_TPID_SPECIAL (2797L)
+#define IOA_VLAN_TPID_SPECIAL_CUSTTPID0 (2798L)
+#define IOA_VLAN_TPID_SPECIAL_CUSTTPID1 (2799L)
+/* IPF */
+#define IPF_CTRL (2800L)
+#define IPF_CTRL_ALL_UNM (2801L)
+#define IPF_CTRL_ALL_UNM_INNER (2802L)
+#define IPF_CTRL_DEL_UNM (2803L)
+#define IPF_CTRL_ENABLE (2804L)
+#define IPF_CTRL_FST_UNM (2805L)
+#define IPF_CTRL_PASSIVE (2806L)
+#define IPF_CTRL_PERSIST (2807L)
+#define IPF_DEBUG (2808L)
+#define IPF_DEBUG_FTF_N (2809L)
+#define IPF_DEBUG_LIMIT_N (2810L)
+#define IPF_EXPIRE (2811L)
+#define IPF_EXPIRE_PERSIST (2812L)
+#define IPF_EXPIRE_T (2813L)
+#define IPF_FTF_DEBUG (2814L)
+#define IPF_FTF_DEBUG_N (2815L)
+#define IPF_RCP_CTRL (2816L)
+#define IPF_RCP_CTRL_ADR (2817L)
+#define IPF_RCP_CTRL_CNT (2818L)
+#define IPF_RCP_DATA (2819L)
+#define IPF_RCP_DATA_ALL_UNM (2820L)
+#define IPF_RCP_DATA_COL_INH (2821L)
+#define IPF_RCP_DATA_DEL_UNM (2822L)
+#define IPF_RCP_DATA_DISC_INH (2823L)
+#define IPF_RCP_DATA_DUP_INH (2824L)
+#define IPF_RCP_DATA_ENABLE (2825L)
+#define IPF_RCP_DATA_FST_UNM (2826L)
+#define IPF_RCP_DATA_GROUP_ID (2827L)
+#define IPF_RCP_DATA_HASH_CENC (2828L)
+#define IPF_RCP_DATA_HSH_INH (2829L)
+#define IPF_RCP_DATA_PORT_GROUP_ID (2830L)
+#define IPF_RCP_DATA_QUEUE_INH (2831L)
+#define IPF_RCP_DATA_UNMQ_HI (2832L)
+#define IPF_RCP_DATA_UNMQ_LO (2833L)
+#define IPF_RCP_DATA_UNM_FLAG_CENC (2834L)
+#define IPF_SIZE_DEBUG (2835L)
+#define IPF_SIZE_DEBUG_N (2836L)
+#define IPF_STAT_MAX1 (2837L)
+#define IPF_STAT_MAX1_N (2838L)
+#define IPF_STAT_MAX2 (2839L)
+#define IPF_STAT_MAX2_N (2840L)
+#define IPF_STAT_MAX3 (2841L)
+#define IPF_STAT_MAX3_N (2842L)
+#define IPF_STAT_MAX4 (2843L)
+#define IPF_STAT_MAX4_N (2844L)
+#define IPF_TIMEOUT (2845L)
+#define IPF_TIMEOUT_T (2846L)
+#define IPF_UNMQ_CTRL (2847L)
+#define IPF_UNMQ_CTRL_ADR (2848L)
+#define IPF_UNMQ_CTRL_CNT (2849L)
+#define IPF_UNMQ_DATA (2850L)
+#define IPF_UNMQ_DATA_CENC (2851L)
+#define IPF_UNMQ_DATA_EN (2852L)
+#define IPF_UNMQ_DATA_ID (2853L)
+#define IPF_UNM_FEED (2854L)
+#define IPF_UNM_FEED_ADDR (2855L)
+#define IPF_UNM_FEED_CNT (2856L)
+#define IPF_UNM_FEED_FEED (2857L)
+#define IPF_UNM_FEED_FEED_VALID (2858L)
+#define IPF_UNM_FEED_RES1 (2859L)
+#define IPF_UNM_FEED_RES2 (2860L)
+#define IPF_UNM_FEED_RES3 (2861L)
+/* KM */
+#define KM_CAM_CTRL (2862L)
+#define KM_CAM_CTRL_ADR (2863L)
+#define KM_CAM_CTRL_CNT (2864L)
+#define KM_CAM_DATA (2865L)
+#define KM_CAM_DATA_FT0 (2866L)
+#define KM_CAM_DATA_FT1 (2867L)
+#define KM_CAM_DATA_FT2 (2868L)
+#define KM_CAM_DATA_FT3 (2869L)
+#define KM_CAM_DATA_FT4 (2870L)
+#define KM_CAM_DATA_FT5 (2871L)
+#define KM_CAM_DATA_W0 (2872L)
+#define KM_CAM_DATA_W1 (2873L)
+#define KM_CAM_DATA_W2 (2874L)
+#define KM_CAM_DATA_W3 (2875L)
+#define KM_CAM_DATA_W4 (2876L)
+#define KM_CAM_DATA_W5 (2877L)
+#define KM_RCP_CTRL (2878L)
+#define KM_RCP_CTRL_ADR (2879L)
+#define KM_RCP_CTRL_CNT (2880L)
+#define KM_RCP_DATA (2881L)
+#define KM_RCP_DATA_BANK_A (2882L)
+#define KM_RCP_DATA_BANK_B (2883L)
+#define KM_RCP_DATA_DUAL (2884L)
+#define KM_RCP_DATA_DW0_B_DYN (2885L)
+#define KM_RCP_DATA_DW0_B_OFS (2886L)
+#define KM_RCP_DATA_DW10_DYN (2887L)
+#define KM_RCP_DATA_DW10_OFS (2888L)
+#define KM_RCP_DATA_DW10_SEL_A (2889L)
+#define KM_RCP_DATA_DW10_SEL_B (2890L)
+#define KM_RCP_DATA_DW2_B_DYN (2891L)
+#define KM_RCP_DATA_DW2_B_OFS (2892L)
+#define KM_RCP_DATA_DW8_B_DYN (2893L)
+#define KM_RCP_DATA_DW8_B_OFS (2894L)
+#define KM_RCP_DATA_DW8_DYN (2895L)
+#define KM_RCP_DATA_DW8_OFS (2896L)
+#define KM_RCP_DATA_DW8_SEL_A (2897L)
+#define KM_RCP_DATA_DW8_SEL_B (2898L)
+#define KM_RCP_DATA_EL_A (2899L)
+#define KM_RCP_DATA_EL_B (2900L)
+#define KM_RCP_DATA_FLOW_SET (2901L)
+#define KM_RCP_DATA_FTM_A (2902L)
+#define KM_RCP_DATA_FTM_B (2903L)
+#define KM_RCP_DATA_INFO_A (2904L)
+#define KM_RCP_DATA_INFO_B (2905L)
+#define KM_RCP_DATA_KEYWAY_A (2906L)
+#define KM_RCP_DATA_KEYWAY_B (2907L)
+#define KM_RCP_DATA_KL_A (2908L)
+#define KM_RCP_DATA_KL_B (2909L)
+#define KM_RCP_DATA_MASK_A (2910L)
+#define KM_RCP_DATA_MASK_B (2911L)
+#define KM_RCP_DATA_PAIRED (2912L)
+#define KM_RCP_DATA_QW0_B_DYN (2913L)
+#define KM_RCP_DATA_QW0_B_OFS (2914L)
+#define KM_RCP_DATA_QW0_DYN (2915L)
+#define KM_RCP_DATA_QW0_OFS (2916L)
+#define KM_RCP_DATA_QW0_SEL_A (2917L)
+#define KM_RCP_DATA_QW0_SEL_B (2918L)
+#define KM_RCP_DATA_QW4_B_DYN (2919L)
+#define KM_RCP_DATA_QW4_B_OFS (2920L)
+#define KM_RCP_DATA_QW4_DYN (2921L)
+#define KM_RCP_DATA_QW4_OFS (2922L)
+#define KM_RCP_DATA_QW4_SEL_A (2923L)
+#define KM_RCP_DATA_QW4_SEL_B (2924L)
+#define KM_RCP_DATA_SW4_B_DYN (2925L)
+#define KM_RCP_DATA_SW4_B_OFS (2926L)
+#define KM_RCP_DATA_SW5_B_DYN (2927L)
+#define KM_RCP_DATA_SW5_B_OFS (2928L)
+#define KM_RCP_DATA_SW8_B_DYN (2929L)
+#define KM_RCP_DATA_SW8_B_OFS (2930L)
+#define KM_RCP_DATA_SW8_DYN (2931L)
+#define KM_RCP_DATA_SW8_OFS (2932L)
+#define KM_RCP_DATA_SW8_SEL_A (2933L)
+#define KM_RCP_DATA_SW8_SEL_B (2934L)
+#define KM_RCP_DATA_SW9_B_DYN (2935L)
+#define KM_RCP_DATA_SW9_B_OFS (2936L)
+#define KM_RCP_DATA_SW9_DYN (2937L)
+#define KM_RCP_DATA_SW9_OFS (2938L)
+#define KM_RCP_DATA_SW9_SEL_A (2939L)
+#define KM_RCP_DATA_SW9_SEL_B (2940L)
+#define KM_RCP_DATA_SWX_CCH (2941L)
+#define KM_RCP_DATA_SWX_OVS_SB (2942L)
+#define KM_RCP_DATA_SWX_SEL_A (2943L)
+#define KM_RCP_DATA_SWX_SEL_B (2944L)
+#define KM_RCP_DATA_SYNERGY_MODE (2945L)
+#define KM_STATUS (2946L)
+#define KM_STATUS_TCQ_RDY (2947L)
+#define KM_TCAM_CTRL (2948L)
+#define KM_TCAM_CTRL_ADR (2949L)
+#define KM_TCAM_CTRL_CNT (2950L)
+#define KM_TCAM_DATA (2951L)
+#define KM_TCAM_DATA_T (2952L)
+#define KM_TCI_CTRL (2953L)
+#define KM_TCI_CTRL_ADR (2954L)
+#define KM_TCI_CTRL_CNT (2955L)
+#define KM_TCI_DATA (2956L)
+#define KM_TCI_DATA_COLOR (2957L)
+#define KM_TCI_DATA_FT (2958L)
+#define KM_TCQ_CTRL (2959L)
+#define KM_TCQ_CTRL_ADR (2960L)
+#define KM_TCQ_CTRL_CNT (2961L)
+#define KM_TCQ_DATA (2962L)
+#define KM_TCQ_DATA_BANK_MASK (2963L)
+#define KM_TCQ_DATA_QUAL (2964L)
+/* LAO */
+/* MAC */
+#define MAC_CONF_SERDES_BITFRAG (2965L)
+#define MAC_CONF_SERDES_BITFRAG_BITFRAG (2966L)
+#define MAC_CONF_SERDES_DELAY (2967L)
+#define MAC_CONF_SERDES_DELAY_DELAY (2968L)
+#define MAC_CONF_SERDES_REORDER (2969L)
+#define MAC_CONF_SERDES_REORDER_REORDER (2970L)
+#define MAC_FAULTY_BLK (2971L)
+#define MAC_FAULTY_BLK_DATA (2972L)
+#define MAC_HOST_STAT_BYTE_FILL (2973L)
+#define MAC_HOST_STAT_BYTE_FILL_CNT (2974L)
+#define MAC_INT (2975L)
+#define MAC_INT_EN (2976L)
+#define MAC_INT_MAX_PACE (2977L)
+#define MAC_LINK_SUMMARY (2978L)
+#define MAC_LINK_SUMMARY_ABS (2979L)
+#define MAC_LINK_SUMMARY_GBOX_INTERR (2980L)
+#define MAC_LINK_SUMMARY_GLB_ALARMN (2981L)
+#define MAC_LINK_SUMMARY_LH_ABS (2982L)
+#define MAC_LINK_SUMMARY_LH_GLB_ALARMN (2983L)
+#define MAC_LINK_SUMMARY_LH_LOCAL_FAULT (2984L)
+#define MAC_LINK_SUMMARY_LH_REMOTE_FAULT (2985L)
+#define MAC_LINK_SUMMARY_LH_RX_LOS (2986L)
+#define MAC_LINK_SUMMARY_LINK_DOWN_CNT (2987L)
+#define MAC_LINK_SUMMARY_LL_PHY_LINK_STATE (2988L)
+#define MAC_LINK_SUMMARY_LOCAL_FAULT (2989L)
+#define MAC_LINK_SUMMARY_NT_PHY_LINK_STATE (2990L)
+#define MAC_LINK_SUMMARY_REMOTE_FAULT (2991L)
+#define MAC_LINK_SUMMARY_RX_LOS (2992L)
+#define MAC_MAC_STAT_BYTE (2993L)
+#define MAC_MAC_STAT_BYTE_CNT (2994L)
+#define MAC_MAC_STAT_CRC (2995L)
+#define MAC_MAC_STAT_CRC_CNT (2996L)
+#define MAC_MAC_STAT_CV (2997L)
+#define MAC_MAC_STAT_CV_CNT (2998L)
+#define MAC_MAC_STAT_FRAME (2999L)
+#define MAC_MAC_STAT_FRAME_CNT (3000L)
+#define MAC_MAC_STAT_MICRO_DROP (3001L)
+#define MAC_MAC_STAT_MICRO_DROP_CNT (3002L)
+#define MAC_MAC_STAT_RATE_DROP (3003L)
+#define MAC_MAC_STAT_RATE_DROP_CNT (3004L)
+#define MAC_MAC_STAT_TRUNC (3005L)
+#define MAC_MAC_STAT_TRUNC_CNT (3006L)
+#define MAC_MDS_CEN_VAL (3007L)
+#define MAC_MDS_CEN_VAL_VAL (3008L)
+#define MAC_MDS_CONF (3009L)
+#define MAC_MDS_CONF_CENTER_REC_ENA (3010L)
+#define MAC_MDS_CONF_CLR_STAT (3011L)
+#define MAC_MDS_CONF_ENA_TS_MOD (3012L)
+#define MAC_MDS_CONF_REC_ENA (3013L)
+#define MAC_MDS_CONF_TIME_MODE (3014L)
+#define MAC_MDS_DATA (3015L)
+#define MAC_MDS_DATA_DATA (3016L)
+#define MAC_MDS_FRAMES (3017L)
+#define MAC_MDS_FRAMES_CNT (3018L)
+#define MAC_MDS_MAX (3019L)
+#define MAC_MDS_MAX_MAX (3020L)
+#define MAC_MDS_MIN (3021L)
+#define MAC_MDS_MIN_MIN (3022L)
+#define MAC_MDS_STAT (3023L)
+#define MAC_MDS_STAT_CLR_BUSY (3024L)
+#define MAC_MDS_STAT_HIT_MAX (3025L)
+#define MAC_MDS_STAT_HIT_MIN (3026L)
+#define MAC_MDS_VAL_REC (3027L)
+#define MAC_MDS_VAL_REC_VALUE (3028L)
+#define MAC_MDS_VAL_REC_FRAME (3029L)
+#define MAC_MDS_VAL_REC_FRAME_VALUE (3030L)
+#define MAC_NT_PORT_CTRL (3031L)
+#define MAC_NT_PORT_CTRL_LED_MODE (3032L)
+#define MAC_RAM_MDS_ADDR (3033L)
+#define MAC_RAM_MDS_ADDR_ADR (3034L)
+#define MAC_RAM_MDS_ADDR_CLR_RAM (3035L)
+#define MAC_RAM_MDS_ADDR_RD_DONE (3036L)
+#define MAC_RAM_MDS_ADDR_RD_ENA (3037L)
+#define MAC_RAW_ADDR (3038L)
+#define MAC_RAW_ADDR_ADR (3039L)
+#define MAC_RAW_ADDR_RDENA (3040L)
+#define MAC_RAW_ADDR_RD_DONE (3041L)
+#define MAC_RAW_CTRL (3042L)
+#define MAC_RAW_CTRL_OVERWR_LM (3043L)
+#define MAC_RAW_CTRL_RESTART (3044L)
+#define MAC_RAW_CTRL_TG_ACT (3045L)
+#define MAC_RAW_CTRL_TG_ENA (3046L)
+#define MAC_RAW_CTRL_WRAP (3047L)
+#define MAC_RAW_DATA (3048L)
+#define MAC_RAW_DATA_RAW_DATA (3049L)
+#define MAC_RAW_REPETITION (3050L)
+#define MAC_RAW_REPETITION_CNT (3051L)
+#define MAC_RX_CONFIG (3052L)
+#define MAC_RX_CONFIG_DESCRAMB (3053L)
+#define MAC_RX_CONFIG_HOST_CLR_CNT (3054L)
+#define MAC_RX_CONFIG_MAC_CLR_CNT (3055L)
+#define MAC_RX_CONFIG_MIN_RX_FRAME (3056L)
+#define MAC_RX_CONFIG_NT_DEBOUNCE_LATENCY (3057L)
+#define MAC_RX_CONFIG_NT_FORCE_LINK_DOWN (3058L)
+#define MAC_RX_CONFIG_NT_LINKUP_LATENCY (3059L)
+#define MAC_RX_CONFIG_RST_BLK_ERR (3060L)
+#define MAC_RX_CONFIG_RX_MAC_EN (3061L)
+#define MAC_RX_CONFIG_TS_EOP (3062L)
+#define MAC_RX_CONFIG_TXRX_LOOP (3063L)
+#define MAC_RX_CONFIG2 (3064L)
+#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_INT (3065L)
+#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_LINK (3066L)
+#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_RST (3067L)
+#define MAC_RX_CONFIG2_NT_RXLOS_MASK_INT (3068L)
+#define MAC_RX_CONFIG2_NT_RXLOS_MASK_LINK (3069L)
+#define MAC_RX_CONFIG2_NT_RXLOS_MASK_RST (3070L)
+#define MAC_RX_STATUS (3071L)
+#define MAC_RX_STATUS_CORE_MODE (3072L)
+#define MAC_RX_STATUS_LOCAL_FAULT (3073L)
+#define MAC_RX_STATUS_REMOTE_FAULT (3074L)
+#define MAC_RX_STATUS_RXTX_OVERFLOW (3075L)
+#define MAC_RX_STATUS_VERSION (3076L)
+#define MAC_TFG_ADDR (3077L)
+#define MAC_TFG_ADDR_ADR (3078L)
+#define MAC_TFG_ADDR_RDENA (3079L)
+#define MAC_TFG_ADDR_RD_DONE (3080L)
+#define MAC_TFG_CTRL (3081L)
+#define MAC_TFG_CTRL_ID_ENA (3082L)
+#define MAC_TFG_CTRL_ID_POS (3083L)
+#define MAC_TFG_CTRL_RESTART (3084L)
+#define MAC_TFG_CTRL_TG_ACT (3085L)
+#define MAC_TFG_CTRL_TG_ENA (3086L)
+#define MAC_TFG_CTRL_TIME_MODE (3087L)
+#define MAC_TFG_CTRL_WRAP (3088L)
+#define MAC_TFG_DATA (3089L)
+#define MAC_TFG_DATA_GAP (3090L)
+#define MAC_TFG_DATA_ID (3091L)
+#define MAC_TFG_DATA_LENGTH (3092L)
+#define MAC_TFG_FRAME_HDR (3093L)
+#define MAC_TFG_FRAME_HDR_HDR (3094L)
+#define MAC_TFG_REPETITION (3095L)
+#define MAC_TFG_REPETITION_CNT (3096L)
+#define MAC_TX_CONFIG (3097L)
+#define MAC_TX_CONFIG_CLR_STICKY (3098L)
+#define MAC_TX_CONFIG_CRC_ERR_INS (3099L)
+#define MAC_TX_CONFIG_HOST_TX_ENA (3100L)
+#define MAC_TX_CONFIG_MAC_LOOP (3101L)
+#define MAC_TX_CONFIG_PCS_BIP_ERR (3102L)
+#define MAC_TX_CONFIG_PCS_DIS_BIP_INS (3103L)
+#define MAC_TX_CONFIG_PCS_IDLE (3104L)
+#define MAC_TX_CONFIG_PCS_IDLE_DIS (3105L)
+#define MAC_TX_CONFIG_PCS_LOCAL_FAULT (3106L)
+#define MAC_TX_CONFIG_PCS_LOCAL_FAULT_DIS (3107L)
+#define MAC_TX_CONFIG_PCS_REMOTE_FAULT (3108L)
+#define MAC_TX_CONFIG_PCS_REMOTE_FAULT_DIS (3109L)
+#define MAC_TX_CONFIG_PCS_SCRAMB_ENA (3110L)
+#define MAC_TX_CONFIG_PCS_SCRAMB_ERR (3111L)
+#define MAC_TX_CONFIG_TIME_OFFSET_TX (3112L)
+#define MAC_TX_CONFIG_TS_EOP (3113L)
+#define MAC_TX_STATUS (3114L)
+#define MAC_TX_STATUS_PCS_ERR (3115L)
+#define MAC_TX_STATUS_TX_MAC_ST (3116L)
+#define MAC_TX_STATUS_UNDER_FLOW (3117L)
+#define MAC_UPD_RX_COUNTERS (3118L)
+#define MAC_UPD_RX_COUNTERS_TRIGGER (3119L)
+/* MAC10 */
+#define MAC10_CFG_0 (3135L)
+#define MAC10_CFG_0_PAD_ENA (3136L)
+#define MAC10_CFG_0_RX_ENA (3137L)
+#define MAC10_CFG_0_RX_PAUSE_ENA (3138L)
+#define MAC10_CFG_0_STR_ENA (3139L)
+#define MAC10_CFG_0_TX_ENA (3140L)
+#define MAC10_CFG_0_TX_PAUSE_ENA (3141L)
+#define MAC10_MA (3142L)
+#define MAC10_MA_MAC10_ADR_0 (3143L)
+#define MAC10_MA_MAC_ADR_0 (3144L)
+#define MAC10_MA_LO (3145L)
+#define MAC10_MA_LO_MA_LO (3146L)
+#define MAC10_MA_MAX_SIZE (3147L)
+#define MAC10_MA_MAX_SIZE_MAC10_ADR_1 (3148L)
+#define MAC10_MA_MAX_SIZE_MAC_ADR_1 (3149L)
+#define MAC10_MA_MAX_SIZE_MTU (3150L)
+#define MAC10_MA_UP (3151L)
+#define MAC10_MA_UP_MA_UP (3152L)
+#define MAC10_STICKY_XAUI (3153L)
+#define MAC10_STICKY_XAUI_STICKY_XAUI (3154L)
+/* MAC100 */
+#define MAC100_CONF_SERDES_BITFRAG (3155L)
+#define MAC100_CONF_SERDES_BITFRAG_BITFRAG (3156L)
+#define MAC100_CONF_SERDES_DELAY (3157L)
+#define MAC100_CONF_SERDES_DELAY_DELAY (3158L)
+#define MAC100_CONF_SERDES_REORDER (3159L)
+#define MAC100_CONF_SERDES_REORDER_REORDER (3160L)
+#define MAC100_FAULTY_BLK (3161L)
+#define MAC100_FAULTY_BLK_DATA (3162L)
+#define MAC100_HOST_STAT_BYTE (3163L)
+#define MAC100_HOST_STAT_BYTE_CNT (3164L)
+#define MAC100_HOST_STAT_BYTE_FILL (3165L)
+#define MAC100_HOST_STAT_BYTE_FILL_CNT (3166L)
+#define MAC100_HOST_STAT_CRC (3167L)
+#define MAC100_HOST_STAT_CRC_CNT (3168L)
+#define MAC100_HOST_STAT_CV (3169L)
+#define MAC100_HOST_STAT_CV_CNT (3170L)
+#define MAC100_HOST_STAT_DROP (3171L)
+#define MAC100_HOST_STAT_DROP_CNT (3172L)
+#define MAC100_HOST_STAT_DROP_BYTE (3173L)
+#define MAC100_HOST_STAT_DROP_BYTE_CNT (3174L)
+#define MAC100_HOST_STAT_FRAME (3175L)
+#define MAC100_HOST_STAT_FRAME_CNT (3176L)
+#define MAC100_HOST_STAT_FRAME_FILL (3177L)
+#define MAC100_HOST_STAT_FRAME_FILL_CNT (3178L)
+#define MAC100_INT (3179L)
+#define MAC100_INT_EN (3180L)
+#define MAC100_INT_MAX_PACE (3181L)
+#define MAC100_LINK_SUMMARY (3182L)
+#define MAC100_LINK_SUMMARY_ABS (3183L)
+#define MAC100_LINK_SUMMARY_GBOX_INTERR (3184L)
+#define MAC100_LINK_SUMMARY_GLB_ALARMN (3185L)
+#define MAC100_LINK_SUMMARY_LH_ABS (3186L)
+#define MAC100_LINK_SUMMARY_LH_GLB_ALARMN (3187L)
+#define MAC100_LINK_SUMMARY_LH_LOCAL_FAULT (3188L)
+#define MAC100_LINK_SUMMARY_LH_REMOTE_FAULT (3189L)
+#define MAC100_LINK_SUMMARY_LH_RX_LOS (3190L)
+#define MAC100_LINK_SUMMARY_LINK_DOWN_CNT (3191L)
+#define MAC100_LINK_SUMMARY_LL_PHY_LINK_STATE (3192L)
+#define MAC100_LINK_SUMMARY_LOCAL_FAULT (3193L)
+#define MAC100_LINK_SUMMARY_NT_PHY_LINK_STATE (3194L)
+#define MAC100_LINK_SUMMARY_REMOTE_FAULT (3195L)
+#define MAC100_LINK_SUMMARY_RX_LOS (3196L)
+#define MAC100_MAC_STAT_BYTE (3197L)
+#define MAC100_MAC_STAT_BYTE_CNT (3198L)
+#define MAC100_MAC_STAT_CRC (3199L)
+#define MAC100_MAC_STAT_CRC_CNT (3200L)
+#define MAC100_MAC_STAT_CV (3201L)
+#define MAC100_MAC_STAT_CV_CNT (3202L)
+#define MAC100_MAC_STAT_FC (3203L)
+#define MAC100_MAC_STAT_FC_CNT (3204L)
+#define MAC100_MAC_STAT_FRAME (3205L)
+#define MAC100_MAC_STAT_FRAME_CNT (3206L)
+#define MAC100_MAC_STAT_MICRO_DROP (3207L)
+#define MAC100_MAC_STAT_MICRO_DROP_CNT (3208L)
+#define MAC100_MAC_STAT_PAUSE (3209L)
+#define MAC100_MAC_STAT_PAUSE_CNT (3210L)
+#define MAC100_MAC_STAT_RATE_DROP (3211L)
+#define MAC100_MAC_STAT_RATE_DROP_CNT (3212L)
+#define MAC100_MAC_STAT_TRUNC (3213L)
+#define MAC100_MAC_STAT_TRUNC_CNT (3214L)
+#define MAC100_MDS_CEN_VAL (3215L)
+#define MAC100_MDS_CEN_VAL_VAL (3216L)
+#define MAC100_MDS_CONF (3217L)
+#define MAC100_MDS_CONF_CENTER_REC_ENA (3218L)
+#define MAC100_MDS_CONF_CLR_STAT (3219L)
+#define MAC100_MDS_CONF_ENA_TS_MOD (3220L)
+#define MAC100_MDS_CONF_REC_ENA (3221L)
+#define MAC100_MDS_CONF_TIME_MODE (3222L)
+#define MAC100_MDS_DATA (3223L)
+#define MAC100_MDS_DATA_DATA (3224L)
+#define MAC100_MDS_FRAMES (3225L)
+#define MAC100_MDS_FRAMES_CNT (3226L)
+#define MAC100_MDS_MAX (3227L)
+#define MAC100_MDS_MAX_MAX (3228L)
+#define MAC100_MDS_MIN (3229L)
+#define MAC100_MDS_MIN_MIN (3230L)
+#define MAC100_MDS_STAT (3231L)
+#define MAC100_MDS_STAT_CLR_BUSY (3232L)
+#define MAC100_MDS_STAT_HIT_MAX (3233L)
+#define MAC100_MDS_STAT_HIT_MIN (3234L)
+#define MAC100_MDS_VAL_REC (3235L)
+#define MAC100_MDS_VAL_REC_VALUE (3236L)
+#define MAC100_MDS_VAL_REC_FRAME (3237L)
+#define MAC100_MDS_VAL_REC_FRAME_VALUE (3238L)
+#define MAC100_NT_PORT_CTRL (3239L)
+#define MAC100_NT_PORT_CTRL_LED_MODE (3240L)
+#define MAC100_RAM_MDS_ADDR (3241L)
+#define MAC100_RAM_MDS_ADDR_ADR (3242L)
+#define MAC100_RAM_MDS_ADDR_CLR_RAM (3243L)
+#define MAC100_RAM_MDS_ADDR_RD_DONE (3244L)
+#define MAC100_RAM_MDS_ADDR_RD_ENA (3245L)
+#define MAC100_RAW_ADDR (3246L)
+#define MAC100_RAW_ADDR_ADR (3247L)
+#define MAC100_RAW_ADDR_RDENA (3248L)
+#define MAC100_RAW_ADDR_RD_DONE (3249L)
+#define MAC100_RAW_CTRL (3250L)
+#define MAC100_RAW_CTRL_OVERWR_LM (3251L)
+#define MAC100_RAW_CTRL_RESTART (3252L)
+#define MAC100_RAW_CTRL_TG_ACT (3253L)
+#define MAC100_RAW_CTRL_TG_ENA (3254L)
+#define MAC100_RAW_CTRL_WRAP (3255L)
+#define MAC100_RAW_DATA (3256L)
+#define MAC100_RAW_DATA_RAW_DATA (3257L)
+#define MAC100_RAW_REPETITION (3258L)
+#define MAC100_RAW_REPETITION_CNT (3259L)
+#define MAC100_RX_CONFIG (3260L)
+#define MAC100_RX_CONFIG_DESCRAMB (3261L)
+#define MAC100_RX_CONFIG_HADP_RUN_MODE (3262L)
+#define MAC100_RX_CONFIG_HOST_CLR_CNT (3263L)
+#define MAC100_RX_CONFIG_MAC_CLR_CNT (3264L)
+#define MAC100_RX_CONFIG_MIN_RX_FRAME (3265L)
+#define MAC100_RX_CONFIG_NT_DEBOUNCE_LATENCY (3266L)
+#define MAC100_RX_CONFIG_NT_FORCE_LINK_DOWN (3267L)
+#define MAC100_RX_CONFIG_NT_LINKUP_LATENCY (3268L)
+#define MAC100_RX_CONFIG_RST_BLK_ERR (3269L)
+#define MAC100_RX_CONFIG_RX_MAC_EN (3270L)
+#define MAC100_RX_CONFIG_TS_EOP (3271L)
+#define MAC100_RX_CONFIG_TXRX_LOOP (3272L)
+#define MAC100_RX_CONFIG2 (3273L)
+#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_INT (3274L)
+#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_LINK (3275L)
+#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_RST (3276L)
+#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_INT (3277L)
+#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_LINK (3278L)
+#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_RST (3279L)
+#define MAC100_RX_STATUS (3280L)
+#define MAC100_RX_STATUS_CORE_MODE (3281L)
+#define MAC100_RX_STATUS_LOCAL_FAULT (3282L)
+#define MAC100_RX_STATUS_REMOTE_FAULT (3283L)
+#define MAC100_RX_STATUS_RXTX_OVERFLOW (3284L)
+#define MAC100_RX_STATUS_VERSION (3285L)
+#define MAC100_TFG_ADDR (3286L)
+#define MAC100_TFG_ADDR_ADR (3287L)
+#define MAC100_TFG_ADDR_RDENA (3288L)
+#define MAC100_TFG_ADDR_RD_DONE (3289L)
+#define MAC100_TFG_CTRL (3290L)
+#define MAC100_TFG_CTRL_ID_ENA (3291L)
+#define MAC100_TFG_CTRL_ID_POS (3292L)
+#define MAC100_TFG_CTRL_RESTART (3293L)
+#define MAC100_TFG_CTRL_TG_ACT (3294L)
+#define MAC100_TFG_CTRL_TG_ENA (3295L)
+#define MAC100_TFG_CTRL_TIME_MODE (3296L)
+#define MAC100_TFG_CTRL_WRAP (3297L)
+#define MAC100_TFG_DATA (3298L)
+#define MAC100_TFG_DATA_GAP (3299L)
+#define MAC100_TFG_DATA_ID (3300L)
+#define MAC100_TFG_DATA_LENGTH (3301L)
+#define MAC100_TFG_FRAME_HDR (3302L)
+#define MAC100_TFG_FRAME_HDR_HDR (3303L)
+#define MAC100_TFG_REPETITION (3304L)
+#define MAC100_TFG_REPETITION_CNT (3305L)
+#define MAC100_TX_CONFIG (3306L)
+#define MAC100_TX_CONFIG_CLR_STICKY (3307L)
+#define MAC100_TX_CONFIG_CRC_ERR_INS (3308L)
+#define MAC100_TX_CONFIG_HADP_LOOP (3309L)
+#define MAC100_TX_CONFIG_HOST_TX_ENA (3310L)
+#define MAC100_TX_CONFIG_MAC_LOOP (3311L)
+#define MAC100_TX_CONFIG_PCS_BIP_ERR (3312L)
+#define MAC100_TX_CONFIG_PCS_DIS_BIP_INS (3313L)
+#define MAC100_TX_CONFIG_PCS_IDLE (3314L)
+#define MAC100_TX_CONFIG_PCS_IDLE_DIS (3315L)
+#define MAC100_TX_CONFIG_PCS_LOCAL_FAULT (3316L)
+#define MAC100_TX_CONFIG_PCS_LOCAL_FAULT_DIS (3317L)
+#define MAC100_TX_CONFIG_PCS_REMOTE_FAULT (3318L)
+#define MAC100_TX_CONFIG_PCS_REMOTE_FAULT_DIS (3319L)
+#define MAC100_TX_CONFIG_PCS_SCRAMB_ENA (3320L)
+#define MAC100_TX_CONFIG_PCS_SCRAMB_ERR (3321L)
+#define MAC100_TX_CONFIG_TIME_OFFSET_TX (3322L)
+#define MAC100_TX_CONFIG_TS_EOP (3323L)
+#define MAC100_TX_STATUS (3324L)
+#define MAC100_TX_STATUS_PCS_ERR (3325L)
+#define MAC100_TX_STATUS_TX_HADP_ST (3326L)
+#define MAC100_TX_STATUS_TX_MAC_ST (3327L)
+#define MAC100_TX_STATUS_UNDER_FLOW (3328L)
+#define MAC100_UPD_RX_COUNTERS (3329L)
+#define MAC100_UPD_RX_COUNTERS_TRIGGER (3330L)
+/* MAC10G */
+#define MAC10G_CFG (3331L)
+#define MAC10G_CFG_MIN_RX_FRAME (3332L)
+#define MAC10G_CFG_RX_ENA (3333L)
+#define MAC10G_CFG_RX_EOP_TS (3334L)
+#define MAC10G_CFG_RX_PAUSE_ENA (3335L)
+#define MAC10G_CFG_STR_ENA (3336L)
+#define MAC10G_CFG_TX_ENA (3337L)
+#define MAC10G_CFG_TX_PAUSE_ENA (3338L)
+#define MAC10G_MA_LO (3339L)
+#define MAC10G_MA_LO_MA_LO (3340L)
+#define MAC10G_MA_UP (3341L)
+#define MAC10G_MA_UP_MA_UP (3342L)
+/* MAC1G */
+#define MAC1G_CFG (3343L)
+#define MAC1G_CFG_MIN_RX_FRAME (3344L)
+#define MAC1G_CFG_RX_ENA (3345L)
+#define MAC1G_CFG_RX_EOP_TS (3346L)
+#define MAC1G_CFG_RX_PAUSE_ENA (3347L)
+#define MAC1G_CFG_SPEED (3348L)
+#define MAC1G_CFG_STR_ENA (3349L)
+#define MAC1G_CFG_TX_ENA (3350L)
+#define MAC1G_CFG_TX_PAUSE_ENA (3351L)
+#define MAC1G_MA_LO (3352L)
+#define MAC1G_MA_LO_MA_LO (3353L)
+#define MAC1G_MA_UP (3354L)
+#define MAC1G_MA_UP_MA_UP (3355L)
+/* MAC_PCS */
+#define MAC_PCS_BAD_CODE (3366L)
+#define MAC_PCS_BAD_CODE_CODE_ERR (3367L)
+#define MAC_PCS_BIP_ERR (3368L)
+#define MAC_PCS_BIP_ERR_BIP_ERR (3369L)
+#define MAC_PCS_BLOCK_LOCK (3370L)
+#define MAC_PCS_BLOCK_LOCK_LOCK (3371L)
+#define MAC_PCS_BLOCK_LOCK_CHG (3372L)
+#define MAC_PCS_BLOCK_LOCK_CHG_LOCK_CHG (3373L)
+#define MAC_PCS_CLKRX_FRQ (3374L)
+#define MAC_PCS_CLKRX_FRQ_RX_FREQ (3375L)
+#define MAC_PCS_CLKTX_FRQ (3376L)
+#define MAC_PCS_CLKTX_FRQ_TX_FREQ (3377L)
+#define MAC_PCS_DEBOUNCE_CTRL (3378L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_DEBOUNCE_LATENCY (3379L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_FORCE_LINK_DOWN (3380L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_LINKUP_LATENCY (3381L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL (3382L)
+#define MAC_PCS_DRP_CONFIG (3383L)
+#define MAC_PCS_DRP_CONFIG_DRP_ADR (3384L)
+#define MAC_PCS_DRP_CONFIG_DRP_DI (3385L)
+#define MAC_PCS_DRP_CONFIG_DRP_EN (3386L)
+#define MAC_PCS_DRP_CONFIG_DRP_MOD_ADR (3387L)
+#define MAC_PCS_DRP_CONFIG_DRP_WREN (3388L)
+#define MAC_PCS_DRP_CTRL (3389L)
+#define MAC_PCS_DRP_CTRL_ADR (3390L)
+#define MAC_PCS_DRP_CTRL_DATA (3391L)
+#define MAC_PCS_DRP_CTRL_DBG_BUSY (3392L)
+#define MAC_PCS_DRP_CTRL_DONE (3393L)
+#define MAC_PCS_DRP_CTRL_MOD_ADR (3394L)
+#define MAC_PCS_DRP_CTRL_WREN (3395L)
+#define MAC_PCS_DRP_DATA (3396L)
+#define MAC_PCS_DRP_DATA_DRP_DO (3397L)
+#define MAC_PCS_DRP_DATA_DRP_RDY (3398L)
+#define MAC_PCS_FEC_CTRL (3399L)
+#define MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN (3400L)
+#define MAC_PCS_FEC_CW_CNT (3401L)
+#define MAC_PCS_FEC_CW_CNT_CW_CNT (3402L)
+#define MAC_PCS_FEC_ERR_CNT_0 (3403L)
+#define MAC_PCS_FEC_ERR_CNT_0_ERR_CNT (3404L)
+#define MAC_PCS_FEC_ERR_CNT_1 (3405L)
+#define MAC_PCS_FEC_ERR_CNT_1_ERR_CNT (3406L)
+#define MAC_PCS_FEC_ERR_CNT_2 (3407L)
+#define MAC_PCS_FEC_ERR_CNT_2_ERR_CNT (3408L)
+#define MAC_PCS_FEC_ERR_CNT_3 (3409L)
+#define MAC_PCS_FEC_ERR_CNT_3_ERR_CNT (3410L)
+#define MAC_PCS_FEC_LANE_DLY_0 (3411L)
+#define MAC_PCS_FEC_LANE_DLY_0_DLY (3412L)
+#define MAC_PCS_FEC_LANE_DLY_1 (3413L)
+#define MAC_PCS_FEC_LANE_DLY_1_DLY (3414L)
+#define MAC_PCS_FEC_LANE_DLY_2 (3415L)
+#define MAC_PCS_FEC_LANE_DLY_2_DLY (3416L)
+#define MAC_PCS_FEC_LANE_DLY_3 (3417L)
+#define MAC_PCS_FEC_LANE_DLY_3_DLY (3418L)
+#define MAC_PCS_FEC_LANE_MAP (3419L)
+#define MAC_PCS_FEC_LANE_MAP_MAPPING (3420L)
+#define MAC_PCS_FEC_STAT (3421L)
+#define MAC_PCS_FEC_STAT_AM_LOCK (3422L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_0 (3423L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_1 (3424L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_2 (3425L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_3 (3426L)
+#define MAC_PCS_FEC_STAT_BLOCK_LOCK (3427L)
+#define MAC_PCS_FEC_STAT_BYPASS (3428L)
+#define MAC_PCS_FEC_STAT_FEC_LANE_ALGN (3429L)
+#define MAC_PCS_FEC_STAT_HI_SER (3430L)
+#define MAC_PCS_FEC_STAT_PCS_LANE_ALGN (3431L)
+#define MAC_PCS_FEC_STAT_VALID (3432L)
+#define MAC_PCS_FEC_UCW_CNT (3433L)
+#define MAC_PCS_FEC_UCW_CNT_UCW_CNT (3434L)
+#define MAC_PCS_FRAMING_ERR (3435L)
+#define MAC_PCS_FRAMING_ERR_FRAMING_ERR (3436L)
+#define MAC_PCS_GTY_CTL (3437L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_0 (3438L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_1 (3439L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_2 (3440L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_3 (3441L)
+#define MAC_PCS_GTY_CTL_RX (3442L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_0 (3443L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_1 (3444L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_2 (3445L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_3 (3446L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_0 (3447L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_1 (3448L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_2 (3449L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_3 (3450L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_0 (3451L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_1 (3452L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_2 (3453L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_3 (3454L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_0 (3455L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_1 (3456L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_2 (3457L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_3 (3458L)
+#define MAC_PCS_GTY_CTL_RX_RATE_0 (3459L)
+#define MAC_PCS_GTY_CTL_RX_RATE_1 (3460L)
+#define MAC_PCS_GTY_CTL_RX_RATE_2 (3461L)
+#define MAC_PCS_GTY_CTL_RX_RATE_3 (3462L)
+#define MAC_PCS_GTY_CTL_TX (3463L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_0 (3464L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_1 (3465L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_2 (3466L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_3 (3467L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_0 (3468L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_1 (3469L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_2 (3470L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_3 (3471L)
+#define MAC_PCS_GTY_DIFF_CTL (3472L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0 (3473L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1 (3474L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2 (3475L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3 (3476L)
+#define MAC_PCS_GTY_LOOP (3477L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_0 (3478L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_1 (3479L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_2 (3480L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_3 (3481L)
+#define MAC_PCS_GTY_POST_CURSOR (3482L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0 (3483L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1 (3484L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2 (3485L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3 (3486L)
+#define MAC_PCS_GTY_PRBS_SEL (3487L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_0 (3488L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_1 (3489L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_2 (3490L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_3 (3491L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_0 (3492L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_1 (3493L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_2 (3494L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_3 (3495L)
+#define MAC_PCS_GTY_PRE_CURSOR (3496L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0 (3497L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1 (3498L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2 (3499L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3 (3500L)
+#define MAC_PCS_GTY_RX_BUF_STAT (3501L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0 (3502L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1 (3503L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2 (3504L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3 (3505L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0 (3506L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1 (3507L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2 (3508L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3 (3509L)
+#define MAC_PCS_GTY_SCAN_CTL (3510L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_0 (3511L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_1 (3512L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_2 (3513L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_3 (3514L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_0 (3515L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_1 (3516L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_2 (3517L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_3 (3518L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_0 (3519L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_1 (3520L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_2 (3521L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_3 (3522L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_0 (3523L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_1 (3524L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_2 (3525L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_3 (3526L)
+#define MAC_PCS_GTY_SCAN_STAT (3527L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_0 (3528L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_1 (3529L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_2 (3530L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_3 (3531L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_0 (3532L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_1 (3533L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_2 (3534L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_3 (3535L)
+#define MAC_PCS_GTY_STAT (3536L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_0 (3537L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_1 (3538L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_2 (3539L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_3 (3540L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_0 (3541L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_1 (3542L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_2 (3543L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_3 (3544L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_0 (3545L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_1 (3546L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_2 (3547L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_3 (3548L)
+#define MAC_PCS_LANE_ALIGNER_FILL (3549L)
+#define MAC_PCS_LANE_ALIGNER_FILL_FILL (3550L)
+#define MAC_PCS_LINK_SUMMARY (3551L)
+#define MAC_PCS_LINK_SUMMARY_ABS (3552L)
+#define MAC_PCS_LINK_SUMMARY_LH_ABS (3553L)
+#define MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT (3554L)
+#define MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT (3555L)
+#define MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT (3556L)
+#define MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE (3557L)
+#define MAC_PCS_LINK_SUMMARY_LOCAL_FAULT (3558L)
+#define MAC_PCS_LINK_SUMMARY_NIM_INTERR (3559L)
+#define MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE (3560L)
+#define MAC_PCS_LINK_SUMMARY_REMOTE_FAULT (3561L)
+#define MAC_PCS_LINK_SUMMARY_RESERVED (3562L)
+#define MAC_PCS_MAC_PCS_CONFIG (3563L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_CORE_RST (3564L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE (3565L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC (3566L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST (3567L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN (3568L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_CORE_RST (3569L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE (3570L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_FCS_REMOVE (3571L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST (3572L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE (3573L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI (3574L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN (3575L)
+#define MAC_PCS_MAX_PKT_LEN (3576L)
+#define MAC_PCS_MAX_PKT_LEN_MAX_LEN (3577L)
+#define MAC_PCS_MF_ERR (3578L)
+#define MAC_PCS_MF_ERR_MF_ERR (3579L)
+#define MAC_PCS_MF_LEN_ERR (3580L)
+#define MAC_PCS_MF_LEN_ERR_MF_LEN_ERR (3581L)
+#define MAC_PCS_MF_REPEAT_ERR (3582L)
+#define MAC_PCS_MF_REPEAT_ERR_MF_REPEAT_ERR (3583L)
+#define MAC_PCS_PHYMAC_MISC (3584L)
+#define MAC_PCS_PHYMAC_MISC_TS_EOP (3585L)
+#define MAC_PCS_PHYMAC_MISC_TX_MUX_STATE (3586L)
+#define MAC_PCS_PHYMAC_MISC_TX_SEL_HOST (3587L)
+#define MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP (3588L)
+#define MAC_PCS_PHYMAC_MISC_TX_SEL_TFG (3589L)
+#define MAC_PCS_PHY_STAT (3590L)
+#define MAC_PCS_PHY_STAT_ALARM (3591L)
+#define MAC_PCS_PHY_STAT_MOD_PRS (3592L)
+#define MAC_PCS_PHY_STAT_RX_LOS (3593L)
+#define MAC_PCS_STAT_PCS_RX (3594L)
+#define MAC_PCS_STAT_PCS_RX_ALIGNED (3595L)
+#define MAC_PCS_STAT_PCS_RX_ALIGNED_ERR (3596L)
+#define MAC_PCS_STAT_PCS_RX_GOT_SIGNAL_OS (3597L)
+#define MAC_PCS_STAT_PCS_RX_HI_BER (3598L)
+#define MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT (3599L)
+#define MAC_PCS_STAT_PCS_RX_LOCAL_FAULT (3600L)
+#define MAC_PCS_STAT_PCS_RX_MISALIGNED (3601L)
+#define MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT (3602L)
+#define MAC_PCS_STAT_PCS_RX_REMOTE_FAULT (3603L)
+#define MAC_PCS_STAT_PCS_RX_STATUS (3604L)
+#define MAC_PCS_STAT_PCS_RX_LATCH (3605L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED (3606L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED_ERR (3607L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_GOT_SIGNAL_OS (3608L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_HI_BER (3609L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_INTERNAL_LOCAL_FAULT (3610L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_LOCAL_FAULT (3611L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_MISALIGNED (3612L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_RECEIVED_LOCAL_FAULT (3613L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_REMOTE_FAULT (3614L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_STATUS (3615L)
+#define MAC_PCS_STAT_PCS_TX (3616L)
+#define MAC_PCS_STAT_PCS_TX_LOCAL_FAULT (3617L)
+#define MAC_PCS_STAT_PCS_TX_LOCAL_FAULT_CHANGED (3618L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR (3619L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR_CHANGED (3620L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR (3621L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR_CHANGED (3622L)
+#define MAC_PCS_STAT_PCS_TX_TX_OVFOUT (3623L)
+#define MAC_PCS_STAT_PCS_TX_TX_OVFOUT_CHANGED (3624L)
+#define MAC_PCS_STAT_PCS_TX_TX_UNFOUT (3625L)
+#define MAC_PCS_STAT_PCS_TX_TX_UNFOUT_CHANGED (3626L)
+#define MAC_PCS_SYNCED (3627L)
+#define MAC_PCS_SYNCED_SYNC (3628L)
+#define MAC_PCS_SYNCED_ERR (3629L)
+#define MAC_PCS_SYNCED_ERR_SYNC_ERROR (3630L)
+#define MAC_PCS_TEST_ERR (3631L)
+#define MAC_PCS_TEST_ERR_CODE_ERR (3632L)
+#define MAC_PCS_TIMESTAMP_COMP (3633L)
+#define MAC_PCS_TIMESTAMP_COMP_RX_DLY (3634L)
+#define MAC_PCS_TIMESTAMP_COMP_TX_DLY (3635L)
+#define MAC_PCS_VL_DEMUXED (3636L)
+#define MAC_PCS_VL_DEMUXED_LOCK (3637L)
+#define MAC_PCS_VL_DEMUXED_CHG (3638L)
+#define MAC_PCS_VL_DEMUXED_CHG_LOCK_CHG (3639L)
+#define MAC_PCS_VL_NUMBER (3640L)
+#define MAC_PCS_VL_NUMBER_VL_NUMBER (3641L)
+/* MAC_PCS_XXV */
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0 (3642L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_ASMDIR (3643L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_BYPASS (3644L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_ENABLE (3645L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_PAUSE (3646L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_RESTART (3647L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1 (3648L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_ASMDIR (3649L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_BYPASS (3650L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_ENABLE (3651L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_PAUSE (3652L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_RESTART (3653L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0 (3654L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_COMPLETE (3655L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_ANEG_ABLE (3656L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_ASM (3657L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_PAUSE (3658L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_RF (3659L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1 (3660L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_COMPLETE (3661L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_ANEG_ABLE (3662L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_ASM (3663L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_PAUSE (3664L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_RF (3665L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0 (3666L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR (3667L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1 (3668L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S (3669L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR (3670L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1 (3671L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S (3672L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1 (3673L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR (3674L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1 (3675L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S (3676L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR (3677L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1 (3678L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S (3679L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2 (3680L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR (3681L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR1 (3682L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR_S (3683L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR (3684L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1 (3685L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S (3686L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3 (3687L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR (3688L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR1 (3689L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR_S (3690L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR (3691L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1 (3692L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S (3693L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0 (3694L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR (3695L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS (3696L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE (3697L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST (3698L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G (3699L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY (3700L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST (3701L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74 (3702L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED (3703L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE (3704L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO (3705L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT (3706L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_RESTART (3707L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST (3708L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE (3709L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE (3710L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1 (3711L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR (3712L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS (3713L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE (3714L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST (3715L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G (3716L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY (3717L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST (3718L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74 (3719L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED (3720L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE (3721L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO (3722L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT (3723L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_RESTART (3724L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST (3725L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE (3726L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE (3727L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2 (3728L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR (3729L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS (3730L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE (3731L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST (3732L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G (3733L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY (3734L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST (3735L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74 (3736L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED (3737L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE (3738L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO (3739L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT (3740L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_RESTART (3741L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST (3742L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE (3743L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE (3744L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3 (3745L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR (3746L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS (3747L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE (3748L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST (3749L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G (3750L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY (3751L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST (3752L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74 (3753L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED (3754L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE (3755L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO (3756L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT (3757L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_RESTART (3758L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST (3759L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE (3760L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE (3761L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0 (3762L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_ANEG_END (3763L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_ANEG_STARTED (3764L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_CDR_HOLD (3765L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_LT_END (3766L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_LT_STARTED (3767L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1 (3768L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_ANEG_END (3769L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_ANEG_STARTED (3770L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_CDR_HOLD (3771L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_LT_END (3772L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_LT_STARTED (3773L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2 (3774L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_ANEG_END (3775L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_ANEG_STARTED (3776L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_CDR_HOLD (3777L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_LT_END (3778L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_LT_STARTED (3779L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3 (3780L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_ANEG_END (3781L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_ANEG_STARTED (3782L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_CDR_HOLD (3783L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_LT_END (3784L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_LT_STARTED (3785L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0 (3786L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR (3787L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR1 (3788L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR_S (3789L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1 (3790L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR (3791L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR1 (3792L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR_S (3793L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2 (3794L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR (3795L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR1 (3796L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR_S (3797L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3 (3798L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR (3799L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR1 (3800L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR_S (3801L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0 (3802L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0_LP_25GBASE_CR (3803L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0_LP_25GBASE_CR_S (3804L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1 (3805L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1_LP_25GBASE_CR (3806L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1_LP_25GBASE_CR_S (3807L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2 (3808L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2_LP_25GBASE_CR (3809L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2_LP_25GBASE_CR_S (3810L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3 (3811L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3_LP_25GBASE_CR (3812L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3_LP_25GBASE_CR_S (3813L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0 (3814L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC74_ABILITY (3815L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC74_REQUEST (3816L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC91_ABILITY (3817L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC91_REQUEST (3818L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_LP_25GBASE_CR1 (3819L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_LP_EX_ABILITY_VALID (3820L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1 (3821L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC74_ABILITY (3822L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC74_REQUEST (3823L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC91_ABILITY (3824L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC91_REQUEST (3825L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_LP_25GBASE_CR1 (3826L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_LP_EX_ABILITY_VALID (3827L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2 (3828L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC74_ABILITY (3829L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC74_REQUEST (3830L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC91_ABILITY (3831L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC91_REQUEST (3832L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_LP_25GBASE_CR1 (3833L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_LP_EX_ABILITY_VALID (3834L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3 (3835L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC74_ABILITY (3836L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC74_REQUEST (3837L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC91_ABILITY (3838L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC91_REQUEST (3839L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_LP_25GBASE_CR1 (3840L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_LP_EX_ABILITY_VALID (3841L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0 (3842L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ABILITY_VALID (3843L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ANEG_ABLE (3844L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ASM (3845L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_FEC74_REQ (3846L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_PAUSE (3847L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_RF (3848L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_RS_FEC_REQ (3849L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1 (3850L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ABILITY_VALID (3851L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ANEG_ABLE (3852L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ASM (3853L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_FEC74_REQ (3854L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_PAUSE (3855L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_RF (3856L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_RS_FEC_REQ (3857L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2 (3858L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ABILITY_VALID (3859L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ANEG_ABLE (3860L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ASM (3861L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_FEC74_REQ (3862L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_PAUSE (3863L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_RF (3864L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_RS_FEC_REQ (3865L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3 (3866L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ABILITY_VALID (3867L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ANEG_ABLE (3868L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ASM (3869L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_FEC74_REQ (3870L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_PAUSE (3871L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_RF (3872L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_RS_FEC_REQ (3873L)
+#define MAC_PCS_XXV_ANEG_STA_0 (3874L)
+#define MAC_PCS_XXV_ANEG_STA_0_COMPLETE (3875L)
+#define MAC_PCS_XXV_ANEG_STA_0_FEC74_EN (3876L)
+#define MAC_PCS_XXV_ANEG_STA_0_PAR_D_FAULT (3877L)
+#define MAC_PCS_XXV_ANEG_STA_0_RS_FEC_EN (3878L)
+#define MAC_PCS_XXV_ANEG_STA_0_RX_PAUSE_EN (3879L)
+#define MAC_PCS_XXV_ANEG_STA_0_TX_PAUSE_EN (3880L)
+#define MAC_PCS_XXV_ANEG_STA_1 (3881L)
+#define MAC_PCS_XXV_ANEG_STA_1_COMPLETE (3882L)
+#define MAC_PCS_XXV_ANEG_STA_1_FEC74_EN (3883L)
+#define MAC_PCS_XXV_ANEG_STA_1_PAR_D_FAULT (3884L)
+#define MAC_PCS_XXV_ANEG_STA_1_RS_FEC_EN (3885L)
+#define MAC_PCS_XXV_ANEG_STA_1_RX_PAUSE_EN (3886L)
+#define MAC_PCS_XXV_ANEG_STA_1_TX_PAUSE_EN (3887L)
+#define MAC_PCS_XXV_ANEG_STA_2 (3888L)
+#define MAC_PCS_XXV_ANEG_STA_2_COMPLETE (3889L)
+#define MAC_PCS_XXV_ANEG_STA_2_FEC74_EN (3890L)
+#define MAC_PCS_XXV_ANEG_STA_2_PAR_D_FAULT (3891L)
+#define MAC_PCS_XXV_ANEG_STA_2_RS_FEC_EN (3892L)
+#define MAC_PCS_XXV_ANEG_STA_2_RX_PAUSE_EN (3893L)
+#define MAC_PCS_XXV_ANEG_STA_2_TX_PAUSE_EN (3894L)
+#define MAC_PCS_XXV_ANEG_STA_3 (3895L)
+#define MAC_PCS_XXV_ANEG_STA_3_COMPLETE (3896L)
+#define MAC_PCS_XXV_ANEG_STA_3_FEC74_EN (3897L)
+#define MAC_PCS_XXV_ANEG_STA_3_PAR_D_FAULT (3898L)
+#define MAC_PCS_XXV_ANEG_STA_3_RS_FEC_EN (3899L)
+#define MAC_PCS_XXV_ANEG_STA_3_RX_PAUSE_EN (3900L)
+#define MAC_PCS_XXV_ANEG_STA_3_TX_PAUSE_EN (3901L)
+#define MAC_PCS_XXV_CLK_REF_ACTIVITY (3902L)
+#define MAC_PCS_XXV_CLK_REF_ACTIVITY_COUNT (3903L)
+#define MAC_PCS_XXV_CORE_CONF_0 (3904L)
+#define MAC_PCS_XXV_CORE_CONF_0_ENHANCED_TS (3905L)
+#define MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE (3906L)
+#define MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK (3907L)
+#define MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE (3908L)
+#define MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC (3909L)
+#define MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP (3910L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE (3911L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS (3912L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS (3913L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE (3914L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI (3915L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI (3916L)
+#define MAC_PCS_XXV_CORE_CONF_1 (3917L)
+#define MAC_PCS_XXV_CORE_CONF_1_ENHANCED_TS (3918L)
+#define MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE (3919L)
+#define MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK (3920L)
+#define MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE (3921L)
+#define MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC (3922L)
+#define MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP (3923L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE (3924L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS (3925L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS (3926L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE (3927L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI (3928L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI (3929L)
+#define MAC_PCS_XXV_CORE_CONF_2 (3930L)
+#define MAC_PCS_XXV_CORE_CONF_2_ENHANCED_TS (3931L)
+#define MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE (3932L)
+#define MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK (3933L)
+#define MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE (3934L)
+#define MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC (3935L)
+#define MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP (3936L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE (3937L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS (3938L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS (3939L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE (3940L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI (3941L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI (3942L)
+#define MAC_PCS_XXV_CORE_CONF_3 (3943L)
+#define MAC_PCS_XXV_CORE_CONF_3_ENHANCED_TS (3944L)
+#define MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE (3945L)
+#define MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK (3946L)
+#define MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE (3947L)
+#define MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC (3948L)
+#define MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP (3949L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE (3950L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS (3951L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS (3952L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE (3953L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI (3954L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI (3955L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0 (3956L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_DEBOUNCE_LATENCY (3957L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_FORCE_LINK_DOWN (3958L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_LINKUP_LATENCY (3959L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL (3960L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1 (3961L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_DEBOUNCE_LATENCY (3962L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_FORCE_LINK_DOWN (3963L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_LINKUP_LATENCY (3964L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL (3965L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2 (3966L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_DEBOUNCE_LATENCY (3967L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_FORCE_LINK_DOWN (3968L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_LINKUP_LATENCY (3969L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL (3970L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3 (3971L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_DEBOUNCE_LATENCY (3972L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_FORCE_LINK_DOWN (3973L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_LINKUP_LATENCY (3974L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL (3975L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_0 (3976L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_0_FEC74_CCW_CNT (3977L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_1 (3978L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_1_FEC74_CCW_CNT (3979L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_2 (3980L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_2_FEC74_CCW_CNT (3981L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_3 (3982L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_3_FEC74_CCW_CNT (3983L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0 (3984L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0_FEC74_ERRORS_TO_PCS (3985L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0_RX_FEC74_ENABLE (3986L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0_TX_FEC74_ENABLE (3987L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1 (3988L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1_FEC74_ERRORS_TO_PCS (3989L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1_RX_FEC74_ENABLE (3990L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1_TX_FEC74_ENABLE (3991L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2 (3992L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2_FEC74_ERRORS_TO_PCS (3993L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2_RX_FEC74_ENABLE (3994L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2_TX_FEC74_ENABLE (3995L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3 (3996L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3_FEC74_ERRORS_TO_PCS (3997L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3_RX_FEC74_ENABLE (3998L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3_TX_FEC74_ENABLE (3999L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_0 (4000L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_0_FEC74_UCW_CNT (4001L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_1 (4002L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_1_FEC74_UCW_CNT (4003L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_2 (4004L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_2_FEC74_UCW_CNT (4005L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_3 (4006L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_3_FEC74_UCW_CNT (4007L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0 (4008L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_CDR_HOLD (4009L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST (4010L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN (4011L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY (4012L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_RATE (4013L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1 (4014L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_CDR_HOLD (4015L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST (4016L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN (4017L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY (4018L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_RATE (4019L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2 (4020L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_CDR_HOLD (4021L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST (4022L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN (4023L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY (4024L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_RATE (4025L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3 (4026L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_CDR_HOLD (4027L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST (4028L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN (4029L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY (4030L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_RATE (4031L)
+#define MAC_PCS_XXV_GTY_CTL_TX_0 (4032L)
+#define MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT (4033L)
+#define MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY (4034L)
+#define MAC_PCS_XXV_GTY_CTL_TX_1 (4035L)
+#define MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT (4036L)
+#define MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY (4037L)
+#define MAC_PCS_XXV_GTY_CTL_TX_2 (4038L)
+#define MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT (4039L)
+#define MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY (4040L)
+#define MAC_PCS_XXV_GTY_CTL_TX_3 (4041L)
+#define MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT (4042L)
+#define MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY (4043L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_0 (4044L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL (4045L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL_ADJUSTED (4046L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_1 (4047L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL (4048L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL_ADJUSTED (4049L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_2 (4050L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL (4051L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL_ADJUSTED (4052L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_3 (4053L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL (4054L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL_ADJUSTED (4055L)
+#define MAC_PCS_XXV_GTY_LOOP_0 (4056L)
+#define MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP (4057L)
+#define MAC_PCS_XXV_GTY_LOOP_1 (4058L)
+#define MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP (4059L)
+#define MAC_PCS_XXV_GTY_LOOP_2 (4060L)
+#define MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP (4061L)
+#define MAC_PCS_XXV_GTY_LOOP_3 (4062L)
+#define MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP (4063L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_0 (4064L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_0_TX_MAIN_CTL (4065L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_1 (4066L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_1_TX_MAIN_CTL (4067L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_2 (4068L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_2_TX_MAIN_CTL (4069L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_3 (4070L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_3_TX_MAIN_CTL (4071L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_0 (4072L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR (4073L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR_ADJUSTED (4074L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_1 (4075L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR (4076L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR_ADJUSTED (4077L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_2 (4078L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR (4079L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR_ADJUSTED (4080L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_3 (4081L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR (4082L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR_ADJUSTED (4083L)
+#define MAC_PCS_XXV_GTY_PRBS_0 (4084L)
+#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_ERR (4085L)
+#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_ERR_INS (4086L)
+#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_RST (4087L)
+#define MAC_PCS_XXV_GTY_PRBS_0_RX_PRBS_SEL (4088L)
+#define MAC_PCS_XXV_GTY_PRBS_0_TX_PRBS_SEL (4089L)
+#define MAC_PCS_XXV_GTY_PRBS_1 (4090L)
+#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_ERR (4091L)
+#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_ERR_INS (4092L)
+#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_RST (4093L)
+#define MAC_PCS_XXV_GTY_PRBS_1_RX_PRBS_SEL (4094L)
+#define MAC_PCS_XXV_GTY_PRBS_1_TX_PRBS_SEL (4095L)
+#define MAC_PCS_XXV_GTY_PRBS_2 (4096L)
+#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_ERR (4097L)
+#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_ERR_INS (4098L)
+#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_RST (4099L)
+#define MAC_PCS_XXV_GTY_PRBS_2_RX_PRBS_SEL (4100L)
+#define MAC_PCS_XXV_GTY_PRBS_2_TX_PRBS_SEL (4101L)
+#define MAC_PCS_XXV_GTY_PRBS_3 (4102L)
+#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_ERR (4103L)
+#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_ERR_INS (4104L)
+#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_RST (4105L)
+#define MAC_PCS_XXV_GTY_PRBS_3_RX_PRBS_SEL (4106L)
+#define MAC_PCS_XXV_GTY_PRBS_3_TX_PRBS_SEL (4107L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_0 (4108L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_0_COUNT (4109L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_1 (4110L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_1_COUNT (4111L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_2 (4112L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_2_COUNT (4113L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_3 (4114L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_3_COUNT (4115L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_0 (4116L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR (4117L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR_ADJUSTED (4118L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_1 (4119L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR (4120L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR_ADJUSTED (4121L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_2 (4122L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR (4123L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR_ADJUSTED (4124L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_3 (4125L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR (4126L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR_ADJUSTED (4127L)
+#define MAC_PCS_XXV_GTY_STATUS_0 (4128L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_POWERGOOD (4129L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_RXBUFSTATUS (4130L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_STARTOFSEQ (4131L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_TXBUFSTATUS (4132L)
+#define MAC_PCS_XXV_GTY_STATUS_1 (4133L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_POWERGOOD (4134L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_RXBUFSTATUS (4135L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_STARTOFSEQ (4136L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_TXBUFSTATUS (4137L)
+#define MAC_PCS_XXV_GTY_STATUS_2 (4138L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_POWERGOOD (4139L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_RXBUFSTATUS (4140L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_STARTOFSEQ (4141L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_TXBUFSTATUS (4142L)
+#define MAC_PCS_XXV_GTY_STATUS_3 (4143L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_POWERGOOD (4144L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_RXBUFSTATUS (4145L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_STARTOFSEQ (4146L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_TXBUFSTATUS (4147L)
+#define MAC_PCS_XXV_LATENCY_0 (4148L)
+#define MAC_PCS_XXV_LATENCY_0_RX_LATENCY_MEAS (4149L)
+#define MAC_PCS_XXV_LATENCY_1 (4150L)
+#define MAC_PCS_XXV_LATENCY_1_RX_LATENCY_MEAS (4151L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0 (4152L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_MAIN (4153L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_POST (4154L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_PRE (4155L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_MAIN (4156L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_POST (4157L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_PRE (4158L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INIT (4159L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_PRESET (4160L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1 (4161L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_MAIN (4162L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_POST (4163L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_PRE (4164L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_MAIN (4165L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_POST (4166L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_PRE (4167L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INIT (4168L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_PRESET (4169L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2 (4170L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_MAIN (4171L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_POST (4172L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_PRE (4173L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_MAIN (4174L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_POST (4175L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_PRE (4176L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INIT (4177L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_PRESET (4178L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3 (4179L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_MAIN (4180L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_POST (4181L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_PRE (4182L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_MAIN (4183L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_POST (4184L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_PRE (4185L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INIT (4186L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_PRESET (4187L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0 (4188L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0_MAIN_STA (4189L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0_POST_STA (4190L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0_PRE_STA (4191L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1 (4192L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1_MAIN_STA (4193L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1_POST_STA (4194L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1_PRE_STA (4195L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2 (4196L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2_MAIN_STA (4197L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2_POST_STA (4198L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2_PRE_STA (4199L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3 (4200L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3_MAIN_STA (4201L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3_POST_STA (4202L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3_PRE_STA (4203L)
+#define MAC_PCS_XXV_LINK_SPEED_0 (4204L)
+#define MAC_PCS_XXV_LINK_SPEED_0_10G (4205L)
+#define MAC_PCS_XXV_LINK_SPEED_0_SPEED (4206L)
+#define MAC_PCS_XXV_LINK_SPEED_0_TOGGLE (4207L)
+#define MAC_PCS_XXV_LINK_SPEED_1 (4208L)
+#define MAC_PCS_XXV_LINK_SPEED_1_10G (4209L)
+#define MAC_PCS_XXV_LINK_SPEED_1_SPEED (4210L)
+#define MAC_PCS_XXV_LINK_SPEED_1_TOGGLE (4211L)
+#define MAC_PCS_XXV_LINK_SPEED_2 (4212L)
+#define MAC_PCS_XXV_LINK_SPEED_2_10G (4213L)
+#define MAC_PCS_XXV_LINK_SPEED_2_SPEED (4214L)
+#define MAC_PCS_XXV_LINK_SPEED_2_TOGGLE (4215L)
+#define MAC_PCS_XXV_LINK_SPEED_3 (4216L)
+#define MAC_PCS_XXV_LINK_SPEED_3_10G (4217L)
+#define MAC_PCS_XXV_LINK_SPEED_3_SPEED (4218L)
+#define MAC_PCS_XXV_LINK_SPEED_3_TOGGLE (4219L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0 (4220L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_ABS (4221L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_ANEG_COMPLETE (4222L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_ANEG_CONSORTIUM_MISMATCH (4223L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_INTERNAL_LOCAL_FAULT (4224L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS (4225L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT (4226L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT (4227L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT (4228L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT (4229L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_FEC74_LOCK_ERROR (4230L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE (4231L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE (4232L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER (4233L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_TX_LOCAL_FAULT (4234L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_TX_UNDERRUN (4235L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT (4236L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE (4237L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK (4238L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK (4239L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT (4240L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT (4241L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LT_DONE (4242L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR (4243L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE (4244L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1 (4245L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_ABS (4246L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_ANEG_COMPLETE (4247L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_ANEG_CONSORTIUM_MISMATCH (4248L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_INTERNAL_LOCAL_FAULT (4249L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS (4250L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT (4251L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT (4252L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT (4253L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT (4254L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_FEC74_LOCK_ERROR (4255L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE (4256L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE (4257L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER (4258L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_TX_LOCAL_FAULT (4259L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_TX_UNDERRUN (4260L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT (4261L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE (4262L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK (4263L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK (4264L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT (4265L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT (4266L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LT_DONE (4267L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR (4268L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE (4269L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2 (4270L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_ABS (4271L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_ANEG_COMPLETE (4272L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_ANEG_CONSORTIUM_MISMATCH (4273L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_INTERNAL_LOCAL_FAULT (4274L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS (4275L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT (4276L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT (4277L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT (4278L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT (4279L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_FEC74_LOCK_ERROR (4280L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE (4281L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE (4282L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER (4283L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_TX_LOCAL_FAULT (4284L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_TX_UNDERRUN (4285L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT (4286L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE (4287L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK (4288L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK (4289L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT (4290L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT (4291L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LT_DONE (4292L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR (4293L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE (4294L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3 (4295L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_ABS (4296L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_ANEG_COMPLETE (4297L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_ANEG_CONSORTIUM_MISMATCH (4298L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_INTERNAL_LOCAL_FAULT (4299L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS (4300L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT (4301L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT (4302L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT (4303L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT (4304L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_FEC74_LOCK_ERROR (4305L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE (4306L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE (4307L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER (4308L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_TX_LOCAL_FAULT (4309L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_TX_UNDERRUN (4310L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT (4311L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE (4312L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK (4313L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK (4314L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT (4315L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT (4316L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LT_DONE (4317L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR (4318L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE (4319L)
+#define MAC_PCS_XXV_LT_CONF_0 (4320L)
+#define MAC_PCS_XXV_LT_CONF_0_ENABLE (4321L)
+#define MAC_PCS_XXV_LT_CONF_0_RESTART (4322L)
+#define MAC_PCS_XXV_LT_CONF_0_SEED (4323L)
+#define MAC_PCS_XXV_LT_CONF_1 (4324L)
+#define MAC_PCS_XXV_LT_CONF_1_ENABLE (4325L)
+#define MAC_PCS_XXV_LT_CONF_1_RESTART (4326L)
+#define MAC_PCS_XXV_LT_CONF_1_SEED (4327L)
+#define MAC_PCS_XXV_LT_CONF_2 (4328L)
+#define MAC_PCS_XXV_LT_CONF_2_ENABLE (4329L)
+#define MAC_PCS_XXV_LT_CONF_2_RESTART (4330L)
+#define MAC_PCS_XXV_LT_CONF_2_SEED (4331L)
+#define MAC_PCS_XXV_LT_CONF_3 (4332L)
+#define MAC_PCS_XXV_LT_CONF_3_ENABLE (4333L)
+#define MAC_PCS_XXV_LT_CONF_3_RESTART (4334L)
+#define MAC_PCS_XXV_LT_CONF_3_SEED (4335L)
+#define MAC_PCS_XXV_LT_STA_0 (4336L)
+#define MAC_PCS_XXV_LT_STA_0_DONE (4337L)
+#define MAC_PCS_XXV_LT_STA_0_FAIL (4338L)
+#define MAC_PCS_XXV_LT_STA_0_LOCK (4339L)
+#define MAC_PCS_XXV_LT_STA_0_TRAIN (4340L)
+#define MAC_PCS_XXV_LT_STA_1 (4341L)
+#define MAC_PCS_XXV_LT_STA_1_DONE (4342L)
+#define MAC_PCS_XXV_LT_STA_1_FAIL (4343L)
+#define MAC_PCS_XXV_LT_STA_1_LOCK (4344L)
+#define MAC_PCS_XXV_LT_STA_1_TRAIN (4345L)
+#define MAC_PCS_XXV_LT_STA_2 (4346L)
+#define MAC_PCS_XXV_LT_STA_2_DONE (4347L)
+#define MAC_PCS_XXV_LT_STA_2_FAIL (4348L)
+#define MAC_PCS_XXV_LT_STA_2_LOCK (4349L)
+#define MAC_PCS_XXV_LT_STA_2_TRAIN (4350L)
+#define MAC_PCS_XXV_LT_STA_3 (4351L)
+#define MAC_PCS_XXV_LT_STA_3_DONE (4352L)
+#define MAC_PCS_XXV_LT_STA_3_FAIL (4353L)
+#define MAC_PCS_XXV_LT_STA_3_LOCK (4354L)
+#define MAC_PCS_XXV_LT_STA_3_TRAIN (4355L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0 (4356L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0_ATTRIB (4357L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0_NEXT (4358L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0_PREV (4359L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1 (4360L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1_ATTRIB (4361L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1_NEXT (4362L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1_PREV (4363L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2 (4364L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2_ATTRIB (4365L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2_NEXT (4366L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2_PREV (4367L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3 (4368L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3_ATTRIB (4369L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3_NEXT (4370L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3_PREV (4371L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0 (4372L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_ATTRIB (4373L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_NEXT (4374L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_PREV (4375L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_SEL (4376L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_TABLE_ADDR (4377L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_UPDATE (4378L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1 (4379L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_ATTRIB (4380L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_NEXT (4381L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_PREV (4382L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_SEL (4383L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_TABLE_ADDR (4384L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_UPDATE (4385L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2 (4386L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_ATTRIB (4387L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_NEXT (4388L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_PREV (4389L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_SEL (4390L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_TABLE_ADDR (4391L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_UPDATE (4392L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3 (4393L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_ATTRIB (4394L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_NEXT (4395L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_PREV (4396L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_SEL (4397L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_TABLE_ADDR (4398L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_UPDATE (4399L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_0 (4400L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_0_RX_MAX_LENGTH (4401L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_1 (4402L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_1_RX_MAX_LENGTH (4403L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_2 (4404L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_2_RX_MAX_LENGTH (4405L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_3 (4406L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_3_RX_MAX_LENGTH (4407L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0 (4408L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0_MIN_RX_FRAME (4409L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0_RX_MIN_LENGTH (4410L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1 (4411L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1_MIN_RX_FRAME (4412L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1_RX_MIN_LENGTH (4413L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2 (4414L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2_MIN_RX_FRAME (4415L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2_RX_MIN_LENGTH (4416L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3 (4417L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3_MIN_RX_FRAME (4418L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3_RX_MIN_LENGTH (4419L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_0 (4420L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_0_MAX_LEN (4421L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_1 (4422L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_1_MAX_LEN (4423L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_2 (4424L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_2_MAX_LEN (4425L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_3 (4426L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_3_MAX_LEN (4427L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0 (4428L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_MAIN (4429L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_POST (4430L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_PRE (4431L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ENABLE (4432L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_INIT (4433L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_PRESET (4434L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_RX_READY (4435L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1 (4436L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_MAIN (4437L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_POST (4438L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_PRE (4439L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ENABLE (4440L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_INIT (4441L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_PRESET (4442L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_RX_READY (4443L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2 (4444L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_MAIN (4445L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_POST (4446L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_PRE (4447L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ENABLE (4448L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_INIT (4449L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_PRESET (4450L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_RX_READY (4451L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3 (4452L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_MAIN (4453L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_POST (4454L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_PRE (4455L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ENABLE (4456L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_INIT (4457L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_PRESET (4458L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_RX_READY (4459L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0 (4460L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_MAIN_STA (4461L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_POST_STA (4462L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_PRE_STA (4463L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1 (4464L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_MAIN_STA (4465L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_POST_STA (4466L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_PRE_STA (4467L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2 (4468L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_MAIN_STA (4469L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_POST_STA (4470L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_PRE_STA (4471L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3 (4472L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_MAIN_STA (4473L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_POST_STA (4474L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_PRE_STA (4475L)
+#define MAC_PCS_XXV_RST_0 (4476L)
+#define MAC_PCS_XXV_RST_0_MAC_PCS (4477L)
+#define MAC_PCS_XXV_RST_1 (4478L)
+#define MAC_PCS_XXV_RST_1_MAC_PCS (4479L)
+#define MAC_PCS_XXV_RST_2 (4480L)
+#define MAC_PCS_XXV_RST_2_MAC_PCS (4481L)
+#define MAC_PCS_XXV_RST_3 (4482L)
+#define MAC_PCS_XXV_RST_3_MAC_PCS (4483L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_0 (4484L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT (4485L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_1 (4486L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT (4487L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_2 (4488L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT (4489L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_3 (4490L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT (4491L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0 (4492L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_CONSORTIUM (4493L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_CORRECTION (4494L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE (4495L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_IEEE_ERROR_INDICATION (4496L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_INDICATION (4497L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1 (4498L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_CONSORTIUM (4499L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_CORRECTION (4500L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE (4501L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_IEEE_ERROR_INDICATION (4502L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_INDICATION (4503L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2 (4504L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_CONSORTIUM (4505L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_CORRECTION (4506L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE (4507L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_IEEE_ERROR_INDICATION (4508L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_INDICATION (4509L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3 (4510L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_CONSORTIUM (4511L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_CORRECTION (4512L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE (4513L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_IEEE_ERROR_INDICATION (4514L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_INDICATION (4515L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_0 (4516L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_0_RS_FEC_ERR_CNT (4517L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_1 (4518L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_1_RS_FEC_ERR_CNT (4519L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_2 (4520L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_2_RS_FEC_ERR_CNT (4521L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_3 (4522L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_3_RS_FEC_ERR_CNT (4523L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_0 (4524L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT (4525L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_1 (4526L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT (4527L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_2 (4528L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT (4529L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_3 (4530L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT (4531L)
+#define MAC_PCS_XXV_RX_BAD_FCS_0 (4532L)
+#define MAC_PCS_XXV_RX_BAD_FCS_0_COUNT (4533L)
+#define MAC_PCS_XXV_RX_BAD_FCS_1 (4534L)
+#define MAC_PCS_XXV_RX_BAD_FCS_1_COUNT (4535L)
+#define MAC_PCS_XXV_RX_BAD_FCS_2 (4536L)
+#define MAC_PCS_XXV_RX_BAD_FCS_2_COUNT (4537L)
+#define MAC_PCS_XXV_RX_BAD_FCS_3 (4538L)
+#define MAC_PCS_XXV_RX_BAD_FCS_3_COUNT (4539L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_0 (4540L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_0_COUNT (4541L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_1 (4542L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_1_COUNT (4543L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_2 (4544L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_2_COUNT (4545L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_3 (4546L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_3_COUNT (4547L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_0 (4548L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_0_COUNT (4549L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_1 (4550L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_1_COUNT (4551L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_2 (4552L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_2_COUNT (4553L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_3 (4554L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_3_COUNT (4555L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_0 (4556L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_0_COUNT (4557L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_1 (4558L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_1_COUNT (4559L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_2 (4560L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_2_COUNT (4561L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_3 (4562L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_3_COUNT (4563L)
+#define MAC_PCS_XXV_RX_LATENCY_0 (4564L)
+#define MAC_PCS_XXV_RX_LATENCY_0_LATENCY (4565L)
+#define MAC_PCS_XXV_RX_LATENCY_1 (4566L)
+#define MAC_PCS_XXV_RX_LATENCY_1_LATENCY (4567L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_0 (4568L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_0_COUNT (4569L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_1 (4570L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_1_COUNT (4571L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_2 (4572L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_2_COUNT (4573L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_3 (4574L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_3_COUNT (4575L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_0 (4576L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_0_COUNT (4577L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_1 (4578L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_1_COUNT (4579L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_2 (4580L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_2_COUNT (4581L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_3 (4582L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_3_COUNT (4583L)
+#define MAC_PCS_XXV_SUB_RST_0 (4584L)
+#define MAC_PCS_XXV_SUB_RST_0_AN_LT (4585L)
+#define MAC_PCS_XXV_SUB_RST_0_QPLL (4586L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_BUF (4587L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA (4588L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS (4589L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_PCS (4590L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_PMA (4591L)
+#define MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL (4592L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA (4593L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS (4594L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_PCS (4595L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_PMA (4596L)
+#define MAC_PCS_XXV_SUB_RST_1 (4597L)
+#define MAC_PCS_XXV_SUB_RST_1_AN_LT (4598L)
+#define MAC_PCS_XXV_SUB_RST_1_QPLL (4599L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_BUF (4600L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA (4601L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS (4602L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_PCS (4603L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_PMA (4604L)
+#define MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL (4605L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA (4606L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS (4607L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_PCS (4608L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_PMA (4609L)
+#define MAC_PCS_XXV_SUB_RST_2 (4610L)
+#define MAC_PCS_XXV_SUB_RST_2_AN_LT (4611L)
+#define MAC_PCS_XXV_SUB_RST_2_QPLL (4612L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_BUF (4613L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA (4614L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS (4615L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_PCS (4616L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_PMA (4617L)
+#define MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL (4618L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA (4619L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS (4620L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_PCS (4621L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_PMA (4622L)
+#define MAC_PCS_XXV_SUB_RST_3 (4623L)
+#define MAC_PCS_XXV_SUB_RST_3_AN_LT (4624L)
+#define MAC_PCS_XXV_SUB_RST_3_QPLL (4625L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_BUF (4626L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA (4627L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS (4628L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_PCS (4629L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_PMA (4630L)
+#define MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL (4631L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA (4632L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS (4633L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_PCS (4634L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_PMA (4635L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0 (4636L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK (4637L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST (4638L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST (4639L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1 (4640L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK (4641L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST (4642L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST (4643L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2 (4644L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK (4645L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST (4646L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST (4647L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3 (4648L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK (4649L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST (4650L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST (4651L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_0 (4652L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY (4653L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY (4654L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_1 (4655L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY (4656L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY (4657L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_2 (4658L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY (4659L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY (4660L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_3 (4661L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY (4662L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY (4663L)
+#define MAC_PCS_XXV_TX_BAD_FCS_0 (4664L)
+#define MAC_PCS_XXV_TX_BAD_FCS_0_COUNT (4665L)
+#define MAC_PCS_XXV_TX_BAD_FCS_1 (4666L)
+#define MAC_PCS_XXV_TX_BAD_FCS_1_COUNT (4667L)
+#define MAC_PCS_XXV_TX_BAD_FCS_2 (4668L)
+#define MAC_PCS_XXV_TX_BAD_FCS_2_COUNT (4669L)
+#define MAC_PCS_XXV_TX_BAD_FCS_3 (4670L)
+#define MAC_PCS_XXV_TX_BAD_FCS_3_COUNT (4671L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_0 (4672L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_0_COUNT (4673L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_1 (4674L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_1_COUNT (4675L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_2 (4676L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_2_COUNT (4677L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_3 (4678L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_3_COUNT (4679L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_0 (4680L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_0_COUNT (4681L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_1 (4682L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_1_COUNT (4683L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_2 (4684L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_2_COUNT (4685L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_3 (4686L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_3_COUNT (4687L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_0 (4688L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_0_COUNT (4689L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_1 (4690L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_1_COUNT (4691L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_2 (4692L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_2_COUNT (4693L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_3 (4694L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_3_COUNT (4695L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_0 (4696L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_0_COUNT (4697L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_1 (4698L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_1_COUNT (4699L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_2 (4700L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_2_COUNT (4701L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_3 (4702L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_3_COUNT (4703L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_0 (4704L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_0_COUNT (4705L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_1 (4706L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_1_COUNT (4707L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_2 (4708L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_2_COUNT (4709L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_3 (4710L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_3_COUNT (4711L)
+/* MAC_RX */
+#define MAC_RX_BAD_FCS (4712L)
+#define MAC_RX_BAD_FCS_COUNT (4713L)
+#define MAC_RX_BAD_PREAMBLE (4714L)
+#define MAC_RX_BAD_PREAMBLE_COUNT (4715L)
+#define MAC_RX_BAD_SFD (4716L)
+#define MAC_RX_BAD_SFD_COUNT (4717L)
+#define MAC_RX_BROADCAST (4718L)
+#define MAC_RX_BROADCAST_COUNT (4719L)
+#define MAC_RX_FRAGMENT (4720L)
+#define MAC_RX_FRAGMENT_COUNT (4721L)
+#define MAC_RX_INRANGEERR (4722L)
+#define MAC_RX_INRANGEERR_COUNT (4723L)
+#define MAC_RX_JABBER (4724L)
+#define MAC_RX_JABBER_COUNT (4725L)
+#define MAC_RX_MULTICAST (4726L)
+#define MAC_RX_MULTICAST_COUNT (4727L)
+#define MAC_RX_OVERSIZE (4728L)
+#define MAC_RX_OVERSIZE_COUNT (4729L)
+#define MAC_RX_PACKET_1024_1518_BYTES (4730L)
+#define MAC_RX_PACKET_1024_1518_BYTES_COUNT (4731L)
+#define MAC_RX_PACKET_128_255_BYTES (4732L)
+#define MAC_RX_PACKET_128_255_BYTES_COUNT (4733L)
+#define MAC_RX_PACKET_1519_1522_BYTES (4734L)
+#define MAC_RX_PACKET_1519_1522_BYTES_COUNT (4735L)
+#define MAC_RX_PACKET_1523_1548_BYTES (4736L)
+#define MAC_RX_PACKET_1523_1548_BYTES_COUNT (4737L)
+#define MAC_RX_PACKET_1549_2047_BYTES (4738L)
+#define MAC_RX_PACKET_1549_2047_BYTES_COUNT (4739L)
+#define MAC_RX_PACKET_2048_4095_BYTES (4740L)
+#define MAC_RX_PACKET_2048_4095_BYTES_COUNT (4741L)
+#define MAC_RX_PACKET_256_511_BYTES (4742L)
+#define MAC_RX_PACKET_256_511_BYTES_COUNT (4743L)
+#define MAC_RX_PACKET_4096_8191_BYTES (4744L)
+#define MAC_RX_PACKET_4096_8191_BYTES_COUNT (4745L)
+#define MAC_RX_PACKET_512_1023_BYTES (4746L)
+#define MAC_RX_PACKET_512_1023_BYTES_COUNT (4747L)
+#define MAC_RX_PACKET_64_BYTES (4748L)
+#define MAC_RX_PACKET_64_BYTES_COUNT (4749L)
+#define MAC_RX_PACKET_65_127_BYTES (4750L)
+#define MAC_RX_PACKET_65_127_BYTES_COUNT (4751L)
+#define MAC_RX_PACKET_8192_9215_BYTES (4752L)
+#define MAC_RX_PACKET_8192_9215_BYTES_COUNT (4753L)
+#define MAC_RX_PACKET_BAD_FCS (4754L)
+#define MAC_RX_PACKET_BAD_FCS_COUNT (4755L)
+#define MAC_RX_PACKET_LARGE (4756L)
+#define MAC_RX_PACKET_LARGE_COUNT (4757L)
+#define MAC_RX_PACKET_SMALL (4758L)
+#define MAC_RX_PACKET_SMALL_COUNT (4759L)
+#define MAC_RX_STOMPED_FCS (4760L)
+#define MAC_RX_STOMPED_FCS_COUNT (4761L)
+#define MAC_RX_TOOLONG (4762L)
+#define MAC_RX_TOOLONG_COUNT (4763L)
+#define MAC_RX_TOTAL_BYTES (4764L)
+#define MAC_RX_TOTAL_BYTES_COUNT (4765L)
+#define MAC_RX_TOTAL_GOOD_BYTES (4766L)
+#define MAC_RX_TOTAL_GOOD_BYTES_COUNT (4767L)
+#define MAC_RX_TOTAL_GOOD_PACKETS (4768L)
+#define MAC_RX_TOTAL_GOOD_PACKETS_COUNT (4769L)
+#define MAC_RX_TOTAL_PACKETS (4770L)
+#define MAC_RX_TOTAL_PACKETS_COUNT (4771L)
+#define MAC_RX_TRUNCATED (4772L)
+#define MAC_RX_TRUNCATED_COUNT (4773L)
+#define MAC_RX_UNDERSIZE (4774L)
+#define MAC_RX_UNDERSIZE_COUNT (4775L)
+#define MAC_RX_UNICAST (4776L)
+#define MAC_RX_UNICAST_COUNT (4777L)
+#define MAC_RX_VLAN (4778L)
+#define MAC_RX_VLAN_COUNT (4779L)
+/* MAC_TFG */
+#define MAC_TFG_TFG_ADDR (4780L)
+#define MAC_TFG_TFG_ADDR_ADR (4781L)
+#define MAC_TFG_TFG_ADDR_RDENA (4782L)
+#define MAC_TFG_TFG_ADDR_RD_DONE (4783L)
+#define MAC_TFG_TFG_CTRL (4784L)
+#define MAC_TFG_TFG_CTRL_ID_ENA (4785L)
+#define MAC_TFG_TFG_CTRL_ID_POS (4786L)
+#define MAC_TFG_TFG_CTRL_RESTART (4787L)
+#define MAC_TFG_TFG_CTRL_TG_ACT (4788L)
+#define MAC_TFG_TFG_CTRL_TG_ENA (4789L)
+#define MAC_TFG_TFG_CTRL_TIME_MODE (4790L)
+#define MAC_TFG_TFG_CTRL_WRAP (4791L)
+#define MAC_TFG_TFG_DATA (4792L)
+#define MAC_TFG_TFG_DATA_GAP (4793L)
+#define MAC_TFG_TFG_DATA_ID (4794L)
+#define MAC_TFG_TFG_DATA_LENGTH (4795L)
+#define MAC_TFG_TFG_FRAME_HDR (4796L)
+#define MAC_TFG_TFG_FRAME_HDR_HDR (4797L)
+#define MAC_TFG_TFG_REPETITION (4798L)
+#define MAC_TFG_TFG_REPETITION_CNT (4799L)
+/* MAC_TX */
+#define MAC_TX_BAD_FCS (4800L)
+#define MAC_TX_BAD_FCS_COUNT (4801L)
+#define MAC_TX_BROADCAST (4802L)
+#define MAC_TX_BROADCAST_COUNT (4803L)
+#define MAC_TX_FRAME_ERRORS (4804L)
+#define MAC_TX_FRAME_ERRORS_COUNT (4805L)
+#define MAC_TX_MULTICAST (4806L)
+#define MAC_TX_MULTICAST_COUNT (4807L)
+#define MAC_TX_PACKET_1024_1518_BYTES (4808L)
+#define MAC_TX_PACKET_1024_1518_BYTES_COUNT (4809L)
+#define MAC_TX_PACKET_128_255_BYTES (4810L)
+#define MAC_TX_PACKET_128_255_BYTES_COUNT (4811L)
+#define MAC_TX_PACKET_1519_1522_BYTES (4812L)
+#define MAC_TX_PACKET_1519_1522_BYTES_COUNT (4813L)
+#define MAC_TX_PACKET_1523_1548_BYTES (4814L)
+#define MAC_TX_PACKET_1523_1548_BYTES_COUNT (4815L)
+#define MAC_TX_PACKET_1549_2047_BYTES (4816L)
+#define MAC_TX_PACKET_1549_2047_BYTES_COUNT (4817L)
+#define MAC_TX_PACKET_2048_4095_BYTES (4818L)
+#define MAC_TX_PACKET_2048_4095_BYTES_COUNT (4819L)
+#define MAC_TX_PACKET_256_511_BYTES (4820L)
+#define MAC_TX_PACKET_256_511_BYTES_COUNT (4821L)
+#define MAC_TX_PACKET_4096_8191_BYTES (4822L)
+#define MAC_TX_PACKET_4096_8191_BYTES_COUNT (4823L)
+#define MAC_TX_PACKET_512_1023_BYTES (4824L)
+#define MAC_TX_PACKET_512_1023_BYTES_COUNT (4825L)
+#define MAC_TX_PACKET_64_BYTES (4826L)
+#define MAC_TX_PACKET_64_BYTES_COUNT (4827L)
+#define MAC_TX_PACKET_65_127_BYTES (4828L)
+#define MAC_TX_PACKET_65_127_BYTES_COUNT (4829L)
+#define MAC_TX_PACKET_8192_9215_BYTES (4830L)
+#define MAC_TX_PACKET_8192_9215_BYTES_COUNT (4831L)
+#define MAC_TX_PACKET_LARGE (4832L)
+#define MAC_TX_PACKET_LARGE_COUNT (4833L)
+#define MAC_TX_PACKET_SMALL (4834L)
+#define MAC_TX_PACKET_SMALL_COUNT (4835L)
+#define MAC_TX_TOTAL_BYTES (4836L)
+#define MAC_TX_TOTAL_BYTES_COUNT (4837L)
+#define MAC_TX_TOTAL_GOOD_BYTES (4838L)
+#define MAC_TX_TOTAL_GOOD_BYTES_COUNT (4839L)
+#define MAC_TX_TOTAL_GOOD_PACKETS (4840L)
+#define MAC_TX_TOTAL_GOOD_PACKETS_COUNT (4841L)
+#define MAC_TX_TOTAL_PACKETS (4842L)
+#define MAC_TX_TOTAL_PACKETS_COUNT (4843L)
+#define MAC_TX_UNICAST (4844L)
+#define MAC_TX_UNICAST_COUNT (4845L)
+#define MAC_TX_VLAN (4846L)
+#define MAC_TX_VLAN_COUNT (4847L)
+/* MCU */
+#define MCU_CSR (4848L)
+#define MCU_CSR_HALT (4849L)
+#define MCU_CSR_PAUSE (4850L)
+#define MCU_CSR_RESET (4851L)
+#define MCU_CSR_RESET_MCU (4852L)
+#define MCU_DRAM_CTRL (4853L)
+#define MCU_DRAM_CTRL_ADR (4854L)
+#define MCU_DRAM_CTRL_CNT (4855L)
+#define MCU_DRAM_RD_DATA (4856L)
+#define MCU_DRAM_RD_DATA_DATA (4857L)
+#define MCU_DRAM_WR_DATA (4858L)
+#define MCU_DRAM_WR_DATA_DATA (4859L)
+#define MCU_IRAM_CTRL (4860L)
+#define MCU_IRAM_CTRL_ADR (4861L)
+#define MCU_IRAM_CTRL_CNT (4862L)
+#define MCU_IRAM_DATA (4863L)
+#define MCU_IRAM_DATA_DATA (4864L)
+/* MDG */
+#define MDG_BSO_CTRL (4865L)
+#define MDG_BSO_CTRL_ADR (4866L)
+#define MDG_BSO_CTRL_CNT (4867L)
+#define MDG_BSO_DATA (4868L)
+#define MDG_BSO_DATA_OFFSET (4869L)
+#define MDG_CONTROL (4870L)
+#define MDG_CONTROL_AE (4871L)
+#define MDG_CONTROL_AS (4872L)
+#define MDG_CONTROL_CE (4873L)
+#define MDG_CONTROL_EN (4874L)
+#define MDG_DBG_EGS_FC0 (4875L)
+#define MDG_DBG_EGS_FC0_BLOCKED (4876L)
+#define MDG_DBG_EGS_FC1 (4877L)
+#define MDG_DBG_EGS_FC1_BLOCKED (4878L)
+#define MDG_DBG_EGS_FC2 (4879L)
+#define MDG_DBG_EGS_FC2_BLOCKED (4880L)
+#define MDG_DBG_EGS_FC3 (4881L)
+#define MDG_DBG_EGS_FC3_BLOCKED (4882L)
+#define MDG_DBG_HBM (4883L)
+#define MDG_DBG_HBM_ADR (4884L)
+#define MDG_DBG_HBM_MAIN (4885L)
+#define MDG_DBG_HBM_MAP (4886L)
+#define MDG_DBG_HBM_META (4887L)
+#define MDG_DBG_HBM_VALID (4888L)
+#define MDG_DBG_IGS_FC0 (4889L)
+#define MDG_DBG_IGS_FC0_BLOCKED (4890L)
+#define MDG_DBG_IGS_FC1 (4891L)
+#define MDG_DBG_IGS_FC1_BLOCKED (4892L)
+#define MDG_DBG_IGS_FC2 (4893L)
+#define MDG_DBG_IGS_FC2_BLOCKED (4894L)
+#define MDG_DBG_IGS_FC3 (4895L)
+#define MDG_DBG_IGS_FC3_BLOCKED (4896L)
+#define MDG_HBM_CTRL (4897L)
+#define MDG_HBM_CTRL_ADR (4898L)
+#define MDG_HBM_CTRL_CNT (4899L)
+#define MDG_HBM_DATA (4900L)
+#define MDG_HBM_DATA_MAIN (4901L)
+#define MDG_HBM_DATA_MAP (4902L)
+#define MDG_HBM_DATA_META (4903L)
+#define MDG_HBS_CTRL (4904L)
+#define MDG_HBS_CTRL_ADR (4905L)
+#define MDG_HBS_CTRL_CNT (4906L)
+#define MDG_HBS_DATA (4907L)
+#define MDG_HBS_DATA_SIZE (4908L)
+#define MDG_MAX_BYTES (4909L)
+#define MDG_MAX_BYTES_MAX (4910L)
+#define MDG_MAX_PACKETS (4911L)
+#define MDG_MAX_PACKETS_MAX (4912L)
+#define MDG_TIMEOUT (4913L)
+#define MDG_TIMEOUT_T (4914L)
+/* MSK */
+#define MSK_RCP_CTRL (4980L)
+#define MSK_RCP_CTRL_ADR (4981L)
+#define MSK_RCP_CTRL_CNT (4982L)
+#define MSK_RCP_DATA (4983L)
+#define MSK_RCP_DATA_MASK_DYN0 (4984L)
+#define MSK_RCP_DATA_MASK_DYN1 (4985L)
+#define MSK_RCP_DATA_MASK_DYN2 (4986L)
+#define MSK_RCP_DATA_MASK_DYN3 (4987L)
+#define MSK_RCP_DATA_MASK_EN0 (4988L)
+#define MSK_RCP_DATA_MASK_EN1 (4989L)
+#define MSK_RCP_DATA_MASK_EN2 (4990L)
+#define MSK_RCP_DATA_MASK_EN3 (4991L)
+#define MSK_RCP_DATA_MASK_LEN0 (4992L)
+#define MSK_RCP_DATA_MASK_LEN1 (4993L)
+#define MSK_RCP_DATA_MASK_LEN2 (4994L)
+#define MSK_RCP_DATA_MASK_LEN3 (4995L)
+#define MSK_RCP_DATA_MASK_OFS0 (4996L)
+#define MSK_RCP_DATA_MASK_OFS1 (4997L)
+#define MSK_RCP_DATA_MASK_OFS2 (4998L)
+#define MSK_RCP_DATA_MASK_OFS3 (4999L)
+/* NIF */
+#define NIF_CTRL (5000L)
+#define NIF_CTRL_GT_PWDN (5001L)
+#define NIF_CTRL_GT_SEL (5002L)
+#define NIF_CTRL_LOOPBACK (5003L)
+#define NIF_CTRL_PMA_INIT (5004L)
+#define NIF_CTRL_PRBS_ERR (5005L)
+#define NIF_CTRL_PRBS_RST (5006L)
+#define NIF_CTRL_PRBS_SEL (5007L)
+#define NIF_CTRL_QPLL_SEL (5008L)
+#define NIF_CTRL_RST (5009L)
+#define NIF_CTRL_TX_INHIBIT (5010L)
+#define NIF_DRP_IF (5011L)
+#define NIF_DRP_IF_ADR (5012L)
+#define NIF_DRP_IF_DATA (5013L)
+#define NIF_DRP_IF_DBG_BUSY (5014L)
+#define NIF_DRP_IF_DONE (5015L)
+#define NIF_DRP_IF_WREN (5016L)
+#define NIF_ERROR (5017L)
+#define NIF_ERROR_HARD_ERR (5018L)
+#define NIF_ERROR_SOFT_ERR (5019L)
+#define NIF_ERROR_SOFT_ERR_CNT (5020L)
+#define NIF_GTH_TX_TUNING (5021L)
+#define NIF_GTH_TX_TUNING_DIFF_CTRL (5022L)
+#define NIF_GTH_TX_TUNING_POST_CURSOR (5023L)
+#define NIF_GTH_TX_TUNING_PRE_CURSOR (5024L)
+#define NIF_HARD_ERROR_CNT (5025L)
+#define NIF_HARD_ERROR_CNT_UNCORRECTABLE_ERRORS (5026L)
+#define NIF_STATUS (5027L)
+#define NIF_STATUS_CH_UP (5028L)
+#define NIF_STATUS_EP0_0_UP (5029L)
+#define NIF_STATUS_EP0_1_UP (5030L)
+#define NIF_STATUS_EP0_2_UP (5031L)
+#define NIF_STATUS_EP0_3_UP (5032L)
+#define NIF_STATUS_EP1_0_UP (5033L)
+#define NIF_STATUS_EP1_1_UP (5034L)
+#define NIF_STATUS_EP1_2_UP (5035L)
+#define NIF_STATUS_EP1_3_UP (5036L)
+#define NIF_STATUS_EP1_4_UP (5037L)
+#define NIF_STATUS_EP1_5_UP (5038L)
+#define NIF_STATUS_EP3_0_UP (5039L)
+#define NIF_STATUS_EP3_1_UP (5040L)
+#define NIF_STATUS_EP3_2_UP (5041L)
+#define NIF_STATUS_EP3_3_UP (5042L)
+#define NIF_STATUS_MMCM_ULCK (5043L)
+#define NIF_STATUS_PLL_LCK (5044L)
+#define NIF_STATUS_QPLLOUT_LCK (5045L)
+#define NIF_STATUS_QPLLOUT_REF_LOST (5046L)
+#define NIF_STATUS_QPLL_LCK (5047L)
+#define NIF_STATUS_RXRST_DONE (5048L)
+#define NIF_STATUS_TXRST_DONE (5049L)
+#define NIF_STATUS_STICK (5050L)
+#define NIF_STATUS_STICK_CH_DOWN (5051L)
+#define NIF_STATUS_STICK_LN_DOWN (5052L)
+#define NIF_STATUS_STICK_MMCM_ULCK (5053L)
+#define NIF_STATUS_STICK_PLL_ULCK (5054L)
+#define NIF_USER_REG (5055L)
+#define NIF_USER_REG_MASTER (5056L)
+#define NIF_USER_REG_RST (5057L)
+#define NIF_USER_REG_SLAVE (5058L)
+#define NIF_USER_REG_STAT (5059L)
+#define NIF_USER_REG_STAT_LL (5060L)
+/* PCIE3 */
+#define PCIE3_BUILD_SEED (5228L)
+#define PCIE3_BUILD_SEED_BUILD_SEED (5229L)
+#define PCIE3_BUILD_TIME (5230L)
+#define PCIE3_BUILD_TIME_TIME (5231L)
+#define PCIE3_CONFIG (5232L)
+#define PCIE3_CONFIG_EXT_TAG (5233L)
+#define PCIE3_CONFIG_MAX_READ (5234L)
+#define PCIE3_CONFIG_MAX_TLP (5235L)
+#define PCIE3_CONTROL (5236L)
+#define PCIE3_CONTROL_RD_ATTR (5237L)
+#define PCIE3_CONTROL_WRAW (5238L)
+#define PCIE3_CONTROL_WR_ATTR (5239L)
+#define PCIE3_CORESPEED (5240L)
+#define PCIE3_CORESPEED_CORESPEED (5241L)
+#define PCIE3_CORESPEED_DDR3SPEED (5242L)
+#define PCIE3_DRP_COMMON (5243L)
+#define PCIE3_DRP_COMMON_DRP_ADDR (5244L)
+#define PCIE3_DRP_COMMON_DRP_RDY (5245L)
+#define PCIE3_DRP_COMMON_GTH_SEL (5246L)
+#define PCIE3_DRP_COMMON_WR (5247L)
+#define PCIE3_DRP_DATE (5248L)
+#define PCIE3_DRP_DATE_DRP_DATA (5249L)
+#define PCIE3_EP_TO_RP_ERR (5250L)
+#define PCIE3_EP_TO_RP_ERR_ERR_COR (5251L)
+#define PCIE3_EP_TO_RP_ERR_ERR_FATAL (5252L)
+#define PCIE3_EP_TO_RP_ERR_ERR_NONFATAL (5253L)
+#define PCIE3_INT_CLR (5254L)
+#define PCIE3_INT_CLR_AVR (5255L)
+#define PCIE3_INT_CLR_FHM (5256L)
+#define PCIE3_INT_CLR_INT_0 (5257L)
+#define PCIE3_INT_CLR_INT_1 (5258L)
+#define PCIE3_INT_CLR_INT_10 (5259L)
+#define PCIE3_INT_CLR_INT_11 (5260L)
+#define PCIE3_INT_CLR_INT_12 (5261L)
+#define PCIE3_INT_CLR_INT_13 (5262L)
+#define PCIE3_INT_CLR_INT_14 (5263L)
+#define PCIE3_INT_CLR_INT_15 (5264L)
+#define PCIE3_INT_CLR_INT_16 (5265L)
+#define PCIE3_INT_CLR_INT_17 (5266L)
+#define PCIE3_INT_CLR_INT_18 (5267L)
+#define PCIE3_INT_CLR_INT_19 (5268L)
+#define PCIE3_INT_CLR_INT_2 (5269L)
+#define PCIE3_INT_CLR_INT_20 (5270L)
+#define PCIE3_INT_CLR_INT_21 (5271L)
+#define PCIE3_INT_CLR_INT_22 (5272L)
+#define PCIE3_INT_CLR_INT_23 (5273L)
+#define PCIE3_INT_CLR_INT_24 (5274L)
+#define PCIE3_INT_CLR_INT_25 (5275L)
+#define PCIE3_INT_CLR_INT_26 (5276L)
+#define PCIE3_INT_CLR_INT_27 (5277L)
+#define PCIE3_INT_CLR_INT_28 (5278L)
+#define PCIE3_INT_CLR_INT_29 (5279L)
+#define PCIE3_INT_CLR_INT_3 (5280L)
+#define PCIE3_INT_CLR_INT_30 (5281L)
+#define PCIE3_INT_CLR_INT_31 (5282L)
+#define PCIE3_INT_CLR_INT_4 (5283L)
+#define PCIE3_INT_CLR_INT_5 (5284L)
+#define PCIE3_INT_CLR_INT_6 (5285L)
+#define PCIE3_INT_CLR_INT_7 (5286L)
+#define PCIE3_INT_CLR_INT_8 (5287L)
+#define PCIE3_INT_CLR_INT_9 (5288L)
+#define PCIE3_INT_CLR_PORT (5289L)
+#define PCIE3_INT_CLR_PPS (5290L)
+#define PCIE3_INT_CLR_QSPI (5291L)
+#define PCIE3_INT_CLR_SPIM (5292L)
+#define PCIE3_INT_CLR_SPIS (5293L)
+#define PCIE3_INT_CLR_STA (5294L)
+#define PCIE3_INT_CLR_TIMER (5295L)
+#define PCIE3_INT_FORC (5296L)
+#define PCIE3_INT_FORC_AVR (5297L)
+#define PCIE3_INT_FORC_FHM (5298L)
+#define PCIE3_INT_FORC_INT_0 (5299L)
+#define PCIE3_INT_FORC_INT_1 (5300L)
+#define PCIE3_INT_FORC_INT_10 (5301L)
+#define PCIE3_INT_FORC_INT_11 (5302L)
+#define PCIE3_INT_FORC_INT_12 (5303L)
+#define PCIE3_INT_FORC_INT_13 (5304L)
+#define PCIE3_INT_FORC_INT_14 (5305L)
+#define PCIE3_INT_FORC_INT_15 (5306L)
+#define PCIE3_INT_FORC_INT_16 (5307L)
+#define PCIE3_INT_FORC_INT_17 (5308L)
+#define PCIE3_INT_FORC_INT_18 (5309L)
+#define PCIE3_INT_FORC_INT_19 (5310L)
+#define PCIE3_INT_FORC_INT_2 (5311L)
+#define PCIE3_INT_FORC_INT_20 (5312L)
+#define PCIE3_INT_FORC_INT_21 (5313L)
+#define PCIE3_INT_FORC_INT_22 (5314L)
+#define PCIE3_INT_FORC_INT_23 (5315L)
+#define PCIE3_INT_FORC_INT_24 (5316L)
+#define PCIE3_INT_FORC_INT_25 (5317L)
+#define PCIE3_INT_FORC_INT_26 (5318L)
+#define PCIE3_INT_FORC_INT_27 (5319L)
+#define PCIE3_INT_FORC_INT_28 (5320L)
+#define PCIE3_INT_FORC_INT_29 (5321L)
+#define PCIE3_INT_FORC_INT_3 (5322L)
+#define PCIE3_INT_FORC_INT_30 (5323L)
+#define PCIE3_INT_FORC_INT_31 (5324L)
+#define PCIE3_INT_FORC_INT_4 (5325L)
+#define PCIE3_INT_FORC_INT_5 (5326L)
+#define PCIE3_INT_FORC_INT_6 (5327L)
+#define PCIE3_INT_FORC_INT_7 (5328L)
+#define PCIE3_INT_FORC_INT_8 (5329L)
+#define PCIE3_INT_FORC_INT_9 (5330L)
+#define PCIE3_INT_FORC_PORT (5331L)
+#define PCIE3_INT_FORC_PPS (5332L)
+#define PCIE3_INT_FORC_QSPI (5333L)
+#define PCIE3_INT_FORC_SPIM (5334L)
+#define PCIE3_INT_FORC_SPIS (5335L)
+#define PCIE3_INT_FORC_STA (5336L)
+#define PCIE3_INT_FORC_TIMER (5337L)
+#define PCIE3_INT_MASK (5338L)
+#define PCIE3_INT_MASK_AVR (5339L)
+#define PCIE3_INT_MASK_FHM (5340L)
+#define PCIE3_INT_MASK_IIC0 (5341L)
+#define PCIE3_INT_MASK_IIC1 (5342L)
+#define PCIE3_INT_MASK_IIC2 (5343L)
+#define PCIE3_INT_MASK_IIC3 (5344L)
+#define PCIE3_INT_MASK_IIC4 (5345L)
+#define PCIE3_INT_MASK_IIC5 (5346L)
+#define PCIE3_INT_MASK_INT_0 (5347L)
+#define PCIE3_INT_MASK_INT_1 (5348L)
+#define PCIE3_INT_MASK_INT_10 (5349L)
+#define PCIE3_INT_MASK_INT_11 (5350L)
+#define PCIE3_INT_MASK_INT_12 (5351L)
+#define PCIE3_INT_MASK_INT_13 (5352L)
+#define PCIE3_INT_MASK_INT_14 (5353L)
+#define PCIE3_INT_MASK_INT_15 (5354L)
+#define PCIE3_INT_MASK_INT_16 (5355L)
+#define PCIE3_INT_MASK_INT_17 (5356L)
+#define PCIE3_INT_MASK_INT_18 (5357L)
+#define PCIE3_INT_MASK_INT_19 (5358L)
+#define PCIE3_INT_MASK_INT_2 (5359L)
+#define PCIE3_INT_MASK_INT_20 (5360L)
+#define PCIE3_INT_MASK_INT_21 (5361L)
+#define PCIE3_INT_MASK_INT_22 (5362L)
+#define PCIE3_INT_MASK_INT_23 (5363L)
+#define PCIE3_INT_MASK_INT_24 (5364L)
+#define PCIE3_INT_MASK_INT_25 (5365L)
+#define PCIE3_INT_MASK_INT_26 (5366L)
+#define PCIE3_INT_MASK_INT_27 (5367L)
+#define PCIE3_INT_MASK_INT_28 (5368L)
+#define PCIE3_INT_MASK_INT_29 (5369L)
+#define PCIE3_INT_MASK_INT_3 (5370L)
+#define PCIE3_INT_MASK_INT_30 (5371L)
+#define PCIE3_INT_MASK_INT_31 (5372L)
+#define PCIE3_INT_MASK_INT_4 (5373L)
+#define PCIE3_INT_MASK_INT_5 (5374L)
+#define PCIE3_INT_MASK_INT_6 (5375L)
+#define PCIE3_INT_MASK_INT_7 (5376L)
+#define PCIE3_INT_MASK_INT_8 (5377L)
+#define PCIE3_INT_MASK_INT_9 (5378L)
+#define PCIE3_INT_MASK_PORT (5379L)
+#define PCIE3_INT_MASK_PPS (5380L)
+#define PCIE3_INT_MASK_QSPI (5381L)
+#define PCIE3_INT_MASK_SPIM (5382L)
+#define PCIE3_INT_MASK_SPIS (5383L)
+#define PCIE3_INT_MASK_STA (5384L)
+#define PCIE3_INT_MASK_TIMER (5385L)
+#define PCIE3_LAT_CTRL (5386L)
+#define PCIE3_LAT_CTRL_CLEAR_RAM (5387L)
+#define PCIE3_LAT_CTRL_ENABLE (5388L)
+#define PCIE3_LAT_CTRL_PRESCAL (5389L)
+#define PCIE3_LAT_CTRL_RAM_VLD (5390L)
+#define PCIE3_LAT_CTRL_READ_RAM (5391L)
+#define PCIE3_LAT_CTRL_STATUS (5392L)
+#define PCIE3_LAT_MAX (5393L)
+#define PCIE3_LAT_MAX_MAX (5394L)
+#define PCIE3_LAT_RAMADR (5395L)
+#define PCIE3_LAT_RAMADR_ADR (5396L)
+#define PCIE3_LAT_RAMDATA (5397L)
+#define PCIE3_LAT_RAMDATA_DATA (5398L)
+#define PCIE3_LINK_STATUS (5399L)
+#define PCIE3_LINK_STATUS_CLEAR (5400L)
+#define PCIE3_LINK_STATUS_RETRAIN_CNT (5401L)
+#define PCIE3_MARKADR_LSB (5402L)
+#define PCIE3_MARKADR_LSB_ADR (5403L)
+#define PCIE3_MARKADR_MSB (5404L)
+#define PCIE3_MARKADR_MSB_ADR (5405L)
+#define PCIE3_PB_INTERVAL (5406L)
+#define PCIE3_PB_INTERVAL_INTERVAL (5407L)
+#define PCIE3_PB_MAX_RD (5408L)
+#define PCIE3_PB_MAX_RD_PB (5409L)
+#define PCIE3_PB_MAX_WR (5410L)
+#define PCIE3_PB_MAX_WR_PB (5411L)
+#define PCIE3_PCIE_CTRL (5412L)
+#define PCIE3_PCIE_CTRL_EXT_TAG_ENA (5413L)
+#define PCIE3_PCI_ENDPOINT (5414L)
+#define PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK (5415L)
+#define PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK (5416L)
+#define PCIE3_PCI_ENDPOINT_GET_MSG (5417L)
+#define PCIE3_PCI_ENDPOINT_IF_ID (5418L)
+#define PCIE3_PCI_ENDPOINT_SEND_MSG (5419L)
+#define PCIE3_PCI_TEST0 (5420L)
+#define PCIE3_PCI_TEST0_DATA (5421L)
+#define PCIE3_PCI_TEST1 (5422L)
+#define PCIE3_PCI_TEST1_DATA (5423L)
+#define PCIE3_PCI_TEST2 (5424L)
+#define PCIE3_PCI_TEST2_DATA (5425L)
+#define PCIE3_PCI_TEST3 (5426L)
+#define PCIE3_PCI_TEST3_DATA (5427L)
+#define PCIE3_PROD_ID_EX (5428L)
+#define PCIE3_PROD_ID_EX_LAYOUT (5429L)
+#define PCIE3_PROD_ID_EX_LAYOUT_VERSION (5430L)
+#define PCIE3_PROD_ID_EX_RESERVED (5431L)
+#define PCIE3_PROD_ID_LSB (5432L)
+#define PCIE3_PROD_ID_LSB_GROUP_ID (5433L)
+#define PCIE3_PROD_ID_LSB_REV_ID (5434L)
+#define PCIE3_PROD_ID_LSB_VER_ID (5435L)
+#define PCIE3_PROD_ID_MSB (5436L)
+#define PCIE3_PROD_ID_MSB_BUILD_NO (5437L)
+#define PCIE3_PROD_ID_MSB_PATCH_NO (5438L)
+#define PCIE3_PROD_ID_MSB_TYPE_ID (5439L)
+#define PCIE3_RESET_CTRL (5440L)
+#define PCIE3_RESET_CTRL_MASK (5441L)
+#define PCIE3_RP_TO_EP_ERR (5442L)
+#define PCIE3_RP_TO_EP_ERR_ERR_COR (5443L)
+#define PCIE3_RP_TO_EP_ERR_ERR_FATAL (5444L)
+#define PCIE3_RP_TO_EP_ERR_ERR_NONFATAL (5445L)
+#define PCIE3_SAMPLE_TIME (5446L)
+#define PCIE3_SAMPLE_TIME_SAMPLE_TIME (5447L)
+#define PCIE3_STATUS (5448L)
+#define PCIE3_STATUS_RD_ERR (5449L)
+#define PCIE3_STATUS_TAGS_IN_USE (5450L)
+#define PCIE3_STATUS_WR_ERR (5451L)
+#define PCIE3_STATUS0 (5452L)
+#define PCIE3_STATUS0_TAGS_IN_USE (5453L)
+#define PCIE3_STATUS0_UR_ADDR (5454L)
+#define PCIE3_STATUS0_UR_DWORD (5455L)
+#define PCIE3_STATUS0_UR_FBE (5456L)
+#define PCIE3_STATUS0_UR_FMT (5457L)
+#define PCIE3_STATUS0_UR_LBE (5458L)
+#define PCIE3_STATUS0_UR_REG (5459L)
+#define PCIE3_STAT_CTRL (5460L)
+#define PCIE3_STAT_CTRL_STAT_ENA (5461L)
+#define PCIE3_STAT_CTRL_STAT_REQ (5462L)
+#define PCIE3_STAT_REFCLK (5463L)
+#define PCIE3_STAT_REFCLK_REFCLK250 (5464L)
+#define PCIE3_STAT_RQ_RDY (5465L)
+#define PCIE3_STAT_RQ_RDY_COUNTER (5466L)
+#define PCIE3_STAT_RQ_VLD (5467L)
+#define PCIE3_STAT_RQ_VLD_COUNTER (5468L)
+#define PCIE3_STAT_RX (5469L)
+#define PCIE3_STAT_RX_COUNTER (5470L)
+#define PCIE3_STAT_TX (5471L)
+#define PCIE3_STAT_TX_COUNTER (5472L)
+#define PCIE3_TEST0 (5473L)
+#define PCIE3_TEST0_DATA (5474L)
+#define PCIE3_TEST1 (5475L)
+#define PCIE3_TEST1_DATA (5476L)
+#define PCIE3_TEST2_DATA (5477L)
+#define PCIE3_TEST3_DATA (5478L)
+#define PCIE3_UUID0 (5479L)
+#define PCIE3_UUID0_UUID0 (5480L)
+#define PCIE3_UUID1 (5481L)
+#define PCIE3_UUID1_UUID1 (5482L)
+#define PCIE3_UUID2 (5483L)
+#define PCIE3_UUID2_UUID2 (5484L)
+#define PCIE3_UUID3 (5485L)
+#define PCIE3_UUID3_UUID3 (5486L)
+/* PCI_RD_TG */
+#define PCI_RD_TG_TG_CTRL (5487L)
+#define PCI_RD_TG_TG_CTRL_TG_RD_RDY (5488L)
+#define PCI_RD_TG_TG_RDADDR (5489L)
+#define PCI_RD_TG_TG_RDADDR_RAM_ADDR (5490L)
+#define PCI_RD_TG_TG_RDDATA0 (5491L)
+#define PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW (5492L)
+#define PCI_RD_TG_TG_RDDATA1 (5493L)
+#define PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH (5494L)
+#define PCI_RD_TG_TG_RDDATA2 (5495L)
+#define PCI_RD_TG_TG_RDDATA2_REQ_HID (5496L)
+#define PCI_RD_TG_TG_RDDATA2_REQ_SIZE (5497L)
+#define PCI_RD_TG_TG_RDDATA2_WAIT (5498L)
+#define PCI_RD_TG_TG_RDDATA2_WRAP (5499L)
+#define PCI_RD_TG_TG_RD_RUN (5500L)
+#define PCI_RD_TG_TG_RD_RUN_RD_ITERATION (5501L)
+/* PCI_TA */
+#define PCI_TA_CONTROL (5502L)
+#define PCI_TA_CONTROL_ENABLE (5503L)
+#define PCI_TA_LENGTH_ERROR (5504L)
+#define PCI_TA_LENGTH_ERROR_AMOUNT (5505L)
+#define PCI_TA_PACKET_BAD (5506L)
+#define PCI_TA_PACKET_BAD_AMOUNT (5507L)
+#define PCI_TA_PACKET_GOOD (5508L)
+#define PCI_TA_PACKET_GOOD_AMOUNT (5509L)
+#define PCI_TA_PAYLOAD_ERROR (5510L)
+#define PCI_TA_PAYLOAD_ERROR_AMOUNT (5511L)
+/* PCI_WR_TG */
+#define PCI_WR_TG_TG_CTRL (5512L)
+#define PCI_WR_TG_TG_CTRL_TG_WR_RDY (5513L)
+#define PCI_WR_TG_TG_SEQ (5514L)
+#define PCI_WR_TG_TG_SEQ_SEQUENCE (5515L)
+#define PCI_WR_TG_TG_WRADDR (5516L)
+#define PCI_WR_TG_TG_WRADDR_RAM_ADDR (5517L)
+#define PCI_WR_TG_TG_WRDATA0 (5518L)
+#define PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW (5519L)
+#define PCI_WR_TG_TG_WRDATA1 (5520L)
+#define PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH (5521L)
+#define PCI_WR_TG_TG_WRDATA2 (5522L)
+#define PCI_WR_TG_TG_WRDATA2_INC_MODE (5523L)
+#define PCI_WR_TG_TG_WRDATA2_REQ_HID (5524L)
+#define PCI_WR_TG_TG_WRDATA2_REQ_SIZE (5525L)
+#define PCI_WR_TG_TG_WRDATA2_WAIT (5526L)
+#define PCI_WR_TG_TG_WRDATA2_WRAP (5527L)
+#define PCI_WR_TG_TG_WR_RUN (5528L)
+#define PCI_WR_TG_TG_WR_RUN_WR_ITERATION (5529L)
+/* PCM_NT100A01_01 */
+#define PCM_NT100A01_01_CTRL (5530L)
+#define PCM_NT100A01_01_CTRL_PTP_CLKSEL (5531L)
+#define PCM_NT100A01_01_CTRL_REC_MMCM_RST (5532L)
+#define PCM_NT100A01_01_CTRL_TS_CLKSEL (5533L)
+#define PCM_NT100A01_01_CTRL_TS_MMCM_RST (5534L)
+#define PCM_NT100A01_01_GPIO_I (5535L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_C2B (5536L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_CS_CA (5537L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_INT_C1B (5538L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_LOL (5539L)
+#define PCM_NT100A01_01_GPIO_O (5540L)
+#define PCM_NT100A01_01_GPIO_O_SI5328_CS_CA (5541L)
+#define PCM_NT100A01_01_GPIO_O_SI5328_RST_B (5542L)
+#define PCM_NT100A01_01_GPIO_T (5543L)
+#define PCM_NT100A01_01_GPIO_T_SI5328_CS_CA (5544L)
+#define PCM_NT100A01_01_LATCH (5545L)
+#define PCM_NT100A01_01_LATCH_REC_MMCM_LOCKED (5546L)
+#define PCM_NT100A01_01_LATCH_TCXO_MMCM_LOCKED (5547L)
+#define PCM_NT100A01_01_LATCH_TS_MMCM_LOCKED (5548L)
+#define PCM_NT100A01_01_STAT (5549L)
+#define PCM_NT100A01_01_STAT_REC_MMCM_LOCKED (5550L)
+#define PCM_NT100A01_01_STAT_TCXO_MMCM_LOCKED (5551L)
+#define PCM_NT100A01_01_STAT_TS_MMCM_LOCKED (5552L)
+/* PCM_NT50B01_01 */
+#define PCM_NT50B01_01_CTRL (5553L)
+#define PCM_NT50B01_01_CTRL_TS_CLKSEL (5554L)
+#define PCM_NT50B01_01_CTRL_TS_MMCM_RST (5555L)
+#define PCM_NT50B01_01_LATCH (5556L)
+#define PCM_NT50B01_01_LATCH_TS_MMCM_LOCKED (5557L)
+#define PCM_NT50B01_01_STAT (5558L)
+#define PCM_NT50B01_01_STAT_TS_MMCM_LOCKED (5559L)
+/* PCS */
+#define PCS_BER_COUNT (5560L)
+#define PCS_BER_COUNT_CNT (5561L)
+#define PCS_BIP_COUNT (5562L)
+#define PCS_BIP_COUNT_CNT (5563L)
+#define PCS_BLOCK_LOCK (5564L)
+#define PCS_BLOCK_LOCK_LOCK (5565L)
+#define PCS_BLOCK_LOCK_LATCH (5566L)
+#define PCS_BLOCK_LOCK_LATCH_LATCH_LOCK (5567L)
+#define PCS_BLOCK_LOCK_ST (5568L)
+#define PCS_BLOCK_LOCK_ST_LATCH_STATE (5569L)
+#define PCS_DDR3_STATUS (5570L)
+#define PCS_DDR3_STATUS_CALIB_DONE (5571L)
+#define PCS_DRP_CONFIG (5572L)
+#define PCS_DRP_CONFIG_DRP_ADR (5573L)
+#define PCS_DRP_CONFIG_DRP_DI (5574L)
+#define PCS_DRP_CONFIG_DRP_EN (5575L)
+#define PCS_DRP_CONFIG_DRP_WREN (5576L)
+#define PCS_DRP_DATA (5577L)
+#define PCS_DRP_DATA_DRP_DO (5578L)
+#define PCS_DRP_DATA_DRP_RDY (5579L)
+#define PCS_FSM_DONE (5580L)
+#define PCS_FSM_DONE_RX_RST_DONE (5581L)
+#define PCS_FSM_DONE_TX_RST_DONE (5582L)
+#define PCS_GTH_CONFIG (5583L)
+#define PCS_GTH_CONFIG_EYE_SCAN_RST (5584L)
+#define PCS_GTH_CONFIG_EYE_SCAN_TRIG (5585L)
+#define PCS_GTH_CONFIG_GT_LOOP (5586L)
+#define PCS_GTH_CONFIG_GT_LPM_EN (5587L)
+#define PCS_GTH_CONFIG_GT_MRST (5588L)
+#define PCS_GTH_CONFIG_GT_RX_RST (5589L)
+#define PCS_GTH_CONFIG_GT_SOFT_RST (5590L)
+#define PCS_GTH_CONFIG_GT_TX_RST (5591L)
+#define PCS_GTH_CONFIG_RX_MONITOR_SEL (5592L)
+#define PCS_GTH_CONFIG_RX_PCS_RST (5593L)
+#define PCS_GTH_CONFIG_RX_USER_RDY (5594L)
+#define PCS_GTH_CONFIG_TX_PCS_RST (5595L)
+#define PCS_GTH_CONFIG_TX_USER_RDYU (5596L)
+#define PCS_GTH_CONTROL (5597L)
+#define PCS_GTH_CONTROL_CPLL_LOCK (5598L)
+#define PCS_GTH_CONTROL_CPLL_REFCLK_LOST (5599L)
+#define PCS_GTH_CONTROL_RX_BUF_RST (5600L)
+#define PCS_GTH_TX_TUNING (5601L)
+#define PCS_GTH_TX_TUNING_DIFF_CTRL (5602L)
+#define PCS_GTH_TX_TUNING_POST_CURSOR (5603L)
+#define PCS_GTH_TX_TUNING_PRE_CURSOR (5604L)
+#define PCS_LANE_LOCK (5605L)
+#define PCS_LANE_LOCK_LOCK (5606L)
+#define PCS_LANE_LOCK_LATCH (5607L)
+#define PCS_LANE_LOCK_LATCH_LATCH_LOCK (5608L)
+#define PCS_LANE_LOCK_ST (5609L)
+#define PCS_LANE_LOCK_ST_LATCH_STATE (5610L)
+#define PCS_LANE_MAPPING (5611L)
+#define PCS_LANE_MAPPING_LANE (5612L)
+#define PCS_LANE_OFFSET (5613L)
+#define PCS_LANE_OFFSET_DIFF (5614L)
+#define PCS_PCS_CONFIG (5615L)
+#define PCS_PCS_CONFIG_BER_RST (5616L)
+#define PCS_PCS_CONFIG_BIP_RST (5617L)
+#define PCS_PCS_CONFIG_LANE_ADDR (5618L)
+#define PCS_PCS_CONFIG_LANE_BLOCK_CLR (5619L)
+#define PCS_PCS_CONFIG_TIME_OFFSET_RX (5620L)
+#define PCS_PCS_CONFIG_TXRX_LOOP (5621L)
+#define PCS_PCS_STATUS (5622L)
+#define PCS_PCS_STATUS_ALIGN (5623L)
+#define PCS_PCS_STATUS_DELAY_ERR (5624L)
+#define PCS_PCS_STATUS_FIFO_DELAY (5625L)
+#define PCS_PCS_STATUS_HI_BER (5626L)
+#define PCS_POLARITY (5627L)
+#define PCS_POLARITY_RX_POL (5628L)
+#define PCS_POLARITY_TX_POL (5629L)
+/* PCS100 */
+#define PCS100_BER_COUNT (5630L)
+#define PCS100_BER_COUNT_CNT (5631L)
+#define PCS100_BIP_COUNT (5632L)
+#define PCS100_BIP_COUNT_CNT (5633L)
+#define PCS100_BLOCK_LOCK (5634L)
+#define PCS100_BLOCK_LOCK_LOCK (5635L)
+#define PCS100_BLOCK_LOCK_LATCH (5636L)
+#define PCS100_BLOCK_LOCK_LATCH_LATCH_LOCK (5637L)
+#define PCS100_BLOCK_LOCK_ST (5638L)
+#define PCS100_BLOCK_LOCK_ST_LATCH_STATE (5639L)
+#define PCS100_DDR3_STATUS (5640L)
+#define PCS100_DDR3_STATUS_CALIB_DONE (5641L)
+#define PCS100_DRP_CONFIG (5642L)
+#define PCS100_DRP_CONFIG_DRP_ADR (5643L)
+#define PCS100_DRP_CONFIG_DRP_DI (5644L)
+#define PCS100_DRP_CONFIG_DRP_EN (5645L)
+#define PCS100_DRP_CONFIG_DRP_WREN (5646L)
+#define PCS100_DRP_DATA (5647L)
+#define PCS100_DRP_DATA_DRP_DO (5648L)
+#define PCS100_DRP_DATA_DRP_RDY (5649L)
+#define PCS100_FSM_DONE (5650L)
+#define PCS100_FSM_DONE_RX_RST_DONE (5651L)
+#define PCS100_FSM_DONE_TX_RST_DONE (5652L)
+#define PCS100_GTH_CONFIG (5653L)
+#define PCS100_GTH_CONFIG_EYE_SCAN_RST (5654L)
+#define PCS100_GTH_CONFIG_EYE_SCAN_TRIG (5655L)
+#define PCS100_GTH_CONFIG_GT_LOOP (5656L)
+#define PCS100_GTH_CONFIG_GT_MRST (5657L)
+#define PCS100_GTH_CONFIG_GT_RX_RST (5658L)
+#define PCS100_GTH_CONFIG_GT_SOFT_RST (5659L)
+#define PCS100_GTH_CONFIG_GT_TX_RST (5660L)
+#define PCS100_GTH_CONFIG_RX_MONITOR_SEL (5661L)
+#define PCS100_GTH_CONFIG_RX_PCS_RST (5662L)
+#define PCS100_GTH_CONFIG_RX_USER_RDY (5663L)
+#define PCS100_GTH_CONFIG_TX_PCS_RST (5664L)
+#define PCS100_GTH_CONFIG_TX_USER_RDYU (5665L)
+#define PCS100_GTH_CONTROL (5666L)
+#define PCS100_GTH_CONTROL_CPLL_LOCK (5667L)
+#define PCS100_GTH_CONTROL_CPLL_REFCLK_LOST (5668L)
+#define PCS100_GTH_CONTROL_QPLL_LOCK (5669L)
+#define PCS100_GTH_CONTROL_QPLL_REFCLK_LOST (5670L)
+#define PCS100_GTH_CONTROL_RX_BUF_RST (5671L)
+#define PCS100_GTH_TX_TUNING (5672L)
+#define PCS100_GTH_TX_TUNING_DIFF_CTRL (5673L)
+#define PCS100_GTH_TX_TUNING_POST_CURSOR (5674L)
+#define PCS100_GTH_TX_TUNING_PRE_CURSOR (5675L)
+#define PCS100_LANE_LOCK (5676L)
+#define PCS100_LANE_LOCK_LOCK (5677L)
+#define PCS100_LANE_LOCK_LATCH (5678L)
+#define PCS100_LANE_LOCK_LATCH_LATCH_LOCK (5679L)
+#define PCS100_LANE_LOCK_ST (5680L)
+#define PCS100_LANE_LOCK_ST_LATCH_STATE (5681L)
+#define PCS100_LANE_MAPPING (5682L)
+#define PCS100_LANE_MAPPING_LANE (5683L)
+#define PCS100_LANE_OFFSET (5684L)
+#define PCS100_LANE_OFFSET_DIFF (5685L)
+#define PCS100_PCS_CONFIG (5686L)
+#define PCS100_PCS_CONFIG_BER_RST (5687L)
+#define PCS100_PCS_CONFIG_BIP_RST (5688L)
+#define PCS100_PCS_CONFIG_LANE_ADDR (5689L)
+#define PCS100_PCS_CONFIG_LANE_BLOCK_CLR (5690L)
+#define PCS100_PCS_CONFIG_TIME_OFFSET_RX (5691L)
+#define PCS100_PCS_CONFIG_TXRX_LOOP (5692L)
+#define PCS100_PCS_STATUS (5693L)
+#define PCS100_PCS_STATUS_ALIGN (5694L)
+#define PCS100_PCS_STATUS_DELAY_ERR (5695L)
+#define PCS100_PCS_STATUS_FIFO_DELAY (5696L)
+#define PCS100_PCS_STATUS_HI_BER (5697L)
+/* PDB */
+#define PDB_CONFIG (5698L)
+#define PDB_CONFIG_PORT_OFS (5699L)
+#define PDB_CONFIG_TS_FORMAT (5700L)
+#define PDB_RCP_CTRL (5701L)
+#define PDB_RCP_CTRL_ADR (5702L)
+#define PDB_RCP_CTRL_CNT (5703L)
+#define PDB_RCP_DATA (5704L)
+#define PDB_RCP_DATA_ALIGN (5705L)
+#define PDB_RCP_DATA_CRC_OVERWRITE (5706L)
+#define PDB_RCP_DATA_DESCRIPTOR (5707L)
+#define PDB_RCP_DATA_DESC_LEN (5708L)
+#define PDB_RCP_DATA_DUPLICATE_BIT (5709L)
+#define PDB_RCP_DATA_DUPLICATE_EN (5710L)
+#define PDB_RCP_DATA_IP_PROT_TNL (5711L)
+#define PDB_RCP_DATA_OFS0_DYN (5712L)
+#define PDB_RCP_DATA_OFS0_REL (5713L)
+#define PDB_RCP_DATA_OFS1_DYN (5714L)
+#define PDB_RCP_DATA_OFS1_REL (5715L)
+#define PDB_RCP_DATA_OFS2_DYN (5716L)
+#define PDB_RCP_DATA_OFS2_REL (5717L)
+#define PDB_RCP_DATA_PCAP_KEEP_FCS (5718L)
+#define PDB_RCP_DATA_PPC_HSH (5719L)
+#define PDB_RCP_DATA_TX_IGNORE (5720L)
+#define PDB_RCP_DATA_TX_NOW (5721L)
+#define PDB_RCP_DATA_TX_PORT (5722L)
+/* PDI */
+#define PDI_CR (5723L)
+#define PDI_CR_EN (5724L)
+#define PDI_CR_PARITY (5725L)
+#define PDI_CR_RST (5726L)
+#define PDI_CR_RXRST (5727L)
+#define PDI_CR_STOP (5728L)
+#define PDI_CR_TXRST (5729L)
+#define PDI_DRR (5730L)
+#define PDI_DRR_DRR (5731L)
+#define PDI_DTR (5732L)
+#define PDI_DTR_DTR (5733L)
+#define PDI_PRE (5734L)
+#define PDI_PRE_PRE (5735L)
+#define PDI_SR (5736L)
+#define PDI_SR_DISABLE_BUSY (5737L)
+#define PDI_SR_DONE (5738L)
+#define PDI_SR_ENABLE_BUSY (5739L)
+#define PDI_SR_FRAME_ERR (5740L)
+#define PDI_SR_OVERRUN_ERR (5741L)
+#define PDI_SR_PARITY_ERR (5742L)
+#define PDI_SR_RXLVL (5743L)
+#define PDI_SR_RX_BUSY (5744L)
+#define PDI_SR_TXLVL (5745L)
+#define PDI_SR_TX_BUSY (5746L)
+#define PDI_SRR (5747L)
+#define PDI_SRR_RST (5748L)
+/* PHY10G */
+#define PHY10G_CORE_CONF (5749L)
+#define PHY10G_CORE_CONF_CLEAR_PCS_LINK_FAULTS (5750L)
+#define PHY10G_CORE_CONF_CLEAR_PCS_STATUS2 (5751L)
+#define PHY10G_CORE_CONF_CLEAR_PMA_PMD_LINK_FAULTS (5752L)
+#define PHY10G_CORE_CONF_CLEAR_TEST_PATT_ERR_COUNT (5753L)
+#define PHY10G_CORE_CONF_DATA_PATT_SEL (5754L)
+#define PHY10G_CORE_CONF_GLOBAL_TX_DISABLE (5755L)
+#define PHY10G_CORE_CONF_NT_FORCE_LINK_DOWN (5756L)
+#define PHY10G_CORE_CONF_NT_LINKUP_LATENCY (5757L)
+#define PHY10G_CORE_CONF_PCS_LOOPBACK (5758L)
+#define PHY10G_CORE_CONF_PCS_RESET (5759L)
+#define PHY10G_CORE_CONF_PMA_LOOPBACK (5760L)
+#define PHY10G_CORE_CONF_PMA_RESET (5761L)
+#define PHY10G_CORE_CONF_PMD_TX_DISABLE (5762L)
+#define PHY10G_CORE_CONF_PRBS31_RX_EN (5763L)
+#define PHY10G_CORE_CONF_PRBS31_TX_EN (5764L)
+#define PHY10G_CORE_CONF_RX_TEST_PATT_EN (5765L)
+#define PHY10G_CORE_CONF_SET_PCS_LINK_STATUS (5766L)
+#define PHY10G_CORE_CONF_SET_PMA_LINK_STATUS (5767L)
+#define PHY10G_CORE_CONF_TEST_PATT_SEL (5768L)
+#define PHY10G_CORE_CONF_TX_TEST_PATT_EN (5769L)
+#define PHY10G_CORE_STAT (5770L)
+#define PHY10G_CORE_STAT_NT_LINK_STATE (5771L)
+#define PHY10G_CORE_STAT_PCS_BER_COUNT (5772L)
+#define PHY10G_CORE_STAT_PCS_BLOCK_LOCK (5773L)
+#define PHY10G_CORE_STAT_PCS_ERR_BLOCK_COUNT (5774L)
+#define PHY10G_CORE_STAT_PCS_HIBER (5775L)
+#define PHY10G_CORE_STAT_PCS_RESET (5776L)
+#define PHY10G_CORE_STAT_PCS_RX_FAULT (5777L)
+#define PHY10G_CORE_STAT_PCS_RX_HIBER_LH (5778L)
+#define PHY10G_CORE_STAT_PCS_RX_LINK_STATUS (5779L)
+#define PHY10G_CORE_STAT_PCS_RX_LOCKED (5780L)
+#define PHY10G_CORE_STAT_PCS_RX_LOCKED_LL (5781L)
+#define PHY10G_CORE_STAT_PCS_TEST_PATT_ERR_COUNT (5782L)
+#define PHY10G_CORE_STAT_PCS_TX_FAULT (5783L)
+#define PHY10G_CORE_STAT_PMA_PMD_LINK_STAT (5784L)
+#define PHY10G_CORE_STAT_PMA_PMD_RX_FAULT (5785L)
+#define PHY10G_CORE_STAT_PMA_PMD_TX_FAULT (5786L)
+#define PHY10G_CORE_STAT_PMA_RESET (5787L)
+#define PHY10G_CORE_STAT_RX_SIG_DET (5788L)
+#define PHY10G_CORE_STAT_TENG_PCS_RX_LINK_STATUS (5789L)
+#define PHY10G_CTRL (5790L)
+#define PHY10G_CTRL_FORCE_LINK_DOWN (5791L)
+#define PHY10G_CTRL_HOST_LOOPBACK (5792L)
+#define PHY10G_CTRL_LINE_LOOPBACK (5793L)
+#define PHY10G_CTRL_LINKUP_LATENCY (5794L)
+#define PHY10G_CTRL_SOFT_RESET (5795L)
+#define PHY10G_GPIO (5796L)
+#define PHY10G_GPIO_ABS (5797L)
+#define PHY10G_GPIO_LED_MODE (5798L)
+#define PHY10G_GPIO_LED_MODE_NIM (5799L)
+#define PHY10G_GPIO_LED_MODE_PHY (5800L)
+#define PHY10G_GPIO_PWR_EN (5801L)
+#define PHY10G_GPIO_RX_LOS (5802L)
+#define PHY10G_GPIO_TX_FAULT (5803L)
+#define PHY10G_GT_CTRL (5804L)
+#define PHY10G_GT_CTRL_EYESCANRESET (5805L)
+#define PHY10G_GT_CTRL_EYESCANTRIGGER (5806L)
+#define PHY10G_GT_CTRL_RXCDRHOLD (5807L)
+#define PHY10G_GT_CTRL_RXDFELPMRESET (5808L)
+#define PHY10G_GT_CTRL_RXLPMEN (5809L)
+#define PHY10G_GT_CTRL_RXPMARESET (5810L)
+#define PHY10G_GT_CTRL_RXPRBSENABLE (5811L)
+#define PHY10G_GT_CTRL_RXRATE (5812L)
+#define PHY10G_GT_CTRL_TXDIFFCTRL (5813L)
+#define PHY10G_GT_CTRL_TXPCSRESET (5814L)
+#define PHY10G_GT_CTRL_TXPMARESET (5815L)
+#define PHY10G_GT_CTRL_TXPOSTCURSOR (5816L)
+#define PHY10G_GT_CTRL_TXPRBSENABLE (5817L)
+#define PHY10G_GT_CTRL_TXPRBSFORCEERR (5818L)
+#define PHY10G_GT_CTRL_TXPRECURSOR (5819L)
+#define PHY10G_GT_STAT (5820L)
+#define PHY10G_GT_STAT_DMONITOROUT (5821L)
+#define PHY10G_GT_STAT_EYESCANDATAERROR (5822L)
+#define PHY10G_GT_STAT_RXBUFSTATUS (5823L)
+#define PHY10G_GT_STAT_RXPMARESETDONE (5824L)
+#define PHY10G_GT_STAT_RXPRBSERR (5825L)
+#define PHY10G_GT_STAT_RXPRBSLOCKED (5826L)
+#define PHY10G_GT_STAT_RXRESETDONE (5827L)
+#define PHY10G_GT_STAT_TXBUFSTATUS (5828L)
+#define PHY10G_GT_STAT_TXRESETDONE (5829L)
+#define PHY10G_GT_STAT2 (5830L)
+#define PHY10G_GT_STAT2_DMONITOR (5831L)
+#define PHY10G_GT_STAT2_RXPRBSCNT (5832L)
+#define PHY10G_INT (5833L)
+#define PHY10G_INT_EN (5834L)
+#define PHY10G_INT_MAX_PACE (5835L)
+#define PHY10G_LINK_SUMMARY (5836L)
+#define PHY10G_LINK_SUMMARY_ABS (5837L)
+#define PHY10G_LINK_SUMMARY_CORE_STATUS (5838L)
+#define PHY10G_LINK_SUMMARY_LINK_DOWN_CNT (5839L)
+#define PHY10G_LINK_SUMMARY_NT_LINK_STATE (5840L)
+#define PHY10G_LINK_SUMMARY_RES (5841L)
+#define PHY10G_TS_COMP (5842L)
+#define PHY10G_TS_COMP_RX (5843L)
+/* PHY3S10G */
+#define PHY3S10G_ANEG_ADV_3S (5844L)
+#define PHY3S10G_ANEG_ADV_3S_DUPLEX (5845L)
+#define PHY3S10G_ANEG_ADV_3S_PAUSE (5846L)
+#define PHY3S10G_ANEG_ADV_3S_REMOTE_FAULT (5847L)
+#define PHY3S10G_CORE_CONF_10G (5848L)
+#define PHY3S10G_CORE_CONF_10G_CLEAR_PCS_LINK_FAULTS (5849L)
+#define PHY3S10G_CORE_CONF_10G_CLEAR_PCS_STATUS2 (5850L)
+#define PHY3S10G_CORE_CONF_10G_CLEAR_PMA_PMD_LINK_FAULTS (5851L)
+#define PHY3S10G_CORE_CONF_10G_PCS_LOOPBACK (5852L)
+#define PHY3S10G_CORE_CONF_10G_PCS_RESET (5853L)
+#define PHY3S10G_CORE_CONF_10G_PMA_LOOPBACK (5854L)
+#define PHY3S10G_CORE_CONF_10G_PMA_RESET (5855L)
+#define PHY3S10G_CORE_CONF_10G_SET_PCS_LINK_STATUS (5856L)
+#define PHY3S10G_CORE_CONF_10G_SET_PMA_LINK_STATUS (5857L)
+#define PHY3S10G_CORE_CONF_3S (5858L)
+#define PHY3S10G_CORE_CONF_3S_ANEG_BYPASS_EN (5859L)
+#define PHY3S10G_CORE_CONF_3S_ANEG_EN (5860L)
+#define PHY3S10G_CORE_CONF_3S_ANEG_RESTART (5861L)
+#define PHY3S10G_CORE_CONF_3S_BASEX_OR_SGMII (5862L)
+#define PHY3S10G_CORE_CONF_3S_LINK_TIMER_BASEX (5863L)
+#define PHY3S10G_CORE_CONF_3S_LOOPBACK_CTRL (5864L)
+#define PHY3S10G_CORE_CONF_3S_POWER_DOWN (5865L)
+#define PHY3S10G_CORE_CONF_3S_SPEED (5866L)
+#define PHY3S10G_CORE_CONF_3S_UNIDIRECT_EN (5867L)
+#define PHY3S10G_CORE_STAT_10G (5868L)
+#define PHY3S10G_CORE_STAT_10G_NT_LINK_STATE (5869L)
+#define PHY3S10G_CORE_STAT_10G_PCS_BER_COUNT (5870L)
+#define PHY3S10G_CORE_STAT_10G_PCS_BLOCK_LOCK (5871L)
+#define PHY3S10G_CORE_STAT_10G_PCS_ERR_BLOCK_COUNT (5872L)
+#define PHY3S10G_CORE_STAT_10G_PCS_HIBER (5873L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_HIBER_LH (5874L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_LINK_STATUS (5875L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_LOCKED (5876L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_LOCKED_LL (5877L)
+#define PHY3S10G_CORE_STAT_10G_PMA_PMD_LINK_STAT (5878L)
+#define PHY3S10G_CORE_STAT_10G_RX_SIG_DET (5879L)
+#define PHY3S10G_CORE_STAT_10G_TENG_PCS_RX_LINK_STATUS (5880L)
+#define PHY3S10G_CORE_STAT_3S (5881L)
+#define PHY3S10G_CORE_STAT_3S_ANEG_COMPLETE (5882L)
+#define PHY3S10G_CORE_STAT_3S_DUPLEX_MODE (5883L)
+#define PHY3S10G_CORE_STAT_3S_LINK_STATUS (5884L)
+#define PHY3S10G_CORE_STAT_3S_LINK_SYNC (5885L)
+#define PHY3S10G_CORE_STAT_3S_NT_LINK_STATE (5886L)
+#define PHY3S10G_CORE_STAT_3S_PAUSE (5887L)
+#define PHY3S10G_CORE_STAT_3S_PHY_LINK_STAT (5888L)
+#define PHY3S10G_CORE_STAT_3S_REM_FAULT_ENC (5889L)
+#define PHY3S10G_CORE_STAT_3S_RESERVED (5890L)
+#define PHY3S10G_CORE_STAT_3S_RUDI_C (5891L)
+#define PHY3S10G_CORE_STAT_3S_RUDI_I (5892L)
+#define PHY3S10G_CORE_STAT_3S_RUDI_INVALID (5893L)
+#define PHY3S10G_CORE_STAT_3S_RXDISPERR (5894L)
+#define PHY3S10G_CORE_STAT_3S_RXNOTINTABLE (5895L)
+#define PHY3S10G_CORE_STAT_3S_SPEED (5896L)
+#define PHY3S10G_CTRL (5897L)
+#define PHY3S10G_CTRL_FORCE_LINK_DOWN (5898L)
+#define PHY3S10G_CTRL_HOST_LOOPBACK_10G (5899L)
+#define PHY3S10G_CTRL_HOST_LOOPBACK_3S (5900L)
+#define PHY3S10G_CTRL_LINE_LOOPBACK_10G (5901L)
+#define PHY3S10G_CTRL_LINE_LOOPBACK_3S (5902L)
+#define PHY3S10G_CTRL_LINKUP_LATENCY (5903L)
+#define PHY3S10G_CTRL_PHY_CHANGE_FSM_DONE (5904L)
+#define PHY3S10G_CTRL_PHY_SEL (5905L)
+#define PHY3S10G_CTRL_SOFT_RESET (5906L)
+#define PHY3S10G_GPIO (5907L)
+#define PHY3S10G_GPIO_ABS (5908L)
+#define PHY3S10G_GPIO_LED_MODE (5909L)
+#define PHY3S10G_GPIO_RATE_SEL (5910L)
+#define PHY3S10G_GPIO_RX_LOS (5911L)
+#define PHY3S10G_GPIO_TX_DISABLE (5912L)
+#define PHY3S10G_GPIO_TX_FAULT (5913L)
+#define PHY3S10G_GT_CR (5914L)
+#define PHY3S10G_GT_CR_EYESCANRESET (5915L)
+#define PHY3S10G_GT_CR_EYESCANTRIGGER (5916L)
+#define PHY3S10G_GT_CR_LOOPBACK (5917L)
+#define PHY3S10G_GT_CR_RXCDRHOLD (5918L)
+#define PHY3S10G_GT_CR_RXDFELPMRESET (5919L)
+#define PHY3S10G_GT_CR_RXLPMEN (5920L)
+#define PHY3S10G_GT_CR_RXPMARESET (5921L)
+#define PHY3S10G_GT_CR_RXPRBSCNTRESET (5922L)
+#define PHY3S10G_GT_CR_RXPRBSSEL (5923L)
+#define PHY3S10G_GT_CR_TXDIFFCTRL (5924L)
+#define PHY3S10G_GT_CR_TXPMARESET (5925L)
+#define PHY3S10G_GT_CR_TXPOSTCURSOR (5926L)
+#define PHY3S10G_GT_CR_TXPRBSFORCEERR (5927L)
+#define PHY3S10G_GT_CR_TXPRBSSEL (5928L)
+#define PHY3S10G_GT_CR_TXPRECURSOR (5929L)
+#define PHY3S10G_GT_SR (5930L)
+#define PHY3S10G_GT_SR_EYESCANDATAERROR (5931L)
+#define PHY3S10G_GT_SR_RXBUFSTATUS (5932L)
+#define PHY3S10G_GT_SR_RXPMARESETDONE (5933L)
+#define PHY3S10G_GT_SR_RXPRBSERR (5934L)
+#define PHY3S10G_GT_SR_RXRESETDONE (5935L)
+#define PHY3S10G_GT_SR_TXBUFSTATUS (5936L)
+#define PHY3S10G_GT_SR_TXRESETDONE (5937L)
+#define PHY3S10G_INT (5938L)
+#define PHY3S10G_INT_EN (5939L)
+#define PHY3S10G_INT_MAX_PACE (5940L)
+#define PHY3S10G_LINK_SUMMARY (5941L)
+#define PHY3S10G_LINK_SUMMARY_ABS (5942L)
+#define PHY3S10G_LINK_SUMMARY_ANEG_BYPASS (5943L)
+#define PHY3S10G_LINK_SUMMARY_LINK_DOWN_CNT (5944L)
+#define PHY3S10G_LINK_SUMMARY_NT_LINK_STATE (5945L)
+#define PHY3S10G_TS_COMP (5946L)
+#define PHY3S10G_TS_COMP_RX (5947L)
+#define PHY3S10G_TS_COMP_RX_10G (5948L)
+#define PHY3S10G_TS_COMP_RX_3S (5949L)
+/* PM */
+#define PM_CTRL (5950L)
+#define PM_CTRL_SW_CLEAN_DONE (5951L)
+#define PM_DEBUG_RP (5952L)
+#define PM_DEBUG_RP_RP (5953L)
+#define PM_DEBUG_RP_SETUP (5954L)
+#define PM_DEBUG_RP_SETUP_HB (5955L)
+#define PM_DEBUG_RX_BLOCK (5956L)
+#define PM_DEBUG_RX_BLOCK_MASK (5957L)
+#define PM_HB_SIZE_RX_MEM_CTRL (5958L)
+#define PM_HB_SIZE_RX_MEM_CTRL_A (5959L)
+#define PM_HB_SIZE_RX_MEM_CTRL_CNT (5960L)
+#define PM_HB_SIZE_RX_MEM_DATA (5961L)
+#define PM_HB_SIZE_RX_MEM_DATA_SIZE (5962L)
+#define PM_HB_SIZE_RX_THRESHOLD (5963L)
+#define PM_HB_SIZE_RX_THRESHOLD_D (5964L)
+#define PM_HB_SIZE_TX_THRESHOLD (5965L)
+#define PM_HB_SIZE_TX_THRESHOLD_D (5966L)
+#define PM_PBI_MEM_CTRL (5967L)
+#define PM_PBI_MEM_CTRL_A (5968L)
+#define PM_PBI_MEM_CTRL_CNT (5969L)
+#define PM_PBI_MEM_DATA (5970L)
+#define PM_PBI_MEM_DATA_PHYADDR (5971L)
+#define PM_PBI_MEM_DATA_SIZE (5972L)
+#define PM_POINTER_BANKS (5973L)
+#define PM_POINTER_BANKS_D (5974L)
+#define PM_RXTX_FAST_MEM_CTRL (5975L)
+#define PM_RXTX_FAST_MEM_CTRL_A (5976L)
+#define PM_RXTX_FAST_MEM_CTRL_CNT (5977L)
+#define PM_RXTX_FAST_MEM_DATA (5978L)
+#define PM_RXTX_FAST_MEM_DATA_BANK (5979L)
+#define PM_RXTX_FAST_MEM_DATA_ENTRY (5980L)
+#define PM_RXTX_FAST_MEM_DATA_HOST_BUFFER (5981L)
+#define PM_RXTX_FAST_MEM_DATA_RX_TX (5982L)
+#define PM_RXTX_FAST_MEM_DATA_VLD (5983L)
+#define PM_RXTX_SLOW_MEM_CTRL (5984L)
+#define PM_RXTX_SLOW_MEM_CTRL_A (5985L)
+#define PM_RXTX_SLOW_MEM_CTRL_CNT (5986L)
+#define PM_RXTX_SLOW_MEM_DATA (5987L)
+#define PM_RXTX_SLOW_MEM_DATA_BANK (5988L)
+#define PM_RXTX_SLOW_MEM_DATA_ENTRY (5989L)
+#define PM_RXTX_SLOW_MEM_DATA_HOST_BUFFER (5990L)
+#define PM_RXTX_SLOW_MEM_DATA_RX_TX (5991L)
+#define PM_RXTX_SLOW_MEM_DATA_VLD (5992L)
+#define PM_RXWP_MEM_CTRL (5993L)
+#define PM_RXWP_MEM_CTRL_A (5994L)
+#define PM_RXWP_MEM_CTRL_CNT (5995L)
+#define PM_RXWP_MEM_DATA (5996L)
+#define PM_RXWP_MEM_DATA_BANK (5997L)
+#define PM_RXWP_MEM_DATA_ENTRY (5998L)
+#define PM_RXWP_MEM_DATA_HOST_BUFFER (5999L)
+#define PM_RXWP_MEM_DATA_VLD (6000L)
+#define PM_RX_BLOCKED_STATUS (6001L)
+#define PM_RX_BLOCKED_STATUS_D (6002L)
+#define PM_RX_BLOCKED_STATUS_HI (6003L)
+#define PM_RX_BLOCKED_STATUS_HI_D (6004L)
+#define PM_RX_OVERFLOW_STATUS (6005L)
+#define PM_RX_OVERFLOW_STATUS_D (6006L)
+#define PM_RX_READER (6007L)
+#define PM_RX_READER_MASK (6008L)
+#define PM_RX_TX_FAST_POINTER_BLOCK_INTERVAL (6009L)
+#define PM_RX_TX_FAST_POINTER_BLOCK_INTERVAL_D (6010L)
+#define PM_RX_TX_SLOW_POINTER_BLOCK_INTERVAL (6011L)
+#define PM_RX_TX_SLOW_POINTER_BLOCK_INTERVAL_D (6012L)
+#define PM_RX_WRITE_POINTER_BLOCK_INTERVAL (6013L)
+#define PM_RX_WRITE_POINTER_BLOCK_INTERVAL_D (6014L)
+#define PM_TXRP_MEM_CTRL (6015L)
+#define PM_TXRP_MEM_CTRL_A (6016L)
+#define PM_TXRP_MEM_CTRL_CNT (6017L)
+#define PM_TXRP_MEM_DATA (6018L)
+#define PM_TXRP_MEM_DATA_BANK (6019L)
+#define PM_TXRP_MEM_DATA_ENTRY (6020L)
+#define PM_TXRP_MEM_DATA_HOST_BUFFER (6021L)
+#define PM_TXRP_MEM_DATA_VLD (6022L)
+#define PM_TX_READ_POINTER_BLOCK_INTERVAL (6023L)
+#define PM_TX_READ_POINTER_BLOCK_INTERVAL_D (6024L)
+/* PRM_NT100A01_01 */
+#define PRM_NT100A01_01_POWER (6025L)
+#define PRM_NT100A01_01_POWER_PU_NSEB (6026L)
+#define PRM_NT100A01_01_POWER_PU_PHY (6027L)
+#define PRM_NT100A01_01_RST (6028L)
+#define PRM_NT100A01_01_RST_PERIPH (6029L)
+#define PRM_NT100A01_01_RST_PLATFORM (6030L)
+/* PRM_NT50B01_01 */
+#define PRM_NT50B01_01_POWER (6031L)
+#define PRM_NT50B01_01_POWER_PU_NSEB (6032L)
+#define PRM_NT50B01_01_POWER_PU_PHY (6033L)
+#define PRM_NT50B01_01_RST (6034L)
+#define PRM_NT50B01_01_RST_PERIPH (6035L)
+#define PRM_NT50B01_01_RST_PLATFORM (6036L)
+/* PTP1588 */
+#define PTP1588_CONF (6037L)
+#define PTP1588_CONF_MII_RX_TX_LOOP (6038L)
+#define PTP1588_CONF_MII_TX_RX_LOOP (6039L)
+#define PTP1588_CONF_PHY_RST (6040L)
+#define PTP1588_CONF_PHY_RST1 (6041L)
+#define PTP1588_CONF_PHY_RST2 (6042L)
+#define PTP1588_CONF_PTP_CTRL_LOCAL (6043L)
+#define PTP1588_CONF_PTP_RX_CTRL (6044L)
+#define PTP1588_CONF_PTP_TX_CTRL (6045L)
+#define PTP1588_CONF_PTP_TX_CTRL_OS (6046L)
+#define PTP1588_CONF_RX_IGNORE_DEST_ADDR (6047L)
+#define PTP1588_CONF_TG_CMD (6048L)
+#define PTP1588_CONF_TG_MODE (6049L)
+#define PTP1588_CONF_TSM_MI_ACK (6050L)
+#define PTP1588_CONF_TSM_MI_BUSY (6051L)
+#define PTP1588_CONF_TSM_MI_ENA (6052L)
+#define PTP1588_CONF_TSM_MI_REQ (6053L)
+#define PTP1588_CONF_TX_IFG (6054L)
+#define PTP1588_CONF_TX_IGNORE_DEST_ADDR (6055L)
+#define PTP1588_CTRL (6056L)
+#define PTP1588_CTRL_CLK_ENABLE (6057L)
+#define PTP1588_CTRL_MII_RX_TX_LOOP (6058L)
+#define PTP1588_CTRL_MII_TX_RX_LOOP (6059L)
+#define PTP1588_CTRL_PRESENT (6060L)
+#define PTP1588_CTRL_RESET_N (6061L)
+#define PTP1588_CTRL_TS_MI_ACK (6062L)
+#define PTP1588_CTRL_TS_MI_BUSY (6063L)
+#define PTP1588_CTRL_TS_MI_ENA (6064L)
+#define PTP1588_CTRL_TS_MI_REQ (6065L)
+#define PTP1588_CTRL_TX_IFG (6066L)
+#define PTP1588_GP_DATA (6067L)
+#define PTP1588_GP_DATA_GPIO (6068L)
+#define PTP1588_GP_DATA_PWRDOWN_INTN (6069L)
+#define PTP1588_GP_DATA_TIMESYNC_CON (6070L)
+#define PTP1588_GP_DATA_LH (6071L)
+#define PTP1588_GP_DATA_LH_GPIO (6072L)
+#define PTP1588_GP_DATA_LH_PWRDOWN_INTN (6073L)
+#define PTP1588_GP_DATA_LH_TIMESYNC_CON (6074L)
+#define PTP1588_GP_DATA_LL (6075L)
+#define PTP1588_GP_DATA_LL_GPIO (6076L)
+#define PTP1588_GP_DATA_LL_PWRDOWN_INTN (6077L)
+#define PTP1588_GP_DATA_LL_TIMESYNC_CON (6078L)
+#define PTP1588_GP_OE (6079L)
+#define PTP1588_GP_OE_GPIO (6080L)
+#define PTP1588_GP_OE_PWRDOWN_INTN (6081L)
+#define PTP1588_GP_OE_TIMESYNC_CON (6082L)
+#define PTP1588_MAC_HOST_ADDR (6083L)
+#define PTP1588_MAC_HOST_ADDR_ADDR (6084L)
+#define PTP1588_MAC_HOST_ADDR_MDIO_ACCESS (6085L)
+#define PTP1588_MAC_HOST_ADDR_OPCODE (6086L)
+#define PTP1588_MAC_HOST_ADDR_RDY (6087L)
+#define PTP1588_MAC_HOST_DATA_LSB (6088L)
+#define PTP1588_MAC_HOST_DATA_LSB_DATA (6089L)
+#define PTP1588_MAC_HOST_DATA_MSB (6090L)
+#define PTP1588_MAC_HOST_DATA_MSB_DATA (6091L)
+#define PTP1588_MAC_INBAND_STAT (6092L)
+#define PTP1588_MAC_INBAND_STAT_DUPLEX (6093L)
+#define PTP1588_MAC_INBAND_STAT_LINK (6094L)
+#define PTP1588_MAC_INBAND_STAT_SPEED (6095L)
+#define PTP1588_MAC_MI_CONF (6096L)
+#define PTP1588_MAC_MI_CONF_ACCESS_TYPE (6097L)
+#define PTP1588_MAC_MI_CONF_ADDRESS (6098L)
+#define PTP1588_MAC_MI_CONF_RDY (6099L)
+#define PTP1588_MAC_MI_DATA (6100L)
+#define PTP1588_MAC_MI_DATA_DATA (6101L)
+#define PTP1588_RX_HOST_ADR_LSB (6102L)
+#define PTP1588_RX_HOST_ADR_LSB_LSB (6103L)
+#define PTP1588_RX_HOST_ADR_MSB (6104L)
+#define PTP1588_RX_HOST_ADR_MSB_MSB (6105L)
+#define PTP1588_RX_HOST_CONF (6106L)
+#define PTP1588_RX_HOST_CONF_ENA (6107L)
+#define PTP1588_RX_HOST_CONF_RDPTR (6108L)
+#define PTP1588_RX_HOST_CONF_REDUCED (6109L)
+#define PTP1588_RX_HOST_CTRL (6110L)
+#define PTP1588_RX_HOST_CTRL_ENA (6111L)
+#define PTP1588_RX_HOST_CTRL_RDPTR (6112L)
+#define PTP1588_RX_HOST_CTRL_REDUCED (6113L)
+#define PTP1588_STAT (6114L)
+#define PTP1588_STAT_DATA (6115L)
+#define PTP1588_STAT_CONF (6116L)
+#define PTP1588_STAT_CONF_INDEX (6117L)
+#define PTP1588_STAT_CONF_LOCK (6118L)
+#define PTP1588_STAT_CTRL (6119L)
+#define PTP1588_STAT_CTRL_INDEX (6120L)
+#define PTP1588_STAT_CTRL_LOCK (6121L)
+#define PTP1588_TX_FIRST_DAT (6122L)
+#define PTP1588_TX_FIRST_DAT_DAT (6123L)
+#define PTP1588_TX_LAST1_DAT (6124L)
+#define PTP1588_TX_LAST1_DAT_DAT (6125L)
+#define PTP1588_TX_LAST2_DAT (6126L)
+#define PTP1588_TX_LAST2_DAT_DAT (6127L)
+#define PTP1588_TX_LAST3_DAT (6128L)
+#define PTP1588_TX_LAST3_DAT_DAT (6129L)
+#define PTP1588_TX_LAST4_DAT (6130L)
+#define PTP1588_TX_LAST4_DAT_DAT (6131L)
+#define PTP1588_TX_MID_DAT (6132L)
+#define PTP1588_TX_MID_DAT_DAT (6133L)
+#define PTP1588_TX_PACKET_STATE (6134L)
+#define PTP1588_TX_PACKET_STATE_MSG_TYPE (6135L)
+#define PTP1588_TX_PACKET_STATE_PCK_TYPE (6136L)
+#define PTP1588_TX_PACKET_STATE_SEQ_ID (6137L)
+#define PTP1588_TX_PACKET_STATE_TEST_MARGIN (6138L)
+#define PTP1588_TX_PACKET_STATE_VALID (6139L)
+#define PTP1588_TX_STATUS (6140L)
+#define PTP1588_TX_STATUS_DB_ERR (6141L)
+#define PTP1588_TX_STATUS_DB_FULL (6142L)
+#define PTP1588_TX_STATUS_FIFO_STATUS (6143L)
+#define PTP1588_TX_STATUS_RDY (6144L)
+#define PTP1588_TX_STATUS_TG_ENA (6145L)
+#define PTP1588_TX_STATUS_TG_MODE (6146L)
+#define PTP1588_TX_TIMESTAMP_NS (6147L)
+#define PTP1588_TX_TIMESTAMP_NS_TIMESTAMP (6148L)
+#define PTP1588_TX_TIMESTAMP_SEC (6149L)
+#define PTP1588_TX_TIMESTAMP_SEC_TIMESTAMP (6150L)
+/* QM */
+#define QM_BLOCK_SIZE (6151L)
+#define QM_BLOCK_SIZE_CELLS (6152L)
+#define QM_CTRL (6153L)
+#define QM_CTRL_ACTIVE_QUEUES (6154L)
+#define QM_CTRL_ACTIVE_QUEUES_QPI_BYPASS (6155L)
+#define QM_CTRL_ENABLE (6156L)
+#define QM_CTRL_PRIORITY_SCHEME (6157L)
+#define QM_DEBUG_BLOCK_SIZE (6158L)
+#define QM_DEBUG_BLOCK_SIZE_CELLS (6159L)
+#define QM_DEBUG_CRC (6160L)
+#define QM_DEBUG_CRC_FORCE_ERROR (6161L)
+#define QM_DEBUG_SDRAM_SIZE (6162L)
+#define QM_DEBUG_SDRAM_SIZE_MASK (6163L)
+#define QM_GROUP_LIMIT_MEM_CTRL (6164L)
+#define QM_GROUP_LIMIT_MEM_CTRL_A (6165L)
+#define QM_GROUP_LIMIT_MEM_CTRL_CNT (6166L)
+#define QM_GROUP_LIMIT_MEM_DATA (6167L)
+#define QM_GROUP_LIMIT_MEM_DATA_LIMIT (6168L)
+#define QM_GROUP_MAPPING_MEM_CTRL (6169L)
+#define QM_GROUP_MAPPING_MEM_CTRL_A (6170L)
+#define QM_GROUP_MAPPING_MEM_CTRL_CNT (6171L)
+#define QM_GROUP_MAPPING_MEM_DATA (6172L)
+#define QM_GROUP_MAPPING_MEM_DATA_GROUP0 (6173L)
+#define QM_GROUP_MAPPING_MEM_DATA_GROUP1 (6174L)
+#define QM_GROUP_MAPPING_MEM_DATA_GROUP2 (6175L)
+#define QM_PRIO_LEVELS_MEM_CTRL (6176L)
+#define QM_PRIO_LEVELS_MEM_CTRL_A (6177L)
+#define QM_PRIO_LEVELS_MEM_CTRL_CNT (6178L)
+#define QM_PRIO_LEVELS_MEM_DATA (6179L)
+#define QM_PRIO_LEVELS_MEM_DATA_PRIO (6180L)
+#define QM_QUEUE_LIMIT_MEM_CTRL (6181L)
+#define QM_QUEUE_LIMIT_MEM_CTRL_A (6182L)
+#define QM_QUEUE_LIMIT_MEM_CTRL_CNT (6183L)
+#define QM_QUEUE_LIMIT_MEM_DATA (6184L)
+#define QM_QUEUE_LIMIT_MEM_DATA_LIMIT (6185L)
+#define QM_STATUS_BLOCKED (6186L)
+#define QM_STATUS_BLOCKED_D (6187L)
+#define QM_STATUS_BLOCKED_HI (6188L)
+#define QM_STATUS_BLOCKED_HI_D (6189L)
+#define QM_STATUS_BLOCKING (6190L)
+#define QM_STATUS_BLOCKING_D (6191L)
+#define QM_STATUS_BLOCKING_HI (6192L)
+#define QM_STATUS_BLOCKING_HI_D (6193L)
+#define QM_STATUS_CRC_ERROR (6194L)
+#define QM_STATUS_CRC_ERROR_CNT (6195L)
+#define QM_STATUS_EMPTY (6196L)
+#define QM_STATUS_EMPTY_D (6197L)
+#define QM_STATUS_EMPTY_HI (6198L)
+#define QM_STATUS_EMPTY_HI_D (6199L)
+#define QM_STATUS_FLUSH_DROP (6200L)
+#define QM_STATUS_FLUSH_DROP_CNT (6201L)
+#define QM_STATUS_SDRAM_BLOCK_MAX_USAGE (6202L)
+#define QM_STATUS_SDRAM_BLOCK_MAX_USAGE_D (6203L)
+#define QM_STATUS_SDRAM_BLOCK_USAGE (6204L)
+#define QM_STATUS_SDRAM_BLOCK_USAGE_D (6205L)
+#define QM_STATUS_SDRAM_CELL_MAX_USAGE (6206L)
+#define QM_STATUS_SDRAM_CELL_MAX_USAGE_D (6207L)
+#define QM_STATUS_SDRAM_CELL_USAGE (6208L)
+#define QM_STATUS_SDRAM_CELL_USAGE_D (6209L)
+/* QSL */
+#define QSL_LTX_CTRL (6210L)
+#define QSL_LTX_CTRL_ADR (6211L)
+#define QSL_LTX_CTRL_CNT (6212L)
+#define QSL_LTX_DATA (6213L)
+#define QSL_LTX_DATA_LR (6214L)
+#define QSL_LTX_DATA_TSA (6215L)
+#define QSL_LTX_DATA_TX_PORT (6216L)
+#define QSL_QEN_CTRL (6217L)
+#define QSL_QEN_CTRL_ADR (6218L)
+#define QSL_QEN_CTRL_CNT (6219L)
+#define QSL_QEN_DATA (6220L)
+#define QSL_QEN_DATA_EN (6221L)
+#define QSL_QST_CTRL (6222L)
+#define QSL_QST_CTRL_ADR (6223L)
+#define QSL_QST_CTRL_CNT (6224L)
+#define QSL_QST_DATA (6225L)
+#define QSL_QST_DATA_EN (6226L)
+#define QSL_QST_DATA_LRE (6227L)
+#define QSL_QST_DATA_QEN (6228L)
+#define QSL_QST_DATA_QUEUE (6229L)
+#define QSL_QST_DATA_TCI (6230L)
+#define QSL_QST_DATA_TX_PORT (6231L)
+#define QSL_QST_DATA_VEN (6232L)
+#define QSL_RCP_CTRL (6233L)
+#define QSL_RCP_CTRL_ADR (6234L)
+#define QSL_RCP_CTRL_CNT (6235L)
+#define QSL_RCP_DATA (6236L)
+#define QSL_RCP_DATA_CAO (6237L)
+#define QSL_RCP_DATA_DISCARD (6238L)
+#define QSL_RCP_DATA_DROP (6239L)
+#define QSL_RCP_DATA_LR (6240L)
+#define QSL_RCP_DATA_TBL_HI (6241L)
+#define QSL_RCP_DATA_TBL_IDX (6242L)
+#define QSL_RCP_DATA_TBL_LO (6243L)
+#define QSL_RCP_DATA_TBL_MSK (6244L)
+#define QSL_RCP_DATA_TSA (6245L)
+#define QSL_RCP_DATA_VLI (6246L)
+#define QSL_UNMQ_CTRL (6247L)
+#define QSL_UNMQ_CTRL_ADR (6248L)
+#define QSL_UNMQ_CTRL_CNT (6249L)
+#define QSL_UNMQ_DATA (6250L)
+#define QSL_UNMQ_DATA_DEST_QUEUE (6251L)
+#define QSL_UNMQ_DATA_EN (6252L)
+/* QSPI */
+#define QSPI_CR (6253L)
+#define QSPI_CR_CPHA (6254L)
+#define QSPI_CR_CPOL (6255L)
+#define QSPI_CR_LOOP (6256L)
+#define QSPI_CR_LSBF (6257L)
+#define QSPI_CR_MSSAE (6258L)
+#define QSPI_CR_MST (6259L)
+#define QSPI_CR_MTI (6260L)
+#define QSPI_CR_RXFIFO_RST (6261L)
+#define QSPI_CR_SPE (6262L)
+#define QSPI_CR_TXFIFO_RST (6263L)
+#define QSPI_DGIE (6264L)
+#define QSPI_DGIE_GIE (6265L)
+#define QSPI_DRR (6266L)
+#define QSPI_DRR_DATA_VAL (6267L)
+#define QSPI_DTR (6268L)
+#define QSPI_DTR_DATA_VAL (6269L)
+#define QSPI_IER (6270L)
+#define QSPI_IER_CMD_ERR (6271L)
+#define QSPI_IER_CPOL_CPHA_ERR (6272L)
+#define QSPI_IER_DRR_FULL (6273L)
+#define QSPI_IER_DRR_NEMPTY (6274L)
+#define QSPI_IER_DRR_OR (6275L)
+#define QSPI_IER_DTR_EMPTY (6276L)
+#define QSPI_IER_DTR_UR (6277L)
+#define QSPI_IER_LOOP_ERR (6278L)
+#define QSPI_IER_MODF (6279L)
+#define QSPI_IER_MSB_ERR (6280L)
+#define QSPI_IER_SLV_ERR (6281L)
+#define QSPI_IER_SLV_MODF (6282L)
+#define QSPI_IER_SLV_MS (6283L)
+#define QSPI_IER_TXFIFO_HEMPTY (6284L)
+#define QSPI_ISR (6285L)
+#define QSPI_ISR_CMD_ERR (6286L)
+#define QSPI_ISR_CPOL_CPHA_ERR (6287L)
+#define QSPI_ISR_DRR_FULL (6288L)
+#define QSPI_ISR_DRR_NEMPTY (6289L)
+#define QSPI_ISR_DRR_OR (6290L)
+#define QSPI_ISR_DTR_EMPTY (6291L)
+#define QSPI_ISR_DTR_UR (6292L)
+#define QSPI_ISR_LOOP_ERR (6293L)
+#define QSPI_ISR_MODF (6294L)
+#define QSPI_ISR_MSB_ERR (6295L)
+#define QSPI_ISR_SLV_ERR (6296L)
+#define QSPI_ISR_SLV_MODF (6297L)
+#define QSPI_ISR_SLV_MS (6298L)
+#define QSPI_ISR_TXFIFO_HEMPTY (6299L)
+#define QSPI_RX_FIFO_OCY (6300L)
+#define QSPI_RX_FIFO_OCY_OCY_VAL (6301L)
+#define QSPI_SR (6302L)
+#define QSPI_SR_CMD_ERR (6303L)
+#define QSPI_SR_CPOL_CPHA_ERR (6304L)
+#define QSPI_SR_LOOP_ERR (6305L)
+#define QSPI_SR_MODF (6306L)
+#define QSPI_SR_MSB_ERR (6307L)
+#define QSPI_SR_RXEMPTY (6308L)
+#define QSPI_SR_RXFULL (6309L)
+#define QSPI_SR_SLVMS (6310L)
+#define QSPI_SR_SLV_ERR (6311L)
+#define QSPI_SR_TXEMPTY (6312L)
+#define QSPI_SR_TXFULL (6313L)
+#define QSPI_SRR (6314L)
+#define QSPI_SRR_RST (6315L)
+#define QSPI_SSR (6316L)
+#define QSPI_SSR_SEL_SLV (6317L)
+#define QSPI_TX_FIFO_OCY (6318L)
+#define QSPI_TX_FIFO_OCY_OCY_VAL (6319L)
+/* R2DRP */
+#define R2DRP_CTRL (6320L)
+#define R2DRP_CTRL_ADR (6321L)
+#define R2DRP_CTRL_DATA (6322L)
+#define R2DRP_CTRL_DBG_BUSY (6323L)
+#define R2DRP_CTRL_DONE (6324L)
+#define R2DRP_CTRL_RES (6325L)
+#define R2DRP_CTRL_WREN (6326L)
+/* RAC */
+#define RAC_DBG_CTRL (6327L)
+#define RAC_DBG_CTRL_C (6328L)
+#define RAC_DBG_DATA (6329L)
+#define RAC_DBG_DATA_D (6330L)
+#define RAC_DUMMY0 (6331L)
+#define RAC_DUMMY1 (6332L)
+#define RAC_DUMMY2 (6333L)
+#define RAC_NDM_REGISTER (6334L)
+#define RAC_NDM_REGISTER_NDM (6335L)
+#define RAC_NMB_DATA (6336L)
+#define RAC_NMB_DATA_NMB_DATA (6337L)
+#define RAC_NMB_RD_ADR (6338L)
+#define RAC_NMB_RD_ADR_ADR (6339L)
+#define RAC_NMB_RD_ADR_RES (6340L)
+#define RAC_NMB_STATUS (6341L)
+#define RAC_NMB_STATUS_BUS_TIMEOUT (6342L)
+#define RAC_NMB_STATUS_NMB_READY (6343L)
+#define RAC_NMB_WR_ADR (6344L)
+#define RAC_NMB_WR_ADR_ADR (6345L)
+#define RAC_NMB_WR_ADR_RES (6346L)
+#define RAC_RAB_BUF_FREE (6347L)
+#define RAC_RAB_BUF_FREE_IB_FREE (6348L)
+#define RAC_RAB_BUF_FREE_IB_OVF (6349L)
+#define RAC_RAB_BUF_FREE_OB_FREE (6350L)
+#define RAC_RAB_BUF_FREE_OB_OVF (6351L)
+#define RAC_RAB_BUF_FREE_TIMEOUT (6352L)
+#define RAC_RAB_BUF_USED (6353L)
+#define RAC_RAB_BUF_USED_FLUSH (6354L)
+#define RAC_RAB_BUF_USED_IB_USED (6355L)
+#define RAC_RAB_BUF_USED_OB_USED (6356L)
+#define RAC_RAB_DMA_IB_HI (6357L)
+#define RAC_RAB_DMA_IB_HI_PHYADDR (6358L)
+#define RAC_RAB_DMA_IB_LO (6359L)
+#define RAC_RAB_DMA_IB_LO_PHYADDR (6360L)
+#define RAC_RAB_DMA_IB_RD (6361L)
+#define RAC_RAB_DMA_IB_RD_PTR (6362L)
+#define RAC_RAB_DMA_IB_WR (6363L)
+#define RAC_RAB_DMA_IB_WR_PTR (6364L)
+#define RAC_RAB_DMA_OB_HI (6365L)
+#define RAC_RAB_DMA_OB_HI_PHYADDR (6366L)
+#define RAC_RAB_DMA_OB_LO (6367L)
+#define RAC_RAB_DMA_OB_LO_PHYADDR (6368L)
+#define RAC_RAB_DMA_OB_WR (6369L)
+#define RAC_RAB_DMA_OB_WR_PTR (6370L)
+#define RAC_RAB_IB_DATA (6371L)
+#define RAC_RAB_IB_DATA_D (6372L)
+#define RAC_RAB_INIT (6373L)
+#define RAC_RAB_INIT_RAB (6374L)
+#define RAC_RAB_OB_DATA (6375L)
+#define RAC_RAB_OB_DATA_D (6376L)
+/* RBH */
+#define RBH_CTRL (6377L)
+#define RBH_CTRL_ENABLE_METADATA_HB (6378L)
+#define RBH_CTRL_ENABLE_PM (6379L)
+#define RBH_CTRL_ENABLE_QHM (6380L)
+#define RBH_CTRL_HB_MAX (6381L)
+#define RBH_CTRL_HB_SEGMENT_SIZE (6382L)
+#define RBH_CTRL_RESERVED (6383L)
+#define RBH_CTRL_RESET_CREDITS_QHM (6384L)
+#define RBH_DEB_REG1 (6385L)
+#define RBH_DEB_REG1_VALUE (6386L)
+#define RBH_DEB_REG2 (6387L)
+#define RBH_DEB_REG2_VALUE (6388L)
+#define RBH_DEB_REG3 (6389L)
+#define RBH_DEB_REG3_VALUE (6390L)
+#define RBH_FLUSH_ADR_HI (6391L)
+#define RBH_FLUSH_ADR_HI_VALUE (6392L)
+#define RBH_FLUSH_ADR_LO (6393L)
+#define RBH_FLUSH_ADR_LO_VALUE (6394L)
+#define RBH_HOST_BUF_SIZE_MEM_CTRL (6395L)
+#define RBH_HOST_BUF_SIZE_MEM_CTRL_A (6396L)
+#define RBH_HOST_BUF_SIZE_MEM_CTRL_CNT (6397L)
+#define RBH_HOST_BUF_SIZE_MEM_DATA (6398L)
+#define RBH_HOST_BUF_SIZE_MEM_DATA_HB_SEGMENT_CNT (6399L)
+#define RBH_STATUS (6400L)
+#define RBH_STATUS_BUFFER_EMPTY (6401L)
+#define RBH_STATUS_DWA_DATAFIFO_EMPTY (6402L)
+#define RBH_STATUS_PWA_DATAFIFO_EMPTY (6403L)
+#define RBH_WP_SET_MEM_CTRL (6404L)
+#define RBH_WP_SET_MEM_CTRL_A (6405L)
+#define RBH_WP_SET_MEM_CTRL_CNT (6406L)
+#define RBH_WP_SET_MEM_DATA (6407L)
+#define RBH_WP_SET_MEM_DATA_WP (6408L)
+/* RFD */
+#define RFD_CTRL (6409L)
+#define RFD_CTRL_CFP (6410L)
+#define RFD_CTRL_ISL (6411L)
+#define RFD_CTRL_PWMCW (6412L)
+#define RFD_MAX_FRAME_SIZE (6413L)
+#define RFD_MAX_FRAME_SIZE_MAX (6414L)
+#define RFD_TNL_VLAN (6415L)
+#define RFD_TNL_VLAN_TPID0 (6416L)
+#define RFD_TNL_VLAN_TPID1 (6417L)
+#define RFD_VLAN (6418L)
+#define RFD_VLAN_TPID0 (6419L)
+#define RFD_VLAN_TPID1 (6420L)
+#define RFD_VXLAN (6421L)
+#define RFD_VXLAN_DP0 (6422L)
+#define RFD_VXLAN_DP1 (6423L)
+/* RMC */
+#define RMC_CTRL (6424L)
+#define RMC_CTRL_BLOCK_KEEPA (6425L)
+#define RMC_CTRL_BLOCK_MAC_PORT (6426L)
+#define RMC_CTRL_BLOCK_RPP_SLICE (6427L)
+#define RMC_CTRL_BLOCK_STATT (6428L)
+#define RMC_CTRL_LAG_PHY_ODD_EVEN (6429L)
+#define RMC_DBG (6430L)
+#define RMC_DBG_MERGE (6431L)
+#define RMC_MAC_IF (6432L)
+#define RMC_MAC_IF_ERR (6433L)
+#define RMC_STATUS (6434L)
+#define RMC_STATUS_DESCR_FIFO_OF (6435L)
+#define RMC_STATUS_SF_RAM_OF (6436L)
+/* RNTC */
+#define RNTC_CTRL (6437L)
+#define RNTC_CTRL_RNTC_ENA (6438L)
+#define RNTC_STAT (6439L)
+#define RNTC_STAT_EMPTY (6440L)
+#define RNTC_TX_DATA (6441L)
+#define RNTC_TX_DATA_D (6442L)
+/* ROA */
+#define ROA_CONFIG (6443L)
+#define ROA_CONFIG_FWD_CELLBUILDER_PCKS (6444L)
+#define ROA_CONFIG_FWD_NON_NORMAL_PCKS (6445L)
+#define ROA_CONFIG_FWD_NORMAL_PCKS (6446L)
+#define ROA_CONFIG_FWD_RECIRCULATE (6447L)
+#define ROA_CONFIG_FWD_TXPORT0 (6448L)
+#define ROA_CONFIG_FWD_TXPORT1 (6449L)
+#define ROA_IGS (6450L)
+#define ROA_IGS_BYTE (6451L)
+#define ROA_IGS_BYTE_DROP (6452L)
+#define ROA_IGS_PKT (6453L)
+#define ROA_IGS_PKT_DROP (6454L)
+#define ROA_LAGCFG_CTRL (6455L)
+#define ROA_LAGCFG_CTRL_ADR (6456L)
+#define ROA_LAGCFG_CTRL_CNT (6457L)
+#define ROA_LAGCFG_DATA (6458L)
+#define ROA_LAGCFG_DATA_TXPHY_PORT (6459L)
+#define ROA_RCC (6460L)
+#define ROA_RCC_BYTE (6461L)
+#define ROA_RCC_BYTE_DROP (6462L)
+#define ROA_RCC_PKT (6463L)
+#define ROA_RCC_PKT_DROP (6464L)
+#define ROA_TUNCFG_CTRL (6465L)
+#define ROA_TUNCFG_CTRL_ADR (6466L)
+#define ROA_TUNCFG_CTRL_CNT (6467L)
+#define ROA_TUNCFG_DATA (6468L)
+#define ROA_TUNCFG_DATA_PUSH_TUNNEL (6469L)
+#define ROA_TUNCFG_DATA_RECIRCULATE (6470L)
+#define ROA_TUNCFG_DATA_RECIRC_BYPASS (6471L)
+#define ROA_TUNCFG_DATA_RECIRC_PORT (6472L)
+#define ROA_TUNCFG_DATA_TUN_IPCS_PRECALC (6473L)
+#define ROA_TUNCFG_DATA_TUN_IPCS_UPD (6474L)
+#define ROA_TUNCFG_DATA_TUN_IPTL_PRECALC (6475L)
+#define ROA_TUNCFG_DATA_TUN_IPTL_UPD (6476L)
+#define ROA_TUNCFG_DATA_TUN_IP_TYPE (6477L)
+#define ROA_TUNCFG_DATA_TUN_LEN (6478L)
+#define ROA_TUNCFG_DATA_TUN_TYPE (6479L)
+#define ROA_TUNCFG_DATA_TUN_VLAN (6480L)
+#define ROA_TUNCFG_DATA_TUN_VXLAN_UDP_LEN_UPD (6481L)
+#define ROA_TUNCFG_DATA_TX_LAG_IX (6482L)
+#define ROA_TUNHDR_CTRL (6483L)
+#define ROA_TUNHDR_CTRL_ADR (6484L)
+#define ROA_TUNHDR_CTRL_CNT (6485L)
+#define ROA_TUNHDR_DATA (6486L)
+#define ROA_TUNHDR_DATA_TUNNEL_HDR (6487L)
+/* RPL */
+#define RPL_EXT_CTRL (6488L)
+#define RPL_EXT_CTRL_ADR (6489L)
+#define RPL_EXT_CTRL_CNT (6490L)
+#define RPL_EXT_DATA (6491L)
+#define RPL_EXT_DATA_RPL_PTR (6492L)
+#define RPL_RCP_CTRL (6493L)
+#define RPL_RCP_CTRL_ADR (6494L)
+#define RPL_RCP_CTRL_CNT (6495L)
+#define RPL_RCP_DATA (6496L)
+#define RPL_RCP_DATA_DYN (6497L)
+#define RPL_RCP_DATA_EXT_PRIO (6498L)
+#define RPL_RCP_DATA_LEN (6499L)
+#define RPL_RCP_DATA_OFS (6500L)
+#define RPL_RCP_DATA_RPL_PTR (6501L)
+#define RPL_RPL_CTRL (6502L)
+#define RPL_RPL_CTRL_ADR (6503L)
+#define RPL_RPL_CTRL_CNT (6504L)
+#define RPL_RPL_DATA (6505L)
+#define RPL_RPL_DATA_VALUE (6506L)
+/* RPP_LR */
+#define RPP_LR_IFR_RCP_CTRL (6507L)
+#define RPP_LR_IFR_RCP_CTRL_ADR (6508L)
+#define RPP_LR_IFR_RCP_CTRL_CNT (6509L)
+#define RPP_LR_IFR_RCP_DATA (6510L)
+#define RPP_LR_IFR_RCP_DATA_EN (6511L)
+#define RPP_LR_IFR_RCP_DATA_MTU (6512L)
+#define RPP_LR_RCP_CTRL (6513L)
+#define RPP_LR_RCP_CTRL_ADR (6514L)
+#define RPP_LR_RCP_CTRL_CNT (6515L)
+#define RPP_LR_RCP_DATA (6516L)
+#define RPP_LR_RCP_DATA_EXP (6517L)
+/* RST7000 */
+#define RST7000_RST (6518L)
+#define RST7000_RST_SYS (6519L)
+/* RST7001 */
+#define RST7001_RST (6520L)
+#define RST7001_RST_SYS (6521L)
+/* RST9500 */
+#define RST9500_CTRL (6598L)
+#define RST9500_CTRL_PTP_MMCM_CLKSEL (6599L)
+#define RST9500_CTRL_TS_CLKSEL (6600L)
+#define RST9500_CTRL_TS_CLKSEL_OVERRIDE (6601L)
+#define RST9500_RST (6602L)
+#define RST9500_RST_DDR3 (6603L)
+#define RST9500_RST_DDR3_IDLY_MMCM (6604L)
+#define RST9500_RST_PERIPH (6605L)
+#define RST9500_RST_PHY10G_QPLL (6606L)
+#define RST9500_RST_PHY3S10G (6607L)
+#define RST9500_RST_PHY3S_MMCM (6608L)
+#define RST9500_RST_PTP (6609L)
+#define RST9500_RST_PTP_MMCM (6610L)
+#define RST9500_RST_RPP (6611L)
+#define RST9500_RST_SDC (6612L)
+#define RST9500_RST_SI5326 (6613L)
+#define RST9500_RST_SYS (6614L)
+#define RST9500_RST_TS (6615L)
+#define RST9500_RST_TS_MMCM (6616L)
+#define RST9500_RST_STAT (6617L)
+#define RST9500_RST_STAT_PCS_RESET_BY_SERDES (6618L)
+#define RST9500_STAT (6619L)
+#define RST9500_STAT_DDR3_IDLY_MMCM_LOCKED (6620L)
+#define RST9500_STAT_DDR3_MMCM_LOCKED (6621L)
+#define RST9500_STAT_DDR3_PLL_LOCKED (6622L)
+#define RST9500_STAT_PHY10G_QPLL_LOCK_0_1 (6623L)
+#define RST9500_STAT_PHY10G_QPLL_LOCK_2_3 (6624L)
+#define RST9500_STAT_PHY3S_MMCM_LOCKED (6625L)
+#define RST9500_STAT_PTP_MMCM_LOCKED (6626L)
+#define RST9500_STAT_SYNCE_MAIN_CLK_LOS (6627L)
+#define RST9500_STAT_SYS_MMCM_LOCKED (6628L)
+#define RST9500_STAT_TS_MMCM_LOCKED (6629L)
+#define RST9500_STICKY (6630L)
+#define RST9500_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6631L)
+#define RST9500_STICKY_DDR3_MMCM_UNLOCKED (6632L)
+#define RST9500_STICKY_DDR3_PLL_UNLOCKED (6633L)
+#define RST9500_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6634L)
+#define RST9500_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6635L)
+#define RST9500_STICKY_PHY3S_MMCM_UNLOCKED (6636L)
+#define RST9500_STICKY_PTP_MMCM_UNLOCKED (6637L)
+#define RST9500_STICKY_TS_MMCM_UNLOCKED (6638L)
+/* RST9501 */
+#define RST9501_CTRL (6639L)
+#define RST9501_CTRL_PTP_MMCM_CLKSEL (6640L)
+#define RST9501_CTRL_TS_CLKSEL (6641L)
+#define RST9501_CTRL_TS_CLKSEL_OVERRIDE (6642L)
+#define RST9501_RST (6643L)
+#define RST9501_RST_DDR3 (6644L)
+#define RST9501_RST_DDR3_IDLY_MMCM (6645L)
+#define RST9501_RST_PERIPH (6646L)
+#define RST9501_RST_PHY10G_QPLL (6647L)
+#define RST9501_RST_PHY3S10G (6648L)
+#define RST9501_RST_PHY3S_MMCM (6649L)
+#define RST9501_RST_PTP (6650L)
+#define RST9501_RST_PTP_MMCM (6651L)
+#define RST9501_RST_RPP (6652L)
+#define RST9501_RST_SDC (6653L)
+#define RST9501_RST_SI5326 (6654L)
+#define RST9501_RST_SYS (6655L)
+#define RST9501_RST_TS (6656L)
+#define RST9501_RST_TS_MMCM (6657L)
+#define RST9501_RST_STAT (6658L)
+#define RST9501_RST_STAT_PCS_RESET_BY_SERDES (6659L)
+#define RST9501_STAT (6660L)
+#define RST9501_STAT_DDR3_IDLY_MMCM_LOCKED (6661L)
+#define RST9501_STAT_DDR3_MMCM_LOCKED (6662L)
+#define RST9501_STAT_DDR3_PLL_LOCKED (6663L)
+#define RST9501_STAT_PHY10G_QPLL_LOCK_0_1 (6664L)
+#define RST9501_STAT_PHY10G_QPLL_LOCK_2_3 (6665L)
+#define RST9501_STAT_PHY3S_MMCM_LOCKED (6666L)
+#define RST9501_STAT_PTP_MMCM_LOCKED (6667L)
+#define RST9501_STAT_SYNCE_MAIN_CLK_LOS (6668L)
+#define RST9501_STAT_SYS_MMCM_LOCKED (6669L)
+#define RST9501_STAT_TS_MMCM_LOCKED (6670L)
+#define RST9501_STICKY (6671L)
+#define RST9501_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6672L)
+#define RST9501_STICKY_DDR3_MMCM_UNLOCKED (6673L)
+#define RST9501_STICKY_DDR3_PLL_UNLOCKED (6674L)
+#define RST9501_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6675L)
+#define RST9501_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6676L)
+#define RST9501_STICKY_PHY3S_MMCM_UNLOCKED (6677L)
+#define RST9501_STICKY_PTP_MMCM_UNLOCKED (6678L)
+#define RST9501_STICKY_TS_MMCM_UNLOCKED (6679L)
+/* RST9502 */
+#define RST9502_CTRL (6680L)
+#define RST9502_CTRL_PTP_MMCM_CLKSEL (6681L)
+#define RST9502_CTRL_TS_CLKSEL (6682L)
+#define RST9502_CTRL_TS_CLKSEL_OVERRIDE (6683L)
+#define RST9502_RST (6684L)
+#define RST9502_RST_DDR3 (6685L)
+#define RST9502_RST_DDR3_IDLY_MMCM (6686L)
+#define RST9502_RST_NSEB (6687L)
+#define RST9502_RST_PERIPH (6688L)
+#define RST9502_RST_PHY10G_QPLL (6689L)
+#define RST9502_RST_PHY3S10G (6690L)
+#define RST9502_RST_PHY3S_MMCM (6691L)
+#define RST9502_RST_PTP (6692L)
+#define RST9502_RST_PTP_MMCM (6693L)
+#define RST9502_RST_RPP (6694L)
+#define RST9502_RST_SDC (6695L)
+#define RST9502_RST_SI5326 (6696L)
+#define RST9502_RST_SYS (6697L)
+#define RST9502_RST_TS (6698L)
+#define RST9502_RST_TS_MMCM (6699L)
+#define RST9502_RST_STAT (6700L)
+#define RST9502_RST_STAT_PCS_RESET_BY_SERDES (6701L)
+#define RST9502_STAT (6702L)
+#define RST9502_STAT_DDR3_IDLY_MMCM_LOCKED (6703L)
+#define RST9502_STAT_DDR3_MMCM_LOCKED (6704L)
+#define RST9502_STAT_DDR3_PLL_LOCKED (6705L)
+#define RST9502_STAT_PHY10G_QPLL_LOCK_0_1 (6706L)
+#define RST9502_STAT_PHY10G_QPLL_LOCK_2_3 (6707L)
+#define RST9502_STAT_PHY3S_MMCM_LOCKED (6708L)
+#define RST9502_STAT_PTP_MMCM_LOCKED (6709L)
+#define RST9502_STAT_SYNCE_MAIN_CLK_LOS (6710L)
+#define RST9502_STAT_SYS_MMCM_LOCKED (6711L)
+#define RST9502_STAT_TS_MMCM_LOCKED (6712L)
+#define RST9502_STICKY (6713L)
+#define RST9502_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6714L)
+#define RST9502_STICKY_DDR3_MMCM_UNLOCKED (6715L)
+#define RST9502_STICKY_DDR3_PLL_UNLOCKED (6716L)
+#define RST9502_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6717L)
+#define RST9502_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6718L)
+#define RST9502_STICKY_PHY3S_MMCM_UNLOCKED (6719L)
+#define RST9502_STICKY_PTP_MMCM_UNLOCKED (6720L)
+#define RST9502_STICKY_TS_MMCM_UNLOCKED (6721L)
+/* RST9503 */
+#define RST9503_CTRL (6722L)
+#define RST9503_CTRL_PTP_MMCM_CLKSEL (6723L)
+#define RST9503_CTRL_TS_CLKSEL (6724L)
+#define RST9503_CTRL_TS_CLKSEL_OVERRIDE (6725L)
+#define RST9503_PORT_CLK_SEL (6726L)
+#define RST9503_PORT_CLK_SEL_PORT0 (6727L)
+#define RST9503_PORT_CLK_SEL_PORT1 (6728L)
+#define RST9503_RST (6729L)
+#define RST9503_RST_DDR3 (6730L)
+#define RST9503_RST_DDR3_IDLY_MMCM (6731L)
+#define RST9503_RST_MAC_RX (6732L)
+#define RST9503_RST_MAC_RX_MMCM (6733L)
+#define RST9503_RST_MAC_TX (6734L)
+#define RST9503_RST_NSEB (6735L)
+#define RST9503_RST_PCS_RX (6736L)
+#define RST9503_RST_PERIPH (6737L)
+#define RST9503_RST_PHY40G (6738L)
+#define RST9503_RST_PTP (6739L)
+#define RST9503_RST_PTP_MMCM (6740L)
+#define RST9503_RST_RPP (6741L)
+#define RST9503_RST_SDC (6742L)
+#define RST9503_RST_SERDES_RX (6743L)
+#define RST9503_RST_SERDES_TX (6744L)
+#define RST9503_RST_SI5326 (6745L)
+#define RST9503_RST_SYS (6746L)
+#define RST9503_RST_TS (6747L)
+#define RST9503_RST_TS_MMCM (6748L)
+#define RST9503_RST_STAT (6749L)
+#define RST9503_RST_STAT_PCS_RESET_BY_SERDES (6750L)
+#define RST9503_STAT (6751L)
+#define RST9503_STAT_DDR3_IDLY_MMCM_LOCKED (6752L)
+#define RST9503_STAT_DDR3_MMCM_LOCKED (6753L)
+#define RST9503_STAT_DDR3_PLL_LOCKED (6754L)
+#define RST9503_STAT_MAC_RX_MMCM_LOCKED (6755L)
+#define RST9503_STAT_PTP_MMCM_LOCKED (6756L)
+#define RST9503_STAT_SYNCE_MAIN_CLK_LOS (6757L)
+#define RST9503_STAT_SYS_MMCM_LOCKED (6758L)
+#define RST9503_STAT_TS_MMCM_LOCKED (6759L)
+#define RST9503_STICKY (6760L)
+#define RST9503_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6761L)
+#define RST9503_STICKY_DDR3_MMCM_UNLOCKED (6762L)
+#define RST9503_STICKY_DDR3_PLL_UNLOCKED (6763L)
+#define RST9503_STICKY_MAC_RX_MMCM_UNLOCKED (6764L)
+#define RST9503_STICKY_PTP_MMCM_UNLOCKED (6765L)
+#define RST9503_STICKY_TS_MMCM_UNLOCKED (6766L)
+/* RST9504 */
+#define RST9504_CTRL (6767L)
+#define RST9504_CTRL_PTP_MMCM_CLKSEL (6768L)
+#define RST9504_CTRL_TS_CLKSEL (6769L)
+#define RST9504_CTRL_TS_CLKSEL_OVERRIDE (6770L)
+#define RST9504_RST (6771L)
+#define RST9504_RST_DDR3 (6772L)
+#define RST9504_RST_DDR3_IDLY_MMCM (6773L)
+#define RST9504_RST_MAC_RX (6774L)
+#define RST9504_RST_MAC_RX_MMCM (6775L)
+#define RST9504_RST_MAC_TX (6776L)
+#define RST9504_RST_NSEB (6777L)
+#define RST9504_RST_PCS_RX (6778L)
+#define RST9504_RST_PERIPH (6779L)
+#define RST9504_RST_PHY100G (6780L)
+#define RST9504_RST_PTP (6781L)
+#define RST9504_RST_PTP_MMCM (6782L)
+#define RST9504_RST_RPP (6783L)
+#define RST9504_RST_SDC (6784L)
+#define RST9504_RST_SERDES_RX (6785L)
+#define RST9504_RST_SERDES_TX (6786L)
+#define RST9504_RST_SI5326 (6787L)
+#define RST9504_RST_SYS (6788L)
+#define RST9504_RST_TS (6789L)
+#define RST9504_RST_TS_MMCM (6790L)
+#define RST9504_RST_STAT (6791L)
+#define RST9504_RST_STAT_PCS_RESET_BY_SERDES (6792L)
+#define RST9504_STAT (6793L)
+#define RST9504_STAT_DDR3_IDLY_MMCM_LOCKED (6794L)
+#define RST9504_STAT_DDR3_MMCM_LOCKED (6795L)
+#define RST9504_STAT_DDR3_PLL_LOCKED (6796L)
+#define RST9504_STAT_MAC_RX_MMCM_LOCKED (6797L)
+#define RST9504_STAT_PTP_MMCM_LOCKED (6798L)
+#define RST9504_STAT_SYNCE_MAIN_CLK_LOS (6799L)
+#define RST9504_STAT_SYS_MMCM_LOCKED (6800L)
+#define RST9504_STAT_TS_MMCM_LOCKED (6801L)
+#define RST9504_STICKY (6802L)
+#define RST9504_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6803L)
+#define RST9504_STICKY_DDR3_MMCM_UNLOCKED (6804L)
+#define RST9504_STICKY_DDR3_PLL_UNLOCKED (6805L)
+#define RST9504_STICKY_MAC_RX_MMCM_UNLOCKED (6806L)
+#define RST9504_STICKY_PTP_MMCM_UNLOCKED (6807L)
+#define RST9504_STICKY_TS_MMCM_UNLOCKED (6808L)
+/* RST9505 */
+#define RST9505_CTRL (6809L)
+#define RST9505_CTRL_PTP_MMCM_CLKSEL (6810L)
+#define RST9505_CTRL_TS_CLKSEL (6811L)
+#define RST9505_CTRL_TS_CLKSEL_OVERRIDE (6812L)
+#define RST9505_RST (6813L)
+#define RST9505_RST_DDR3 (6814L)
+#define RST9505_RST_DDR3_IDLY_MMCM (6815L)
+#define RST9505_RST_MAC_RX (6816L)
+#define RST9505_RST_MAC_RX_MMCM (6817L)
+#define RST9505_RST_MAC_TX (6818L)
+#define RST9505_RST_NSEB (6819L)
+#define RST9505_RST_PCS_RX (6820L)
+#define RST9505_RST_PERIPH (6821L)
+#define RST9505_RST_PHY100G (6822L)
+#define RST9505_RST_PTP (6823L)
+#define RST9505_RST_PTP_MMCM (6824L)
+#define RST9505_RST_RPP (6825L)
+#define RST9505_RST_SDC (6826L)
+#define RST9505_RST_SERDES_RX (6827L)
+#define RST9505_RST_SERDES_TX (6828L)
+#define RST9505_RST_SI5326 (6829L)
+#define RST9505_RST_SYS (6830L)
+#define RST9505_RST_TS (6831L)
+#define RST9505_RST_TS_MMCM (6832L)
+#define RST9505_RST_STAT (6833L)
+#define RST9505_RST_STAT_PCS_RESET_BY_SERDES (6834L)
+#define RST9505_STAT (6835L)
+#define RST9505_STAT_DDR3_IDLY_MMCM_LOCKED (6836L)
+#define RST9505_STAT_DDR3_MMCM_LOCKED (6837L)
+#define RST9505_STAT_DDR3_PLL_LOCKED (6838L)
+#define RST9505_STAT_MAC_RX_MMCM_LOCKED (6839L)
+#define RST9505_STAT_PTP_MMCM_LOCKED (6840L)
+#define RST9505_STAT_SYNCE_MAIN_CLK_LOS (6841L)
+#define RST9505_STAT_SYS_MMCM_LOCKED (6842L)
+#define RST9505_STAT_TS_MMCM_LOCKED (6843L)
+#define RST9505_STICKY (6844L)
+#define RST9505_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6845L)
+#define RST9505_STICKY_DDR3_MMCM_UNLOCKED (6846L)
+#define RST9505_STICKY_DDR3_PLL_UNLOCKED (6847L)
+#define RST9505_STICKY_MAC_RX_MMCM_UNLOCKED (6848L)
+#define RST9505_STICKY_PTP_MMCM_UNLOCKED (6849L)
+#define RST9505_STICKY_TS_MMCM_UNLOCKED (6850L)
+/* RST9506 */
+/* RST9507 */
+/* RST9508 */
+#define RST9508_CTRL (6851L)
+#define RST9508_CTRL_PTP_MMCM_CLKSEL (6852L)
+#define RST9508_CTRL_TS_CLKSEL (6853L)
+#define RST9508_CTRL_TS_CLKSEL_OVERRIDE (6854L)
+#define RST9508_CTRL_TS_CLKSEL_REF (6855L)
+#define RST9508_POWER (6856L)
+#define RST9508_POWER_PU_NSEB (6857L)
+#define RST9508_POWER_PU_PHY (6858L)
+#define RST9508_RST (6859L)
+#define RST9508_RST_CORE_MMCM (6860L)
+#define RST9508_RST_DDR4 (6861L)
+#define RST9508_RST_MAC_RX (6862L)
+#define RST9508_RST_PERIPH (6863L)
+#define RST9508_RST_PHY (6864L)
+#define RST9508_RST_PTP (6865L)
+#define RST9508_RST_PTP_MMCM (6866L)
+#define RST9508_RST_RPP (6867L)
+#define RST9508_RST_SDC (6868L)
+#define RST9508_RST_SYS (6869L)
+#define RST9508_RST_SYS_MMCM (6870L)
+#define RST9508_RST_TMC (6871L)
+#define RST9508_RST_TS (6872L)
+#define RST9508_RST_TSM_REF_MMCM (6873L)
+#define RST9508_RST_TS_MMCM (6874L)
+#define RST9508_STAT (6875L)
+#define RST9508_STAT_CORE_MMCM_LOCKED (6876L)
+#define RST9508_STAT_DDR4_MMCM_LOCKED (6877L)
+#define RST9508_STAT_DDR4_PLL_LOCKED (6878L)
+#define RST9508_STAT_PCI_SYS_MMCM_LOCKED (6879L)
+#define RST9508_STAT_PTP_MMCM_LOCKED (6880L)
+#define RST9508_STAT_SYS_MMCM_LOCKED (6881L)
+#define RST9508_STAT_TSM_REF_MMCM_LOCKED (6882L)
+#define RST9508_STAT_TS_MMCM_LOCKED (6883L)
+#define RST9508_STICKY (6884L)
+#define RST9508_STICKY_CORE_MMCM_UNLOCKED (6885L)
+#define RST9508_STICKY_DDR4_MMCM_UNLOCKED (6886L)
+#define RST9508_STICKY_DDR4_PLL_UNLOCKED (6887L)
+#define RST9508_STICKY_PCI_SYS_MMCM_UNLOCKED (6888L)
+#define RST9508_STICKY_PTP_MMCM_UNLOCKED (6889L)
+#define RST9508_STICKY_SYS_MMCM_UNLOCKED (6890L)
+#define RST9508_STICKY_TSM_REF_MMCM_UNLOCKED (6891L)
+#define RST9508_STICKY_TS_MMCM_UNLOCKED (6892L)
+/* RST9509 */
+/* RST9510 */
+/* RST9512 */
+#define RST9512_CTRL (6893L)
+#define RST9512_CTRL_PTP_MMCM_CLKSEL (6894L)
+#define RST9512_CTRL_TS_CLKSEL (6895L)
+#define RST9512_CTRL_TS_CLKSEL_OVERRIDE (6896L)
+#define RST9512_CTRL_TS_CLKSEL_REF (6897L)
+#define RST9512_POWER (6898L)
+#define RST9512_POWER_PU_NSEB (6899L)
+#define RST9512_POWER_PU_PHY (6900L)
+#define RST9512_RST (6901L)
+#define RST9512_RST_CORE_MMCM (6902L)
+#define RST9512_RST_DDR4 (6903L)
+#define RST9512_RST_MAC_RX (6904L)
+#define RST9512_RST_MAC_TX (6905L)
+#define RST9512_RST_PCS_RX (6906L)
+#define RST9512_RST_PERIPH (6907L)
+#define RST9512_RST_PHY (6908L)
+#define RST9512_RST_PTP (6909L)
+#define RST9512_RST_PTP_MMCM (6910L)
+#define RST9512_RST_RPP (6911L)
+#define RST9512_RST_SDC (6912L)
+#define RST9512_RST_SERDES_RX (6913L)
+#define RST9512_RST_SERDES_RX_DATAPATH (6914L)
+#define RST9512_RST_SERDES_TX (6915L)
+#define RST9512_RST_SYS (6916L)
+#define RST9512_RST_SYS_MMCM (6917L)
+#define RST9512_RST_TS (6918L)
+#define RST9512_RST_TSM_REF_MMCM (6919L)
+#define RST9512_RST_TS_MMCM (6920L)
+#define RST9512_STAT (6921L)
+#define RST9512_STAT_CORE_MMCM_LOCKED (6922L)
+#define RST9512_STAT_DDR4_MMCM_LOCKED (6923L)
+#define RST9512_STAT_DDR4_PLL_LOCKED (6924L)
+#define RST9512_STAT_PCI_SYS_MMCM_LOCKED (6925L)
+#define RST9512_STAT_PTP_MMCM_LOCKED (6926L)
+#define RST9512_STAT_SYS_MMCM_LOCKED (6927L)
+#define RST9512_STAT_TSM_REF_MMCM_LOCKED (6928L)
+#define RST9512_STAT_TS_MMCM_LOCKED (6929L)
+#define RST9512_STICKY (6930L)
+#define RST9512_STICKY_CORE_MMCM_UNLOCKED (6931L)
+#define RST9512_STICKY_DDR4_MMCM_UNLOCKED (6932L)
+#define RST9512_STICKY_DDR4_PLL_UNLOCKED (6933L)
+#define RST9512_STICKY_PCI_SYS_MMCM_UNLOCKED (6934L)
+#define RST9512_STICKY_PTP_MMCM_UNLOCKED (6935L)
+#define RST9512_STICKY_SYS_MMCM_UNLOCKED (6936L)
+#define RST9512_STICKY_TSM_REF_MMCM_UNLOCKED (6937L)
+#define RST9512_STICKY_TS_MMCM_UNLOCKED (6938L)
+/* RST9513 */
+/* RST9515 */
+#define RST9515_CTRL (6939L)
+#define RST9515_CTRL_PTP_MMCM_CLKSEL (6940L)
+#define RST9515_CTRL_TS_CLKSEL (6941L)
+#define RST9515_CTRL_TS_CLKSEL_OVERRIDE (6942L)
+#define RST9515_CTRL_TS_CLKSEL_REF (6943L)
+#define RST9515_POWER (6944L)
+#define RST9515_POWER_PU_NSEB (6945L)
+#define RST9515_POWER_PU_PHY (6946L)
+#define RST9515_RST (6947L)
+#define RST9515_RST_CORE_MMCM (6948L)
+#define RST9515_RST_DDR4 (6949L)
+#define RST9515_RST_MAC_RX (6950L)
+#define RST9515_RST_PERIPH (6951L)
+#define RST9515_RST_PHY (6952L)
+#define RST9515_RST_PTP (6953L)
+#define RST9515_RST_PTP_MMCM (6954L)
+#define RST9515_RST_RPP (6955L)
+#define RST9515_RST_SDC (6956L)
+#define RST9515_RST_SYS (6957L)
+#define RST9515_RST_SYS_MMCM (6958L)
+#define RST9515_RST_TMC (6959L)
+#define RST9515_RST_TS (6960L)
+#define RST9515_RST_TSM_REF_MMCM (6961L)
+#define RST9515_RST_TS_MMCM (6962L)
+#define RST9515_STAT (6963L)
+#define RST9515_STAT_CORE_MMCM_LOCKED (6964L)
+#define RST9515_STAT_DDR4_MMCM_LOCKED (6965L)
+#define RST9515_STAT_DDR4_PLL_LOCKED (6966L)
+#define RST9515_STAT_PCI_SYS_MMCM_LOCKED (6967L)
+#define RST9515_STAT_PTP_MMCM_LOCKED (6968L)
+#define RST9515_STAT_SYS_MMCM_LOCKED (6969L)
+#define RST9515_STAT_TSM_REF_MMCM_LOCKED (6970L)
+#define RST9515_STAT_TS_MMCM_LOCKED (6971L)
+#define RST9515_STICKY (6972L)
+#define RST9515_STICKY_CORE_MMCM_UNLOCKED (6973L)
+#define RST9515_STICKY_DDR4_MMCM_UNLOCKED (6974L)
+#define RST9515_STICKY_DDR4_PLL_UNLOCKED (6975L)
+#define RST9515_STICKY_PCI_SYS_MMCM_UNLOCKED (6976L)
+#define RST9515_STICKY_PTP_MMCM_UNLOCKED (6977L)
+#define RST9515_STICKY_SYS_MMCM_UNLOCKED (6978L)
+#define RST9515_STICKY_TSM_REF_MMCM_UNLOCKED (6979L)
+#define RST9515_STICKY_TS_MMCM_UNLOCKED (6980L)
+/* RST9516 */
+#define RST9516_CTRL (6981L)
+#define RST9516_CTRL_PTP_MMCM_CLKSEL (6982L)
+#define RST9516_CTRL_TS_CLKSEL (6983L)
+#define RST9516_CTRL_TS_CLKSEL_OVERRIDE (6984L)
+#define RST9516_CTRL_TS_CLKSEL_REF (6985L)
+#define RST9516_POWER (6986L)
+#define RST9516_POWER_PU_NSEB (6987L)
+#define RST9516_POWER_PU_PHY (6988L)
+#define RST9516_RST (6989L)
+#define RST9516_RST_CORE_MMCM (6990L)
+#define RST9516_RST_DDR4 (6991L)
+#define RST9516_RST_MAC_RX (6992L)
+#define RST9516_RST_PCS_RX (6993L)
+#define RST9516_RST_PERIPH (6994L)
+#define RST9516_RST_PHY (6995L)
+#define RST9516_RST_PTP (6996L)
+#define RST9516_RST_PTP_MMCM (6997L)
+#define RST9516_RST_RPP (6998L)
+#define RST9516_RST_SDC (6999L)
+#define RST9516_RST_SERDES_RX (7000L)
+#define RST9516_RST_SERDES_TX (7001L)
+#define RST9516_RST_SYS (7002L)
+#define RST9516_RST_SYS_MMCM (7003L)
+#define RST9516_RST_TMC (7004L)
+#define RST9516_RST_TS (7005L)
+#define RST9516_RST_TSM_REF_MMCM (7006L)
+#define RST9516_RST_TS_MMCM (7007L)
+#define RST9516_STAT (7008L)
+#define RST9516_STAT_CORE_MMCM_LOCKED (7009L)
+#define RST9516_STAT_DDR4_MMCM_LOCKED (7010L)
+#define RST9516_STAT_DDR4_PLL_LOCKED (7011L)
+#define RST9516_STAT_PCI_SYS_MMCM_LOCKED (7012L)
+#define RST9516_STAT_PTP_MMCM_LOCKED (7013L)
+#define RST9516_STAT_SYS_MMCM_LOCKED (7014L)
+#define RST9516_STAT_TSM_REF_MMCM_LOCKED (7015L)
+#define RST9516_STAT_TS_MMCM_LOCKED (7016L)
+#define RST9516_STICKY (7017L)
+#define RST9516_STICKY_CORE_MMCM_UNLOCKED (7018L)
+#define RST9516_STICKY_DDR4_MMCM_UNLOCKED (7019L)
+#define RST9516_STICKY_DDR4_PLL_UNLOCKED (7020L)
+#define RST9516_STICKY_PCI_SYS_MMCM_UNLOCKED (7021L)
+#define RST9516_STICKY_PTP_MMCM_UNLOCKED (7022L)
+#define RST9516_STICKY_SYS_MMCM_UNLOCKED (7023L)
+#define RST9516_STICKY_TSM_REF_MMCM_UNLOCKED (7024L)
+#define RST9516_STICKY_TS_MMCM_UNLOCKED (7025L)
+/* RST9517 */
+#define RST9517_CTRL (7026L)
+#define RST9517_CTRL_PTP_MMCM_CLKSEL (7027L)
+#define RST9517_CTRL_TS_CLKSEL (7028L)
+#define RST9517_CTRL_TS_CLKSEL_OVERRIDE (7029L)
+#define RST9517_RST (7030L)
+#define RST9517_RST_DDR3 (7031L)
+#define RST9517_RST_DDR3_IDLY_MMCM (7032L)
+#define RST9517_RST_NSEB (7033L)
+#define RST9517_RST_PERIPH (7034L)
+#define RST9517_RST_PHY10G_QPLL (7035L)
+#define RST9517_RST_PHY3S10G (7036L)
+#define RST9517_RST_PHY3S_MMCM (7037L)
+#define RST9517_RST_PTP (7038L)
+#define RST9517_RST_PTP_MMCM (7039L)
+#define RST9517_RST_RPP (7040L)
+#define RST9517_RST_SDC (7041L)
+#define RST9517_RST_SI5326 (7042L)
+#define RST9517_RST_SYS (7043L)
+#define RST9517_RST_TS (7044L)
+#define RST9517_RST_TS_MMCM (7045L)
+#define RST9517_RST_STAT (7046L)
+#define RST9517_RST_STAT_PCS_RESET_BY_SERDES (7047L)
+#define RST9517_STAT (7048L)
+#define RST9517_STAT_DDR3_IDLY_MMCM_LOCKED (7049L)
+#define RST9517_STAT_DDR3_MMCM_LOCKED (7050L)
+#define RST9517_STAT_DDR3_PLL_LOCKED (7051L)
+#define RST9517_STAT_PHY10G_QPLL_LOCK_0_1 (7052L)
+#define RST9517_STAT_PHY10G_QPLL_LOCK_2_3 (7053L)
+#define RST9517_STAT_PHY3S_MMCM_LOCKED (7054L)
+#define RST9517_STAT_PTP_MMCM_LOCKED (7055L)
+#define RST9517_STAT_SYNCE_MAIN_CLK_LOS (7056L)
+#define RST9517_STAT_SYS_MMCM_LOCKED (7057L)
+#define RST9517_STAT_TS_MMCM_LOCKED (7058L)
+#define RST9517_STICKY (7059L)
+#define RST9517_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7060L)
+#define RST9517_STICKY_DDR3_MMCM_UNLOCKED (7061L)
+#define RST9517_STICKY_DDR3_PLL_UNLOCKED (7062L)
+#define RST9517_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7063L)
+#define RST9517_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7064L)
+#define RST9517_STICKY_PHY3S_MMCM_UNLOCKED (7065L)
+#define RST9517_STICKY_PTP_MMCM_UNLOCKED (7066L)
+#define RST9517_STICKY_TS_MMCM_UNLOCKED (7067L)
+/* RST9519 */
+#define RST9519_CTRL (7068L)
+#define RST9519_CTRL_PTP_MMCM_CLKSEL (7069L)
+#define RST9519_CTRL_TS_CLKSEL (7070L)
+#define RST9519_CTRL_TS_CLKSEL_OVERRIDE (7071L)
+#define RST9519_RST (7072L)
+#define RST9519_RST_DDR3 (7073L)
+#define RST9519_RST_DDR3_IDLY_MMCM (7074L)
+#define RST9519_RST_PERIPH (7075L)
+#define RST9519_RST_PHY10G (7076L)
+#define RST9519_RST_PHY10G_QPLL (7077L)
+#define RST9519_RST_PTP (7078L)
+#define RST9519_RST_PTP_MMCM (7079L)
+#define RST9519_RST_RPP (7080L)
+#define RST9519_RST_SDC (7081L)
+#define RST9519_RST_SI5326 (7082L)
+#define RST9519_RST_SYS (7083L)
+#define RST9519_RST_TS (7084L)
+#define RST9519_RST_TS_MMCM (7085L)
+#define RST9519_RST_STAT (7086L)
+#define RST9519_RST_STAT_PCS_RESET_BY_SERDES (7087L)
+#define RST9519_STAT (7088L)
+#define RST9519_STAT_DDR3_IDLY_MMCM_LOCKED (7089L)
+#define RST9519_STAT_DDR3_MMCM_LOCKED (7090L)
+#define RST9519_STAT_DDR3_PLL_LOCKED (7091L)
+#define RST9519_STAT_PHY10G_QPLL_LOCK (7092L)
+#define RST9519_STAT_PTP_MMCM_LOCKED (7093L)
+#define RST9519_STAT_SYNCE_MAIN_CLK_LOS (7094L)
+#define RST9519_STAT_SYS_MMCM_LOCKED (7095L)
+#define RST9519_STAT_TS_MMCM_LOCKED (7096L)
+#define RST9519_STICKY (7097L)
+#define RST9519_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7098L)
+#define RST9519_STICKY_DDR3_MMCM_UNLOCKED (7099L)
+#define RST9519_STICKY_DDR3_PLL_UNLOCKED (7100L)
+#define RST9519_STICKY_PHY10G_QPLL_UNLOCK (7101L)
+#define RST9519_STICKY_PTP_MMCM_UNLOCKED (7102L)
+#define RST9519_STICKY_TS_MMCM_UNLOCKED (7103L)
+/* RST9520 */
+/* RST9521 */
+#define RST9521_CTRL (7104L)
+#define RST9521_CTRL_PTP_MMCM_CLKSEL (7105L)
+#define RST9521_CTRL_TS_CLKSEL (7106L)
+#define RST9521_CTRL_TS_CLKSEL_OVERRIDE (7107L)
+#define RST9521_POWER (7108L)
+#define RST9521_POWER_PU_NSEB (7109L)
+#define RST9521_POWER_PU_PHY (7110L)
+#define RST9521_RST (7111L)
+#define RST9521_RST_CORE_MMCM (7112L)
+#define RST9521_RST_DDR4 (7113L)
+#define RST9521_RST_MAC_RX (7114L)
+#define RST9521_RST_PERIPH (7115L)
+#define RST9521_RST_PHY (7116L)
+#define RST9521_RST_PTP (7117L)
+#define RST9521_RST_PTP_MMCM (7118L)
+#define RST9521_RST_RPP (7119L)
+#define RST9521_RST_SDC (7120L)
+#define RST9521_RST_SYS (7121L)
+#define RST9521_RST_SYS_MMCM (7122L)
+#define RST9521_RST_TMC (7123L)
+#define RST9521_RST_TS (7124L)
+#define RST9521_RST_TSM_REF_MMCM (7125L)
+#define RST9521_RST_TS_MMCM (7126L)
+#define RST9521_STAT (7127L)
+#define RST9521_STAT_CORE_MMCM_LOCKED (7128L)
+#define RST9521_STAT_DDR4_MMCM_LOCKED (7129L)
+#define RST9521_STAT_DDR4_PLL_LOCKED (7130L)
+#define RST9521_STAT_PTP_MMCM_LOCKED (7131L)
+#define RST9521_STAT_SYS_MMCM_LOCKED (7132L)
+#define RST9521_STAT_TS_MMCM_LOCKED (7133L)
+#define RST9521_STICKY (7134L)
+#define RST9521_STICKY_CORE_MMCM_UNLOCKED (7135L)
+#define RST9521_STICKY_DDR4_MMCM_UNLOCKED (7136L)
+#define RST9521_STICKY_DDR4_PLL_UNLOCKED (7137L)
+#define RST9521_STICKY_PTP_MMCM_UNLOCKED (7138L)
+#define RST9521_STICKY_SYS_MMCM_UNLOCKED (7139L)
+#define RST9521_STICKY_TS_MMCM_UNLOCKED (7140L)
+/* RST9522 */
+#define RST9522_CTRL (7141L)
+#define RST9522_CTRL_PTP_MMCM_CLKSEL (7142L)
+#define RST9522_CTRL_TS_CLKSEL (7143L)
+#define RST9522_CTRL_TS_CLKSEL_OVERRIDE (7144L)
+#define RST9522_CTRL_TS_CLKSEL_REF (7145L)
+#define RST9522_POWER (7146L)
+#define RST9522_POWER_PU_NSEB (7147L)
+#define RST9522_POWER_PU_PHY (7148L)
+#define RST9522_RST (7149L)
+#define RST9522_RST_CORE_MMCM (7150L)
+#define RST9522_RST_DDR4 (7151L)
+#define RST9522_RST_PERIPH (7152L)
+#define RST9522_RST_PHY10G (7153L)
+#define RST9522_RST_PHY10G_QPLL (7154L)
+#define RST9522_RST_PTP (7155L)
+#define RST9522_RST_PTP_MMCM (7156L)
+#define RST9522_RST_RPP (7157L)
+#define RST9522_RST_SDC (7158L)
+#define RST9522_RST_SYS (7159L)
+#define RST9522_RST_SYS_MMCM (7160L)
+#define RST9522_RST_TS (7161L)
+#define RST9522_RST_TSM_REF_MMCM (7162L)
+#define RST9522_RST_TS_MMCM (7163L)
+#define RST9522_STAT (7164L)
+#define RST9522_STAT_CORE_MMCM_LOCKED (7165L)
+#define RST9522_STAT_DDR4_MMCM_LOCKED (7166L)
+#define RST9522_STAT_DDR4_PLL_LOCKED (7167L)
+#define RST9522_STAT_PCI_SYS_MMCM_LOCKED (7168L)
+#define RST9522_STAT_PHY10G_QPLL_LOCKED (7169L)
+#define RST9522_STAT_PTP_MMCM_LOCKED (7170L)
+#define RST9522_STAT_SYS_MMCM_LOCKED (7171L)
+#define RST9522_STAT_TSM_REF_MMCM_LOCKED (7172L)
+#define RST9522_STAT_TS_MMCM_LOCKED (7173L)
+#define RST9522_STICKY (7174L)
+#define RST9522_STICKY_CORE_MMCM_UNLOCKED (7175L)
+#define RST9522_STICKY_DDR4_MMCM_UNLOCKED (7176L)
+#define RST9522_STICKY_DDR4_PLL_UNLOCKED (7177L)
+#define RST9522_STICKY_PCI_SYS_MMCM_UNLOCKED (7178L)
+#define RST9522_STICKY_PHY10G_QPLL_UNLOCKED (7179L)
+#define RST9522_STICKY_PTP_MMCM_UNLOCKED (7180L)
+#define RST9522_STICKY_SYS_MMCM_UNLOCKED (7181L)
+#define RST9522_STICKY_TSM_REF_MMCM_UNLOCKED (7182L)
+#define RST9522_STICKY_TS_MMCM_UNLOCKED (7183L)
+/* RST9523 */
+/* RST9524 */
+#define RST9524_CTRL (7184L)
+#define RST9524_CTRL_PTP_MMCM_CLKSEL (7185L)
+#define RST9524_CTRL_TS_CLKSEL (7186L)
+#define RST9524_CTRL_TS_CLKSEL_OVERRIDE (7187L)
+#define RST9524_POWER (7188L)
+#define RST9524_POWER_PU_NSEB (7189L)
+#define RST9524_POWER_PU_PHY (7190L)
+#define RST9524_RST (7191L)
+#define RST9524_RST_CORE_MMCM (7192L)
+#define RST9524_RST_DDR4 (7193L)
+#define RST9524_RST_MAC_RX (7194L)
+#define RST9524_RST_PERIPH (7195L)
+#define RST9524_RST_PHY (7196L)
+#define RST9524_RST_PTP (7197L)
+#define RST9524_RST_PTP_MMCM (7198L)
+#define RST9524_RST_RPP (7199L)
+#define RST9524_RST_SDC (7200L)
+#define RST9524_RST_SYS (7201L)
+#define RST9524_RST_SYS_MMCM (7202L)
+#define RST9524_RST_TMC (7203L)
+#define RST9524_RST_TS (7204L)
+#define RST9524_RST_TS_MMCM (7205L)
+#define RST9524_STAT (7206L)
+#define RST9524_STAT_CORE_MMCM_LOCKED (7207L)
+#define RST9524_STAT_DDR4_MMCM_LOCKED (7208L)
+#define RST9524_STAT_DDR4_PLL_LOCKED (7209L)
+#define RST9524_STAT_PTP_MMCM_LOCKED (7210L)
+#define RST9524_STAT_SYS_MMCM_LOCKED (7211L)
+#define RST9524_STAT_TS_MMCM_LOCKED (7212L)
+#define RST9524_STICKY (7213L)
+#define RST9524_STICKY_CORE_MMCM_UNLOCKED (7214L)
+#define RST9524_STICKY_DDR4_MMCM_UNLOCKED (7215L)
+#define RST9524_STICKY_DDR4_PLL_UNLOCKED (7216L)
+#define RST9524_STICKY_PTP_MMCM_UNLOCKED (7217L)
+#define RST9524_STICKY_SYS_MMCM_UNLOCKED (7218L)
+#define RST9524_STICKY_TS_MMCM_UNLOCKED (7219L)
+/* RST9525 */
+#define RST9525_CTRL (7220L)
+#define RST9525_CTRL_PTP_MMCM_CLKSEL (7221L)
+#define RST9525_CTRL_TS_CLKSEL (7222L)
+#define RST9525_CTRL_TS_CLKSEL_OVERRIDE (7223L)
+#define RST9525_CTRL_TS_CLKSEL_REF (7224L)
+#define RST9525_POWER (7225L)
+#define RST9525_POWER_PU_NSEB (7226L)
+#define RST9525_POWER_PU_PHY (7227L)
+#define RST9525_RST (7228L)
+#define RST9525_RST_CORE_MMCM (7229L)
+#define RST9525_RST_DDR4 (7230L)
+#define RST9525_RST_MAC_RX (7231L)
+#define RST9525_RST_MAC_TX (7232L)
+#define RST9525_RST_PCS_RX (7233L)
+#define RST9525_RST_PERIPH (7234L)
+#define RST9525_RST_PHY (7235L)
+#define RST9525_RST_PTP (7236L)
+#define RST9525_RST_PTP_MMCM (7237L)
+#define RST9525_RST_RPP (7238L)
+#define RST9525_RST_SDC (7239L)
+#define RST9525_RST_SERDES_RX (7240L)
+#define RST9525_RST_SERDES_RX_DATAPATH (7241L)
+#define RST9525_RST_SERDES_TX (7242L)
+#define RST9525_RST_SYS (7243L)
+#define RST9525_RST_SYS_MMCM (7244L)
+#define RST9525_RST_TS (7245L)
+#define RST9525_RST_TSM_REF_MMCM (7246L)
+#define RST9525_RST_TS_MMCM (7247L)
+#define RST9525_STAT (7248L)
+#define RST9525_STAT_CORE_MMCM_LOCKED (7249L)
+#define RST9525_STAT_DDR4_MMCM_LOCKED (7250L)
+#define RST9525_STAT_DDR4_PLL_LOCKED (7251L)
+#define RST9525_STAT_PCI_SYS_MMCM_LOCKED (7252L)
+#define RST9525_STAT_PTP_MMCM_LOCKED (7253L)
+#define RST9525_STAT_SYS_MMCM_LOCKED (7254L)
+#define RST9525_STAT_TSM_REF_MMCM_LOCKED (7255L)
+#define RST9525_STAT_TS_MMCM_LOCKED (7256L)
+#define RST9525_STICKY (7257L)
+#define RST9525_STICKY_CORE_MMCM_UNLOCKED (7258L)
+#define RST9525_STICKY_DDR4_MMCM_UNLOCKED (7259L)
+#define RST9525_STICKY_DDR4_PLL_UNLOCKED (7260L)
+#define RST9525_STICKY_PCI_SYS_MMCM_UNLOCKED (7261L)
+#define RST9525_STICKY_PTP_MMCM_UNLOCKED (7262L)
+#define RST9525_STICKY_SYS_MMCM_UNLOCKED (7263L)
+#define RST9525_STICKY_TSM_REF_MMCM_UNLOCKED (7264L)
+#define RST9525_STICKY_TS_MMCM_UNLOCKED (7265L)
+/* RST9526 */
+#define RST9526_CTRL (7266L)
+#define RST9526_CTRL_PTP_MMCM_CLKSEL (7267L)
+#define RST9526_CTRL_TS_CLKSEL (7268L)
+#define RST9526_CTRL_TS_CLKSEL_OVERRIDE (7269L)
+#define RST9526_POWER (7270L)
+#define RST9526_POWER_PU_NSEB (7271L)
+#define RST9526_POWER_PU_PHY (7272L)
+#define RST9526_RST (7273L)
+#define RST9526_RST_CORE_MMCM (7274L)
+#define RST9526_RST_DDR4 (7275L)
+#define RST9526_RST_MAC_RX (7276L)
+#define RST9526_RST_MAC_TX (7277L)
+#define RST9526_RST_PCS_RX (7278L)
+#define RST9526_RST_PERIPH (7279L)
+#define RST9526_RST_PHY (7280L)
+#define RST9526_RST_PTP (7281L)
+#define RST9526_RST_PTP_MMCM (7282L)
+#define RST9526_RST_RPP (7283L)
+#define RST9526_RST_SDC (7284L)
+#define RST9526_RST_SERDES_RX (7285L)
+#define RST9526_RST_SERDES_RX_DATAPATH (7286L)
+#define RST9526_RST_SERDES_TX (7287L)
+#define RST9526_RST_SYS (7288L)
+#define RST9526_RST_SYS_MMCM (7289L)
+#define RST9526_RST_TMC (7290L)
+#define RST9526_RST_TS (7291L)
+#define RST9526_RST_TS_MMCM (7292L)
+#define RST9526_STAT (7293L)
+#define RST9526_STAT_CORE_MMCM_LOCKED (7294L)
+#define RST9526_STAT_DDR4_MMCM_LOCKED (7295L)
+#define RST9526_STAT_DDR4_PLL_LOCKED (7296L)
+#define RST9526_STAT_PTP_MMCM_LOCKED (7297L)
+#define RST9526_STAT_SYS_MMCM_LOCKED (7298L)
+#define RST9526_STAT_TS_MMCM_LOCKED (7299L)
+#define RST9526_STICKY (7300L)
+#define RST9526_STICKY_CORE_MMCM_UNLOCKED (7301L)
+#define RST9526_STICKY_DDR4_MMCM_UNLOCKED (7302L)
+#define RST9526_STICKY_DDR4_PLL_UNLOCKED (7303L)
+#define RST9526_STICKY_PTP_MMCM_UNLOCKED (7304L)
+#define RST9526_STICKY_SYS_MMCM_UNLOCKED (7305L)
+#define RST9526_STICKY_TS_MMCM_UNLOCKED (7306L)
+/* RST9527 */
+#define RST9527_CTRL (7307L)
+#define RST9527_CTRL_PTP_MMCM_CLKSEL (7308L)
+#define RST9527_CTRL_TS_CLKSEL (7309L)
+#define RST9527_CTRL_TS_CLKSEL_OVERRIDE (7310L)
+#define RST9527_POWER (7311L)
+#define RST9527_POWER_PU_NSEB (7312L)
+#define RST9527_POWER_PU_PHY (7313L)
+#define RST9527_RST (7314L)
+#define RST9527_RST_CORE_MMCM (7315L)
+#define RST9527_RST_DDR4 (7316L)
+#define RST9527_RST_MAC_RX (7317L)
+#define RST9527_RST_MAC_TX (7318L)
+#define RST9527_RST_PCS_RX (7319L)
+#define RST9527_RST_PERIPH (7320L)
+#define RST9527_RST_PHY (7321L)
+#define RST9527_RST_PTP (7322L)
+#define RST9527_RST_PTP_MMCM (7323L)
+#define RST9527_RST_RPP (7324L)
+#define RST9527_RST_SDC (7325L)
+#define RST9527_RST_SERDES_RX (7326L)
+#define RST9527_RST_SERDES_RX_DATAPATH (7327L)
+#define RST9527_RST_SERDES_TX (7328L)
+#define RST9527_RST_SYS (7329L)
+#define RST9527_RST_SYS_MMCM (7330L)
+#define RST9527_RST_TMC (7331L)
+#define RST9527_RST_TS (7332L)
+#define RST9527_RST_TS_MMCM (7333L)
+#define RST9527_STAT (7334L)
+#define RST9527_STAT_CORE_MMCM_LOCKED (7335L)
+#define RST9527_STAT_DDR4_MMCM_LOCKED (7336L)
+#define RST9527_STAT_DDR4_PLL_LOCKED (7337L)
+#define RST9527_STAT_PTP_MMCM_LOCKED (7338L)
+#define RST9527_STAT_SYS_MMCM_LOCKED (7339L)
+#define RST9527_STAT_TS_MMCM_LOCKED (7340L)
+#define RST9527_STICKY (7341L)
+#define RST9527_STICKY_CORE_MMCM_UNLOCKED (7342L)
+#define RST9527_STICKY_DDR4_MMCM_UNLOCKED (7343L)
+#define RST9527_STICKY_DDR4_PLL_UNLOCKED (7344L)
+#define RST9527_STICKY_PTP_MMCM_UNLOCKED (7345L)
+#define RST9527_STICKY_SYS_MMCM_UNLOCKED (7346L)
+#define RST9527_STICKY_TS_MMCM_UNLOCKED (7347L)
+/* RST9528 */
+/* RST9529 */
+#define RST9529_CTRL (7348L)
+#define RST9529_CTRL_PTP_MMCM_CLKSEL (7349L)
+#define RST9529_CTRL_TS_CLKSEL (7350L)
+#define RST9529_CTRL_TS_CLKSEL_OVERRIDE (7351L)
+#define RST9529_CTRL_TS_CLKSEL_REF (7352L)
+#define RST9529_POWER (7353L)
+#define RST9529_POWER_PU_NSEB (7354L)
+#define RST9529_POWER_PU_PHY (7355L)
+#define RST9529_RST (7356L)
+#define RST9529_RST_CORE_MMCM (7357L)
+#define RST9529_RST_DDR4 (7358L)
+#define RST9529_RST_PERIPH (7359L)
+#define RST9529_RST_PHY (7360L)
+#define RST9529_RST_PTP (7361L)
+#define RST9529_RST_PTP_MMCM (7362L)
+#define RST9529_RST_RPP (7363L)
+#define RST9529_RST_SDC (7364L)
+#define RST9529_RST_SYS (7365L)
+#define RST9529_RST_SYS_MMCM (7366L)
+#define RST9529_RST_TS (7367L)
+#define RST9529_RST_TSM_REF_MMCM (7368L)
+#define RST9529_RST_TS_MMCM (7369L)
+#define RST9529_STAT (7370L)
+#define RST9529_STAT_CORE_MMCM_LOCKED (7371L)
+#define RST9529_STAT_DDR4_MMCM_LOCKED (7372L)
+#define RST9529_STAT_DDR4_PLL_LOCKED (7373L)
+#define RST9529_STAT_PCI_SYS_MMCM_LOCKED (7374L)
+#define RST9529_STAT_PTP_MMCM_LOCKED (7375L)
+#define RST9529_STAT_SYS_MMCM_LOCKED (7376L)
+#define RST9529_STAT_TSM_REF_MMCM_LOCKED (7377L)
+#define RST9529_STAT_TS_MMCM_LOCKED (7378L)
+#define RST9529_STICKY (7379L)
+#define RST9529_STICKY_CORE_MMCM_UNLOCKED (7380L)
+#define RST9529_STICKY_DDR4_MMCM_UNLOCKED (7381L)
+#define RST9529_STICKY_DDR4_PLL_UNLOCKED (7382L)
+#define RST9529_STICKY_PCI_SYS_MMCM_UNLOCKED (7383L)
+#define RST9529_STICKY_PTP_MMCM_UNLOCKED (7384L)
+#define RST9529_STICKY_SYS_MMCM_UNLOCKED (7385L)
+#define RST9529_STICKY_TSM_REF_MMCM_UNLOCKED (7386L)
+#define RST9529_STICKY_TS_MMCM_UNLOCKED (7387L)
+/* RST9530 */
+#define RST9530_CTRL (7388L)
+#define RST9530_CTRL_PTP_MMCM_CLKSEL (7389L)
+#define RST9530_CTRL_TS_CLKSEL (7390L)
+#define RST9530_CTRL_TS_CLKSEL_OVERRIDE (7391L)
+#define RST9530_CTRL_TS_CLKSEL_REF (7392L)
+#define RST9530_POWER (7393L)
+#define RST9530_POWER_PU_NSEB (7394L)
+#define RST9530_POWER_PU_PHY (7395L)
+#define RST9530_RST (7396L)
+#define RST9530_RST_CORE_MMCM (7397L)
+#define RST9530_RST_DDR4 (7398L)
+#define RST9530_RST_NFV_OVS (7399L)
+#define RST9530_RST_PERIPH (7400L)
+#define RST9530_RST_PHY (7401L)
+#define RST9530_RST_PTP (7402L)
+#define RST9530_RST_PTP_MMCM (7403L)
+#define RST9530_RST_RPP (7404L)
+#define RST9530_RST_SDC (7405L)
+#define RST9530_RST_SYS (7406L)
+#define RST9530_RST_SYS_MMCM (7407L)
+#define RST9530_RST_TMC (7408L)
+#define RST9530_RST_TS (7409L)
+#define RST9530_RST_TSM_REF_MMCM (7410L)
+#define RST9530_RST_TS_MMCM (7411L)
+#define RST9530_STAT (7412L)
+#define RST9530_STAT_CORE_MMCM_LOCKED (7413L)
+#define RST9530_STAT_DDR4_MMCM_LOCKED (7414L)
+#define RST9530_STAT_DDR4_PLL_LOCKED (7415L)
+#define RST9530_STAT_PTP_MMCM_LOCKED (7416L)
+#define RST9530_STAT_SYS_MMCM_LOCKED (7417L)
+#define RST9530_STAT_TSM_REF_MMCM_LOCKED (7418L)
+#define RST9530_STAT_TS_MMCM_LOCKED (7419L)
+#define RST9530_STICKY (7420L)
+#define RST9530_STICKY_CORE_MMCM_UNLOCKED (7421L)
+#define RST9530_STICKY_DDR4_MMCM_UNLOCKED (7422L)
+#define RST9530_STICKY_DDR4_PLL_UNLOCKED (7423L)
+#define RST9530_STICKY_PCI_SYS_MMCM_UNLOCKED (7424L)
+#define RST9530_STICKY_PTP_MMCM_UNLOCKED (7425L)
+#define RST9530_STICKY_SYS_MMCM_UNLOCKED (7426L)
+#define RST9530_STICKY_TSM_REF_MMCM_UNLOCKED (7427L)
+#define RST9530_STICKY_TS_MMCM_UNLOCKED (7428L)
+/* RST9531 */
+#define RST9531_CTRL (7429L)
+#define RST9531_CTRL_PTP_MMCM_CLKSEL (7430L)
+#define RST9531_CTRL_TS_CLKSEL (7431L)
+#define RST9531_CTRL_TS_CLKSEL_OVERRIDE (7432L)
+#define RST9531_CTRL_TS_CLKSEL_REF (7433L)
+#define RST9531_POWER (7434L)
+#define RST9531_POWER_PU_NSEB (7435L)
+#define RST9531_POWER_PU_PHY (7436L)
+#define RST9531_RST (7437L)
+#define RST9531_RST_CORE_MMCM (7438L)
+#define RST9531_RST_DDR4 (7439L)
+#define RST9531_RST_PERIPH (7440L)
+#define RST9531_RST_PHY (7441L)
+#define RST9531_RST_PTP (7442L)
+#define RST9531_RST_PTP_MMCM (7443L)
+#define RST9531_RST_RPP (7444L)
+#define RST9531_RST_SDC (7445L)
+#define RST9531_RST_SYS (7446L)
+#define RST9531_RST_SYS_MMCM (7447L)
+#define RST9531_RST_TS (7448L)
+#define RST9531_RST_TSM_REF_MMCM (7449L)
+#define RST9531_RST_TS_MMCM (7450L)
+#define RST9531_STAT (7451L)
+#define RST9531_STAT_CORE_MMCM_LOCKED (7452L)
+#define RST9531_STAT_DDR4_MMCM_LOCKED (7453L)
+#define RST9531_STAT_DDR4_PLL_LOCKED (7454L)
+#define RST9531_STAT_PCI_SYS_MMCM_LOCKED (7455L)
+#define RST9531_STAT_PTP_MMCM_LOCKED (7456L)
+#define RST9531_STAT_SYS_MMCM_LOCKED (7457L)
+#define RST9531_STAT_TSM_REF_MMCM_LOCKED (7458L)
+#define RST9531_STAT_TS_MMCM_LOCKED (7459L)
+#define RST9531_STICKY (7460L)
+#define RST9531_STICKY_CORE_MMCM_UNLOCKED (7461L)
+#define RST9531_STICKY_DDR4_MMCM_UNLOCKED (7462L)
+#define RST9531_STICKY_DDR4_PLL_UNLOCKED (7463L)
+#define RST9531_STICKY_PCI_SYS_MMCM_UNLOCKED (7464L)
+#define RST9531_STICKY_PTP_MMCM_UNLOCKED (7465L)
+#define RST9531_STICKY_SYS_MMCM_UNLOCKED (7466L)
+#define RST9531_STICKY_TSM_REF_MMCM_UNLOCKED (7467L)
+#define RST9531_STICKY_TS_MMCM_UNLOCKED (7468L)
+/* RST9532 */
+#define RST9532_CTRL (7469L)
+#define RST9532_CTRL_PTP_MMCM_CLKSEL (7470L)
+#define RST9532_CTRL_TS_CLKSEL (7471L)
+#define RST9532_CTRL_TS_CLKSEL_OVERRIDE (7472L)
+#define RST9532_POWER (7473L)
+#define RST9532_POWER_PU_NSEB (7474L)
+#define RST9532_POWER_PU_PHY (7475L)
+#define RST9532_RST (7476L)
+#define RST9532_RST_CORE_MMCM (7477L)
+#define RST9532_RST_DDR4 (7478L)
+#define RST9532_RST_PERIPH (7479L)
+#define RST9532_RST_PHY (7480L)
+#define RST9532_RST_PTP (7481L)
+#define RST9532_RST_PTP_MMCM (7482L)
+#define RST9532_RST_RPP (7483L)
+#define RST9532_RST_SDC (7484L)
+#define RST9532_RST_SYS (7485L)
+#define RST9532_RST_SYS_MMCM (7486L)
+#define RST9532_RST_TMC (7487L)
+#define RST9532_RST_TS (7488L)
+#define RST9532_RST_TS_MMCM (7489L)
+#define RST9532_STAT (7490L)
+#define RST9532_STAT_CORE_MMCM_LOCKED (7491L)
+#define RST9532_STAT_DDR4_MMCM_LOCKED (7492L)
+#define RST9532_STAT_DDR4_PLL_LOCKED (7493L)
+#define RST9532_STAT_PTP_MMCM_LOCKED (7494L)
+#define RST9532_STAT_SYS_MMCM_LOCKED (7495L)
+#define RST9532_STAT_TS_MMCM_LOCKED (7496L)
+#define RST9532_STICKY (7497L)
+#define RST9532_STICKY_CORE_MMCM_UNLOCKED (7498L)
+#define RST9532_STICKY_DDR4_MMCM_UNLOCKED (7499L)
+#define RST9532_STICKY_DDR4_PLL_UNLOCKED (7500L)
+#define RST9532_STICKY_PTP_MMCM_UNLOCKED (7501L)
+#define RST9532_STICKY_SYS_MMCM_UNLOCKED (7502L)
+#define RST9532_STICKY_TS_MMCM_UNLOCKED (7503L)
+/* RST9533 */
+#define RST9533_CTRL (7504L)
+#define RST9533_CTRL_PTP_MMCM_CLKSEL (7505L)
+#define RST9533_CTRL_TS_CLKSEL (7506L)
+#define RST9533_CTRL_TS_CLKSEL_OVERRIDE (7507L)
+#define RST9533_POWER (7508L)
+#define RST9533_POWER_PU_NSEB (7509L)
+#define RST9533_POWER_PU_PHY (7510L)
+#define RST9533_RST (7511L)
+#define RST9533_RST_CORE_MMCM (7512L)
+#define RST9533_RST_DDR4 (7513L)
+#define RST9533_RST_PERIPH (7514L)
+#define RST9533_RST_PHY (7515L)
+#define RST9533_RST_PTP (7516L)
+#define RST9533_RST_PTP_MMCM (7517L)
+#define RST9533_RST_RPP (7518L)
+#define RST9533_RST_SDC (7519L)
+#define RST9533_RST_SYS (7520L)
+#define RST9533_RST_SYS_MMCM (7521L)
+#define RST9533_RST_TMC (7522L)
+#define RST9533_RST_TS (7523L)
+#define RST9533_RST_TS_MMCM (7524L)
+#define RST9533_STAT (7525L)
+#define RST9533_STAT_CORE_MMCM_LOCKED (7526L)
+#define RST9533_STAT_DDR4_MMCM_LOCKED (7527L)
+#define RST9533_STAT_DDR4_PLL_LOCKED (7528L)
+#define RST9533_STAT_PTP_MMCM_LOCKED (7529L)
+#define RST9533_STAT_SYS_MMCM_LOCKED (7530L)
+#define RST9533_STAT_TS_MMCM_LOCKED (7531L)
+#define RST9533_STICKY (7532L)
+#define RST9533_STICKY_CORE_MMCM_UNLOCKED (7533L)
+#define RST9533_STICKY_DDR4_MMCM_UNLOCKED (7534L)
+#define RST9533_STICKY_DDR4_PLL_UNLOCKED (7535L)
+#define RST9533_STICKY_PTP_MMCM_UNLOCKED (7536L)
+#define RST9533_STICKY_SYS_MMCM_UNLOCKED (7537L)
+#define RST9533_STICKY_TS_MMCM_UNLOCKED (7538L)
+/* RST9534 */
+#define RST9534_CTRL (7539L)
+#define RST9534_CTRL_PTP_MMCM_CLKSEL (7540L)
+#define RST9534_CTRL_TS_CLKSEL (7541L)
+#define RST9534_CTRL_TS_CLKSEL_OVERRIDE (7542L)
+#define RST9534_POWER (7543L)
+#define RST9534_POWER_PU_NSEB (7544L)
+#define RST9534_POWER_PU_PHY (7545L)
+#define RST9534_RST (7546L)
+#define RST9534_RST_CORE_MMCM (7547L)
+#define RST9534_RST_DDR4 (7548L)
+#define RST9534_RST_PERIPH (7549L)
+#define RST9534_RST_PHY (7550L)
+#define RST9534_RST_PTP (7551L)
+#define RST9534_RST_PTP_MMCM (7552L)
+#define RST9534_RST_RPP (7553L)
+#define RST9534_RST_SDC (7554L)
+#define RST9534_RST_SYS (7555L)
+#define RST9534_RST_SYS_MMCM (7556L)
+#define RST9534_RST_TMC (7557L)
+#define RST9534_RST_TS (7558L)
+#define RST9534_RST_TS_MMCM (7559L)
+#define RST9534_STAT (7560L)
+#define RST9534_STAT_CORE_MMCM_LOCKED (7561L)
+#define RST9534_STAT_DDR4_MMCM_LOCKED (7562L)
+#define RST9534_STAT_DDR4_PLL_LOCKED (7563L)
+#define RST9534_STAT_PTP_MMCM_LOCKED (7564L)
+#define RST9534_STAT_SYS_MMCM_LOCKED (7565L)
+#define RST9534_STAT_TS_MMCM_LOCKED (7566L)
+#define RST9534_STICKY (7567L)
+#define RST9534_STICKY_CORE_MMCM_UNLOCKED (7568L)
+#define RST9534_STICKY_DDR4_MMCM_UNLOCKED (7569L)
+#define RST9534_STICKY_DDR4_PLL_UNLOCKED (7570L)
+#define RST9534_STICKY_PTP_MMCM_UNLOCKED (7571L)
+#define RST9534_STICKY_SYS_MMCM_UNLOCKED (7572L)
+#define RST9534_STICKY_TS_MMCM_UNLOCKED (7573L)
+/* RST9535 */
+#define RST9535_CTRL (7574L)
+#define RST9535_CTRL_PTP_MMCM_CLKSEL (7575L)
+#define RST9535_CTRL_TS_CLKSEL (7576L)
+#define RST9535_CTRL_TS_CLKSEL_OVERRIDE (7577L)
+#define RST9535_POWER (7578L)
+#define RST9535_POWER_PU_NSEB (7579L)
+#define RST9535_POWER_PU_PHY (7580L)
+#define RST9535_RST (7581L)
+#define RST9535_RST_CORE_MMCM (7582L)
+#define RST9535_RST_DDR4 (7583L)
+#define RST9535_RST_MAC_RX (7584L)
+#define RST9535_RST_MAC_TX (7585L)
+#define RST9535_RST_PCS_RX (7586L)
+#define RST9535_RST_PERIPH (7587L)
+#define RST9535_RST_PHY (7588L)
+#define RST9535_RST_PTP (7589L)
+#define RST9535_RST_PTP_MMCM (7590L)
+#define RST9535_RST_RPP (7591L)
+#define RST9535_RST_SDC (7592L)
+#define RST9535_RST_SERDES_RX (7593L)
+#define RST9535_RST_SERDES_RX_DATAPATH (7594L)
+#define RST9535_RST_SERDES_TX (7595L)
+#define RST9535_RST_SYS (7596L)
+#define RST9535_RST_SYS_MMCM (7597L)
+#define RST9535_RST_TMC (7598L)
+#define RST9535_RST_TS (7599L)
+#define RST9535_RST_TS_MMCM (7600L)
+#define RST9535_STAT (7601L)
+#define RST9535_STAT_CORE_MMCM_LOCKED (7602L)
+#define RST9535_STAT_DDR4_MMCM_LOCKED (7603L)
+#define RST9535_STAT_DDR4_PLL_LOCKED (7604L)
+#define RST9535_STAT_PTP_MMCM_LOCKED (7605L)
+#define RST9535_STAT_SYS_MMCM_LOCKED (7606L)
+#define RST9535_STAT_TS_MMCM_LOCKED (7607L)
+#define RST9535_STICKY (7608L)
+#define RST9535_STICKY_CORE_MMCM_UNLOCKED (7609L)
+#define RST9535_STICKY_DDR4_MMCM_UNLOCKED (7610L)
+#define RST9535_STICKY_DDR4_PLL_UNLOCKED (7611L)
+#define RST9535_STICKY_PTP_MMCM_UNLOCKED (7612L)
+#define RST9535_STICKY_SYS_MMCM_UNLOCKED (7613L)
+#define RST9535_STICKY_TS_MMCM_UNLOCKED (7614L)
+/* RST9536 */
+#define RST9536_CTRL (7615L)
+#define RST9536_CTRL_PTP_MMCM_CLKSEL (7616L)
+#define RST9536_CTRL_TS_CLKSEL (7617L)
+#define RST9536_CTRL_TS_CLKSEL_OVERRIDE (7618L)
+#define RST9536_POWER (7619L)
+#define RST9536_POWER_PU_NSEB (7620L)
+#define RST9536_POWER_PU_PHY (7621L)
+#define RST9536_RST (7622L)
+#define RST9536_RST_CORE_MMCM (7623L)
+#define RST9536_RST_DDR4 (7624L)
+#define RST9536_RST_MAC_RX (7625L)
+#define RST9536_RST_PERIPH (7626L)
+#define RST9536_RST_PHY (7627L)
+#define RST9536_RST_PTP (7628L)
+#define RST9536_RST_PTP_MMCM (7629L)
+#define RST9536_RST_RPP (7630L)
+#define RST9536_RST_SDC (7631L)
+#define RST9536_RST_SYS (7632L)
+#define RST9536_RST_SYS_MMCM (7633L)
+#define RST9536_RST_TMC (7634L)
+#define RST9536_RST_TS (7635L)
+#define RST9536_RST_TS_MMCM (7636L)
+#define RST9536_STAT (7637L)
+#define RST9536_STAT_CORE_MMCM_LOCKED (7638L)
+#define RST9536_STAT_DDR4_MMCM_LOCKED (7639L)
+#define RST9536_STAT_DDR4_PLL_LOCKED (7640L)
+#define RST9536_STAT_PTP_MMCM_LOCKED (7641L)
+#define RST9536_STAT_SYS_MMCM_LOCKED (7642L)
+#define RST9536_STAT_TS_MMCM_LOCKED (7643L)
+#define RST9536_STICKY (7644L)
+#define RST9536_STICKY_CORE_MMCM_UNLOCKED (7645L)
+#define RST9536_STICKY_DDR4_MMCM_UNLOCKED (7646L)
+#define RST9536_STICKY_DDR4_PLL_UNLOCKED (7647L)
+#define RST9536_STICKY_PTP_MMCM_UNLOCKED (7648L)
+#define RST9536_STICKY_SYS_MMCM_UNLOCKED (7649L)
+#define RST9536_STICKY_TS_MMCM_UNLOCKED (7650L)
+/* RST9537 */
+#define RST9537_CTRL (7651L)
+#define RST9537_CTRL_PTP_MMCM_CLKSEL (7652L)
+#define RST9537_CTRL_TS_CLKSEL (7653L)
+#define RST9537_CTRL_TS_CLKSEL_OVERRIDE (7654L)
+#define RST9537_RST (7655L)
+#define RST9537_RST_DDR3 (7656L)
+#define RST9537_RST_DDR3_IDLY_MMCM (7657L)
+#define RST9537_RST_NSEB (7658L)
+#define RST9537_RST_PERIPH (7659L)
+#define RST9537_RST_PHY10G_QPLL (7660L)
+#define RST9537_RST_PHY3S10G (7661L)
+#define RST9537_RST_PHY3S_MMCM (7662L)
+#define RST9537_RST_PTP (7663L)
+#define RST9537_RST_PTP_MMCM (7664L)
+#define RST9537_RST_RPP (7665L)
+#define RST9537_RST_SDC (7666L)
+#define RST9537_RST_SI5326 (7667L)
+#define RST9537_RST_SYS (7668L)
+#define RST9537_RST_TS (7669L)
+#define RST9537_RST_TS_MMCM (7670L)
+#define RST9537_RST_STAT (7671L)
+#define RST9537_RST_STAT_PCS_RESET_BY_SERDES (7672L)
+#define RST9537_STAT (7673L)
+#define RST9537_STAT_DDR3_IDLY_MMCM_LOCKED (7674L)
+#define RST9537_STAT_DDR3_MMCM_LOCKED (7675L)
+#define RST9537_STAT_DDR3_PLL_LOCKED (7676L)
+#define RST9537_STAT_PHY10G_QPLL_LOCK_0_1 (7677L)
+#define RST9537_STAT_PHY10G_QPLL_LOCK_2_3 (7678L)
+#define RST9537_STAT_PHY3S_MMCM_LOCKED (7679L)
+#define RST9537_STAT_PTP_MMCM_LOCKED (7680L)
+#define RST9537_STAT_SYNCE_MAIN_CLK_LOS (7681L)
+#define RST9537_STAT_SYS_MMCM_LOCKED (7682L)
+#define RST9537_STAT_TS_MMCM_LOCKED (7683L)
+#define RST9537_STICKY (7684L)
+#define RST9537_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7685L)
+#define RST9537_STICKY_DDR3_MMCM_UNLOCKED (7686L)
+#define RST9537_STICKY_DDR3_PLL_UNLOCKED (7687L)
+#define RST9537_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7688L)
+#define RST9537_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7689L)
+#define RST9537_STICKY_PHY3S_MMCM_UNLOCKED (7690L)
+#define RST9537_STICKY_PTP_MMCM_UNLOCKED (7691L)
+#define RST9537_STICKY_TS_MMCM_UNLOCKED (7692L)
+/* RST9538 */
+#define RST9538_CTRL (7693L)
+#define RST9538_CTRL_PTP_MMCM_CLKSEL (7694L)
+#define RST9538_CTRL_TS_CLKSEL (7695L)
+#define RST9538_CTRL_TS_CLKSEL_OVERRIDE (7696L)
+#define RST9538_RST (7697L)
+#define RST9538_RST_DDR3 (7698L)
+#define RST9538_RST_DDR3_IDLY_MMCM (7699L)
+#define RST9538_RST_NSEB (7700L)
+#define RST9538_RST_PERIPH (7701L)
+#define RST9538_RST_PHY10G_QPLL (7702L)
+#define RST9538_RST_PHY3S10G (7703L)
+#define RST9538_RST_PHY3S_MMCM (7704L)
+#define RST9538_RST_PTP (7705L)
+#define RST9538_RST_PTP_MMCM (7706L)
+#define RST9538_RST_RPP (7707L)
+#define RST9538_RST_SDC (7708L)
+#define RST9538_RST_SI5326 (7709L)
+#define RST9538_RST_SYS (7710L)
+#define RST9538_RST_TS (7711L)
+#define RST9538_RST_TS_MMCM (7712L)
+#define RST9538_RST_STAT (7713L)
+#define RST9538_RST_STAT_PCS_RESET_BY_SERDES (7714L)
+#define RST9538_STAT (7715L)
+#define RST9538_STAT_DDR3_IDLY_MMCM_LOCKED (7716L)
+#define RST9538_STAT_DDR3_MMCM_LOCKED (7717L)
+#define RST9538_STAT_DDR3_PLL_LOCKED (7718L)
+#define RST9538_STAT_PHY10G_QPLL_LOCK_0_1 (7719L)
+#define RST9538_STAT_PHY10G_QPLL_LOCK_2_3 (7720L)
+#define RST9538_STAT_PHY3S_MMCM_LOCKED (7721L)
+#define RST9538_STAT_PTP_MMCM_LOCKED (7722L)
+#define RST9538_STAT_SYNCE_MAIN_CLK_LOS (7723L)
+#define RST9538_STAT_SYS_MMCM_LOCKED (7724L)
+#define RST9538_STAT_TS_MMCM_LOCKED (7725L)
+#define RST9538_STICKY (7726L)
+#define RST9538_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7727L)
+#define RST9538_STICKY_DDR3_MMCM_UNLOCKED (7728L)
+#define RST9538_STICKY_DDR3_PLL_UNLOCKED (7729L)
+#define RST9538_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7730L)
+#define RST9538_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7731L)
+#define RST9538_STICKY_PHY3S_MMCM_UNLOCKED (7732L)
+#define RST9538_STICKY_PTP_MMCM_UNLOCKED (7733L)
+#define RST9538_STICKY_TS_MMCM_UNLOCKED (7734L)
+/* RST9539 */
+#define RST9539_CTRL (7735L)
+#define RST9539_CTRL_PTP_MMCM_CLKSEL (7736L)
+#define RST9539_CTRL_TS_CLKSEL (7737L)
+#define RST9539_CTRL_TS_CLKSEL_OVERRIDE (7738L)
+#define RST9539_POWER (7739L)
+#define RST9539_POWER_PU_NSEB (7740L)
+#define RST9539_POWER_PU_PHY (7741L)
+#define RST9539_RST (7742L)
+#define RST9539_RST_CORE_MMCM (7743L)
+#define RST9539_RST_DDR4 (7744L)
+#define RST9539_RST_PERIPH (7745L)
+#define RST9539_RST_PHY (7746L)
+#define RST9539_RST_PTP (7747L)
+#define RST9539_RST_PTP_MMCM (7748L)
+#define RST9539_RST_RPP (7749L)
+#define RST9539_RST_SDC (7750L)
+#define RST9539_RST_SYS (7751L)
+#define RST9539_RST_SYS_MMCM (7752L)
+#define RST9539_RST_TMC (7753L)
+#define RST9539_RST_TS (7754L)
+#define RST9539_RST_TS_MMCM (7755L)
+#define RST9539_STAT (7756L)
+#define RST9539_STAT_CORE_MMCM_LOCKED (7757L)
+#define RST9539_STAT_DDR4_MMCM_LOCKED (7758L)
+#define RST9539_STAT_DDR4_PLL_LOCKED (7759L)
+#define RST9539_STAT_PTP_MMCM_LOCKED (7760L)
+#define RST9539_STAT_SYS_MMCM_LOCKED (7761L)
+#define RST9539_STAT_TS_MMCM_LOCKED (7762L)
+#define RST9539_STICKY (7763L)
+#define RST9539_STICKY_CORE_MMCM_UNLOCKED (7764L)
+#define RST9539_STICKY_DDR4_MMCM_UNLOCKED (7765L)
+#define RST9539_STICKY_DDR4_PLL_UNLOCKED (7766L)
+#define RST9539_STICKY_PTP_MMCM_UNLOCKED (7767L)
+#define RST9539_STICKY_SYS_MMCM_UNLOCKED (7768L)
+#define RST9539_STICKY_TS_MMCM_UNLOCKED (7769L)
+/* RST9540 */
+#define RST9540_CTRL (7770L)
+#define RST9540_CTRL_PTP_MMCM_CLKSEL (7771L)
+#define RST9540_CTRL_TS_CLKSEL (7772L)
+#define RST9540_CTRL_TS_CLKSEL_OVERRIDE (7773L)
+#define RST9540_POWER (7774L)
+#define RST9540_POWER_PU_NSEB (7775L)
+#define RST9540_POWER_PU_PHY (7776L)
+#define RST9540_RST (7777L)
+#define RST9540_RST_CORE_MMCM (7778L)
+#define RST9540_RST_DDR4 (7779L)
+#define RST9540_RST_MAC_RX (7780L)
+#define RST9540_RST_MAC_TX (7781L)
+#define RST9540_RST_PCS_RX (7782L)
+#define RST9540_RST_PERIPH (7783L)
+#define RST9540_RST_PHY (7784L)
+#define RST9540_RST_PTP (7785L)
+#define RST9540_RST_PTP_MMCM (7786L)
+#define RST9540_RST_RPP (7787L)
+#define RST9540_RST_SDC (7788L)
+#define RST9540_RST_SERDES_RX (7789L)
+#define RST9540_RST_SERDES_RX_DATAPATH (7790L)
+#define RST9540_RST_SERDES_TX (7791L)
+#define RST9540_RST_SYS (7792L)
+#define RST9540_RST_SYS_MMCM (7793L)
+#define RST9540_RST_TMC (7794L)
+#define RST9540_RST_TS (7795L)
+#define RST9540_RST_TS_MMCM (7796L)
+#define RST9540_STAT (7797L)
+#define RST9540_STAT_CORE_MMCM_LOCKED (7798L)
+#define RST9540_STAT_DDR4_MMCM_LOCKED (7799L)
+#define RST9540_STAT_DDR4_PLL_LOCKED (7800L)
+#define RST9540_STAT_PTP_MMCM_LOCKED (7801L)
+#define RST9540_STAT_SYS_MMCM_LOCKED (7802L)
+#define RST9540_STAT_TS_MMCM_LOCKED (7803L)
+#define RST9540_STICKY (7804L)
+#define RST9540_STICKY_CORE_MMCM_UNLOCKED (7805L)
+#define RST9540_STICKY_DDR4_MMCM_UNLOCKED (7806L)
+#define RST9540_STICKY_DDR4_PLL_UNLOCKED (7807L)
+#define RST9540_STICKY_PTP_MMCM_UNLOCKED (7808L)
+#define RST9540_STICKY_SYS_MMCM_UNLOCKED (7809L)
+#define RST9540_STICKY_TS_MMCM_UNLOCKED (7810L)
+/* RST9541 */
+#define RST9541_LATCH (7811L)
+#define RST9541_LATCH_DDR4_CALIB_COMPLETE (7812L)
+#define RST9541_LATCH_PHY_RDY (7813L)
+#define RST9541_POWER (7814L)
+#define RST9541_POWER_PU_PHY (7815L)
+#define RST9541_RST (7816L)
+#define RST9541_RST_DDR4 (7817L)
+#define RST9541_RST_PERIPH (7818L)
+#define RST9541_RST_PHY (7819L)
+#define RST9541_RST_POWER (7820L)
+#define RST9541_RST_SYS (7821L)
+#define RST9541_STAT (7822L)
+#define RST9541_STAT_DDR4_CALIB_COMPLETE (7823L)
+#define RST9541_STAT_PHY_RDY (7824L)
+/* RST9542 */
+#define RST9542_LATCH (7825L)
+#define RST9542_LATCH_DDR4_CALIB_COMPLETE (7826L)
+#define RST9542_LATCH_PHY_RDY (7827L)
+#define RST9542_POWER (7828L)
+#define RST9542_POWER_PU_PHY (7829L)
+#define RST9542_RST (7830L)
+#define RST9542_RST_DDR4 (7831L)
+#define RST9542_RST_PERIPH (7832L)
+#define RST9542_RST_PHY (7833L)
+#define RST9542_RST_SYS (7834L)
+#define RST9542_STAT (7835L)
+#define RST9542_STAT_DDR4_CALIB_COMPLETE (7836L)
+#define RST9542_STAT_PHY_RDY (7837L)
+/* RST9543 */
+#define RST9543_CTRL (7838L)
+#define RST9543_CTRL_PTP_MMCM_CLKSEL (7839L)
+#define RST9543_CTRL_TS_CLKSEL (7840L)
+#define RST9543_CTRL_TS_CLKSEL_OVERRIDE (7841L)
+#define RST9543_POWER (7842L)
+#define RST9543_POWER_PU_NSEB (7843L)
+#define RST9543_POWER_PU_PHY (7844L)
+#define RST9543_RST (7845L)
+#define RST9543_RST_CORE_MMCM (7846L)
+#define RST9543_RST_DDR4 (7847L)
+#define RST9543_RST_MAC_RX (7848L)
+#define RST9543_RST_PERIPH (7849L)
+#define RST9543_RST_PHY (7850L)
+#define RST9543_RST_PTP (7851L)
+#define RST9543_RST_PTP_MMCM (7852L)
+#define RST9543_RST_RPP (7853L)
+#define RST9543_RST_SDC (7854L)
+#define RST9543_RST_SYS (7855L)
+#define RST9543_RST_SYS_MMCM (7856L)
+#define RST9543_RST_TMC (7857L)
+#define RST9543_RST_TS (7858L)
+#define RST9543_RST_TS_MMCM (7859L)
+#define RST9543_STAT (7860L)
+#define RST9543_STAT_CORE_MMCM_LOCKED (7861L)
+#define RST9543_STAT_DDR4_MMCM_LOCKED (7862L)
+#define RST9543_STAT_DDR4_PLL_LOCKED (7863L)
+#define RST9543_STAT_PTP_MMCM_LOCKED (7864L)
+#define RST9543_STAT_SYS_MMCM_LOCKED (7865L)
+#define RST9543_STAT_TS_MMCM_LOCKED (7866L)
+#define RST9543_STICKY (7867L)
+#define RST9543_STICKY_CORE_MMCM_UNLOCKED (7868L)
+#define RST9543_STICKY_DDR4_MMCM_UNLOCKED (7869L)
+#define RST9543_STICKY_DDR4_PLL_UNLOCKED (7870L)
+#define RST9543_STICKY_PTP_MMCM_UNLOCKED (7871L)
+#define RST9543_STICKY_SYS_MMCM_UNLOCKED (7872L)
+#define RST9543_STICKY_TS_MMCM_UNLOCKED (7873L)
+/* RST9544 */
+#define RST9544_CTRL (7874L)
+#define RST9544_CTRL_PTP_MMCM_CLKSEL (7875L)
+#define RST9544_CTRL_TS_CLKSEL (7876L)
+#define RST9544_CTRL_TS_CLKSEL_OVERRIDE (7877L)
+#define RST9544_CTRL_TS_CLKSEL_REF (7878L)
+#define RST9544_POWER (7879L)
+#define RST9544_POWER_PU_NSEB (7880L)
+#define RST9544_POWER_PU_PHY (7881L)
+#define RST9544_RST (7882L)
+#define RST9544_RST_CORE_MMCM (7883L)
+#define RST9544_RST_DDR4 (7884L)
+#define RST9544_RST_NFV_OVS (7885L)
+#define RST9544_RST_PERIPH (7886L)
+#define RST9544_RST_PHY (7887L)
+#define RST9544_RST_PTP (7888L)
+#define RST9544_RST_PTP_MMCM (7889L)
+#define RST9544_RST_RPP (7890L)
+#define RST9544_RST_SDC (7891L)
+#define RST9544_RST_SYS (7892L)
+#define RST9544_RST_SYS_MMCM (7893L)
+#define RST9544_RST_TMC (7894L)
+#define RST9544_RST_TS (7895L)
+#define RST9544_RST_TSM_REF_MMCM (7896L)
+#define RST9544_RST_TS_MMCM (7897L)
+#define RST9544_STAT (7898L)
+#define RST9544_STAT_CORE_MMCM_LOCKED (7899L)
+#define RST9544_STAT_DDR4_MMCM_LOCKED (7900L)
+#define RST9544_STAT_DDR4_PLL_LOCKED (7901L)
+#define RST9544_STAT_PTP_MMCM_LOCKED (7902L)
+#define RST9544_STAT_SYS_MMCM_LOCKED (7903L)
+#define RST9544_STAT_TSM_REF_MMCM_LOCKED (7904L)
+#define RST9544_STAT_TS_MMCM_LOCKED (7905L)
+#define RST9544_STICKY (7906L)
+#define RST9544_STICKY_CORE_MMCM_UNLOCKED (7907L)
+#define RST9544_STICKY_DDR4_MMCM_UNLOCKED (7908L)
+#define RST9544_STICKY_DDR4_PLL_UNLOCKED (7909L)
+#define RST9544_STICKY_PCI_SYS_MMCM_UNLOCKED (7910L)
+#define RST9544_STICKY_PTP_MMCM_UNLOCKED (7911L)
+#define RST9544_STICKY_SYS_MMCM_UNLOCKED (7912L)
+#define RST9544_STICKY_TSM_REF_MMCM_UNLOCKED (7913L)
+#define RST9544_STICKY_TS_MMCM_UNLOCKED (7914L)
+/* RST9545 */
+#define RST9545_CTRL (7915L)
+#define RST9545_CTRL_PTP_MMCM_CLKSEL (7916L)
+#define RST9545_CTRL_TS_CLKSEL (7917L)
+#define RST9545_CTRL_TS_CLKSEL_OVERRIDE (7918L)
+#define RST9545_POWER (7919L)
+#define RST9545_POWER_PU_NSEB (7920L)
+#define RST9545_POWER_PU_PHY (7921L)
+#define RST9545_RST (7922L)
+#define RST9545_RST_CORE_MMCM (7923L)
+#define RST9545_RST_DDR4 (7924L)
+#define RST9545_RST_PERIPH (7925L)
+#define RST9545_RST_PHY (7926L)
+#define RST9545_RST_PTP (7927L)
+#define RST9545_RST_PTP_MMCM (7928L)
+#define RST9545_RST_RPP (7929L)
+#define RST9545_RST_SDC (7930L)
+#define RST9545_RST_SYS (7931L)
+#define RST9545_RST_SYS_MMCM (7932L)
+#define RST9545_RST_TMC (7933L)
+#define RST9545_RST_TS (7934L)
+#define RST9545_RST_TS_MMCM (7935L)
+#define RST9545_STAT (7936L)
+#define RST9545_STAT_CORE_MMCM_LOCKED (7937L)
+#define RST9545_STAT_DDR4_MMCM_LOCKED (7938L)
+#define RST9545_STAT_DDR4_PLL_LOCKED (7939L)
+#define RST9545_STAT_PTP_MMCM_LOCKED (7940L)
+#define RST9545_STAT_SYS_MMCM_LOCKED (7941L)
+#define RST9545_STAT_TS_MMCM_LOCKED (7942L)
+#define RST9545_STICKY (7943L)
+#define RST9545_STICKY_CORE_MMCM_UNLOCKED (7944L)
+#define RST9545_STICKY_DDR4_MMCM_UNLOCKED (7945L)
+#define RST9545_STICKY_DDR4_PLL_UNLOCKED (7946L)
+#define RST9545_STICKY_PTP_MMCM_UNLOCKED (7947L)
+#define RST9545_STICKY_SYS_MMCM_UNLOCKED (7948L)
+#define RST9545_STICKY_TS_MMCM_UNLOCKED (7949L)
+/* RST9546 */
+#define RST9546_CTRL (7950L)
+#define RST9546_CTRL_PTP_MMCM_CLKSEL (7951L)
+#define RST9546_CTRL_TS_CLKSEL (7952L)
+#define RST9546_CTRL_TS_CLKSEL_OVERRIDE (7953L)
+#define RST9546_POWER (7954L)
+#define RST9546_POWER_PU_NSEB (7955L)
+#define RST9546_POWER_PU_PHY (7956L)
+#define RST9546_RST (7957L)
+#define RST9546_RST_CORE_MMCM (7958L)
+#define RST9546_RST_DDR4 (7959L)
+#define RST9546_RST_MAC_RX (7960L)
+#define RST9546_RST_MAC_TX (7961L)
+#define RST9546_RST_PCS_RX (7962L)
+#define RST9546_RST_PERIPH (7963L)
+#define RST9546_RST_PHY (7964L)
+#define RST9546_RST_PTP (7965L)
+#define RST9546_RST_PTP_MMCM (7966L)
+#define RST9546_RST_RPP (7967L)
+#define RST9546_RST_SDC (7968L)
+#define RST9546_RST_SERDES_RX (7969L)
+#define RST9546_RST_SERDES_RX_DATAPATH (7970L)
+#define RST9546_RST_SERDES_TX (7971L)
+#define RST9546_RST_SYS (7972L)
+#define RST9546_RST_SYS_MMCM (7973L)
+#define RST9546_RST_TMC (7974L)
+#define RST9546_RST_TS (7975L)
+#define RST9546_RST_TS_MMCM (7976L)
+#define RST9546_STAT (7977L)
+#define RST9546_STAT_CORE_MMCM_LOCKED (7978L)
+#define RST9546_STAT_DDR4_MMCM_LOCKED (7979L)
+#define RST9546_STAT_DDR4_PLL_LOCKED (7980L)
+#define RST9546_STAT_PTP_MMCM_LOCKED (7981L)
+#define RST9546_STAT_SYS_MMCM_LOCKED (7982L)
+#define RST9546_STAT_TS_MMCM_LOCKED (7983L)
+#define RST9546_STICKY (7984L)
+#define RST9546_STICKY_CORE_MMCM_UNLOCKED (7985L)
+#define RST9546_STICKY_DDR4_MMCM_UNLOCKED (7986L)
+#define RST9546_STICKY_DDR4_PLL_UNLOCKED (7987L)
+#define RST9546_STICKY_PTP_MMCM_UNLOCKED (7988L)
+#define RST9546_STICKY_SYS_MMCM_UNLOCKED (7989L)
+#define RST9546_STICKY_TS_MMCM_UNLOCKED (7990L)
+/* RST9547 */
+#define RST9547_LATCH (7991L)
+#define RST9547_LATCH_DDR4_CALIB_COMPLETE (7992L)
+#define RST9547_LATCH_PHY_RDY (7993L)
+#define RST9547_POWER (7994L)
+#define RST9547_POWER_PU_PHY (7995L)
+#define RST9547_RST (7996L)
+#define RST9547_RST_DDR4 (7997L)
+#define RST9547_RST_PERIPH (7998L)
+#define RST9547_RST_PHY (7999L)
+#define RST9547_RST_SYS (8000L)
+#define RST9547_STAT (8001L)
+#define RST9547_STAT_DDR4_CALIB_COMPLETE (8002L)
+#define RST9547_STAT_PHY_RDY (8003L)
+/* RST9548 */
+#define RST9548_CTRL (8004L)
+#define RST9548_CTRL_PTP_MMCM_CLKSEL (8005L)
+#define RST9548_CTRL_TS_CLKSEL (8006L)
+#define RST9548_CTRL_TS_CLKSEL_OVERRIDE (8007L)
+#define RST9548_POWER (8008L)
+#define RST9548_POWER_PU_NSEB (8009L)
+#define RST9548_POWER_PU_PHY (8010L)
+#define RST9548_RST (8011L)
+#define RST9548_RST_CORE_MMCM (8012L)
+#define RST9548_RST_DDR4 (8013L)
+#define RST9548_RST_PERIPH (8014L)
+#define RST9548_RST_PHY (8015L)
+#define RST9548_RST_PTP (8016L)
+#define RST9548_RST_PTP_MMCM (8017L)
+#define RST9548_RST_RPP (8018L)
+#define RST9548_RST_SDC (8019L)
+#define RST9548_RST_SYS (8020L)
+#define RST9548_RST_SYS_MMCM (8021L)
+#define RST9548_RST_TMC (8022L)
+#define RST9548_RST_TS (8023L)
+#define RST9548_RST_TS_MMCM (8024L)
+#define RST9548_STAT (8025L)
+#define RST9548_STAT_CORE_MMCM_LOCKED (8026L)
+#define RST9548_STAT_DDR4_MMCM_LOCKED (8027L)
+#define RST9548_STAT_DDR4_PLL_LOCKED (8028L)
+#define RST9548_STAT_PTP_MMCM_LOCKED (8029L)
+#define RST9548_STAT_SYS_MMCM_LOCKED (8030L)
+#define RST9548_STAT_TS_MMCM_LOCKED (8031L)
+#define RST9548_STICKY (8032L)
+#define RST9548_STICKY_CORE_MMCM_UNLOCKED (8033L)
+#define RST9548_STICKY_DDR4_MMCM_UNLOCKED (8034L)
+#define RST9548_STICKY_DDR4_PLL_UNLOCKED (8035L)
+#define RST9548_STICKY_PTP_MMCM_UNLOCKED (8036L)
+#define RST9548_STICKY_SYS_MMCM_UNLOCKED (8037L)
+#define RST9548_STICKY_TS_MMCM_UNLOCKED (8038L)
+/* RST9549 */
+#define RST9549_CTRL (8039L)
+#define RST9549_CTRL_PTP_MMCM_CLKSEL (8040L)
+#define RST9549_CTRL_TS_CLKSEL (8041L)
+#define RST9549_CTRL_TS_CLKSEL_OVERRIDE (8042L)
+#define RST9549_POWER (8043L)
+#define RST9549_POWER_PU_NSEB (8044L)
+#define RST9549_POWER_PU_PHY (8045L)
+#define RST9549_RST (8046L)
+#define RST9549_RST_CORE_MMCM (8047L)
+#define RST9549_RST_DDR4 (8048L)
+#define RST9549_RST_PERIPH (8049L)
+#define RST9549_RST_PHY (8050L)
+#define RST9549_RST_PTP (8051L)
+#define RST9549_RST_PTP_MMCM (8052L)
+#define RST9549_RST_RPP (8053L)
+#define RST9549_RST_SDC (8054L)
+#define RST9549_RST_SYS (8055L)
+#define RST9549_RST_SYS_MMCM (8056L)
+#define RST9549_RST_TMC (8057L)
+#define RST9549_RST_TS (8058L)
+#define RST9549_RST_TS_MMCM (8059L)
+#define RST9549_STAT (8060L)
+#define RST9549_STAT_CORE_MMCM_LOCKED (8061L)
+#define RST9549_STAT_DDR4_MMCM_LOCKED (8062L)
+#define RST9549_STAT_DDR4_PLL_LOCKED (8063L)
+#define RST9549_STAT_PTP_MMCM_LOCKED (8064L)
+#define RST9549_STAT_SYS_MMCM_LOCKED (8065L)
+#define RST9549_STAT_TS_MMCM_LOCKED (8066L)
+#define RST9549_STICKY (8067L)
+#define RST9549_STICKY_CORE_MMCM_UNLOCKED (8068L)
+#define RST9549_STICKY_DDR4_MMCM_UNLOCKED (8069L)
+#define RST9549_STICKY_DDR4_PLL_UNLOCKED (8070L)
+#define RST9549_STICKY_PTP_MMCM_UNLOCKED (8071L)
+#define RST9549_STICKY_SYS_MMCM_UNLOCKED (8072L)
+#define RST9549_STICKY_TS_MMCM_UNLOCKED (8073L)
+/* RST9553 */
+#define RST9553_LATCH (8074L)
+#define RST9553_LATCH_DDR4_CALIB_COMPLETE (8075L)
+#define RST9553_LATCH_PHY_RDY (8076L)
+#define RST9553_RST (8077L)
+#define RST9553_RST_DDR4 (8078L)
+#define RST9553_RST_PHY (8079L)
+#define RST9553_RST_SYS (8080L)
+#define RST9553_STAT (8081L)
+#define RST9553_STAT_DDR4_CALIB_COMPLETE (8082L)
+#define RST9553_STAT_PHY_RDY (8083L)
+/* RST9555 */
+#define RST9555_CTRL (8094L)
+#define RST9555_CTRL_PTP_MMCM_CLKSEL (8095L)
+#define RST9555_CTRL_TS_CLKSEL (8096L)
+#define RST9555_CTRL_TS_CLKSEL_OVERRIDE (8097L)
+#define RST9555_POWER (8098L)
+#define RST9555_POWER_PU_NSEB (8099L)
+#define RST9555_POWER_PU_PHY (8100L)
+#define RST9555_RST (8101L)
+#define RST9555_RST_CORE_MMCM (8102L)
+#define RST9555_RST_DDR4 (8103L)
+#define RST9555_RST_PERIPH (8104L)
+#define RST9555_RST_PHY (8105L)
+#define RST9555_RST_PTP (8106L)
+#define RST9555_RST_PTP_MMCM (8107L)
+#define RST9555_RST_RPP (8108L)
+#define RST9555_RST_SDC (8109L)
+#define RST9555_RST_SYS (8110L)
+#define RST9555_RST_SYS_MMCM (8111L)
+#define RST9555_RST_TMC (8112L)
+#define RST9555_RST_TS (8113L)
+#define RST9555_RST_TS_MMCM (8114L)
+#define RST9555_STAT (8115L)
+#define RST9555_STAT_CORE_MMCM_LOCKED (8116L)
+#define RST9555_STAT_DDR4_MMCM_LOCKED (8117L)
+#define RST9555_STAT_DDR4_PLL_LOCKED (8118L)
+#define RST9555_STAT_PTP_MMCM_LOCKED (8119L)
+#define RST9555_STAT_SYS_MMCM_LOCKED (8120L)
+#define RST9555_STAT_TS_MMCM_LOCKED (8121L)
+#define RST9555_STICKY (8122L)
+#define RST9555_STICKY_CORE_MMCM_UNLOCKED (8123L)
+#define RST9555_STICKY_DDR4_MMCM_UNLOCKED (8124L)
+#define RST9555_STICKY_DDR4_PLL_UNLOCKED (8125L)
+#define RST9555_STICKY_PTP_MMCM_UNLOCKED (8126L)
+#define RST9555_STICKY_SYS_MMCM_UNLOCKED (8127L)
+#define RST9555_STICKY_TS_MMCM_UNLOCKED (8128L)
+/* RST9559 */
+#define RST9559_LATCH (8129L)
+#define RST9559_LATCH_DDR4_CALIB_COMPLETE (8130L)
+#define RST9559_LATCH_PHY_RDY (8131L)
+#define RST9559_RST (8132L)
+#define RST9559_RST_DDR4 (8133L)
+#define RST9559_RST_PHY (8134L)
+#define RST9559_RST_SYS (8135L)
+#define RST9559_STAT (8136L)
+#define RST9559_STAT_DDR4_CALIB_COMPLETE (8137L)
+#define RST9559_STAT_PHY_RDY (8138L)
+/* RST9563 */
+#define RST9563_CTRL (8159L)
+#define RST9563_CTRL_PTP_MMCM_CLKSEL (8160L)
+#define RST9563_CTRL_TS_CLKSEL (8161L)
+#define RST9563_CTRL_TS_CLKSEL_OVERRIDE (8162L)
+#define RST9563_POWER (8163L)
+#define RST9563_POWER_PU_NSEB (8164L)
+#define RST9563_POWER_PU_PHY (8165L)
+#define RST9563_RST (8166L)
+#define RST9563_RST_CORE_MMCM (8167L)
+#define RST9563_RST_DDR4 (8168L)
+#define RST9563_RST_MAC_RX (8169L)
+#define RST9563_RST_PERIPH (8170L)
+#define RST9563_RST_PHY (8171L)
+#define RST9563_RST_PTP (8172L)
+#define RST9563_RST_PTP_MMCM (8173L)
+#define RST9563_RST_RPP (8174L)
+#define RST9563_RST_SDC (8175L)
+#define RST9563_RST_SYS (8176L)
+#define RST9563_RST_SYS_MMCM (8177L)
+#define RST9563_RST_TMC (8178L)
+#define RST9563_RST_TS (8179L)
+#define RST9563_RST_TSM_REF_MMCM (8180L)
+#define RST9563_RST_TS_MMCM (8181L)
+#define RST9563_STAT (8182L)
+#define RST9563_STAT_CORE_MMCM_LOCKED (8183L)
+#define RST9563_STAT_DDR4_MMCM_LOCKED (8184L)
+#define RST9563_STAT_DDR4_PLL_LOCKED (8185L)
+#define RST9563_STAT_PTP_MMCM_LOCKED (8186L)
+#define RST9563_STAT_SYS_MMCM_LOCKED (8187L)
+#define RST9563_STAT_TS_MMCM_LOCKED (8188L)
+#define RST9563_STICKY (8189L)
+#define RST9563_STICKY_CORE_MMCM_UNLOCKED (8190L)
+#define RST9563_STICKY_DDR4_MMCM_UNLOCKED (8191L)
+#define RST9563_STICKY_DDR4_PLL_UNLOCKED (8192L)
+#define RST9563_STICKY_PTP_MMCM_UNLOCKED (8193L)
+#define RST9563_STICKY_SYS_MMCM_UNLOCKED (8194L)
+#define RST9563_STICKY_TS_MMCM_UNLOCKED (8195L)
+/* RTD */
+#define RTD_CTRL (8196L)
+#define RTD_CTRL_ENABLE_RTD (8197L)
+#define RTD_CTRL_ENABLE_TX_FLUSH (8198L)
+#define RTD_CTRL_ENABLE_TX_MACPHY (8199L)
+#define RTD_CTRL_RDPTR_UPDATE_TIMER (8200L)
+#define RTD_CTRL_RESERVED (8201L)
+#define RTD_CTRL_TX_SPEED (8202L)
+#define RTD_DEB_REG1 (8203L)
+#define RTD_DEB_REG1_VALUE (8204L)
+#define RTD_DEB_REG2 (8205L)
+#define RTD_DEB_REG2_VALUE (8206L)
+#define RTD_DEB_REG3 (8207L)
+#define RTD_DEB_REG3_VALUE (8208L)
+#define RTD_HOSTBUFFER_ADR_HI (8209L)
+#define RTD_HOSTBUFFER_ADR_HI_VALUE (8210L)
+#define RTD_HOSTBUFFER_ADR_LO (8211L)
+#define RTD_HOSTBUFFER_ADR_LO_VALUE (8212L)
+#define RTD_RDPTR_ADR_HI (8213L)
+#define RTD_RDPTR_ADR_HI_VALUE (8214L)
+#define RTD_RDPTR_ADR_LO (8215L)
+#define RTD_RDPTR_ADR_LO_VALUE (8216L)
+#define RTD_STATUS (8217L)
+#define RTD_STATUS_HB_EMPTY (8218L)
+#define RTD_STATUS_LHF_EMPTY (8219L)
+#define RTD_STATUS_UNPACKER_STATUS (8220L)
+#define RTD_WRPTR (8221L)
+#define RTD_WRPTR_VALUE (8222L)
+/* RTD_HMP */
+#define RTD_HMP_CTRL (8223L)
+#define RTD_HMP_CTRL_ENABLE_HMP_0 (8224L)
+#define RTD_HMP_CTRL_ENABLE_HMP_1 (8225L)
+#define RTD_HMP_CTRL_ENABLE_HMP_2 (8226L)
+#define RTD_HMP_CTRL_ENABLE_HMP_3 (8227L)
+#define RTD_HMP_CTRL_WRPTR_POLL_TIMER (8228L)
+#define RTD_HMP_DEB_REG1 (8229L)
+#define RTD_HMP_DEB_REG1_VALUE (8230L)
+#define RTD_HMP_DEB_REG2 (8231L)
+#define RTD_HMP_DEB_REG2_VALUE (8232L)
+#define RTD_HMP_DEB_REG3 (8233L)
+#define RTD_HMP_DEB_REG3_VALUE (8234L)
+#define RTD_HMP_STATUS (8235L)
+#define RTD_HMP_STATUS_HMP_ACTIVE (8236L)
+#define RTD_HMP_WRPTR_ADR_HI (8237L)
+#define RTD_HMP_WRPTR_ADR_HI_VALUE (8238L)
+#define RTD_HMP_WRPTR_ADR_LO (8239L)
+#define RTD_HMP_WRPTR_ADR_LO_VALUE (8240L)
+/* RTX */
+#define RTX_CTRL (8241L)
+#define RTX_CTRL_PORT (8242L)
+#define RTX_CTRL_SIZE (8243L)
+#define RTX_STATUS (8244L)
+#define RTX_STATUS_AF (8245L)
+#define RTX_STATUS_BUSY (8246L)
+#define RTX_TXF_CTRL (8247L)
+#define RTX_TXF_CTRL_CNT (8248L)
+#define RTX_TXF_DATA (8249L)
+#define RTX_TXF_DATA_PAYLOAD (8250L)
+#define RXAUI_DEBUG (8268L)
+#define RXAUI_DEBUG_MGT_CV_0 (8269L)
+#define RXAUI_DEBUG_MGT_CV_1 (8270L)
+#define RXAUI_DEBUG_MGT_CV_2 (8271L)
+#define RXAUI_DEBUG_MGT_CV_3 (8272L)
+#define RXAUI_DEBUG_MGT_CV_4 (8273L)
+#define RXAUI_DEBUG_MGT_CV_5 (8274L)
+#define RXAUI_DEBUG_MGT_CV_6 (8275L)
+#define RXAUI_DEBUG_MGT_CV_7 (8276L)
+#define RXAUI_DEBUG_MGT_RXLOCK_0 (8277L)
+#define RXAUI_DEBUG_MGT_RXLOCK_1 (8278L)
+#define RXAUI_DEBUG_MGT_RX_RESET (8279L)
+#define RXAUI_DEBUG_MGT_TX_RESET (8280L)
+#define RXAUI_DEBUG_MMCM1_LOCKED (8281L)
+#define RXAUI_DRP_AD (8282L)
+#define RXAUI_DRP_AD_ADDRESS (8283L)
+#define RXAUI_DRP_AD_DFEEYEDACMON (8284L)
+#define RXAUI_DRP_AD_GTX_NO (8285L)
+#define RXAUI_DRP_AD_READY (8286L)
+#define RXAUI_DRP_AD_RESERVED3 (8287L)
+#define RXAUI_DRP_AD_RESERVED4 (8288L)
+#define RXAUI_DRP_DA (8289L)
+#define RXAUI_DRP_DA_DATA (8290L)
+#define RXAUI_GTX_CONFIG (8291L)
+#define RXAUI_GTX_CONFIG_LOOPBACK (8292L)
+#define RXAUI_GTX_CONFIG_LOOPBACKMUX (8293L)
+#define RXAUI_GTX_CONFIG_PRBSCNTRESET (8294L)
+#define RXAUI_GTX_CONFIG_RESERVED6 (8295L)
+#define RXAUI_GTX_CONFIG_RESERVED7 (8296L)
+#define RXAUI_GTX_CONFIG_RXENPRBSTST (8297L)
+#define RXAUI_GTX_CONFIG_RXEQMIX (8298L)
+#define RXAUI_GTX_CONFIG_TXDIFFCTRL (8299L)
+#define RXAUI_GTX_CONFIG_TXENPRBSTST (8300L)
+#define RXAUI_GTX_CONFIG_TXPOSTEMPHAS (8301L)
+#define RXAUI_GTX_CONFIG_TXPRBSFORCEE (8302L)
+#define RXAUI_GTX_CONFIG_TXPREEMPHASI (8303L)
+#define RXAUI_GTX_STAT (8304L)
+#define RXAUI_GTX_STAT_RESERVED10 (8305L)
+#define RXAUI_GTX_STAT_RESERVED11 (8306L)
+#define RXAUI_GTX_STAT_RESERVED12 (8307L)
+#define RXAUI_GTX_STAT_RESERVED13 (8308L)
+#define RXAUI_GTX_STAT_RESERVED8 (8309L)
+#define RXAUI_GTX_STAT_RESERVED9 (8310L)
+#define RXAUI_GTX_STAT_RXBUFSTATUS0 (8311L)
+#define RXAUI_GTX_STAT_RXBUFSTATUS1 (8312L)
+#define RXAUI_GTX_STAT_RXBYTEISAL_0 (8313L)
+#define RXAUI_GTX_STAT_RXBYTEISAL_1 (8314L)
+#define RXAUI_GTX_STAT_RXBYTEREAL_0 (8315L)
+#define RXAUI_GTX_STAT_RXBYTEREAL_1 (8316L)
+#define RXAUI_GTX_STAT_RXCHANREAL_0 (8317L)
+#define RXAUI_GTX_STAT_RXCHANREAL_1 (8318L)
+#define RXAUI_GTX_STAT_RXCOMMADET_0 (8319L)
+#define RXAUI_GTX_STAT_RXCOMMADET_1 (8320L)
+#define RXAUI_GTX_STAT_RXPRBSERR_0 (8321L)
+#define RXAUI_GTX_STAT_RXPRBSERR_1 (8322L)
+/* SDC */
+#define SDC_CELL_CNT (8612L)
+#define SDC_CELL_CNT_CELL_CNT (8613L)
+#define SDC_CELL_CNT_PERIOD (8614L)
+#define SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD (8615L)
+#define SDC_CTRL (8616L)
+#define SDC_CTRL_INIT (8617L)
+#define SDC_CTRL_RESET_POINTERS (8618L)
+#define SDC_CTRL_RUN_TEST (8619L)
+#define SDC_CTRL_STOP_CLIENT (8620L)
+#define SDC_CTRL_TEST_EN (8621L)
+#define SDC_FILL_LVL (8622L)
+#define SDC_FILL_LVL_FILL_LVL (8623L)
+#define SDC_MAX_FILL_LVL (8624L)
+#define SDC_MAX_FILL_LVL_MAX_FILL_LVL (8625L)
+#define SDC_STAT (8626L)
+#define SDC_STAT_CALIB (8627L)
+#define SDC_STAT_CELL_CNT_STOPPED (8628L)
+#define SDC_STAT_ERR_FOUND (8629L)
+#define SDC_STAT_INIT_DONE (8630L)
+#define SDC_STAT_MMCM_LOCK (8631L)
+#define SDC_STAT_PLL_LOCK (8632L)
+#define SDC_STAT_RESETTING (8633L)
+/* SLC */
+#define SLC_RCP_CTRL (8681L)
+#define SLC_RCP_CTRL_ADR (8682L)
+#define SLC_RCP_CTRL_CNT (8683L)
+#define SLC_RCP_DATA (8684L)
+#define SLC_RCP_DATA_PCAP (8685L)
+#define SLC_RCP_DATA_TAIL_DYN (8686L)
+#define SLC_RCP_DATA_TAIL_OFS (8687L)
+#define SLC_RCP_DATA_TAIL_SLC_EN (8688L)
+/* SLC_LR */
+/* SMM */
+#define SMM_CTRL (8770L)
+#define SMM_CTRL_ENABLE (8771L)
+#define SMM_READY_STATUS (8772L)
+#define SMM_READY_STATUS_D (8773L)
+#define SMM_SEG_INVLD_STICKY_STATUS (8774L)
+#define SMM_SEG_INVLD_STICKY_STATUS_D (8775L)
+#define SMM_SEG_MEM_CTRL (8776L)
+#define SMM_SEG_MEM_CTRL_A (8777L)
+#define SMM_SEG_MEM_CTRL_CNT (8778L)
+#define SMM_SEG_MEM_DATA (8779L)
+#define SMM_SEG_MEM_DATA_PHYADDR (8780L)
+#define SMM_SEG_MEM_DATA_SIZE (8781L)
+#define SMM_START_SEG_MEM_CTRL (8782L)
+#define SMM_START_SEG_MEM_CTRL_A (8783L)
+#define SMM_START_SEG_MEM_CTRL_CNT (8784L)
+#define SMM_START_SEG_MEM_DATA (8785L)
+#define SMM_START_SEG_MEM_DATA_SEG (8786L)
+/* SPIM */
+#define SPIM_CFG (8793L)
+#define SPIM_CFG_PRE (8794L)
+#define SPIM_CMD (8795L)
+#define SPIM_CMD_ADDR (8796L)
+#define SPIM_CMD_CMD (8797L)
+#define SPIM_CMD_DATA (8798L)
+#define SPIM_CONF0 (8799L)
+#define SPIM_CONF0_BYTE_PACE (8800L)
+#define SPIM_CONF0_MIRROR_EN (8801L)
+#define SPIM_CONF0_MSB_FIRST (8802L)
+#define SPIM_CONF0_PRESCAL_CLK (8803L)
+#define SPIM_CONF0_RESTART (8804L)
+#define SPIM_CONF0_RST (8805L)
+#define SPIM_CONF0_SYNC_MON_EN (8806L)
+#define SPIM_CONF1 (8807L)
+#define SPIM_CONF1_MIRROR_PACE (8808L)
+#define SPIM_CONF1_MIRROR_SCAN (8809L)
+#define SPIM_CONF1_SYNCTIMEOUT (8810L)
+#define SPIM_CONF2 (8811L)
+#define SPIM_CONF2_MIRROR_PRESC (8812L)
+#define SPIM_CONF2_OPCODE_RD (8813L)
+#define SPIM_CONF2_OPCODE_WR (8814L)
+#define SPIM_CONF3 (8815L)
+#define SPIM_CONF3_MIRROR_RDADR (8816L)
+#define SPIM_CONF3_MIRROR_WRADR (8817L)
+#define SPIM_CR (8818L)
+#define SPIM_CR_EN (8819L)
+#define SPIM_CR_LOOP (8820L)
+#define SPIM_CR_RXRST (8821L)
+#define SPIM_CR_TXRST (8822L)
+#define SPIM_DRR (8823L)
+#define SPIM_DRR_DRR (8824L)
+#define SPIM_DTR (8825L)
+#define SPIM_DTR_DTR (8826L)
+#define SPIM_REPLY (8827L)
+#define SPIM_REPLY_RDDATA (8828L)
+#define SPIM_SR (8829L)
+#define SPIM_SR_DONE (8830L)
+#define SPIM_SR_RXEMPTY (8831L)
+#define SPIM_SR_RXFULL (8832L)
+#define SPIM_SR_RXLVL (8833L)
+#define SPIM_SR_TXEMPTY (8834L)
+#define SPIM_SR_TXFULL (8835L)
+#define SPIM_SR_TXLVL (8836L)
+#define SPIM_SRR (8837L)
+#define SPIM_SRR_RST (8838L)
+#define SPIM_STATUS (8839L)
+#define SPIM_STATUS_CMDPENDING (8840L)
+#define SPIM_STATUS_RESERVED (8841L)
+#define SPIM_STATUS_RESYNCDETECT (8842L)
+#define SPIM_STATUS_RESYNCING (8843L)
+/* SPIS */
+#define SPIS_CR (8844L)
+#define SPIS_CR_DEBUG (8845L)
+#define SPIS_CR_EN (8846L)
+#define SPIS_CR_LOOP (8847L)
+#define SPIS_CR_RXRST (8848L)
+#define SPIS_CR_TXRST (8849L)
+#define SPIS_DRR (8850L)
+#define SPIS_DRR_DRR (8851L)
+#define SPIS_DTR (8852L)
+#define SPIS_DTR_DTR (8853L)
+#define SPIS_RAM_CTRL (8854L)
+#define SPIS_RAM_CTRL_ADR (8855L)
+#define SPIS_RAM_CTRL_CNT (8856L)
+#define SPIS_RAM_DATA (8857L)
+#define SPIS_RAM_DATA_DATA (8858L)
+#define SPIS_SR (8859L)
+#define SPIS_SR_DONE (8860L)
+#define SPIS_SR_FRAME_ERR (8861L)
+#define SPIS_SR_READ_ERR (8862L)
+#define SPIS_SR_RXEMPTY (8863L)
+#define SPIS_SR_RXFULL (8864L)
+#define SPIS_SR_RXLVL (8865L)
+#define SPIS_SR_TXEMPTY (8866L)
+#define SPIS_SR_TXFULL (8867L)
+#define SPIS_SR_TXLVL (8868L)
+#define SPIS_SR_WRITE_ERR (8869L)
+#define SPIS_SRR (8870L)
+#define SPIS_SRR_RST (8871L)
+/* STA */
+#define STA_BYTE (8872L)
+#define STA_BYTE_CNT (8873L)
+#define STA_CFG (8874L)
+#define STA_CFG_CNT_CLEAR (8875L)
+#define STA_CFG_CNT_FRZ (8876L)
+#define STA_CFG_DMA_ENA (8877L)
+#define STA_CFG_TX_DISABLE (8878L)
+#define STA_CV_ERR (8879L)
+#define STA_CV_ERR_CNT (8880L)
+#define STA_FCS_ERR (8881L)
+#define STA_FCS_ERR_CNT (8882L)
+#define STA_HOST_ADR_LSB (8883L)
+#define STA_HOST_ADR_LSB_LSB (8884L)
+#define STA_HOST_ADR_MSB (8885L)
+#define STA_HOST_ADR_MSB_MSB (8886L)
+#define STA_PCKT (8887L)
+#define STA_PCKT_CNT (8888L)
+#define STA_STATUS (8889L)
+#define STA_STATUS_STAT_TOGGLE_MISSED (8890L)
+/* TBH */
+#define TBH_CTRL (9103L)
+#define TBH_CTRL_DISABLE_LR_LB (9104L)
+#define TBH_CTRL_ENABLE (9105L)
+#define TBH_CTRL_PORT (9106L)
+#define TBH_CTRL_PORT_AUS (9107L)
+#define TBH_CTRL_SEGMENT (9108L)
+#define TBH_CTRL_SEGMENT_SIZE (9109L)
+#define TBH_DBG_DLN_ERR (9110L)
+#define TBH_DBG_DLN_ERR_E (9111L)
+#define TBH_DBG_DLN_ERR_HB (9112L)
+#define TBH_DBG_ILLEGAL_RANGE (9113L)
+#define TBH_DBG_ILLEGAL_RANGE_E (9114L)
+#define TBH_DBG_ILLEGAL_RANGE_HB (9115L)
+#define TBH_DBG_MAX_PCI_QUIET (9116L)
+#define TBH_DBG_MAX_PCI_QUIET_CYCLES (9117L)
+#define TBH_DISABLE (9118L)
+#define TBH_DISABLE_DISABLE (9119L)
+#define TBH_DISABLE_HB (9120L)
+#define TBH_HB_DSC_MEM_CTRL (9121L)
+#define TBH_HB_DSC_MEM_CTRL_ADR (9122L)
+#define TBH_HB_DSC_MEM_CTRL_CNT (9123L)
+#define TBH_HB_DSC_MEM_DATA (9124L)
+#define TBH_HB_DSC_MEM_DATA_DT (9125L)
+#define TBH_HB_DSC_MEM_DATA_FCS (9126L)
+#define TBH_HB_DSC_MEM_DATA_FCS_CTL_POS (9127L)
+#define TBH_HB_DSC_MEM_DATA_FCS_CTL_USE (9128L)
+#define TBH_HB_DSC_MEM_DATA_IG_POS (9129L)
+#define TBH_HB_DSC_MEM_DATA_IG_USE (9130L)
+#define TBH_HB_DSC_MEM_DATA_OCS_CMD_POS (9131L)
+#define TBH_HB_DSC_MEM_DATA_OCS_CMD_USE (9132L)
+#define TBH_HB_DSC_MEM_DATA_OFS0_POS (9133L)
+#define TBH_HB_DSC_MEM_DATA_OFS0_USE (9134L)
+#define TBH_HB_DSC_MEM_DATA_OFS1_POS (9135L)
+#define TBH_HB_DSC_MEM_DATA_OFS1_USE (9136L)
+#define TBH_HB_DSC_MEM_DATA_OFS2_POS (9137L)
+#define TBH_HB_DSC_MEM_DATA_OFS2_USE (9138L)
+#define TBH_HB_DSC_MEM_DATA_PFD (9139L)
+#define TBH_HB_DSC_MEM_DATA_PORT (9140L)
+#define TBH_HB_DSC_MEM_DATA_PORT_MASK (9141L)
+#define TBH_HB_DSC_MEM_DATA_PORT_POS (9142L)
+#define TBH_HB_DSC_MEM_DATA_SET_CLOCK_POS (9143L)
+#define TBH_HB_DSC_MEM_DATA_SET_CLOCK_USE (9144L)
+#define TBH_HB_DSC_MEM_DATA_SW_TFD_TYPE_POS (9145L)
+#define TBH_HB_DSC_MEM_DATA_SW_TFD_TYPE_USE (9146L)
+#define TBH_HB_DSC_MEM_DATA_TS_APPEND (9147L)
+#define TBH_HB_DSC_MEM_DATA_TS_FMT (9148L)
+#define TBH_HB_DSC_MEM_DATA_TS_INJECT_POS (9149L)
+#define TBH_HB_DSC_MEM_DATA_TS_INJECT_USE (9150L)
+#define TBH_HB_DSC_MEM_DATA_TX_NOW_POS (9151L)
+#define TBH_HB_DSC_MEM_DATA_TX_NOW_USE (9152L)
+#define TBH_HB_DSC_MEM_DATA_TX_ON_TS (9153L)
+#define TBH_HB_DSC_MEM_DATA_WL_USE (9154L)
+#define TBH_HB_INFO_MEM_CTRL (9155L)
+#define TBH_HB_INFO_MEM_CTRL_A (9156L)
+#define TBH_HB_INFO_MEM_CTRL_CNT (9157L)
+#define TBH_HB_INFO_MEM_DATA (9158L)
+#define TBH_HB_INFO_MEM_DATA_SIZE (9159L)
+#define TBH_HB_PORTS_MEM_CTRL (9160L)
+#define TBH_HB_PORTS_MEM_CTRL_A (9161L)
+#define TBH_HB_PORTS_MEM_CTRL_CNT (9162L)
+#define TBH_HB_PORTS_MEM_DATA (9163L)
+#define TBH_HB_PORTS_MEM_DATA_MAPPING (9164L)
+#define TBH_PORT_MAPPING (9165L)
+#define TBH_PORT_MAPPING_P0 (9166L)
+#define TBH_PORT_MAPPING_P1 (9167L)
+#define TBH_PORT_MAPPING_P2 (9168L)
+#define TBH_PORT_MAPPING_P3 (9169L)
+#define TBH_PORT_MAPPING_P4 (9170L)
+#define TBH_PORT_MAPPING_P5 (9171L)
+#define TBH_PORT_MAPPING_P6 (9172L)
+#define TBH_PORT_MAPPING_P7 (9173L)
+#define TBH_SET_RD_POINTER (9174L)
+#define TBH_SET_RD_POINTER_HB (9175L)
+#define TBH_SET_RD_POINTER_OFFSET (9176L)
+#define TBH_STATUS (9177L)
+#define TBH_STATUS_STOPPED (9178L)
+/* TEMPMON */
+#define TEMPMON_ALARMS (9179L)
+#define TEMPMON_ALARMS_OT (9180L)
+#define TEMPMON_ALARMS_OT_OVERWR (9181L)
+#define TEMPMON_ALARMS_OT_OVERWRVAL (9182L)
+#define TEMPMON_ALARMS_TEMP (9183L)
+#define TEMPMON_STAT (9184L)
+#define TEMPMON_STAT_TEMP (9185L)
+/* TINT */
+#define TINT_CTRL (9186L)
+#define TINT_CTRL_INTERVAL (9187L)
+#define TINT_STATUS (9188L)
+#define TINT_STATUS_DELAYED (9189L)
+#define TINT_STATUS_SKIPPED (9190L)
+/* TMC */
+#define TMC_PORT_RPL (9191L)
+#define TMC_PORT_RPL_P0 (9192L)
+#define TMC_PORT_RPL_P1 (9193L)
+#define TMC_PORT_RPL_P2 (9194L)
+#define TMC_PORT_RPL_P3 (9195L)
+#define TMC_PORT_RPL_P4 (9196L)
+#define TMC_PORT_RPL_P5 (9197L)
+#define TMC_PORT_RPL_P6 (9198L)
+#define TMC_PORT_RPL_P7 (9199L)
+/* TSM */
+#define TSM_ADJ_FINE_N (9200L)
+#define TSM_ADJ_FINE_N_2DY (9201L)
+#define TSM_ADJ_FINE_N_2DY2DX (9202L)
+#define TSM_ADJ_FINE_P (9203L)
+#define TSM_ADJ_FINE_P_2DY (9204L)
+#define TSM_ADJ_FINE_P_2DY2DX (9205L)
+#define TSM_ADJ_LIMIT_HI (9206L)
+#define TSM_ADJ_LIMIT_HI_LIMIT (9207L)
+#define TSM_ADJ_LIMIT_LO (9208L)
+#define TSM_ADJ_LIMIT_LO_LIMIT (9209L)
+#define TSM_BASIC_2DY (9210L)
+#define TSM_BASIC_2DY_2DY (9211L)
+#define TSM_BASIC_2DY2DX (9212L)
+#define TSM_BASIC_2DY2DX_2DY2DX (9213L)
+#define TSM_CON0_CONFIG (9214L)
+#define TSM_CON0_CONFIG_BLIND (9215L)
+#define TSM_CON0_CONFIG_DC_SRC (9216L)
+#define TSM_CON0_CONFIG_PORT (9217L)
+#define TSM_CON0_CONFIG_PPSIN_2_5V (9218L)
+#define TSM_CON0_CONFIG_SAMPLE_EDGE (9219L)
+#define TSM_CON0_INTERFACE (9220L)
+#define TSM_CON0_INTERFACE_EX_TERM (9221L)
+#define TSM_CON0_INTERFACE_IN_REF_PWM (9222L)
+#define TSM_CON0_INTERFACE_PWM_ENA (9223L)
+#define TSM_CON0_INTERFACE_RESERVED (9224L)
+#define TSM_CON0_INTERFACE_VTERM_PWM (9225L)
+#define TSM_CON0_SAMPLE_HI (9226L)
+#define TSM_CON0_SAMPLE_HI_SEC (9227L)
+#define TSM_CON0_SAMPLE_LO (9228L)
+#define TSM_CON0_SAMPLE_LO_NS (9229L)
+#define TSM_CON1_CONFIG (9230L)
+#define TSM_CON1_CONFIG_BLIND (9231L)
+#define TSM_CON1_CONFIG_DC_SRC (9232L)
+#define TSM_CON1_CONFIG_PORT (9233L)
+#define TSM_CON1_CONFIG_PPSIN_2_5V (9234L)
+#define TSM_CON1_CONFIG_SAMPLE_EDGE (9235L)
+#define TSM_CON1_SAMPLE_HI (9236L)
+#define TSM_CON1_SAMPLE_HI_SEC (9237L)
+#define TSM_CON1_SAMPLE_LO (9238L)
+#define TSM_CON1_SAMPLE_LO_NS (9239L)
+#define TSM_CON2_CONFIG (9240L)
+#define TSM_CON2_CONFIG_BLIND (9241L)
+#define TSM_CON2_CONFIG_DC_SRC (9242L)
+#define TSM_CON2_CONFIG_PORT (9243L)
+#define TSM_CON2_CONFIG_PPSIN_2_5V (9244L)
+#define TSM_CON2_CONFIG_SAMPLE_EDGE (9245L)
+#define TSM_CON2_SAMPLE_HI (9246L)
+#define TSM_CON2_SAMPLE_HI_SEC (9247L)
+#define TSM_CON2_SAMPLE_LO (9248L)
+#define TSM_CON2_SAMPLE_LO_NS (9249L)
+#define TSM_CON3_CONFIG (9250L)
+#define TSM_CON3_CONFIG_BLIND (9251L)
+#define TSM_CON3_CONFIG_PORT (9252L)
+#define TSM_CON3_CONFIG_SAMPLE_EDGE (9253L)
+#define TSM_CON3_SAMPLE_HI (9254L)
+#define TSM_CON3_SAMPLE_HI_SEC (9255L)
+#define TSM_CON3_SAMPLE_LO (9256L)
+#define TSM_CON3_SAMPLE_LO_NS (9257L)
+#define TSM_CON4_CONFIG (9258L)
+#define TSM_CON4_CONFIG_BLIND (9259L)
+#define TSM_CON4_CONFIG_PORT (9260L)
+#define TSM_CON4_CONFIG_SAMPLE_EDGE (9261L)
+#define TSM_CON4_SAMPLE_HI (9262L)
+#define TSM_CON4_SAMPLE_HI_SEC (9263L)
+#define TSM_CON4_SAMPLE_LO (9264L)
+#define TSM_CON4_SAMPLE_LO_NS (9265L)
+#define TSM_CON5_CONFIG (9266L)
+#define TSM_CON5_CONFIG_BLIND (9267L)
+#define TSM_CON5_CONFIG_PORT (9268L)
+#define TSM_CON5_CONFIG_SAMPLE_EDGE (9269L)
+#define TSM_CON5_SAMPLE_HI (9270L)
+#define TSM_CON5_SAMPLE_HI_SEC (9271L)
+#define TSM_CON5_SAMPLE_LO (9272L)
+#define TSM_CON5_SAMPLE_LO_TIME (9273L)
+#define TSM_CON6_CONFIG (9274L)
+#define TSM_CON6_CONFIG_BLIND (9275L)
+#define TSM_CON6_CONFIG_PORT (9276L)
+#define TSM_CON6_CONFIG_SAMPLE_EDGE (9277L)
+#define TSM_CON6_SAMPLE_HI (9278L)
+#define TSM_CON6_SAMPLE_HI_SEC (9279L)
+#define TSM_CON6_SAMPLE_LO (9280L)
+#define TSM_CON6_SAMPLE_LO_NS (9281L)
+#define TSM_CON7_HOST_SAMPLE_HI (9282L)
+#define TSM_CON7_HOST_SAMPLE_HI_SEC (9283L)
+#define TSM_CON7_HOST_SAMPLE_LO (9284L)
+#define TSM_CON7_HOST_SAMPLE_LO_NS (9285L)
+#define TSM_CONFIG (9286L)
+#define TSM_CONFIG_NTTS_SRC (9287L)
+#define TSM_CONFIG_NTTS_SYNC (9288L)
+#define TSM_CONFIG_TIMESET_EDGE (9289L)
+#define TSM_CONFIG_TIMESET_SRC (9290L)
+#define TSM_CONFIG_TIMESET_UP (9291L)
+#define TSM_CONFIG_TS_FORMAT (9292L)
+#define TSM_CTRL (9293L)
+#define TSM_CTRL_DCEN_CON0 (9294L)
+#define TSM_CTRL_DCEN_CON1 (9295L)
+#define TSM_CTRL_DCEN_CON2 (9296L)
+#define TSM_CTRL_FORMAT (9297L)
+#define TSM_CTRL_HIGH_SAMPLE (9298L)
+#define TSM_CTRL_LED_CON0 (9299L)
+#define TSM_CTRL_LED_CON1 (9300L)
+#define TSM_CTRL_LED_CON2 (9301L)
+#define TSM_CTRL_MASTER_STAT (9302L)
+#define TSM_CTRL_OEN_CON0 (9303L)
+#define TSM_CTRL_OEN_CON1 (9304L)
+#define TSM_CTRL_OEN_CON2 (9305L)
+#define TSM_CTRL_PPSEN (9306L)
+#define TSM_CTRL_PPS_NEGEDGE (9307L)
+#define TSM_CTRL_PPS_TIME_UP (9308L)
+#define TSM_CTRL_PTP_TIME_UP (9309L)
+#define TSM_CTRL_RESERVED (9310L)
+#define TSM_CTRL_SEL_EXTSRC (9311L)
+#define TSM_CTRL_SYNEN (9312L)
+#define TSM_CTRL_TS_CON0 (9313L)
+#define TSM_CTRL_TS_CON1 (9314L)
+#define TSM_CTRL_TS_CON2 (9315L)
+#define TSM_EXT_STAT (9316L)
+#define TSM_EXT_STAT_STAT (9317L)
+#define TSM_EXT_TIME_HI (9318L)
+#define TSM_EXT_TIME_HI_TIME (9319L)
+#define TSM_EXT_TIME_LO (9320L)
+#define TSM_EXT_TIME_LO_TIME (9321L)
+#define TSM_INTERFACE (9322L)
+#define TSM_INTERFACE_EX_TERM (9323L)
+#define TSM_INTERFACE_IN_REF_PWM (9324L)
+#define TSM_INTERFACE_PWM_ENA (9325L)
+#define TSM_INTERFACE_RESERVED (9326L)
+#define TSM_INTERFACE_VTERM_PWM (9327L)
+#define TSM_INT_CONFIG (9328L)
+#define TSM_INT_CONFIG_AUTO_DISABLE (9329L)
+#define TSM_INT_CONFIG_MASK (9330L)
+#define TSM_INT_STAT (9331L)
+#define TSM_INT_STAT_CAUSE (9332L)
+#define TSM_INT_STAT_ENABLE (9333L)
+#define TSM_INT_TIME_HI (9334L)
+#define TSM_INT_TIME_HI_TIME (9335L)
+#define TSM_INT_TIME_LO (9336L)
+#define TSM_INT_TIME_LO_TIME (9337L)
+#define TSM_LED (9338L)
+#define TSM_LED_LED0_BG_COLOR (9339L)
+#define TSM_LED_LED0_COLOR (9340L)
+#define TSM_LED_LED0_MODE (9341L)
+#define TSM_LED_LED0_SRC (9342L)
+#define TSM_LED_LED1_BG_COLOR (9343L)
+#define TSM_LED_LED1_COLOR (9344L)
+#define TSM_LED_LED1_MODE (9345L)
+#define TSM_LED_LED1_SRC (9346L)
+#define TSM_LED_LED2_BG_COLOR (9347L)
+#define TSM_LED_LED2_COLOR (9348L)
+#define TSM_LED_LED2_MODE (9349L)
+#define TSM_LED_LED2_SRC (9350L)
+#define TSM_NTTS_CONFIG (9351L)
+#define TSM_NTTS_CONFIG_AUTO_HARDSET (9352L)
+#define TSM_NTTS_CONFIG_EXT_CLK_ADJ (9353L)
+#define TSM_NTTS_CONFIG_HIGH_SAMPLE (9354L)
+#define TSM_NTTS_CONFIG_TS_SRC_FORMAT (9355L)
+#define TSM_NTTS_CTRL (9356L)
+#define TSM_NTTS_CTRL_NTTS_CMD (9357L)
+#define TSM_NTTS_DATA_HI (9358L)
+#define TSM_NTTS_DATA_HI_DATA (9359L)
+#define TSM_NTTS_DATA_LO (9360L)
+#define TSM_NTTS_DATA_LO_DATA (9361L)
+#define TSM_NTTS_EXT_STAT (9362L)
+#define TSM_NTTS_EXT_STAT_MASTER_ID (9363L)
+#define TSM_NTTS_EXT_STAT_MASTER_REV (9364L)
+#define TSM_NTTS_EXT_STAT_MASTER_STAT (9365L)
+#define TSM_NTTS_LIMIT_HI (9366L)
+#define TSM_NTTS_LIMIT_HI_SEC (9367L)
+#define TSM_NTTS_LIMIT_LO (9368L)
+#define TSM_NTTS_LIMIT_LO_NS (9369L)
+#define TSM_NTTS_OFFSET (9370L)
+#define TSM_NTTS_OFFSET_NS (9371L)
+#define TSM_NTTS_SAMPLE_HI (9372L)
+#define TSM_NTTS_SAMPLE_HI_SEC (9373L)
+#define TSM_NTTS_SAMPLE_LO (9374L)
+#define TSM_NTTS_SAMPLE_LO_NS (9375L)
+#define TSM_NTTS_STAT (9376L)
+#define TSM_NTTS_STAT_NTTS_VALID (9377L)
+#define TSM_NTTS_STAT_SIGNAL_LOST (9378L)
+#define TSM_NTTS_STAT_SYNC_LOST (9379L)
+#define TSM_NTTS_TS_T0_HI (9380L)
+#define TSM_NTTS_TS_T0_HI_TIME (9381L)
+#define TSM_NTTS_TS_T0_LO (9382L)
+#define TSM_NTTS_TS_T0_LO_TIME (9383L)
+#define TSM_NTTS_TS_T0_OFFSET (9384L)
+#define TSM_NTTS_TS_T0_OFFSET_COUNT (9385L)
+#define TSM_OFFSET_HI (9386L)
+#define TSM_OFFSET_HI_OFFSET (9387L)
+#define TSM_OFFSET_LO (9388L)
+#define TSM_OFFSET_LO_OFFSET (9389L)
+#define TSM_PB_CTRL (9390L)
+#define TSM_PB_CTRL_INSTMEM_WR (9391L)
+#define TSM_PB_CTRL_RESET (9392L)
+#define TSM_PB_CTRL_RST (9393L)
+#define TSM_PB_INSTMEM (9394L)
+#define TSM_PB_INSTMEM_ADDR (9395L)
+#define TSM_PB_INSTMEM_DATA (9396L)
+#define TSM_PB_INSTMEM_MEM_ADDR (9397L)
+#define TSM_PB_INSTMEM_MEM_DATA (9398L)
+#define TSM_PI_CTRL_I (9399L)
+#define TSM_PI_CTRL_I_VAL (9400L)
+#define TSM_PI_CTRL_KI (9401L)
+#define TSM_PI_CTRL_KI_GAIN (9402L)
+#define TSM_PI_CTRL_KP (9403L)
+#define TSM_PI_CTRL_KP_GAIN (9404L)
+#define TSM_PI_CTRL_SHL (9405L)
+#define TSM_PI_CTRL_SHL_VAL (9406L)
+#define TSM_RSYNC_COUNT (9407L)
+#define TSM_RSYNC_COUNT_COUNT (9408L)
+#define TSM_STAT (9409L)
+#define TSM_STAT_EXT_SRC_OK (9410L)
+#define TSM_STAT_HARD_SYNC (9411L)
+#define TSM_STAT_INSYNC (9412L)
+#define TSM_STAT_LINK_ACTIVE (9413L)
+#define TSM_STAT_LINK_CON0 (9414L)
+#define TSM_STAT_LINK_CON1 (9415L)
+#define TSM_STAT_LINK_CON2 (9416L)
+#define TSM_STAT_LINK_CON3 (9417L)
+#define TSM_STAT_LINK_CON4 (9418L)
+#define TSM_STAT_LINK_CON5 (9419L)
+#define TSM_STAT_NTTS_INSYNC (9420L)
+#define TSM_STAT_PTP_MI_PRESENT (9421L)
+#define TSM_TIMER_CTRL (9422L)
+#define TSM_TIMER_CTRL_TIMER_EN_T0 (9423L)
+#define TSM_TIMER_CTRL_TIMER_EN_T1 (9424L)
+#define TSM_TIMER_CTRL_TRIGGER_SEL (9425L)
+#define TSM_TIMER_D_T0 (9426L)
+#define TSM_TIMER_D_T0_MAX_COUNT (9427L)
+#define TSM_TIMER_T0 (9428L)
+#define TSM_TIMER_T0_MAX_COUNT (9429L)
+#define TSM_TIMER_T1 (9430L)
+#define TSM_TIMER_T1_MAX_COUNT (9431L)
+#define TSM_TIMESTAMP_HI (9432L)
+#define TSM_TIMESTAMP_HI_TIME (9433L)
+#define TSM_TIMESTAMP_LO (9434L)
+#define TSM_TIMESTAMP_LO_TIME (9435L)
+#define TSM_TIME_HARDSET_HI (9436L)
+#define TSM_TIME_HARDSET_HI_TIME (9437L)
+#define TSM_TIME_HARDSET_LO (9438L)
+#define TSM_TIME_HARDSET_LO_TIME (9439L)
+#define TSM_TIME_HI (9440L)
+#define TSM_TIME_HI_SEC (9441L)
+#define TSM_TIME_HI_TIME (9442L)
+#define TSM_TIME_LO (9443L)
+#define TSM_TIME_LO_NS (9444L)
+#define TSM_TIME_RATE_ADJ (9445L)
+#define TSM_TIME_RATE_ADJ_FRACTION (9446L)
+#define TSM_TS_HI (9447L)
+#define TSM_TS_HI_TIME (9448L)
+#define TSM_TS_LO (9449L)
+#define TSM_TS_LO_TIME (9450L)
+#define TSM_TS_OFFSET (9451L)
+#define TSM_TS_OFFSET_NS (9452L)
+#define TSM_TS_STAT (9453L)
+#define TSM_TS_STAT_OVERRUN (9454L)
+#define TSM_TS_STAT_SAMPLES (9455L)
+#define TSM_TS_STAT_HI_OFFSET (9456L)
+#define TSM_TS_STAT_HI_OFFSET_NS (9457L)
+#define TSM_TS_STAT_LO_OFFSET (9458L)
+#define TSM_TS_STAT_LO_OFFSET_NS (9459L)
+#define TSM_TS_STAT_TAR_HI (9460L)
+#define TSM_TS_STAT_TAR_HI_SEC (9461L)
+#define TSM_TS_STAT_TAR_LO (9462L)
+#define TSM_TS_STAT_TAR_LO_NS (9463L)
+#define TSM_TS_STAT_X (9464L)
+#define TSM_TS_STAT_X_NS (9465L)
+#define TSM_TS_STAT_X2_HI (9466L)
+#define TSM_TS_STAT_X2_HI_NS (9467L)
+#define TSM_TS_STAT_X2_LO (9468L)
+#define TSM_TS_STAT_X2_LO_NS (9469L)
+#define TSM_UTC_OFFSET (9470L)
+#define TSM_UTC_OFFSET_SEC (9471L)
+
+#endif /* _NTHW_FPGA_REGISTERS_DEFS_ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 2/8] net/ntnic: adds core registers and fpga functionality
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 13:25 ` [PATCH 3/8] net/ntnic: adds NT200A02 adapter support Mykola Kostenok
` (19 subsequent siblings)
20 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
Includes functionality to reset, initialize, program, and collect
stats for the NTNIC FPGA.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/ntnic/include/nthw_bus.h | 10 +
drivers/net/ntnic/meson.build | 32 +
.../net/ntnic/nthw/core/nthw_clock_profiles.c | 9 +
.../net/ntnic/nthw/core/nthw_clock_profiles.h | 39 +
drivers/net/ntnic/nthw/core/nthw_core.h | 31 +
drivers/net/ntnic/nthw/core/nthw_fpga.c | 914 +++++++++
drivers/net/ntnic/nthw/core/nthw_fpga.h | 47 +
.../net/ntnic/nthw/core/nthw_fpga_nt200a0x.c | 46 +
.../net/ntnic/nthw/core/nthw_fpga_nt200a0x.h | 14 +
drivers/net/ntnic/nthw/core/nthw_fpga_rst.c | 10 +
drivers/net/ntnic/nthw/core/nthw_fpga_rst.h | 17 +
.../net/ntnic/nthw/core/nthw_fpga_rst9563.c | 241 +++
.../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c | 674 +++++++
.../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h | 89 +
drivers/net/ntnic/nthw/core/nthw_gpio_phy.c | 271 +++
drivers/net/ntnic/nthw/core/nthw_gpio_phy.h | 57 +
drivers/net/ntnic/nthw/core/nthw_hif.c | 342 ++++
drivers/net/ntnic/nthw/core/nthw_hif.h | 156 ++
drivers/net/ntnic/nthw/core/nthw_iic.c | 570 ++++++
drivers/net/ntnic/nthw/core/nthw_iic.h | 101 +
drivers/net/ntnic/nthw/core/nthw_mac_pcs.c | 1034 ++++++++++
drivers/net/ntnic/nthw/core/nthw_mac_pcs.h | 261 +++
.../net/ntnic/nthw/core/nthw_mac_pcs_xxv.c | 1631 ++++++++++++++++
.../net/ntnic/nthw/core/nthw_mac_pcs_xxv.h | 291 +++
drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c | 121 ++
drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h | 51 +
drivers/net/ntnic/nthw/core/nthw_pci_ta.c | 99 +
drivers/net/ntnic/nthw/core/nthw_pci_ta.h | 40 +
drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c | 127 ++
drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h | 55 +
drivers/net/ntnic/nthw/core/nthw_pcie3.c | 274 +++
drivers/net/ntnic/nthw/core/nthw_pcie3.h | 100 +
drivers/net/ntnic/nthw/core/nthw_sdc.c | 177 ++
drivers/net/ntnic/nthw/core/nthw_sdc.h | 43 +
drivers/net/ntnic/nthw/core/nthw_si5340.c | 206 ++
drivers/net/ntnic/nthw/core/nthw_si5340.h | 34 +
drivers/net/ntnic/nthw/core/nthw_spi_v3.c | 380 ++++
drivers/net/ntnic/nthw/core/nthw_spi_v3.h | 106 ++
drivers/net/ntnic/nthw/core/nthw_spim.c | 117 ++
drivers/net/ntnic/nthw/core/nthw_spim.h | 52 +
drivers/net/ntnic/nthw/core/nthw_spis.c | 147 ++
drivers/net/ntnic/nthw/core/nthw_spis.h | 63 +
drivers/net/ntnic/nthw/core/nthw_tsm.c | 179 ++
drivers/net/ntnic/nthw/core/nthw_tsm.h | 53 +
drivers/net/ntnic/nthw/nthw_dbs.c | 1301 +++++++++++++
drivers/net/ntnic/nthw/nthw_dbs.h | 313 +++
drivers/net/ntnic/nthw/nthw_drv.h | 82 +
drivers/net/ntnic/nthw/nthw_epp.c | 335 ++++
drivers/net/ntnic/nthw/nthw_epp.h | 99 +
drivers/net/ntnic/nthw/nthw_fpga_model.c | 1677 +++++++++++++++++
drivers/net/ntnic/nthw/nthw_fpga_model.h | 308 +++
drivers/net/ntnic/nthw/nthw_helper.h | 21 +
drivers/net/ntnic/nthw/nthw_platform.c | 35 +
drivers/net/ntnic/nthw/nthw_platform_drv.h | 42 +
drivers/net/ntnic/nthw/nthw_profile.h | 15 +
drivers/net/ntnic/nthw/nthw_rac.c | 976 ++++++++++
drivers/net/ntnic/nthw/nthw_rac.h | 159 ++
drivers/net/ntnic/nthw/nthw_register.h | 2 +
drivers/net/ntnic/nthw/nthw_stat.c | 266 +++
drivers/net/ntnic/nthw/nthw_stat.h | 72 +
drivers/net/ntnic/ntlog/include/ntlog.h | 162 ++
drivers/net/ntnic/ntlog/ntlog.c | 114 ++
drivers/net/ntnic/ntutil/include/nt_util.h | 71 +
drivers/net/ntnic/ntutil/nt_util.c | 77 +
64 files changed, 15438 insertions(+)
create mode 100644 drivers/net/ntnic/include/nthw_bus.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_core.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.h
create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.c
create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.h
create mode 100644 drivers/net/ntnic/nthw/nthw_drv.h
create mode 100644 drivers/net/ntnic/nthw/nthw_epp.c
create mode 100644 drivers/net/ntnic/nthw/nthw_epp.h
create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.c
create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.h
create mode 100644 drivers/net/ntnic/nthw/nthw_helper.h
create mode 100644 drivers/net/ntnic/nthw/nthw_platform.c
create mode 100644 drivers/net/ntnic/nthw/nthw_platform_drv.h
create mode 100644 drivers/net/ntnic/nthw/nthw_profile.h
create mode 100644 drivers/net/ntnic/nthw/nthw_rac.c
create mode 100644 drivers/net/ntnic/nthw/nthw_rac.h
create mode 100644 drivers/net/ntnic/nthw/nthw_stat.c
create mode 100644 drivers/net/ntnic/nthw/nthw_stat.h
create mode 100644 drivers/net/ntnic/ntlog/include/ntlog.h
create mode 100644 drivers/net/ntnic/ntlog/ntlog.c
create mode 100644 drivers/net/ntnic/ntutil/include/nt_util.h
create mode 100644 drivers/net/ntnic/ntutil/nt_util.c
diff --git a/drivers/net/ntnic/include/nthw_bus.h b/drivers/net/ntnic/include/nthw_bus.h
new file mode 100644
index 0000000000..975cc95e78
--- /dev/null
+++ b/drivers/net/ntnic/include/nthw_bus.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_BUS_H__
+#define __NTHW_BUS_H__
+
+typedef uint8_t rab_bus_id_t;
+
+#endif /* __NTHW_BUS_H__ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 99569c2843..65064f44ab 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -10,13 +10,45 @@ cflags += [
includes = [
include_directories('.'),
include_directories('include'),
+ include_directories('ntlog/include'),
+ include_directories('ntutil/include'),
include_directories('nthw'),
+ include_directories('nthw/core'),
include_directories('nthw/supported'),
]
# all sources
sources = files(
+ 'nthw/core/nthw_clock_profiles.c',
+ 'nthw/core/nthw_fpga.c',
+ 'nthw/core/nthw_fpga_nt200a0x.c',
+ 'nthw/core/nthw_fpga_rst.c',
+ 'nthw/core/nthw_fpga_rst9563.c',
+ 'nthw/core/nthw_fpga_rst_nt200a0x.c',
+ 'nthw/core/nthw_gpio_phy.c',
+ 'nthw/core/nthw_hif.c',
+ 'nthw/core/nthw_iic.c',
+ 'nthw/core/nthw_mac_pcs.c',
+ 'nthw/core/nthw_mac_pcs_xxv.c',
+ 'nthw/core/nthw_pci_rd_tg.c',
+ 'nthw/core/nthw_pci_ta.c',
+ 'nthw/core/nthw_pci_wr_tg.c',
+ 'nthw/core/nthw_pcie3.c',
+ 'nthw/core/nthw_sdc.c',
+ 'nthw/core/nthw_si5340.c',
+ 'nthw/core/nthw_spi_v3.c',
+ 'nthw/core/nthw_spim.c',
+ 'nthw/core/nthw_spis.c',
+ 'nthw/core/nthw_tsm.c',
+ 'nthw/nthw_fpga_model.c',
+ 'nthw/nthw_dbs.c',
+ 'nthw/nthw_epp.c',
+ 'nthw/nthw_platform.c',
+ 'nthw/nthw_rac.c',
+ 'nthw/nthw_stat.c',
'nthw/supported/nthw_fpga_9563_055_024_0000.c',
+ 'ntlog/ntlog.c',
+ 'ntutil/nt_util.c',
)
if is_variable('default_cflags')
diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
new file mode 100644
index 0000000000..efdcc222a8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_clock_profiles.h"
+
+/* Clock profile for NT200A02 2x40G, 2x100G */
+const int n_data_si5340_nt200a02_u23_v5;
+const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;
diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h
new file mode 100644
index 0000000000..4252f69e92
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_CLOCK_PROFILES_H__
+#define __NTHW_CLOCK_PROFILES_H__
+
+#include <stdint.h>
+
+#include "nthw_helper.h"
+
+#define clk_profile_size_error_msg "size test failed"
+
+typedef struct {
+ unsigned char reg_addr;
+ unsigned char reg_val;
+ unsigned char reg_mask;
+} clk_profile_data_fmt0_t;
+
+typedef struct {
+ uint16_t reg_addr;
+ uint8_t reg_val;
+} clk_profile_data_fmt1_t;
+
+typedef struct {
+ unsigned int reg_addr;
+ unsigned char reg_val;
+} clk_profile_data_fmt2_t;
+
+typedef enum {
+ CLK_PROFILE_DATA_FMT_0,
+ CLK_PROFILE_DATA_FMT_1,
+ CLK_PROFILE_DATA_FMT_2
+} clk_profile_data_fmt_t;
+
+extern const int n_data_si5340_nt200a02_u23_v5;
+extern const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;
+
+#endif /* __NTHW_CLOCK_PROFILES_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h
new file mode 100644
index 0000000000..798a95d5cf
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_core.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_CORE_H__
+#define __NTHW_CORE_H__
+
+#include "nthw_helper.h"
+
+#include "nthw_platform_drv.h"
+#include "nthw_fpga_model.h"
+#include "nthw_hif.h"
+#include "nthw_pcie3.h"
+#include "nthw_pci_rd_tg.h"
+#include "nthw_pci_wr_tg.h"
+#include "nthw_pci_ta.h"
+#include "nthw_iic.h"
+
+#include "nthw_gpio_phy.h"
+#include "nthw_mac_pcs.h"
+#include "nthw_mac_pcs_xxv.h"
+#include "nthw_sdc.h"
+
+#include "nthw_spim.h"
+#include "nthw_spis.h"
+
+#include "nthw_tsm.h"
+
+#include "nthw_si5340.h"
+
+#endif /* __NTHW_CORE_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c
new file mode 100644
index 0000000000..646d45b7eb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c
@@ -0,0 +1,914 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_fpga.h"
+#include "nthw_fpga_instances.h"
+
+#include "nthw_spi_v3.h"
+
+#include <arpa/inet.h>
+
+int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga)
+{
+ const int n_nims = fpga_get_product_param(p_fpga, NT_NIMS, -1);
+ const int n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, -1);
+ const int n_phy_quads = fpga_get_product_param(p_fpga, NT_PHY_QUADS, -1);
+ const int n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, -1);
+ const int n_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, -1);
+
+ p_fpga_info->n_nims = n_nims;
+ p_fpga_info->n_phy_ports = n_phy_ports;
+ p_fpga_info->n_phy_quads = n_phy_quads;
+ p_fpga_info->n_rx_ports = n_rx_ports;
+ p_fpga_info->n_tx_ports = n_tx_ports;
+ p_fpga_info->profile = FPGA_INFO_PROFILE_UNKNOWN;
+
+ /* Check for VSWITCH FPGA */
+ if (fpga_get_product_param(p_fpga, NT_NFV_OVS_PRODUCT, 0) != 0)
+ p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH;
+ /* Check for VSWITCH FPGA - legacy */
+ else if (fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0) != 0)
+ p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH;
+
+ else if (fpga_get_product_param(p_fpga, NT_QM_PRESENT, 0) != 0)
+ p_fpga_info->profile = FPGA_INFO_PROFILE_CAPTURE;
+
+ else
+ p_fpga_info->profile = FPGA_INFO_PROFILE_INLINE;
+
+ return 0;
+}
+
+int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr)
+{
+ nthw_iic_t nthw_iic;
+ uint8_t val = 0;
+
+ if (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0)
+ return -1;
+
+ if (nthw_iic_readbyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) == 0)
+ return val;
+
+ else
+ return -1;
+}
+
+int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr,
+ uint8_t val)
+{
+ nthw_iic_t nthw_iic;
+
+ if (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0)
+ return -1;
+
+ if (nthw_iic_writebyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) != 0)
+ return -1;
+
+ return 0;
+}
+
+int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin,
+ const int n_instance_no_end)
+{
+ int i;
+
+ assert(n_instance_no_begin <= n_instance_no_end);
+
+ for (i = n_instance_no_begin; i <= n_instance_no_end; i++) {
+ nthw_iic_t *p_nthw_iic = nthw_iic_new();
+
+ if (p_nthw_iic) {
+ const int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8);
+
+ if (rc == 0) {
+ nthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100,
+ 3, 3);
+ nthw_iic_scan(p_nthw_iic);
+ }
+ nthw_iic_delete(p_nthw_iic);
+ p_nthw_iic = NULL;
+ }
+ }
+ return 0;
+}
+
+int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no,
+ const int n_dev_addr, const int n_page_reg_addr)
+{
+ const char *const p_adapter_id_str _unused =
+ p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint64_t ident = -1;
+ int res = -1;
+
+ nthw_iic_t *p_nthw_iic = nthw_iic_new();
+
+ if (p_nthw_iic) {
+ uint8_t data;
+ uint8_t a_silabs_ident[8];
+
+ nthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8);
+
+ data = 0;
+ /* switch to page 0 */
+ nthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr,
+ (uint8_t)n_page_reg_addr, 1, &data);
+ res = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00,
+ sizeof(a_silabs_ident), a_silabs_ident);
+ if (res == 0) {
+ int i;
+
+ for (i = 0; i < (int)sizeof(a_silabs_ident); i++) {
+ ident <<= 8;
+ ident |= a_silabs_ident[i];
+ }
+ }
+ nthw_iic_delete(p_nthw_iic);
+ p_nthw_iic = NULL;
+
+ /* Conclude SiLabs part */
+ if (res == 0) {
+ if (a_silabs_ident[3] == 0x53) {
+ if (a_silabs_ident[2] == 0x40)
+ res = 5340;
+ else if (a_silabs_ident[2] == 0x41)
+ res = 5341;
+ } else if (a_silabs_ident[2] == 38) {
+ res = 5338;
+ } else {
+ res = -1;
+ }
+ }
+ }
+
+ NT_LOG(DBG, NTHW, "%s: %016" PRIX64 ": %d\n", p_adapter_id_str, ident,
+ res);
+ return res;
+}
+
+/*
+ * Calculate CRC-16-CCITT of passed data
+ * CRC-16-CCITT ^16 + ^12 + ^5 + 1 (0x1021) (X.25, HDLC, XMODEM, Bluetooth,
+ * SD, many others; known as CRC-CCITT)
+ */
+static uint16_t crc16(uint8_t *buffer, size_t length)
+{
+ uint16_t seed = 0;
+
+ while (length--) {
+ seed = (uint16_t)(seed >> 8 | seed << 8);
+ seed = (uint16_t)(seed ^ *buffer++);
+ seed = (uint16_t)(seed ^ (seed & 0xff) >> 4);
+ seed = (uint16_t)(seed ^ seed << 8 << 4);
+ seed = (uint16_t)(seed ^ (seed & 0xff) << 4 << 1);
+ }
+ return seed;
+}
+
+int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no)
+{
+ struct fpga_info_s *p_fpga_info = p_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ nthw_spi_v3_t *p_avr_spi;
+ int res = -1;
+
+ p_avr_spi = nthw_spi_v3_new();
+ if (p_avr_spi) {
+ struct avr_vpd_info_s {
+ /* avr info */
+ uint32_t n_avr_spi_version;
+ uint8_t n_avr_fw_ver_major;
+ uint8_t n_avr_fw_ver_minor;
+ uint8_t n_avr_fw_ver_micro;
+ uint8_t a_avr_fw_ver_str[50];
+ uint8_t a_avr_fw_plat_id_str[20];
+
+ /* vpdEeprom_t */
+ uint8_t psu_hw_version;
+ uint8_t vpd_pn[GEN2_PN_SIZE];
+ uint8_t vpd_pba[GEN2_PBA_SIZE];
+ uint8_t vpd_sn[GEN2_SN_SIZE];
+ uint8_t vpd_board_name[GEN2_BNAME_SIZE];
+ uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];
+
+ /* BoardInfo_t aka vpd_platform_section: */
+ uint32_t product_family; /* uint8_t 1: capture, 2: Inline, 3: analysis */
+ uint32_t feature_mask; /* Bit 0: OC192 capable */
+ uint32_t invfeature_mask;
+ uint8_t no_of_macs;
+ uint8_t mac_address[6];
+ uint16_t custom_id;
+ uint8_t user_id[8];
+ /*
+ * Reserved NT operations to monitor the reprogram count of userId with
+ * vpduser
+ */
+ uint16_t user_id_erase_write_count;
+
+ /*
+ * AVR_OP_SYSINFO: struct version_sysinfo_request_container
+ * Which version of the sysinfo container to retrieve. Set to zero to fetch
+ * latest. offset zero of latest always contain an uint8_t version info
+ */
+ uint8_t sysinfo_container_version;
+
+ /* AVR_OP_SYSINFO: struct AvrLibcVersion */
+ uint32_t sysinfo_avr_libc_version; /* The constant __AVR_LIBC_VERSION__ */
+
+ /* AVR_OP_SYSINFO: struct AvrLibcSignature */
+ uint8_t sysinfo_signature_0; /* The constant SIGNATURE_0 */
+ uint8_t sysinfo_signature_1; /* The constant SIGNATURE_1 */
+ uint8_t sysinfo_signature_2; /* The constant SIGNATURE_2 */
+
+ /* AVR_OP_SYSINFO: struct AvrOs */
+ uint8_t sysinfo_spi_version; /* SPI command layer version */
+ /*
+ * Hardware revision. Locked to eeprom address zero. Is also available via
+ * VPD read opcode (prior to v1.4b, this is required)
+ */
+ uint8_t sysinfo_hw_revision;
+ /*
+ * Number of ticks/second (Note: Be aware this may become zero if timer
+ * module is rewritten to a tickles system!)
+ */
+ uint8_t sysinfo_ticks_per_second;
+ uint32_t sysinfo_uptime; /* Uptime in seconds since last AVR reset */
+ uint8_t sysinfo_osccal; /* OSCCAL value */
+
+ /*
+ * Meta data concluded/calculated from req/reply
+ */
+ bool b_feature_mask_valid;
+ bool b_crc16_valid;
+ uint16_t n_crc16_stored;
+ uint16_t n_crc16_calced;
+ uint64_t n_mac_val;
+ };
+
+ struct avr_vpd_info_s avr_vpd_info;
+ struct tx_rx_buf tx_buf;
+ struct tx_rx_buf rx_buf;
+ char rx_data[MAX_AVR_CONTAINER_SIZE];
+ uint32_t u32;
+
+ memset(&avr_vpd_info, 0, sizeof(avr_vpd_info));
+
+ nthw_spi_v3_init(p_avr_spi, p_fpga, n_instance_no);
+
+ /* AVR_OP_SPI_VERSION */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(u32);
+ rx_buf.p_buf = &u32;
+ u32 = 0;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SPI_VERSION, &tx_buf,
+ &rx_buf);
+ avr_vpd_info.n_avr_spi_version = u32;
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", p_adapter_id_str,
+ n_instance_no, avr_vpd_info.n_avr_spi_version);
+
+ /* AVR_OP_VERSION */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VERSION, &tx_buf,
+ &rx_buf);
+
+ avr_vpd_info.n_avr_fw_ver_major = rx_data[0];
+ avr_vpd_info.n_avr_fw_ver_minor = rx_data[1];
+ avr_vpd_info.n_avr_fw_ver_micro = rx_data[2];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER: %c.%c.%c\n",
+ p_adapter_id_str, n_instance_no, avr_vpd_info.n_avr_fw_ver_major,
+ avr_vpd_info.n_avr_fw_ver_minor,
+ avr_vpd_info.n_avr_fw_ver_micro);
+
+ memcpy(avr_vpd_info.a_avr_fw_ver_str, &rx_data[0 + 3],
+ sizeof(avr_vpd_info.a_avr_fw_ver_str));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER_STR: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ (int)sizeof(avr_vpd_info.a_avr_fw_ver_str),
+ avr_vpd_info.a_avr_fw_ver_str);
+
+ memcpy(avr_vpd_info.a_avr_fw_plat_id_str, &rx_data[0 + 3 + 50],
+ sizeof(avr_vpd_info.a_avr_fw_plat_id_str));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: FW_HW_ID_STR: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ (int)sizeof(avr_vpd_info.a_avr_fw_plat_id_str),
+ avr_vpd_info.a_avr_fw_plat_id_str);
+
+ rte_strscpy(p_fpga_info->nthw_hw_info.hw_plat_id_str,
+ (char *)avr_vpd_info.a_avr_fw_plat_id_str,
+ sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str));
+ p_fpga_info->nthw_hw_info.hw_plat_id_str
+ [sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str) - 1] =
+ 0;
+
+ /* AVR_OP_SYSINFO_2 */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO_2, &tx_buf,
+ &rx_buf);
+ if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+ rx_buf.size >= 16) {
+ if (rx_buf.size != 16) {
+ NT_LOG(WRN, NTHW,
+ "%s: AVR%d: SYSINFO2: reply is larger than expected: %04X %04X\n",
+ p_adapter_id_str, n_instance_no, rx_buf.size,
+ 16);
+ } else {
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SYSINFO2: OK: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res,
+ rx_buf.size);
+ }
+
+ avr_vpd_info.sysinfo_container_version = rx_data[0];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_container_version);
+
+ memcpy(&avr_vpd_info.sysinfo_avr_libc_version,
+ &rx_data[0 + 1],
+ sizeof(avr_vpd_info.sysinfo_avr_libc_version));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_avr_libc_version);
+
+ avr_vpd_info.sysinfo_signature_0 = rx_data[5];
+ avr_vpd_info.sysinfo_signature_1 = rx_data[6];
+ avr_vpd_info.sysinfo_signature_2 = rx_data[7];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SIGNATURE: %02x%02x%02x\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_signature_0,
+ avr_vpd_info.sysinfo_signature_1,
+ avr_vpd_info.sysinfo_signature_2);
+
+ avr_vpd_info.sysinfo_spi_version = rx_data[8];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_spi_version);
+
+ avr_vpd_info.sysinfo_hw_revision = rx_data[9];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_hw_revision);
+
+ avr_vpd_info.sysinfo_ticks_per_second = rx_data[10];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_ticks_per_second);
+
+ memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11],
+ sizeof(avr_vpd_info.sysinfo_uptime));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_uptime);
+
+ avr_vpd_info.sysinfo_osccal = rx_data[15];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_osccal);
+
+ {
+ bool b_spi_ver_match _unused =
+ (avr_vpd_info.n_avr_spi_version ==
+ avr_vpd_info.sysinfo_spi_version);
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n",
+ p_adapter_id_str, n_instance_no,
+ (b_spi_ver_match ? "OK" : "MISMATCH"),
+ avr_vpd_info.n_avr_spi_version,
+ avr_vpd_info.sysinfo_spi_version);
+ }
+ /* SYSINFO2: if response: only populate hw_id not hw_id_emulated */
+ p_fpga_info->nthw_hw_info.hw_id =
+ avr_vpd_info.sysinfo_hw_revision;
+ } else {
+ /* AVR_OP_SYSINFO */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO,
+ &tx_buf, &rx_buf);
+ if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+ rx_buf.size >= 16) {
+ if (rx_buf.size != 16) {
+ NT_LOG(WRN, NTHW,
+ "%s: AVR%d: SYSINFO: reply is larger than expected: %04X %04X\n",
+ p_adapter_id_str, n_instance_no,
+ rx_buf.size, 16);
+ } else {
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SYSINFO: OK: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res,
+ rx_buf.size);
+ }
+
+ avr_vpd_info.sysinfo_container_version =
+ rx_data[0];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SYSINFO_REQ_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_container_version);
+
+ memcpy(&avr_vpd_info.sysinfo_avr_libc_version,
+ &rx_data[0 + 1],
+ sizeof(avr_vpd_info
+ .sysinfo_avr_libc_version));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_avr_libc_version);
+
+ avr_vpd_info.sysinfo_signature_0 = rx_data[5];
+ avr_vpd_info.sysinfo_signature_1 = rx_data[6];
+ avr_vpd_info.sysinfo_signature_2 = rx_data[7];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SIGNATURE: %02x%02x%02x\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_signature_0,
+ avr_vpd_info.sysinfo_signature_1,
+ avr_vpd_info.sysinfo_signature_2);
+
+ avr_vpd_info.sysinfo_spi_version = rx_data[8];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_spi_version);
+
+ avr_vpd_info.sysinfo_hw_revision = rx_data[9];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_hw_revision);
+ NT_LOG(INF, NTHW, "%s: AVR%d: HW_REV: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_hw_revision);
+
+ avr_vpd_info.sysinfo_ticks_per_second =
+ rx_data[10];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: TICKS_PER_SEC: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_ticks_per_second);
+
+ memcpy(&avr_vpd_info.sysinfo_uptime,
+ &rx_data[11],
+ sizeof(avr_vpd_info.sysinfo_uptime));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_uptime);
+
+ avr_vpd_info.sysinfo_osccal = rx_data[15];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_osccal);
+
+ {
+ bool b_spi_ver_match _unused =
+ (avr_vpd_info.n_avr_spi_version ==
+ avr_vpd_info
+ .sysinfo_spi_version);
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n",
+ p_adapter_id_str, n_instance_no,
+ (b_spi_ver_match ? "OK" :
+ "MISMATCH"),
+ avr_vpd_info.n_avr_spi_version,
+ avr_vpd_info.sysinfo_spi_version);
+ }
+
+ p_fpga_info->nthw_hw_info.hw_id =
+ avr_vpd_info.sysinfo_hw_revision;
+ p_fpga_info->nthw_hw_info.hw_id_emulated =
+ avr_vpd_info.sysinfo_hw_revision;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: AVR%d: SYSINFO: NA: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res,
+ rx_buf.size);
+ }
+ }
+
+ /* AVR_OP_VPD_READ */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VPD_READ, &tx_buf,
+ &rx_buf);
+ if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+ rx_buf.size >= GEN2_VPD_SIZE_TOTAL) {
+ avr_vpd_info.n_crc16_calced =
+ crc16(rx_buf.p_buf, rx_buf.size - 2);
+ memcpy(&avr_vpd_info.n_crc16_stored,
+ &rx_data[rx_buf.size - 2],
+ sizeof(avr_vpd_info.n_crc16_stored));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: VPD_CRC: %04X %04X\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.n_crc16_stored,
+ avr_vpd_info.n_crc16_calced);
+
+ avr_vpd_info.b_crc16_valid = (avr_vpd_info.n_crc16_stored ==
+ avr_vpd_info.n_crc16_calced);
+ NT_LOG(DBG, NTHW, "%s: AVR%d: CRC_TST: %s\n",
+ p_adapter_id_str, n_instance_no,
+ (avr_vpd_info.b_crc16_valid ? "OK" : "ERROR"));
+
+ if (avr_vpd_info.b_crc16_valid) {
+ memcpy(&avr_vpd_info.psu_hw_version, &rx_data[0],
+ sizeof(avr_vpd_info.psu_hw_version));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: PSU_HW_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.psu_hw_version);
+
+ memcpy(&avr_vpd_info.vpd_pn, &rx_data[0 + 1],
+ sizeof(avr_vpd_info.vpd_pn));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: PN: '%.*s'\n",
+ p_adapter_id_str, n_instance_no, GEN2_PN_SIZE,
+ avr_vpd_info.vpd_pn);
+
+ memcpy(&avr_vpd_info.vpd_pba,
+ &rx_data[0 + 1 + GEN2_PN_SIZE],
+ sizeof(avr_vpd_info.vpd_pba));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: PBA: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ GEN2_PBA_SIZE, avr_vpd_info.vpd_pba);
+
+ memcpy(&avr_vpd_info.vpd_sn,
+ &rx_data[0 + 1 + GEN2_PN_SIZE +
+ GEN2_PBA_SIZE],
+ sizeof(avr_vpd_info.vpd_sn));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SN: '%.*s'\n",
+ p_adapter_id_str, n_instance_no, GEN2_SN_SIZE,
+ avr_vpd_info.vpd_sn);
+
+ memcpy(&avr_vpd_info.vpd_board_name,
+ &rx_data[0 + 1 + GEN2_PN_SIZE +
+ GEN2_PBA_SIZE + GEN2_SN_SIZE],
+ sizeof(avr_vpd_info.vpd_board_name));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: BN: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ GEN2_BNAME_SIZE,
+ avr_vpd_info.vpd_board_name);
+
+ {
+ uint32_t u1;
+ union mac_u {
+ uint8_t a_u8[8];
+ uint16_t a_u16[4];
+ uint32_t a_u32[2];
+ uint64_t a_u64[1];
+ } mac;
+
+ /* vpd_platform_section */
+ uint8_t *p_vpd_board_info =
+ (uint8_t *)(&rx_data[1 +
+ GEN2_PN_SIZE +
+ GEN2_PBA_SIZE +
+ GEN2_SN_SIZE +
+ GEN2_BNAME_SIZE]);
+ memcpy(&avr_vpd_info.product_family,
+ &p_vpd_board_info[0],
+ sizeof(avr_vpd_info
+ .product_family));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: PROD_FAM: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.product_family);
+
+ memcpy(&avr_vpd_info.feature_mask,
+ &p_vpd_board_info[0 + 4],
+ sizeof(avr_vpd_info.feature_mask));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: FMSK_VAL: 0x%08X\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.feature_mask);
+
+ memcpy(&avr_vpd_info.invfeature_mask,
+ &p_vpd_board_info[0 + 4 + 4],
+ sizeof(avr_vpd_info
+ .invfeature_mask));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: FMSK_INV: 0x%08X\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.invfeature_mask);
+
+ avr_vpd_info.b_feature_mask_valid =
+ (avr_vpd_info.feature_mask ==
+ ~avr_vpd_info.invfeature_mask);
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: FMSK_TST: %s\n",
+ p_adapter_id_str, n_instance_no,
+ (avr_vpd_info.b_feature_mask_valid ?
+ "OK" :
+ "ERROR"));
+
+ memcpy(&avr_vpd_info.no_of_macs,
+ &p_vpd_board_info[0 + 4 + 4 + 4],
+ sizeof(avr_vpd_info.no_of_macs));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: NUM_MACS: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.no_of_macs);
+
+ memcpy(&avr_vpd_info.mac_address,
+ &p_vpd_board_info[0 + 4 + 4 + 4 + 1],
+ sizeof(avr_vpd_info.mac_address));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: MAC_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.mac_address[0],
+ avr_vpd_info.mac_address[1],
+ avr_vpd_info.mac_address[2],
+ avr_vpd_info.mac_address[3],
+ avr_vpd_info.mac_address[4],
+ avr_vpd_info.mac_address[5]);
+
+ mac.a_u64[0] = 0;
+ memcpy(&mac.a_u8[2],
+ &avr_vpd_info.mac_address,
+ sizeof(avr_vpd_info.mac_address));
+ u1 = ntohl(mac.a_u32[0]);
+ if (u1 != mac.a_u32[0]) {
+ const uint32_t u0 = ntohl(mac.a_u32[1]);
+ mac.a_u32[0] = u0;
+ mac.a_u32[1] = u1;
+ }
+ avr_vpd_info.n_mac_val = mac.a_u64[0];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: MAC_U64: %012" PRIX64
+ "\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.n_mac_val);
+ }
+ }
+ p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count =
+ avr_vpd_info.no_of_macs;
+ p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value =
+ avr_vpd_info.n_mac_val;
+ memcpy(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets,
+ avr_vpd_info.mac_address,
+ ARRAY_SIZE(p_fpga_info->nthw_hw_info.vpd_info
+ .ma_mac_addr_octets));
+ } else {
+ NT_LOG(ERR, NTHW, "%s:%u: res=%d\n", __func__, __LINE__,
+ res);
+ NT_LOG(ERR, NTHW,
+ "%s: AVR%d: SYSINFO2: NA: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res, rx_buf.size);
+ }
+ }
+
+ return res;
+}
+
+/*
+ * NT50B01, NT200A02, NT200A01-HWbuild2
+ */
+int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga,
+ const uint8_t n_iic_addr,
+ const clk_profile_data_fmt2_t *p_clk_profile,
+ const int n_clk_profile_rec_cnt)
+{
+ int res;
+ nthw_iic_t *p_nthw_iic = nthw_iic_new();
+ nthw_si5340_t *p_nthw_si5340 = nthw_si5340_new();
+
+ assert(p_nthw_iic);
+ assert(p_nthw_si5340);
+ nthw_iic_init(p_nthw_iic, p_fpga, 0, 8); /* I2C cycle time 125Mhz ~ 8ns */
+
+ nthw_si5340_init(p_nthw_si5340, p_nthw_iic,
+ n_iic_addr); /* Si5340_U23_I2c_Addr_7bit */
+ res = nthw_si5340_config_fmt2(p_nthw_si5340, p_clk_profile,
+ n_clk_profile_rec_cnt);
+ nthw_si5340_delete(p_nthw_si5340);
+ p_nthw_si5340 = NULL;
+
+ return res;
+}
+
+int nthw_fpga_init(struct fpga_info_s *p_fpga_info)
+{
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+
+ nthw_hif_t *p_nthw_hif = NULL;
+ nthw_pcie3_t *p_nthw_pcie3 = NULL;
+ nthw_rac_t *p_nthw_rac = NULL;
+ nthw_tsm_t *p_nthw_tsm = NULL;
+
+ uint64_t n_fpga_ident = 0;
+ nt_fpga_mgr_t *p_fpga_mgr = NULL;
+ nt_fpga_t *p_fpga = NULL;
+
+ char s_fpga_prod_ver_rev_str[32] = { 0 };
+
+ int res = 0;
+
+ assert(p_fpga_info);
+
+ {
+ int n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id;
+ uint64_t n_fpga_ident;
+ uint32_t n_fpga_ident_low, n_fpga_ident_high, n_fpga_build_time;
+
+ nthw_rac_reg_read32(p_fpga_info, 0x0, &n_fpga_ident_low);
+ nthw_rac_reg_read32(p_fpga_info, 0x8, &n_fpga_ident_high);
+ nthw_rac_reg_read32(p_fpga_info, 0x10, &n_fpga_build_time);
+
+ n_fpga_ident = (((uint64_t)n_fpga_ident_high << 32) | n_fpga_ident_low);
+ n_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident);
+ n_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident);
+ n_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident);
+ n_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident);
+
+ p_fpga_info->n_fpga_ident = n_fpga_ident;
+ p_fpga_info->n_fpga_type_id = n_fpga_type_id;
+ p_fpga_info->n_fpga_prod_id = n_fpga_prod_id;
+ p_fpga_info->n_fpga_ver_id = n_fpga_ver_id;
+ p_fpga_info->n_fpga_rev_id = n_fpga_rev_id;
+ p_fpga_info->n_fpga_build_time = n_fpga_build_time;
+
+ snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str),
+ "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id,
+ n_fpga_ver_id, n_fpga_rev_id);
+
+ NT_LOG(INF, NTHW, "%s: FPGA %s (%" PRIX64 ") [%08X]\n",
+ p_adapter_id_str, s_fpga_prod_ver_rev_str, n_fpga_ident,
+ n_fpga_build_time);
+ }
+
+ n_fpga_ident = p_fpga_info->n_fpga_ident;
+
+ p_fpga_mgr = fpga_mgr_new();
+ fpga_mgr_init(p_fpga_mgr);
+ fpga_mgr_log_dump(p_fpga_mgr);
+ p_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info);
+ p_fpga_info->mp_fpga = p_fpga;
+ if (p_fpga == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: %s (%08X)\n",
+ p_adapter_id_str, s_fpga_prod_ver_rev_str,
+ p_fpga_info->n_fpga_build_time);
+ return -1;
+ }
+
+ if (p_fpga_mgr) {
+ fpga_mgr_delete(p_fpga_mgr);
+ p_fpga_mgr = NULL;
+ }
+
+ /* Read Fpga param info */
+ nthw_fpga_get_param_info(p_fpga_info, p_fpga);
+
+ /* debug: report params */
+ NT_LOG(DBG, NTHW, "%s: NT_NIMS=%d\n", p_adapter_id_str, p_fpga_info->n_nims);
+ NT_LOG(DBG, NTHW, "%s: NT_PHY_PORTS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_phy_ports);
+ NT_LOG(DBG, NTHW, "%s: NT_PHY_QUADS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_phy_quads);
+ NT_LOG(DBG, NTHW, "%s: NT_RX_PORTS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_rx_ports);
+ NT_LOG(DBG, NTHW, "%s: NT_TX_PORTS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_tx_ports);
+ NT_LOG(DBG, NTHW, "%s: nProfile=%d\n", p_adapter_id_str,
+ (int)p_fpga_info->profile);
+
+ p_nthw_rac = nthw_rac_new();
+ if (p_nthw_rac == NULL) {
+ NT_LOG(ERR, NTHW,
+ "%s: Unsupported FPGA: RAC is not found: %s (%08X)\n",
+ p_adapter_id_str, s_fpga_prod_ver_rev_str,
+ p_fpga_info->n_fpga_build_time);
+ return -1;
+ }
+
+ nthw_rac_init(p_nthw_rac, p_fpga, p_fpga_info);
+ nthw_rac_rab_flush(p_nthw_rac);
+ p_fpga_info->mp_nthw_rac = p_nthw_rac;
+
+ /* special case: values below 0x100 will disable debug on RAC communication */
+ {
+ const int n_fpga_initial_debug_mode = p_fpga_info->n_fpga_debug_mode;
+
+ fpga_set_debug_mode(p_fpga, n_fpga_initial_debug_mode);
+ }
+
+ switch (p_fpga_info->n_nthw_adapter_id) {
+ case NT_HW_ADAPTER_ID_NT200A01: /* fallthrough */
+ case NT_HW_ADAPTER_ID_NT200A02:
+ res = nthw_fpga_nt200a0x_init(p_fpga_info);
+ break;
+ default:
+ NT_LOG(ERR, NTHW, "%s: Unsupported HW product id: %d\n",
+ p_adapter_id_str, p_fpga_info->n_nthw_adapter_id);
+ res = -1;
+ break;
+ }
+
+ if (res) {
+ NT_LOG(ERR, NTHW, "%s: status: 0x%08X\n", p_adapter_id_str, res);
+ return res;
+ }
+
+ res = nthw_pcie3_init(NULL, p_fpga, 0); /* Probe for module */
+ if (res == 0) {
+ p_nthw_pcie3 = nthw_pcie3_new();
+ if (p_nthw_pcie3) {
+ res = nthw_pcie3_init(p_nthw_pcie3, p_fpga, 0);
+ if (res == 0) {
+ NT_LOG(DBG, NTHW, "%s: Pcie3 module found\n",
+ p_adapter_id_str);
+ nthw_pcie3_trigger_sample_time(p_nthw_pcie3);
+ } else {
+ nthw_pcie3_delete(p_nthw_pcie3);
+ p_nthw_pcie3 = NULL;
+ }
+ }
+ p_fpga_info->mp_nthw_pcie3 = p_nthw_pcie3;
+ }
+
+ if (p_nthw_pcie3 == NULL) {
+ p_nthw_hif = nthw_hif_new();
+ if (p_nthw_hif) {
+ res = nthw_hif_init(p_nthw_hif, p_fpga, 0);
+ if (res == 0) {
+ NT_LOG(DBG, NTHW, "%s: Hif module found\n",
+ p_adapter_id_str);
+ nthw_hif_trigger_sample_time(p_nthw_hif);
+ } else {
+ nthw_hif_delete(p_nthw_hif);
+ p_nthw_hif = NULL;
+ }
+ }
+ }
+ p_fpga_info->mp_nthw_hif = p_nthw_hif;
+
+ p_nthw_tsm = nthw_tsm_new();
+ if (p_nthw_tsm) {
+ nthw_tsm_init(p_nthw_tsm, p_fpga, 0);
+
+ nthw_tsm_set_config_ts_format(p_nthw_tsm,
+ 1); /* 1 = TSM: TS format native */
+
+ /* Timer T0 - stat toggle timer */
+ nthw_tsm_set_timer_t0_enable(p_nthw_tsm, false);
+ nthw_tsm_set_timer_t0_max_count(p_nthw_tsm, 50 * 1000 * 1000); /* ns */
+ nthw_tsm_set_timer_t0_enable(p_nthw_tsm, true);
+
+ /* Timer T1 - keep alive timer */
+ nthw_tsm_set_timer_t1_enable(p_nthw_tsm, false);
+ nthw_tsm_set_timer_t1_max_count(p_nthw_tsm,
+ 100 * 1000 * 1000); /* ns */
+ nthw_tsm_set_timer_t1_enable(p_nthw_tsm, true);
+ }
+ p_fpga_info->mp_nthw_tsm = p_nthw_tsm;
+
+ /* TSM sample triggering: test validation... */
+#if defined(DEBUG) && (1)
+ {
+ uint64_t n_time, n_ts;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (p_nthw_hif)
+ nthw_hif_trigger_sample_time(p_nthw_hif);
+
+ else if (p_nthw_pcie3)
+ nthw_pcie3_trigger_sample_time(p_nthw_pcie3);
+ nthw_tsm_get_time(p_nthw_tsm, &n_time);
+ nthw_tsm_get_ts(p_nthw_tsm, &n_ts);
+
+ NT_LOG(DBG, NTHW,
+ "%s: TSM time: %016" PRIX64 " %016" PRIX64 "\n",
+ p_adapter_id_str, n_time, n_ts);
+
+ NT_OS_WAIT_USEC(1000);
+ }
+ }
+#endif
+
+ return res;
+}
+
+int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info)
+{
+ int res = -1;
+
+ if (p_fpga_info) {
+ if (p_fpga_info && p_fpga_info->mp_nthw_rac)
+ res = nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.h b/drivers/net/ntnic/nthw/core/nthw_fpga.h
new file mode 100644
index 0000000000..336d81f337
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_H__
+#define __NTHW_FPGA_H__
+
+#include "nthw_drv.h"
+
+#include "nthw_fpga_model.h"
+
+#include "nthw_rac.h"
+#include "nthw_iic.h"
+
+#include "nthw_stat.h"
+
+#include "nthw_fpga_rst.h"
+
+#include "nthw_fpga_nt200a0x.h"
+
+#include "nthw_dbs.h"
+
+int nthw_fpga_init(struct fpga_info_s *p_fpga_info);
+int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info);
+
+int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga);
+
+int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no);
+
+int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin,
+ const int n_instance_no_end);
+
+int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr);
+int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr,
+ uint8_t val);
+
+int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no,
+ const int n_dev_addr, const int n_page_reg_addr);
+
+int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga,
+ const uint8_t n_iic_addr,
+ const clk_profile_data_fmt2_t *p_clk_profile,
+ const int n_clk_profile_rec_cnt);
+
+#endif /* __NTHW_FPGA_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c
new file mode 100644
index 0000000000..70338fdfd7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_fpga.h"
+#include "nthw_fpga_nt200a0x.h"
+
+int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info)
+{
+ assert(p_fpga_info);
+
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ struct nthw_fpga_rst_nt200a0x rst;
+ int res = -1;
+
+ /* reset common */
+ res = nthw_fpga_rst_nt200a0x_init(p_fpga_info, &rst);
+ if (res) {
+ NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n",
+ p_adapter_id_str, __func__, __LINE__,
+ p_fpga_info->n_fpga_prod_id, res);
+ return res;
+ }
+
+ /* reset specific */
+ switch (p_fpga_info->n_fpga_prod_id) {
+ case 9563:
+ res = nthw_fpga_rst9563_init(p_fpga_info, &rst);
+ break;
+ default:
+ NT_LOG(ERR, NTHW, "%s: Unsupported FPGA product: %04d\n",
+ p_adapter_id_str, p_fpga_info->n_fpga_prod_id);
+ res = -1;
+ break;
+ }
+ if (res) {
+ NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n",
+ p_adapter_id_str, __func__, __LINE__,
+ p_fpga_info->n_fpga_prod_id, res);
+ return res;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h
new file mode 100644
index 0000000000..ff324bee39
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_NT200A0X_H__
+#define __NTHW_FPGA_NT200A0X_H__
+
+int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info);
+
+/* NT200A02: 9563 */
+int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *const p);
+
+#endif /* __NTHW_FPGA_NT200A0X_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c
new file mode 100644
index 0000000000..66c148bab2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_fpga.h"
+#include "nthw_fpga_nt200a0x.h"
+
+#include "nthw_fpga_rst.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h
new file mode 100644
index 0000000000..2099c4b677
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_RST_H__
+#define __NTHW_FPGA_RST_H__
+
+#include "nthw_drv.h"
+
+#include "nthw_fpga_model.h"
+
+#include "nthw_rac.h"
+#include "nthw_iic.h"
+
+#include "nthw_fpga_rst_nt200a0x.h"
+
+#endif /* __NTHW_FPGA_RST_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c
new file mode 100644
index 0000000000..077b043c60
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+#include "nthw_clock_profiles.h"
+
+static int nthw_fpga_rst9563_setup(nt_fpga_t *p_fpga,
+ struct nthw_fpga_rst_nt200a0x *const p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const int n_fpga_product_id = p_fpga->m_product_id;
+ const int n_fpga_version = p_fpga->m_fpga_version;
+ const int n_fpga_revision = p_fpga->m_fpga_revision;
+
+ nt_module_t *p_mod_rst;
+ nt_register_t *p_curr_reg;
+
+ assert(p);
+ p->mn_fpga_product_id = n_fpga_product_id;
+ p->mn_fpga_version = n_fpga_version;
+ p->mn_fpga_revision = n_fpga_revision;
+
+ NT_LOG(DBG, NTHW, "%s: %s: FPGA reset setup: FPGA %04d-%02d-%02d\n",
+ p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version,
+ n_fpga_revision);
+
+ p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);
+ if (p_mod_rst == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n",
+ p_adapter_id_str, 0);
+ return -1;
+ }
+
+ p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);
+ if (p_mod_rst == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n",
+ p_adapter_id_str, 0);
+ return -1;
+ }
+
+ /* RST register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_RST);
+ p->mp_fld_rst_sys = register_get_field(p_curr_reg, RST9563_RST_SYS);
+ p->mp_fld_rst_sys_mmcm = register_get_field(p_curr_reg, RST9563_RST_SYS_MMCM);
+ p->mp_fld_rst_core_mmcm =
+ register_get_field(p_curr_reg, RST9563_RST_CORE_MMCM);
+ p->mp_fld_rst_rpp = register_get_field(p_curr_reg, RST9563_RST_RPP);
+ p->mp_fld_rst_ddr4 = register_get_field(p_curr_reg, RST9563_RST_DDR4);
+ p->mp_fld_rst_sdc = register_get_field(p_curr_reg, RST9563_RST_SDC);
+ p->mp_fld_rst_phy = register_get_field(p_curr_reg, RST9563_RST_PHY);
+ p->mp_fld_rst_serdes_rx = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_serdes_tx = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_serdes_rx_datapath = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_pcs_rx = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_mac_rx = register_get_field(p_curr_reg, RST9563_RST_MAC_RX);
+ p->mp_fld_rst_mac_tx = NULL;
+ p->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP);
+ p->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP);
+ p->mp_fld_rst_ts = register_get_field(p_curr_reg, RST9563_RST_TS);
+ p->mp_fld_rst_ptp_mmcm = register_get_field(p_curr_reg, RST9563_RST_PTP_MMCM);
+ p->mp_fld_rst_ts_mmcm = register_get_field(p_curr_reg, RST9563_RST_TS_MMCM);
+ /* referenced in separate function */
+ p->mp_fld_rst_periph = register_get_field(p_curr_reg, RST9563_RST_PERIPH);
+ p->mp_fld_rst_tsm_ref_mmcm =
+ register_query_field(p_curr_reg, RST9563_RST_TSM_REF_MMCM);
+ p->mp_fld_rst_tmc = register_query_field(p_curr_reg, RST9563_RST_TMC);
+
+ if (!p->mp_fld_rst_tsm_ref_mmcm) {
+ NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TSM_REF_MMCM found\n",
+ p_adapter_id_str);
+ }
+ if (!p->mp_fld_rst_tmc) {
+ NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TMC found\n",
+ p_adapter_id_str);
+ }
+ register_update(p_curr_reg);
+
+ /* CTRL register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_CTRL);
+ p->mp_fld_ctrl_ts_clk_sel_override =
+ register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL_OVERRIDE);
+ /* Field not present on 9563 */
+ p->mp_fld_ctrl_ts_clk_sel =
+ register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL);
+ p->mp_fld_ctrl_ts_clk_sel_ref = NULL; /* Field not present on 9563 */
+ p->mp_fld_ctrl_ptp_mmcm_clk_sel =
+ register_get_field(p_curr_reg, RST9563_CTRL_PTP_MMCM_CLKSEL);
+ register_update(p_curr_reg);
+
+ /* STAT register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_STAT);
+ p->mp_fld_stat_ddr4_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_DDR4_MMCM_LOCKED);
+ p->mp_fld_stat_sys_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_SYS_MMCM_LOCKED);
+ p->mp_fld_stat_core_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_CORE_MMCM_LOCKED);
+ p->mp_fld_stat_ddr4_pll_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_DDR4_PLL_LOCKED);
+ p->mp_fld_stat_ptp_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_PTP_MMCM_LOCKED);
+ p->mp_fld_stat_ts_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_TS_MMCM_LOCKED);
+ p->mp_fld_stat_tsm_ref_mmcm_locked = NULL; /* Field not present on 9563 */
+
+ if (!p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ NT_LOG(DBG, NTHW,
+ "%s: No RST9563_STAT_TSM_REF_MMCM_LOCKED found\n",
+ p_adapter_id_str);
+ }
+ register_update(p_curr_reg);
+
+ /* STICKY register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_STICKY);
+ p->mp_fld_sticky_ptp_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_PTP_MMCM_UNLOCKED);
+ p->mp_fld_sticky_ts_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_TS_MMCM_UNLOCKED);
+ p->mp_fld_sticky_ddr4_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_DDR4_MMCM_UNLOCKED);
+ p->mp_fld_sticky_ddr4_pll_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_DDR4_PLL_UNLOCKED);
+ p->mp_fld_sticky_core_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_CORE_MMCM_UNLOCKED);
+ p->mp_fld_sticky_pci_sys_mmcm_unlocked = NULL; /* Field not present on 9563 */
+ p->mp_fld_sticky_tsm_ref_mmcm_unlocked = NULL; /* Field not present on 9563 */
+
+ if (!p->mp_fld_sticky_tsm_ref_mmcm_unlocked) {
+ NT_LOG(DBG, NTHW,
+ "%s: No RST9563_STICKY_TSM_REF_MMCM_UNLOCKED found\n",
+ p_adapter_id_str);
+ }
+ register_update(p_curr_reg);
+
+ /* POWER register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_POWER);
+ p->mp_fld_power_pu_phy = register_get_field(p_curr_reg, RST9563_POWER_PU_PHY);
+ p->mp_fld_power_pu_nseb =
+ register_get_field(p_curr_reg, RST9563_POWER_PU_NSEB);
+ register_update(p_curr_reg);
+
+ return 0;
+}
+
+static int nthw_fpga_rst9563_periph_reset(nt_fpga_t *p_fpga)
+{
+ const char *const _unused p_adapter_id_str =
+ p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);
+
+ if (p_mod_rst) {
+ nt_register_t *p_reg_rst;
+ nt_field_t *p_fld_rst_periph;
+
+ NT_LOG(DBG, NTHW, "%s: PERIPH RST\n", p_adapter_id_str);
+ p_reg_rst = module_get_register(p_mod_rst, RST9563_RST);
+ p_fld_rst_periph = register_get_field(p_reg_rst, RST9563_RST_PERIPH);
+ field_set_flush(p_fld_rst_periph);
+ field_clr_flush(p_fld_rst_periph);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+nthw_fpga_rst9563_clock_synth_init(nt_fpga_t *p_fpga,
+ const int n_si_labs_clock_synth_model,
+ const uint8_t n_si_labs_clock_synth_i2c_addr)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const int n_fpga_product_id = p_fpga->m_product_id;
+ int res;
+
+ if (n_si_labs_clock_synth_model == 5340) {
+ res = nthw_fpga_si5340_clock_synth_init_fmt2(p_fpga,
+ n_si_labs_clock_synth_i2c_addr,
+ p_data_si5340_nt200a02_u23_v5,
+ n_data_si5340_nt200a02_u23_v5);
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: Fpga %d: Unsupported clock synth model (%d)\n",
+ p_adapter_id_str, n_fpga_product_id, n_si_labs_clock_synth_model);
+ res = -1;
+ }
+ return res;
+}
+
+int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *p_rst)
+{
+ assert(p_fpga_info);
+ assert(p_rst);
+
+ const char *const _unused p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = -1;
+ int n_si_labs_clock_synth_model;
+ uint8_t n_si_labs_clock_synth_i2c_addr;
+ nt_fpga_t *p_fpga = NULL;
+
+ p_fpga = p_fpga_info->mp_fpga;
+ n_si_labs_clock_synth_model = p_rst->mn_si_labs_clock_synth_model;
+ n_si_labs_clock_synth_i2c_addr = p_rst->mn_si_labs_clock_synth_i2c_addr;
+
+ res = nthw_fpga_rst9563_periph_reset(p_fpga);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ res = nthw_fpga_rst9563_clock_synth_init(p_fpga, n_si_labs_clock_synth_model,
+ n_si_labs_clock_synth_i2c_addr);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ res = nthw_fpga_rst9563_setup(p_fpga, p_rst);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ res = nthw_fpga_rst_nt200a0x_reset(p_fpga, p_rst);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c
new file mode 100644
index 0000000000..f519020c8e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c
@@ -0,0 +1,674 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+static const uint8_t si5338_u23_i2c_addr_7bit = 0x70;
+static const uint8_t si5340_u23_i2c_addr_7bit = 0x74;
+
+/*
+ * Wait until DDR4 PLL LOCKED
+ */
+static int nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint32_t locked;
+ uint32_t retrycount = 5;
+ uint32_t timeout = 50000; /* initial timeout must be set to 5 sec. */
+ /* 14: wait until DDR4 PLL LOCKED */
+ NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock\n", p_adapter_id_str);
+ /*
+ * The following retry count gives a total timeout of 1 * 5 + 5 * 8 = 45sec
+ * It has been observed that at least 21sec can be necessary
+ */
+ while (true) {
+ int locked = field_wait_set_any32(p->mp_fld_stat_ddr4_pll_locked,
+ timeout, 100);
+ if (locked == 0)
+ break;
+ NT_LOG(DBG, NTHW,
+ "%s: Waiting for DDR4 PLL to lock - timeout\n",
+ p_adapter_id_str);
+ if (retrycount <= 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for DDR4 PLL to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ break;
+ }
+ field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */
+ field_clr_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */
+ retrycount--;
+ timeout =
+ 80000; /* Increase timeout for second attempt to 8 sec. */
+ }
+
+ NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ddr4_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for DDR4 MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ return -1;
+ }
+
+ if ((true) && p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1,
+ -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ return -1;
+ }
+ }
+
+ /* 10: Clear all MMCM/PLL lock sticky bits before testing them */
+ NT_LOG(DBG, NTHW, "%s: Clear sticky MMCM unlock bits\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ /* Clear all sticky bits */
+ field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);
+ field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);
+
+ /* 11: Ensure sticky bits are not unlocked except PTP MMCM and TS MMCM */
+ if (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_pll_unlocked() returned true\n",
+ p_adapter_id_str);
+ }
+
+ return 0;
+}
+
+/*
+ * Wait for SDRAM controller has been calibrated - On some adapters we have seen
+ * calibration time of 2.3 seconds
+ */
+static int
+nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nthw_sdc_t *p_nthw_sdc = NULL;
+ const int n_retry_cnt_max = 5;
+ int n_retry_cnt;
+ int res;
+
+ res = nthw_sdc_init(NULL, p_fpga, 0); /* probe for module */
+ if (res == 0) {
+ p_nthw_sdc = nthw_sdc_new();
+ if (p_nthw_sdc) {
+ res = nthw_sdc_init(p_nthw_sdc, p_fpga, 0);
+ if (res) {
+ NT_LOG(ERR, NTHW,
+ "%s: SDC init failed: res=%d [%s:%d]\n",
+ p_adapter_id_str, res, __func__, __LINE__);
+ nthw_sdc_delete(p_nthw_sdc);
+ p_nthw_sdc = NULL;
+ return -1;
+ }
+ } else {
+ nthw_sdc_delete(p_nthw_sdc);
+ p_nthw_sdc = NULL;
+ }
+ } else {
+ NT_LOG(DBG, NTHW, "%s: No SDC found\n", p_adapter_id_str);
+ }
+ n_retry_cnt = 0;
+ res = -1;
+ while ((res != 0) && (n_retry_cnt <= n_retry_cnt_max)) {
+ /* wait until DDR4 PLL LOCKED */
+ res = nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(p_fpga, p);
+ if (res == 0) {
+ if (p_nthw_sdc) {
+ /*
+ * Wait for SDRAM controller has been calibrated
+ * On some adapters we have seen calibration time of 2.3 seconds
+ */
+ NT_LOG(DBG, NTHW,
+ "%s: Waiting for SDRAM to calibrate\n",
+ p_adapter_id_str);
+ res = nthw_sdc_wait_states(p_nthw_sdc, 10000, 1000);
+ {
+ uint64_t n_result_mask;
+
+ int n_state_code _unused =
+ nthw_sdc_get_states(p_nthw_sdc,
+ &n_result_mask);
+ NT_LOG(DBG, NTHW,
+ "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n",
+ p_adapter_id_str, n_result_mask,
+ n_state_code, n_retry_cnt, res);
+ }
+ if (res == 0)
+ break;
+ }
+
+ if (n_retry_cnt >= n_retry_cnt_max) {
+ uint64_t n_result_mask;
+ int n_state_code _unused = nthw_sdc_get_states(p_nthw_sdc,
+ &n_result_mask);
+
+ NT_LOG(DBG, NTHW,
+ "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n",
+ p_adapter_id_str, n_result_mask, n_state_code,
+ n_retry_cnt, res);
+ if (res != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Timeout waiting for SDRAM controller calibration\n",
+ p_adapter_id_str);
+ }
+ }
+ }
+
+ /*
+ * SDRAM controller is not calibrated with DDR4 ram blocks:
+ * reset DDR and perform calibration retry
+ */
+ field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */
+ NT_OS_WAIT_USEC(100);
+ field_clr_flush(p->mp_fld_rst_ddr4);
+
+ n_retry_cnt++;
+ }
+ nthw_sdc_delete(p_nthw_sdc);
+
+ return res;
+}
+
+int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const fpga_info_t *const p_fpga_info = p_fpga->p_fpga_info;
+
+ const int n_fpga_product_id = p->mn_fpga_product_id;
+ const int n_fpga_version = p->mn_fpga_version;
+ const int n_fpga_revision = p->mn_fpga_revision;
+ const int n_nthw_adapter_id = p_fpga_info->n_nthw_adapter_id;
+ const bool b_is_nt200a01 = (n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01);
+ const int n_hw_id = p_fpga_info->nthw_hw_info.hw_id;
+ const uint8_t index = 0;
+ int locked;
+ int res = -1;
+
+ NT_LOG(DBG, NTHW,
+ "%s: %s: FPGA reset sequence: FPGA %04d-%02d-%02d @ HWId%d\n",
+ p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version,
+ n_fpga_revision, n_hw_id);
+ assert(n_fpga_product_id == p_fpga->m_product_id);
+
+ /*
+ * Reset all domains / modules except peripherals
+ * Set default reset values to ensure that all modules are reset correctly
+ * no matter if nic has been powercycled or ntservice has been reloaded
+ */
+
+ /*
+ * Reset to defaults
+ * 1: Reset all domains
+ */
+ NT_LOG(DBG, NTHW, "%s: RST defaults\n", p_adapter_id_str);
+
+ field_update_register(p->mp_fld_rst_sys);
+ field_set_flush(p->mp_fld_rst_sys);
+ if (p->mp_fld_rst_tmc)
+ field_set_flush(p->mp_fld_rst_tmc);
+ field_set_flush(p->mp_fld_rst_rpp);
+ field_set_flush(p->mp_fld_rst_ddr4); /* 0x07 3 banks */
+ field_set_flush(p->mp_fld_rst_sdc);
+
+ /* Reset port 0 and 1 in the following registers: */
+ field_set_flush(p->mp_fld_rst_phy); /* 0x03 2 ports */
+ if (p->mp_fld_rst_mac_rx)
+ field_set_flush(p->mp_fld_rst_mac_rx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_mac_tx)
+ field_set_flush(p->mp_fld_rst_mac_tx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_pcs_rx)
+ field_set_flush(p->mp_fld_rst_pcs_rx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_serdes_rx)
+ field_set_flush(p->mp_fld_rst_serdes_rx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_serdes_rx_datapath) {
+ field_set_flush(p->mp_fld_rst_serdes_rx_datapath);
+ field_clr_flush(p->mp_fld_rst_serdes_rx);
+ }
+ if (p->mp_fld_rst_serdes_tx)
+ field_set_flush(p->mp_fld_rst_serdes_tx);
+
+ field_set_flush(p->mp_fld_rst_ptp);
+ field_set_flush(p->mp_fld_rst_ts);
+ field_set_flush(p->mp_fld_rst_sys_mmcm);
+ field_set_flush(p->mp_fld_rst_core_mmcm);
+ field_set_flush(p->mp_fld_rst_ptp_mmcm);
+ field_set_flush(p->mp_fld_rst_ts_mmcm);
+
+ if ((true) && p->mp_fld_rst_tsm_ref_mmcm)
+ field_set_flush(p->mp_fld_rst_tsm_ref_mmcm);
+
+ /* Write all changes to register */
+ field_flush_register(p->mp_fld_rst_sys);
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ if (p->mp_fld_rst_tsm_ref_mmcm) {
+ field_update_register(p->mp_fld_rst_tsm_ref_mmcm);
+ field_set_flush(p->mp_fld_rst_tsm_ref_mmcm);
+ }
+ }
+
+ /*
+ * 2: Force use of 50 MHz reference clock for timesync;
+ * NOTE: From 9508-05-18 this is a 20 MHz clock
+ */
+ NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL OVERRIDE\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_ctrl_ts_clk_sel_override);
+ field_set_flush(p->mp_fld_ctrl_ts_clk_sel_override);
+
+ NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_ctrl_ts_clk_sel);
+ field_set_flush(p->mp_fld_ctrl_ts_clk_sel);
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ NT_LOG(DBG, NTHW, "%s: _selecting 20MHz TS CLK SEL REF\n",
+ p_adapter_id_str);
+ if (p->mp_fld_ctrl_ts_clk_sel_ref) {
+ field_update_register(p->mp_fld_ctrl_ts_clk_sel_ref);
+ field_clr_flush(p->mp_fld_ctrl_ts_clk_sel_ref);
+ }
+ }
+
+ /* 4: De-assert sys reset, CORE and SYS MMCM resets */
+ NT_LOG(DBG, NTHW, "%s: De-asserting SYS, CORE and SYS MMCM resets\n",
+ p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_sys);
+ field_clr_flush(p->mp_fld_rst_sys);
+ field_clr_flush(p->mp_fld_rst_sys_mmcm);
+ field_clr_flush(p->mp_fld_rst_core_mmcm);
+
+ /* 5: wait until CORE MMCM and SYS MMCM are LOCKED */
+ NT_LOG(DBG, NTHW, "%s: Waiting for SYS MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_sys_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for SYS MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+
+ NT_LOG(DBG, NTHW, "%s: Waiting for CORE MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_core_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for CORE MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+
+ /* RAC RAB bus "flip/flip" reset second stage - new impl (ref RMT#37020) */
+ /* RAC/RAB init - SYS/CORE MMCM is locked - pull the remaining RAB busses out of reset */
+ {
+ nthw_rac_t *p_nthw_rac = p_fpga_info->mp_nthw_rac;
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting remaining RAB busses\n",
+ p_adapter_id_str);
+ nthw_rac_rab_init(p_nthw_rac, 0);
+ }
+
+ if ((true) && p->mp_fld_rst_tsm_ref_mmcm) {
+ NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n",
+ p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);
+ if (p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ NT_LOG(DBG, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked,
+ -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+ }
+
+ /*
+ * 5.2: Having ensured CORE MMCM and SYS MMCM are LOCKED,
+ * we need to select the alternative 20 MHz reference clock,
+ * the external TSM reference clock
+ * on NT200A01 - build 2 HW only (see SSF00024 p.32)
+ */
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL REF\n",
+ p_adapter_id_str);
+ if (p->mp_fld_ctrl_ts_clk_sel_ref)
+ field_set_flush(p->mp_fld_ctrl_ts_clk_sel_ref);
+ if (p->mp_fld_rst_tsm_ref_mmcm) {
+ NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n",
+ p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);
+ }
+ NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n",
+ p_adapter_id_str);
+ if (p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked,
+ -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+ }
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting all PHY resets\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_phy);
+ field_clr_flush(p->mp_fld_rst_phy);
+
+ /* MAC_PCS_XXV 10G/25G: 9530 / 9544 */
+ if (n_fpga_product_id == 9530 || n_fpga_product_id == 9544) {
+ {
+ /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */
+ nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv0 = nthw_mac_pcs_xxv_new();
+
+ assert(p_nthw_mac_pcs_xxv0);
+ nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv0, p_fpga, 0, 1);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, true,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, false,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv0);
+ }
+
+ {
+ /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */
+ nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv1 = nthw_mac_pcs_xxv_new();
+
+ assert(p_nthw_mac_pcs_xxv1);
+ nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv1, p_fpga, 1, 1);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, true,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, false,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv1);
+ }
+ NT_OS_WAIT_USEC(3000);
+ }
+
+ /*
+ * 8: De-assert reset for remaining domains/modules resets except
+ * TS, PTP, PTP_MMCM and TS_MMCM
+ */
+ NT_LOG(DBG, NTHW, "%s: De-asserting TMC RST\n", p_adapter_id_str);
+ if (p->mp_fld_rst_tmc) {
+ field_update_register(p->mp_fld_rst_tmc);
+ field_clr_flush(p->mp_fld_rst_tmc);
+ }
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting RPP RST\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_rpp);
+ field_clr_flush(p->mp_fld_rst_rpp);
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting DDR4 RST\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_ddr4);
+ field_clr_flush(p->mp_fld_rst_ddr4);
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting SDC RST\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_sdc);
+ field_clr_flush(p->mp_fld_rst_sdc);
+
+ /* NOTE: 9522 implements PHY10G_QPLL reset and lock at this stage in mac_rx_rst() */
+ NT_LOG(DBG, NTHW, "%s: De-asserting MAC RX RST\n", p_adapter_id_str);
+ if (p->mp_fld_rst_mac_rx) {
+ field_update_register(p->mp_fld_rst_mac_rx);
+ field_clr_flush(p->mp_fld_rst_mac_rx);
+ }
+
+ /* await until DDR4 PLL LOCKED and SDRAM controller has been calibrated */
+ res = nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(p_fpga, p);
+ if (res) {
+ NT_LOG(ERR, NTHW,
+ "%s: nthw_fpga_rst_nt200a0x_wait_sdc_calibrated() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_core_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_tsm_ref_mmcm_unlocked returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+ }
+
+ /*
+ * Timesync/PTP reset sequence
+ * De-assert TS_MMCM reset
+ */
+ NT_LOG(DBG, NTHW, "%s: De-asserting TS MMCM RST\n", p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ts_mmcm);
+
+ /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */
+ NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TS MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+
+ NT_LOG(DBG, NTHW, "%s: Calling clear_sticky_mmcm_unlock_bits()\n",
+ p_adapter_id_str);
+ field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ /* Clear all sticky bits */
+ field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);
+ field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);
+
+ /* De-assert TS reset bit */
+ NT_LOG(DBG, NTHW, "%s: De-asserting TS RST\n", p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ts);
+
+ if (field_get_updated(p->mp_fld_sticky_ts_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ts_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_pll_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_core_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_tsm_ref_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+ }
+
+ if (false) {
+ /* Deassert PTP_MMCM */
+ NT_LOG(DBG, NTHW, "%s: De-asserting PTP MMCM RST\n",
+ p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ptp_mmcm);
+
+ if ((b_is_nt200a01 && n_fpga_version >= 9) || !b_is_nt200a01) {
+ /* Wait until PTP_MMCM LOCKED */
+ NT_LOG(DBG, NTHW, "%s: Waiting for PTP MMCM to lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ptp_mmcm_locked,
+ -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for PTP MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+
+ /* Switch PTP MMCM sel to use ptp clk */
+ NT_LOG(DBG, NTHW, "%s: Setting PTP MMCM CLK SEL\n",
+ p_adapter_id_str);
+ field_set_flush(p->mp_fld_ctrl_ptp_mmcm_clk_sel);
+
+ /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */
+ NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to re-lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TS MMCM to re-lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting PTP RST\n", p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ptp);
+
+ /* POWER staging introduced in 9508-05-09 and always for 9512 */
+ if (n_fpga_product_id == 9508 && n_fpga_version <= 5 &&
+ n_fpga_revision <= 8) {
+ NT_LOG(DBG, NTHW, "%s: No power staging\n", p_adapter_id_str);
+ } else {
+ NT_LOG(DBG, NTHW, "%s: Staging power\n", p_adapter_id_str);
+ field_set_flush(p->mp_fld_power_pu_phy); /* PHY power up */
+ field_clr_flush(p->mp_fld_power_pu_nseb); /* NSEB power down */
+ }
+
+ NT_LOG(DBG, NTHW, "%s: %s: END\n", p_adapter_id_str, __func__);
+
+ return 0;
+}
+
+int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *p_rst)
+{
+ assert(p_fpga_info);
+
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = -1;
+ int n_si_labs_clock_synth_model = -1;
+ uint8_t n_si_labs_clock_synth_i2c_addr = 0;
+ nt_fpga_t *p_fpga = NULL;
+
+ p_fpga = p_fpga_info->mp_fpga;
+
+ NT_LOG(DBG, NTHW, "%s: %s: RAB init/reset\n", p_adapter_id_str, __func__);
+ nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);
+ nthw_rac_rab_setup(p_fpga_info->mp_nthw_rac);
+
+ res = nthw_fpga_avr_probe(p_fpga, 0);
+
+ res = nthw_fpga_iic_scan(p_fpga, 0, 0);
+ res = nthw_fpga_iic_scan(p_fpga, 2, 3);
+
+ /*
+ * Detect clock synth model
+ * check for NT200A02/NT200A01 HW-build2 - most commonly seen
+ */
+ n_si_labs_clock_synth_i2c_addr = si5340_u23_i2c_addr_7bit;
+ n_si_labs_clock_synth_model =
+ nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 1);
+ if (n_si_labs_clock_synth_model == -1) {
+ /* check for old NT200A01 HW-build1 */
+ n_si_labs_clock_synth_i2c_addr = si5338_u23_i2c_addr_7bit;
+ n_si_labs_clock_synth_model =
+ nthw_fpga_silabs_detect(p_fpga, 0,
+ n_si_labs_clock_synth_i2c_addr, 255);
+ if (n_si_labs_clock_synth_model == -1) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed to detect clock synth model (%d)\n",
+ p_adapter_id_str, n_si_labs_clock_synth_model);
+ return -1;
+ }
+ }
+ p_rst->mn_si_labs_clock_synth_model = n_si_labs_clock_synth_model;
+ p_rst->mn_si_labs_clock_synth_i2c_addr = n_si_labs_clock_synth_i2c_addr;
+ p_rst->mn_hw_id = p_fpga_info->nthw_hw_info.hw_id;
+ NT_LOG(DBG, NTHW, "%s: %s: Si%04d @ 0x%02x\n", p_adapter_id_str, __func__,
+ p_rst->mn_si_labs_clock_synth_model, p_rst->mn_si_labs_clock_synth_i2c_addr);
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h
new file mode 100644
index 0000000000..1f192f5ecc
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_RST_NT200A0X_H__
+#define __NTHW_FPGA_RST_NT200A0X_H__
+
+#include "nthw_drv.h"
+#include "nthw_fpga_model.h"
+
+struct nthw_fpga_rst_nt200a0x {
+ int mn_fpga_product_id;
+ int mn_fpga_version;
+ int mn_fpga_revision;
+
+ int mn_hw_id;
+
+ int mn_si_labs_clock_synth_model;
+ uint8_t mn_si_labs_clock_synth_i2c_addr;
+
+ nt_field_t *mp_fld_rst_sys;
+ nt_field_t *mp_fld_rst_sys_mmcm;
+ nt_field_t *mp_fld_rst_core_mmcm;
+ nt_field_t *mp_fld_rst_rpp;
+ nt_field_t *mp_fld_rst_ddr4;
+ nt_field_t *mp_fld_rst_sdc;
+ nt_field_t *mp_fld_rst_phy;
+ nt_field_t *mp_fld_rst_serdes_rx;
+ nt_field_t *mp_fld_rst_serdes_tx;
+ nt_field_t *mp_fld_rst_serdes_rx_datapath;
+ nt_field_t *mp_fld_rst_pcs_rx;
+ nt_field_t *mp_fld_rst_mac_rx;
+ nt_field_t *mp_fld_rst_mac_tx;
+ nt_field_t *mp_fld_rst_ptp;
+ nt_field_t *mp_fld_rst_ts;
+ nt_field_t *mp_fld_rst_ptp_mmcm;
+ nt_field_t *mp_fld_rst_ts_mmcm;
+ nt_field_t *mp_fld_rst_periph;
+ nt_field_t *mp_fld_rst_tsm_ref_mmcm;
+ nt_field_t *mp_fld_rst_tmc;
+
+ /* CTRL register field pointers */
+ nt_field_t *mp_fld_ctrl_ts_clk_sel_override;
+ nt_field_t *mp_fld_ctrl_ts_clk_sel;
+ nt_field_t *mp_fld_ctrl_ts_clk_sel_ref;
+ nt_field_t *mp_fld_ctrl_ptp_mmcm_clk_sel;
+
+ /* STAT register field pointers */
+ nt_field_t *mp_fld_stat_ddr4_mmcm_locked;
+ nt_field_t *mp_fld_stat_sys_mmcm_locked;
+ nt_field_t *mp_fld_stat_core_mmcm_locked;
+ nt_field_t *mp_fld_stat_ddr4_pll_locked;
+ nt_field_t *mp_fld_stat_ptp_mmcm_locked;
+ nt_field_t *mp_fld_stat_ts_mmcm_locked;
+ nt_field_t *mp_fld_stat_tsm_ref_mmcm_locked;
+
+ /* STICKY register field pointers */
+ nt_field_t *mp_fld_sticky_ptp_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_ts_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_ddr4_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_ddr4_pll_unlocked;
+ nt_field_t *mp_fld_sticky_core_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_pci_sys_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_tsm_ref_mmcm_unlocked;
+
+ /* POWER register field pointers */
+ nt_field_t *mp_fld_power_pu_phy;
+ nt_field_t *mp_fld_power_pu_nseb;
+ /* */
+
+ void (*reset_serdes_rx)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+ uint32_t rst);
+ void (*pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+ uint32_t rst);
+ void (*get_serdes_rx_rst)(struct nthw_fpga_rst_nt200a0x *p,
+ uint32_t intf_no, uint32_t *p_set);
+ void (*get_pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+ uint32_t *p_set);
+ bool (*is_rst_serdes_rx_datapath_implemented)(struct nthw_fpga_rst_nt200a0x *p);
+};
+
+typedef struct nthw_fpga_rst_nt200a0x nthw_fpga_rst_nt200a0x_t;
+
+int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *p_rst);
+int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p);
+
+#endif /* __NTHW_FPGA_RST_NT200A0X_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c
new file mode 100644
index 0000000000..9b536726d0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_gpio_phy.h"
+
+nthw_gpio_phy_t *nthw_gpio_phy_new(void)
+{
+ nthw_gpio_phy_t *p = malloc(sizeof(nthw_gpio_phy_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_gpio_phy_t));
+ return p;
+}
+
+void nthw_gpio_phy_delete(nthw_gpio_phy_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_gpio_phy_t));
+ free(p);
+ }
+}
+
+int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_GPIO_PHY, n_instance);
+
+ if (p == NULL)
+ return (p_mod == NULL ? -1 : 0);
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: GPIO_PHY %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_gpio_phy = p_mod;
+
+ /* Registers */
+ p->mp_reg_config = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_CFG);
+ p->mp_reg_gpio = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_GPIO);
+
+ /* PORT-0, config fields */
+ p->mpa_fields[0].cfg_fld_lp_mode =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_LPMODE);
+ p->mpa_fields[0].cfg_int =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_INT_B);
+ p->mpa_fields[0].cfg_reset =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_RESET_B);
+ p->mpa_fields[0].cfg_mod_prs =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_MODPRS_B);
+
+ /* PORT-0, Non-mandatory fields (queryField) */
+ p->mpa_fields[0].cfg_pll_int =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_PLL_INTR);
+ p->mpa_fields[0].cfg_port_rxlos =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT0_RXLOS);
+
+ /* PORT-1, config fields */
+ p->mpa_fields[1].cfg_fld_lp_mode =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_LPMODE);
+ p->mpa_fields[1].cfg_int =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_INT_B);
+ p->mpa_fields[1].cfg_reset =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_RESET_B);
+ p->mpa_fields[1].cfg_mod_prs =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_MODPRS_B);
+
+ /* PORT-1, Non-mandatory fields (queryField) */
+ p->mpa_fields[1].cfg_pll_int =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_PLL_INTR);
+ p->mpa_fields[1].cfg_port_rxlos =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT1_RXLOS);
+
+ /* PORT-0, gpio fields */
+ p->mpa_fields[0].gpio_fld_lp_mode =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_LPMODE);
+ p->mpa_fields[0].gpio_int =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_INT_B);
+ p->mpa_fields[0].gpio_reset =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_RESET_B);
+ p->mpa_fields[0].gpio_mod_prs =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_MODPRS_B);
+
+ /* PORT-0, Non-mandatory fields (queryField) */
+ p->mpa_fields[0].gpio_pll_int =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_PLL_INTR);
+ p->mpa_fields[0].gpio_port_rxlos =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT0_RXLOS);
+
+ /* PORT-1, gpio fields */
+ p->mpa_fields[1].gpio_fld_lp_mode =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_LPMODE);
+ p->mpa_fields[1].gpio_int =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_INT_B);
+ p->mpa_fields[1].gpio_reset =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_RESET_B);
+ p->mpa_fields[1].gpio_mod_prs =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_MODPRS_B);
+
+ /* PORT-1, Non-mandatory fields (queryField) */
+ p->mpa_fields[1].gpio_pll_int =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_PLL_INTR);
+ p->mpa_fields[1].gpio_port_rxlos =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT1_RXLOS);
+
+ register_update(p->mp_reg_config);
+
+ return 0;
+}
+
+bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ if (field_get_updated(p->mpa_fields[if_no].gpio_fld_lp_mode))
+ return true;
+
+ else
+ return false;
+}
+
+bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a negated GPIO PIN "INT_B" */
+ if (field_get_updated(p->mpa_fields[if_no].gpio_int))
+ return false;
+
+ else
+ return true;
+}
+
+bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a negated GPIO PIN "RESET_B" */
+ if (field_get_updated(p->mpa_fields[if_no].gpio_reset))
+ return false;
+
+ else
+ return true;
+}
+
+bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a negated GPIO PIN "MODPRS_B" */
+ return field_get_updated(p->mpa_fields[if_no].gpio_mod_prs) == 0U ? true :
+ false;
+}
+
+bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a normal GPIO PIN "PLL_INTR" */
+ if (p->mpa_fields[if_no].gpio_pll_int) {
+ if (field_get_updated(p->mpa_fields[if_no].gpio_pll_int))
+ return true;
+
+ else
+ return false;
+ } else {
+ /* this HW doesn't support "PLL_INTR" (INTR from SyncE jitter attenuater) */
+ return false;
+ }
+}
+
+bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ if (p->mpa_fields[if_no].gpio_port_rxlos) {
+ if (field_get_updated(p->mpa_fields[if_no].gpio_port_rxlos))
+ return true;
+ else
+ return false;
+ } else {
+ return false;
+ }
+}
+
+void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ if (enable)
+ field_set_flush(p->mpa_fields[if_no].gpio_fld_lp_mode);
+
+ else
+ field_clr_flush(p->mpa_fields[if_no].gpio_fld_lp_mode);
+ field_clr_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable output */
+}
+
+void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ if (enable)
+ field_clr_flush(p->mpa_fields[if_no].gpio_reset);
+
+ else
+ field_set_flush(p->mpa_fields[if_no].gpio_reset);
+ field_clr_flush(p->mpa_fields[if_no].cfg_reset); /* enable output */
+}
+
+void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ if (p->mpa_fields[if_no].gpio_port_rxlos) {
+ if (enable)
+ field_set_flush(p->mpa_fields[if_no].gpio_port_rxlos);
+
+ else
+ field_clr_flush(p->mpa_fields[if_no].gpio_port_rxlos);
+ }
+}
+
+void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ field_set_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable input */
+ field_set_flush(p->mpa_fields[if_no].cfg_int); /* enable input */
+ field_set_flush(p->mpa_fields[if_no].cfg_reset); /* enable input */
+ field_set_flush(p->mpa_fields[if_no].cfg_mod_prs); /* enable input */
+ if (p->mpa_fields[if_no].cfg_port_rxlos)
+ field_clr_flush(p->mpa_fields[if_no].cfg_port_rxlos); /* enable output */
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h
new file mode 100644
index 0000000000..1c6185150c
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_GPIO_PHY_H_
+#define NTHW_GPIO_PHY_H_
+
+#define GPIO_PHY_INTERFACES (2)
+
+typedef struct {
+ nt_field_t *cfg_fld_lp_mode; /* Cfg Low Power Mode */
+ nt_field_t *cfg_int; /* Cfg Port Interrupt */
+ nt_field_t *cfg_reset; /* Cfg Reset */
+ nt_field_t *cfg_mod_prs; /* Cfg Module Present */
+ nt_field_t *cfg_pll_int; /* Cfg PLL Interrupt */
+ nt_field_t *cfg_port_rxlos; /* Emulate Cfg Port RXLOS */
+
+ nt_field_t *gpio_fld_lp_mode; /* Gpio Low Power Mode */
+ nt_field_t *gpio_int; /* Gpio Port Interrupt */
+ nt_field_t *gpio_reset; /* Gpio Reset */
+ nt_field_t *gpio_mod_prs; /* Gpio Module Present */
+ nt_field_t *gpio_pll_int; /* Gpio PLL Interrupt */
+ nt_field_t *gpio_port_rxlos; /* Emulate Gpio Port RXLOS */
+} gpio_phy_fields_t;
+
+struct nthw_gpio_phy {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_gpio_phy;
+ int mn_instance;
+
+ /* Registers */
+ nt_register_t *mp_reg_config;
+ nt_register_t *mp_reg_gpio;
+
+ /* Fields */
+ gpio_phy_fields_t mpa_fields[GPIO_PHY_INTERFACES];
+};
+
+typedef struct nthw_gpio_phy nthw_gpio_phy_t;
+typedef struct nthw_gpio_phy nthw_gpio_phy;
+
+nthw_gpio_phy_t *nthw_gpio_phy_new(void);
+void nthw_gpio_phy_delete(nthw_gpio_phy_t *p);
+int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no);
+void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);
+void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);
+void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);
+void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no);
+
+#endif /* NTHW_GPIO_PHY_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c
new file mode 100644
index 0000000000..7b7a919108
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_hif.c
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_hif.h"
+
+nthw_hif_t *nthw_hif_new(void)
+{
+ nthw_hif_t *p = malloc(sizeof(nthw_hif_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_hif_t));
+ return p;
+}
+
+void nthw_hif_delete(nthw_hif_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_hif_t));
+ free(p);
+ }
+}
+
+int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str _unused =
+ p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_HIF, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: HIF %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_hif = mod;
+
+ /* default for (Xilinx-based) products until august 2022: (1e6/4000 = 250 MHz) */
+ p->mn_fpga_param_hif_per_ps =
+ fpga_get_product_param(p->mp_fpga, NT_HIF_PER_PS, 4000);
+ p->mn_fpga_hif_ref_clk_freq =
+ (uint32_t)(1000000000000ULL /
+ (unsigned int)p->mn_fpga_param_hif_per_ps);
+
+ p->mp_reg_prod_id_lsb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_LSB);
+ p->mp_fld_prod_id_lsb_rev_id =
+ register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_REV_ID);
+ p->mp_fld_prod_id_lsb_ver_id =
+ register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_VER_ID);
+ p->mp_fld_prod_id_lsb_group_id =
+ register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_GROUP_ID);
+
+ p->mp_reg_prod_id_msb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_MSB);
+ p->mp_fld_prod_id_msb_type_id =
+ register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_TYPE_ID);
+ p->mp_fld_prod_id_msb_build_no =
+ register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_BUILD_NO);
+
+ p->mp_reg_build_time = module_get_register(p->mp_mod_hif, HIF_BUILD_TIME);
+ p->mp_fld_build_time =
+ register_get_field(p->mp_reg_build_time, HIF_BUILD_TIME_TIME);
+
+ p->mn_fpga_id_prod = field_get_updated(p->mp_fld_prod_id_lsb_group_id);
+ p->mn_fpga_id_ver = field_get_updated(p->mp_fld_prod_id_lsb_ver_id);
+ p->mn_fpga_id_rev = field_get_updated(p->mp_fld_prod_id_lsb_rev_id);
+ p->mn_fpga_id_build_no = field_get_updated(p->mp_fld_prod_id_msb_build_no);
+ p->mn_fpga_id_item = field_get_updated(p->mp_fld_prod_id_msb_type_id);
+
+ NT_LOG(DBG, NTHW, "%s: HIF %d: %s: %d-%d-%d-%d-%d\n", p_adapter_id_str,
+ p->mn_instance, __func__, p->mn_fpga_id_item, p->mn_fpga_id_prod,
+ p->mn_fpga_id_ver, p->mn_fpga_id_rev, p->mn_fpga_id_build_no);
+ NT_LOG(DBG, NTHW,
+ "%s: HIF %d: %s: HIF ref clock: %d Hz (%d ticks/ps)\n",
+ p_adapter_id_str, p->mn_instance, __func__, p->mn_fpga_hif_ref_clk_freq,
+ p->mn_fpga_param_hif_per_ps);
+
+ p->mp_reg_build_seed = NULL; /* Reg/Fld not present on HIF */
+ if (p->mp_reg_build_seed)
+ p->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */
+ else
+ p->mp_fld_build_seed = NULL;
+
+ p->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */
+ if (p->mp_reg_core_speed) {
+ p->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */
+ p->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */
+ } else {
+ p->mp_reg_core_speed = NULL;
+ p->mp_fld_core_speed = NULL;
+ p->mp_fld_ddr3_speed = NULL;
+ }
+
+ /* Optional registers since: 2018-04-25 */
+ p->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */
+ p->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */
+ p->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */
+
+ p->mp_fld_int_mask_timer = NULL;
+ p->mp_fld_int_clr_timer = NULL;
+ p->mp_fld_int_force_timer = NULL;
+
+ p->mp_fld_int_mask_port = NULL;
+ p->mp_fld_int_clr_port = NULL;
+ p->mp_fld_int_force_port = NULL;
+
+ p->mp_fld_int_mask_pps = NULL;
+ p->mp_fld_int_clr_pps = NULL;
+ p->mp_fld_int_force_pps = NULL;
+
+ p->mp_reg_stat_ctrl = module_get_register(p->mp_mod_hif, HIF_STAT_CTRL);
+ p->mp_fld_stat_ctrl_ena =
+ register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA);
+ p->mp_fld_stat_ctrl_req =
+ register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ);
+
+ p->mp_reg_stat_rx = module_get_register(p->mp_mod_hif, HIF_STAT_RX);
+ p->mp_fld_stat_rx_counter =
+ register_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER);
+
+ p->mp_reg_stat_tx = module_get_register(p->mp_mod_hif, HIF_STAT_TX);
+ p->mp_fld_stat_tx_counter =
+ register_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER);
+
+ p->mp_reg_stat_ref_clk = module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK);
+ p->mp_fld_stat_ref_clk_ref_clk = register_get_field(p->mp_reg_stat_ref_clk,
+ HIF_STAT_REFCLK_REFCLK250);
+
+ p->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS);
+ if (p->mp_reg_status) {
+ p->mp_fld_status_tags_in_use =
+ register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE);
+ p->mp_fld_status_wr_err =
+ register_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR);
+ p->mp_fld_status_rd_err =
+ register_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR);
+ } else {
+ p->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS);
+ p->mp_fld_status_tags_in_use =
+ register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE);
+ p->mp_fld_status_wr_err = NULL;
+ p->mp_fld_status_rd_err = NULL;
+ }
+
+ p->mp_reg_pci_test0 = module_get_register(p->mp_mod_hif, HIF_TEST0);
+ p->mp_fld_pci_test0 = register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA);
+
+ p->mp_reg_pci_test1 = module_get_register(p->mp_mod_hif, HIF_TEST1);
+ p->mp_fld_pci_test1 = register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA);
+
+ /* Required to run TSM */
+ p->mp_reg_sample_time = module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME);
+ if (p->mp_reg_sample_time) {
+ p->mp_fld_sample_time =
+ register_get_field(p->mp_reg_sample_time, HIF_SAMPLE_TIME_SAMPLE_TIME);
+ } else {
+ p->mp_fld_sample_time = NULL;
+ }
+
+ /* We need to optimize PCIe3 TLP-size read-request and extended tag usage */
+ {
+ p->mp_reg_config = module_query_register(p->mp_mod_hif, HIF_CONFIG);
+ if (p->mp_reg_config) {
+ p->mp_fld_max_tlp =
+ register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP);
+ p->mp_fld_max_read =
+ register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ);
+ p->mp_fld_ext_tag =
+ register_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG);
+ } else {
+ p->mp_fld_max_tlp = NULL;
+ p->mp_fld_max_read = NULL;
+ p->mp_fld_ext_tag = NULL;
+ }
+ }
+
+ return 0;
+}
+
+int nthw_hif_setup_config(nthw_hif_t *p)
+{
+ const char *const p_adapter_id_str _unused =
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+
+ /*
+ * We need to optimize PCIe3 read-request and extended tag usage
+ * original check: HW_ADAPTER_ID_NT200A02 HW_ADAPTER_ID_NT100A01 HW_ADAPTER_ID_NT50B01
+ */
+ if (p->mp_fpga->p_fpga_info->n_nthw_adapter_id != NT_HW_ADAPTER_ID_NT40E3) {
+ if (p->mp_fld_max_read) {
+ /*
+ * NOTE: On Pandion DELL server, this param was negotiated to 4096
+ * (index=5), but the server crashed. For now we need to limit this value to
+ * 512 (index=2)
+ */
+ const uint32_t n_max_read_req_size =
+ field_get_updated(p->mp_fld_max_read);
+ if (n_max_read_req_size > 2) {
+ field_set_val_flush32(p->mp_fld_max_read, 2);
+ NT_LOG(INF, NTHW,
+ "%s: %s: PCIe: MaxReadReqsize %d - changed to 2 (512B)\n",
+ p_adapter_id_str, __func__,
+ n_max_read_req_size);
+ }
+ }
+
+ if (p->mp_fld_ext_tag)
+ field_set_val_flush32(p->mp_fld_ext_tag, 1);
+
+ if (p->mp_fld_max_tlp && p->mp_fld_max_read && p->mp_fld_ext_tag) {
+ NT_LOG(INF, NTHW,
+ "%s: %s: PCIe config: MaxTlp = %d, MaxReadReqsize = %d, ExtTagEna = %d\n",
+ p_adapter_id_str, __func__,
+ field_get_updated(p->mp_fld_max_tlp),
+ field_get_updated(p->mp_fld_max_read),
+ field_get_updated(p->mp_fld_ext_tag));
+ }
+ }
+ return 0;
+}
+
+int nthw_hif_trigger_sample_time(nthw_hif_t *p)
+{
+ field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);
+
+ return 0;
+}
+
+int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err, uint64_t *p_wr_err)
+{
+ *p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter);
+ *p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter);
+
+ *p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk);
+
+ *p_tg_unit_size = NTHW_TG_CNT_SIZE;
+ *p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq;
+
+ *p_tags_in_use = (p->mp_fld_status_tags_in_use ?
+ field_get_updated(p->mp_fld_status_tags_in_use) :
+ 0);
+
+ *p_rd_err = (p->mp_fld_status_rd_err ? field_get_updated(p->mp_fld_status_rd_err) :
+ 0);
+ *p_wr_err = (p->mp_fld_status_wr_err ? field_get_updated(p->mp_fld_status_wr_err) :
+ 0);
+
+ return 0;
+}
+
+int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt,
+ uint64_t *p_wr_err_cnt)
+{
+ uint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq;
+ uint64_t n_tags_in_use, n_rd_err, n_wr_err;
+
+ nthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq,
+ &n_tags_in_use, &n_rd_err, &n_wr_err);
+
+ *p_tags_in_use = n_tags_in_use;
+ if (n_rd_err)
+ (*p_rd_err_cnt)++;
+ if (n_wr_err)
+ (*p_wr_err_cnt)++;
+
+ if (ref_clk_cnt) {
+ uint64_t rx_rate;
+ uint64_t tx_rate;
+
+ *p_ref_clk_cnt = ref_clk_cnt;
+
+ rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_rx_rate = rx_rate;
+
+ tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_tx_rate = tx_rate;
+ } else {
+ *p_pci_rx_rate = 0;
+ *p_pci_tx_rate = 0;
+ *p_ref_clk_cnt = 0;
+ }
+
+ return 0;
+}
+
+int nthw_hif_stat_req_enable(nthw_hif_t *p)
+{
+ field_set_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_hif_stat_req_disable(nthw_hif_t *p)
+{
+ field_clr_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate,
+ uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt)
+{
+ nthw_hif_stat_req_enable(p);
+ NT_OS_WAIT_USEC(100000);
+ nthw_hif_stat_req_disable(p);
+ nthw_hif_get_stat_rate(p, p_rx_rate, p_tx_rate, p_ref_clk_cnt, p_tags_in_use,
+ p_rd_err_cnt, p_wr_err_cnt);
+
+ return 0;
+}
+
+int nthw_hif_end_point_counters_sample(nthw_hif_t *p,
+ struct nthw_hif_end_point_counters *epc)
+{
+ assert(epc);
+
+ /* Get stat rate and maintain rx/tx min/max */
+ nthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt,
+ &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.h b/drivers/net/ntnic/nthw/core/nthw_hif.h
new file mode 100644
index 0000000000..2701e222b3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_hif.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_HIF_H__
+#define __NTHW_HIF_H__
+
+#define NTHW_TG_CNT_SIZE (4ULL)
+
+struct nthw_hif {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_hif;
+ int mn_instance;
+
+ nt_register_t *mp_reg_prod_id_lsb;
+ nt_field_t *mp_fld_prod_id_lsb_rev_id;
+ nt_field_t *mp_fld_prod_id_lsb_ver_id;
+ nt_field_t *mp_fld_prod_id_lsb_group_id;
+
+ nt_register_t *mp_reg_prod_id_msb;
+ nt_field_t *mp_fld_prod_id_msb_type_id;
+ nt_field_t *mp_fld_prod_id_msb_build_no;
+
+ nt_register_t *mp_reg_build_time;
+ nt_field_t *mp_fld_build_time;
+
+ nt_register_t *mp_reg_build_seed;
+ nt_field_t *mp_fld_build_seed;
+
+ nt_register_t *mp_reg_core_speed;
+ nt_field_t *mp_fld_core_speed;
+ nt_field_t *mp_fld_ddr3_speed;
+
+ nt_register_t *mp_reg_int_mask;
+ nt_field_t *mp_fld_int_mask_timer;
+ nt_field_t *mp_fld_int_mask_port;
+ nt_field_t *mp_fld_int_mask_pps;
+
+ nt_register_t *mp_reg_int_clr;
+ nt_field_t *mp_fld_int_clr_timer;
+ nt_field_t *mp_fld_int_clr_port;
+ nt_field_t *mp_fld_int_clr_pps;
+
+ nt_register_t *mp_reg_int_force;
+ nt_field_t *mp_fld_int_force_timer;
+ nt_field_t *mp_fld_int_force_port;
+ nt_field_t *mp_fld_int_force_pps;
+
+ nt_register_t *mp_reg_sample_time;
+ nt_field_t *mp_fld_sample_time;
+
+ nt_register_t *mp_reg_status;
+ nt_field_t *mp_fld_status_tags_in_use;
+ nt_field_t *mp_fld_status_wr_err;
+ nt_field_t *mp_fld_status_rd_err;
+
+ nt_register_t *mp_reg_stat_ctrl;
+ nt_field_t *mp_fld_stat_ctrl_ena;
+ nt_field_t *mp_fld_stat_ctrl_req;
+
+ nt_register_t *mp_reg_stat_rx;
+ nt_field_t *mp_fld_stat_rx_counter;
+
+ nt_register_t *mp_reg_stat_tx;
+ nt_field_t *mp_fld_stat_tx_counter;
+
+ nt_register_t *mp_reg_stat_ref_clk;
+ nt_field_t *mp_fld_stat_ref_clk_ref_clk;
+
+ nt_register_t *mp_reg_pci_test0;
+ nt_field_t *mp_fld_pci_test0;
+
+ nt_register_t *mp_reg_pci_test1;
+ nt_field_t *mp_fld_pci_test1;
+
+ nt_register_t *mp_reg_pci_test2;
+ nt_field_t *mp_fld_pci_test2;
+
+ nt_register_t *mp_reg_pci_test3;
+ nt_field_t *mp_fld_pci_test3;
+
+ nt_register_t *mp_reg_config;
+ nt_field_t *mp_fld_max_tlp;
+ nt_field_t *mp_fld_max_read;
+ nt_field_t *mp_fld_ext_tag;
+
+ int mn_fpga_id_item;
+ int mn_fpga_id_prod;
+ int mn_fpga_id_ver;
+ int mn_fpga_id_rev;
+ int mn_fpga_id_build_no;
+
+ int mn_fpga_param_hif_per_ps;
+ uint32_t mn_fpga_hif_ref_clk_freq;
+};
+
+typedef struct nthw_hif nthw_hif_t;
+typedef struct nthw_hif nthw_hif;
+
+struct nthw_hif_end_point_err_counters {
+ uint32_t n_err_correctable, n_err_non_fatal, n_err_fatal;
+};
+
+struct nthw_hif_end_point_counters {
+ int n_numa_node;
+
+ int n_tg_direction;
+ int n_tg_pkt_size;
+ int n_tg_num_pkts;
+ int n_tg_delay;
+
+ uint64_t cur_rx, cur_tx;
+ uint64_t cur_pci_nt_util, cur_pci_xil_util;
+ uint64_t n_ref_clk_cnt;
+
+ uint64_t n_tags_in_use;
+ uint64_t n_rd_err;
+ uint64_t n_wr_err;
+
+ struct nthw_hif_end_point_err_counters s_rc_ep_pre, s_rc_ep_post, s_rc_ep_delta;
+ struct nthw_hif_end_point_err_counters s_ep_rc_pre, s_ep_rc_post, s_ep_rc_delta;
+
+ int bo_error;
+};
+
+struct nthw_hif_end_points {
+ struct nthw_hif_end_point_counters pri, sla;
+};
+
+nthw_hif_t *nthw_hif_new(void);
+void nthw_hif_delete(nthw_hif_t *p);
+int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+int nthw_hif_setup_config(nthw_hif_t *p);
+
+int nthw_hif_trigger_sample_time(nthw_hif_t *p);
+
+int nthw_hif_stat_req_enable(nthw_hif_t *p);
+int nthw_hif_stat_req_disable(nthw_hif_t *p);
+int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate,
+ uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt);
+
+int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err, uint64_t *p_wr_err);
+int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt,
+ uint64_t *p_wr_err_cnt);
+
+int nthw_hif_end_point_counters_sample(nthw_hif_t *p,
+ struct nthw_hif_end_point_counters *epc);
+
+#endif /* __NTHW_HIF_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.c b/drivers/net/ntnic/nthw/core/nthw_iic.c
new file mode 100644
index 0000000000..14aee221ce
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_iic.c
@@ -0,0 +1,570 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_iic.h"
+
+#define I2C_TRANSMIT_WR (0x00)
+#define I2C_TRANSMIT_RD (0x01)
+
+#define I2C_WAIT_US(x) NT_OS_WAIT_USEC(x)
+
+/*
+ * Minimum timing values for I2C for a Marvel 88E11111 Phy.
+ * This Phy is used in many Trispeed NIMs.
+ * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz.
+ */
+static const uint32_t susta = 4700; /* ns */
+static const uint32_t susto = 4000; /* ns */
+static const uint32_t hdsta = 4000; /* ns */
+static const uint32_t sudat = 250; /* ns */
+static const uint32_t buf = 4700; /* ns */
+static const uint32_t high = 4000; /* ns */
+static const uint32_t low = 4700; /* ns */
+static const uint32_t hddat = 300; /* ns */
+
+static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p)
+{
+ field_update_register(p->mp_fld_cr_txfifo_reset);
+
+ field_set_all(p->mp_fld_cr_txfifo_reset);
+ field_flush_register(p->mp_fld_cr_txfifo_reset);
+
+ field_clr_all(p->mp_fld_cr_txfifo_reset);
+ field_flush_register(p->mp_fld_cr_txfifo_reset);
+
+ return 0;
+}
+
+static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start,
+ bool stop)
+{
+ if (start)
+ field_set_all(p->mp_fld_tx_fifo_start);
+
+ else
+ field_clr_all(p->mp_fld_tx_fifo_start);
+
+ if (stop)
+ field_set_all(p->mp_fld_tx_fifo_stop);
+
+ else
+ field_clr_all(p->mp_fld_tx_fifo_stop);
+
+ field_set_val32(p->mp_fld_tx_fifo_txdata, data);
+
+ register_flush(p->mp_reg_tx_fifo, 1);
+
+ return 0;
+}
+
+static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data)
+{
+ assert(p_data);
+
+ *p_data = (uint8_t)field_get_updated(p->mp_fld_rx_fifo_rxdata);
+
+ return 0;
+}
+
+static int nthw_iic_reg_softr(nthw_iic_t *p)
+{
+ field_update_register(p->mp_fld_cr_en);
+ field_set_val_flush32(p->mp_fld_softr_rkey, 0x0A);
+
+ return 0;
+}
+
+static int nthw_iic_reg_enable(nthw_iic_t *p)
+{
+ field_update_register(p->mp_fld_cr_en);
+ field_set_flush(p->mp_fld_cr_en);
+
+ return 0;
+}
+
+static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag)
+{
+ assert(pb_flag);
+
+ *pb_flag = field_get_updated(p->mp_fld_sr_bb) ? true : false;
+
+ return 0;
+}
+
+static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag)
+{
+ assert(pb_flag);
+
+ *pb_flag = field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false;
+
+ return 0;
+}
+
+/*
+ * nIicCycleTime is the I2C clock cycle time in ns ie 125MHz = 8ns
+ */
+static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time)
+{
+ uint32_t val;
+
+ val = susta / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tsusta, &val, 1);
+
+ val = susto / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tsusto, &val, 1);
+
+ val = hdsta / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_thdsta, &val, 1);
+
+ val = sudat / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tsudat, &val, 1);
+
+ val = buf / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tbuf, &val, 1);
+
+ val = high / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_thigh, &val, 1);
+
+ val = low / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tlow, &val, 1);
+
+ val = hddat / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_thddat, &val, 1);
+
+ return 0;
+}
+
+nthw_iic_t *nthw_iic_new(void)
+{
+ nthw_iic_t *p = malloc(sizeof(nthw_iic_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_iic_t));
+ return p;
+}
+
+int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance,
+ uint32_t n_iic_cycle_time)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_IIC, n_iic_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance\n",
+ p_adapter_id_str, n_iic_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_iic_instance = n_iic_instance;
+
+ p->mn_iic_cycle_time = n_iic_cycle_time;
+
+ nthw_iic_set_retry_params(p, -1, -1, -1, -1, -1);
+
+ p->mp_mod_iic = mod;
+
+ /* I2C is a primary communication channel - turn off debug by default */
+ module_set_debug_mode(p->mp_mod_iic, 0x00);
+
+ p->mp_reg_tsusta = module_get_register(p->mp_mod_iic, IIC_TSUSTA);
+ p->mp_fld_tsusta =
+ register_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL);
+
+ p->mp_reg_tsusto = module_get_register(p->mp_mod_iic, IIC_TSUSTO);
+ p->mp_fld_tsusto =
+ register_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL);
+
+ p->mp_reg_thdsta = module_get_register(p->mp_mod_iic, IIC_THDSTA);
+ p->mp_fld_thdsta =
+ register_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL);
+
+ p->mp_reg_tsudat = module_get_register(p->mp_mod_iic, IIC_TSUDAT);
+ p->mp_fld_tsudat =
+ register_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL);
+
+ p->mp_reg_tbuf = module_get_register(p->mp_mod_iic, IIC_TBUF);
+ p->mp_fld_tbuf = register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL);
+
+ p->mp_reg_thigh = module_get_register(p->mp_mod_iic, IIC_THIGH);
+ p->mp_fld_thigh = register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL);
+
+ p->mp_reg_tlow = module_get_register(p->mp_mod_iic, IIC_TLOW);
+ p->mp_fld_tlow = register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL);
+
+ p->mp_reg_thddat = module_get_register(p->mp_mod_iic, IIC_THDDAT);
+ p->mp_fld_thddat =
+ register_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL);
+
+ p->mp_reg_cr = module_get_register(p->mp_mod_iic, IIC_CR);
+ p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, IIC_CR_EN);
+ p->mp_fld_cr_msms = register_get_field(p->mp_reg_cr, IIC_CR_MSMS);
+ p->mp_fld_cr_txfifo_reset =
+ register_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET);
+ p->mp_fld_cr_txak = register_get_field(p->mp_reg_cr, IIC_CR_TXAK);
+
+ p->mp_reg_sr = module_get_register(p->mp_mod_iic, IIC_SR);
+ p->mp_fld_sr_bb = register_get_field(p->mp_reg_sr, IIC_SR_BB);
+ p->mp_fld_sr_rxfifo_full =
+ register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL);
+ p->mp_fld_sr_rxfifo_empty =
+ register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY);
+ p->mp_fld_sr_txfifo_full =
+ register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL);
+ p->mp_fld_sr_txfifo_empty =
+ register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY);
+
+ p->mp_reg_tx_fifo = module_get_register(p->mp_mod_iic, IIC_TX_FIFO);
+ p->mp_fld_tx_fifo_txdata =
+ register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA);
+ p->mp_fld_tx_fifo_start =
+ register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START);
+ p->mp_fld_tx_fifo_stop =
+ register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP);
+
+ p->mp_reg_rx_fifo_pirq =
+ module_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ);
+ p->mp_fld_rx_fifo_pirq_cmp_val =
+ register_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL);
+
+ p->mp_reg_rx_fifo = module_get_register(p->mp_mod_iic, IIC_RX_FIFO);
+ p->mp_fld_rx_fifo_rxdata =
+ register_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA);
+
+ p->mp_reg_softr = module_get_register(p->mp_mod_iic, IIC_SOFTR);
+ p->mp_fld_softr_rkey = register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY);
+
+ /*
+ * Initialize I2C controller by applying soft reset and enable the controller
+ */
+ nthw_iic_reg_softr(p);
+ /* Enable the controller */
+ nthw_iic_reg_enable(p);
+
+ /* Setup controller timing */
+ if (p->mn_iic_cycle_time) {
+ NT_LOG(DBG, NTHW, "%s: I2C%d: cycletime=%d\n", p_adapter_id_str,
+ p->mn_iic_instance, p->mn_iic_cycle_time);
+ nthw_iic_reg_set_timing(p, p->mn_iic_cycle_time);
+ }
+
+ /* Reset TX fifo - must be after enable */
+ nthw_iic_reg_control_txfifo_reset(p);
+ nthw_iic_reg_tx_fifo_write(p, 0, 0, 0);
+
+ return 0;
+}
+
+void nthw_iic_delete(nthw_iic_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_iic_t));
+ free(p);
+ }
+}
+
+int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay,
+ const int n_bus_ready_retry, const int n_data_ready_retry,
+ const int n_read_data_retry, const int n_write_data_retry)
+{
+ p->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10;
+
+ p->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000;
+ p->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000;
+
+ p->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10;
+ p->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10;
+
+ return 0;
+}
+
+int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ const int n_debug_mode = module_get_debug_mode(p->mp_mod_iic);
+
+ uint8_t *pb = (uint8_t *)p_void;
+ int retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10);
+
+ if (n_debug_mode == 0xff) {
+ NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d\n",
+ p_adapter_id_str, dev_addr, reg_addr, data_len);
+ }
+
+ while (nthw_iic_readbyte(p, dev_addr, reg_addr, data_len, pb) != 0) {
+ retry--;
+ if (retry <= 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: I2C%d: Read retry exhausted (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, dev_addr,
+ reg_addr);
+ return -1;
+ }
+#if defined(DEBUG)
+ NT_LOG(DBG, NTHW,
+ "%s: I2C%d: Read retry=%d (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, retry, dev_addr,
+ reg_addr);
+#endif
+ }
+
+ if (n_debug_mode == 0xff) {
+ NT_LOG(DBG, NTHW,
+ "%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\n",
+ p_adapter_id_str, dev_addr, reg_addr, data_len, retry);
+ }
+
+ return 0;
+}
+
+int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+
+ uint32_t value;
+ uint32_t i;
+
+ if (nthw_iic_bus_ready(p)) {
+ /* Reset TX fifo */
+ nthw_iic_reg_control_txfifo_reset(p);
+
+ /* Write device address to TX_FIFO and set start bit!! */
+ value = (dev_addr << 1) | I2C_TRANSMIT_WR;
+ nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
+
+ /* Write reg_addr to TX FIFO */
+ nthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 1);
+
+ if (!nthw_iic_bus_ready(p)) {
+ NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* Write device address + RD bit to TX_FIFO and set start bit!! */
+ value = (dev_addr << 1) | I2C_TRANSMIT_RD;
+ nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
+
+ /* Write DataLen to TX_FIFO and set stop bit!! */
+ nthw_iic_reg_tx_fifo_write(p, data_len, 0, 1);
+
+ for (i = 0; i < data_len; i++) {
+ /* Wait for RX FIFO not empty */
+ if (!nthw_iic_data_ready(p))
+ return -1;
+
+ /* Read DataLen bytes from RX_FIFO */
+ nthw_iic_reg_read_i2c_rx_fifo(p, p_byte);
+ p_byte++;
+ }
+
+ return 0;
+
+ } else {
+ NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+ return 0;
+}
+
+int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10);
+ uint8_t *pb = (uint8_t *)p_void;
+
+ while (nthw_iic_writebyte(p, dev_addr, reg_addr, data_len, pb) != 0) {
+ retry--;
+ if (retry <= 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: I2C%d: Write retry exhausted (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, dev_addr,
+ reg_addr);
+ return -1;
+ }
+#if defined(DEBUG)
+ NT_LOG(DBG, NTHW,
+ "%s: I2C%d: Write retry=%d (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, retry, dev_addr,
+ reg_addr);
+#endif
+ }
+
+ return 0;
+}
+
+int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ uint32_t value;
+ int count;
+ int i;
+
+ if (data_len == 0)
+ return -1;
+
+ count = data_len - 1;
+ if (nthw_iic_bus_ready(p)) {
+ /* Reset TX fifo */
+ nthw_iic_reg_control_txfifo_reset(p);
+
+ /* Write device address to TX_FIFO and set start bit!! */
+ value = (dev_addr << 1) | I2C_TRANSMIT_WR;
+ nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
+
+ /* Write reg_addr to TX FIFO */
+ nthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 0);
+
+ for (i = 0; i < count; i++) {
+ /* Write data byte to TX fifo and set stop bit */
+ nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0);
+ p_byte++;
+ }
+
+ /* Write data byte to TX fifo and set stop bit */
+ nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1);
+
+ if (!nthw_iic_bus_ready(p)) {
+ NT_LOG(WRN, NTHW, "%s: warn: !busReady (%s:%u)\n",
+ p_adapter_id_str, __func__, __LINE__);
+ while (true) {
+ if (nthw_iic_bus_ready(p)) {
+ NT_LOG(DBG, NTHW,
+ "%s: info: busReady (%s:%u)\n",
+ p_adapter_id_str, __func__,
+ __LINE__);
+ break;
+ }
+ }
+ }
+
+ return 0;
+
+ } else {
+ NT_LOG(WRN, NTHW, "%s: (%s:%u)\n", p_adapter_id_str, __func__,
+ __LINE__);
+ return -1;
+ }
+}
+
+/*
+ * Support function for read/write functions below. Waits for bus ready.
+ */
+bool nthw_iic_bus_ready(nthw_iic_t *p)
+{
+ int count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000);
+ bool b_bus_busy = true;
+
+ while (true) {
+ nthw_iic_reg_busbusy(p, &b_bus_busy);
+ if (!b_bus_busy)
+ break;
+
+ count--;
+ if (count <= 0) /* Test for timeout */
+ break;
+
+ if (p->mn_poll_delay != 0)
+ I2C_WAIT_US(p->mn_poll_delay);
+ }
+
+ if (count == 0)
+ return false;
+
+ return true;
+}
+
+/*
+ * Support function for read function. Waits for data ready.
+ */
+bool nthw_iic_data_ready(nthw_iic_t *p)
+{
+ int count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000);
+ bool b_rx_fifo_empty = true;
+
+ while (true) {
+ nthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty);
+ if (!b_rx_fifo_empty)
+ break;
+
+ count--;
+ if (count <= 0) /* Test for timeout */
+ break;
+
+ if (p->mn_poll_delay != 0)
+ I2C_WAIT_US(p->mn_poll_delay);
+ }
+
+ if (count == 0)
+ return false;
+
+ return true;
+}
+
+int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr)
+{
+ const char *const p_adapter_id_str _unused =
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int res;
+ uint8_t data_val = -1;
+
+ res = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1,
+ &data_val);
+ if (res == 0) {
+ NT_LOG(DBG, NTHW,
+ "%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\n",
+ p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr,
+ n_reg_addr, data_val, data_val, res);
+ }
+ return res;
+}
+
+int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate)
+{
+ const char *const p_adapter_id_str _unused =
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+
+ int res = 0;
+ int i = 0;
+
+ if (b_increate) {
+ for (i = n_dev_addr_start; i < 128; i++) {
+ res = nthw_iic_scan_dev_addr(p, i, 0x00);
+ if (res == 0)
+ break;
+ }
+ } else {
+ for (i = n_dev_addr_start; i >= 0; i--) {
+ res = nthw_iic_scan_dev_addr(p, i, 0x00);
+ if (res == 0)
+ break;
+ }
+ }
+ NT_LOG(DBG, NTHW, "%s: I2C%d: FOUND: %d\n", p_adapter_id_str,
+ p->mn_iic_instance, i);
+ return (res == 0 ? i : -1);
+}
+
+int nthw_iic_scan(nthw_iic_t *p)
+{
+ int i;
+
+ for (i = 0; i < 128; i++)
+ (void)nthw_iic_scan_dev_addr(p, i, 0x00);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.h b/drivers/net/ntnic/nthw/core/nthw_iic.h
new file mode 100644
index 0000000000..e3bd313c88
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_iic.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_IIC_H__
+#define __NTHW_IIC_H__
+
+#include "nthw_fpga_model.h"
+
+struct nthw_iic {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_iic;
+ int mn_iic_instance;
+
+ uint32_t mn_iic_cycle_time;
+ int mn_poll_delay;
+ int mn_bus_ready_retry;
+ int mn_data_ready_retry;
+ int mn_read_data_retry;
+ int mn_write_data_retry;
+
+ nt_register_t *mp_reg_tsusta;
+ nt_field_t *mp_fld_tsusta;
+
+ nt_register_t *mp_reg_tsusto;
+ nt_field_t *mp_fld_tsusto;
+
+ nt_register_t *mp_reg_thdsta;
+ nt_field_t *mp_fld_thdsta;
+
+ nt_register_t *mp_reg_tsudat;
+ nt_field_t *mp_fld_tsudat;
+
+ nt_register_t *mp_reg_tbuf;
+ nt_field_t *mp_fld_tbuf;
+
+ nt_register_t *mp_reg_thigh;
+ nt_field_t *mp_fld_thigh;
+
+ nt_register_t *mp_reg_tlow;
+ nt_field_t *mp_fld_tlow;
+
+ nt_register_t *mp_reg_thddat;
+ nt_field_t *mp_fld_thddat;
+
+ nt_register_t *mp_reg_cr;
+ nt_field_t *mp_fld_cr_en;
+ nt_field_t *mp_fld_cr_msms;
+ nt_field_t *mp_fld_cr_txfifo_reset;
+ nt_field_t *mp_fld_cr_txak;
+
+ nt_register_t *mp_reg_sr;
+ nt_field_t *mp_fld_sr_bb;
+ nt_field_t *mp_fld_sr_rxfifo_full;
+ nt_field_t *mp_fld_sr_rxfifo_empty;
+ nt_field_t *mp_fld_sr_txfifo_full;
+ nt_field_t *mp_fld_sr_txfifo_empty;
+
+ nt_register_t *mp_reg_tx_fifo;
+ nt_field_t *mp_fld_tx_fifo_txdata;
+ nt_field_t *mp_fld_tx_fifo_start;
+ nt_field_t *mp_fld_tx_fifo_stop;
+
+ nt_register_t *mp_reg_rx_fifo_pirq;
+ nt_field_t *mp_fld_rx_fifo_pirq_cmp_val;
+
+ nt_register_t *mp_reg_rx_fifo;
+ nt_field_t *mp_fld_rx_fifo_rxdata;
+
+ nt_register_t *mp_reg_softr;
+ nt_field_t *mp_fld_softr_rkey;
+};
+
+typedef struct nthw_iic nthw_iic_t;
+typedef struct nthw_iic nthw_iic;
+
+nthw_iic_t *nthw_iic_new(void);
+int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance,
+ uint32_t n_iic_cycle_time);
+void nthw_iic_delete(nthw_iic_t *p);
+
+int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay,
+ const int n_bus_ready_retry, const int n_data_ready_retry,
+ const int n_read_data_retry, const int n_write_data_retry);
+
+int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void);
+int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte);
+int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void);
+int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte);
+bool nthw_iic_bus_ready(nthw_iic_t *p);
+bool nthw_iic_data_ready(nthw_iic_t *p);
+
+int nthw_iic_scan(nthw_iic_t *p);
+int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr);
+int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate);
+
+#endif /* __NTHW_IIC_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c
new file mode 100644
index 0000000000..d206c374b4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c
@@ -0,0 +1,1034 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_mac_pcs.h"
+
+#define NTHW_MAC_PCS_LANES (20)
+
+static const uint8_t c_pcs_lanes = NTHW_MAC_PCS_LANES;
+static const uint8_t c_mac_pcs_receiver_mode_dfe _unused;
+
+nthw_mac_pcs_t *nthw_mac_pcs_new(void)
+{
+ nthw_mac_pcs_t *p = malloc(sizeof(nthw_mac_pcs_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_mac_pcs_t));
+ return p;
+}
+
+void nthw_mac_pcs_delete(nthw_mac_pcs_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_mac_pcs_t));
+ free(p);
+ }
+}
+
+/*
+ * Parameters:
+ * p != NULL: init struct pointed to by p
+ * p == NULL: check fpga module(s) presence (but no struct to init)
+ *
+ * Return value:
+ * <0: if p == NULL then fpga module(s) is/are not present.
+ * if p != NULL then fpga module(s) is/are not present, struct undefined
+ * ==0: if p == NULL then fpga module(s) is/are are present (no struct to init)
+ * : if p != NULL then fpga module(s) is/are present and struct initialized
+ */
+int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_MAC_PCS, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: MAC_PCS %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_mac_pcs = mod;
+
+ assert(n_instance >= 0 && n_instance <= 255);
+ nthw_mac_pcs_set_port_no(p, (uint8_t)n_instance);
+
+ {
+ nt_register_t *p_reg_block_lock, *p_reg_stat_pcs_rx,
+ *p_reg_stat_pcs_rx_latch;
+ nt_register_t *p_reg_vl_demuxed, *p_reg_gty_stat, *p_reg_pcs_config,
+ *p_reg_phymac_misc;
+ const int product_id = fpga_get_product_id(p_fpga);
+
+ p_reg_block_lock =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BLOCK_LOCK);
+ p->mp_reg_block_lock = p_reg_block_lock;
+ p->mp_fld_block_lock_lock =
+ register_get_field(p_reg_block_lock, MAC_PCS_BLOCK_LOCK_LOCK);
+
+ p_reg_stat_pcs_rx =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_STAT_PCS_RX);
+ p->mp_reg_stat_pcs_rx = p_reg_stat_pcs_rx;
+ p->mp_fld_stat_pcs_rx_status =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_STATUS);
+ p->mp_fld_stat_pcs_rx_aligned =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED);
+ p->mp_fld_stat_pcs_rx_aligned_err =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED_ERR);
+ p->mp_fld_stat_pcs_rx_misaligned =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_MISALIGNED);
+ p->mp_fld_stat_pcs_rx_internal_local_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT);
+ p->mp_fld_stat_pcs_rx_received_local_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT);
+ p->mp_fld_stat_pcs_rx_local_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_LOCAL_FAULT);
+ p->mp_fld_stat_pcs_rx_remote_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_REMOTE_FAULT);
+ p->mp_fld_stat_pcs_rx_hi_ber =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_HI_BER);
+
+ p_reg_stat_pcs_rx_latch =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_STAT_PCS_RX_LATCH);
+ p->mp_reg_stat_pcs_rx_latch = p_reg_stat_pcs_rx_latch;
+ p->mp_fld_stat_pcs_rx_latch_status =
+ register_get_field(p_reg_stat_pcs_rx_latch,
+ MAC_PCS_STAT_PCS_RX_LATCH_STATUS);
+
+ p_reg_vl_demuxed =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_VL_DEMUXED);
+ p->mp_fld_vl_demuxed_lock =
+ register_get_field(p_reg_vl_demuxed, MAC_PCS_VL_DEMUXED_LOCK);
+
+ p_reg_gty_stat =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_STAT);
+ p->mp_fld_gty_stat_tx_rst_done0 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_0);
+ p->mp_fld_gty_stat_tx_rst_done1 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_1);
+ p->mp_fld_gty_stat_tx_rst_done2 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_2);
+ p->mp_fld_gty_stat_tx_rst_done3 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_3);
+ p->mp_fld_gty_stat_rx_rst_done0 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_0);
+ p->mp_fld_gty_stat_rx_rst_done1 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_1);
+ p->mp_fld_gty_stat_rx_rst_done2 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_2);
+ p->mp_fld_gty_stat_rx_rst_done3 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_3);
+
+ p->m_fld_block_lock_lock_mask = 0;
+ p->m_fld_vl_demuxed_lock_mask = 0;
+ p->m_fld_gty_stat_tx_rst_done_mask = 0;
+ p->m_fld_gty_stat_rx_rst_done_mask = 0;
+
+ if (product_id == 9563) {
+ /* NT200A01_2X100 implements 20 virtual lanes */
+ p->m_fld_block_lock_lock_mask = (1 << 20) - 1;
+ /* NT200A01_2X100 implements 20 virtual lanes */
+ p->m_fld_vl_demuxed_lock_mask = (1 << 20) - 1;
+ p->m_fld_gty_stat_tx_rst_done_mask =
+ 1; /* NT200A01_2X100 implements 4 GTY */
+ p->m_fld_gty_stat_rx_rst_done_mask =
+ 1; /* NT200A01_2X100 implements 4 GTY */
+ } else {
+ /* Remember to add new productIds */
+ assert(0);
+ }
+
+ p_reg_pcs_config = module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_MAC_PCS_CONFIG);
+ p->mp_fld_pcs_config_tx_path_rst =
+ register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST);
+ p->mp_fld_pcs_config_rx_path_rst =
+ register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST);
+ p->mp_fld_pcs_config_rx_enable =
+ register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE);
+ p->mp_fld_pcs_config_rx_force_resync =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC);
+ p->mp_fld_pcs_config_rx_test_pattern =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN);
+ p->mp_fld_pcs_config_tx_enable =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE);
+ p->mp_fld_pcs_config_tx_send_idle =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE);
+ p->mp_fld_pcs_config_tx_send_rfi =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI);
+ p->mp_fld_pcs_config_tx_test_pattern =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN);
+
+ p->mp_reg_gty_loop =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_LOOP);
+ p->mp_fld_gty_loop_gt_loop0 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_0);
+ p->mp_fld_gty_loop_gt_loop1 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_1);
+ p->mp_fld_gty_loop_gt_loop2 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_2);
+ p->mp_fld_gty_loop_gt_loop3 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_3);
+
+ p_reg_phymac_misc =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_PHYMAC_MISC);
+ p->mp_reg_phymac_misc = p_reg_phymac_misc;
+ p->mp_fld_phymac_misc_tx_sel_host =
+ register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_HOST);
+ p->mp_fld_phymac_misc_tx_sel_tfg =
+ register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_TFG);
+ p->mp_fld_phymac_misc_tx_sel_rx_loop =
+ register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP);
+
+ /* SOP or EOP TIMESTAMP */
+ p->mp_fld_phymac_misc_ts_eop =
+ register_query_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TS_EOP);
+
+ p->mp_reg_link_summary =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_LINK_SUMMARY);
+ p->mp_fld_link_summary_abs =
+ register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_ABS);
+ p->mp_fld_link_summary_nt_phy_link_state =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE);
+ p->mp_fld_link_summary_lh_abs =
+ register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_LH_ABS);
+ p->mp_fld_link_summary_ll_nt_phy_link_state =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE);
+ p->mp_fld_link_summary_link_down_cnt =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT);
+ p->mp_fld_link_summary_nim_interr =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_NIM_INTERR);
+ p->mp_fld_link_summary_lh_local_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT);
+ p->mp_fld_link_summary_lh_remote_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT);
+ p->mp_fld_link_summary_local_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LOCAL_FAULT);
+ p->mp_fld_link_summary_remote_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_REMOTE_FAULT);
+
+ p->mp_reg_bip_err =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BIP_ERR);
+ p->mp_fld_reg_bip_err_bip_err =
+ register_get_field(p->mp_reg_bip_err, MAC_PCS_BIP_ERR_BIP_ERR);
+
+ p->mp_reg_fec_ctrl =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CTRL);
+ p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in =
+ register_get_field(p->mp_reg_fec_ctrl, MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN);
+
+ p->mp_reg_fec_stat =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_STAT);
+ p->mp_field_fec_stat_bypass =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_BYPASS);
+ p->mp_field_fec_stat_valid =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_VALID);
+ p->mp_field_fec_stat_am_lock0 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_0);
+ p->mp_field_fec_stat_am_lock1 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_1);
+ p->mp_field_fec_stat_am_lock2 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_2);
+ p->mp_field_fec_stat_am_lock3 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_3);
+ p->mp_field_fec_stat_fec_lane_algn =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_FEC_LANE_ALGN);
+
+ p->mp_reg_fec_cw_cnt =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CW_CNT);
+ p->mp_field_fec_cw_cnt_cw_cnt =
+ register_get_field(p->mp_reg_fec_cw_cnt, MAC_PCS_FEC_CW_CNT_CW_CNT);
+
+ p->mp_reg_fec_ucw_cnt =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_UCW_CNT);
+ p->mp_field_fec_ucw_cnt_ucw_cnt =
+ register_get_field(p->mp_reg_fec_ucw_cnt, MAC_PCS_FEC_UCW_CNT_UCW_CNT);
+
+ /* GTY_RX_BUF_STAT */
+#ifdef RXBUFSTAT
+ p->mp_reg_gty_rx_buf_stat =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_RX_BUF_STAT);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat0 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat1 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat2 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat3 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3);
+#endif
+
+ /* GTY_PRE_CURSOR */
+ p->mp_reg_gty_pre_cursor =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_PRE_CURSOR);
+ p->mp_field_gty_pre_cursor_tx_pre_csr0 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0);
+ p->mp_field_gty_pre_cursor_tx_pre_csr1 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1);
+ p->mp_field_gty_pre_cursor_tx_pre_csr2 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2);
+ p->mp_field_gty_pre_cursor_tx_pre_csr3 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3);
+
+ /* GTY_DIFF_CTL */
+ p->mp_reg_gty_diff_ctl =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_DIFF_CTL);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3);
+
+ /* GTY_POST_CURSOR */
+ p->mp_reg_gty_post_cursor =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_GTY_POST_CURSOR);
+ p->mp_field_gty_post_cursor_tx_post_csr0 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0);
+ p->mp_field_gty_post_cursor_tx_post_csr1 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1);
+ p->mp_field_gty_post_cursor_tx_post_csr2 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2);
+ p->mp_field_gty_post_cursor_tx_post_csr3 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3);
+
+ /* GTY_CTL */
+ p->mp_reg_gty_ctl =
+ module_query_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL);
+ if (p->mp_reg_gty_ctl) {
+ p->mp_field_gty_ctl_tx_pol0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_0);
+ p->mp_field_gty_ctl_tx_pol1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_1);
+ p->mp_field_gty_ctl_tx_pol2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_2);
+ p->mp_field_gty_ctl_tx_pol3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_3);
+ } else {
+ p->mp_reg_gty_ctl =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_GTY_CTL_RX);
+ p->mp_reg_gty_ctl_tx =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_GTY_CTL_TX);
+ p->mp_field_gty_ctl_tx_pol0 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_0);
+ p->mp_field_gty_ctl_tx_pol1 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_1);
+ p->mp_field_gty_ctl_tx_pol2 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_2);
+ p->mp_field_gty_ctl_tx_pol3 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_3);
+ }
+ p->mp_field_gty_ctl_rx_pol0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_0);
+ p->mp_field_gty_ctl_rx_pol1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_1);
+ p->mp_field_gty_ctl_rx_pol2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_2);
+ p->mp_field_gty_ctl_rx_pol3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_3);
+ p->mp_field_gty_ctl_rx_lpm_en0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_0);
+ p->mp_field_gty_ctl_rx_lpm_en1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_1);
+ p->mp_field_gty_ctl_rx_lpm_en2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_2);
+ p->mp_field_gty_ctl_rx_lpm_en3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_3);
+ p->mp_field_gty_ctl_rx_equa_rst0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_0);
+ p->mp_field_gty_ctl_rx_equa_rst1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_1);
+ p->mp_field_gty_ctl_rx_equa_rst2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_2);
+ p->mp_field_gty_ctl_rx_equa_rst3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_3);
+
+ /* DEBOUNCE_CTRL */
+ p->mp_reg_debounce_ctrl =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_DEBOUNCE_CTRL);
+ p->mp_field_debounce_ctrl_nt_port_ctrl =
+ register_get_field(p->mp_reg_debounce_ctrl,
+ MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL);
+
+ p->mp_reg_time_stamp_comp =
+ module_query_register(p->mp_mod_mac_pcs,
+ MAC_PCS_TIMESTAMP_COMP);
+ if (p->mp_reg_time_stamp_comp) {
+ /* TIMESTAMP_COMP */
+ p->mp_field_time_stamp_comp_rx_dly =
+ register_get_field(p->mp_reg_time_stamp_comp,
+ MAC_PCS_TIMESTAMP_COMP_RX_DLY);
+ p->mp_field_time_stamp_comp_tx_dly =
+ register_get_field(p->mp_reg_time_stamp_comp,
+ MAC_PCS_TIMESTAMP_COMP_TX_DLY);
+ }
+ }
+ return 0;
+}
+
+/* wrapper - for ease of use */
+void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p, bool enable)
+{
+ nthw_mac_pcs_set_tx_sel_host(p, enable);
+ nthw_mac_pcs_set_tx_sel_tfg(p, !enable);
+}
+
+void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_rx_enable);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_rx_enable);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_rx_enable);
+}
+
+void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_tx_enable);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_tx_enable);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_tx_enable);
+}
+
+void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_phymac_misc_tx_sel_host);
+ if (enable)
+ field_set_flush(p->mp_fld_phymac_misc_tx_sel_host);
+
+ else
+ field_clr_flush(p->mp_fld_phymac_misc_tx_sel_host);
+}
+
+void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_phymac_misc_tx_sel_tfg);
+ if (enable)
+ field_set_flush(p->mp_fld_phymac_misc_tx_sel_tfg);
+
+ else
+ field_clr_flush(p->mp_fld_phymac_misc_tx_sel_tfg);
+}
+
+void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable)
+{
+ if (p->mp_fld_phymac_misc_ts_eop) {
+ field_get_updated(p->mp_fld_phymac_misc_ts_eop);
+ if (enable)
+ field_set_flush(p->mp_fld_phymac_misc_ts_eop);
+
+ else
+ field_clr_flush(p->mp_fld_phymac_misc_ts_eop);
+ }
+}
+
+bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p)
+{
+ uint32_t block_lock;
+ uint32_t lane_lock;
+
+ block_lock = field_get_updated(p->mp_fld_block_lock_lock) &
+ p->m_fld_block_lock_lock_mask;
+ lane_lock = field_get_updated(p->mp_fld_vl_demuxed_lock) &
+ p->m_fld_vl_demuxed_lock_mask;
+ if (block_lock == p->m_fld_block_lock_lock_mask &&
+ lane_lock == p->m_fld_vl_demuxed_lock_mask)
+ return true;
+
+ return false;
+}
+
+void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_tx_path_rst);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_tx_path_rst);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_tx_path_rst);
+}
+
+void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_rx_path_rst);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_rx_path_rst);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_rx_path_rst);
+}
+
+bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_pcs_config_rx_path_rst);
+}
+
+void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_tx_send_rfi);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_tx_send_rfi);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_tx_send_rfi);
+}
+
+void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_rx_force_resync);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_rx_force_resync);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_rx_force_resync);
+}
+
+bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p)
+{
+ if ((field_get_updated(p->mp_fld_gty_stat_rx_rst_done0) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_rx_rst_done1) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_rx_rst_done2) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_rx_rst_done3) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask)
+ return true;
+
+ else
+ return false;
+}
+
+bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p)
+{
+ if ((field_get_updated(p->mp_fld_gty_stat_tx_rst_done0) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_tx_rst_done1) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_tx_rst_done2) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_tx_rst_done3) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask)
+ return true;
+
+ else
+ return false;
+}
+
+void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable)
+{
+ register_update(p->mp_reg_gty_loop);
+ if (enable) {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 2);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 2);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 2);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 2);
+ } else {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0);
+ }
+ register_flush(p->mp_reg_gty_loop, 1);
+}
+
+void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable)
+{
+ register_update(p->mp_reg_gty_loop);
+ if (enable) {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 4);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 4);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 4);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 4);
+ } else {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0);
+ }
+ register_flush(p->mp_reg_gty_loop, 1);
+}
+
+void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p)
+{
+ uint32_t lane_bit_errors[NTHW_MAC_PCS_LANES];
+
+ register_update(p->mp_reg_bip_err);
+ field_get_val(p->mp_fld_reg_bip_err_bip_err, (uint32_t *)lane_bit_errors,
+ ARRAY_SIZE(lane_bit_errors));
+
+#if defined(DEBUG)
+ {
+ uint8_t lane;
+
+ for (lane = 0; lane < c_pcs_lanes; lane++) {
+ if (lane_bit_errors[lane]) {
+ NT_LOG(DBG, NTHW,
+ "Port %u: pcsLane %2u: BIP8 errors: %u\n",
+ p->m_port_no, lane, lane_bit_errors[lane]);
+ }
+ }
+ }
+#else
+ (void)c_pcs_lanes; /* unused - kill warning */
+#endif
+}
+
+void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status)
+{
+ *status = field_get_updated(p->mp_fld_stat_pcs_rx_status) & 0x01;
+}
+
+bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_stat_pcs_rx_hi_ber);
+}
+
+void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs,
+ uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs,
+ uint32_t *p_ll_nt_phy_link_state,
+ uint32_t *p_link_down_cnt, uint32_t *p_nim_interr,
+ uint32_t *p_lh_local_fault,
+ uint32_t *p_lh_remote_fault, uint32_t *p_local_fault,
+ uint32_t *p_remote_fault)
+{
+ register_update(p->mp_reg_link_summary);
+ if (p_abs)
+ *p_abs = field_get_val32(p->mp_fld_link_summary_abs);
+ if (p_nt_phy_link_state) {
+ *p_nt_phy_link_state =
+ field_get_val32(p->mp_fld_link_summary_nt_phy_link_state);
+ }
+ if (p_lh_abs)
+ *p_lh_abs = field_get_val32(p->mp_fld_link_summary_lh_abs);
+ if (p_ll_nt_phy_link_state) {
+ *p_ll_nt_phy_link_state =
+ field_get_val32(p->mp_fld_link_summary_ll_nt_phy_link_state);
+ }
+ if (p_link_down_cnt)
+ *p_link_down_cnt = field_get_val32(p->mp_fld_link_summary_link_down_cnt);
+ if (p_nim_interr)
+ *p_nim_interr = field_get_val32(p->mp_fld_link_summary_nim_interr);
+ if (p_lh_local_fault) {
+ *p_lh_local_fault =
+ field_get_val32(p->mp_fld_link_summary_lh_local_fault);
+ }
+ if (p_lh_remote_fault) {
+ *p_lh_remote_fault =
+ field_get_val32(p->mp_fld_link_summary_lh_remote_fault);
+ }
+ if (p_local_fault)
+ *p_local_fault = field_get_val32(p->mp_fld_link_summary_local_fault);
+ if (p_remote_fault)
+ *p_remote_fault = field_get_val32(p->mp_fld_link_summary_remote_fault);
+}
+
+/*
+ * Returns true if the lane/block lock bits indicate that a reset is required.
+ * This is the case if Block/Lane lock is not all zero but not all set either.
+ */
+bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p)
+{
+ uint32_t block_lock = nthw_mac_pcs_get_fld_block_lock_lock(p);
+ uint32_t lane_lock = nthw_mac_pcs_get_fld_lane_lock_lock(p);
+ uint32_t block_lock_mask = nthw_mac_pcs_get_fld_block_lock_lock_mask(p);
+ uint32_t lane_lock_mask = nthw_mac_pcs_get_fld_lane_lock_lock_mask(p);
+
+ return ((block_lock != 0) && (block_lock != block_lock_mask)) ||
+ ((lane_lock != 0) && (lane_lock != lane_lock_mask));
+}
+
+void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable)
+{
+ NT_LOG(DBG, NTHW, "Port %u: Set FEC: %u\n", p->m_port_no, enable);
+
+ field_get_updated(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in);
+ if (enable) {
+ field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, 0);
+ } else {
+ field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in,
+ (1 << 5) - 1);
+ }
+
+ /* Both Rx and Tx must be reset for new FEC state to become active */
+ nthw_mac_pcs_rx_path_rst(p, true);
+ nthw_mac_pcs_tx_path_rst(p, true);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+
+ nthw_mac_pcs_rx_path_rst(p, false);
+ nthw_mac_pcs_tx_path_rst(p, false);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+
+#ifdef DEBUG
+ if (enable) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC valid: %u\n", p->m_port_no,
+ field_get_updated(p->mp_field_fec_stat_valid));
+ } else {
+ NT_LOG(DBG, NTHW, "Port %u: FEC bypass: %u\n", p->m_port_no,
+ field_get_updated(p->mp_field_fec_stat_bypass));
+ }
+#endif
+}
+
+bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_field_fec_stat_bypass);
+}
+
+bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_field_fec_stat_valid);
+}
+
+bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_field_fec_stat_fec_lane_algn);
+}
+
+bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_stat);
+ if ((field_get_val32(p->mp_field_fec_stat_am_lock0)) ||
+ (field_get_val32(p->mp_field_fec_stat_am_lock1)) ||
+ (field_get_val32(p->mp_field_fec_stat_am_lock2)) ||
+ (field_get_val32(p->mp_field_fec_stat_am_lock3)))
+ return true;
+ return false;
+}
+
+bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_stat);
+ if ((field_get_val32(p->mp_field_fec_stat_am_lock0)) &&
+ (field_get_val32(p->mp_field_fec_stat_am_lock1)) &&
+ (field_get_val32(p->mp_field_fec_stat_am_lock2)) &&
+ (field_get_val32(p->mp_field_fec_stat_am_lock3)))
+ return true;
+ return false;
+}
+
+void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_stat);
+ NT_LOG(DBG, NTHW,
+ "Port %u: FEC_STAT VALID: %u, AM_LOCK_0: %u, AM_LOCK_1: %u, AM_LOCK_2: %u, AM_LOCK_0: %u, FEC_LANE_ALGN: %u\n",
+ p->m_port_no, field_get_val32(p->mp_field_fec_stat_valid),
+ field_get_val32(p->mp_field_fec_stat_am_lock0),
+ field_get_val32(p->mp_field_fec_stat_am_lock1),
+ field_get_val32(p->mp_field_fec_stat_am_lock2),
+ field_get_val32(p->mp_field_fec_stat_am_lock3),
+ field_get_val32(p->mp_field_fec_stat_fec_lane_algn));
+}
+
+void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_cw_cnt);
+ register_update(p->mp_reg_fec_ucw_cnt);
+
+ if (field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u\n", p->m_port_no,
+ field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt));
+ }
+ if (field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u\n", p->m_port_no,
+ field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt));
+ }
+}
+
+bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_gty_rx_buf_stat);
+
+ if (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3)) {
+ if (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3)) {
+ NT_LOG(DBG, NTHW,
+ "Port %u: GTY RX_BUF_STAT_0: %u, RX_BUF_STAT_1: %u, RX_BUF_STAT_2: %u, RX_BUF_STAT_3: %u\n",
+ p->m_port_no,
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0),
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1),
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2),
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3));
+
+ return true;
+ }
+ }
+ return false;
+}
+
+void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr,
+ uint8_t tx_diff_ctl, uint8_t tx_post_csr)
+{
+ /* GTY_PRE_CURSOR */
+ register_update(p->mp_reg_gty_pre_cursor);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr0,
+ tx_pre_csr & 0x1F);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr1,
+ tx_pre_csr & 0x1F);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr2,
+ tx_pre_csr & 0x1F);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr3,
+ tx_pre_csr & 0x1F);
+ break;
+ }
+
+ /* GTY_DIFF_CTL */
+ register_update(p->mp_reg_gty_diff_ctl);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0,
+ tx_diff_ctl & 0x1F);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1,
+ tx_diff_ctl & 0x1F);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2,
+ tx_diff_ctl & 0x1F);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3,
+ tx_diff_ctl & 0x1F);
+ break;
+ }
+
+ /* GTY_POST_CURSOR */
+ register_update(p->mp_reg_gty_post_cursor);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr0,
+ tx_post_csr & 0x1F);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr1,
+ tx_post_csr & 0x1F);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr2,
+ tx_post_csr & 0x1F);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr3,
+ tx_post_csr & 0x1F);
+ break;
+ }
+
+ NT_LOG(DBG, NTHW,
+ "Port %u, lane %u: GTY txPreCsr: %d, txDiffCtl: %d, txPostCsr: %d\n",
+ p->m_port_no, lane, tx_pre_csr, tx_diff_ctl, tx_post_csr);
+}
+
+/*
+ * Set receiver equalization mode
+ * 0: enable DFE
+ * mode 1: enable LPM
+ *
+ * See UltraScale Architecture GTY Transceivers www.xilinx.com page 181,
+ * UG578 (v1.1) November 24, 2015
+ */
+void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode)
+{
+ register_update(p->mp_reg_gty_ctl);
+ field_set_val32(p->mp_field_gty_ctl_rx_lpm_en0, mode & 0x1);
+ field_set_val32(p->mp_field_gty_ctl_rx_lpm_en1, mode & 0x1);
+ field_set_val32(p->mp_field_gty_ctl_rx_lpm_en2, mode & 0x1);
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_lpm_en3, mode & 0x1);
+
+ /* Toggle reset */
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 1);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 1);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 1);
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 1);
+
+ NT_OS_WAIT_USEC(1000); /* 1ms */
+
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 0);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 0);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 0);
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 0);
+
+ NT_LOG(DBG, NTHW, "Port %u: GTY receiver mode: %s\n", p->m_port_no,
+ (mode == c_mac_pcs_receiver_mode_dfe ? "DFE" : "LPM"));
+}
+
+void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap)
+{
+ register_update(p->mp_reg_gty_ctl);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol0, swap);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol1, swap);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol2, swap);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol3, swap);
+ break;
+ }
+ NT_LOG(DBG, NTHW, "Port %u: set GTY Tx lane (%d) polarity: %d\n",
+ p->m_port_no, lane, swap);
+}
+
+void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap)
+{
+ register_update(p->mp_reg_gty_ctl);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol0, swap);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol1, swap);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol2, swap);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol3, swap);
+ break;
+ }
+ NT_LOG(DBG, NTHW, "Port %u: set GTY Rx lane (%d) polarity: %d\n",
+ p->m_port_no, lane, swap);
+}
+
+void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode)
+{
+ field_get_updated(p->mp_field_debounce_ctrl_nt_port_ctrl);
+ field_set_val_flush32(p->mp_field_debounce_ctrl_nt_port_ctrl, mode);
+}
+
+void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly)
+{
+ if (p->mp_field_time_stamp_comp_rx_dly) {
+ field_get_updated(p->mp_field_time_stamp_comp_rx_dly);
+ field_set_val_flush32(p->mp_field_time_stamp_comp_rx_dly, rx_dly);
+ }
+}
+
+void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no)
+{
+ p->m_port_no = port_no;
+}
+
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_block_lock_lock);
+}
+
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p)
+{
+ return p->m_fld_block_lock_lock_mask;
+}
+
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_vl_demuxed_lock);
+}
+
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p)
+{
+ return p->m_fld_vl_demuxed_lock_mask;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h
new file mode 100644
index 0000000000..08197f8b9e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h
@@ -0,0 +1,261 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_MAC_PCS_H_
+#define NTHW_MAC_PCS_H_
+
+enum nthw_mac_pcs_led_mode_e {
+ NTHW_MAC_PCS_LED_AUTO = 0x00,
+ NTHW_MAC_PCS_LED_ON = 0x01,
+ NTHW_MAC_PCS_LED_OFF = 0x02,
+ NTHW_MAC_PCS_LED_PORTID = 0x03,
+};
+
+#define nthw_mac_pcs_receiver_mode_dfe (0)
+#define nthw_mac_pcs_receiver_mode_lpm (1)
+
+struct nthw_mac_pcs {
+ uint8_t m_port_no;
+
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_mac_pcs;
+ int mn_instance;
+
+ /* Block lock status */
+ nt_field_t *mp_fld_block_lock_lock;
+ uint32_t m_fld_block_lock_lock_mask;
+
+ /* Lane lock status */
+ nt_field_t *mp_fld_vl_demuxed_lock;
+ uint32_t m_fld_vl_demuxed_lock_mask;
+
+ /* GTY_STAT */
+ nt_field_t *mp_fld_gty_stat_rx_rst_done0;
+ nt_field_t *mp_fld_gty_stat_rx_rst_done1;
+ nt_field_t *mp_fld_gty_stat_rx_rst_done2;
+ nt_field_t *mp_fld_gty_stat_rx_rst_done3;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done0;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done1;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done2;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done3;
+ uint32_t m_fld_gty_stat_rx_rst_done_mask;
+ uint32_t m_fld_gty_stat_tx_rst_done_mask;
+
+ /* GTY_LOOP */
+ nt_register_t *mp_reg_gty_loop;
+ nt_field_t *mp_fld_gty_loop_gt_loop0;
+ nt_field_t *mp_fld_gty_loop_gt_loop1;
+ nt_field_t *mp_fld_gty_loop_gt_loop2;
+ nt_field_t *mp_fld_gty_loop_gt_loop3;
+
+ /* MAC_PCS_CONFIG */
+ nt_field_t *mp_fld_pcs_config_tx_path_rst;
+ nt_field_t *mp_fld_pcs_config_rx_path_rst;
+ nt_field_t *mp_fld_pcs_config_rx_enable;
+ nt_field_t *mp_fld_pcs_config_rx_force_resync;
+ nt_field_t *mp_fld_pcs_config_rx_test_pattern;
+ nt_field_t *mp_fld_pcs_config_tx_enable;
+ nt_field_t *mp_fld_pcs_config_tx_send_idle;
+ nt_field_t *mp_fld_pcs_config_tx_send_rfi;
+ nt_field_t *mp_fld_pcs_config_tx_test_pattern;
+
+ /* STAT PCS */
+ nt_field_t *mp_fld_stat_pcs_rx_status;
+ nt_field_t *mp_fld_stat_pcs_rx_aligned;
+ nt_field_t *mp_fld_stat_pcs_rx_aligned_err;
+ nt_field_t *mp_fld_stat_pcs_rx_misaligned;
+ nt_field_t *mp_fld_stat_pcs_rx_internal_local_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_received_local_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_local_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_remote_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_hi_ber;
+
+ /* STAT_PCS_RX_LATCH */
+ nt_field_t *mp_fld_stat_pcs_rx_latch_status;
+
+ /* PHYMAC_MISC */
+ nt_field_t *mp_fld_phymac_misc_tx_sel_host;
+ nt_field_t *mp_fld_phymac_misc_tx_sel_tfg;
+ nt_field_t *mp_fld_phymac_misc_tx_sel_rx_loop;
+ nt_field_t *mp_fld_phymac_misc_ts_eop;
+
+ /* LINK_SUMMARY */
+ nt_register_t *mp_reg_link_summary;
+ nt_field_t *mp_fld_link_summary_abs;
+ nt_field_t *mp_fld_link_summary_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_lh_abs;
+ nt_field_t *mp_fld_link_summary_ll_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_link_down_cnt;
+ nt_field_t *mp_fld_link_summary_nim_interr;
+ nt_field_t *mp_fld_link_summary_lh_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_remote_fault;
+ nt_field_t *mp_fld_link_summary_local_fault;
+ nt_field_t *mp_fld_link_summary_remote_fault;
+
+ /* BIP_ERR */
+ nt_register_t *mp_reg_bip_err;
+ nt_field_t *mp_fld_reg_bip_err_bip_err;
+
+ /* FEC_CTRL */
+ nt_register_t *mp_reg_fec_ctrl;
+ nt_field_t *mp_field_fec_ctrl_reg_rs_fec_ctrl_in;
+
+ /* FEC_STAT */
+ nt_register_t *mp_reg_fec_stat;
+ nt_field_t *mp_field_fec_stat_bypass;
+ nt_field_t *mp_field_fec_stat_valid;
+ nt_field_t *mp_field_fec_stat_am_lock0;
+ nt_field_t *mp_field_fec_stat_am_lock1;
+ nt_field_t *mp_field_fec_stat_am_lock2;
+ nt_field_t *mp_field_fec_stat_am_lock3;
+ nt_field_t *mp_field_fec_stat_fec_lane_algn;
+
+ /* FEC Corrected code word count */
+ nt_register_t *mp_reg_fec_cw_cnt;
+ nt_field_t *mp_field_fec_cw_cnt_cw_cnt;
+
+ /* FEC Uncorrected code word count */
+ nt_register_t *mp_reg_fec_ucw_cnt;
+ nt_field_t *mp_field_fec_ucw_cnt_ucw_cnt;
+
+ /* GTY_RX_BUF_STAT */
+ nt_register_t *mp_reg_gty_rx_buf_stat;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat0;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat1;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat2;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat3;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed0;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed1;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed2;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed3;
+
+ /* GTY_PRE_CURSOR */
+ nt_register_t *mp_reg_gty_pre_cursor;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr0;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr1;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr2;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr3;
+
+ /* GTY_DIFF_CTL */
+ nt_register_t *mp_reg_gty_diff_ctl;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl0;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl1;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl2;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl3;
+
+ /* GTY_POST_CURSOR */
+ nt_register_t *mp_reg_gty_post_cursor;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr0;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr1;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr2;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr3;
+
+ /* GTY_CTL */
+ nt_register_t *mp_reg_gty_ctl;
+ nt_register_t *mp_reg_gty_ctl_tx;
+ nt_field_t *mp_field_gty_ctl_tx_pol0;
+ nt_field_t *mp_field_gty_ctl_tx_pol1;
+ nt_field_t *mp_field_gty_ctl_tx_pol2;
+ nt_field_t *mp_field_gty_ctl_tx_pol3;
+ nt_field_t *mp_field_gty_ctl_rx_pol0;
+ nt_field_t *mp_field_gty_ctl_rx_pol1;
+ nt_field_t *mp_field_gty_ctl_rx_pol2;
+ nt_field_t *mp_field_gty_ctl_rx_pol3;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en0;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en1;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en2;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en3;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst0;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst1;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst2;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst3;
+
+ /* DEBOUNCE_CTRL */
+ nt_register_t *mp_reg_debounce_ctrl;
+ nt_field_t *mp_field_debounce_ctrl_nt_port_ctrl;
+
+ /* TIMESTAMP_COMP */
+ nt_register_t *mp_reg_time_stamp_comp;
+ nt_field_t *mp_field_time_stamp_comp_rx_dly;
+ nt_field_t *mp_field_time_stamp_comp_tx_dly;
+
+ /* STAT_PCS_RX */
+ nt_register_t *mp_reg_stat_pcs_rx;
+
+ /* STAT_PCS_RX */
+ nt_register_t *mp_reg_stat_pcs_rx_latch;
+
+ /* PHYMAC_MISC */
+ nt_register_t *mp_reg_phymac_misc;
+
+ /* BLOCK_LOCK */
+ nt_register_t *mp_reg_block_lock;
+};
+
+typedef struct nthw_mac_pcs nthw_mac_pcs_t;
+typedef struct nthw_mac_pcs nthw_mac_pcs;
+
+nthw_mac_pcs_t *nthw_mac_pcs_new(void);
+int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_mac_pcs_delete(nthw_mac_pcs_t *p);
+
+bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable);
+bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable);
+bool nthw_mac_pcs_is_dd_r3_calib_done(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p,
+ bool enable); /* wrapper - for ease of use */
+void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status);
+bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p);
+
+void nthw_mac_pcs_get_link_summary1(nthw_mac_pcs_t *p, uint32_t *p_status,
+ uint32_t *p_status_latch, uint32_t *p_aligned,
+ uint32_t *p_local_fault, uint32_t *p_remote_fault);
+
+void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs,
+ uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs,
+ uint32_t *p_ll_nt_phy_link_state,
+ uint32_t *p_link_down_cnt, uint32_t *p_nim_interr,
+ uint32_t *p_lh_local_fault,
+ uint32_t *p_lh_remote_fault, uint32_t *p_local_fault,
+ uint32_t *p_remote_fault);
+
+bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable);
+bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr,
+ uint8_t tx_diff_ctl, uint8_t tx_post_csr);
+void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap);
+void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap);
+void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode);
+void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode);
+void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly);
+void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no);
+
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p);
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p);
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p);
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p);
+
+#endif /* NTHW_MAC_PCS_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c
new file mode 100644
index 0000000000..d8e1f0de5d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c
@@ -0,0 +1,1631 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_mac_pcs_xxv.h"
+
+static void nthw_mac_pcs_xxv_field_set_or_clr_flush(const nt_field_t *f, bool set)
+{
+ if (f) {
+ field_get_updated(f);
+ if (set)
+ field_set_flush(f);
+ else
+ field_clr_flush(f);
+ }
+}
+
+nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void)
+{
+ nthw_mac_pcs_xxv_t *p = malloc(sizeof(nthw_mac_pcs_xxv_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_mac_pcs_xxv_t));
+ return p;
+}
+
+void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_mac_pcs_xxv_t));
+ free(p);
+ }
+}
+
+uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return index == 0 ? (uint8_t)p->mn_instance : index;
+}
+
+void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no)
+{
+ p->m_port_no = port_no;
+}
+
+void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p,
+ uint32_t *p_abs, uint32_t *p_nt_phy_link_state,
+ uint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt,
+ uint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault,
+ uint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault,
+ uint8_t index)
+{
+ struct nthw_mac_pcs_xxv__registers_fields *r =
+ &p->regs[index]; /* register and fields */
+
+ assert(p);
+
+ register_update(r->mp_reg_link_summary);
+ if (p_abs)
+ *p_abs = field_get_val32(r->mp_fld_link_summary_abs);
+ if (p_nt_phy_link_state) {
+ *p_nt_phy_link_state =
+ field_get_val32(r->mp_fld_link_summary_nt_phy_link_state);
+ }
+ if (p_lh_abs)
+ *p_lh_abs = field_get_val32(r->mp_fld_link_summary_lh_abs);
+ if (p_ll_nt_phy_link_state) {
+ *p_ll_nt_phy_link_state =
+ field_get_val32(r->mp_fld_link_summary_ll_nt_phy_link_state);
+ }
+ if (p_link_down_cnt)
+ *p_link_down_cnt = field_get_val32(r->mp_fld_link_summary_link_down_cnt);
+ if (p_nim_interr)
+ *p_nim_interr = field_get_val32(r->mp_fld_link_summary_nim_interr);
+ if (p_lh_local_fault) {
+ *p_lh_local_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_local_fault);
+ }
+ if (p_lh_remote_fault) {
+ *p_lh_remote_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_remote_fault);
+ }
+ if (p_lh_internal_local_fault) {
+ *p_lh_internal_local_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_internal_local_fault);
+ }
+ if (p_lh_received_local_fault) {
+ *p_lh_received_local_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_received_local_fault);
+ }
+}
+
+void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_force_resync;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_gt_data;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_gt_data;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_an_lt;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_speed_ctrl;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_rfi;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_lfi;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi,
+ bool enable_rfi, uint8_t index)
+{
+ register_update(p->regs[index].mp_reg_core_conf);
+ field_set_val32(p->regs[index].mp_fld_core_conf_tx_send_lfi, enable_lfi);
+ field_set_val32(p->regs[index].mp_fld_core_conf_tx_send_rfi, enable_rfi);
+ register_flush(p->regs[index].mp_reg_core_conf, 1);
+}
+
+bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en;
+
+ /* NOTE: DFE is enabled when LPM is disabled */
+ return !field_get_updated(f);
+}
+
+void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en;
+ const bool set_dfe =
+ !enable; /* NOTE: Enable DFE mode means setting LPM = 0 */
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, set_dfe);
+
+ /* Toggle GTY_CTL_RX->EQUA_RST to 1 and 0 to assert new LPM_EN setting */
+ f = p->regs[index].mp_fld_gty_ctl_rx_equa_rst;
+ field_get_updated(f);
+ field_set_val_flush32(f, 1); /* Assert GTH SOFT RESET */
+ field_get_updated(f);
+ field_set_val_flush32(f, 0); /* De-Assert GTH SOFT RESET */
+ field_get_updated(f);
+}
+
+void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_polarity;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_polarity;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_inhibit;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_loop_gt_loop;
+
+ field_get_updated(f);
+ field_set_val_flush32(f, enable ? 2U : 0U);
+}
+
+void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_line_loopback;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_rx_rst);
+}
+
+bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_tx_rst);
+}
+
+/*
+ * QPLL lock signal.
+ * For cores capable of 10G only, there are only 1 QPLL. For cores capable of
+ * 10G/25G, there are 2 QPLLs.
+ */
+bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return (field_get_updated(p->regs[index].mp_fld_sub_rst_status_qpll_lock) ==
+ 3);
+}
+
+bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return (nthw_mac_pcs_xxv_is_qpll_lock(p, index) &&
+ !nthw_mac_pcs_xxv_is_user_rx_rst(p, index) &&
+ !nthw_mac_pcs_xxv_is_user_tx_rst(p, index));
+}
+
+bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_aneg_config_enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_idle;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_ins_fcs;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g;
+
+ return field_get_updated(f) != 0; /* 0 = 25g, 1 = 10g */
+}
+
+void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_link_speed_toggle;
+
+ field_get_updated(f);
+ field_set_flush(f);
+}
+
+void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_rs_fec_conf_rs_fec_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index)
+{
+ const nt_field_t *const f =
+ p->regs[index].mp_field_debounce_ctrl_nt_port_ctrl;
+
+ field_get_updated(f);
+ field_set_val_flush32(f, mode);
+}
+
+void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_mac_pcs;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_mac_pcs;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ register_update(p->regs[index].mp_reg_rs_fec_ccw);
+ register_update(p->regs[index].mp_reg_rs_fec_ucw);
+
+ if (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u", p->m_port_no,
+ field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt));
+ }
+ if (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u", p->m_port_no,
+ field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt));
+ }
+}
+
+void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly,
+ uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_timestamp_comp_rx_dly);
+ field_set_val_flush32(p->regs[index].mp_field_timestamp_comp_rx_dly, rx_dly);
+}
+
+void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly,
+ uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_timestamp_comp_tx_dly);
+ field_set_val_flush32(p->regs[index].mp_field_timestamp_comp_tx_dly, tx_dly);
+}
+
+void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_ts_at_eop;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl);
+ field_set_val_flush32(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl,
+ value);
+}
+
+void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr);
+ field_set_val_flush32(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr, value);
+}
+
+void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_gty_post_cursor_tx_post_csr);
+ field_set_val_flush32(p->regs[index].mp_field_gty_post_cursor_tx_post_csr,
+ value);
+}
+
+void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_lt_conf_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec91_request;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_rs_fec_request;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec74_request;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_bypass;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode,
+ uint8_t index)
+{
+ if (dac_mode == NTHW_MAC_PCS_XXV_DAC_OFF) {
+ nthw_mac_pcs_xxv_reset_an_lt(p, false, index);
+ nthw_mac_pcs_xxv_set_aneg_config_enable(p, false, index);
+ nthw_mac_pcs_xxv_set_aneg_config_bypass(p, true, index);
+ nthw_mac_pcs_xxv_set_lt_conf_enable(p, false, index);
+ nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, true, index);
+ nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, true, index);
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p, true, index);
+ nthw_mac_pcs_xxv_reset_tx_gt_data(p, true, index);
+ nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, false, index);
+ nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, false, index);
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p, false, index);
+ nthw_mac_pcs_xxv_reset_tx_gt_data(p, false, index);
+
+ return;
+ }
+ assert(0); /* If you end up here you need to implement other DAC modes */
+}
+
+bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_fec74_lock);
+}
+
+bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_rsfec_lane_alignment);
+}
+
+int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance,
+ int n_channels)
+{
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_MAC_PCS_XXV, n_instance);
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const bool m_mac8x10_g = false;
+ nt_module_t *module = p_mod;
+ uint64_t n_module_version_packed64 = -1;
+ nt_register_t *r;
+ nt_register_t *(*get_register)(nt_module_t *, uint32_t) =
+ module_get_register;
+ nt_field_t *(*get_field)(const nt_register_t *, uint32_t) =
+ register_get_field;
+ nt_field_t *(*query_field)(const nt_register_t *, uint32_t) =
+ register_query_field;
+ struct nthw_mac_pcs_xxv__registers_fields *rf;
+
+ if (p == NULL)
+ return (p_mod == NULL ? -1 : 0);
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW,
+ "%s: MAC_PCS_XXV instance=%d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_mac_pcs_xxv = p_mod;
+
+ memset(p->regs, 0, sizeof(p->regs));
+
+ n_module_version_packed64 = module_get_version_packed64(p->mp_mod_mac_pcs_xxv);
+ switch (n_module_version_packed64) {
+ case (0UL << 32) | 0UL: /* 0.0 */
+ case (0UL << 32) | 1UL: /* 0.1 */
+ case (0UL << 32) | 2UL: /* 0.2 */
+ NT_LOG(DBG, NTHW,
+ "%s: MAC_PCS_XXV instance=%d: version=0x%08lX\n",
+ p_adapter_id_str, p->mn_instance, n_module_version_packed64);
+ break;
+ default:
+ NT_LOG(ERR, NTHW,
+ "%s: MAC_PCS_XXV instance=%d: version=0x%08lX: unsupported module version\n",
+ p_adapter_id_str, p->mn_instance, n_module_version_packed64);
+ return -1;
+ }
+
+ assert(n_channels == 1 || n_channels == 2 || n_channels == 4);
+
+ /* Register MAC_PCS_XXV_CORE_CONF_0 -- MAC_PCS_XXV_CORE_CONF_3 */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_0);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_1);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_2);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_3);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP);
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_ANEG_CONFIG_0 -- MAC_PCS_XXV_ANEG_CONFIG_3
+ * and MAC_PCS_XXV_ANEG_ABILITY_0 -- MAC_PCS_XXV_ANEG_ABILITY_3
+ * and MAC_PCS_XXV_LT_CONF_0 -- MAC_PCS_XXV_LT_CONF_3
+ */
+ if (!m_mac8x10_g && n_channels < 4) {
+ /* 2 x 10 25 G */
+ /* ANEG_CONFIG */
+ rf = &p->regs[0];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_0);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_0);
+ rf->mp_reg_aneg_ability = r;
+
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr) {
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S);
+ if (!rf->mp_fld_aneg_ability25_g_base_crs) {
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr1) {
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1);
+ }
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_0);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_0_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_0_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_0_SEED);
+ }
+
+ if (!m_mac8x10_g && n_channels >= 2) {
+ /* 2 x 10 25 G */
+ /* ANEG_CONFIG */
+
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_1);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_1);
+ rf->mp_reg_aneg_ability = r;
+
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr) {
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S);
+ if (!rf->mp_fld_aneg_ability25_g_base_crs) {
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr1) {
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1);
+ }
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_1);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_1_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_1_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_1_SEED);
+ }
+
+ if (!m_mac8x10_g && n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_2);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_2);
+ rf->mp_reg_aneg_ability = r;
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR);
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S);
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1);
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_2);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_2_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_2_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_2_SEED);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_3);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_3);
+ rf->mp_reg_aneg_ability = r;
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR);
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S);
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1);
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_3);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_3_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_3_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_3_SEED);
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_SUB_RST_0 -- MAC_PCS_XXV_SUB_RST_3
+ * and MAC_PCS_XXV_SUB_RST_STATUS_0 -- MAC_PCS_XXV_SUB_RST_STATUS_3
+ */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_0);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_0_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_0);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_1);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_1_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_1);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_2);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_2_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_2);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_3);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_3_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_3);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK);
+ }
+
+ /* Registers MAC_PCS_XXV_LINK_SUMMARY_0 -- MAC_PCS_XXV_LINK_SUMMARY_3 */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_0);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_1);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_2);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_3);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR);
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_GTY_LOOP_0 -- MAC_PCS_XXV_GTY_LOOP_3
+ * and MAC_PCS_XXV_GTY_CTL_RX_0 -- MAC_PCS_XXV_GTY_CTL_RX_3
+ * and MAC_PCS_XXV_GTY_CTL_TX_0 -- MAC_PCS_XXV_GTY_CTL_TX_3
+ * and MAC_PCS_XXV_LINK_SPEED_0 -- MAC_PCS_XXV_LINK_SPEED_3
+ * and MAC_PCS_XXV_RS_FEC_CONF_0 -- MAC_PCS_XXV_RS_FEC_CONF_0
+ */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_0);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_0);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_0);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_0);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_0);
+
+ rf->mp_fld_link_speed10_g =
+ query_field(r, MAC_PCS_XXV_LINK_SPEED_0_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_0_10G);
+ }
+
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_0_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_0);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_0);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_0);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT);
+ }
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_1);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_1);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_1);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_1);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_1);
+
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_1_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_1_10G);
+ }
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_1_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_1);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_1);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_1);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT);
+ }
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_2);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_2);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_2);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_2);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_2);
+
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_2_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_2_10G);
+ }
+
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_2_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_2);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_2);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_2);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT);
+ }
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_3);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_3);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_3);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_3);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_3);
+
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_3_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_3_10G);
+ }
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_3_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_3);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_3);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_3);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT);
+ }
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_DEBOUNCE_CTRL_0 -- MAC_PCS_XXV_DEBOUNCE_CTRL_3
+ * and MAC_PCS_XXV_TIMESTAMP_COMP_0 -- MAC_PCS_XXV_TIMESTAMP_COMP_3
+ * and MAC_PCS_XXV_GTY_PRE_CURSOR_0 -- MAC_PCS_XXV_GTY_PRE_CURSOR_3
+ * and MAC_PCS_XXV_GTY_DIFF_CTL_0 -- MAC_PCS_XXV_GTY_DIFF_CTL_0
+ * and MAC_PCS_XXV_GTY_POST_CURSOR_0 -- MAC_PCS_XXV_GTY_POST_CURSOR_3
+ */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_0);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_0);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_0);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_0);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_0);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_1);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_1);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_1);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_1);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_1);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_2);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_2);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_2);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_2);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_2);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_3);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_3);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_3);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_3);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_3);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR);
+ }
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h
new file mode 100644
index 0000000000..5a38494f7e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_MAC_PCS_XXV_H_
+#define NTHW_MAC_PCS_XXV_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "nthw_fpga_model.h"
+
+enum nthw_mac_pcs_xxv_led_mode_e {
+ NTHW_MAC_PCS_XXV_LED_AUTO = 0x00,
+ NTHW_MAC_PCS_XXV_LED_ON = 0x01,
+ NTHW_MAC_PCS_XXV_LED_OFF = 0x02,
+ NTHW_MAC_PCS_XXV_LED_PORTID = 0x03,
+};
+
+enum nthw_mac_pcs_xxv_dac_mode_e {
+ NTHW_MAC_PCS_XXV_DAC_OFF = 0x00,
+ NTHW_MAC_PCS_XXV_DAC_CA_25G_N = 0x01,
+ NTHW_MAC_PCS_XXV_DAC_CA_25G_S = 0x02,
+ NTHW_MAC_PCS_XXV_DAC_CA_25G_L = 0x03,
+};
+
+struct nthw_mac_pcs_xxv {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_mac_pcs_xxv;
+ int mn_instance;
+
+ uint8_t m_port_no;
+
+#define NTHW_MAC_PCS_XXV_NUM_ELEMS 4
+ struct nthw_mac_pcs_xxv__registers_fields {
+ /* CORE_CONF */
+ nt_register_t *mp_reg_core_conf;
+ nt_field_t *mp_fld_core_conf_rx_enable;
+ nt_field_t *mp_fld_core_conf_rx_force_resync;
+ nt_field_t *mp_fld_core_conf_tx_enable;
+ nt_field_t *mp_fld_core_conf_tx_ins_fcs;
+ nt_field_t *mp_fld_core_conf_tx_ign_fcs;
+ nt_field_t *mp_fld_core_conf_tx_send_lfi;
+ nt_field_t *mp_fld_core_conf_tx_send_rfi;
+ nt_field_t *mp_fld_core_conf_tx_send_idle;
+ nt_field_t *mp_fld_core_conf_inline_mode;
+ nt_field_t *mp_fld_core_conf_line_loopback;
+ nt_field_t *mp_fld_core_conf_ts_at_eop;
+
+ /* ANEG_CONFIG */
+ nt_register_t *mp_reg_aneg_config;
+ nt_field_t *mp_fld_aneg_config_enable;
+ nt_field_t *mp_fld_aneg_config_bypass;
+ nt_field_t *mp_fld_aneg_config_restart;
+ nt_field_t *mp_fld_aneg_config_pseudo;
+ nt_field_t *mp_fld_aneg_config_nonce_seed;
+ nt_field_t *mp_fld_aneg_config_remote_fault;
+ nt_field_t *mp_fld_aneg_config_pause;
+ nt_field_t *mp_fld_aneg_config_asmdir;
+ nt_field_t *mp_fld_aneg_config_fec74_request10_g;
+ nt_field_t *mp_fld_aneg_config_hide_fec74;
+ nt_field_t *mp_fld_aneg_config_fec74_request;
+ nt_field_t *mp_fld_aneg_config_fec91_request;
+ nt_field_t *mp_fld_aneg_config_fec91_ability;
+ nt_field_t *mp_fld_aneg_config_rs_fec_request;
+ nt_field_t *mp_fld_aneg_config_sw_fec_overwrite;
+ nt_field_t *mp_fld_aneg_config_sw_speed_overwrite;
+
+ /* ANEG_ABILITY */
+ nt_register_t *mp_reg_aneg_ability;
+ nt_field_t *mp_fld_aneg_ability25_g_base_cr;
+ nt_field_t *mp_fld_aneg_ability25_g_base_crs;
+ nt_field_t *mp_fld_aneg_ability25_g_base_cr1;
+
+ /* LT_CONF */
+ nt_register_t *mp_reg_lt_conf;
+ nt_field_t *mp_fld_lt_conf_enable;
+ nt_field_t *mp_fld_lt_conf_restart;
+ nt_field_t *mp_fld_lt_conf_seed;
+
+ /* SUB_RST */
+ nt_register_t *mp_reg_sub_rst;
+ nt_field_t *mp_fld_sub_rst_rx_mac_pcs;
+ nt_field_t *mp_fld_sub_rst_tx_mac_pcs;
+ nt_field_t *mp_fld_sub_rst_rx_gt_data;
+ nt_field_t *mp_fld_sub_rst_tx_gt_data;
+ nt_field_t *mp_fld_sub_rst_rx_buf;
+ nt_field_t *mp_fld_sub_rst_rx_pma;
+ nt_field_t *mp_fld_sub_rst_tx_pma;
+ nt_field_t *mp_fld_sub_rst_rx_pcs;
+ nt_field_t *mp_fld_sub_rst_tx_pcs;
+ nt_field_t *mp_fld_sub_rst_an_lt;
+ nt_field_t *mp_fld_sub_rst_speed_ctrl;
+
+ /* SUB_RST_STATUS */
+ nt_register_t *mp_reg_sub_rst_status;
+ nt_field_t *mp_fld_sub_rst_status_user_rx_rst;
+ nt_field_t *mp_fld_sub_rst_status_user_tx_rst;
+ nt_field_t *mp_fld_sub_rst_status_qpll_lock;
+
+ /* LINK_SUMMARY */
+ nt_register_t *mp_reg_link_summary;
+ nt_field_t *mp_fld_link_summary_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_ll_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_abs;
+ nt_field_t *mp_fld_link_summary_lh_abs;
+ nt_field_t *mp_fld_link_summary_link_down_cnt;
+ /* Begin 2 x 10/25 Gbps only fields: */
+ nt_field_t *mp_fld_link_summary_ll_rx_fec74_lock;
+ nt_field_t *mp_fld_link_summary_lh_rx_rsfec_hi_ser;
+ nt_field_t *mp_fld_link_summary_ll_rx_rsfec_lane_alignment;
+ nt_field_t *mp_fld_link_summary_ll_tx_rsfec_lane_alignment;
+ nt_field_t *mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code;
+ /* End 2 x 10/25 Gbps only fields. */
+ nt_field_t *mp_fld_link_summary_ll_rx_block_lock;
+ nt_field_t *mp_fld_link_summary_lh_rx_high_bit_error_rate;
+ nt_field_t *mp_fld_link_summary_lh_internal_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_received_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_remote_fault;
+ nt_field_t *mp_fld_link_summary_lh_tx_local_fault;
+ nt_field_t *mp_fld_link_summary_nim_interr;
+
+ /* GTY_LOOP */
+ nt_register_t *mp_reg_gty_loop;
+ nt_field_t *mp_fld_gty_loop_gt_loop;
+
+ /* GTY_CTL_RX */
+ nt_register_t *mp_reg_gty_ctl_rx;
+ nt_field_t *mp_fld_gty_ctl_rx_polarity;
+ nt_field_t *mp_fld_gty_ctl_rx_lpm_en;
+ nt_field_t *mp_fld_gty_ctl_rx_equa_rst;
+
+ /* GTY_CTL_TX */
+ nt_register_t *mp_reg_gty_ctl_tx;
+ nt_field_t *mp_fld_gty_ctl_tx_polarity;
+ nt_field_t *mp_fld_gty_ctl_tx_inhibit;
+
+ /* LINK_SPEED */
+ nt_register_t *mp_reg_link_speed;
+ nt_field_t *mp_fld_link_speed10_g;
+ nt_field_t *mp_fld_link_speed_toggle;
+
+ /* RS_FEC_CONF */
+ nt_register_t *mp_reg_rs_fec_conf;
+ nt_field_t *mp_fld_rs_fec_conf_rs_fec_enable;
+
+ /* DEBOUNCE_CTRL */
+ nt_register_t *mp_reg_debounce_ctrl;
+ nt_field_t *mp_field_debounce_ctrl_nt_port_ctrl;
+
+ /* FEC_CCW_CNT */
+ nt_register_t *mp_reg_rs_fec_ccw;
+ nt_field_t *mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt;
+
+ /* FEC_UCW_CNT */
+ nt_register_t *mp_reg_rs_fec_ucw;
+ nt_field_t *mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt;
+
+ /* TIMESTAMP_COMP */
+ nt_register_t *mp_reg_timestamp_comp;
+ nt_field_t *mp_field_timestamp_comp_rx_dly;
+ nt_field_t *mp_field_timestamp_comp_tx_dly;
+
+ /* GTY_PRE_CURSOR */
+ nt_register_t *mp_reg_gty_pre_cursor;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr;
+
+ /* GTY_DIFF_CTL */
+ nt_register_t *mp_reg_gty_diff_ctl;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl;
+
+ /* GTY_POST_CURSOR */
+ nt_register_t *mp_reg_gty_post_cursor;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr;
+ } regs[NTHW_MAC_PCS_XXV_NUM_ELEMS];
+};
+
+typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv_t;
+typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv;
+
+nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void);
+void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p);
+int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance,
+ int n_channels);
+
+void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p,
+ uint32_t *p_abs, uint32_t *p_nt_phy_link_state,
+ uint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt,
+ uint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault,
+ uint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault,
+ uint8_t index);
+
+uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no);
+
+void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi,
+ bool enable_rfi, uint8_t index);
+
+bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index);
+void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+
+bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index);
+void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);
+void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);
+void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+#endif /* NTHW_MAC_PCS_XXV_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c
new file mode 100644
index 0000000000..92089d2fa3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pci_rd_tg.h"
+
+nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void)
+{
+ nthw_pci_rd_tg_t *p = malloc(sizeof(nthw_pci_rd_tg_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pci_rd_tg_t));
+ return p;
+}
+
+void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pci_rd_tg_t));
+ free(p);
+ }
+}
+
+int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_RD_TG, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCI_RD_TG %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pci_rd_tg = mod;
+
+ p->mn_param_pci_ta_tg_present =
+ fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);
+
+ p->mp_reg_pci_rd_tg_rd_data0 =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA0);
+ p->mp_fld_pci_rd_tg_phys_addr_low =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data0,
+ PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW);
+
+ p->mp_reg_pci_rd_tg_rd_data1 =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA1);
+ p->mp_fld_pci_rd_tg_phys_addr_high =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data1,
+ PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH);
+
+ p->mp_reg_pci_rd_tg_rd_data2 =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA2);
+ p->mp_fld_pci_rd_tg_req_size =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_SIZE);
+ p->mp_fld_pci_rd_tg_wait =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WAIT);
+ p->mp_fld_pci_rd_tg_wrap =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WRAP);
+ /* optional VF host id */
+ p->mp_fld_pci_rd_tg_req_hid =
+ register_query_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_HID);
+
+ p->mp_reg_pci_rd_tg_rd_addr =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDADDR);
+ p->mp_fld_pci_rd_tg_ram_addr =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_addr, PCI_RD_TG_TG_RDADDR_RAM_ADDR);
+
+ p->mp_reg_pci_rd_tg_rd_run =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RD_RUN);
+ p->mp_fld_pci_rd_tg_run_iteration =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_run, PCI_RD_TG_TG_RD_RUN_RD_ITERATION);
+
+ p->mp_reg_pci_rd_tg_rd_ctrl =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_CTRL);
+ p->mp_fld_pci_rd_tg_ctrl_rdy =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_ctrl, PCI_RD_TG_TG_CTRL_TG_RD_RDY);
+
+ return 0;
+}
+
+void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_low,
+ (uint32_t)(n_phys_addr & ((1UL << 32) - 1)));
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_high,
+ (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1)));
+}
+
+void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_ram_addr, n_ram_addr);
+}
+
+void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap)
+{
+ field_set_val32(p->mp_fld_pci_rd_tg_req_size, req_size);
+ field_set_val32(p->mp_fld_pci_rd_tg_wait, wait);
+ field_set_val32(p->mp_fld_pci_rd_tg_wrap, wrap);
+ field_flush_register(p->mp_fld_pci_rd_tg_wrap);
+}
+
+void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations)
+{
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_run_iteration, n_iterations);
+}
+
+uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p)
+{
+ return field_get_updated(p->mp_fld_pci_rd_tg_ctrl_rdy);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h
new file mode 100644
index 0000000000..b1c912f0f3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCI_RD_TG_H__
+#define __NTHW_PCI_RD_TG_H__
+
+struct nthw_pci_rd_tg {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pci_rd_tg;
+ int mn_instance;
+
+ int mn_param_pci_ta_tg_present;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_data0;
+ nt_field_t *mp_fld_pci_rd_tg_phys_addr_low;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_data1;
+ nt_field_t *mp_fld_pci_rd_tg_phys_addr_high;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_data2;
+ nt_field_t *mp_fld_pci_rd_tg_req_size;
+ nt_field_t *mp_fld_pci_rd_tg_req_hid;
+ nt_field_t *mp_fld_pci_rd_tg_wait;
+ nt_field_t *mp_fld_pci_rd_tg_wrap;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_addr;
+ nt_field_t *mp_fld_pci_rd_tg_ram_addr;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_run;
+ nt_field_t *mp_fld_pci_rd_tg_run_iteration;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_ctrl;
+ nt_field_t *mp_fld_pci_rd_tg_ctrl_rdy;
+};
+
+typedef struct nthw_pci_rd_tg nthw_pci_rd_tg_t;
+typedef struct nthw_pci_rd_tg nthw_pci_rd_tg;
+
+nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void);
+void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p);
+int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr);
+void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr);
+void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap);
+void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations);
+uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p);
+
+#endif /* __NTHW_PCI_RD_TG_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.c b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c
new file mode 100644
index 0000000000..17e30a670d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pci_ta.h"
+
+nthw_pci_ta_t *nthw_pci_ta_new(void)
+{
+ nthw_pci_ta_t *p = malloc(sizeof(nthw_pci_ta_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pci_ta_t));
+ return p;
+}
+
+void nthw_pci_ta_delete(nthw_pci_ta_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pci_ta_t));
+ free(p);
+ }
+}
+
+int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_TA, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCI_TA %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pci_ta = mod;
+
+ p->mn_param_pci_ta_tg_present =
+ fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);
+
+ p->mp_reg_pci_ta_ctrl = module_get_register(p->mp_mod_pci_ta, PCI_TA_CONTROL);
+ p->mp_fld_pci_ta_ctrl_enable =
+ register_get_field(p->mp_reg_pci_ta_ctrl, PCI_TA_CONTROL_ENABLE);
+
+ p->mp_reg_pci_ta_packet_good =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_GOOD);
+ p->mp_fld_pci_ta_packet_good_amount =
+ register_get_field(p->mp_reg_pci_ta_packet_good, PCI_TA_PACKET_GOOD_AMOUNT);
+
+ p->mp_reg_pci_ta_packet_bad =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_BAD);
+ p->mp_fld_pci_ta_packet_bad_amount =
+ register_get_field(p->mp_reg_pci_ta_packet_bad, PCI_TA_PACKET_BAD_AMOUNT);
+
+ p->mp_reg_pci_ta_length_error =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_LENGTH_ERROR);
+ p->mp_fld_pci_ta_length_error_amount =
+ register_get_field(p->mp_reg_pci_ta_length_error, PCI_TA_LENGTH_ERROR_AMOUNT);
+
+ p->mp_reg_pci_ta_payload_error =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_PAYLOAD_ERROR);
+ p->mp_fld_pci_ta_payload_error_amount =
+ register_get_field(p->mp_reg_pci_ta_payload_error, PCI_TA_PAYLOAD_ERROR_AMOUNT);
+
+ return 0;
+}
+
+void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val)
+{
+ field_set_val_flush32(p->mp_fld_pci_ta_ctrl_enable, val);
+}
+
+void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_packet_good_amount);
+}
+
+void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_packet_bad_amount);
+}
+
+void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_length_error_amount);
+}
+
+void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_payload_error_amount);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.h b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h
new file mode 100644
index 0000000000..7968cad9fa
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCI_TA_H__
+#define __NTHW_PCI_TA_H__
+
+struct nthw_pci_ta {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pci_ta;
+ int mn_instance;
+
+ int mn_param_pci_ta_tg_present;
+
+ nt_register_t *mp_reg_pci_ta_ctrl;
+ nt_field_t *mp_fld_pci_ta_ctrl_enable;
+ nt_register_t *mp_reg_pci_ta_packet_good;
+ nt_field_t *mp_fld_pci_ta_packet_good_amount;
+ nt_register_t *mp_reg_pci_ta_packet_bad;
+ nt_field_t *mp_fld_pci_ta_packet_bad_amount;
+ nt_register_t *mp_reg_pci_ta_length_error;
+ nt_field_t *mp_fld_pci_ta_length_error_amount;
+ nt_register_t *mp_reg_pci_ta_payload_error;
+ nt_field_t *mp_fld_pci_ta_payload_error_amount;
+};
+
+typedef struct nthw_pci_ta nthw_pci_ta_t;
+typedef struct nthw_pci_ta nthw_pci_ta;
+
+nthw_pci_ta_t *nthw_pci_ta_new(void);
+void nthw_pci_ta_delete(nthw_pci_ta_t *p);
+int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val);
+void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val);
+void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val);
+void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val);
+void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val);
+
+#endif /* __NTHW_PCI_TA_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c
new file mode 100644
index 0000000000..f830a586b2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pci_wr_tg.h"
+
+nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void)
+{
+ nthw_pci_wr_tg_t *p = malloc(sizeof(nthw_pci_wr_tg_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pci_wr_tg_t));
+ return p;
+}
+
+void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pci_wr_tg_t));
+ free(p);
+ }
+}
+
+int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_WR_TG, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCI_WR_TG %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pci_wr_tg = mod;
+
+ p->mn_param_pci_ta_tg_present =
+ fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);
+
+ p->mp_reg_pci_wr_tg_data0 =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA0);
+ p->mp_fld_pci_wr_tg_phys_addr_low =
+ register_get_field(p->mp_reg_pci_wr_tg_data0, PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW);
+
+ p->mp_reg_pci_wr_tg_data1 =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA1);
+ p->mp_fld_pci_wr_tg_phys_addr_high =
+ register_get_field(p->mp_reg_pci_wr_tg_data1, PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH);
+
+ p->mp_reg_pci_wr_tg_data2 =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA2);
+ p->mp_fld_pci_wr_tg_req_size =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_SIZE);
+ p->mp_fld_pci_wr_tg_inc_mode =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_INC_MODE);
+ p->mp_fld_pci_wr_tg_wait =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WAIT);
+ p->mp_fld_pci_wr_tg_wrap =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WRAP);
+ /* optional VF host id */
+ p->mp_fld_pci_wr_tg_req_hid =
+ register_query_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_HID);
+
+ p->mp_reg_pci_wr_tg_addr =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRADDR);
+ p->mp_fld_pci_wr_tg_ram_addr =
+ register_get_field(p->mp_reg_pci_wr_tg_addr, PCI_WR_TG_TG_WRADDR_RAM_ADDR);
+
+ p->mp_reg_pci_wr_tg_run =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WR_RUN);
+ p->mp_fld_pci_wr_tg_run_iteration =
+ register_get_field(p->mp_reg_pci_wr_tg_run, PCI_WR_TG_TG_WR_RUN_WR_ITERATION);
+
+ p->mp_reg_pci_wr_tg_ctrl =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_CTRL);
+ p->mp_fld_pci_wr_tg_ctrl_rdy =
+ register_get_field(p->mp_reg_pci_wr_tg_ctrl, PCI_WR_TG_TG_CTRL_TG_WR_RDY);
+
+ p->mp_reg_pci_wr_tg_seq =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_SEQ);
+ p->mp_fld_pci_wr_tg_seq_sequence =
+ register_get_field(p->mp_reg_pci_wr_tg_seq, PCI_WR_TG_TG_SEQ_SEQUENCE);
+
+ return 0;
+}
+
+void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_low,
+ (uint32_t)(n_phys_addr & ((1UL << 32) - 1)));
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_high,
+ (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1)));
+}
+
+void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_ram_addr, n_ram_addr);
+}
+
+void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap, bool inc)
+{
+ field_set_val32(p->mp_fld_pci_wr_tg_req_size, req_size);
+ field_set_val32(p->mp_fld_pci_wr_tg_wait, wait);
+ field_set_val32(p->mp_fld_pci_wr_tg_wrap, wrap);
+ field_set_val32(p->mp_fld_pci_wr_tg_inc_mode, inc);
+ field_flush_register(p->mp_fld_pci_wr_tg_inc_mode);
+}
+
+void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations)
+{
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_run_iteration, n_iterations);
+}
+
+uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p)
+{
+ return field_get_updated(p->mp_fld_pci_wr_tg_ctrl_rdy);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h
new file mode 100644
index 0000000000..535b39526e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCI_WR_TG_H__
+#define __NTHW_PCI_WR_TG_H__
+
+struct nthw_pci_wr_tg {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pci_wr_tg;
+ int mn_instance;
+
+ int mn_param_pci_ta_tg_present;
+
+ nt_register_t *mp_reg_pci_wr_tg_data0;
+ nt_field_t *mp_fld_pci_wr_tg_phys_addr_low;
+
+ nt_register_t *mp_reg_pci_wr_tg_data1;
+ nt_field_t *mp_fld_pci_wr_tg_phys_addr_high;
+
+ nt_register_t *mp_reg_pci_wr_tg_data2;
+ nt_field_t *mp_fld_pci_wr_tg_req_size;
+ nt_field_t *mp_fld_pci_wr_tg_req_hid;
+ nt_field_t *mp_fld_pci_wr_tg_inc_mode;
+ nt_field_t *mp_fld_pci_wr_tg_wait;
+ nt_field_t *mp_fld_pci_wr_tg_wrap;
+
+ nt_register_t *mp_reg_pci_wr_tg_addr;
+ nt_field_t *mp_fld_pci_wr_tg_ram_addr;
+
+ nt_register_t *mp_reg_pci_wr_tg_run;
+ nt_field_t *mp_fld_pci_wr_tg_run_iteration;
+
+ nt_register_t *mp_reg_pci_wr_tg_ctrl;
+ nt_field_t *mp_fld_pci_wr_tg_ctrl_rdy;
+
+ nt_register_t *mp_reg_pci_wr_tg_seq;
+ nt_field_t *mp_fld_pci_wr_tg_seq_sequence;
+};
+
+typedef struct nthw_pci_wr_tg nthw_pci_wr_tg_t;
+typedef struct nthw_pci_wr_tg nthw_pci_wr_tg;
+
+nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void);
+void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p);
+int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr);
+void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr);
+void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap, bool inc);
+void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations);
+uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p);
+
+#endif /* __NTHW_PCI_WR_TG_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.c b/drivers/net/ntnic/nthw/core/nthw_pcie3.c
new file mode 100644
index 0000000000..07ad784695
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.c
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pcie3.h"
+
+#define NTHW_TG_REF_FREQ (250000000ULL)
+
+nthw_pcie3_t *nthw_pcie3_new(void)
+{
+ nthw_pcie3_t *p = malloc(sizeof(nthw_pcie3_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pcie3_t));
+ return p;
+}
+
+void nthw_pcie3_delete(nthw_pcie3_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pcie3_t));
+ free(p);
+ }
+}
+
+int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCIE3, n_instance);
+
+ if (p == NULL)
+ return (mod == NULL ? -1 : 0);
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCIE3 %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pcie3 = mod;
+
+ /* PCIe3 */
+ p->mp_reg_stat_ctrl = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_CTRL);
+ p->mp_fld_stat_ctrl_ena =
+ register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_ENA);
+ p->mp_fld_stat_ctrl_req =
+ register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_REQ);
+
+ p->mp_reg_stat_rx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RX);
+ p->mp_fld_stat_rx_counter =
+ register_get_field(p->mp_reg_stat_rx, PCIE3_STAT_RX_COUNTER);
+
+ p->mp_reg_stat_tx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_TX);
+ p->mp_fld_stat_tx_counter =
+ register_get_field(p->mp_reg_stat_tx, PCIE3_STAT_TX_COUNTER);
+
+ p->mp_reg_stat_ref_clk =
+ module_get_register(p->mp_mod_pcie3, PCIE3_STAT_REFCLK);
+ p->mp_fld_stat_ref_clk_ref_clk =
+ register_get_field(p->mp_reg_stat_ref_clk, PCIE3_STAT_REFCLK_REFCLK250);
+
+ p->mp_reg_stat_rq_rdy =
+ module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_RDY);
+ p->mp_fld_stat_rq_rdy_counter =
+ register_get_field(p->mp_reg_stat_rq_rdy, PCIE3_STAT_RQ_RDY_COUNTER);
+
+ p->mp_reg_stat_rq_vld =
+ module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_VLD);
+ p->mp_fld_stat_rq_vld_counter =
+ register_get_field(p->mp_reg_stat_rq_vld, PCIE3_STAT_RQ_VLD_COUNTER);
+
+ p->mp_reg_status0 = module_get_register(p->mp_mod_pcie3, PCIE3_STATUS0);
+ p->mp_fld_status0_tags_in_use =
+ register_get_field(p->mp_reg_status0, PCIE3_STATUS0_TAGS_IN_USE);
+
+ p->mp_reg_rp_to_ep_err =
+ module_get_register(p->mp_mod_pcie3, PCIE3_RP_TO_EP_ERR);
+ p->mp_fld_rp_to_ep_err_cor =
+ register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_COR);
+ p->mp_fld_rp_to_ep_err_non_fatal =
+ register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_NONFATAL);
+ p->mp_fld_rp_to_ep_err_fatal =
+ register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_FATAL);
+
+ p->mp_reg_ep_to_rp_err =
+ module_get_register(p->mp_mod_pcie3, PCIE3_EP_TO_RP_ERR);
+ p->mp_fld_ep_to_rp_err_cor = register_get_field(p->mp_reg_ep_to_rp_err,
+ PCIE3_EP_TO_RP_ERR_ERR_COR);
+ p->mp_fld_ep_to_rp_err_non_fatal =
+ register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_NONFATAL);
+ p->mp_fld_ep_to_rp_err_fatal =
+ register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_FATAL);
+
+ p->mp_reg_sample_time =
+ module_get_register(p->mp_mod_pcie3, PCIE3_SAMPLE_TIME);
+ p->mp_fld_sample_time =
+ register_get_field(p->mp_reg_sample_time, PCIE3_SAMPLE_TIME_SAMPLE_TIME);
+
+ p->mp_reg_pci_end_point =
+ module_get_register(p->mp_mod_pcie3, PCIE3_PCI_ENDPOINT);
+ p->mp_fld_pci_end_point_if_id =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_IF_ID);
+ p->mp_fld_pci_end_point_send_msg =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_SEND_MSG);
+ p->mp_fld_pci_end_point_get_msg =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_GET_MSG);
+ p->mp_fld_pci_end_point_dmae_p0_allow_mask =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK);
+ p->mp_fld_pci_end_point_dmae_p1_allow_mask =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK);
+ if (p->mp_reg_pci_end_point)
+ register_update(p->mp_reg_pci_end_point);
+
+ p->mp_reg_pci_test0 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST0);
+ p->mp_fld_pci_test0 =
+ register_get_field(p->mp_reg_pci_test0, PCIE3_PCI_TEST0_DATA);
+ if (p->mp_reg_pci_test0)
+ register_update(p->mp_reg_pci_test0);
+
+ p->mp_reg_pci_test1 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST1);
+ p->mp_fld_pci_test1 =
+ register_get_field(p->mp_reg_pci_test1, PCIE3_PCI_TEST1_DATA);
+ if (p->mp_reg_pci_test1)
+ register_update(p->mp_reg_pci_test1);
+
+ p->mp_reg_pci_e3_mark_adr_lsb =
+ module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_LSB);
+ p->mp_fld_pci_e3_mark_adr_lsb_adr =
+ register_get_field(p->mp_reg_pci_e3_mark_adr_lsb, PCIE3_MARKADR_LSB_ADR);
+ if (p->mp_reg_pci_e3_mark_adr_lsb)
+ register_update(p->mp_reg_pci_e3_mark_adr_lsb);
+
+ p->mp_reg_pci_e3_mark_adr_msb =
+ module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_MSB);
+ p->mp_fld_pci_e3_mark_adr_msb_adr =
+ register_get_field(p->mp_reg_pci_e3_mark_adr_msb, PCIE3_MARKADR_MSB_ADR);
+ if (p->mp_reg_pci_e3_mark_adr_msb)
+ register_update(p->mp_reg_pci_e3_mark_adr_msb);
+
+ /* Initial setup - disable markerscheme and bifurcation */
+ if (p->mp_fld_pci_end_point_dmae_p0_allow_mask)
+ field_clr_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask);
+
+ if (p->mp_fld_pci_end_point_dmae_p1_allow_mask)
+ field_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask);
+
+ if (p->mp_fld_pci_e3_mark_adr_lsb_adr)
+ field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_lsb_adr, 0UL);
+
+ if (p->mp_fld_pci_e3_mark_adr_msb_adr)
+ field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_msb_adr, 0UL);
+
+ if (p->mp_fld_pci_end_point_dmae_p0_allow_mask)
+ field_set_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask);
+
+ if (p->mp_fld_pci_end_point_dmae_p1_allow_mask)
+ field_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask);
+ return 0;
+};
+
+int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p)
+{
+ field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);
+
+ return 0;
+}
+
+int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p)
+{
+ field_set_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p)
+{
+ field_clr_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt,
+ uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt)
+{
+ *p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter);
+ *p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter);
+
+ *p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk);
+
+ *p_tg_unit_size = NTHW_TG_CNT_SIZE;
+ *p_tg_ref_freq = NTHW_TG_REF_FREQ;
+
+ *p_tag_use_cnt = field_get_updated(p->mp_fld_status0_tags_in_use);
+
+ *p_rq_rdy_cnt = field_get_updated(p->mp_fld_stat_rq_rdy_counter);
+ *p_rq_vld_cnt = field_get_updated(p->mp_fld_stat_rq_vld_counter);
+
+ return 0;
+}
+
+int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util,
+ uint64_t *p_pci_xil_bus_util)
+{
+ uint32_t rx_cnt, tx_cnt, ref_clk_cnt;
+ uint32_t tg_unit_size, tg_ref_freq;
+ uint32_t tag_use_cnt, rq_rdy_cnt, rq_vld_cnt;
+
+ nthw_pcie3_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size,
+ &tg_ref_freq, &tag_use_cnt, &rq_rdy_cnt, &rq_vld_cnt);
+
+ if (ref_clk_cnt) {
+ uint64_t nt_bus_util, xil_bus_util;
+ uint64_t rx_rate, tx_rate;
+
+ rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_rx_rate = rx_rate;
+
+ tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_tx_rate = tx_rate;
+
+ *p_ref_clk_cnt = ref_clk_cnt;
+
+ *p_tag_use_cnt = tag_use_cnt;
+
+ nt_bus_util =
+ ((uint64_t)rq_vld_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt;
+ *p_pci_nt_bus_util = nt_bus_util;
+ xil_bus_util =
+ ((uint64_t)rq_rdy_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt;
+ *p_pci_xil_bus_util = xil_bus_util;
+ } else {
+ *p_ref_clk_cnt = 0;
+ *p_pci_nt_bus_util = 0;
+ *p_pci_xil_bus_util = 0;
+ }
+
+ return 0;
+}
+
+int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc)
+{
+ NT_LOG(DBG, NTHW, "%s:%u: empty function\n", __func__, __LINE__);
+
+ (void)p;
+ (void)epc;
+
+ return 0;
+}
+
+int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc)
+{
+ NT_LOG(DBG, NTHW, "%s:%u:\n", __func__, __LINE__);
+ assert(epc);
+ nthw_pcie3_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt,
+ &epc->n_tags_in_use, &epc->cur_pci_nt_util,
+ &epc->cur_pci_xil_util);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.h b/drivers/net/ntnic/nthw/core/nthw_pcie3.h
new file mode 100644
index 0000000000..beb79a9577
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCIE3_H__
+#define __NTHW_PCIE3_H__
+
+struct nthw_pcie3 {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pcie3;
+ int mn_instance;
+
+ nt_register_t *mp_reg_stat_ctrl;
+ nt_field_t *mp_fld_stat_ctrl_req;
+ nt_field_t *mp_fld_stat_ctrl_ena;
+
+ nt_register_t *mp_reg_stat_rx;
+ nt_field_t *mp_fld_stat_rx_counter;
+
+ nt_register_t *mp_reg_stat_tx;
+ nt_field_t *mp_fld_stat_tx_counter;
+
+ nt_register_t *mp_reg_stat_rq_rdy;
+ nt_field_t *mp_fld_stat_rq_rdy_counter;
+
+ nt_register_t *mp_reg_stat_rq_vld;
+ nt_field_t *mp_fld_stat_rq_vld_counter;
+
+ nt_register_t *mp_reg_status0;
+ nt_field_t *mp_fld_status0_tags_in_use;
+
+ nt_register_t *mp_reg_stat_ref_clk;
+ nt_field_t *mp_fld_stat_ref_clk_ref_clk;
+
+ nt_register_t *mp_reg_rp_to_ep_err;
+ nt_field_t *mp_fld_rp_to_ep_err_cor;
+ nt_field_t *mp_fld_rp_to_ep_err_non_fatal;
+ nt_field_t *mp_fld_rp_to_ep_err_fatal;
+
+ nt_register_t *mp_reg_ep_to_rp_err;
+ nt_field_t *mp_fld_ep_to_rp_err_cor;
+ nt_field_t *mp_fld_ep_to_rp_err_non_fatal;
+ nt_field_t *mp_fld_ep_to_rp_err_fatal;
+
+ nt_register_t *mp_reg_sample_time;
+ nt_field_t *mp_fld_sample_time;
+
+ nt_register_t *mp_reg_pci_end_point;
+ nt_field_t *mp_fld_pci_end_point_if_id;
+ nt_field_t *mp_fld_pci_end_point_send_msg;
+ nt_field_t *mp_fld_pci_end_point_get_msg;
+ nt_field_t *mp_fld_pci_end_point_dmae_p0_allow_mask;
+ nt_field_t *mp_fld_pci_end_point_dmae_p1_allow_mask;
+
+ nt_register_t *mp_reg_pci_e3_mark_adr_lsb;
+ nt_field_t *mp_fld_pci_e3_mark_adr_lsb_adr;
+
+ nt_register_t *mp_reg_pci_e3_mark_adr_msb;
+ nt_field_t *mp_fld_pci_e3_mark_adr_msb_adr;
+
+ nt_register_t *mp_reg_pci_test0;
+ nt_field_t *mp_fld_pci_test0;
+
+ nt_register_t *mp_reg_pci_test1;
+ nt_field_t *mp_fld_pci_test1;
+
+ nt_register_t *mp_reg_pci_test2;
+ nt_field_t *mp_fld_pci_test2;
+
+ nt_register_t *mp_reg_pci_test3;
+ nt_field_t *mp_fld_pci_test3;
+};
+
+typedef struct nthw_pcie3 nthw_pcie3_t;
+typedef struct nthw_pcie3 nthw_pcie3;
+
+nthw_pcie3_t *nthw_pcie3_new(void);
+void nthw_pcie3_delete(nthw_pcie3_t *p);
+int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p);
+
+int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p);
+int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p);
+
+int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt,
+ uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt);
+int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util,
+ uint64_t *p_pci_xil_bus_util);
+
+int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc);
+int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc);
+
+#endif /* __NTHW_PCIE3_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.c b/drivers/net/ntnic/nthw/core/nthw_sdc.c
new file mode 100644
index 0000000000..0547b92c47
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.c
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_sdc.h"
+
+nthw_sdc_t *nthw_sdc_new(void)
+{
+ nthw_sdc_t *p = malloc(sizeof(nthw_sdc_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_sdc_t));
+ return p;
+}
+
+void nthw_sdc_delete(nthw_sdc_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_sdc_t));
+ free(p);
+ }
+}
+
+int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_SDC, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: SDC %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_sdc = mod;
+
+ {
+ nt_register_t *p_reg;
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_CTRL);
+ p->mp_fld_ctrl_init = register_get_field(p_reg, SDC_CTRL_INIT);
+ p->mp_fld_ctrl_run_test =
+ register_get_field(p_reg, SDC_CTRL_RUN_TEST);
+ p->mp_fld_ctrl_stop_client =
+ register_get_field(p_reg, SDC_CTRL_STOP_CLIENT);
+ p->mp_fld_ctrl_test_enable =
+ register_get_field(p_reg, SDC_CTRL_TEST_EN);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_STAT);
+ p->mp_fld_stat_calib = register_get_field(p_reg, SDC_STAT_CALIB);
+ p->mp_fld_stat_cell_cnt_stopped =
+ register_get_field(p_reg, SDC_STAT_CELL_CNT_STOPPED);
+ p->mp_fld_stat_err_found =
+ register_get_field(p_reg, SDC_STAT_ERR_FOUND);
+ p->mp_fld_stat_init_done =
+ register_get_field(p_reg, SDC_STAT_INIT_DONE);
+ p->mp_fld_stat_mmcm_lock =
+ register_get_field(p_reg, SDC_STAT_MMCM_LOCK);
+ p->mp_fld_stat_pll_lock =
+ register_get_field(p_reg, SDC_STAT_PLL_LOCK);
+ p->mp_fld_stat_resetting =
+ register_get_field(p_reg, SDC_STAT_RESETTING);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT);
+ p->mp_fld_cell_cnt =
+ register_get_field(p_reg, SDC_CELL_CNT_CELL_CNT);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT_PERIOD);
+ p->mp_fld_cell_cnt_period =
+ register_get_field(p_reg, SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_FILL_LVL);
+ p->mp_fld_fill_level =
+ register_get_field(p_reg, SDC_FILL_LVL_FILL_LVL);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_MAX_FILL_LVL);
+ p->mp_fld_max_fill_level =
+ register_get_field(p_reg, SDC_MAX_FILL_LVL_MAX_FILL_LVL);
+ }
+ return 0;
+}
+
+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask)
+{
+ int n_err_cnt = 0;
+ uint64_t n_mask = 0;
+ uint32_t val;
+ uint32_t val_mask;
+ int n_val_width;
+
+ if (!p || !pn_result_mask)
+ return -1;
+
+ val = field_get_updated(p->mp_fld_stat_calib);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_calib);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_init_done);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_init_done);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_mmcm_lock);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_mmcm_lock);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_pll_lock);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_pll_lock);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_resetting);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_resetting);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != 0)
+ n_err_cnt++;
+
+ if (pn_result_mask)
+ *pn_result_mask = n_mask;
+
+ return n_err_cnt; /* 0 = all ok */
+}
+
+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations,
+ const int n_poll_interval)
+{
+ int res;
+ int n_err_cnt = 0;
+
+ res = field_wait_set_all32(p->mp_fld_stat_calib, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_set_all32(p->mp_fld_stat_init_done, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_set_all32(p->mp_fld_stat_mmcm_lock, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_set_all32(p->mp_fld_stat_pll_lock, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_clr_all32(p->mp_fld_stat_resetting, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ return n_err_cnt; /* 0 = all ok */
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.h b/drivers/net/ntnic/nthw/core/nthw_sdc.h
new file mode 100644
index 0000000000..e6c08ffbc3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SDC_H__
+#define __NTHW_SDC_H__
+
+struct nthw_sdc {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_sdc;
+ int mn_instance;
+
+ nt_field_t *mp_fld_ctrl_init;
+ nt_field_t *mp_fld_ctrl_run_test;
+ nt_field_t *mp_fld_ctrl_stop_client;
+ nt_field_t *mp_fld_ctrl_test_enable;
+
+ nt_field_t *mp_fld_stat_calib;
+ nt_field_t *mp_fld_stat_cell_cnt_stopped;
+ nt_field_t *mp_fld_stat_err_found;
+ nt_field_t *mp_fld_stat_init_done;
+ nt_field_t *mp_fld_stat_mmcm_lock;
+ nt_field_t *mp_fld_stat_pll_lock;
+ nt_field_t *mp_fld_stat_resetting;
+
+ nt_field_t *mp_fld_cell_cnt;
+ nt_field_t *mp_fld_cell_cnt_period;
+ nt_field_t *mp_fld_fill_level;
+ nt_field_t *mp_fld_max_fill_level;
+};
+
+typedef struct nthw_sdc nthw_sdc_t;
+typedef struct nthw_sdc nthw_sdc;
+
+nthw_sdc_t *nthw_sdc_new(void);
+int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_sdc_delete(nthw_sdc_t *p);
+
+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations,
+ const int n_poll_interval);
+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask);
+
+#endif /* __NTHW_SDC_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.c b/drivers/net/ntnic/nthw/core/nthw_si5340.c
new file mode 100644
index 0000000000..3337f1f9e3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_si5340.c
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ *
+ * This file implements Si5340 clock synthesizer support.
+ * The implementation is generic and must be tailored to a specific use by the
+ * correct initialization data.
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_si5340.h"
+
+#define SI5340_WAIT_US(x) NT_OS_WAIT_USEC(x)
+
+#define SI5340_LOG_DEBUG(...) NT_LOG(DBG, NTHW, __VA_ARGS__)
+#define SI5340_LOG_INFO(...) NT_LOG(INF, NTHW, __VA_ARGS__)
+#define SI5340_LOG_WARN(...) NT_LOG(WRN, NTHW, __VA_ARGS__)
+#define SI5340_LOG_ERROR(...) NT_LOG(ERR, NTHW, __VA_ARGS__)
+
+#define SI5340_PAGE_REG_ADDR (0x01)
+
+nthw_si5340_t *nthw_si5340_new(void)
+{
+ nthw_si5340_t *p = malloc(sizeof(nthw_si5340_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_si5340_t));
+ return p;
+}
+
+int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr)
+{
+ uint8_t data;
+
+ p->mp_nthw_iic = p_nthw_iic;
+ p->mn_iic_addr = n_iic_addr;
+ p->mn_clk_cfg = -1;
+
+ p->m_si5340_page = 0;
+ data = p->m_si5340_page;
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1,
+ &data);
+
+ return 0;
+}
+
+void nthw_si5340_delete(nthw_si5340_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_si5340_t));
+ free(p);
+ }
+}
+
+/*
+ * Read access (via I2C) to the clock synthesizer IC. The IC is located at I2C
+ * 7bit address 0x74
+ */
+static uint8_t nthw_si5340_read(nthw_si5340_t *p, uint16_t reg_addr)
+{
+ const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff);
+ uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff);
+ uint8_t data;
+
+ /* check if we are on the right page */
+ if (page != p->m_si5340_page) {
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr,
+ SI5340_PAGE_REG_ADDR, 1, &page);
+ p->m_si5340_page = page;
+ }
+ nthw_iic_read_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data);
+ return data;
+}
+
+/*
+ * Write access (via I2C) to the clock synthesizer IC. The IC is located at I2C
+ * 7 bit address 0x74
+ */
+static int nthw_si5340_write(nthw_si5340_t *p, uint16_t reg_addr, uint8_t data)
+{
+ const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff);
+ uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff);
+
+ /* check if we are on the right page */
+ if (page != p->m_si5340_page) {
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr,
+ SI5340_PAGE_REG_ADDR, 1, &page);
+ p->m_si5340_page = page;
+ }
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data);
+
+ return 0;
+}
+
+static int nthw_si5340_cfg(nthw_si5340_t *p, const void *p_data, int data_cnt,
+ clk_profile_data_fmt_t data_format)
+{
+ const char *const p_adapter_id_str =
+ p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int i;
+ uint16_t addr;
+ uint8_t value;
+ uint8_t ctrl_value;
+
+ NT_LOG(DBG, NTHW, "%s: %s: data_cnt = %d, dataFormat = %d\n",
+ p_adapter_id_str, __func__, data_cnt, data_format);
+
+ for (i = 0; i < data_cnt; i++) {
+ if (data_format == CLK_PROFILE_DATA_FMT_1) {
+ addr = ((const clk_profile_data_fmt1_t *)p_data)->reg_addr;
+ value = ((const clk_profile_data_fmt1_t *)p_data)->reg_val;
+ p_data = ((const clk_profile_data_fmt1_t *)p_data) + 1;
+ } else if (data_format == CLK_PROFILE_DATA_FMT_2) {
+ addr = (uint16_t)(((const clk_profile_data_fmt2_t *)p_data)
+ ->reg_addr);
+ value = ((const clk_profile_data_fmt2_t *)p_data)->reg_val;
+ p_data = ((const clk_profile_data_fmt2_t *)p_data) + 1;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: Unhandled Si5340 data format (%d)\n",
+ p_adapter_id_str, data_format);
+ return -1;
+ }
+
+ if (addr == 0x0006) {
+ /* Wait 300ms before continuing. See NT200E3-2-PTP_U23_Si5340_adr0_v2.h */
+ NT_OS_WAIT_USEC(300000);
+ }
+
+ nthw_si5340_write(p, addr, value);
+
+ if (addr == 0x001C) {
+ /* skip readback for "soft reset" register */
+ continue;
+ }
+
+ ctrl_value = nthw_si5340_read(p, addr);
+
+ if (ctrl_value != value) {
+ NT_LOG(ERR, NTHW,
+ "%s: Si5340 configuration readback check failed. (Addr = 0x%04X, Write = 0x%02X, Read = 0x%02X)\n",
+ p_adapter_id_str, addr, value, ctrl_value);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt,
+ clk_profile_data_fmt_t data_format)
+{
+ const char *const p_adapter_id_str =
+ p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int i;
+ bool success = false;
+ uint8_t status, sticky;
+ uint8_t design_id[9];
+
+ (void)nthw_si5340_cfg(p, p_data, data_cnt, data_format);
+
+ /* Check if DPLL is locked and SYS is calibrated */
+ for (i = 0; i < 5; i++) {
+ status = nthw_si5340_read(p, 0x0c);
+ sticky = nthw_si5340_read(p, 0x11);
+ nthw_si5340_write(p, 0x11, 0x00);
+
+ if (((status & 0x09) == 0x00) && ((sticky & 0x09) == 0x00)) {
+ success = true;
+ break;
+ }
+ NT_OS_WAIT_USEC(1000000); /* 1 sec */
+ }
+
+ if (!success) {
+ NT_LOG(ERR, NTHW,
+ "%s: Si5340 configuration failed. (Status = 0x%02X, Sticky = 0x%02X)\n",
+ p_adapter_id_str, status, sticky);
+ return -1;
+ }
+
+ for (i = 0; i < (int)sizeof(design_id) - 1; i++)
+ design_id[i] = nthw_si5340_read(p, (uint16_t)(0x26B + i));
+ design_id[sizeof(design_id) - 1] = 0;
+
+ (void)design_id; /* Only used in debug mode */
+ NT_LOG(DBG, NTHW, "%s: Si5340.DesignId = %s\n", p_adapter_id_str,
+ design_id);
+
+ return 0;
+}
+
+int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data,
+ const int data_cnt)
+{
+ return nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_1);
+}
+
+int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data,
+ const int data_cnt)
+{
+ return nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_2);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.h b/drivers/net/ntnic/nthw/core/nthw_si5340.h
new file mode 100644
index 0000000000..f588b5b825
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_si5340.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SI5340_H__
+#define __NTHW_SI5340_H__
+
+#include "nthw_clock_profiles.h"
+
+#define SI5340_SUCCESS (0)
+#define SI5340_FAILED (999)
+#define SI5340_TIMEOUT (666)
+
+struct nthw_si5340 {
+ uint8_t mn_iic_addr;
+ nthw_iic_t *mp_nthw_iic;
+ int mn_clk_cfg;
+ uint8_t m_si5340_page;
+};
+
+typedef struct nthw_si5340 nthw_si5340_t;
+
+nthw_si5340_t *nthw_si5340_new(void);
+int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr);
+void nthw_si5340_delete(nthw_si5340_t *p);
+
+int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt,
+ clk_profile_data_fmt_t data_format);
+int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data,
+ const int data_cnt);
+int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data,
+ const int data_cnt);
+
+#endif /* __NTHW_SI5338_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.c b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c
new file mode 100644
index 0000000000..454c9b73b8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+
+#include "nthw_spi_v3.h"
+
+#include <arpa/inet.h>
+
+#undef SPI_V3_DEBUG_PRINT
+
+nthw_spi_v3_t *nthw_spi_v3_new(void)
+{
+ nthw_spi_v3_t *p = malloc(sizeof(nthw_spi_v3_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_spi_v3_t));
+ return p;
+}
+
+void nthw_spi_v3_delete(nthw_spi_v3_t *p)
+{
+ if (p) {
+ if (p->mp_spim_mod) {
+ nthw_spim_delete(p->mp_spim_mod);
+ p->mp_spim_mod = NULL;
+ }
+
+ if (p->mp_spis_mod) {
+ nthw_spis_delete(p->mp_spis_mod);
+ p->mp_spis_mod = NULL;
+ }
+
+ memset(p, 0, sizeof(nthw_spi_v3_t));
+ free(p);
+ }
+}
+
+int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out)
+{
+ p->m_time_out = time_out;
+ return 0;
+}
+
+int nthw_spi_v3_get_version(nthw_spi_v3_t *p)
+{
+ (void)p;
+ return 3;
+}
+
+/*
+ * Wait until Tx data have been sent after they have been placed in the Tx FIFO.
+ */
+static int wait_for_tx_data_sent(nthw_spim_t *p_spim_mod, uint64_t time_out)
+{
+ int result;
+ bool empty;
+ uint64_t start_time;
+ uint64_t cur_time;
+
+ start_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+
+ while (true) {
+ NT_OS_WAIT_USEC(1000); /* Every 1ms */
+
+ result = nthw_spim_get_tx_fifo_empty(p_spim_mod, &empty);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spim_get_tx_fifo_empty failed\n");
+ return result;
+ }
+
+ if (empty)
+ break;
+
+ cur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+ if ((cur_time - start_time) > time_out) {
+ NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Wait until Rx data have been received.
+ */
+static int wait_for_rx_data_ready(nthw_spis_t *p_spis_mod, uint64_t time_out)
+{
+ int result;
+ bool empty;
+ uint64_t start_time;
+ uint64_t cur_time;
+
+ start_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+
+ /* Wait for data to become ready in the Rx FIFO */
+ while (true) {
+ NT_OS_WAIT_USEC(10000); /* Every 10ms */
+
+ result = nthw_spis_get_rx_fifo_empty(p_spis_mod, &empty);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spis_get_rx_empty failed\n");
+ return result;
+ }
+
+ if (!empty)
+ break;
+
+ cur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+ if ((cur_time - start_time) > time_out) {
+ NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef SPI_V3_DEBUG_PRINT
+static void dump_hex(uint8_t *p_data, uint16_t count)
+{
+ int i;
+ int j = 0;
+ char tmp_str[128];
+
+ for (i = 0; i < count; i++) {
+ sprintf(&tmp_str[j * 3], "%02X ", *(p_data++));
+ j++;
+
+ if (j == 16 || (i == count - 1)) {
+ tmp_str[j * 3 - 1] = '\0';
+ NT_LOG(DBG, NTHW, " %s\n", tmp_str);
+ j = 0;
+ }
+ }
+}
+#endif
+
+int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint32_t result;
+
+ p->mn_instance_no = n_instance_no;
+
+ nthw_spi_v3_set_timeout(p, 1);
+
+ /* Initialize SPIM module */
+ p->mp_spim_mod = nthw_spim_new();
+
+ result = nthw_spim_init(p->mp_spim_mod, p_fpga, n_instance_no);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spis_init failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ /* Initialize SPIS module */
+ p->mp_spis_mod = nthw_spis_new();
+
+ result = nthw_spis_init(p->mp_spis_mod, p_fpga, n_instance_no);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spim_init failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ /* Reset SPIM and SPIS modules */
+ result = nthw_spim_reset(p->mp_spim_mod);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spim_reset failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ result = nthw_spis_reset(p->mp_spis_mod);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spis_reset failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ return result;
+}
+
+/*
+ * Send Tx data using the SPIM module and receive any data using the SPIS module.
+ * The data are sent and received being wrapped into a SPI v3 container.
+ */
+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode,
+ struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf)
+{
+ const uint16_t max_payload_rx_size = rx_buf->size;
+ int result = 0;
+
+#pragma pack(push, 1)
+ union {
+ uint32_t raw;
+
+ struct {
+ uint16_t opcode;
+ uint16_t size;
+ };
+ } spi_tx_hdr;
+
+ union {
+ uint32_t raw;
+
+ struct {
+ uint16_t error_code;
+ uint16_t size;
+ };
+ } spi_rx_hdr;
+#pragma pack(pop)
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, "%s: Started\n", __func__);
+#endif
+
+ /* Disable transmission from Tx FIFO */
+ result = nthw_spim_enable(p->mp_spim_mod, false);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n");
+ return result;
+ }
+
+ /* Enable SPIS module */
+ result = nthw_spis_enable(p->mp_spis_mod, true);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spis_enable failed\n");
+ return result;
+ }
+
+ /* Put data into Tx FIFO */
+ spi_tx_hdr.opcode = opcode;
+ spi_tx_hdr.size = tx_buf->size;
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, "opcode=0x%04X tx_bufsize=0x%04X rx_bufsize=0x%04X\n",
+ opcode, tx_buf->size, rx_buf->size);
+
+#endif /* SPI_V3_DEBUG_PRINT */
+
+ result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(spi_tx_hdr.raw));
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed\n");
+ return result;
+ }
+
+ {
+ uint8_t *tx_data = (uint8_t *)tx_buf->p_buf;
+ uint16_t tx_size = tx_buf->size;
+ uint16_t count;
+ uint32_t value;
+
+ while (tx_size > 0) {
+ if (tx_size > 4) {
+ count = 4;
+ } else {
+ count = tx_size;
+ value = 0;
+ }
+
+ memcpy(&value, tx_data, count);
+
+ result = nthw_spim_write_tx_fifo(p->mp_spim_mod,
+ htonl(value));
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spim_write_tx_fifo failed\n");
+ return result;
+ }
+
+ tx_size = (uint16_t)(tx_size - count);
+ tx_data += count;
+ }
+ }
+
+ /* Enable Tx FIFO */
+ result = nthw_spim_enable(p->mp_spim_mod, true);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n");
+ return result;
+ }
+
+ result = wait_for_tx_data_sent(p->mp_spim_mod, p->m_time_out);
+ if (result != 0)
+ return result;
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, "%s: SPI header and payload data have been sent\n",
+ __func__);
+#endif
+
+ {
+ /*
+ * Start receiving data
+ * The first data to read is the header
+ */
+ uint16_t rx_size = sizeof(spi_rx_hdr.raw);
+ uint8_t *rx_data = (uint8_t *)rx_buf->p_buf;
+ bool rx_hdr_read = false;
+
+ rx_buf->size = 0;
+
+ while (true) {
+ uint16_t count;
+ uint32_t value;
+
+ if (!rx_hdr_read) { /* Read the header */
+ result = wait_for_rx_data_ready(p->mp_spis_mod,
+ p->m_time_out);
+ if (result != 0)
+ return result;
+
+ result = nthw_spis_read_rx_fifo(p->mp_spis_mod,
+ &spi_rx_hdr.raw);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spis_read_rx_fifo failed\n");
+ return result;
+ }
+
+ spi_rx_hdr.raw = ntohl(spi_rx_hdr.raw);
+ rx_size = spi_rx_hdr.size;
+ rx_hdr_read = true; /* Next time read payload */
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW,
+ " spi_rx_hdr.error_code = 0x%04X, spi_rx_hdr.size = 0x%04X\n",
+ spi_rx_hdr.error_code, spi_rx_hdr.size);
+#endif
+
+ if (spi_rx_hdr.error_code != 0) {
+ result = -1; /* NT_ERROR_AVR_OPCODE_RETURNED_ERROR; */
+ break;
+ }
+
+ if (rx_size > max_payload_rx_size) {
+ result = 1; /* NT_ERROR_AVR_RX_BUFFER_TOO_SMALL; */
+ break;
+ }
+ } else { /* Read the payload */
+ count = (uint16_t)(rx_size < 4U ? rx_size : 4U);
+
+ if (count == 0)
+ break;
+
+ result = wait_for_rx_data_ready(p->mp_spis_mod,
+ p->m_time_out);
+ if (result != 0)
+ return result;
+
+ result = nthw_spis_read_rx_fifo(p->mp_spis_mod,
+ &value);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spis_read_rx_fifo failed\n");
+ return result;
+ }
+
+ value = ntohl(value); /* Convert to host endian */
+ memcpy(rx_data, &value, count);
+ rx_buf->size = (uint16_t)(rx_buf->size + count);
+ rx_size = (uint16_t)(rx_size - count);
+ rx_data += count;
+ }
+ }
+ }
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, " RxData: %d\n", rx_buf->size);
+ dump_hex(rx_buf->p_buf, rx_buf->size);
+ NT_LOG(DBG, NTHW, "%s: Ended: %d\n", __func__, result);
+#endif
+
+ return result;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.h b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h
new file mode 100644
index 0000000000..c54379a273
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NT4GA_SPI_V3__
+#define __NT4GA_SPI_V3__
+
+/* Must include v1.x series. The first v1.0a only had 248 bytes of storage. v2.0x have 255 */
+#define MAX_AVR_CONTAINER_SIZE (248)
+
+enum avr_opcodes {
+ AVR_OP_NOP = 0, /* v2 NOP command */
+ /* version handlers */
+ AVR_OP_VERSION = 1,
+ AVR_OP_SPI_VERSION = 2, /* v2.0+ command Get protocol version */
+ AVR_OP_SYSINFO = 3,
+ /* Ping handlers */
+ AVR_OP_PING = 4,
+ AVR_OP_PING_DELAY = 5,
+ /* i2c handlers */
+ AVR_OP_I2C_READ = 9,
+ AVR_OP_I2C_WRITE = 10,
+ AVR_OP_I2C_RANDOM_READ = 11,
+ /* VPD handlers */
+ AVR_OP_VPD_READ = 19,
+ AVR_OP_VPD_WRITE = 20,
+ /* SENSOR handlers */
+ AVR_OP_SENSOR_FETCH = 28,
+ /* The following command are only relevant to V3 */
+ AVR_OP_SENSOR_MON_CONTROL = 42,
+ AVR_OP_SENSOR_MON_SETUP = 43,
+ /* special version handler */
+ AVR_OP_SYSINFO_2 = 62,
+};
+
+#define GEN2_AVR_IDENT_SIZE (20)
+#define GEN2_AVR_VERSION_SIZE (50)
+
+#define GEN2_PN_SIZE (13)
+#define GEN2_PBA_SIZE (16)
+#define GEN2_SN_SIZE (10)
+#define GEN2_BNAME_SIZE (14)
+#define GEN2_PLATFORM_SIZE (72)
+#define GEN2_VPD_SIZE_TOTAL \
+ (1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + GEN2_SN_SIZE + GEN2_BNAME_SIZE + \
+ GEN2_PLATFORM_SIZE + 2)
+
+typedef struct vpd_eeprom_s {
+ uint8_t psu_hw_version; /* Hw revision - MUST NEVER ne overwritten. */
+ /* Vital Product Data: P/N (13bytes ascii 0-9) */
+ uint8_t vpd_pn[GEN2_PN_SIZE];
+ /* Vital Product Data: PBA (16bytes ascii 0-9) */
+ uint8_t vpd_pba[GEN2_PBA_SIZE];
+ /* Vital Product Data: S/N (10bytes ascii 0-9) */
+ uint8_t vpd_sn[GEN2_SN_SIZE];
+ /* Vital Product Data: Board Name (10bytes ascii) (e.g. "ntmainb1e2" or "ntfront20b1") */
+ uint8_t vpd_board_name[GEN2_BNAME_SIZE];
+ /*
+ * Vital Product Data: Other (72bytes of MAC addresses or other stuff.. (gives up to 12 mac
+ * addresses)
+ */
+ uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];
+ /* CRC16 checksum of all of above. This field is not included in the checksum */
+ uint16_t crc16;
+} vpd_eeprom_t;
+
+typedef struct {
+ uint8_t psu_hw_revision;
+ char board_type[GEN2_BNAME_SIZE + 1];
+ char product_id[GEN2_PN_SIZE + 1];
+ char pba_id[GEN2_PBA_SIZE + 1];
+ char serial_number[GEN2_SN_SIZE + 1];
+ uint8_t product_family;
+ uint32_t feature_mask;
+ uint32_t invfeature_mask;
+ uint8_t no_of_macs;
+ uint8_t mac_address[6];
+ uint16_t custom_id;
+ uint8_t user_id[8];
+} board_info_t;
+
+struct tx_rx_buf {
+ uint16_t size;
+ void *p_buf;
+};
+
+struct nthw__spi__v3 {
+ int m_time_out;
+ int mn_instance_no;
+ nthw_spim_t *mp_spim_mod;
+ nthw_spis_t *mp_spis_mod;
+};
+
+typedef struct nthw__spi__v3 nthw_spi_v3_t;
+typedef struct nthw__spi__v3 nthw_spi_v3;
+
+nthw_spi_v3_t *nthw_spi_v3_new(void);
+int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no);
+void nthw_spi_v3_delete(nthw_spi_v3_t *p);
+
+int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out);
+int nthw_spi_v3_get_version(nthw_spi_v3_t *p);
+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode,
+ struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf);
+
+#endif /* __NT4GA_SPI_V3__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.c b/drivers/net/ntnic/nthw/core/nthw_spim.c
new file mode 100644
index 0000000000..ece7db26e1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spim.c
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_spim.h"
+
+nthw_spim_t *nthw_spim_new(void)
+{
+ nthw_spim_t *p = malloc(sizeof(nthw_spim_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_spim_t));
+ return p;
+}
+
+int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIM, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: SPIM %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_spim = mod;
+
+ /* SPIM is a primary communication channel - turn off debug by default */
+ module_set_debug_mode(p->mp_mod_spim, 0x00);
+
+ p->mp_reg_srr = module_get_register(p->mp_mod_spim, SPIM_SRR);
+ p->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIM_SRR_RST);
+
+ p->mp_reg_cr = module_get_register(p->mp_mod_spim, SPIM_CR);
+ p->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIM_CR_LOOP);
+ p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIM_CR_EN);
+ p->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIM_CR_TXRST);
+ p->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIM_CR_RXRST);
+
+ p->mp_reg_sr = module_get_register(p->mp_mod_spim, SPIM_SR);
+ p->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIM_SR_DONE);
+ p->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIM_SR_TXEMPTY);
+ p->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIM_SR_RXEMPTY);
+ p->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIM_SR_TXFULL);
+ p->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIM_SR_RXFULL);
+ p->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIM_SR_TXLVL);
+ p->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIM_SR_RXLVL);
+
+ p->mp_reg_dtr = module_get_register(p->mp_mod_spim, SPIM_DTR);
+ p->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIM_DTR_DTR);
+
+ p->mp_reg_drr = module_get_register(p->mp_mod_spim, SPIM_DRR);
+ p->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIM_DRR_DRR);
+
+ p->mp_reg_cfg = module_get_register(p->mp_mod_spim, SPIM_CFG);
+ p->mp_fld_cfg_pre = register_get_field(p->mp_reg_cfg, SPIM_CFG_PRE);
+
+ return 0;
+}
+
+void nthw_spim_delete(nthw_spim_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_spim_t));
+ free(p);
+ }
+}
+
+uint32_t nthw_spim_reset(nthw_spim_t *p)
+{
+ register_update(p->mp_reg_srr);
+ field_set_val32(p->mp_fld_srr_rst,
+ 0x0A); /* 0x0A hardcoded value - see doc */
+ register_flush(p->mp_reg_srr, 1);
+
+ return 0;
+}
+
+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_cr_en);
+
+ if (b_enable)
+ field_set_all(p->mp_fld_cr_en);
+
+ else
+ field_clr_all(p->mp_fld_cr_en);
+ field_flush_register(p->mp_fld_cr_en);
+
+ return 0;
+}
+
+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data)
+{
+ field_set_val_flush32(p->mp_fld_dtr_dtr, n_data);
+ return 0;
+}
+
+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty)
+{
+ assert(pb_empty);
+
+ *pb_empty = field_get_updated(p->mp_fld_sr_txempty) ? true : false;
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.h b/drivers/net/ntnic/nthw/core/nthw_spim.h
new file mode 100644
index 0000000000..713751e563
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spim.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SPIM_H__
+#define __NTHW_SPIM_H__
+
+struct nthw_spim {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_spim;
+ int mn_instance;
+
+ nt_register_t *mp_reg_srr;
+ nt_field_t *mp_fld_srr_rst;
+
+ nt_register_t *mp_reg_cr;
+ nt_field_t *mp_fld_cr_loop;
+ nt_field_t *mp_fld_cr_en;
+ nt_field_t *mp_fld_cr_txrst;
+ nt_field_t *mp_fld_cr_rxrst;
+
+ nt_register_t *mp_reg_sr;
+ nt_field_t *mp_fld_sr_done;
+ nt_field_t *mp_fld_sr_txempty;
+ nt_field_t *mp_fld_sr_rxempty;
+ nt_field_t *mp_fld_sr_txfull;
+ nt_field_t *mp_fld_sr_rxfull;
+ nt_field_t *mp_fld_sr_txlvl;
+ nt_field_t *mp_fld_sr_rxlvl;
+
+ nt_register_t *mp_reg_dtr;
+ nt_field_t *mp_fld_dtr_dtr;
+
+ nt_register_t *mp_reg_drr;
+ nt_field_t *mp_fld_drr_drr;
+ nt_register_t *mp_reg_cfg;
+ nt_field_t *mp_fld_cfg_pre;
+};
+
+typedef struct nthw_spim nthw_spim_t;
+typedef struct nthw_spim nthw_spim;
+
+nthw_spim_t *nthw_spim_new(void);
+int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_spim_delete(nthw_spim_t *p);
+
+uint32_t nthw_spim_reset(nthw_spim_t *p);
+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable);
+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty);
+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data);
+
+#endif /* __NTHW_SPIM_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.c b/drivers/net/ntnic/nthw/core/nthw_spis.c
new file mode 100644
index 0000000000..8799584194
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spis.c
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_spis.h"
+
+nthw_spis_t *nthw_spis_new(void)
+{
+ nthw_spis_t *p = malloc(sizeof(nthw_spis_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_spis_t));
+ return p;
+}
+
+int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIS, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: SPIS %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_spis = mod;
+
+ /* SPIS is a primary communication channel - turn off debug by default */
+ module_set_debug_mode(p->mp_mod_spis, 0x00);
+
+ p->mp_reg_srr = module_get_register(p->mp_mod_spis, SPIS_SRR);
+ p->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIS_SRR_RST);
+
+ p->mp_reg_cr = module_get_register(p->mp_mod_spis, SPIS_CR);
+ p->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIS_CR_LOOP);
+ p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIS_CR_EN);
+ p->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIS_CR_TXRST);
+ p->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIS_CR_RXRST);
+ p->mp_fld_cr_debug = register_get_field(p->mp_reg_cr, SPIS_CR_DEBUG);
+
+ p->mp_reg_sr = module_get_register(p->mp_mod_spis, SPIS_SR);
+ p->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIS_SR_DONE);
+ p->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIS_SR_TXEMPTY);
+ p->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIS_SR_RXEMPTY);
+ p->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIS_SR_TXFULL);
+ p->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIS_SR_RXFULL);
+ p->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIS_SR_TXLVL);
+ p->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIS_SR_RXLVL);
+ p->mp_fld_sr_frame_err =
+ register_get_field(p->mp_reg_sr, SPIS_SR_FRAME_ERR);
+ p->mp_fld_sr_read_err = register_get_field(p->mp_reg_sr, SPIS_SR_READ_ERR);
+ p->mp_fld_sr_write_err =
+ register_get_field(p->mp_reg_sr, SPIS_SR_WRITE_ERR);
+
+ p->mp_reg_dtr = module_get_register(p->mp_mod_spis, SPIS_DTR);
+ p->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIS_DTR_DTR);
+
+ p->mp_reg_drr = module_get_register(p->mp_mod_spis, SPIS_DRR);
+ p->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIS_DRR_DRR);
+
+ p->mp_reg_ram_ctrl = module_get_register(p->mp_mod_spis, SPIS_RAM_CTRL);
+ p->mp_fld_ram_ctrl_adr =
+ register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_ADR);
+ p->mp_fld_ram_ctrl_cnt =
+ register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_CNT);
+
+ p->mp_reg_ram_data = module_get_register(p->mp_mod_spis, SPIS_RAM_DATA);
+ p->mp_fld_ram_data_data =
+ register_get_field(p->mp_reg_ram_data, SPIS_RAM_DATA_DATA);
+
+ return 0;
+}
+
+void nthw_spis_delete(nthw_spis_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_spis_t));
+ free(p);
+ }
+}
+
+uint32_t nthw_spis_reset(nthw_spis_t *p)
+{
+ register_update(p->mp_reg_srr);
+ field_set_val32(p->mp_fld_srr_rst,
+ 0x0A); /* 0x0A hardcoded value - see doc */
+ register_flush(p->mp_reg_srr, 1);
+
+ return 0;
+}
+
+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_cr_en);
+
+ if (b_enable)
+ field_set_all(p->mp_fld_cr_en);
+
+ else
+ field_clr_all(p->mp_fld_cr_en);
+ field_flush_register(p->mp_fld_cr_en);
+
+ return 0;
+}
+
+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty)
+{
+ assert(pb_empty);
+
+ *pb_empty = field_get_updated(p->mp_fld_sr_rxempty) ? true : false;
+
+ return 0;
+}
+
+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data)
+{
+ assert(p_data);
+
+ *p_data = field_get_updated(p->mp_fld_drr_drr);
+
+ return 0;
+}
+
+uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx,
+ uint32_t *p_sensor_result)
+{
+ assert(p_sensor_result);
+
+ field_set_val32(p->mp_fld_ram_ctrl_adr, n_result_idx);
+ field_set_val32(p->mp_fld_ram_ctrl_cnt, 1);
+ register_flush(p->mp_reg_ram_ctrl, 1);
+
+ *p_sensor_result = field_get_updated(p->mp_fld_ram_data_data);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.h b/drivers/net/ntnic/nthw/core/nthw_spis.h
new file mode 100644
index 0000000000..2ebe840c9e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spis.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SPIS_H__
+#define __NTHW_SPIS_H__
+
+struct nthw_spis {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_spis;
+ int mn_instance;
+
+ nt_register_t *mp_reg_srr;
+ nt_field_t *mp_fld_srr_rst;
+
+ nt_register_t *mp_reg_cr;
+ nt_field_t *mp_fld_cr_loop;
+ nt_field_t *mp_fld_cr_en;
+ nt_field_t *mp_fld_cr_txrst;
+ nt_field_t *mp_fld_cr_rxrst;
+ nt_field_t *mp_fld_cr_debug;
+
+ nt_register_t *mp_reg_sr;
+ nt_field_t *mp_fld_sr_done;
+ nt_field_t *mp_fld_sr_txempty;
+ nt_field_t *mp_fld_sr_rxempty;
+ nt_field_t *mp_fld_sr_txfull;
+ nt_field_t *mp_fld_sr_rxfull;
+ nt_field_t *mp_fld_sr_txlvl;
+ nt_field_t *mp_fld_sr_rxlvl;
+ nt_field_t *mp_fld_sr_frame_err;
+ nt_field_t *mp_fld_sr_read_err;
+ nt_field_t *mp_fld_sr_write_err;
+
+ nt_register_t *mp_reg_dtr;
+ nt_field_t *mp_fld_dtr_dtr;
+
+ nt_register_t *mp_reg_drr;
+ nt_field_t *mp_fld_drr_drr;
+
+ nt_register_t *mp_reg_ram_ctrl;
+ nt_field_t *mp_fld_ram_ctrl_adr;
+ nt_field_t *mp_fld_ram_ctrl_cnt;
+
+ nt_register_t *mp_reg_ram_data;
+ nt_field_t *mp_fld_ram_data_data;
+};
+
+typedef struct nthw_spis nthw_spis_t;
+typedef struct nthw_spis nthw_spis;
+
+nthw_spis_t *nthw_spis_new(void);
+int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_spis_delete(nthw_spis_t *p);
+
+uint32_t nthw_spis_reset(nthw_spis_t *p);
+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable);
+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty);
+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data);
+uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx,
+ uint32_t *p_sensor_result);
+
+#endif /* __NTHW_SPIS_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.c b/drivers/net/ntnic/nthw/core/nthw_tsm.c
new file mode 100644
index 0000000000..8ea4a4c440
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_tsm.c
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_tsm.h"
+
+nthw_tsm_t *nthw_tsm_new(void)
+{
+ nthw_tsm_t *p = malloc(sizeof(nthw_tsm_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_tsm_t));
+ return p;
+}
+
+void nthw_tsm_delete(nthw_tsm_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_tsm_t));
+ free(p);
+ }
+}
+
+int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_TSM, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TSM %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_tsm = mod;
+
+ {
+ nt_register_t *p_reg;
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_CONFIG);
+ p->mp_fld_config_ts_format =
+ register_get_field(p_reg, TSM_CONFIG_TS_FORMAT);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_CTRL);
+ p->mp_fld_timer_ctrl_timer_en_t0 =
+ register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T0);
+ p->mp_fld_timer_ctrl_timer_en_t1 =
+ register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T1);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T0);
+ p->mp_fld_timer_timer_t0_max_count =
+ register_get_field(p_reg, TSM_TIMER_T0_MAX_COUNT);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T1);
+ p->mp_fld_timer_timer_t1_max_count =
+ register_get_field(p_reg, TSM_TIMER_T1_MAX_COUNT);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_LO);
+ p->mp_reg_time_lo = module_get_register(p->mp_mod_tsm, TSM_TIME_LO);
+ p->mp_fld_time_lo = register_get_field(p_reg, TSM_TIME_LO_NS);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_HI);
+ p->mp_reg_time_hi = module_get_register(p->mp_mod_tsm, TSM_TIME_HI);
+ p->mp_fld_time_hi = register_get_field(p_reg, TSM_TIME_HI_SEC);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TS_LO);
+ p->mp_reg_ts_lo = module_get_register(p->mp_mod_tsm, TSM_TS_LO);
+ p->mp_fld_ts_lo = register_get_field(p_reg, TSM_TS_LO_TIME);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TS_HI);
+ p->mp_reg_ts_hi = module_get_register(p->mp_mod_tsm, TSM_TS_HI);
+ p->mp_fld_ts_hi = register_get_field(p_reg, TSM_TS_HI_TIME);
+ }
+ return 0;
+}
+
+int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts)
+{
+ uint32_t n_ts_lo, n_ts_hi;
+ uint64_t val;
+
+ if (!p_ts)
+ return -1;
+
+ n_ts_lo = field_get_updated(p->mp_fld_ts_lo);
+ n_ts_hi = field_get_updated(p->mp_fld_ts_hi);
+
+ val = ((((uint64_t)n_ts_hi) << 32UL) | n_ts_lo);
+
+ if (p_ts)
+ *p_ts = val;
+
+ return 0;
+}
+
+int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time)
+{
+ uint32_t n_time_lo, n_time_hi;
+ uint64_t val;
+
+ if (!p_time)
+ return -1;
+
+ n_time_lo = field_get_updated(p->mp_fld_time_lo);
+ n_time_hi = field_get_updated(p->mp_fld_time_hi);
+
+ val = ((((uint64_t)n_time_hi) << 32UL) | n_time_lo);
+
+ if (p_time)
+ *p_time = val;
+
+ return 0;
+}
+
+int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time)
+{
+ field_set_val_flush32(p->mp_fld_time_lo, (n_time & 0xFFFFFFFF));
+ field_set_val_flush32(p->mp_fld_time_hi,
+ (uint32_t)((n_time >> 32) & 0xFFFFFFFF));
+ return 0;
+}
+
+int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_timer_ctrl_timer_en_t0);
+ if (b_enable)
+ field_set_flush(p->mp_fld_timer_ctrl_timer_en_t0);
+
+ else
+ field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t0);
+ return 0;
+}
+
+int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val)
+{
+ /* Timer T0 - stat toggle timer */
+ field_update_register(p->mp_fld_timer_timer_t0_max_count);
+ field_set_val_flush32(p->mp_fld_timer_timer_t0_max_count,
+ n_timer_val); /* ns (50*1000*1000) */
+ return 0;
+}
+
+int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_timer_ctrl_timer_en_t1);
+ if (b_enable)
+ field_set_flush(p->mp_fld_timer_ctrl_timer_en_t1);
+
+ else
+ field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t1);
+ return 0;
+}
+
+int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val)
+{
+ /* Timer T1 - keep alive timer */
+ field_update_register(p->mp_fld_timer_timer_t1_max_count);
+ field_set_val_flush32(p->mp_fld_timer_timer_t1_max_count,
+ n_timer_val); /* ns (100*1000*1000) */
+ return 0;
+}
+
+int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val)
+{
+ field_update_register(p->mp_fld_config_ts_format);
+ /* 0x1: Native - 10ns units, start date: 1970-01-01. */
+ field_set_val_flush32(p->mp_fld_config_ts_format, n_val);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.h b/drivers/net/ntnic/nthw/core/nthw_tsm.h
new file mode 100644
index 0000000000..590e04c312
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_tsm.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_TSM_H__
+#define __NTHW_TSM_H__
+
+struct nthw_tsm {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_tsm;
+ int mn_instance;
+
+ nt_field_t *mp_fld_config_ts_format;
+
+ nt_field_t *mp_fld_timer_ctrl_timer_en_t0;
+ nt_field_t *mp_fld_timer_ctrl_timer_en_t1;
+
+ nt_field_t *mp_fld_timer_timer_t0_max_count;
+
+ nt_field_t *mp_fld_timer_timer_t1_max_count;
+
+ nt_register_t *mp_reg_ts_lo;
+ nt_field_t *mp_fld_ts_lo;
+
+ nt_register_t *mp_reg_ts_hi;
+ nt_field_t *mp_fld_ts_hi;
+
+ nt_register_t *mp_reg_time_lo;
+ nt_field_t *mp_fld_time_lo;
+
+ nt_register_t *mp_reg_time_hi;
+ nt_field_t *mp_fld_time_hi;
+};
+
+typedef struct nthw_tsm nthw_tsm_t;
+typedef struct nthw_tsm nthw_tsm;
+
+nthw_tsm_t *nthw_tsm_new(void);
+void nthw_tsm_delete(nthw_tsm_t *p);
+int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts);
+int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time);
+int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time);
+
+int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable);
+int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val);
+int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable);
+int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val);
+
+int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val);
+
+#endif /* __NTHW_TSM_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_dbs.c b/drivers/net/ntnic/nthw/nthw_dbs.c
new file mode 100644
index 0000000000..9fc853da73
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_dbs.c
@@ -0,0 +1,1301 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <errno.h>
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_dbs.h"
+
+#undef DBS_PRINT_REGS
+
+static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable,
+ uint32_t ir, uint32_t bs);
+static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index,
+ uint32_t virtual_port);
+static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed);
+static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t header,
+ uint32_t packed);
+static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order);
+static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec,
+ uint32_t istk);
+static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index);
+
+nthw_dbs_t *nthw_dbs_new(void)
+{
+ nthw_dbs_t *p = malloc(sizeof(nthw_dbs_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_dbs_t));
+ return p;
+}
+
+void nthw_dbs_delete(nthw_dbs_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_dbs_t));
+ free(p);
+ }
+}
+
+int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_DBS, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: DBS %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_dbs = mod;
+
+ p->mn_param_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);
+ if (p->mn_param_dbs_present == 0) {
+ NT_LOG(WRN, NTHW,
+ "%s: DBS %d: logical error: module found but not flagged at present\n",
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str, p->mn_instance);
+ }
+
+ p->mp_reg_rx_control = module_get_register(p->mp_mod_dbs, DBS_RX_CONTROL);
+ p->mp_fld_rx_control_last_queue =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_LQ);
+ p->mp_fld_rx_control_avail_monitor_enable =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AME);
+ p->mp_fld_rx_control_avail_monitor_scan_speed =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AMS);
+ p->mp_fld_rx_control_used_write_enable =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWE);
+ p->mp_fld_rx_control_used_writer_update_speed =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWS);
+ p->mp_fld_rx_control_rx_queues_enable =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_QE);
+
+ p->mp_reg_tx_control = module_get_register(p->mp_mod_dbs, DBS_TX_CONTROL);
+ p->mp_fld_tx_control_last_queue =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_LQ);
+ p->mp_fld_tx_control_avail_monitor_enable =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AME);
+ p->mp_fld_tx_control_avail_monitor_scan_speed =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AMS);
+ p->mp_fld_tx_control_used_write_enable =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWE);
+ p->mp_fld_tx_control_used_writer_update_speed =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWS);
+ p->mp_fld_tx_control_tx_queues_enable =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_QE);
+
+ p->mp_reg_rx_init = module_get_register(p->mp_mod_dbs, DBS_RX_INIT);
+ p->mp_fld_rx_init_init =
+ register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_INIT);
+ p->mp_fld_rx_init_queue =
+ register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_QUEUE);
+ p->mp_fld_rx_init_busy =
+ register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_BUSY);
+
+ p->mp_reg_rx_init_val = module_query_register(p->mp_mod_dbs, DBS_RX_INIT_VAL);
+ if (p->mp_reg_rx_init_val) {
+ p->mp_fld_rx_init_val_idx = register_query_field(p->mp_reg_rx_init_val,
+ DBS_RX_INIT_VAL_IDX);
+ p->mp_fld_rx_init_val_ptr = register_query_field(p->mp_reg_rx_init_val,
+ DBS_RX_INIT_VAL_PTR);
+ }
+
+ p->mp_reg_rx_ptr = module_query_register(p->mp_mod_dbs, DBS_RX_PTR);
+ if (p->mp_reg_rx_ptr) {
+ p->mp_fld_rx_ptr_ptr =
+ register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_PTR);
+ p->mp_fld_rx_ptr_queue =
+ register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_QUEUE);
+ p->mp_fld_rx_ptr_valid =
+ register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_VALID);
+ }
+
+ p->mp_reg_tx_init = module_get_register(p->mp_mod_dbs, DBS_TX_INIT);
+ p->mp_fld_tx_init_init =
+ register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_INIT);
+ p->mp_fld_tx_init_queue =
+ register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_QUEUE);
+ p->mp_fld_tx_init_busy =
+ register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_BUSY);
+
+ p->mp_reg_tx_init_val = module_query_register(p->mp_mod_dbs, DBS_TX_INIT_VAL);
+ if (p->mp_reg_tx_init_val) {
+ p->mp_fld_tx_init_val_idx = register_query_field(p->mp_reg_tx_init_val,
+ DBS_TX_INIT_VAL_IDX);
+ p->mp_fld_tx_init_val_ptr = register_query_field(p->mp_reg_tx_init_val,
+ DBS_TX_INIT_VAL_PTR);
+ }
+
+ p->mp_reg_tx_ptr = module_query_register(p->mp_mod_dbs, DBS_TX_PTR);
+ if (p->mp_reg_tx_ptr) {
+ p->mp_fld_tx_ptr_ptr =
+ register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_PTR);
+ p->mp_fld_tx_ptr_queue =
+ register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_QUEUE);
+ p->mp_fld_tx_ptr_valid =
+ register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_VALID);
+ }
+
+ p->mp_reg_rx_idle = module_query_register(p->mp_mod_dbs, DBS_RX_IDLE);
+ if (p->mp_reg_rx_idle) {
+ p->mp_fld_rx_idle_idle =
+ register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_IDLE);
+ p->mp_fld_rx_idle_queue =
+ register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_QUEUE);
+ p->mp_fld_rx_idle_busy =
+ register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_BUSY);
+ }
+
+ p->mp_reg_tx_idle = module_query_register(p->mp_mod_dbs, DBS_TX_IDLE);
+ if (p->mp_reg_tx_idle) {
+ p->mp_fld_tx_idle_idle =
+ register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_IDLE);
+ p->mp_fld_tx_idle_queue =
+ register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_QUEUE);
+ p->mp_fld_tx_idle_busy =
+ register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_BUSY);
+ }
+
+ p->mp_reg_rx_avail_monitor_control =
+ module_get_register(p->mp_mod_dbs, DBS_RX_AM_CTRL);
+ p->mp_fld_rx_avail_monitor_control_adr =
+ register_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_ADR);
+ p->mp_fld_rx_avail_monitor_control_cnt =
+ register_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_CNT);
+
+ p->mp_reg_rx_avail_monitor_data =
+ module_get_register(p->mp_mod_dbs, DBS_RX_AM_DATA);
+ p->mp_fld_rx_avail_monitor_data_guest_physical_address =
+ register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_GPA);
+ p->mp_fld_rx_avail_monitor_data_enable =
+ register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_ENABLE);
+ p->mp_fld_rx_avail_monitor_data_host_id =
+ register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_HID);
+ p->mp_fld_rx_avail_monitor_data_packed =
+ register_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_PCKED);
+ p->mp_fld_rx_avail_monitor_data_int =
+ register_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_INT);
+
+ p->mp_reg_tx_avail_monitor_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_AM_CTRL);
+ p->mp_fld_tx_avail_monitor_control_adr =
+ register_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_ADR);
+ p->mp_fld_tx_avail_monitor_control_cnt =
+ register_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_CNT);
+
+ p->mp_reg_tx_avail_monitor_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_AM_DATA);
+ p->mp_fld_tx_avail_monitor_data_guest_physical_address =
+ register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_GPA);
+ p->mp_fld_tx_avail_monitor_data_enable =
+ register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_ENABLE);
+ p->mp_fld_tx_avail_monitor_data_host_id =
+ register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_HID);
+ p->mp_fld_tx_avail_monitor_data_packed =
+ register_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_PCKED);
+ p->mp_fld_tx_avail_monitor_data_int =
+ register_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_INT);
+
+ p->mp_reg_rx_used_writer_control =
+ module_get_register(p->mp_mod_dbs, DBS_RX_UW_CTRL);
+ p->mp_fld_rx_used_writer_control_adr =
+ register_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_ADR);
+ p->mp_fld_rx_used_writer_control_cnt =
+ register_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_CNT);
+
+ p->mp_reg_rx_used_writer_data =
+ module_get_register(p->mp_mod_dbs, DBS_RX_UW_DATA);
+ p->mp_fld_rx_used_writer_data_guest_physical_address =
+ register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_GPA);
+ p->mp_fld_rx_used_writer_data_host_id =
+ register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_HID);
+ p->mp_fld_rx_used_writer_data_queue_size =
+ register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_QS);
+ p->mp_fld_rx_used_writer_data_packed =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_PCKED);
+ p->mp_fld_rx_used_writer_data_int =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_INT);
+ p->mp_fld_rx_used_writer_data_vec =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_VEC);
+ p->mp_fld_rx_used_writer_data_istk =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_ISTK);
+
+ p->mp_reg_tx_used_writer_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_UW_CTRL);
+ p->mp_fld_tx_used_writer_control_adr =
+ register_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_ADR);
+ p->mp_fld_tx_used_writer_control_cnt =
+ register_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_CNT);
+
+ p->mp_reg_tx_used_writer_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_UW_DATA);
+ p->mp_fld_tx_used_writer_data_guest_physical_address =
+ register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_GPA);
+ p->mp_fld_tx_used_writer_data_host_id =
+ register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_HID);
+ p->mp_fld_tx_used_writer_data_queue_size =
+ register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_QS);
+ p->mp_fld_tx_used_writer_data_packed =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_PCKED);
+ p->mp_fld_tx_used_writer_data_int =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INT);
+ p->mp_fld_tx_used_writer_data_vec =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_VEC);
+ p->mp_fld_tx_used_writer_data_istk =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_ISTK);
+ p->mp_fld_tx_used_writer_data_in_order =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INO);
+
+ p->mp_reg_rx_descriptor_reader_control =
+ module_get_register(p->mp_mod_dbs, DBS_RX_DR_CTRL);
+ p->mp_fld_rx_descriptor_reader_control_adr =
+ register_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_ADR);
+ p->mp_fld_rx_descriptor_reader_control_cnt =
+ register_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_CNT);
+
+ p->mp_reg_rx_descriptor_reader_data =
+ module_get_register(p->mp_mod_dbs, DBS_RX_DR_DATA);
+ p->mp_fld_rx_descriptor_reader_data_guest_physical_address =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_GPA);
+ p->mp_fld_rx_descriptor_reader_data_host_id =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HID);
+ p->mp_fld_rx_descriptor_reader_data_queue_size =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_QS);
+ p->mp_fld_rx_descriptor_reader_data_header =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HDR);
+ p->mp_fld_rx_descriptor_reader_data_packed =
+ register_query_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_PCKED);
+
+ p->mp_reg_tx_descriptor_reader_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_DR_CTRL);
+ p->mp_fld_tx_descriptor_reader_control_adr =
+ register_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_ADR);
+ p->mp_fld_tx_descriptor_reader_control_cnt =
+ register_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_CNT);
+
+ p->mp_reg_tx_descriptor_reader_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_DR_DATA);
+ p->mp_fld_tx_descriptor_reader_data_guest_physical_address =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_GPA);
+ p->mp_fld_tx_descriptor_reader_data_host_id =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HID);
+ p->mp_fld_tx_descriptor_reader_data_queue_size =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_QS);
+ p->mp_fld_tx_descriptor_reader_data_header =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HDR);
+ p->mp_fld_tx_descriptor_reader_data_port =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PORT);
+ p->mp_fld_tx_descriptor_reader_data_packed =
+ register_query_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PCKED);
+
+ p->mp_reg_tx_queue_property_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_QP_CTRL);
+ p->mp_fld_tx_queue_property_control_adr =
+ register_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_ADR);
+ p->mp_fld_tx_queue_property_control_cnt =
+ register_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_CNT);
+
+ p->mp_reg_tx_queue_property_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_QP_DATA);
+ p->mp_fld_tx_queue_property_data_v_port =
+ register_get_field(p->mp_reg_tx_queue_property_data, DBS_TX_QP_DATA_VPORT);
+
+ /* HW QoS Tx rate limiting policing RFC2697/RFC4111 */
+ p->mp_reg_tx_queue_qos_control =
+ module_query_register(p->mp_mod_dbs, DBS_TX_QOS_CTRL);
+ p->mp_reg_tx_queue_qos_data =
+ module_query_register(p->mp_mod_dbs, DBS_TX_QOS_DATA);
+ if (p->mp_reg_tx_queue_qos_control) {
+ p->mp_reg_tx_queue_qos_control_adr =
+ register_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_ADR);
+ p->mp_reg_tx_queue_qos_control_cnt =
+ register_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_CNT);
+
+ if (p->mp_reg_tx_queue_qos_data) {
+ p->mp_reg_tx_queue_qos_data_en =
+ register_query_field(p->mp_reg_tx_queue_qos_data,
+ DBS_TX_QOS_DATA_EN);
+ p->mp_reg_tx_queue_qos_data_ir =
+ register_query_field(p->mp_reg_tx_queue_qos_data,
+ DBS_TX_QOS_DATA_IR);
+ p->mp_reg_tx_queue_qos_data_bs =
+ register_query_field(p->mp_reg_tx_queue_qos_data,
+ DBS_TX_QOS_DATA_BS);
+ }
+ }
+
+ p->mp_reg_tx_queue_qos_rate =
+ module_query_register(p->mp_mod_dbs, DBS_TX_QOS_RATE);
+ if (p->mp_reg_tx_queue_qos_rate) {
+ p->mp_reg_tx_queue_qos_rate_mul =
+ register_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_MUL);
+ p->mp_reg_tx_queue_qos_rate_div =
+ register_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_DIV);
+ }
+
+ return 0;
+}
+
+int dbs_reset_rx_control(nthw_dbs_t *p)
+{
+ field_set_val32(p->mp_fld_rx_control_last_queue, 0);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_enable, 0);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed, 8);
+ field_set_val32(p->mp_fld_rx_control_used_write_enable, 0);
+ field_set_val32(p->mp_fld_rx_control_used_writer_update_speed, 5);
+ field_set_val32(p->mp_fld_rx_control_rx_queues_enable, 0);
+ register_flush(p->mp_reg_rx_control, 1);
+ return 0;
+}
+
+int dbs_reset_tx_control(nthw_dbs_t *p)
+{
+ field_set_val32(p->mp_fld_tx_control_last_queue, 0);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_enable, 0);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed, 5);
+ field_set_val32(p->mp_fld_tx_control_used_write_enable, 0);
+ field_set_val32(p->mp_fld_tx_control_used_writer_update_speed, 8);
+ field_set_val32(p->mp_fld_tx_control_tx_queues_enable, 0);
+ register_flush(p->mp_reg_tx_control, 1);
+ return 0;
+}
+
+void dbs_reset(nthw_dbs_t *p)
+{
+ uint32_t i;
+
+ NT_LOG(DBG, NTHW, "NthwDbs::%s: resetting DBS", __func__);
+
+ dbs_reset_rx_control(p);
+ dbs_reset_tx_control(p);
+
+ /* Reset RX memory banks and shado */
+ for (i = 0; i < NT_DBS_RX_QUEUES_MAX; ++i) {
+ set_shadow_rx_am_data(p, i, 0, 0, 0, 0, 0);
+ flush_rx_am_data(p, i);
+
+ set_shadow_rx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0);
+ flush_rx_uw_data(p, i);
+
+ set_shadow_rx_dr_data(p, i, 0, 0, 0, 0, 0);
+ flush_rx_dr_data(p, i);
+ }
+
+ /* Reset TX memory banks and shado */
+ for (i = 0; i < NT_DBS_TX_QUEUES_MAX; ++i) {
+ set_shadow_tx_am_data(p, i, 0, 0, 0, 0, 0);
+ flush_tx_am_data(p, i);
+
+ set_shadow_tx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0, 0);
+ flush_tx_uw_data(p, i);
+
+ set_shadow_tx_dr_data(p, i, 0, 0, 0, 0, 0, 0);
+ flush_tx_dr_data(p, i);
+
+ set_shadow_tx_qp_data(p, i, 0);
+ flush_tx_qp_data(p, i);
+
+ set_shadow_tx_qos_data(p, i, 0, 0, 0);
+ flush_tx_qos_data(p, i);
+ }
+}
+
+int set_rx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t rx_queue_enable)
+{
+#ifdef DBS_PRINT_REGS
+ printf("last_queue %u\n", last_queue);
+ printf("avail_monitor_enable %u\n", avail_monitor_enable);
+ printf("avail_monitor_speed %u\n", avail_monitor_speed);
+ printf("used_write_enable %u\n", used_write_enable);
+ printf("used_write_speed %u\n", used_write_speed);
+ printf("rx_queue_enable %u\n", rx_queue_enable);
+#endif
+
+ field_set_val32(p->mp_fld_rx_control_last_queue, last_queue);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_enable, avail_monitor_enable);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed,
+ avail_monitor_speed);
+ field_set_val32(p->mp_fld_rx_control_used_write_enable, used_write_enable);
+ field_set_val32(p->mp_fld_rx_control_used_writer_update_speed, used_write_speed);
+ field_set_val32(p->mp_fld_rx_control_rx_queues_enable, rx_queue_enable);
+ register_flush(p->mp_reg_rx_control, 1);
+ return 0;
+}
+
+int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *rx_queue_enable)
+{
+ *last_queue = field_get_val32(p->mp_fld_rx_control_last_queue);
+ *avail_monitor_enable =
+ field_get_val32(p->mp_fld_rx_control_avail_monitor_enable);
+ *avail_monitor_speed =
+ field_get_val32(p->mp_fld_rx_control_avail_monitor_scan_speed);
+ *used_write_enable = field_get_val32(p->mp_fld_rx_control_used_write_enable);
+ *used_write_speed =
+ field_get_val32(p->mp_fld_rx_control_used_writer_update_speed);
+ *rx_queue_enable = field_get_val32(p->mp_fld_rx_control_rx_queues_enable);
+ return 0;
+}
+
+int set_tx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t tx_queue_enable)
+{
+#ifdef DBS_PRINT_REGS
+ printf("last_queue %u\n", last_queue);
+ printf("avail_monitor_enable %u\n", avail_monitor_enable);
+ printf("avail_monitor_speed %u\n", avail_monitor_speed);
+ printf("used_write_enable %u\n", used_write_enable);
+ printf("used_write_speed %u\n", used_write_speed);
+#endif
+
+ field_set_val32(p->mp_fld_tx_control_last_queue, last_queue);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_enable, avail_monitor_enable);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed,
+ avail_monitor_speed);
+ field_set_val32(p->mp_fld_tx_control_used_write_enable, used_write_enable);
+ field_set_val32(p->mp_fld_tx_control_used_writer_update_speed, used_write_speed);
+ field_set_val32(p->mp_fld_tx_control_tx_queues_enable, tx_queue_enable);
+ register_flush(p->mp_reg_tx_control, 1);
+ return 0;
+}
+
+int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *tx_queue_enable)
+{
+ *last_queue = field_get_val32(p->mp_fld_tx_control_last_queue);
+ *avail_monitor_enable =
+ field_get_val32(p->mp_fld_tx_control_avail_monitor_enable);
+ *avail_monitor_speed =
+ field_get_val32(p->mp_fld_tx_control_avail_monitor_scan_speed);
+ *used_write_enable = field_get_val32(p->mp_fld_tx_control_used_write_enable);
+ *used_write_speed =
+ field_get_val32(p->mp_fld_tx_control_used_writer_update_speed);
+ *tx_queue_enable = field_get_val32(p->mp_fld_tx_control_tx_queues_enable);
+ return 0;
+}
+
+int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue)
+{
+ if (p->mp_reg_rx_init_val) {
+ field_set_val32(p->mp_fld_rx_init_val_idx, start_idx);
+ field_set_val32(p->mp_fld_rx_init_val_ptr, start_ptr);
+ register_flush(p->mp_reg_rx_init_val, 1);
+ }
+ field_set_val32(p->mp_fld_rx_init_init, init);
+ field_set_val32(p->mp_fld_rx_init_queue, queue);
+ register_flush(p->mp_reg_rx_init, 1);
+ return 0;
+}
+
+int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy)
+{
+ *init = field_get_val32(p->mp_fld_rx_init_init);
+ *queue = field_get_val32(p->mp_fld_rx_init_queue);
+ *busy = field_get_val32(p->mp_fld_rx_init_busy);
+ return 0;
+}
+
+int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue)
+{
+ if (p->mp_reg_tx_init_val) {
+ field_set_val32(p->mp_fld_tx_init_val_idx, start_idx);
+ field_set_val32(p->mp_fld_tx_init_val_ptr, start_ptr);
+ register_flush(p->mp_reg_tx_init_val, 1);
+ }
+ field_set_val32(p->mp_fld_tx_init_init, init);
+ field_set_val32(p->mp_fld_tx_init_queue, queue);
+ register_flush(p->mp_reg_tx_init, 1);
+ return 0;
+}
+
+int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy)
+{
+ *init = field_get_val32(p->mp_fld_tx_init_init);
+ *queue = field_get_val32(p->mp_fld_tx_init_queue);
+ *busy = field_get_val32(p->mp_fld_tx_init_busy);
+ return 0;
+}
+
+int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue)
+
+{
+ if (!p->mp_reg_rx_idle)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_rx_idle_idle, idle);
+ field_set_val32(p->mp_fld_rx_idle_queue, queue);
+ register_flush(p->mp_reg_rx_idle, 1);
+ return 0;
+}
+
+int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy)
+{
+ if (!p->mp_reg_rx_idle)
+ return -ENOTSUP;
+
+ *idle = field_get_updated(p->mp_fld_rx_idle_idle);
+ *queue = 0;
+ *busy = field_get_updated(p->mp_fld_rx_idle_busy);
+ return 0;
+}
+
+int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue)
+
+{
+ if (!p->mp_reg_tx_idle)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_tx_idle_idle, idle);
+ field_set_val32(p->mp_fld_tx_idle_queue, queue);
+ register_flush(p->mp_reg_tx_idle, 1);
+ return 0;
+}
+
+int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy)
+{
+ if (!p->mp_reg_tx_idle)
+ return -ENOTSUP;
+
+ *idle = field_get_updated(p->mp_fld_tx_idle_idle);
+ *queue = 0;
+ *busy = field_get_updated(p->mp_fld_tx_idle_busy);
+ return 0;
+}
+
+int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue)
+{
+ if (!p->mp_reg_rx_ptr)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_rx_ptr_queue, queue);
+ register_flush(p->mp_reg_rx_ptr, 1);
+ return 0;
+}
+
+int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid)
+{
+ if (!p->mp_reg_rx_ptr)
+ return -ENOTSUP;
+
+ *ptr = field_get_updated(p->mp_fld_rx_ptr_ptr);
+ *queue = 0;
+ *valid = field_get_updated(p->mp_fld_rx_ptr_valid);
+ return 0;
+}
+
+int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue)
+{
+ if (!p->mp_reg_tx_ptr)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_tx_ptr_queue, queue);
+ register_flush(p->mp_reg_tx_ptr, 1);
+ return 0;
+}
+
+int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid)
+{
+ if (!p->mp_reg_tx_ptr)
+ return -ENOTSUP;
+
+ *ptr = field_get_updated(p->mp_fld_tx_ptr_ptr);
+ *queue = 0;
+ *valid = field_get_updated(p->mp_fld_tx_ptr_valid);
+ return 0;
+}
+
+static void set_rx_am_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_rx_avail_monitor_control_adr, index);
+ field_set_val32(p->mp_fld_rx_avail_monitor_control_cnt, 1);
+ register_flush(p->mp_reg_rx_avail_monitor_control, 1);
+}
+
+static void
+set_shadow_rx_am_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_rx_am_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void nthw_dbs_set_shadow_rx_am_data_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t enable)
+{
+ p->m_rx_am_shadow[index].enable = enable;
+}
+
+static void set_shadow_rx_am_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_rx_am_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_rx_am_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_rx_am_shadow[index].packed = packed;
+}
+
+static void set_shadow_rx_am_data_int_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t int_enable)
+{
+ p->m_rx_am_shadow[index].int_enable = int_enable;
+}
+
+static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ set_shadow_rx_am_data_guest_physical_address(p, index, guest_physical_address);
+ nthw_dbs_set_shadow_rx_am_data_enable(p, index, enable);
+ set_shadow_rx_am_data_host_id(p, index, host_id);
+ set_shadow_rx_am_data_packed(p, index, packed);
+ set_shadow_rx_am_data_int_enable(p, index, int_enable);
+}
+
+static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_rx_avail_monitor_data_guest_physical_address,
+ (uint32_t *)&p->m_rx_am_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_enable,
+ p->m_rx_am_shadow[index].enable);
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_host_id,
+ p->m_rx_am_shadow[index].host_id);
+ if (p->mp_fld_rx_avail_monitor_data_packed) {
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_packed,
+ p->m_rx_am_shadow[index].packed);
+ }
+ if (p->mp_fld_rx_avail_monitor_data_int) {
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_int,
+ p->m_rx_am_shadow[index].int_enable);
+ }
+
+ set_rx_am_data_index(p, index);
+ register_flush(p->mp_reg_rx_avail_monitor_data, 1);
+}
+
+int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ if (!p->mp_reg_rx_avail_monitor_data)
+ return -ENOTSUP;
+
+ set_shadow_rx_am_data(p, index, guest_physical_address, enable, host_id,
+ packed, int_enable);
+ flush_rx_am_data(p, index);
+ return 0;
+}
+
+static void set_tx_am_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_avail_monitor_control_adr, index);
+ field_set_val32(p->mp_fld_tx_avail_monitor_control_cnt, 1);
+ register_flush(p->mp_reg_tx_avail_monitor_control, 1);
+}
+
+static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ p->m_tx_am_shadow[index].guest_physical_address = guest_physical_address;
+ p->m_tx_am_shadow[index].enable = enable;
+ p->m_tx_am_shadow[index].host_id = host_id;
+ p->m_tx_am_shadow[index].packed = packed;
+ p->m_tx_am_shadow[index].int_enable = int_enable;
+}
+
+static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_tx_avail_monitor_data_guest_physical_address,
+ (uint32_t *)&p->m_tx_am_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_enable,
+ p->m_tx_am_shadow[index].enable);
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_host_id,
+ p->m_tx_am_shadow[index].host_id);
+ if (p->mp_fld_tx_avail_monitor_data_packed) {
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_packed,
+ p->m_tx_am_shadow[index].packed);
+ }
+ if (p->mp_fld_tx_avail_monitor_data_int) {
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_int,
+ p->m_tx_am_shadow[index].int_enable);
+ }
+
+ set_tx_am_data_index(p, index);
+ register_flush(p->mp_reg_tx_avail_monitor_data, 1);
+}
+
+int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ if (!p->mp_reg_tx_avail_monitor_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_am_data(p, index, guest_physical_address, enable, host_id,
+ packed, int_enable);
+ flush_tx_am_data(p, index);
+ return 0;
+}
+
+static void set_rx_uw_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_rx_used_writer_control_adr, index);
+ field_set_val32(p->mp_fld_rx_used_writer_control_cnt, 1);
+ register_flush(p->mp_reg_rx_used_writer_control, 1);
+}
+
+static void
+set_shadow_rx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_rx_uw_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_rx_uw_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_rx_uw_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_rx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_rx_uw_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_rx_uw_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_rx_uw_shadow[index].packed = packed;
+}
+
+static void set_shadow_rx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t int_enable)
+{
+ p->m_rx_uw_shadow[index].int_enable = int_enable;
+}
+
+static void set_shadow_rx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec)
+{
+ p->m_rx_uw_shadow[index].vec = vec;
+}
+
+static void set_shadow_rx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk)
+{
+ p->m_rx_uw_shadow[index].istk = istk;
+}
+
+static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk)
+{
+ set_shadow_rx_uw_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_rx_uw_data_host_id(p, index, host_id);
+ set_shadow_rx_uw_data_queue_size(p, index, queue_size);
+ set_shadow_rx_uw_data_packed(p, index, packed);
+ set_shadow_rx_uw_data_int_enable(p, index, int_enable);
+ set_shadow_rx_uw_data_vec(p, index, vec);
+ set_shadow_rx_uw_data_istk(p, index, istk);
+}
+
+static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_rx_used_writer_data_guest_physical_address,
+ (uint32_t *)&p->m_rx_uw_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_rx_used_writer_data_host_id,
+ p->m_rx_uw_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_rx_used_writer_data_queue_size,
+ (1U << p->m_rx_uw_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_rx_used_writer_data_queue_size,
+ p->m_rx_uw_shadow[index].queue_size);
+ }
+ if (p->mp_fld_rx_used_writer_data_packed) {
+ field_set_val32(p->mp_fld_rx_used_writer_data_packed,
+ p->m_rx_uw_shadow[index].packed);
+ }
+ if (p->mp_fld_rx_used_writer_data_int) {
+ field_set_val32(p->mp_fld_rx_used_writer_data_int,
+ p->m_rx_uw_shadow[index].int_enable);
+ field_set_val32(p->mp_fld_rx_used_writer_data_vec,
+ p->m_rx_uw_shadow[index].vec);
+ field_set_val32(p->mp_fld_rx_used_writer_data_istk,
+ p->m_rx_uw_shadow[index].istk);
+ }
+
+ set_rx_uw_data_index(p, index);
+ register_flush(p->mp_reg_rx_used_writer_data, 1);
+}
+
+int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk)
+{
+ if (!p->mp_reg_rx_used_writer_data)
+ return -ENOTSUP;
+
+ set_shadow_rx_uw_data(p, index, guest_physical_address, host_id, queue_size,
+ packed, int_enable, vec, istk);
+ flush_rx_uw_data(p, index);
+ return 0;
+}
+
+static void set_tx_uw_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_used_writer_control_adr, index);
+ field_set_val32(p->mp_fld_tx_used_writer_control_cnt, 1);
+ register_flush(p->mp_reg_tx_used_writer_control, 1);
+}
+
+static void
+set_shadow_tx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_tx_uw_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_tx_uw_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_tx_uw_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_tx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_tx_uw_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_tx_uw_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_tx_uw_shadow[index].packed = packed;
+}
+
+static void set_shadow_tx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t int_enable)
+{
+ p->m_tx_uw_shadow[index].int_enable = int_enable;
+}
+
+static void set_shadow_tx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec)
+{
+ p->m_tx_uw_shadow[index].vec = vec;
+}
+
+static void set_shadow_tx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk)
+{
+ p->m_tx_uw_shadow[index].istk = istk;
+}
+
+static void set_shadow_tx_uw_data_in_order(nthw_dbs_t *p, uint32_t index,
+ uint32_t in_order)
+{
+ p->m_tx_uw_shadow[index].in_order = in_order;
+}
+
+static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order)
+{
+ set_shadow_tx_uw_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_tx_uw_data_host_id(p, index, host_id);
+ set_shadow_tx_uw_data_queue_size(p, index, queue_size);
+ set_shadow_tx_uw_data_packed(p, index, packed);
+ set_shadow_tx_uw_data_int_enable(p, index, int_enable);
+ set_shadow_tx_uw_data_vec(p, index, vec);
+ set_shadow_tx_uw_data_istk(p, index, istk);
+ set_shadow_tx_uw_data_in_order(p, index, in_order);
+}
+
+static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_tx_used_writer_data_guest_physical_address,
+ (uint32_t *)&p->m_tx_uw_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_tx_used_writer_data_host_id,
+ p->m_tx_uw_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_queue_size,
+ (1U << p->m_tx_uw_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_tx_used_writer_data_queue_size,
+ p->m_tx_uw_shadow[index].queue_size);
+ }
+ if (p->mp_fld_tx_used_writer_data_packed) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_packed,
+ p->m_tx_uw_shadow[index].packed);
+ }
+ if (p->mp_fld_tx_used_writer_data_int) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_int,
+ p->m_tx_uw_shadow[index].int_enable);
+ field_set_val32(p->mp_fld_tx_used_writer_data_vec,
+ p->m_tx_uw_shadow[index].vec);
+ field_set_val32(p->mp_fld_tx_used_writer_data_istk,
+ p->m_tx_uw_shadow[index].istk);
+ }
+ if (p->mp_fld_tx_used_writer_data_in_order) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_in_order,
+ p->m_tx_uw_shadow[index].in_order);
+ }
+
+ set_tx_uw_data_index(p, index);
+ register_flush(p->mp_reg_tx_used_writer_data, 1);
+}
+
+int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order)
+{
+ if (!p->mp_reg_tx_used_writer_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_uw_data(p, index, guest_physical_address, host_id, queue_size,
+ packed, int_enable, vec, istk, in_order);
+ flush_tx_uw_data(p, index);
+ return 0;
+}
+
+static void set_rx_dr_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_rx_descriptor_reader_control_adr, index);
+ field_set_val32(p->mp_fld_rx_descriptor_reader_control_cnt, 1);
+ register_flush(p->mp_reg_rx_descriptor_reader_control, 1);
+}
+
+static void
+set_shadow_rx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_rx_dr_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_rx_dr_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_rx_dr_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_rx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_rx_dr_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_rx_dr_data_header(nthw_dbs_t *p, uint32_t index,
+ uint32_t header)
+{
+ p->m_rx_dr_shadow[index].header = header;
+}
+
+static void set_shadow_rx_dr_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_rx_dr_shadow[index].packed = packed;
+}
+
+static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t header,
+ uint32_t packed)
+{
+ set_shadow_rx_dr_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_rx_dr_data_host_id(p, index, host_id);
+ set_shadow_rx_dr_data_queue_size(p, index, queue_size);
+ set_shadow_rx_dr_data_header(p, index, header);
+ set_shadow_rx_dr_data_packed(p, index, packed);
+}
+
+static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_rx_descriptor_reader_data_guest_physical_address,
+ (uint32_t *)&p->m_rx_dr_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_host_id,
+ p->m_rx_dr_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size,
+ (1U << p->m_rx_dr_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size,
+ p->m_rx_dr_shadow[index].queue_size);
+ }
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_header,
+ p->m_rx_dr_shadow[index].header);
+ if (p->mp_fld_rx_descriptor_reader_data_packed) {
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_packed,
+ p->m_rx_dr_shadow[index].packed);
+ }
+
+ set_rx_dr_data_index(p, index);
+ register_flush(p->mp_reg_rx_descriptor_reader_data, 1);
+}
+
+int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t header,
+ uint32_t packed)
+{
+ if (!p->mp_reg_rx_descriptor_reader_data)
+ return -ENOTSUP;
+
+ set_shadow_rx_dr_data(p, index, guest_physical_address, host_id, queue_size,
+ header, packed);
+ flush_rx_dr_data(p, index);
+ return 0;
+}
+
+static void set_tx_dr_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_descriptor_reader_control_adr, index);
+ field_set_val32(p->mp_fld_tx_descriptor_reader_control_cnt, 1);
+ register_flush(p->mp_reg_tx_descriptor_reader_control, 1);
+}
+
+static void
+set_shadow_tx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_tx_dr_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_tx_dr_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_tx_dr_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_tx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_tx_dr_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_tx_dr_data_header(nthw_dbs_t *p, uint32_t index,
+ uint32_t header)
+{
+ p->m_tx_dr_shadow[index].header = header;
+}
+
+static void set_shadow_tx_dr_data_port(nthw_dbs_t *p, uint32_t index, uint32_t port)
+{
+ p->m_tx_dr_shadow[index].port = port;
+}
+
+static void set_shadow_tx_dr_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_tx_dr_shadow[index].packed = packed;
+}
+
+static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed)
+{
+ set_shadow_tx_dr_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_tx_dr_data_host_id(p, index, host_id);
+ set_shadow_tx_dr_data_queue_size(p, index, queue_size);
+ set_shadow_tx_dr_data_header(p, index, header);
+ set_shadow_tx_dr_data_port(p, index, port);
+ set_shadow_tx_dr_data_packed(p, index, packed);
+}
+
+static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_tx_descriptor_reader_data_guest_physical_address,
+ (uint32_t *)&p->m_tx_dr_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_host_id,
+ p->m_tx_dr_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size,
+ (1U << p->m_tx_dr_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size,
+ p->m_tx_dr_shadow[index].queue_size);
+ }
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_header,
+ p->m_tx_dr_shadow[index].header);
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_port,
+ p->m_tx_dr_shadow[index].port);
+ if (p->mp_fld_tx_descriptor_reader_data_packed) {
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_packed,
+ p->m_tx_dr_shadow[index].packed);
+ }
+
+ set_tx_dr_data_index(p, index);
+ register_flush(p->mp_reg_tx_descriptor_reader_data, 1);
+}
+
+int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed)
+{
+ if (!p->mp_reg_tx_descriptor_reader_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_dr_data(p, index, guest_physical_address, host_id, queue_size,
+ port, header, packed);
+ flush_tx_dr_data(p, index);
+ return 0;
+}
+
+static void set_tx_qp_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_queue_property_control_adr, index);
+ field_set_val32(p->mp_fld_tx_queue_property_control_cnt, 1);
+ register_flush(p->mp_reg_tx_queue_property_control, 1);
+}
+
+static void set_shadow_tx_qp_data_virtual_port(nthw_dbs_t *p, uint32_t index,
+ uint32_t virtual_port)
+{
+ p->m_tx_qp_shadow[index].virtual_port = virtual_port;
+}
+
+static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index,
+ uint32_t virtual_port)
+{
+ set_shadow_tx_qp_data_virtual_port(p, index, virtual_port);
+}
+
+static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_queue_property_data_v_port,
+ p->m_tx_qp_shadow[index].virtual_port);
+
+ set_tx_qp_data_index(p, index);
+ register_flush(p->mp_reg_tx_queue_property_data, 1);
+}
+
+int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port)
+{
+ if (!p->mp_reg_tx_queue_property_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_qp_data(p, index, virtual_port);
+ flush_tx_qp_data(p, index);
+ return 0;
+}
+
+static void set_tx_qos_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_reg_tx_queue_qos_control_adr, index);
+ field_set_val32(p->mp_reg_tx_queue_qos_control_cnt, 1);
+ register_flush(p->mp_reg_tx_queue_qos_control, 1);
+}
+
+static void set_shadow_tx_qos_data_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t enable)
+{
+ p->m_tx_qos_shadow[index].enable = enable;
+}
+
+static void set_shadow_tx_qos_data_ir(nthw_dbs_t *p, uint32_t index, uint32_t ir)
+{
+ p->m_tx_qos_shadow[index].ir = ir;
+}
+
+static void set_shadow_tx_qos_data_bs(nthw_dbs_t *p, uint32_t index, uint32_t bs)
+{
+ p->m_tx_qos_shadow[index].bs = bs;
+}
+
+static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable,
+ uint32_t ir, uint32_t bs)
+{
+ set_shadow_tx_qos_data_enable(p, index, enable);
+ set_shadow_tx_qos_data_ir(p, index, ir);
+ set_shadow_tx_qos_data_bs(p, index, bs);
+}
+
+static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_reg_tx_queue_qos_data_en, p->m_tx_qos_shadow[index].enable);
+ field_set_val32(p->mp_reg_tx_queue_qos_data_ir, p->m_tx_qos_shadow[index].ir);
+ field_set_val32(p->mp_reg_tx_queue_qos_data_bs, p->m_tx_qos_shadow[index].bs);
+
+ set_tx_qos_data_index(p, index);
+ register_flush(p->mp_reg_tx_queue_qos_data, 1);
+}
+
+int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir,
+ uint32_t bs)
+{
+ if (!p->mp_reg_tx_queue_qos_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_qos_data(p, index, enable, ir, bs);
+ flush_tx_qos_data(p, index);
+ return 0;
+}
+
+int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div)
+{
+ if (!p->mp_reg_tx_queue_qos_rate)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_reg_tx_queue_qos_rate_mul, mul);
+ field_set_val32(p->mp_reg_tx_queue_qos_rate_div, div);
+ register_flush(p->mp_reg_tx_queue_qos_rate, 1);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_dbs.h b/drivers/net/ntnic/nthw/nthw_dbs.h
new file mode 100644
index 0000000000..d5891d7538
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_dbs.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_DBS_HPP_
+#define NTHW_DBS_HPP_
+
+#define NT_DBS_RX_QUEUES_MAX (128)
+#define NT_DBS_TX_QUEUES_MAX (128)
+
+/*
+ * Struct for implementation of memory bank shadows
+ */
+
+/* DBS_RX_AM_DATA */
+struct nthw_dbs_rx_am_data_s {
+ uint64_t guest_physical_address;
+ uint32_t enable;
+ uint32_t host_id;
+ uint32_t packed;
+ uint32_t int_enable;
+};
+
+/* DBS_TX_AM_DATA */
+struct nthw_dbs_tx_am_data_s {
+ uint64_t guest_physical_address;
+ uint32_t enable;
+ uint32_t host_id;
+ uint32_t packed;
+ uint32_t int_enable;
+};
+
+/* DBS_RX_UW_DATA */
+struct nthw_dbs_rx_uw_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t packed;
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+};
+
+/* DBS_TX_UW_DATA */
+struct nthw_dbs_tx_uw_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t packed;
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+ uint32_t in_order;
+};
+
+/* DBS_RX_DR_DATA */
+struct nthw_dbs_rx_dr_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t header;
+ uint32_t packed;
+};
+
+/* DBS_TX_DR_DATA */
+struct nthw_dbs_tx_dr_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t header;
+ uint32_t port;
+ uint32_t packed;
+};
+
+/* DBS_TX_QP_DATA */
+struct nthw_dbs_tx_qp_data_s {
+ uint32_t virtual_port;
+};
+
+struct nthw_dbs_tx_qos_data_s {
+ uint32_t enable;
+ uint32_t ir;
+ uint32_t bs;
+};
+
+struct nthw_dbs_s {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_dbs;
+ int mn_instance;
+
+ int mn_param_dbs_present;
+
+ nt_register_t *mp_reg_rx_control;
+ nt_field_t *mp_fld_rx_control_last_queue;
+ nt_field_t *mp_fld_rx_control_avail_monitor_enable;
+ nt_field_t *mp_fld_rx_control_avail_monitor_scan_speed;
+ nt_field_t *mp_fld_rx_control_used_write_enable;
+ nt_field_t *mp_fld_rx_control_used_writer_update_speed;
+ nt_field_t *mp_fld_rx_control_rx_queues_enable;
+
+ nt_register_t *mp_reg_tx_control;
+ nt_field_t *mp_fld_tx_control_last_queue;
+ nt_field_t *mp_fld_tx_control_avail_monitor_enable;
+ nt_field_t *mp_fld_tx_control_avail_monitor_scan_speed;
+ nt_field_t *mp_fld_tx_control_used_write_enable;
+ nt_field_t *mp_fld_tx_control_used_writer_update_speed;
+ nt_field_t *mp_fld_tx_control_tx_queues_enable;
+
+ nt_register_t *mp_reg_rx_init;
+ nt_field_t *mp_fld_rx_init_init;
+ nt_field_t *mp_fld_rx_init_queue;
+ nt_field_t *mp_fld_rx_init_busy;
+
+ nt_register_t *mp_reg_rx_init_val;
+ nt_field_t *mp_fld_rx_init_val_idx;
+ nt_field_t *mp_fld_rx_init_val_ptr;
+
+ nt_register_t *mp_reg_rx_ptr;
+ nt_field_t *mp_fld_rx_ptr_ptr;
+ nt_field_t *mp_fld_rx_ptr_queue;
+ nt_field_t *mp_fld_rx_ptr_valid;
+
+ nt_register_t *mp_reg_tx_init;
+ nt_field_t *mp_fld_tx_init_init;
+ nt_field_t *mp_fld_tx_init_queue;
+ nt_field_t *mp_fld_tx_init_busy;
+
+ nt_register_t *mp_reg_tx_init_val;
+ nt_field_t *mp_fld_tx_init_val_idx;
+ nt_field_t *mp_fld_tx_init_val_ptr;
+
+ nt_register_t *mp_reg_tx_ptr;
+ nt_field_t *mp_fld_tx_ptr_ptr;
+ nt_field_t *mp_fld_tx_ptr_queue;
+ nt_field_t *mp_fld_tx_ptr_valid;
+
+ nt_register_t *mp_reg_rx_idle;
+ nt_field_t *mp_fld_rx_idle_idle;
+ nt_field_t *mp_fld_rx_idle_queue;
+ nt_field_t *mp_fld_rx_idle_busy;
+
+ nt_register_t *mp_reg_tx_idle;
+ nt_field_t *mp_fld_tx_idle_idle;
+ nt_field_t *mp_fld_tx_idle_queue;
+ nt_field_t *mp_fld_tx_idle_busy;
+
+ nt_register_t *mp_reg_rx_avail_monitor_control;
+ nt_field_t *mp_fld_rx_avail_monitor_control_adr;
+ nt_field_t *mp_fld_rx_avail_monitor_control_cnt;
+
+ nt_register_t *mp_reg_rx_avail_monitor_data;
+ nt_field_t *mp_fld_rx_avail_monitor_data_guest_physical_address;
+ nt_field_t *mp_fld_rx_avail_monitor_data_enable;
+ nt_field_t *mp_fld_rx_avail_monitor_data_host_id;
+ nt_field_t *mp_fld_rx_avail_monitor_data_packed;
+ nt_field_t *mp_fld_rx_avail_monitor_data_int;
+
+ nt_register_t *mp_reg_tx_avail_monitor_control;
+ nt_field_t *mp_fld_tx_avail_monitor_control_adr;
+ nt_field_t *mp_fld_tx_avail_monitor_control_cnt;
+
+ nt_register_t *mp_reg_tx_avail_monitor_data;
+ nt_field_t *mp_fld_tx_avail_monitor_data_guest_physical_address;
+ nt_field_t *mp_fld_tx_avail_monitor_data_enable;
+ nt_field_t *mp_fld_tx_avail_monitor_data_host_id;
+ nt_field_t *mp_fld_tx_avail_monitor_data_packed;
+ nt_field_t *mp_fld_tx_avail_monitor_data_int;
+
+ nt_register_t *mp_reg_rx_used_writer_control;
+ nt_field_t *mp_fld_rx_used_writer_control_adr;
+ nt_field_t *mp_fld_rx_used_writer_control_cnt;
+
+ nt_register_t *mp_reg_rx_used_writer_data;
+ nt_field_t *mp_fld_rx_used_writer_data_guest_physical_address;
+ nt_field_t *mp_fld_rx_used_writer_data_host_id;
+ nt_field_t *mp_fld_rx_used_writer_data_queue_size;
+ nt_field_t *mp_fld_rx_used_writer_data_packed;
+ nt_field_t *mp_fld_rx_used_writer_data_int;
+ nt_field_t *mp_fld_rx_used_writer_data_vec;
+ nt_field_t *mp_fld_rx_used_writer_data_istk;
+
+ nt_register_t *mp_reg_tx_used_writer_control;
+ nt_field_t *mp_fld_tx_used_writer_control_adr;
+ nt_field_t *mp_fld_tx_used_writer_control_cnt;
+
+ nt_register_t *mp_reg_tx_used_writer_data;
+ nt_field_t *mp_fld_tx_used_writer_data_guest_physical_address;
+ nt_field_t *mp_fld_tx_used_writer_data_host_id;
+ nt_field_t *mp_fld_tx_used_writer_data_queue_size;
+ nt_field_t *mp_fld_tx_used_writer_data_packed;
+ nt_field_t *mp_fld_tx_used_writer_data_int;
+ nt_field_t *mp_fld_tx_used_writer_data_vec;
+ nt_field_t *mp_fld_tx_used_writer_data_istk;
+ nt_field_t *mp_fld_tx_used_writer_data_in_order;
+
+ nt_register_t *mp_reg_rx_descriptor_reader_control;
+ nt_field_t *mp_fld_rx_descriptor_reader_control_adr;
+ nt_field_t *mp_fld_rx_descriptor_reader_control_cnt;
+
+ nt_register_t *mp_reg_rx_descriptor_reader_data;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_guest_physical_address;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_host_id;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_queue_size;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_header;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_packed;
+
+ nt_register_t *mp_reg_tx_descriptor_reader_control;
+ nt_field_t *mp_fld_tx_descriptor_reader_control_adr;
+ nt_field_t *mp_fld_tx_descriptor_reader_control_cnt;
+
+ nt_register_t *mp_reg_tx_descriptor_reader_data;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_guest_physical_address;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_host_id;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_queue_size;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_port;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_header;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_packed;
+
+ nt_register_t *mp_reg_tx_queue_property_control;
+ nt_field_t *mp_fld_tx_queue_property_control_adr;
+ nt_field_t *mp_fld_tx_queue_property_control_cnt;
+
+ nt_register_t *mp_reg_tx_queue_property_data;
+ nt_field_t *mp_fld_tx_queue_property_data_v_port;
+
+ nt_register_t *mp_reg_tx_queue_qos_control;
+ nt_field_t *mp_reg_tx_queue_qos_control_adr;
+ nt_field_t *mp_reg_tx_queue_qos_control_cnt;
+
+ nt_register_t *mp_reg_tx_queue_qos_data;
+ nt_field_t *mp_reg_tx_queue_qos_data_en;
+ nt_field_t *mp_reg_tx_queue_qos_data_ir;
+ nt_field_t *mp_reg_tx_queue_qos_data_bs;
+
+ nt_register_t *mp_reg_tx_queue_qos_rate;
+ nt_field_t *mp_reg_tx_queue_qos_rate_mul;
+ nt_field_t *mp_reg_tx_queue_qos_rate_div;
+
+ struct nthw_dbs_rx_am_data_s m_rx_am_shadow[NT_DBS_RX_QUEUES_MAX];
+ struct nthw_dbs_rx_uw_data_s m_rx_uw_shadow[NT_DBS_RX_QUEUES_MAX];
+ struct nthw_dbs_rx_dr_data_s m_rx_dr_shadow[NT_DBS_RX_QUEUES_MAX];
+
+ struct nthw_dbs_tx_am_data_s m_tx_am_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_uw_data_s m_tx_uw_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_dr_data_s m_tx_dr_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_qp_data_s m_tx_qp_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_qos_data_s m_tx_qos_shadow[NT_DBS_TX_QUEUES_MAX];
+};
+
+typedef struct nthw_dbs_s nthw_dbs_t;
+
+nthw_dbs_t *nthw_dbs_new(void);
+void nthw_dbs_delete(nthw_dbs_t *p);
+int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance);
+void dbs_reset(nthw_dbs_t *p);
+
+int dbs_reset_rx_control(nthw_dbs_t *p);
+int dbs_reset_tx_control(nthw_dbs_t *p);
+int set_rx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t rx_queue_enable);
+int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *rx_queue_enable);
+int set_tx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t tx_queue_enable);
+int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *tx_queue_enable);
+int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue);
+int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy);
+int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue);
+int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy);
+int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue);
+int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy);
+int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue);
+int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy);
+int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue);
+int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid);
+int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue);
+int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid);
+int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk);
+int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order);
+int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t header,
+ uint32_t packed);
+int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed);
+int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port);
+int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir,
+ uint32_t bs);
+int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div);
+
+#endif /* NTHW_DBS_H_ */
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
new file mode 100644
index 0000000000..7fdd9bf0e2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_DRV_H__
+#define __NTHW_DRV_H__
+
+#include "nthw_profile.h"
+
+typedef enum nt_meta_port_type_e {
+ PORT_TYPE_PHYSICAL,
+ PORT_TYPE_VIRTUAL,
+ PORT_TYPE_OVERRIDE,
+} nt_meta_port_type_t;
+
+#include "nthw_helper.h"
+#include "nthw_platform_drv.h"
+#include "nthw_fpga_model.h"
+#include "nthw_stat.h"
+#include "nthw_dbs.h"
+#include "nthw_epp.h"
+#include "nthw_core.h"
+
+typedef struct nthwhw_info_s {
+ /* From FW */
+ int hw_id;
+ int hw_id_emulated;
+ char hw_plat_id_str[32];
+
+ struct vpd_info_s {
+ int mn_mac_addr_count;
+ uint64_t mn_mac_addr_value;
+ uint8_t ma_mac_addr_octets[6];
+ } vpd_info;
+} nthw_hw_info_t;
+
+typedef struct fpga_info_s {
+ uint64_t n_fpga_ident;
+
+ int n_fpga_type_id;
+ int n_fpga_prod_id;
+ int n_fpga_ver_id;
+ int n_fpga_rev_id;
+
+ int n_fpga_build_time;
+
+ int n_fpga_debug_mode;
+
+ int n_nims;
+ int n_phy_ports;
+ int n_phy_quads;
+ int n_rx_ports;
+ int n_tx_ports;
+
+ enum fpga_info_profile profile;
+
+ struct nt_fpga_s *mp_fpga;
+
+ struct nthw_rac *mp_nthw_rac;
+ struct nthw_hif *mp_nthw_hif;
+ struct nthw_pcie3 *mp_nthw_pcie3;
+ struct nthw_tsm *mp_nthw_tsm;
+
+ nthw_dbs_t *mp_nthw_dbs;
+ nthw_epp_t *mp_nthw_epp;
+
+ uint8_t *bar0_addr; /* Needed for register read/write */
+ size_t bar0_size;
+
+ int adapter_no; /* Needed for nthw_rac DMA array indexing */
+ uint32_t pciident; /* Needed for nthw_rac DMA memzone_reserve */
+ int numa_node; /* Needed for nthw_rac DMA memzone_reserve */
+
+ char *mp_adapter_id_str; /* Pointer to string literal used in nthw log messages */
+
+ struct nthwhw_info_s nthw_hw_info;
+
+ nthw_adapter_id_t n_nthw_adapter_id;
+
+} fpga_info_t;
+
+#endif /* __NTHW_DRV_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_epp.c b/drivers/net/ntnic/nthw/nthw_epp.c
new file mode 100644
index 0000000000..fbe3993b25
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_epp.c
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_epp.h"
+
+#include <errno.h> /* ENOTSUP */
+
+nthw_epp_t *nthw_epp_new(void)
+{
+ nthw_epp_t *p = malloc(sizeof(nthw_epp_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_epp_t));
+ return p;
+}
+
+void nthw_epp_delete(nthw_epp_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_epp_t));
+ free(p);
+ }
+}
+
+int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance)
+{
+ return nthw_epp_init(NULL, p_fpga, n_instance) == 0;
+}
+
+int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_EPP, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: EPP %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_epp = mod;
+
+ p->mn_epp_categories = fpga_get_product_param(p_fpga, NT_EPP_CATEGORIES, 0);
+
+ p->mp_reg_reciepe_memory_control =
+ module_get_register(p->mp_mod_epp, EPP_RCP_CTRL);
+ p->mp_fld_reciepe_memory_control_adr =
+ register_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_ADR);
+ p->mp_fld_reciepe_memory_control_cnt =
+ register_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_CNT);
+
+ p->mp_reg_reciepe_memory_data =
+ module_get_register(p->mp_mod_epp, EPP_RCP_DATA);
+ p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_MTU_EPP_EN);
+ p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_MTU_EPP_EN);
+ p->mp_fld_reciepe_memory_data_size_adjust_tx_port =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_TXP);
+ p->mp_fld_reciepe_memory_data_size_adjust_virtual_port =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_VPORT);
+ p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_FIXED_18B_L2_MTU);
+ p->mp_fld_reciepe_memory_data_txp_qos_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_QOS_EPP_EN);
+ p->mp_fld_reciepe_memory_data_queue_qos_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_QOS_EPP_EN);
+
+ p->mp_reg_txp_port_mtu_control =
+ module_get_register(p->mp_mod_epp, EPP_TXP_MTU_CTRL);
+ p->mp_fld_txp_port_mtu_control_adr =
+ register_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_ADR);
+ p->mp_fld_txp_port_mtu_control_cnt =
+ register_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_CNT);
+
+ p->mp_reg_txp_port_mtu_data =
+ module_get_register(p->mp_mod_epp, EPP_TXP_MTU_DATA);
+ p->mp_fld_txp_port_mtu_data_max_mtu =
+ register_get_field(p->mp_reg_txp_port_mtu_data, EPP_TXP_MTU_DATA_MAX_MTU);
+
+ p->mp_reg_queue_mtu_control =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_CTRL);
+ p->mp_fld_queue_mtu_control_adr =
+ register_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_ADR);
+ p->mp_fld_queue_mtu_control_cnt =
+ register_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_CNT);
+
+ p->mp_reg_queue_mtu_data =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_DATA);
+ p->mp_fld_queue_mtu_data_max_mtu =
+ register_get_field(p->mp_reg_queue_mtu_data, EPP_QUEUE_MTU_DATA_MAX_MTU);
+
+ p->mp_reg_txp_qos_control =
+ module_get_register(p->mp_mod_epp, EPP_TXP_QOS_CTRL);
+ p->mp_fld_txp_qos_control_adr =
+ register_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_ADR);
+ p->mp_fld_txp_qos_control_cnt =
+ register_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_CNT);
+
+ p->mp_reg_txp_qos_data = module_get_register(p->mp_mod_epp, EPP_TXP_QOS_DATA);
+ p->mp_fld_txp_qos_data_enable =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_EN);
+ p->mp_fld_txp_qos_data_information_rate =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR);
+ p->mp_fld_txp_qos_data_information_rate_fractional =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR_FRACTION);
+ p->mp_fld_txp_qos_data_burst_size =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_BS);
+
+ p->mp_reg_vport_qos_control =
+ module_get_register(p->mp_mod_epp, EPP_VPORT_QOS_CTRL);
+ p->mp_fld_vport_qos_control_adr =
+ register_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_ADR);
+ p->mp_fld_vport_qos_control_cnt =
+ register_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_CNT);
+
+ p->mp_reg_vport_qos_data =
+ module_get_register(p->mp_mod_epp, EPP_VPORT_QOS_DATA);
+ p->mp_fld_vport_qos_data_enable =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_EN);
+ p->mp_fld_vport_qos_data_information_rate =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR);
+ p->mp_fld_vport_qos_data_information_rate_fractional =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR_FRACTION);
+ p->mp_fld_vport_qos_data_burst_size =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_BS);
+
+ p->mp_reg_queue_vport_control =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_CTRL);
+ p->mp_fld_queue_vport_control_adr =
+ register_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_ADR);
+ p->mp_fld_queue_vport_control_cnt =
+ register_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_CNT);
+
+ p->mp_reg_queue_vport_data =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_DATA);
+ p->mp_fld_queue_vport_data_vport =
+ register_get_field(p->mp_reg_queue_vport_data, EPP_QUEUE_VPORT_DATA_VPORT);
+
+ return 0;
+}
+
+int nthw_epp_setup(nthw_epp_t *p)
+{
+ if (p == NULL)
+ return 0;
+
+ /* Set recieps for 2 first records */
+ field_set_val32(p->mp_fld_reciepe_memory_control_cnt, 1);
+
+ /* Zero all categories */
+ for (int i = 0; i < p->mn_epp_categories; ++i) {
+ field_set_val32(p->mp_fld_reciepe_memory_control_adr, i);
+ register_flush(p->mp_reg_reciepe_memory_control, 1);
+
+ field_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port,
+ 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 0);
+ register_flush(p->mp_reg_reciepe_memory_data, 1);
+ }
+
+ for (int i = 0; i < NRECIPE; ++i) {
+ field_set_val32(p->mp_fld_reciepe_memory_control_adr, i);
+ register_flush(p->mp_reg_reciepe_memory_control, 1);
+
+ field_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port,
+ rcp_data_size_adjust_txp[i]);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port,
+ rcp_data_size_adjust_vport[i]);
+ field_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 1);
+ register_flush(p->mp_reg_reciepe_memory_data, 1);
+ }
+ /* phy mtu setup */
+ field_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1);
+ for (int i = 0; i < 2; ++i) {
+ field_set_val32(p->mp_fld_txp_port_mtu_control_adr, i);
+ register_flush(p->mp_reg_txp_port_mtu_control, 1);
+
+ field_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, MTUINITVAL);
+ register_flush(p->mp_reg_txp_port_mtu_data, 1);
+ }
+ /* phy QoS setup */
+ field_set_val32(p->mp_fld_txp_qos_control_cnt, 1);
+ for (int i = 0; i < 2; ++i) {
+ field_set_val32(p->mp_fld_txp_qos_control_adr, i);
+ register_flush(p->mp_reg_txp_qos_control, 1);
+
+ field_set_val32(p->mp_fld_txp_qos_data_enable, 0);
+ register_flush(p->mp_reg_txp_qos_data, 1);
+ }
+
+ /* virt mtu setup */
+ field_set_val32(p->mp_fld_queue_mtu_control_cnt, 1);
+ for (int i = 0; i < 128; ++i) {
+ field_set_val32(p->mp_fld_queue_mtu_control_adr, i);
+ register_flush(p->mp_reg_queue_mtu_control, 1);
+
+ field_set_val32(p->mp_fld_queue_mtu_data_max_mtu, MTUINITVAL);
+ register_flush(p->mp_reg_queue_mtu_data, 1);
+ }
+
+ /* virt QoS setup */
+ field_set_val32(p->mp_fld_vport_qos_control_cnt, 1);
+ for (int i = 0; i < 128; ++i) {
+ field_set_val32(p->mp_fld_vport_qos_control_adr, i);
+ register_flush(p->mp_reg_vport_qos_control, 1);
+
+ field_set_val32(p->mp_fld_vport_qos_data_enable, 0);
+ register_flush(p->mp_reg_vport_qos_data, 1);
+ }
+
+ return 0;
+}
+
+/*
+ * Set the MTU registers in context with the current setMTU request.
+ */
+int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu,
+ nt_meta_port_type_t port_type)
+{
+ if (p == NULL)
+ return 0;
+
+ if (port_type == PORT_TYPE_PHYSICAL) {
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_txp_port_mtu_control_adr, port);
+ field_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1);
+ register_flush(p->mp_reg_txp_port_mtu_control, 1);
+
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, max_mtu);
+ register_flush(p->mp_reg_txp_port_mtu_data, 1);
+ } else if (port_type == PORT_TYPE_VIRTUAL) {
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_queue_mtu_control_adr, port);
+ field_set_val32(p->mp_fld_queue_mtu_control_cnt, 1);
+ register_flush(p->mp_reg_queue_mtu_control, 1);
+
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_queue_mtu_data_max_mtu, max_mtu);
+ register_flush(p->mp_reg_queue_mtu_data, 1);
+ } else {
+ NT_LOG(DBG, NTHW, "NthwEpp::%s - port_type unsupported",
+ __func__);
+ register_reset(p->mp_reg_queue_mtu_control);
+ register_flush(p->mp_reg_queue_mtu_control, 1);
+ register_reset(p->mp_reg_queue_mtu_data);
+ register_flush(p->mp_reg_queue_mtu_data, 1);
+ register_reset(p->mp_reg_txp_port_mtu_control);
+ register_flush(p->mp_reg_txp_port_mtu_control, 1);
+ register_reset(p->mp_reg_txp_port_mtu_data);
+ register_flush(p->mp_reg_txp_port_mtu_data, 1);
+
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size)
+{
+ if (p == NULL)
+ return 0;
+
+ field_set_val32(p->mp_fld_txp_qos_control_adr, port);
+ field_set_val32(p->mp_fld_txp_qos_control_cnt, 1);
+ register_flush(p->mp_reg_txp_qos_control, 1);
+
+ uint32_t enable = ((information_rate | information_rate_fractional |
+ burst_size) != 0);
+ field_set_val32(p->mp_fld_txp_qos_data_enable, enable);
+ field_set_val32(p->mp_fld_txp_qos_data_information_rate, information_rate);
+ field_set_val32(p->mp_fld_txp_qos_data_information_rate_fractional,
+ information_rate_fractional);
+ field_set_val32(p->mp_fld_txp_qos_data_burst_size, burst_size);
+ register_flush(p->mp_reg_txp_qos_data, 1);
+
+ return 0;
+}
+
+int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size)
+{
+ if (p == NULL)
+ return 0;
+
+ field_set_val32(p->mp_fld_vport_qos_control_adr, port);
+ field_set_val32(p->mp_fld_vport_qos_control_cnt, 1);
+ register_flush(p->mp_reg_vport_qos_control, 1);
+
+ uint32_t enable = ((information_rate | information_rate_fractional |
+ burst_size) != 0);
+ field_set_val32(p->mp_fld_vport_qos_data_enable, enable);
+ field_set_val32(p->mp_fld_vport_qos_data_information_rate, information_rate);
+ field_set_val32(p->mp_fld_vport_qos_data_information_rate_fractional,
+ information_rate_fractional);
+ field_set_val32(p->mp_fld_vport_qos_data_burst_size, burst_size);
+ register_flush(p->mp_reg_vport_qos_data, 1);
+
+ return 0;
+}
+
+int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport)
+{
+ if (p == NULL)
+ return 0;
+
+ field_set_val32(p->mp_fld_queue_vport_control_adr, qid);
+ field_set_val32(p->mp_fld_queue_vport_control_cnt, 1);
+ register_flush(p->mp_reg_queue_vport_control, 1);
+
+ field_set_val32(p->mp_fld_queue_vport_data_vport, vport);
+ register_flush(p->mp_reg_queue_vport_data, 1);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_epp.h b/drivers/net/ntnic/nthw/nthw_epp.h
new file mode 100644
index 0000000000..b404c9b61a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_epp.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_EPP_HPP_
+#define NTHW_EPP_HPP_
+
+/* VXLAN adds extra 50 bytes */
+#define VXLANDATASIZEADJUST 50
+#define VXLANDATASIZEADJUSTIPV6 70
+#define MTUINITVAL 1500
+#define NRECIPE 3
+
+/* List of size adjust values to put in the recipe memory data register at startup */
+static const int rcp_data_size_adjust_txp[NRECIPE] = { 0, VXLANDATASIZEADJUST,
+ VXLANDATASIZEADJUSTIPV6
+ };
+static const int rcp_data_size_adjust_vport[NRECIPE] = { 0, VXLANDATASIZEADJUST,
+ VXLANDATASIZEADJUSTIPV6
+ };
+
+struct nthw_epp_s {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_epp;
+ int mn_instance;
+ int mn_epp_categories;
+
+ nt_register_t *mp_reg_reciepe_memory_control;
+ nt_field_t *mp_fld_reciepe_memory_control_adr;
+ nt_field_t *mp_fld_reciepe_memory_control_cnt;
+
+ nt_register_t *mp_reg_reciepe_memory_data;
+ nt_field_t *mp_fld_reciepe_memory_data_tx_mtu_epp_enable;
+ nt_field_t *mp_fld_reciepe_memory_data_queue_mtu_epp_enable;
+ nt_field_t *mp_fld_reciepe_memory_data_size_adjust_tx_port;
+ nt_field_t *mp_fld_reciepe_memory_data_size_adjust_virtual_port;
+ nt_field_t *mp_fld_reciepe_memory_data_fixed18b_l2_mtu;
+ nt_field_t *mp_fld_reciepe_memory_data_txp_qos_epp_enable;
+ nt_field_t *mp_fld_reciepe_memory_data_queue_qos_epp_enable;
+
+ nt_register_t *mp_reg_txp_port_mtu_control;
+ nt_field_t *mp_fld_txp_port_mtu_control_adr;
+ nt_field_t *mp_fld_txp_port_mtu_control_cnt;
+
+ nt_register_t *mp_reg_txp_port_mtu_data;
+ nt_field_t *mp_fld_txp_port_mtu_data_max_mtu;
+
+ nt_register_t *mp_reg_queue_mtu_control;
+ nt_field_t *mp_fld_queue_mtu_control_adr;
+ nt_field_t *mp_fld_queue_mtu_control_cnt;
+
+ nt_register_t *mp_reg_queue_mtu_data;
+ nt_field_t *mp_fld_queue_mtu_data_max_mtu;
+
+ nt_register_t *mp_reg_txp_qos_control;
+ nt_field_t *mp_fld_txp_qos_control_adr;
+ nt_field_t *mp_fld_txp_qos_control_cnt;
+
+ nt_register_t *mp_reg_txp_qos_data;
+ nt_field_t *mp_fld_txp_qos_data_enable;
+ nt_field_t *mp_fld_txp_qos_data_information_rate;
+ nt_field_t *mp_fld_txp_qos_data_information_rate_fractional;
+ nt_field_t *mp_fld_txp_qos_data_burst_size;
+
+ nt_register_t *mp_reg_vport_qos_control;
+ nt_field_t *mp_fld_vport_qos_control_adr;
+ nt_field_t *mp_fld_vport_qos_control_cnt;
+
+ nt_register_t *mp_reg_vport_qos_data;
+ nt_field_t *mp_fld_vport_qos_data_enable;
+ nt_field_t *mp_fld_vport_qos_data_information_rate;
+ nt_field_t *mp_fld_vport_qos_data_information_rate_fractional;
+ nt_field_t *mp_fld_vport_qos_data_burst_size;
+
+ nt_register_t *mp_reg_queue_vport_control;
+ nt_field_t *mp_fld_queue_vport_control_adr;
+ nt_field_t *mp_fld_queue_vport_control_cnt;
+
+ nt_register_t *mp_reg_queue_vport_data;
+ nt_field_t *mp_fld_queue_vport_data_vport;
+};
+
+typedef struct nthw_epp_s nthw_epp_t;
+
+nthw_epp_t *nthw_epp_new(void);
+void nthw_epp_delete(nthw_epp_t *p);
+
+int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance);
+int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance);
+int nthw_epp_setup(nthw_epp_t *p);
+int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu,
+ nt_meta_port_type_t port_type);
+int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size);
+int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size);
+int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport);
+
+#endif /* NTHW_EPP_HPP_ */
diff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.c b/drivers/net/ntnic/nthw/nthw_fpga_model.c
new file mode 100644
index 0000000000..fca13e0f31
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_fpga_model.c
@@ -0,0 +1,1677 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <time.h> /* ctime */
+
+#include "nthw_drv.h" /* fpga_info_s */
+#include "nthw_register.h"
+#include "nthw_fpga_model.h"
+#include "nthw_rac.h"
+#include "ntlog.h"
+
+#include "nthw_fpga_instances.h"
+#include "nthw_fpga_modules_defs.h"
+
+/* Generated code */
+nt_fpga_prod_init_t *nthw_fpga_instances[] = { &nthw_fpga_9563_055_024_0000,
+ NULL
+ };
+
+static const struct {
+ const int a;
+ const char *b;
+} sa_nthw_fpga_mod_map[] = {
+ { MOD_CAT, "CAT" },
+ { MOD_CB, "CB" },
+ { MOD_CCIP, "CCIP" },
+ { MOD_CFP4_CTRL_GBOX, "CFP4_CTRL_GBOX" },
+ { MOD_COR, "COR" },
+ { MOD_CPY, "CPY" },
+ { MOD_CSU, "CSU" },
+ { MOD_DBS, "DBS" },
+ { MOD_DDP, "DDP" },
+ { MOD_EPP, "EPP" },
+ { MOD_EQM, "EQM" },
+ { MOD_FHM, "FHM" },
+ { MOD_FLM, "FLM" },
+ { MOD_GFG, "GFG" },
+ { MOD_GMF, "GMF" },
+ { MOD_GPIO_PHY, "GPIO_PHY" },
+ { MOD_GPIO_PHY_PORTS, "GPIO_PHY_PORTS" },
+ { MOD_GPIO_SFPP, "GPIO_SFPP" },
+ { MOD_HFU, "HFU" },
+ { MOD_HIF, "HIF" },
+ { MOD_HSH, "HSH" },
+ { MOD_HST, "HST" },
+ { MOD_ICORE_10G, "ICORE_10G" },
+ { MOD_IFR, "IFR" },
+ { MOD_IIC, "IIC" },
+ { MOD_INS, "INS" },
+ { MOD_IOA, "IOA" },
+ { MOD_IPF, "IPF" },
+ { MOD_KM, "KM" },
+ { MOD_LAO, "LAO" },
+ { MOD_MAC, "MAC" },
+ { MOD_MAC10, "MAC10" },
+ { MOD_MAC100, "MAC100" },
+ { MOD_MAC10G, "MAC10G" },
+ { MOD_MAC1G, "MAC1G" },
+ { MOD_MAC_PCS, "MAC_PCS" },
+ { MOD_MAC_PCS_XXV, "MAC_PCS_XXV" },
+ { MOD_MAC_RX, "MAC_RX" },
+ { MOD_MAC_TFG, "MAC_TFG" },
+ { MOD_MAC_TX, "MAC_TX" },
+ { MOD_MCU, "MCU" },
+ { MOD_MDG, "MDG" },
+ { MOD_MSK, "MSK" },
+ { MOD_NIF, "NIF" },
+ { MOD_PCIE3, "PCIE3" },
+ { MOD_PCI_RD_TG, "PCI_RD_TG" },
+ { MOD_PCI_TA, "PCI_TA" },
+ { MOD_PCI_WR_TG, "PCI_WR_TG" },
+ { MOD_PCM_NT100A01_01, "PCM_NT100A01_01" },
+ { MOD_PCM_NT50B01_01, "PCM_NT50B01_01" },
+ { MOD_PCS, "PCS" },
+ { MOD_PCS100, "PCS100" },
+ { MOD_PDB, "PDB" },
+ { MOD_PDI, "PDI" },
+ { MOD_PHY10G, "PHY10G" },
+ { MOD_PHY3S10G, "PHY3S10G" },
+ { MOD_PM, "PM" },
+ { MOD_PRM_NT100A01_01, "PRM_NT100A01_01" },
+ { MOD_PRM_NT50B01_01, "PRM_NT50B01_01" },
+ { MOD_PTP1588, "PTP1588" },
+ { MOD_QM, "QM" },
+ { MOD_QSL, "QSL" },
+ { MOD_QSPI, "QSPI" },
+ { MOD_R2DRP, "R2DRP" },
+ { MOD_RAC, "RAC" },
+ { MOD_RBH, "RBH" },
+ { MOD_RFD, "RFD" },
+ { MOD_RMC, "RMC" },
+ { MOD_RNTC, "RNTC" },
+ { MOD_ROA, "ROA" },
+ { MOD_RPL, "RPL" },
+ { MOD_RPP_LR, "RPP_LR" },
+ { MOD_RST7000, "RST7000" },
+ { MOD_RST7001, "RST7001" },
+ { MOD_RST9500, "RST9500" },
+ { MOD_RST9501, "RST9501" },
+ { MOD_RST9502, "RST9502" },
+ { MOD_RST9503, "RST9503" },
+ { MOD_RST9504, "RST9504" },
+ { MOD_RST9505, "RST9505" },
+ { MOD_RST9506, "RST9506" },
+ { MOD_RST9507, "RST9507" },
+ { MOD_RST9508, "RST9508" },
+ { MOD_RST9509, "RST9509" },
+ { MOD_RST9510, "RST9510" },
+ { MOD_RST9512, "RST9512" },
+ { MOD_RST9513, "RST9513" },
+ { MOD_RST9515, "RST9515" },
+ { MOD_RST9516, "RST9516" },
+ { MOD_RST9517, "RST9517" },
+ { MOD_RST9519, "RST9519" },
+ { MOD_RST9520, "RST9520" },
+ { MOD_RST9521, "RST9521" },
+ { MOD_RST9522, "RST9522" },
+ { MOD_RST9523, "RST9523" },
+ { MOD_RST9524, "RST9524" },
+ { MOD_RST9525, "RST9525" },
+ { MOD_RST9526, "RST9526" },
+ { MOD_RST9527, "RST9527" },
+ { MOD_RST9528, "RST9528" },
+ { MOD_RST9529, "RST9529" },
+ { MOD_RST9530, "RST9530" },
+ { MOD_RST9531, "RST9531" },
+ { MOD_RST9532, "RST9532" },
+ { MOD_RST9533, "RST9533" },
+ { MOD_RST9534, "RST9534" },
+ { MOD_RST9535, "RST9535" },
+ { MOD_RST9536, "RST9536" },
+ { MOD_RST9537, "RST9537" },
+ { MOD_RST9538, "RST9538" },
+ { MOD_RST9539, "RST9539" },
+ { MOD_RST9540, "RST9540" },
+ { MOD_RST9541, "RST9541" },
+ { MOD_RST9542, "RST9542" },
+ { MOD_RST9543, "RST9543" },
+ { MOD_RST9544, "RST9544" },
+ { MOD_RST9545, "RST9545" },
+ { MOD_RST9546, "RST9546" },
+ { MOD_RST9547, "RST9547" },
+ { MOD_RST9548, "RST9548" },
+ { MOD_RST9549, "RST9549" },
+ { MOD_RST9553, "RST9553" },
+ { MOD_RST9555, "RST9555" },
+ { MOD_RST9559, "RST9559" },
+ { MOD_RST9563, "RST9563" },
+ { MOD_RTD, "RTD" },
+ { MOD_RTD_HMP, "RTD_HMP" },
+ { MOD_RTX, "RTX" },
+ { MOD_SDC, "SDC" },
+ { MOD_SLC, "SLC" },
+ { MOD_SLC_LR, "SLC_LR" },
+ { MOD_SMM, "SMM" },
+ { MOD_SMM_RX, "SMM_RX" },
+ { MOD_SMM_TX, "SMM_TX" },
+ { MOD_SPIM, "SPIM" },
+ { MOD_SPIS, "SPIS" },
+ { MOD_STA, "STA" },
+ { MOD_TBH, "TBH" },
+ { MOD_TEMPMON, "TEMPMON" },
+ { MOD_TINT, "TINT" },
+ { MOD_TMC, "TMC" },
+ { MOD_TSM, "TSM" },
+ { MOD_TX_CPY, "TX_CPY" },
+ { MOD_TX_CSI, "TX_CSI" },
+ { MOD_TX_CSO, "TX_CSO" },
+ { MOD_TX_INS, "TX_INS" },
+ { MOD_TX_RPL, "TX_RPL" },
+ { 0L, NULL },
+};
+
+/* NOTE: this needs to be (manually) synced with enum */
+static const char *const a_bus_type[] = {
+ "ERR", /* BUS_TYPE_UNKNOWN, */
+ "BAR", /* BUS_TYPE_BAR, */
+ "PCI", /* BUS_TYPE_PCI, */
+ "CCIP", /* BUS_TYPE_CCIP, */
+ "RAB0", /* BUS_TYPE_RAB0, */
+ "RAB1", /* BUS_TYPE_RAB1, */
+ "RAB2", /* BUS_TYPE_RAB2, */
+ "NMB", /* BUS_TYPE_NMB, */
+ "NDM", /* BUS_TYPE_NDM, */
+};
+
+static const char *get_bus_name(int n_bus_type_id)
+{
+ if (n_bus_type_id >= 1 && n_bus_type_id <= (int)ARRAY_SIZE(a_bus_type))
+ return a_bus_type[n_bus_type_id];
+
+ else
+ return "ERR";
+}
+
+/*
+ * Module name lookup by id from array
+ * Uses naive linear search as performance is not an issue here...
+ */
+static const char *nthw_fpga_mod_id_to_str(uint64_t n_fpga_mod_id)
+{
+ int i;
+
+ for (i = 0; i <= (int)ARRAY_SIZE(sa_nthw_fpga_mod_map); i++) {
+ if ((uint64_t)sa_nthw_fpga_mod_map[i].a == n_fpga_mod_id)
+ break;
+ }
+ return (sa_nthw_fpga_mod_map[i].b ? sa_nthw_fpga_mod_map[i].b :
+ "unknown");
+}
+
+/*
+ * Force C linkage for xxx_addr_bases and xxx_module_versions
+ */
+static int read_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id, uint32_t addr,
+ uint32_t len, uint32_t *p_data)
+{
+ int rc = -1;
+
+ assert(p_fpga_info);
+ assert(p_data);
+
+ switch (n_bus_type_id) {
+ case BUS_TYPE_BAR:
+ case BUS_TYPE_PCI:
+ assert(len == 1);
+ nthw_rac_reg_read32(p_fpga_info, addr, p_data);
+ rc = 0;
+ break;
+ case BUS_TYPE_RAB0:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 0, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB1:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 1, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB2:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 2, len,
+ p_data);
+ break;
+ default:
+ assert(false);
+ return -1;
+ }
+
+ return rc;
+}
+
+static int read_data_tsc(struct fpga_info_s *p_fpga_info, int n_bus_type_id,
+ uint32_t addr, uint32_t len, uint32_t *p_data,
+ uint64_t *p_tsc1, uint64_t *p_tsc2)
+{
+ int rc = -1;
+
+ (void)p_tsc1;
+ (void)p_tsc2;
+
+ rc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data);
+
+ return rc;
+}
+
+static int write_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id,
+ uint32_t addr, uint32_t len, const uint32_t *p_data)
+{
+ int rc = -1;
+
+ assert(p_fpga_info);
+ assert(p_data);
+
+ switch (n_bus_type_id) {
+ case BUS_TYPE_BAR:
+ case BUS_TYPE_PCI:
+ assert(len == 1);
+ nthw_rac_reg_write32(p_fpga_info, addr, *p_data);
+ rc = 0;
+ break;
+ case BUS_TYPE_RAB0:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 0, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB1:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 1, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB2:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 2, len,
+ p_data);
+ break;
+ default:
+ assert(false);
+ return -1;
+ }
+
+ return rc;
+}
+
+/*
+ * FpgaMgr
+ */
+nt_fpga_mgr_t *fpga_mgr_new(void)
+{
+ nt_fpga_mgr_t *p = malloc(sizeof(nt_fpga_mgr_t));
+ return p;
+}
+
+void fpga_mgr_delete(nt_fpga_mgr_t *p)
+{
+ memset(p, 0, sizeof(nt_fpga_mgr_t));
+ free(p);
+}
+
+void fpga_mgr_init(nt_fpga_mgr_t *p)
+{
+ size_t i;
+
+ /* Count fpga instance in array */
+ p->mpa_fpga_prod_init = nthw_fpga_instances;
+ for (i = 0; i < ARRAY_SIZE(nthw_fpga_instances); i++) {
+ if (p->mpa_fpga_prod_init[i] == NULL)
+ break;
+ }
+ p->mn_fpgas = (int)i;
+}
+
+nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id,
+ struct fpga_info_s *p_fpga_info)
+{
+ int i;
+
+ const int n_fpga_prod = FPGAID_TO_PRODUCTCODE(n_fpga_id);
+ const int n_fpga_ver = FPGAID_TO_VERSIONCODE(n_fpga_id);
+ const int n_fpga_rev = FPGAID_TO_REVISIONCODE(n_fpga_id);
+
+ for (i = 0; i < p->mn_fpgas; i++) {
+ nt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i];
+
+ if (p_init->fpga_product_id == n_fpga_prod &&
+ p_init->fpga_version == n_fpga_ver &&
+ p_init->fpga_revision == n_fpga_rev) {
+ {
+ nt_fpga_t *p_fpga = fpga_new();
+
+ fpga_init(p_fpga, p_init, p_fpga_info);
+ return p_fpga;
+ }
+ }
+ }
+
+ NT_LOG(ERR, NTHW,
+ "FPGA Id 0x%" PRIX64 ": %04d: %d.%d: no match found\n", n_fpga_id,
+ n_fpga_prod, n_fpga_ver, n_fpga_rev);
+
+ return NULL;
+}
+
+void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *fh_out, int detail_level)
+{
+ int i;
+
+ fprintf(fh_out, "\n"); /* start of records */
+ for (i = 0; i < p->mn_fpgas; i++) {
+ nt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i];
+
+ if (detail_level == 0) {
+ fprintf(fh_out, "%04d-%02d-%02d\n",
+ p_init->fpga_product_id, p_init->fpga_version,
+ p_init->fpga_revision);
+ } else {
+ time_t fpga_build_time = p_init->fpga_build_time;
+
+ fprintf(fh_out, "%04d-%02d-%02d: 0x%08lX: %s\n",
+ p_init->fpga_product_id, p_init->fpga_version,
+ p_init->fpga_revision, fpga_build_time,
+ (fpga_build_time ? ctime(&fpga_build_time) :
+ "NA\n"));
+ }
+ }
+ fprintf(fh_out, "\n"); /* end of records */
+ fflush(fh_out);
+}
+
+void fpga_mgr_log_dump(nt_fpga_mgr_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: fpgas=%d\n", __func__, p->mn_fpgas);
+ for (i = 0; i < p->mn_fpgas; i++) {
+ nt_fpga_prod_init_t *p_init _unused = p->mpa_fpga_prod_init[i];
+ NT_LOG(DBG, NTHW, "%s: fpga=%d/%d: %04d-%02d-%02d\n", __func__,
+ i, p->mn_fpgas, p_init->fpga_product_id, p_init->fpga_version,
+ p_init->fpga_revision);
+ }
+}
+
+/*
+ * Fpga
+ */
+nt_fpga_t *fpga_new(void)
+{
+ nt_fpga_t *p = malloc(sizeof(nt_fpga_t));
+
+ if (p)
+ memset(p, 0, sizeof(nt_fpga_t));
+ return p;
+}
+
+void fpga_delete(nt_fpga_t *p)
+{
+ memset(p, 0, sizeof(nt_fpga_t));
+ free(p);
+}
+
+void fpga_delete_all(nt_fpga_t *p)
+{
+ int i;
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ if (p_mod)
+ module_delete(p_mod);
+ }
+
+ fpga_delete(p);
+}
+
+void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init,
+ struct fpga_info_s *p_fpga_info)
+{
+ int i;
+
+ p->p_fpga_info = p_fpga_info;
+ p->mp_init = fpga_prod_init;
+
+ p->m_item_id = fpga_prod_init->fpga_item_id;
+ p->m_product_id = fpga_prod_init->fpga_product_id;
+ p->m_fpga_version = fpga_prod_init->fpga_version;
+ p->m_fpga_revision = fpga_prod_init->fpga_revision;
+ p->m_fpga_patch_no = fpga_prod_init->fpga_patch_no;
+ p->m_fpga_build_no = fpga_prod_init->fpga_build_no;
+ p->m_fpga_build_time = fpga_prod_init->fpga_build_time;
+
+ p->mn_params = fpga_prod_init->nb_prod_params;
+
+ if (p->mn_params) {
+ p->mpa_params = malloc(p->mn_params * sizeof(nt_param_t *));
+ if (p->mpa_params) {
+ memset(p->mpa_params, 0,
+ (p->mn_params * sizeof(nt_param_t *)));
+ for (i = 0; i < p->mn_params; i++) {
+ nt_param_t *p_param = param_new();
+
+ param_init(p_param, p,
+ &fpga_prod_init->product_params[i]);
+ p->mpa_params[i] = p_param;
+ }
+ }
+ }
+
+ p->mn_modules = fpga_prod_init->nb_modules;
+
+ if (p->mn_modules) {
+ p->mpa_modules =
+ malloc(fpga_prod_init->nb_modules * sizeof(nt_module_t *));
+ if (p->mpa_modules) {
+ memset(p->mpa_modules, 0,
+ (p->mn_modules * sizeof(nt_module_t *)));
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = module_new();
+
+ module_init(p_mod, p, &fpga_prod_init->modules[i]);
+ p->mpa_modules[i] = p_mod;
+ }
+ }
+ }
+}
+
+void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode)
+{
+ int i;
+
+ p->m_debug_mode = n_debug_mode;
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ if (p_mod)
+ module_set_debug_mode(p_mod, n_debug_mode);
+ }
+}
+
+nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance)
+{
+ int i;
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ if (p_mod->m_mod_id == id && p_mod->m_instance == instance)
+ return p_mod;
+ }
+ return NULL;
+}
+
+bool fpga_query(nt_fpga_t *p, int id, int instance)
+{
+ return (fpga_query_module(p, id, instance) != NULL);
+}
+
+nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance)
+{
+ int i;
+
+ for (i = 0; i < p->mp_init->nb_modules; i++) {
+ nt_fpga_module_init_t *p_mod_init = &p->mp_init->modules[i];
+
+ if (p_mod_init->id == id && p_mod_init->instance == instance)
+ return p_mod_init;
+ }
+ return NULL;
+}
+
+int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id,
+ const int n_default_value)
+{
+ int i;
+
+ for (i = 0; i < p->mn_params; i++) {
+ nt_param_t *p_param = p->mpa_params[i];
+
+ if (p_param->param_id == n_param_id)
+ return p_param->param_value;
+ }
+
+ return n_default_value;
+}
+
+int fpga_get_product_id(const nt_fpga_t *p)
+{
+ return p->m_product_id;
+}
+
+int fpga_get_fpga_version(const nt_fpga_t *p)
+{
+ return p->m_fpga_version;
+}
+
+int fpga_get_fpga_revision(const nt_fpga_t *p)
+{
+ return p->m_fpga_revision;
+}
+
+void fpga_log_info(const nt_fpga_t *p _unused)
+{
+ NT_LOG(INF, NTHW, "FPGA: %d-%d-%d-%d-%d-%d (%08X)\n", p->m_item_id,
+ p->m_product_id, p->m_fpga_version, p->m_fpga_revision,
+ p->m_fpga_patch_no, p->m_fpga_build_no, p->m_fpga_build_time);
+}
+
+void fpga_dump(const nt_fpga_t *p)
+{
+ NT_LOG(DBG, NTHW, "%s: id=%d ver=%d.%d params=%d modules=%d\n",
+ __func__, p->m_product_id, p->m_fpga_version, p->m_fpga_revision,
+ p->mn_params, p->mn_modules);
+ fpga_dump_params(p);
+ fpga_dump_modules(p);
+}
+
+void fpga_dump_params(const nt_fpga_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: params=%d\n", __func__, p->mn_params);
+
+ for (i = 0; i < p->mn_params; i++) {
+ nt_param_t *p_par = p->mpa_params[i];
+
+ param_dump(p_par);
+ }
+}
+
+void fpga_dump_modules(const nt_fpga_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: modules=%d\n", __func__, p->mn_modules);
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ module_dump(p_mod);
+ }
+}
+
+/*
+ * Param
+ */
+nt_param_t *param_new(void)
+{
+ nt_param_t *p = malloc(sizeof(nt_param_t));
+ return p;
+}
+
+void param_delete(nt_param_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nt_param_t));
+ free(p);
+ }
+}
+
+void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init)
+{
+ p->mp_owner = p_fpga;
+ p->mp_init = p_init;
+
+ p->param_id = p_init->param_id;
+ p->param_value = p_init->param_value;
+}
+
+void param_dump(const nt_param_t *p _unused)
+{
+ NT_LOG(DBG, NTHW, "%s: id=%d value=%d\n", __func__, p->param_id,
+ p->param_value);
+}
+
+/*
+ * Module
+ */
+nt_module_t *module_new(void)
+{
+ nt_module_t *p = malloc(sizeof(nt_module_t));
+ return p;
+}
+
+void module_delete(nt_module_t *p)
+{
+ int i;
+
+ for (i = 0; i < p->mn_registers; i++) {
+ nt_register_t *p_reg = p->mpa_registers[i];
+
+ if (p_reg)
+ register_delete(p_reg);
+ }
+ memset(p, 0, sizeof(nt_module_t));
+ free(p);
+}
+
+void module_init(nt_module_t *p, nt_fpga_t *p_fpga, nt_fpga_module_init_t *p_init)
+{
+ int i;
+
+ p->mp_owner = p_fpga;
+ p->mp_init = p_init;
+
+ p->m_mod_id = p_init->id;
+ p->m_instance = p_init->instance;
+
+ /* Copy debug mode from owner */
+ if (p->mp_owner)
+ p->m_debug_mode = p->mp_owner->m_debug_mode;
+
+ else
+ p->m_debug_mode = 0;
+
+ p->m_mod_def_id = p_init->def_id;
+ p->m_major_version = p_init->major_version;
+ p->m_minor_version = p_init->minor_version;
+ p->m_bus = p_init->bus_id;
+ p->m_addr_base = p_init->addr_base;
+
+ p->mn_registers = p_init->nb_registers;
+ if (p->mn_registers) {
+ p->mpa_registers =
+ malloc(p->mn_registers * sizeof(nt_register_t *));
+ if (p->mpa_registers) {
+ memset(p->mpa_registers, 0,
+ (p->mn_registers * sizeof(nt_register_t *)));
+ for (i = 0; i < p->mn_registers; i++) {
+ nt_register_t *p_reg = register_new();
+
+ register_init(p_reg, p, &p_init->registers[i]);
+ p->mpa_registers[i] = p_reg;
+ }
+ }
+ }
+}
+
+void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance,
+ int debug_mode)
+{
+ nt_fpga_module_init_t *p_init = NULL;
+
+ p_init = fpga_lookup_init(p_fpga, mod_id, instance);
+ module_init(p, p_fpga, p_init);
+
+ /* set debug mode after regulat init... */
+ p->m_debug_mode = debug_mode;
+}
+
+void module_dump(const nt_module_t *p)
+{
+ NT_LOG(DBG, NTHW,
+ "%s: id=%d inst=%d def=%d ver=%d.%d busid=%d base=0x%X regs=%d\n",
+ __func__, p->m_mod_id, p->m_instance, p->m_mod_def_id,
+ p->m_major_version, p->m_minor_version, p->m_bus, p->m_addr_base,
+ p->mn_registers);
+ module_dump_registers(p);
+}
+
+void module_dump_registers(const nt_module_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: regs=%d\n", __func__, p->mn_registers);
+
+ for (i = 0; i < p->mn_registers; i++) {
+ nt_register_t *p_reg = p->mpa_registers[i];
+
+ register_dump(p_reg);
+ }
+}
+
+int module_get_major_version(const nt_module_t *p)
+{
+ return p->m_major_version;
+}
+
+int module_get_minor_version(const nt_module_t *p)
+{
+ return p->m_minor_version;
+}
+
+uint64_t module_get_version_packed64(const nt_module_t *p)
+{
+ return (((uint64_t)p->m_major_version & 0xFFFFFFFF) << 32) |
+ (p->m_minor_version & 0xFFFFFFFF);
+}
+
+bool module_is_version_newer(const nt_module_t *p, int major_version,
+ int minor_version)
+{
+ if (major_version == p->m_major_version)
+ return p->m_minor_version >= minor_version;
+ return p->m_major_version >= major_version;
+}
+
+static nt_register_t *module_lookup_register(nt_module_t *p, uint32_t id)
+{
+ int i;
+ nt_register_t *p_register = NULL;
+
+ for (i = 0; i < p->mn_registers; i++) {
+ if (p->mpa_registers[i]->m_id == id) {
+ p_register = p->mpa_registers[i];
+ break;
+ }
+ }
+ return p_register;
+}
+
+nt_register_t *module_get_register(nt_module_t *p, uint32_t id)
+{
+ nt_register_t *p_register;
+
+ if (p == NULL) {
+ NT_LOG(ERR, NTHW, "Illegal module context for register %d\n",
+ id);
+ return NULL;
+ }
+
+ p_register = module_lookup_register(p, id);
+ if (!p_register) {
+ NT_LOG(ERR, NTHW, "Register %d not found in module: %s (%d)\n",
+ id, nthw_fpga_mod_id_to_str(p->m_mod_id), p->m_mod_id);
+ }
+ return p_register;
+}
+
+nt_register_t *module_query_register(nt_module_t *p, uint32_t id)
+{
+ return module_lookup_register(p, id);
+}
+
+int module_get_debug_mode(const nt_module_t *p)
+{
+ return p->m_debug_mode;
+}
+
+void module_set_debug_mode(nt_module_t *p, unsigned int n_debug_mode)
+{
+ int i;
+ nt_register_t *p_register = NULL;
+
+ p->m_debug_mode = n_debug_mode;
+
+ for (i = 0; i < p->mn_registers; i++) {
+ p_register = p->mpa_registers[i];
+ if (p_register)
+ register_set_debug_mode(p_register, n_debug_mode);
+ }
+}
+
+int module_get_bus(const nt_module_t *p)
+{
+ return p->m_bus;
+}
+
+uint32_t module_get_addr_base(const nt_module_t *p)
+{
+ return p->m_addr_base;
+}
+
+void module_unsuppported(const nt_module_t *p)
+{
+ NT_LOG(ERR, NTHW, "Module %d not supported", p->mp_init->id);
+}
+
+/*
+ * Register
+ */
+nt_register_t *register_new(void)
+{
+ nt_register_t *p = malloc(sizeof(nt_register_t));
+ return p;
+}
+
+void register_delete(nt_register_t *p)
+{
+ int i;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ nt_field_t *p_field = p->mpa_fields[i];
+
+ if (p_field)
+ field_delete(p_field);
+ }
+
+ if (p->mp_shadow)
+ free(p->mp_shadow);
+
+ if (p->mp_dirty)
+ free(p->mp_dirty);
+
+ memset(p, 0, sizeof(nt_register_t));
+ free(p);
+}
+
+void register_init(nt_register_t *p, nt_module_t *p_module,
+ nt_fpga_register_init_t *p_init)
+{
+ int i;
+
+ p->mp_owner = p_module;
+
+ p->m_id = p_init->id;
+ p->mn_bit_width = p_init->bw;
+ p->mn_addr_rel = p_init->addr_rel;
+ p->m_addr = p_module->m_addr_base + p_init->addr_rel;
+ p->m_type = p_init->type;
+ p->m_len =
+ ((p_init->bw != (uint16_t)-1) ?
+ ((p_init->bw + 31) >> 5) :
+ 1); /* Old P200 registers have no bw at register level - default to BW=-1 */
+ p->m_debug_mode = p_module->m_debug_mode;
+
+ p->mn_fields = p_init->nb_fields;
+ if (p->mn_fields) {
+ p->mpa_fields = malloc(p->mn_fields * sizeof(nt_field_t *));
+
+ if (p->mpa_fields) {
+ memset(p->mpa_fields, 0,
+ (p->mn_fields * sizeof(nt_field_t *)));
+ for (i = 0; i < p->mn_fields; i++) {
+ nt_field_t *p_field = field_new();
+
+ field_init(p_field, p, &p_init->fields[i]);
+ p->mpa_fields[i] = p_field;
+ }
+
+ p->mp_shadow = malloc(p->m_len * sizeof(uint32_t));
+ if (p->mp_shadow) {
+ memset(p->mp_shadow, 0x00,
+ (p->m_len * sizeof(uint32_t)));
+ }
+
+ p->mp_dirty = malloc(p->m_len * sizeof(bool));
+ if (p->mp_dirty) {
+ memset(p->mp_dirty, 0x00,
+ (p->m_len * sizeof(bool)));
+ }
+ }
+ }
+}
+
+void register_dump(const nt_register_t *p)
+{
+ NT_LOG(DBG, NTHW,
+ "%s(id=%d type=%d addr=0x%08X addrrel=0x%08X len=%d bw=%d\n",
+ __func__, p->m_id, p->m_type, p->m_addr, p->mn_addr_rel, p->m_len,
+ p->mn_bit_width);
+ register_dump_fields(p);
+}
+
+void register_dump_fields(const nt_register_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s(addr=0x%08X fields=%d\n", __func__, p->m_addr,
+ p->mn_fields);
+ for (i = 0; i < p->mn_fields; i++)
+ field_dump(p->mpa_fields[i]);
+ NT_LOG(DBG, NTHW, "\n");
+}
+
+uint32_t register_get_address(const nt_register_t *p)
+{
+ return p->m_addr;
+}
+
+void register_reset(const nt_register_t *p)
+{
+ int i;
+ nt_field_t *p_field = NULL;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ p_field = p->mpa_fields[i];
+ if (p_field)
+ field_reset(p_field);
+ }
+}
+
+static nt_field_t *register_lookup_field(const nt_register_t *p, uint32_t id)
+{
+ int i;
+ nt_field_t *p_field = NULL;
+
+ if (!p)
+ return NULL;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ if (p->mpa_fields[i]->m_id == id) {
+ p_field = p->mpa_fields[i];
+ break;
+ }
+ }
+ return p_field;
+}
+
+nt_field_t *register_get_field(const nt_register_t *p, uint32_t id)
+{
+ nt_field_t *p_field;
+
+ if (p == NULL) {
+ NT_LOG(ERR, NTHW, "Illegal register context for field %d\n",
+ id);
+ return NULL;
+ }
+
+ p_field = register_lookup_field(p, id);
+ if (!p_field) {
+ NT_LOG(ERR, NTHW, "Field %d not found in module: %s (%d)\n", id,
+ nthw_fpga_mod_id_to_str(p->mp_owner->m_mod_id),
+ p->mp_owner->m_mod_id);
+ }
+ return p_field;
+}
+
+nt_field_t *register_query_field(const nt_register_t *p, uint32_t id)
+{
+ return register_lookup_field(p, id);
+}
+
+int register_get_bit_width(const nt_register_t *p)
+{
+ return p->mn_bit_width;
+}
+
+uint32_t register_get_addr_rel(const nt_register_t *p)
+{
+ return p->mn_addr_rel;
+}
+
+int register_get_debug_mode(const nt_module_t *p)
+{
+ return p->m_debug_mode;
+}
+
+/*
+ * NOTE: do not set debug on fields - as register operation dumps typically are enough
+ */
+void register_set_debug_mode(nt_register_t *p, unsigned int n_debug_mode)
+{
+ int i;
+ nt_field_t *p_field = NULL;
+
+ p->m_debug_mode = n_debug_mode;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ p_field = p->mpa_fields[i];
+ if (p_field)
+ field_set_debug_mode(p_field, n_debug_mode);
+ }
+}
+
+static int register_read_data(const nt_register_t *p)
+{
+ int rc = -1;
+
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ struct fpga_info_s *p_fpga_info = NULL;
+
+ if (p && p->mp_owner && p->mp_owner->mp_owner)
+ p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
+ assert(p_fpga_info);
+ assert(p_data);
+
+ rc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data);
+ return rc;
+}
+
+static int register_read_data_tsc(const nt_register_t *p, uint64_t *p_tsc1,
+ uint64_t *p_tsc2)
+{
+ int rc = -1;
+
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ struct fpga_info_s *p_fpga_info = NULL;
+
+ if (p && p->mp_owner && p->mp_owner->mp_owner)
+ p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
+
+ rc = read_data_tsc(p_fpga_info, n_bus_type_id, addr, len, p_data, p_tsc1, p_tsc2);
+
+ return rc;
+}
+
+static int register_write_data(const nt_register_t *p, uint32_t cnt)
+{
+ int rc = -1;
+
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ struct fpga_info_s *p_fpga_info = NULL;
+
+ if (p && p->mp_owner && p->mp_owner->mp_owner)
+ p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
+ assert(p_fpga_info);
+ assert(p_data);
+
+ rc = write_data(p_fpga_info, n_bus_type_id, addr, (len * cnt), p_data);
+
+ return rc;
+}
+
+void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len)
+{
+ uint32_t i;
+
+ if (len == (uint32_t)-1 || len > p->m_len)
+ len = p->m_len;
+
+ assert(len <= p->m_len);
+ assert(p_data);
+
+ for (i = 0; i < len; i++)
+ p_data[i] = p->mp_shadow[i];
+}
+
+uint32_t register_get_val32(const nt_register_t *p)
+{
+ uint32_t val = 0;
+
+ register_get_val(p, &val, 1);
+ return val;
+}
+
+void register_update(const nt_register_t *p)
+{
+ if (p && p->m_type != REGISTER_TYPE_WO) {
+ const char *const p_dev_name _unused = "NA";
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+
+ const char *const p_bus_name _unused = get_bus_name(n_bus_type_id);
+ const uint32_t addr _unused = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ register_read_data(p);
+ if (p->m_debug_mode & ON_READ) {
+ uint32_t i = len;
+
+ uint32_t *ptr _unused = p_data;
+ NT_LOG(DBG, NTHW,
+ "Register::read(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:",
+ p_dev_name, p_bus_name, addr, len);
+ while (i--)
+ NT_LOG(DBG, NTHW, " 0x%08X ", *ptr++);
+ NT_LOG(DBG, NTHW, ")\n");
+ }
+ }
+}
+
+uint32_t register_get_val_updated32(const nt_register_t *p)
+{
+ uint32_t val = 0;
+
+ register_update(p);
+ register_get_val(p, &val, 1);
+ return val;
+}
+
+void register_make_dirty(nt_register_t *p)
+{
+ uint32_t i;
+
+ for (i = 0; i < p->m_len; i++)
+ p->mp_dirty[i] = true;
+}
+
+void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len)
+{
+ assert(len <= p->m_len);
+ assert(p_data);
+
+ if (len == (uint32_t)-1 || len > p->m_len)
+ len = p->m_len;
+
+ if (p->mp_shadow != p_data)
+ memcpy(p->mp_shadow, p_data, (len * sizeof(uint32_t)));
+}
+
+void register_set_val_flush(nt_register_t *p, const uint32_t *p_data, uint32_t len)
+{
+ register_set_val(p, p_data, len);
+ register_flush(p, 1);
+}
+
+void register_flush(const nt_register_t *p, uint32_t cnt)
+{
+ int rc;
+
+ if (p->m_type != REGISTER_TYPE_RO) {
+ const char *const p_dev_name = "NA";
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const char *p_bus_name = get_bus_name(n_bus_type_id);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+ uint32_t i;
+
+ assert(len * cnt <= 256);
+
+ if (p->m_debug_mode & ON_WRITE) {
+ uint32_t i = len * cnt;
+ uint32_t *ptr = p_data;
+ char *tmp_string =
+ ntlog_helper_str_alloc("Register::write");
+ ntlog_helper_str_add(tmp_string,
+ "(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:",
+ p_dev_name, p_bus_name, addr, i);
+ while (i--) {
+ ntlog_helper_str_add(tmp_string, " 0x%08X",
+ *ptr++);
+ }
+ ntlog_helper_str_add(tmp_string, ")\n");
+ NT_LOG(DBG, NTHW, "%s", tmp_string);
+ ntlog_helper_str_free(tmp_string);
+ }
+
+ rc = register_write_data(p, cnt);
+
+ if (rc)
+ NT_LOG(ERR, NTHW, "Register write error %d\n", rc);
+
+ for (i = 0; i < cnt; i++)
+ p->mp_dirty[i] = false;
+ }
+}
+
+void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1,
+ uint64_t *tsc2)
+{
+ register_read_data_tsc(p, tsc1, tsc2);
+}
+
+void register_clr(nt_register_t *p)
+{
+ memset(p->mp_shadow, 0, p->m_len * sizeof(uint32_t));
+ register_make_dirty(p);
+}
+
+void register_set(nt_register_t *p)
+{
+ memset(p->mp_shadow, 0xff, p->m_len * sizeof(uint32_t));
+ register_make_dirty(p);
+}
+
+/*
+ * Field
+ */
+nt_field_t *field_new(void)
+{
+ nt_field_t *p = malloc(sizeof(nt_field_t));
+ return p;
+}
+
+void field_delete(nt_field_t *p)
+{
+ memset(p, 0, sizeof(nt_field_t));
+ free(p);
+}
+
+void field_init(nt_field_t *p, nt_register_t *p_reg,
+ const nt_fpga_field_init_t *p_init)
+{
+ p->mp_owner = p_reg;
+
+ p->m_debug_mode = p_reg->m_debug_mode;
+
+ p->m_id = p_init->id;
+ p->mn_bit_width = p_init->bw;
+ p->mn_bit_pos_low = p_init->low;
+ p->m_reset_val = (uint32_t)p_init->reset_val;
+ p->m_first_word = p_init->low / 32;
+ p->m_first_bit = p_init->low % 32;
+ p->m_front_mask = 0;
+ p->m_body_length = 0;
+ p->mn_words = (p_init->bw + 0x1f) / 0x20;
+ p->m_tail_mask = 0;
+
+ {
+ int bits_remaining = p_init->bw;
+ int front_mask_length = 32 - p->m_first_bit;
+
+ if (front_mask_length > bits_remaining)
+ front_mask_length = bits_remaining;
+ bits_remaining -= front_mask_length;
+
+ p->m_front_mask = (uint32_t)(((1ULL << front_mask_length) - 1)
+ << p->m_first_bit);
+
+ p->m_body_length = bits_remaining / 32;
+ bits_remaining -= p->m_body_length * 32;
+ p->m_tail_mask = (1 << bits_remaining) - 1;
+
+ if (p->m_debug_mode >= 0x100) {
+ NT_LOG(DBG, NTHW,
+ "%s: fldid=%08d: [%08d:%08d] %08d/%08d: (%08d,%08d) (0x%08X,%08d,0x%08X)\n",
+ __func__, p_init->id, p_init->low,
+ (p_init->low + p_init->bw), p_init->bw,
+ ((p_init->bw + 31) / 32), p->m_first_word,
+ p->m_first_bit, p->m_front_mask, p->m_body_length,
+ p->m_tail_mask);
+ }
+ }
+}
+
+int field_get_debug_mode(const nt_module_t *p)
+{
+ return p->m_debug_mode;
+}
+
+void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode)
+{
+ p->m_debug_mode = n_debug_mode;
+}
+
+int field_get_bit_width(const nt_field_t *p)
+{
+ return p->mn_bit_width;
+}
+
+int field_get_bit_pos_low(const nt_field_t *p)
+{
+ return p->mn_bit_pos_low;
+}
+
+int field_get_bit_pos_high(const nt_field_t *p)
+{
+ return p->mn_bit_pos_low + p->mn_bit_width - 1;
+}
+
+uint32_t field_get_mask(const nt_field_t *p)
+{
+ return p->m_front_mask;
+}
+
+void field_reset(const nt_field_t *p)
+{
+ field_set_val32(p, (uint32_t)p->m_reset_val);
+}
+
+uint32_t field_get_val_mask(const nt_field_t *p)
+{
+ return (p->m_front_mask >> p->mn_bit_pos_low);
+}
+
+uint32_t field_get_reset_val(const nt_field_t *p)
+{
+ return (uint32_t)p->m_reset_val;
+}
+
+void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len)
+{
+ uint32_t i;
+ uint32_t data_index = 0;
+ uint32_t shadow_index = p->m_first_word;
+
+ union {
+ uint32_t w32[2];
+ uint64_t w64;
+ } buf;
+
+ (void)len;
+ assert(len == p->mn_words);
+
+ /* handle front */
+ buf.w32[0] = p->mp_owner->mp_shadow[shadow_index++] & p->m_front_mask;
+
+ /* handle body */
+ for (i = 0; i < p->m_body_length; i++) {
+ buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++];
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ assert(data_index < len);
+ p_data[data_index++] = buf.w32[0];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ }
+
+ /* handle tail */
+ if (p->m_tail_mask)
+ buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++] & p->m_tail_mask;
+
+ else
+ buf.w32[1] = 0;
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ p_data[data_index++] = buf.w32[0];
+ if (data_index < p->mn_words)
+ p_data[data_index++] = buf.w32[1];
+}
+
+void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len)
+{
+ uint32_t i;
+ uint32_t data_index = 0;
+ uint32_t shadow_index = p->m_first_word;
+
+ union {
+ uint32_t w32[2];
+ uint64_t w64;
+ } buf;
+
+ (void)len;
+ assert(len == p->mn_words);
+
+ /* handle front */
+ buf.w32[0] = 0;
+ buf.w32[1] = p_data[data_index++];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ p->mp_owner->mp_shadow[shadow_index] =
+ (p->mp_owner->mp_shadow[shadow_index] & ~p->m_front_mask) |
+ (buf.w32[0] & p->m_front_mask);
+ shadow_index++;
+
+ /* handle body */
+ for (i = 0; i < p->m_body_length; i++) {
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ assert(data_index < len);
+ buf.w32[1] = p_data[data_index++];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ p->mp_owner->mp_shadow[shadow_index++] = buf.w32[0];
+ }
+
+ /* handle tail */
+ if (p->m_tail_mask) {
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ if (data_index < len)
+ buf.w32[1] = p_data[data_index];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ p->mp_owner->mp_shadow[shadow_index] =
+ (p->mp_owner->mp_shadow[shadow_index] & ~p->m_tail_mask) |
+ (buf.w32[0] & p->m_tail_mask);
+ }
+
+ register_make_dirty(p->mp_owner);
+}
+
+void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data, uint32_t len)
+{
+ field_set_val(p, p_data, len);
+ field_flush_register(p);
+}
+
+uint32_t field_get_val32(const nt_field_t *p)
+{
+ uint32_t val;
+
+ field_get_val(p, &val, 1);
+ return val;
+}
+
+uint32_t field_get_updated(const nt_field_t *p)
+{
+ uint32_t val;
+
+ register_update(p->mp_owner);
+ field_get_val(p, &val, 1);
+
+ return val;
+}
+
+void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2)
+{
+ register_do_read_trig_ts(p->mp_owner, tsc1, tsc2);
+}
+
+void field_update_register(const nt_field_t *p)
+{
+ register_update(p->mp_owner);
+}
+
+void field_flush_register(const nt_field_t *p)
+{
+ register_flush(p->mp_owner, 1);
+}
+
+void field_set_val32(const nt_field_t *p, uint32_t val)
+{
+ field_set_val(p, &val, 1);
+}
+
+void field_set_val_flush32(const nt_field_t *p, uint32_t val)
+{
+ field_set_val(p, &val, 1);
+ register_flush(p->mp_owner, 1);
+}
+
+void field_clr_all(const nt_field_t *p)
+{
+ assert(p->m_body_length == 0);
+ field_set_val32(p, 0);
+}
+
+void field_clr_flush(const nt_field_t *p)
+{
+ field_clr_all(p);
+ register_flush(p->mp_owner, 1);
+}
+
+void field_set_all(const nt_field_t *p)
+{
+ assert(p->m_body_length == 0);
+ field_set_val32(p, ~0);
+}
+
+void field_set_flush(const nt_field_t *p)
+{
+ field_set_all(p);
+ register_flush(p->mp_owner, 1);
+}
+
+enum field_match {
+ FIELD_MATCH_CLR_ALL,
+ FIELD_MATCH_SET_ALL,
+ FIELD_MATCH_CLR_ANY,
+ FIELD_MATCH_SET_ANY,
+};
+
+static int field_wait_cond32(const nt_field_t *p, enum field_match e_match,
+ int n_poll_iterations, int n_poll_interval)
+{
+ const uint32_t n_mask = (1 << p->mn_bit_width) - 1;
+
+ if (n_poll_iterations == -1)
+ n_poll_iterations = 10000;
+ if (n_poll_interval == -1)
+ n_poll_interval = 100; /* usec */
+
+ if (p->m_debug_mode) {
+ const char *const p_cond_name _unused =
+ ((e_match == FIELD_MATCH_SET_ALL) ?
+ "SetAll" :
+ ((e_match == FIELD_MATCH_CLR_ALL) ?
+ "ClrAll" :
+ ((e_match == FIELD_MATCH_CLR_ANY) ?
+ "ClrAny" :
+ "SetAny")));
+ const char *const p_dev_name _unused = "NA";
+ const char *const p_bus_name _unused =
+ get_bus_name(module_get_bus(p->mp_owner->mp_owner));
+ uint32_t n_reg_addr _unused = register_get_address(p->mp_owner);
+
+ uint32_t n_reg_mask _unused =
+ (((1 << p->mn_bit_width) - 1) << p->mn_bit_pos_low);
+
+ NT_LOG(DBG, NTHW,
+ "Register::Field::wait%s32(Dev: %s, Bus: %s, Addr: 0x%08X, Mask: 0x%08X, Iterations: %d, Interval: %d)\n",
+ p_cond_name, p_dev_name, p_bus_name, n_reg_addr, n_reg_mask,
+ n_poll_iterations, n_poll_interval);
+ }
+
+ while (true) {
+ uint32_t val = field_get_updated(p);
+
+ if (e_match == FIELD_MATCH_SET_ANY && val != 0) {
+ return 0;
+ } else if (e_match == FIELD_MATCH_SET_ALL && val == n_mask) {
+ return 0;
+ } else if (e_match == FIELD_MATCH_CLR_ALL && val == 0) {
+ return 0;
+ } else if (e_match == FIELD_MATCH_CLR_ANY) {
+ uint32_t mask = field_get_mask(p);
+
+ if (val != mask)
+ return 0;
+ }
+
+ n_poll_iterations--;
+ if (n_poll_iterations <= 0)
+ return -1;
+ NT_OS_WAIT_USEC(n_poll_interval);
+ }
+ return 0;
+}
+
+int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_SET_ALL, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_CLR_ALL, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_SET_ANY, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_CLR_ANY, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value,
+ uint32_t n_wait_cond_mask, int n_poll_iterations,
+ int n_poll_interval)
+{
+ if (n_poll_iterations == -1)
+ n_poll_iterations = 10000;
+ if (n_poll_interval == -1)
+ n_poll_interval = 100;
+
+ while (true) {
+ uint32_t val = field_get_updated(p);
+
+ if (val == (n_wait_cond_value & n_wait_cond_mask))
+ break;
+ n_poll_iterations--;
+ if (n_poll_iterations <= 0)
+ return -1;
+ NT_OS_WAIT_USEC(n_poll_interval);
+ }
+ return 0;
+}
+
+void field_dump(const nt_field_t *p _unused)
+{
+ NT_LOG(DBG, NTHW, "%s: %02d: %02d %02d %02d: %02d: %X\n", __func__,
+ p->m_id, p->mn_bit_pos_low, (p->mn_bit_pos_low + p->mn_bit_width),
+ p->mn_bit_width, p->mn_words, p->m_reset_val);
+}
+
+void field_dump_val(const nt_field_t *p)
+{
+ int i;
+ uint32_t buf[32];
+
+ field_get_val(p, buf, p->mn_words);
+ NT_LOG(DBG, NTHW, " @%d:", p->m_first_bit + p->m_first_word * 32);
+ NT_LOG(DBG, NTHW, "%X", buf[p->mn_words - 1]);
+ for (i = p->mn_words - 1; i > 0; i--)
+ NT_LOG(DBG, NTHW, "%08X", buf[i - 1]);
+ NT_LOG(DBG, NTHW, "\n");
+}
+
+void field_dump_init(const nt_fpga_field_init_t *p _unused)
+{
+ NT_LOG(DBG, NTHW, "%s: %02d: %02d %02d %02d: 0x%" PRIX64 "\n", __func__,
+ p->id, p->low, p->low + p->bw, p->bw, p->reset_val);
+}
+
+/*
+ * nthw fpga model helpers
+ */
+
+nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident)
+{
+ nt_fpga_mgr_t *p_fpga_mgr = NULL;
+ nt_fpga_t *p_fpga = NULL;
+ int n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id;
+ char s_fpga_prod_ver_rev_str[32];
+
+ p_fpga_mgr = fpga_mgr_new();
+ fpga_mgr_init(p_fpga_mgr);
+ p_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info);
+
+ n_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident);
+ n_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident);
+ n_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident);
+ n_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident);
+
+ snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str),
+ "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id,
+ n_fpga_rev_id);
+
+ if (p_fpga == NULL) {
+ NT_LOG(ERR, NTHW, "%s: no match for FPGA: %s\n", __func__,
+ s_fpga_prod_ver_rev_str);
+ /* do not return here... */
+ }
+
+ if (p_fpga_mgr) {
+ fpga_mgr_delete(p_fpga_mgr);
+ p_fpga_mgr = NULL;
+ }
+
+ return p_fpga;
+}
+
+nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance)
+{
+ nt_module_t *p_mod = fpga_query_module(p_fpga, n_mod, n_instance);
+ return p_mod;
+}
+
+nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg)
+{
+ nt_register_t *p_reg = module_get_register(p_mod, n_reg);
+ return p_reg;
+}
+
+nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld)
+{
+ nt_field_t *p_fld = register_get_field(p_reg, n_fld);
+ return p_fld;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.h b/drivers/net/ntnic/nthw/nthw_fpga_model.h
new file mode 100644
index 0000000000..b00b7b6cfa
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_fpga_model.h
@@ -0,0 +1,308 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_MODEL_H__
+#define __NTHW_FPGA_MODEL_H__
+
+#include <stdbool.h>
+#include <stdio.h>
+#include "fpga_model.h"
+
+#ifndef FPGAID_TO_PRODUCTCODE
+#define FPGAID_TO_PRODUCTTYPE(fpga_id) ((uint16_t)((fpga_id) >> 32) & 0xFF)
+#define FPGAID_TO_PRODUCTCODE(fpga_id) ((uint16_t)((fpga_id) >> 16) & 0xFFFF)
+#define FPGAID_TO_VERSIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 8 & 0xFF))
+#define FPGAID_TO_REVISIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 0 & 0xFF))
+#endif
+
+#define VERSION_PACKED64(_major_, _minor_) \
+ ((((uint64_t)(_major_) & 0xFFFFFFFF) << 32) | ((_minor_) & 0xFFFFFFFF))
+
+enum debug_mode { NO_DEBUG, ON_READ, ON_WRITE };
+
+enum nthw_bus_type {
+ NTHW_BUS_UNKNOWN,
+ NTHW_BUS_BAR,
+ NTHW_BUS_PCI,
+ NTHW_BUS_NMB,
+ NTHW_BUS_NDM,
+ NTHW_BUS_RAB0,
+ NTHW_BUS_RAB1,
+ NTHW_BUS_RAB2
+};
+
+struct nt_fpga_s;
+
+struct nt_param_s;
+
+struct nt_module_s;
+
+struct nt_register_s;
+
+struct nt_field_s;
+
+struct nt_fpga_mgr_s {
+ int mn_fpgas;
+ struct nt_fpga_prod_init **mpa_fpga_prod_init;
+};
+
+typedef struct nt_fpga_mgr_s nt_fpga_mgr_t;
+
+struct nt_fpga_s {
+ struct fpga_info_s *p_fpga_info;
+
+ int m_item_id;
+ int m_product_id;
+ int m_fpga_version;
+ int m_fpga_revision;
+ int m_fpga_patch_no;
+ int m_fpga_build_no;
+ uint32_t m_fpga_build_time;
+
+ int mn_params;
+ struct nt_param_s **mpa_params;
+
+ int mn_modules;
+ struct nt_module_s **mpa_modules;
+
+ nt_fpga_prod_init_t *mp_init;
+
+ int m_debug_mode;
+};
+
+typedef struct nt_fpga_s nt_fpga_t;
+
+struct nt_param_s {
+ nt_fpga_t *mp_owner;
+
+ int param_id;
+ int param_value;
+
+ nt_fpga_prod_param_t *mp_init;
+};
+
+typedef struct nt_param_s nt_param_t;
+
+struct nt_module_s {
+ nt_fpga_t *mp_owner;
+
+ int m_mod_id;
+
+ int m_instance;
+
+ int m_mod_def_id;
+ int m_major_version;
+ int m_minor_version;
+
+ int m_bus;
+ uint32_t m_addr_base;
+
+ int m_debug_mode;
+
+ int mn_registers;
+ struct nt_register_s **mpa_registers;
+
+ nt_fpga_module_init_t *mp_init;
+};
+
+typedef struct nt_module_s nt_module_t;
+
+struct nt_register_s {
+ nt_module_t *mp_owner;
+
+ uint32_t m_id;
+
+ uint32_t mn_bit_width;
+ uint32_t mn_addr_rel;
+ uint32_t m_addr;
+ uint32_t m_type;
+ uint32_t m_len;
+
+ int m_debug_mode;
+
+ int mn_fields;
+ struct nt_field_s **mpa_fields;
+
+ uint32_t *mp_shadow;
+ bool *mp_dirty;
+
+ nt_fpga_register_init_t *mp_init;
+};
+
+typedef struct nt_register_s nt_register_t;
+
+struct nt_field_s {
+ nt_register_t *mp_owner;
+
+ uint32_t m_id;
+
+ uint32_t mn_bit_width;
+ uint32_t mn_bit_pos_low;
+ uint32_t m_reset_val;
+ uint32_t m_first_word;
+ uint32_t m_first_bit;
+ uint32_t m_front_mask;
+ uint32_t m_body_length;
+ uint32_t mn_words;
+ uint32_t m_tail_mask;
+
+ int m_debug_mode;
+
+ nt_fpga_field_init_t *mp_init;
+};
+
+typedef struct nt_field_s nt_field_t;
+
+nt_fpga_mgr_t *fpga_mgr_new(void);
+void fpga_mgr_init(nt_fpga_mgr_t *p);
+void fpga_mgr_delete(nt_fpga_mgr_t *p);
+nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id,
+ struct fpga_info_s *p_fpga_info);
+
+void fpga_mgr_log_dump(nt_fpga_mgr_t *p);
+void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *out, int detail_level);
+
+nt_fpga_t *fpga_new(void);
+void fpga_delete(nt_fpga_t *p);
+void fpga_delete_all(nt_fpga_t *p);
+void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init,
+ struct fpga_info_s *p_fpga_info);
+
+int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id,
+ const int default_value);
+int fpga_get_product_id(const nt_fpga_t *p);
+int fpga_get_fpga_version(const nt_fpga_t *p);
+int fpga_get_fpga_revision(const nt_fpga_t *p);
+nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance);
+nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance);
+bool fpga_query(nt_fpga_t *p, int id, int instance);
+void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode);
+
+void fpga_log_info(const nt_fpga_t *p);
+void fpga_dump(const nt_fpga_t *p);
+void fpga_dump_params(const nt_fpga_t *p);
+void fpga_dump_modules(const nt_fpga_t *p);
+
+nt_param_t *param_new(void);
+void param_delete(nt_param_t *p);
+void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init);
+
+void param_dump(const nt_param_t *p);
+
+nt_module_t *module_new(void);
+void module_delete(nt_module_t *p);
+void module_init(nt_module_t *p, nt_fpga_t *p_fpga,
+ nt_fpga_module_init_t *p_init);
+void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance,
+ int debug_mode);
+
+int module_get_major_version(const nt_module_t *p);
+int module_get_minor_version(const nt_module_t *p);
+uint64_t module_get_version_packed64(const nt_module_t *p);
+bool module_is_version_newer(const nt_module_t *p, int major_version,
+ int minor_version);
+
+int module_get_bus(const nt_module_t *p);
+nt_register_t *module_get_register(nt_module_t *p, uint32_t id);
+nt_register_t *module_query_register(nt_module_t *p, uint32_t id);
+int module_get_debug_mode(const nt_module_t *p);
+void module_set_debug_mode(nt_module_t *p, unsigned int debug_mode);
+uint32_t module_get_addr_base(const nt_module_t *p);
+void module_unsuppported(const nt_module_t *p);
+
+void module_dump(const nt_module_t *p);
+void module_dump_registers(const nt_module_t *p);
+
+nt_register_t *register_new(void);
+void register_delete(nt_register_t *p);
+void register_init(nt_register_t *p, nt_module_t *p_module,
+ nt_fpga_register_init_t *p_init);
+
+nt_field_t *register_get_field(const nt_register_t *p, uint32_t id);
+nt_field_t *register_query_field(const nt_register_t *p, uint32_t id);
+
+uint32_t register_get_address(const nt_register_t *p);
+uint32_t register_get_addr_rel(const nt_register_t *p);
+int register_get_bit_width(const nt_register_t *p);
+int register_get_debug_mode(const nt_module_t *p);
+void register_set_debug_mode(nt_register_t *p, unsigned int debug_mode);
+
+void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len);
+uint32_t register_get_val32(const nt_register_t *p);
+uint32_t register_get_val_updated32(const nt_register_t *p);
+
+void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len);
+void register_set_val_flush(nt_register_t *p, const uint32_t *p_data,
+ uint32_t len);
+
+void register_make_dirty(nt_register_t *p);
+void register_update(const nt_register_t *p);
+void register_reset(const nt_register_t *p);
+void register_flush(const nt_register_t *p, uint32_t cnt);
+void register_clr(nt_register_t *p);
+void register_set(nt_register_t *p);
+
+void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1,
+ uint64_t *tsc2);
+
+void register_dump(const nt_register_t *p);
+void register_dump_fields(const nt_register_t *p);
+
+nt_field_t *field_new(void);
+void field_delete(nt_field_t *p);
+void field_init(nt_field_t *p, nt_register_t *p_reg,
+ const nt_fpga_field_init_t *p_init);
+
+int field_get_debug_mode(const nt_module_t *p);
+void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode);
+int field_get_bit_width(const nt_field_t *p);
+int field_get_bit_pos_low(const nt_field_t *p);
+int field_get_bit_pos_high(const nt_field_t *p);
+uint32_t field_get_mask(const nt_field_t *p);
+void field_reset(const nt_field_t *p);
+uint32_t field_get_reset_val(const nt_field_t *p);
+void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len);
+void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len);
+void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data,
+ uint32_t len);
+uint32_t field_get_val_mask(const nt_field_t *p);
+uint32_t field_get_val32(const nt_field_t *p);
+uint32_t field_get_updated(const nt_field_t *p);
+void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2);
+void field_update_register(const nt_field_t *p);
+void field_flush_register(const nt_field_t *p);
+void field_set_val32(const nt_field_t *p, uint32_t val);
+void field_set_val_flush32(const nt_field_t *p, uint32_t val);
+void field_clr_all(const nt_field_t *p);
+void field_clr_flush(const nt_field_t *p);
+void field_set_all(const nt_field_t *p);
+void field_set_flush(const nt_field_t *p);
+
+int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+
+int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+
+int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value,
+ uint32_t n_wait_cond_mask, int n_poll_iterations,
+ int n_poll_interval);
+
+void field_dump(const nt_field_t *p);
+void field_dump_val(const nt_field_t *p);
+void field_dump_init(const nt_fpga_field_init_t *p);
+
+/*
+ * nthw helpers
+ */
+nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident);
+nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance);
+nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg);
+nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld);
+
+#endif /* __NTHW_FPGA_MODEL_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_helper.h b/drivers/net/ntnic/nthw/nthw_helper.h
new file mode 100644
index 0000000000..22f6a0d471
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_helper.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_HELPER_H__
+#define __NTHW_HELPER_H__
+
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+#endif /* __NTHW_HELPER_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_platform.c b/drivers/net/ntnic/nthw/nthw_platform.c
new file mode 100644
index 0000000000..203947e03a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_platform.c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_platform_drv.h"
+
+nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id)
+{
+ switch (n_pci_device_id) {
+ case NT_HW_PCI_DEVICE_ID_NT40E3:
+ return NT_HW_ADAPTER_ID_NT40E3;
+ case NT_HW_PCI_DEVICE_ID_NT100E3:
+ return NT_HW_ADAPTER_ID_NT100E3;
+ case NT_HW_PCI_DEVICE_ID_NT80E3:
+ return NT_HW_ADAPTER_ID_NT80E3;
+ case NT_HW_PCI_DEVICE_ID_NT40A00:
+ return NT_HW_ADAPTER_ID_NT40E3;
+ case NT_HW_PCI_DEVICE_ID_NT40A01:
+ return NT_HW_ADAPTER_ID_NT40E3;
+ case NT_HW_PCI_DEVICE_ID_NT200E3:
+ return NT_HW_ADAPTER_ID_NT200E3;
+ case NT_HW_PCI_DEVICE_ID_NT200A01:
+ return NT_HW_ADAPTER_ID_NT200A01;
+ case NT_HW_PCI_DEVICE_ID_NT200D01:
+ return NT_HW_ADAPTER_ID_NT200D01;
+ case NT_HW_PCI_DEVICE_ID_NT200A02:
+ return NT_HW_ADAPTER_ID_NT200A02;
+ case NT_HW_PCI_DEVICE_ID_NT50B01:
+ return NT_HW_ADAPTER_ID_NT50B01;
+ case NT_HW_PCI_DEVICE_ID_NT100A01:
+ return NT_HW_ADAPTER_ID_NT100A01;
+ default:
+ return NT_HW_ADAPTER_ID_UNKNOWN;
+ }
+}
diff --git a/drivers/net/ntnic/nthw/nthw_platform_drv.h b/drivers/net/ntnic/nthw/nthw_platform_drv.h
new file mode 100644
index 0000000000..fee2dc4853
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_platform_drv.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PLATFORM_DRV_H__
+#define __NTHW_PLATFORM_DRV_H__
+
+#include "nthw_helper.h"
+
+#define NT_HW_PCI_VENDOR_ID (0x18f4)
+
+#define NT_HW_PCI_DEVICE_ID_NT40E3 (0x145)
+#define NT_HW_PCI_DEVICE_ID_NT100E3 (0x155)
+#define NT_HW_PCI_DEVICE_ID_NT80E3 (0x165)
+#define NT_HW_PCI_DEVICE_ID_NT40A00 (0x175)
+#define NT_HW_PCI_DEVICE_ID_NT40A01 (0x185)
+#define NT_HW_PCI_DEVICE_ID_NT200E3 (0x195)
+#define NT_HW_PCI_DEVICE_ID_NT200A01 (0x1A5)
+#define NT_HW_PCI_DEVICE_ID_NT200D01 (0x1B5)
+#define NT_HW_PCI_DEVICE_ID_NT200A02 (0x1C5)
+#define NT_HW_PCI_DEVICE_ID_NT50B01 (0x1D5)
+#define NT_HW_PCI_DEVICE_ID_NT100A01 (0x1E5)
+
+enum nthw_adapter_id_e {
+ NT_HW_ADAPTER_ID_UNKNOWN = 0,
+ NT_HW_ADAPTER_ID_NT40E3,
+ NT_HW_ADAPTER_ID_NT40A01 = NT_HW_ADAPTER_ID_NT40E3,
+ NT_HW_ADAPTER_ID_NT50B01,
+ NT_HW_ADAPTER_ID_NT80E3,
+ NT_HW_ADAPTER_ID_NT100E3,
+ NT_HW_ADAPTER_ID_NT100A01,
+ NT_HW_ADAPTER_ID_NT200E3,
+ NT_HW_ADAPTER_ID_NT200A01,
+ NT_HW_ADAPTER_ID_NT200D01,
+ NT_HW_ADAPTER_ID_NT200A02,
+};
+
+typedef enum nthw_adapter_id_e nthw_adapter_id_t;
+
+nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id);
+
+#endif /* __NTHW_PLATFORM_DRV_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_profile.h b/drivers/net/ntnic/nthw/nthw_profile.h
new file mode 100644
index 0000000000..2fcb7b4adf
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_profile.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PROFILE_H__
+#define __NTHW_PROFILE_H__
+
+enum fpga_info_profile {
+ FPGA_INFO_PROFILE_UNKNOWN = 0,
+ FPGA_INFO_PROFILE_VSWITCH = 1,
+ FPGA_INFO_PROFILE_INLINE = 2,
+ FPGA_INFO_PROFILE_CAPTURE = 3,
+};
+
+#endif /* __NTHW_PROFILE_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_rac.c b/drivers/net/ntnic/nthw/nthw_rac.c
new file mode 100644
index 0000000000..fc50b1a50b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_rac.c
@@ -0,0 +1,976 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_rac.h"
+
+#include <pthread.h>
+
+/*
+ * Prevent that RAB echo debug trace ever gets into a release build
+ */
+#if defined(DEBUG)
+#undef RAB_DEBUG_ECHO
+#else
+#undef RAB_DEBUG_ECHO
+#endif /* DEBUG */
+
+#define RAB_DMA_WAIT (1000000)
+#define RAB_DMA_BUF_CNT (0x4000)
+
+#define RAB_READ (0x01)
+#define RAB_WRITE (0x02)
+#define RAB_ECHO (0x08)
+#define RAB_COMPLETION (0x0F)
+
+#define RAB_READ_ECHO (RAB_READ | RAB_ECHO)
+#define RAB_WRITE_ECHO (RAB_WRITE | RAB_ECHO)
+
+#define RAB_OPR_LO (28)
+#define RAB_OPR_HI (31)
+#define RAB_OPR_BW (4)
+
+#define RAB_CNT_LO (20)
+#define RAB_CNT_HI (27)
+#define RAB_CNT_BW (8)
+
+#define RAB_BUSID_LO (16)
+#define RAB_BUSID_HI (19)
+#define RAB_BUSID_BW (4)
+
+#define RAB_ADDR_LO (0)
+#define RAB_ADDR_HI (15)
+#define RAB_ADDR_BW (16)
+
+nthw_rac_t *nthw_rac_new(void)
+{
+ nthw_rac_t *p = malloc(sizeof(nthw_rac_t));
+
+ memset(p, 0, sizeof(nthw_rac_t));
+ return p;
+}
+
+void nthw_rac_delete(nthw_rac_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_rac_t));
+ free(p);
+ }
+}
+
+int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info)
+{
+ assert(p_fpga_info);
+
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_RAC, 0);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RAC %d: no such instance\n",
+ p_adapter_id_str, 0);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mp_mod_rac = mod;
+
+ {
+ /*
+ * RAC is a primary communication channel
+ * turn off debug by default
+ * except for rac_rab_init
+ */
+ const int n_debug_mode = module_get_debug_mode(p->mp_mod_rac);
+
+ if (n_debug_mode && n_debug_mode <= 0xff) {
+ module_set_debug_mode(p->mp_mod_rac, 0);
+ register_set_debug_mode(p->mp_reg_rab_init, n_debug_mode);
+ }
+ }
+
+ /* Params */
+ p->mn_param_rac_rab_interfaces =
+ fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_INTERFACES, 3);
+ NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d\n", p_adapter_id_str,
+ p->mn_param_rac_rab_interfaces);
+
+ p->mn_param_rac_rab_ob_update =
+ fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_OB_UPDATE, 0);
+ NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_OB_UPDATE=%d\n", p_adapter_id_str,
+ p->mn_param_rac_rab_ob_update);
+
+ /* Optional dummy test registers */
+ p->mp_reg_dummy0 = module_query_register(p->mp_mod_rac, RAC_DUMMY0);
+ p->mp_reg_dummy1 = module_query_register(p->mp_mod_rac, RAC_DUMMY1);
+ p->mp_reg_dummy2 = module_query_register(p->mp_mod_rac, RAC_DUMMY2);
+
+ p->mp_reg_rab_init = module_get_register(p->mp_mod_rac, RAC_RAB_INIT);
+ p->mp_fld_rab_init = register_get_field(p->mp_reg_rab_init, RAC_RAB_INIT_RAB);
+ p->mn_fld_rab_init_bw = field_get_bit_width(p->mp_fld_rab_init);
+ p->mn_fld_rab_init_mask = field_get_mask(p->mp_fld_rab_init);
+
+ /* RAC_RAB_INIT_RAB reg/field sanity checks: */
+ assert(p->mn_fld_rab_init_mask == ((1UL << p->mn_fld_rab_init_bw) - 1));
+ assert(p->mn_fld_rab_init_bw == p->mn_param_rac_rab_interfaces);
+
+ p->mp_reg_dbg_ctrl = module_query_register(p->mp_mod_rac, RAC_DBG_CTRL);
+ if (p->mp_reg_dbg_ctrl) {
+ p->mp_fld_dbg_ctrl =
+ register_query_field(p->mp_reg_dbg_ctrl, RAC_DBG_CTRL_C);
+ } else {
+ p->mp_fld_dbg_ctrl = NULL;
+ }
+ p->mp_reg_dbg_data = module_query_register(p->mp_mod_rac, RAC_DBG_DATA);
+ if (p->mp_reg_dbg_data) {
+ p->mp_fld_dbg_data =
+ register_query_field(p->mp_reg_dbg_data, RAC_DBG_DATA_D);
+ } else {
+ p->mp_reg_dbg_data = NULL;
+ }
+ p->mp_reg_rab_ib_data = module_get_register(p->mp_mod_rac, RAC_RAB_IB_DATA);
+ p->mp_fld_rab_ib_data =
+ register_get_field(p->mp_reg_rab_ib_data, RAC_RAB_IB_DATA_D);
+
+ p->mp_reg_rab_ob_data = module_get_register(p->mp_mod_rac, RAC_RAB_OB_DATA);
+ p->mp_fld_rab_ob_data =
+ register_get_field(p->mp_reg_rab_ob_data, RAC_RAB_OB_DATA_D);
+
+ p->mp_reg_rab_buf_free = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_FREE);
+ p->mp_fld_rab_buf_free_ib_free =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_FREE);
+ p->mp_fld_rab_buf_free_ib_ovf =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_OVF);
+ p->mp_fld_rab_buf_free_ob_free =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_FREE);
+ p->mp_fld_rab_buf_free_ob_ovf =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_OVF);
+ p->mp_fld_rab_buf_free_timeout =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_TIMEOUT);
+
+ p->mp_reg_rab_buf_used = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_USED);
+ p->mp_fld_rab_buf_used_ib_used =
+ register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_IB_USED);
+ p->mp_fld_rab_buf_used_ob_used =
+ register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_OB_USED);
+ p->mp_fld_rab_buf_used_flush =
+ register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_FLUSH);
+
+ /*
+ * RAC_RAB_DMA regs are optional - only found in real NT4GA - not found in 9231/9232 and
+ * earlier
+ */
+ p->mp_reg_rab_dma_ib_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_LO);
+ p->mp_fld_rab_dma_ib_lo_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ib_lo, RAC_RAB_DMA_IB_LO_PHYADDR);
+
+ p->mp_reg_rab_dma_ib_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_HI);
+ p->mp_fld_rab_dma_ib_hi_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ib_hi, RAC_RAB_DMA_IB_HI_PHYADDR);
+
+ p->mp_reg_rab_dma_ob_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_LO);
+ p->mp_fld_rab_dma_ob_lo_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ob_lo, RAC_RAB_DMA_OB_LO_PHYADDR);
+
+ p->mp_reg_rab_dma_ob_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_HI);
+ p->mp_fld_rab_dma_ob_hi_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ob_hi, RAC_RAB_DMA_OB_HI_PHYADDR);
+
+ p->mp_reg_rab_dma_ib_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_WR);
+ p->mp_fld_rab_dma_ib_wr_ptr =
+ register_get_field(p->mp_reg_rab_dma_ib_wr, RAC_RAB_DMA_IB_WR_PTR);
+
+ p->mp_reg_rab_dma_ib_rd = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_RD);
+ p->mp_fld_rab_dma_ib_rd_ptr =
+ register_get_field(p->mp_reg_rab_dma_ib_rd, RAC_RAB_DMA_IB_RD_PTR);
+
+ p->mp_reg_rab_dma_ob_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_WR);
+ p->mp_fld_rab_dma_ob_wr_ptr =
+ register_get_field(p->mp_reg_rab_dma_ob_wr, RAC_RAB_DMA_OB_WR_PTR);
+
+ p->rac_rab_init_addr = register_get_address(p->mp_reg_rab_init);
+ p->rac_rab_ib_data_addr = register_get_address(p->mp_reg_rab_ib_data);
+ p->rac_rab_ob_data_addr = register_get_address(p->mp_reg_rab_ob_data);
+ p->rac_rab_buf_free_addr = register_get_address(p->mp_reg_rab_buf_free);
+ p->rac_rab_buf_used_addr = register_get_address(p->mp_reg_rab_buf_used);
+
+ /*
+ * RAC_RAB_DMA regs are optional - only found in real NT4GA -
+ * not found in 9231/9232 and earlier
+ */
+
+ p->rac_rab_dma_ib_lo_addr = register_get_address(p->mp_reg_rab_dma_ib_lo);
+ p->rac_rab_dma_ib_hi_addr = register_get_address(p->mp_reg_rab_dma_ib_hi);
+ p->rac_rab_dma_ob_lo_addr = register_get_address(p->mp_reg_rab_dma_ob_lo);
+ p->rac_rab_dma_ob_hi_addr = register_get_address(p->mp_reg_rab_dma_ob_hi);
+ p->rac_rab_dma_ib_rd_addr = register_get_address(p->mp_reg_rab_dma_ib_rd);
+ p->rac_rab_dma_ob_wr_addr = register_get_address(p->mp_reg_rab_dma_ob_wr);
+ p->rac_rab_dma_ib_wr_addr = register_get_address(p->mp_reg_rab_dma_ib_wr);
+
+ p->rac_rab_buf_free_ib_free_mask =
+ field_get_mask(p->mp_fld_rab_buf_free_ib_free);
+ p->rac_rab_buf_free_ob_free_mask =
+ field_get_mask(p->mp_fld_rab_buf_free_ob_free);
+ p->rac_rab_buf_used_ib_used_mask =
+ field_get_mask(p->mp_fld_rab_buf_used_ib_used);
+ p->rac_rab_buf_used_ob_used_mask =
+ field_get_mask(p->mp_fld_rab_buf_used_ob_used);
+
+ p->rac_rab_buf_used_flush_mask = field_get_mask(p->mp_fld_rab_buf_used_flush);
+
+ p->rac_rab_buf_used_ob_used_low =
+ field_get_bit_pos_low(p->mp_fld_rab_buf_used_ob_used);
+
+ p->mp_reg_rab_nmb_rd = module_query_register(p->mp_mod_rac, RAC_NMB_RD_ADR);
+ if (p->mp_reg_rab_nmb_rd)
+ p->rac_nmb_rd_adr_addr = register_get_address(p->mp_reg_rab_nmb_rd);
+
+ p->mp_reg_rab_nmb_data = module_query_register(p->mp_mod_rac, RAC_NMB_DATA);
+ if (p->mp_reg_rab_nmb_data)
+ p->rac_nmb_data_addr = register_get_address(p->mp_reg_rab_nmb_data);
+
+ p->mp_reg_rab_nmb_wr = module_query_register(p->mp_mod_rac, RAC_NMB_WR_ADR);
+ if (p->mp_reg_rab_nmb_wr)
+ p->rac_nmb_wr_adr_addr = register_get_address(p->mp_reg_rab_nmb_wr);
+
+ p->mp_reg_rab_nmb_status =
+ module_query_register(p->mp_mod_rac, RAC_NMB_STATUS);
+ if (p->mp_reg_rab_nmb_status) {
+ p->rac_nmb_status_addr =
+ register_get_address(p->mp_reg_rab_nmb_status);
+ }
+
+ p->m_dma = NULL;
+
+ pthread_mutex_init(&p->m_mutex, NULL);
+
+ return 0;
+}
+
+int nthw_rac_get_rab_interface_count(const nthw_rac_t *p)
+{
+ return p->mn_param_rac_rab_interfaces;
+}
+
+static inline int nthw_rac_wait_for_rab_done(const nthw_rac_t *p, uint32_t address,
+ uint32_t word_cnt)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ uint32_t used = 0;
+ uint32_t retry;
+
+ for (retry = 0; retry < 100000; retry++) {
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &used);
+ used = (used & p->rac_rab_buf_used_ob_used_mask) >>
+ p->rac_rab_buf_used_ob_used_low;
+ if (used >= word_cnt)
+ break;
+ }
+
+ if (used < word_cnt) {
+ NT_LOG(ERR, NTHW,
+ "%s: Fail rab bus r/w addr=0x%08X used=%x wordcount=%d\n",
+ p_adapter_id_str, address, used, word_cnt);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * NT_PCI_REG_P9xyz_RAC_RAB_INIT
+ *
+ * Initializes (resets) the programmable registers on the Register Access Busses (RAB).
+ * This initialization must be performed by software as part of the driver load procedure.
+ *
+ * Bit n of this field initializes the programmable registers on RAB interface n.
+ * Software must write one to the bit and then clear the bit again.
+ *
+ * All RAB module registers will be reset to their defaults.
+ * This includes the product specific RESET module (eg RST9xyz)
+ * As a consequence of this behavior the official reset sequence
+ * must be excersised - as all RAB modules will be held in reset.
+ */
+int nthw_rac_rab_init(nthw_rac_t *p, uint32_t n_rab_intf_mask)
+{
+ /*
+ * Write rac_rab_init
+ * Perform operation twice - first to get trace of operation -
+ * second to get things done...
+ */
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ field_set_val_flush32(p->mp_fld_rab_init, n_rab_intf_mask);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_init_addr, n_rab_intf_mask);
+ return 0;
+}
+
+int nthw_rac_rab_reset(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ const char *const p_adapter_id_str _unused = p_fpga_info->mp_adapter_id_str;
+
+ /* RAC RAB bus "flip/flip" reset */
+ const int n_rac_rab_bus_count = nthw_rac_get_rab_interface_count(p);
+ const int n_rac_rab_bus_mask = (1 << n_rac_rab_bus_count) - 1;
+
+ NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d (0x%02X)\n",
+ p_adapter_id_str, n_rac_rab_bus_count, n_rac_rab_bus_mask);
+ assert(n_rac_rab_bus_count);
+ assert(n_rac_rab_bus_mask);
+
+ /* RAC RAB bus "flip/flip" reset first stage - new impl (ref RMT#37020) */
+ nthw_rac_rab_init(p, 0);
+ nthw_rac_rab_init(p, n_rac_rab_bus_mask);
+ nthw_rac_rab_init(p, n_rac_rab_bus_mask & ~0x01);
+
+ return 0;
+}
+
+int nthw_rac_rab_setup(nthw_rac_t *p)
+{
+ int rc = 0;
+
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ uint32_t n_dma_buf_size = 2L * RAB_DMA_BUF_CNT * sizeof(uint32_t);
+ const size_t align_size = ALIGN_SIZE(n_dma_buf_size);
+ int numa_node = p_fpga_info->numa_node;
+ uint64_t dma_addr;
+ uint32_t buf;
+
+ if (!p->m_dma) {
+ struct nt_dma_s *vfio_dma;
+ /* FPGA needs Page alignment (4K) */
+ vfio_dma = nt_dma_alloc(align_size, 0x1000, numa_node);
+
+ if (vfio_dma == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: nt_dma_alloc failed\n",
+ __func__);
+ return -1;
+ }
+ p->m_dma_in_buf = (uint32_t *)vfio_dma->addr;
+ p->m_dma_out_buf = p->m_dma_in_buf + RAB_DMA_BUF_CNT;
+ p->m_dma = vfio_dma;
+ }
+
+ /* Setup DMA on the adapter */
+ dma_addr = p->m_dma->iova;
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_lo_addr,
+ dma_addr & 0xffffffff);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_hi_addr,
+ (uint32_t)(dma_addr >> 32) & 0xffffffff);
+ dma_addr += RAB_DMA_BUF_CNT * sizeof(uint32_t);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_lo_addr,
+ dma_addr & 0xffffffff);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_hi_addr,
+ (uint32_t)(dma_addr >> 32) & 0xffffffff);
+
+ /* Set initial value of internal pointers */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ib_rd_addr, &buf);
+ p->m_dma_in_ptr_wr = (uint16_t)(buf / sizeof(uint32_t));
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ob_wr_addr, &buf);
+ p->m_dma_out_ptr_rd = (uint16_t)(buf / sizeof(uint32_t));
+ p->m_in_free = RAB_DMA_BUF_CNT;
+
+ return rc;
+}
+
+int nthw_rac_rab_dma_begin(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ if (p->m_dma_active) {
+ pthread_mutex_unlock(&p->m_mutex);
+ NT_LOG(ERR, NTHW,
+ "%s: DMA begin requested, but a DMA transaction is already active\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ p->m_dma_active = true;
+
+ return 0;
+}
+
+static void nthw_rac_rab_dma_activate(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;
+
+ /* Write completion word */
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] = completion;
+ p->m_dma_in_ptr_wr =
+ (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
+
+ /* Clear output completion word */
+ p->m_dma_out_buf[p->m_dma_out_ptr_rd] = 0;
+
+ /* _update DMA pointer and start transfer */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_wr_addr,
+ (uint32_t)(p->m_dma_in_ptr_wr * sizeof(uint32_t)));
+}
+
+static int nthw_rac_rab_dma_wait(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;
+ uint32_t i;
+
+ for (i = 0; i < RAB_DMA_WAIT; i++) {
+ NT_OS_WAIT_USEC_POLL(1);
+ if ((p->m_dma_out_buf[p->m_dma_out_ptr_rd] & completion) ==
+ completion)
+ break;
+ }
+
+ if (i == RAB_DMA_WAIT) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Unexpected value of completion (0x%08X)\n",
+ p_fpga_info->mp_adapter_id_str,
+ p->m_dma_out_buf[p->m_dma_out_ptr_rd]);
+ return -1;
+ }
+
+ p->m_dma_out_ptr_rd =
+ (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));
+ p->m_in_free = RAB_DMA_BUF_CNT;
+
+ return 0;
+}
+
+int nthw_rac_rab_dma_commit(nthw_rac_t *p)
+{
+ int ret;
+
+ if (!p->m_dma_active) {
+ /* Expecting mutex not to be locked! */
+ assert(0); /* alert developer that something is wrong */
+ return -1;
+ }
+
+ nthw_rac_rab_dma_activate(p);
+ ret = nthw_rac_rab_dma_wait(p);
+
+ p->m_dma_active = false;
+
+ pthread_mutex_unlock(&p->m_mutex);
+
+ return ret;
+}
+
+void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t *p_data)
+{
+ *p_data = *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr +
+ reg_addr);
+}
+
+void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t p_data)
+{
+ *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr) =
+ p_data;
+}
+
+int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ if (word_cnt == 0 || word_cnt > 256) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed rab dma write length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\n",
+ p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt,
+ p->m_in_free);
+ assert(0); /* alert developer that something is wrong */
+ return -1;
+ }
+
+ if (p->m_in_free < (word_cnt + 3)) {
+ /*
+ * No more memory available.
+ * nthw_rac_rab_dma_commit() needs to be called to start and finish pending
+ * transfers.
+ */
+ return -1;
+ }
+
+ p->m_in_free -= (word_cnt + 1);
+
+ /* Write the command word */
+#if defined(RAB_DEBUG_ECHO)
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_WRITE_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt + 1) &
+ (RAB_DMA_BUF_CNT - 1));
+#else
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_WRITE << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif
+ p->m_dma_in_ptr_wr =
+ (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
+
+ for (uint32_t i = 0; i < word_cnt; i++) {
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] = p_data[i];
+ p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) &
+ (RAB_DMA_BUF_CNT - 1));
+ }
+
+ return 0;
+}
+
+int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, struct dma_buf_ptr *buf_ptr)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ if (word_cnt == 0 || word_cnt > 256) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\n",
+ p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt,
+ p->m_in_free);
+ assert(0); /* alert developer that something is wrong */
+ return -1;
+ }
+
+ if ((word_cnt + 3) > RAB_DMA_BUF_CNT) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d: 0x%08X",
+ p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt);
+ return -1;
+ }
+
+ if (p->m_in_free < 3) {
+ /*
+ * No more memory available.
+ * nthw_rac_rab_dma_commit() needs to be called to start and finish pending
+ * transfers.
+ */
+ return -1;
+ }
+
+ p->m_in_free -= 1;
+
+ /* Write the command word */
+#if defined(RAB_DEBUG_ECHO)
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_READ_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ p->m_dma_out_ptr_rd =
+ (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));
+#else
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_READ << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif
+ p->m_dma_in_ptr_wr =
+ (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
+
+ buf_ptr->index = p->m_dma_out_ptr_rd;
+ buf_ptr->size = RAB_DMA_BUF_CNT;
+ buf_ptr->base = p->m_dma_out_buf;
+ p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt) &
+ (RAB_DMA_BUF_CNT - 1U));
+
+ return 0;
+}
+
+int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = 0;
+ uint32_t rab_oper_wr;
+ uint32_t rab_oper_cmpl;
+ uint32_t rab_echo_oper_cmpl;
+ uint32_t word_cnt_expected;
+ uint32_t buf_used;
+ uint32_t buf_free;
+ uint32_t in_buf_free;
+ uint32_t out_buf_free;
+
+ if (address > (1 << RAB_ADDR_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal address: value too large %d - max %d\n",
+ p_adapter_id_str, address, (1 << RAB_ADDR_BW));
+ return -1;
+ }
+
+ if (bus_id > (1 << RAB_BUSID_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal bus id: value too large %d - max %d\n",
+ p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));
+ return -1;
+ }
+
+ if (word_cnt == 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value is zero (%d)\n",
+ p_adapter_id_str, word_cnt);
+ return -1;
+ }
+
+ if (word_cnt > (1 << RAB_CNT_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value too large %d - max %d\n",
+ p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));
+ return -1;
+ }
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ if (p->m_dma_active) {
+ NT_LOG(ERR, NTHW, "%s: RAB: Illegal operation: DMA enabled\n",
+ p_adapter_id_str);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free);
+
+ in_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask;
+ out_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16;
+
+ /* Read buffer used register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used);
+
+ buf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask |
+ p->rac_rab_buf_used_ob_used_mask);
+
+ /*
+ * Verify that output buffer can hold one completion word,
+ * input buffer can hold the number of words to be written +
+ * one write and one completion command
+ * and that the input and output "used" buffer is 0
+ */
+ if ((out_buf_free >= 1 && (in_buf_free >= word_cnt + 2)) && buf_used == 0) {
+ uint32_t i;
+
+ word_cnt_expected = 0;
+
+ /* Compose write command */
+#if defined(RAB_DEBUG_ECHO)
+ rab_oper_wr =
+ (RAB_WRITE_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ word_cnt_expected += word_cnt + 1;
+#else
+ rab_oper_wr =
+ (RAB_WRITE << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif /* RAB_DEBUG_ECHO */
+
+ /* Write command */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ rab_oper_wr);
+
+ /* Write da to input buffer */
+ for (i = 0; i < word_cnt; i++) {
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ *p_data);
+ p_data++;
+ }
+
+ /* Compose completion command */
+ rab_oper_cmpl = (RAB_COMPLETION << RAB_OPR_LO);
+ word_cnt_expected++;
+
+ /* Write command */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ rab_oper_cmpl);
+
+ /* Wait until done */
+ if (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+#if defined(RAB_DEBUG_ECHO)
+ {
+ uint32_t rab_echo_oper_wr;
+
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,
+ &rab_echo_oper_wr);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info,
+ p->rac_rab_ob_data_addr, 0);
+ }
+ if (rab_oper_wr != rab_echo_oper_wr) {
+ NT_LOG(ERR, NTHW,
+ "%s: expected rab read echo oper (0x%08X) - read (0x%08X)\n",
+ p_adapter_id_str, rab_oper_wr, rab_echo_oper_wr);
+ }
+ }
+
+ {
+ /* Read data from output buffer */
+ uint32_t data;
+
+ for (i = 0; i < word_cnt; i++) {
+ nthw_rac_reg_read32(p_fpga_info,
+ p->rac_rab_ob_data_addr,
+ &data);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info,
+ p->rac_rab_ob_data_addr, 0);
+ }
+ }
+ }
+#endif /* RAB_DEBUG_ECHO */
+
+ /* Read completion from out buffer */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,
+ &rab_echo_oper_cmpl);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr,
+ 0);
+ }
+ if (rab_echo_oper_cmpl != rab_oper_cmpl) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Unexpected value of completion (0x%08X)- inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, rab_echo_oper_cmpl, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr,
+ &buf_free);
+ if (buf_free & 0x80000000) {
+ /* Clear Timeout and overflow bits */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr,
+ 0x0);
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ res = 0;
+ goto exit_unlock_res;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, word_cnt, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+exit_unlock_res:
+ pthread_mutex_unlock(&p->m_mutex);
+ return res;
+}
+
+int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, uint32_t *p_data)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = 0;
+ uint32_t rab_oper_rd;
+ uint32_t word_cnt_expected;
+ uint32_t buf_used;
+ uint32_t buf_free;
+ uint32_t in_buf_free;
+ uint32_t out_buf_free;
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ if (address > (1 << RAB_ADDR_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal address: value too large %d - max %d\n",
+ p_adapter_id_str, address, (1 << RAB_ADDR_BW));
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ if (bus_id > (1 << RAB_BUSID_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal bus id: value too large %d - max %d\n",
+ p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ if (word_cnt == 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value is zero (%d)\n",
+ p_adapter_id_str, word_cnt);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ if (word_cnt > (1 << RAB_CNT_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value too large %d - max %d\n",
+ p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free);
+
+ in_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask;
+ out_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16;
+
+ /* Read buffer used register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used);
+
+ buf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask |
+ p->rac_rab_buf_used_ob_used_mask);
+
+ /*
+ * Verify that output buffer can hold the number of words to be read,
+ * input buffer can hold one read command
+ * and that the input and output "used" buffer is 0
+ */
+ if ((out_buf_free >= word_cnt && in_buf_free >= 1) && buf_used == 0) {
+ word_cnt_expected = word_cnt;
+
+#if defined(RAB_DEBUG_ECHO)
+ rab_oper_rd =
+ (RAB_READ_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ word_cnt_expected++;
+#else
+ rab_oper_rd = (RAB_READ << RAB_OPR_LO) | (word_cnt << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif /* RAB_DEBUG_ECHO */
+
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ rab_oper_rd);
+
+ /* Wait until done */
+ if (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+#if defined(RAB_DEBUG_ECHO)
+ uint32_t rab_echo_oper_rd;
+
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,
+ &rab_echo_oper_rd);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr,
+ 0);
+ }
+ if (rab_oper_rd != rab_echo_oper_rd) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: expected rab read echo oper (0x%08X) - read (0x%08X)\n",
+ p_adapter_id_str, rab_oper_rd, rab_echo_oper_rd);
+ }
+#endif /* RAB_DEBUG_ECHO */
+
+ /* Read data from output buffer */
+ {
+ uint32_t i;
+
+ for (i = 0; i < word_cnt; i++) {
+ nthw_rac_reg_read32(p_fpga_info,
+ p->rac_rab_ob_data_addr,
+ p_data);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info,
+ p->rac_rab_ob_data_addr,
+ 0);
+ }
+ p_data++;
+ }
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr,
+ &buf_free);
+ if (buf_free & 0x80000000) {
+ /* Clear Timeout and overflow bits */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr,
+ 0x0);
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ res = 0;
+ goto exit_unlock_res;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, word_cnt, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+exit_unlock_res:
+ pthread_mutex_unlock(&p->m_mutex);
+ return res;
+}
+
+int nthw_rac_rab_flush(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ uint32_t data = 0;
+ uint32_t retry;
+ int res = 0;
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ /* Set the flush bit */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr,
+ p->rac_rab_buf_used_flush_mask);
+
+ /* Reset BUF FREE register */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr, 0x0);
+
+ /* Wait until OB_USED and IB_USED are 0 */
+ for (retry = 0; retry < 100000; retry++) {
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &data);
+
+ if ((data & 0xFFFFFFFF) == p->rac_rab_buf_used_flush_mask)
+ break;
+ }
+
+ if (data != p->rac_rab_buf_used_flush_mask) {
+ NT_LOG(ERR, NTHW, "%s: RAB: Rab bus flush error.\n",
+ p_adapter_id_str);
+ res = -1;
+ }
+
+ /* Clear flush bit when done */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr, 0x0);
+
+ pthread_mutex_unlock(&p->m_mutex);
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_rac.h b/drivers/net/ntnic/nthw/nthw_rac.h
new file mode 100644
index 0000000000..7e782516af
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_rac.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_RAC_H__
+#define __NTHW_RAC_H__
+
+#include "nt_util.h"
+#include "nthw_bus.h"
+
+struct nthw_rac {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_rac;
+
+ pthread_mutex_t m_mutex;
+
+ int mn_param_rac_rab_interfaces;
+ int mn_param_rac_rab_ob_update;
+
+ nt_register_t *mp_reg_dummy0;
+ nt_register_t *mp_reg_dummy1;
+ nt_register_t *mp_reg_dummy2;
+
+ nt_register_t *mp_reg_rab_init;
+ nt_field_t *mp_fld_rab_init;
+
+ int mn_fld_rab_init_bw;
+ uint32_t mn_fld_rab_init_mask;
+
+ nt_register_t *mp_reg_dbg_ctrl;
+ nt_field_t *mp_fld_dbg_ctrl;
+
+ nt_register_t *mp_reg_dbg_data;
+ nt_field_t *mp_fld_dbg_data;
+
+ nt_register_t *mp_reg_rab_ib_data;
+ nt_field_t *mp_fld_rab_ib_data;
+
+ nt_register_t *mp_reg_rab_ob_data;
+ nt_field_t *mp_fld_rab_ob_data;
+
+ nt_register_t *mp_reg_rab_buf_free;
+ nt_field_t *mp_fld_rab_buf_free_ib_free;
+ nt_field_t *mp_fld_rab_buf_free_ib_ovf;
+ nt_field_t *mp_fld_rab_buf_free_ob_free;
+ nt_field_t *mp_fld_rab_buf_free_ob_ovf;
+ nt_field_t *mp_fld_rab_buf_free_timeout;
+
+ nt_register_t *mp_reg_rab_buf_used;
+ nt_field_t *mp_fld_rab_buf_used_ib_used;
+ nt_field_t *mp_fld_rab_buf_used_ob_used;
+ nt_field_t *mp_fld_rab_buf_used_flush;
+
+ nt_register_t *mp_reg_rab_dma_ib_lo;
+ nt_field_t *mp_fld_rab_dma_ib_lo_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ib_hi;
+ nt_field_t *mp_fld_rab_dma_ib_hi_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ob_hi;
+ nt_field_t *mp_fld_rab_dma_ob_hi_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ob_lo;
+ nt_field_t *mp_fld_rab_dma_ob_lo_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ib_wr;
+ nt_field_t *mp_fld_rab_dma_ib_wr_ptr;
+
+ nt_register_t *mp_reg_rab_dma_ib_rd;
+ nt_field_t *mp_fld_rab_dma_ib_rd_ptr;
+
+ nt_register_t *mp_reg_rab_dma_ob_wr;
+ nt_field_t *mp_fld_rab_dma_ob_wr_ptr;
+
+ nt_register_t *mp_reg_rab_nmb_rd;
+ nt_register_t *mp_reg_rab_nmb_data;
+ nt_register_t *mp_reg_rab_nmb_wr;
+ nt_register_t *mp_reg_rab_nmb_status;
+
+ uint32_t rac_rab_init_addr;
+ uint32_t rac_rab_ib_data_addr;
+ uint32_t rac_rab_ob_data_addr;
+ uint32_t rac_rab_buf_free_addr;
+ uint32_t rac_rab_buf_used_addr;
+
+ uint32_t rac_rab_dma_ib_lo_addr;
+ uint32_t rac_rab_dma_ib_hi_addr;
+ uint32_t rac_rab_dma_ob_lo_addr;
+ uint32_t rac_rab_dma_ob_hi_addr;
+ uint32_t rac_rab_dma_ib_rd_addr;
+ uint32_t rac_rab_dma_ob_wr_addr;
+ uint32_t rac_rab_dma_ib_wr_addr;
+
+ uint32_t rac_rab_buf_free_ib_free_mask;
+ uint32_t rac_rab_buf_free_ob_free_mask;
+ uint32_t rac_rab_buf_used_ib_used_mask;
+ uint32_t rac_rab_buf_used_ob_used_mask;
+ uint32_t rac_rab_buf_used_flush_mask;
+
+ uint32_t rac_rab_buf_used_ob_used_low;
+
+ uint32_t rac_nmb_rd_adr_addr;
+ uint32_t rac_nmb_data_addr;
+ uint32_t rac_nmb_wr_adr_addr;
+ uint32_t rac_nmb_status_addr;
+
+ bool m_dma_active;
+
+ struct nt_dma_s *m_dma;
+
+ volatile uint32_t *m_dma_in_buf;
+ volatile uint32_t *m_dma_out_buf;
+
+ uint16_t m_dma_out_ptr_rd;
+ uint16_t m_dma_in_ptr_wr;
+ uint32_t m_in_free;
+};
+
+typedef struct nthw_rac nthw_rac_t;
+typedef struct nthw_rac nthw_rac;
+
+struct dma_buf_ptr {
+ uint32_t size;
+ uint32_t index;
+ volatile uint32_t *base;
+};
+
+nthw_rac_t *nthw_rac_new(void);
+void nthw_rac_delete(nthw_rac_t *p);
+int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info);
+
+int nthw_rac_get_rab_interface_count(const nthw_rac_t *p);
+
+int nthw_rac_rab_init(nthw_rac_t *p, uint32_t rab_intf_mask);
+
+int nthw_rac_rab_setup(nthw_rac_t *p);
+
+int nthw_rac_rab_reset(nthw_rac_t *p);
+
+int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data);
+int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data);
+int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, uint32_t *p_data);
+int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, struct dma_buf_ptr *buf_ptr);
+
+int nthw_rac_rab_flush(nthw_rac_t *p);
+
+int nthw_rac_rab_dma_begin(nthw_rac_t *p);
+int nthw_rac_rab_dma_commit(nthw_rac_t *p);
+
+void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t *p_data);
+void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t p_data);
+
+#endif /* __NTHW_RAC_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h
index 5cdbd9fc5d..4fe3496b9f 100644
--- a/drivers/net/ntnic/nthw/nthw_register.h
+++ b/drivers/net/ntnic/nthw/nthw_register.h
@@ -10,6 +10,8 @@
#include <stdbool.h>
#include <inttypes.h>
+#include "nthw_fpga_model.h"
+
#include "fpga_model.h"
#include "nthw_fpga_modules_defs.h"
diff --git a/drivers/net/ntnic/nthw/nthw_stat.c b/drivers/net/ntnic/nthw/nthw_stat.c
new file mode 100644
index 0000000000..fbecbc2dba
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_stat.c
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_stat.h"
+
+#include <malloc.h>
+
+nthw_stat_t *nthw_stat_new(void)
+{
+ nthw_stat_t *p = malloc(sizeof(nthw_stat_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_stat_t));
+ return p;
+}
+
+void nthw_stat_delete(nthw_stat_t *p)
+{
+ if (p)
+ free(p);
+}
+
+int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint64_t n_module_version_packed64 = -1;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_STA, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: STAT %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_stat = mod;
+
+ n_module_version_packed64 = module_get_version_packed64(p->mp_mod_stat);
+ NT_LOG(DBG, NTHW, "%s: STAT %d: version=0x%08lX\n", p_adapter_id_str,
+ p->mn_instance, n_module_version_packed64);
+
+ {
+ nt_register_t *p_reg;
+ /* STA_CFG register */
+ p_reg = module_get_register(p->mp_mod_stat, STA_CFG);
+ p->mp_fld_dma_ena = register_get_field(p_reg, STA_CFG_DMA_ENA);
+ p->mp_fld_cnt_clear = register_get_field(p_reg, STA_CFG_CNT_CLEAR);
+
+ /* CFG: fields NOT available from v. 3 */
+ p->mp_fld_tx_disable =
+ register_query_field(p_reg, STA_CFG_TX_DISABLE);
+ p->mp_fld_cnt_freeze = register_query_field(p_reg, STA_CFG_CNT_FRZ);
+
+ /* STA_STATUS register */
+ p_reg = module_get_register(p->mp_mod_stat, STA_STATUS);
+ p->mp_fld_stat_toggle_missed =
+ register_get_field(p_reg, STA_STATUS_STAT_TOGGLE_MISSED);
+
+ /* HOST_ADR registers */
+ p_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_LSB);
+ p->mp_fld_dma_lsb = register_get_field(p_reg, STA_HOST_ADR_LSB_LSB);
+
+ p_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_MSB);
+ p->mp_fld_dma_msb = register_get_field(p_reg, STA_HOST_ADR_MSB_MSB);
+ }
+
+ /* Params */
+ p->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH;
+
+ p->m_nb_nim_ports = fpga_get_product_param(p_fpga, NT_NIMS, 0);
+ p->m_nb_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0);
+
+ p->m_nb_rx_ports =
+ fpga_get_product_param(p_fpga, NT_STA_RX_PORTS, -1); /* VSWITCH */
+ if (p->m_nb_rx_ports == -1) {
+ p->m_nb_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS,
+ -1); /* non-VSWITCH */
+ if (p->m_nb_rx_ports == -1) {
+ p->m_nb_rx_ports = fpga_get_product_param(p_fpga,
+ NT_PORTS,
+ 0); /* non-VSWITCH */
+ }
+ }
+
+ p->m_nb_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, 0);
+ p->m_rx_port_replicate =
+ fpga_get_product_param(p_fpga, NT_RX_PORT_REPLICATE, 0);
+
+ p->m_nb_color_counters = fpga_get_product_param(p_fpga, NT_STA_COLORS, 64) *
+ 2; /* VSWITCH */
+ if (p->m_nb_color_counters == 0) {
+ p->m_nb_color_counters =
+ fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0) *
+ 2; /* non-VSWITCH */
+ }
+
+ p->m_nb_rx_host_buffers = fpga_get_product_param(p_fpga, NT_QUEUES, 0);
+ p->m_nb_tx_host_buffers = p->m_nb_rx_host_buffers;
+
+ p->m_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);
+
+ p->m_nb_rx_hb_counters =
+ (p->m_nb_rx_host_buffers *
+ (6 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?
+ p->m_dbs_present :
+ 0)));
+
+ p->m_nb_tx_hb_counters = 0;
+
+ p->m_nb_rx_port_counters =
+ 42 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?
+ p->m_dbs_present :
+ 0);
+ p->m_nb_tx_port_counters = 0;
+
+ p->m_nb_counters =
+ p->m_nb_color_counters + p->m_nb_rx_hb_counters + p->m_nb_tx_hb_counters;
+
+ p->mn_stat_layout_version = 0;
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 8)) {
+ p->mn_stat_layout_version = 6;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {
+ p->mn_stat_layout_version = 5;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 4)) {
+ p->mn_stat_layout_version = 4;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 3)) {
+ p->mn_stat_layout_version = 3;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 2)) {
+ p->mn_stat_layout_version = 2;
+ } else if (n_module_version_packed64 > VERSION_PACKED64(0, 0)) {
+ p->mn_stat_layout_version = 1;
+ } else {
+ p->mn_stat_layout_version = 0;
+ NT_LOG(ERR, NTHW,
+ "%s: unknown module_version 0x%08lX layout=%d\n",
+ p_adapter_id_str, n_module_version_packed64,
+ p->mn_stat_layout_version);
+ }
+ assert(p->mn_stat_layout_version);
+
+ /* STA module 0.2+ adds IPF counters per port (Rx feature) */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 2))
+ p->m_nb_rx_port_counters += 6;
+
+ /* STA module 0.3+ adds TX stats */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 3) ||
+ p->m_nb_tx_ports >= 1)
+ p->mb_has_tx_stats = true;
+
+ /* STA module 0.3+ adds TX stat counters */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 3))
+ p->m_nb_tx_port_counters += 22;
+
+ /* STA module 0.4+ adds TX drop event counter */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 4))
+ p->m_nb_tx_port_counters += 1; /* TX drop event counter */
+
+ /*
+ * STA module 0.6+ adds pkt filter drop octets+pkts, retransmit and
+ * duplicate counters
+ */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {
+ p->m_nb_rx_port_counters += 4;
+ p->m_nb_tx_port_counters += 1;
+ }
+
+ if (p->mb_is_vswitch) {
+ p->m_nb_rx_port_counters = 5;
+ p->m_nb_tx_port_counters = 5;
+ }
+
+ p->m_nb_counters += (p->m_nb_rx_ports * p->m_nb_rx_port_counters);
+
+ if (p->mb_has_tx_stats)
+ p->m_nb_counters += (p->m_nb_tx_ports * p->m_nb_tx_port_counters);
+
+ /* Output params (debug) */
+ NT_LOG(DBG, NTHW,
+ "%s: nims=%d rxports=%d txports=%d rxrepl=%d colors=%d queues=%d\n",
+ p_adapter_id_str, p->m_nb_nim_ports, p->m_nb_rx_ports, p->m_nb_tx_ports,
+ p->m_rx_port_replicate, p->m_nb_color_counters, p->m_nb_rx_host_buffers);
+ NT_LOG(DBG, NTHW,
+ "%s: hbs=%d hbcounters=%d rxcounters=%d txcounters=%d\n",
+ p_adapter_id_str, p->m_nb_rx_host_buffers, p->m_nb_rx_hb_counters,
+ p->m_nb_rx_port_counters, p->m_nb_tx_port_counters);
+ NT_LOG(DBG, NTHW, "%s: layout=%d\n", p_adapter_id_str,
+ p->mn_stat_layout_version);
+ NT_LOG(DBG, NTHW, "%s: counters=%d (0x%X)\n", p_adapter_id_str,
+ p->m_nb_counters, p->m_nb_counters);
+ NT_LOG(DBG, NTHW, "%s: vswitch=%d\n", p_adapter_id_str, p->mb_is_vswitch);
+
+ /* Init */
+ if (p->mp_fld_tx_disable)
+ field_set_flush(p->mp_fld_tx_disable);
+
+ field_update_register(p->mp_fld_cnt_clear);
+ field_set_flush(p->mp_fld_cnt_clear);
+ field_clr_flush(p->mp_fld_cnt_clear);
+
+ field_update_register(p->mp_fld_stat_toggle_missed);
+ field_set_flush(p->mp_fld_stat_toggle_missed);
+
+ field_update_register(p->mp_fld_dma_ena);
+ field_clr_flush(p->mp_fld_dma_ena);
+ field_update_register(p->mp_fld_dma_ena);
+
+ return 0;
+}
+
+int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,
+ uint32_t *p_stat_dma_virtual)
+{
+ assert(p_stat_dma_virtual);
+ p->mp_timestamp = NULL;
+
+ p->m_stat_dma_physical = stat_dma_physical;
+ p->mp_stat_dma_virtual = p_stat_dma_virtual;
+
+ memset(p->mp_stat_dma_virtual, 0, (p->m_nb_counters * sizeof(uint32_t)));
+
+ field_set_val_flush32(p->mp_fld_dma_msb,
+ (uint32_t)((p->m_stat_dma_physical >> 32) &
+ 0xffffffff));
+ field_set_val_flush32(p->mp_fld_dma_lsb,
+ (uint32_t)(p->m_stat_dma_physical & 0xffffffff));
+
+ p->mp_timestamp = (uint64_t *)(p->mp_stat_dma_virtual + p->m_nb_counters);
+ NT_LOG(DBG, NTHW,
+ "%s: statDmaPhysical=%" PRIX64 " p_stat_dma_virtual=%" PRIX64
+ " mp_timestamp=%" PRIX64 "\n",
+ __func__, p->m_stat_dma_physical, p->mp_stat_dma_virtual,
+ p->mp_timestamp);
+ if (p->mb_is_vswitch)
+ *p->mp_timestamp = NT_OS_GET_TIME_NS();
+
+ else
+ *p->mp_timestamp = (uint64_t)(int64_t)-1;
+ return 0;
+}
+
+int nthw_stat_trigger(nthw_stat_t *p)
+{
+ int n_toggle_miss = field_get_updated(p->mp_fld_stat_toggle_missed);
+
+ if (n_toggle_miss)
+ field_set_flush(p->mp_fld_stat_toggle_missed);
+
+ if (p->mp_timestamp)
+ *p->mp_timestamp = -1; /* Clear old ts */
+
+ field_update_register(p->mp_fld_dma_ena);
+ field_set_flush(p->mp_fld_dma_ena);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_stat.h b/drivers/net/ntnic/nthw/nthw_stat.h
new file mode 100644
index 0000000000..7bce7ecd15
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_stat.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_STAT_H__
+#define __NTHW_STAT_H__
+
+struct nthw_stat {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_stat;
+ int mn_instance;
+
+ int mn_stat_layout_version;
+
+ bool mb_is_vswitch;
+ bool mb_has_tx_stats;
+
+ int m_nb_phy_ports;
+ int m_nb_nim_ports;
+
+ int m_nb_rx_ports;
+ int m_nb_tx_ports;
+
+ int m_nb_rx_host_buffers;
+ int m_nb_tx_host_buffers;
+
+ int m_dbs_present;
+
+ int m_rx_port_replicate;
+
+ int m_nb_color_counters;
+
+ int m_nb_rx_hb_counters;
+ int m_nb_tx_hb_counters;
+
+ int m_nb_rx_port_counters;
+ int m_nb_tx_port_counters;
+
+ int m_nb_counters;
+
+ nt_field_t *mp_fld_dma_ena;
+ nt_field_t *mp_fld_cnt_clear;
+
+ nt_field_t *mp_fld_tx_disable;
+
+ nt_field_t *mp_fld_cnt_freeze;
+
+ nt_field_t *mp_fld_stat_toggle_missed;
+
+ nt_field_t *mp_fld_dma_lsb;
+ nt_field_t *mp_fld_dma_msb;
+
+ uint64_t m_stat_dma_physical;
+ uint32_t *mp_stat_dma_virtual;
+
+ uint64_t last_ts;
+
+ uint64_t *mp_timestamp;
+};
+
+typedef struct nthw_stat nthw_stat_t;
+typedef struct nthw_stat nthw_stat;
+
+nthw_stat_t *nthw_stat_new(void);
+int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_stat_delete(nthw_stat_t *p);
+
+int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,
+ uint32_t *p_stat_dma_virtual);
+int nthw_stat_trigger(nthw_stat_t *p);
+
+#endif /* __NTHW_STAT_H__ */
diff --git a/drivers/net/ntnic/ntlog/include/ntlog.h b/drivers/net/ntnic/ntlog/include/ntlog.h
new file mode 100644
index 0000000000..81bc014d66
--- /dev/null
+++ b/drivers/net/ntnic/ntlog/include/ntlog.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTOSS_SYSTEM_NTLOG_H
+#define NTOSS_SYSTEM_NTLOG_H
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#ifndef NT_LOG_MODULE_PREFIX
+
+/* DPDK modules */
+#define NT_LOG_MODULE_EAL 0
+#define NT_LOG_MODULE_MALLOC 1
+#define NT_LOG_MODULE_RING 2
+#define NT_LOG_MODULE_MEMPOOL 3
+#define NT_LOG_MODULE_TIMER 4
+#define NT_LOG_MODULE_PMD 5
+#define NT_LOG_MODULE_HASH 6
+#define NT_LOG_MODULE_LPM 7
+#define NT_LOG_MODULE_KNI 8
+#define NT_LOG_MODULE_ACL 9
+#define NT_LOG_MODULE_POWER 10
+#define NT_LOG_MODULE_METER 11
+#define NT_LOG_MODULE_SCHED 12
+#define NT_LOG_MODULE_PORT 13
+#define NT_LOG_MODULE_TABLE 14
+#define NT_LOG_MODULE_PIPELINE 15
+#define NT_LOG_MODULE_MBUF 16
+#define NT_LOG_MODULE_CRYPTODEV 17
+#define NT_LOG_MODULE_EFD 18
+#define NT_LOG_MODULE_EVENTDEV 19
+#define NT_LOG_MODULE_GSO 20
+#define NT_LOG_MODULE_USER1 24
+#define NT_LOG_MODULE_USER2 25
+#define NT_LOG_MODULE_USER3 26
+#define NT_LOG_MODULE_USER4 27
+#define NT_LOG_MODULE_USER5 28
+#define NT_LOG_MODULE_USER6 29
+#define NT_LOG_MODULE_USER7 30
+#define NT_LOG_MODULE_USER8 31
+
+/* NT modules */
+#define NT_LOG_MODULE_GENERAL 10000 /* Should always be a first (smallest) */
+#define NT_LOG_MODULE_NTHW 10001
+#define NT_LOG_MODULE_FILTER 10002
+#define NT_LOG_MODULE_VDPA 10003
+#define NT_LOG_MODULE_FPGA 10004
+#define NT_LOG_MODULE_NTCONNECT 10005
+#define NT_LOG_MODULE_ETHDEV 10006
+#define NT_LOG_MODULE_END 10007 /* Mark for the range end of NT_LOG */
+
+#define NT_LOG_MODULE_COUNT (NT_LOG_MODULE_END - NT_LOG_MODULE_GENERAL)
+#define NT_LOG_MODULE_INDEX(module) ((module) - NT_LOG_MODULE_GENERAL)
+#define NT_LOG_MODULE_PREFIX(type) NT_LOG_MODULE_##type
+
+#endif
+
+#ifndef NT_LOG_ENABLE
+#define NT_LOG_ENABLE 1
+#endif
+
+#if defined NT_LOG_ENABLE && NT_LOG_ENABLE > 0
+#ifndef NT_LOG_ENABLE_ERR
+#define NT_LOG_ENABLE_ERR 1
+#endif
+#ifndef NT_LOG_ENABLE_WRN
+#define NT_LOG_ENABLE_WRN 1
+#endif
+#ifndef NT_LOG_ENABLE_INF
+#define NT_LOG_ENABLE_INF 1
+#endif
+#ifndef NT_LOG_ENABLE_DBG
+#define NT_LOG_ENABLE_DBG 1
+#endif
+#ifndef NT_LOG_ENABLE_DB1
+#define NT_LOG_ENABLE_DB1 0
+#endif
+#ifndef NT_LOG_ENABLE_DB2
+#define NT_LOG_ENABLE_DB2 0
+#endif
+#endif
+
+#if defined NT_LOG_ENABLE_ERR && NT_LOG_ENABLE_ERR > 0
+#define NT_LOG_NT_LOG_ERR(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_ERR(...)
+#endif
+
+#if defined NT_LOG_ENABLE_WRN && NT_LOG_ENABLE_WRN > 0
+#define NT_LOG_NT_LOG_WRN(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_WRN(...)
+#endif
+
+#if defined NT_LOG_ENABLE_INF && NT_LOG_ENABLE_INF > 0
+#define NT_LOG_NT_LOG_INF(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_INF(...)
+#endif
+
+#if defined NT_LOG_ENABLE_DBG && NT_LOG_ENABLE_DBG > 0
+#define NT_LOG_NT_LOG_DBG(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_DBG(...)
+#endif
+
+#if defined NT_LOG_ENABLE_DB1 && NT_LOG_ENABLE_DB1 > 0
+#define NT_LOG_NT_LOG_DB1(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_DB1(...)
+#endif
+
+#if defined NT_LOG_ENABLE_DB2 && NT_LOG_ENABLE_DB2 > 0
+#define NT_LOG_NT_LOG_DB2(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_DB2(...)
+#endif
+
+#define NT_LOG(level, module, ...) \
+ NT_LOG_NT_LOG_##level(NT_LOG_##level, NT_LOG_MODULE_PREFIX(module), \
+ #module ": " #level ": " __VA_ARGS__)
+
+enum nt_log_level {
+ NT_LOG_ERR = 0x001,
+ NT_LOG_WRN = 0x002,
+ NT_LOG_INF = 0x004,
+ NT_LOG_DBG = 0x008,
+ NT_LOG_DB1 = 0x010,
+ NT_LOG_DB2 = 0x020,
+};
+
+struct nt_log_impl {
+ int (*init)(void);
+ int (*log)(enum nt_log_level level, uint32_t module, const char *format,
+ va_list args);
+ int (*is_debug)(uint32_t module);
+};
+
+int nt_log_init(struct nt_log_impl *impl);
+
+int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...);
+
+/* Returns 1 if RTE_DEBUG, 0 if lower log level, -1 if incorrect module */
+int nt_log_is_debug(uint32_t module);
+
+/*
+ * nt log helper functions
+ * to create a string for NT_LOG usage to output a one-liner log
+ * to use when one single function call to NT_LOG is not optimal - that is
+ * you do not know the number of parameters at programming time or it is variable
+ */
+char *ntlog_helper_str_alloc(const char *sinit);
+
+void ntlog_helper_str_reset(char *s, const char *sinit);
+
+void ntlog_helper_str_add(char *s, const char *format, ...);
+
+void ntlog_helper_str_free(char *s);
+
+#endif /* NTOSS_SYSTEM_NTLOG_H */
diff --git a/drivers/net/ntnic/ntlog/ntlog.c b/drivers/net/ntnic/ntlog/ntlog.c
new file mode 100644
index 0000000000..b9109754ac
--- /dev/null
+++ b/drivers/net/ntnic/ntlog/ntlog.c
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <rte_string_fns.h>
+
+#define NTLOG_HELPER_STR_SIZE_MAX (1024)
+
+static struct nt_log_impl *user_impl;
+
+int nt_log_init(struct nt_log_impl *impl)
+{
+ user_impl = impl;
+ return user_impl->init();
+}
+
+static char *last_trailing_eol(char *s)
+{
+ int i = strlen(s) - 1;
+ /* Skip spaces */
+ while (i > 0 && s[i] == ' ')
+ --i;
+ if (s[i] != '\n')
+ return NULL;
+ /*
+ * Find the last trailing EOL "hello_world\n\n\n"
+ * ^
+ */
+ while (i > 1 && s[i] == '\n' && s[i - 1] == '\n')
+ --i;
+ return &s[i];
+}
+
+/* Always terminates the NT_LOG statement with a !!!single!!! EOL. */
+int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...)
+{
+ int rv = -1;
+ va_list args;
+
+ if (user_impl == NULL)
+ return rv;
+
+ char *actual_format = ntlog_helper_str_alloc(format);
+ char *eol = last_trailing_eol(actual_format);
+
+ if (!eol) { /* If log line is not terminated with '\n' we add it. */
+ strncat(actual_format, "\n",
+ NTLOG_HELPER_STR_SIZE_MAX - strlen(actual_format));
+ } else { /* If multiple trailing EOLs, then keep just one of them. */
+ *(eol + 1) = '\0';
+ }
+
+ va_start(args, format);
+ rv = user_impl->log(level, module, actual_format, args);
+ va_end(args);
+
+ ntlog_helper_str_free(actual_format);
+ return rv;
+}
+
+int nt_log_is_debug(uint32_t module)
+{
+ return user_impl->is_debug(module);
+}
+
+char *ntlog_helper_str_alloc(const char *sinit)
+{
+ char *s = malloc(NTLOG_HELPER_STR_SIZE_MAX);
+
+ if (!s)
+ return NULL;
+ if (sinit)
+ rte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX);
+ else
+ s[0] = '\0';
+ return s;
+}
+
+void ntlog_helper_str_reset(char *s, const char *sinit)
+{
+ if (s) {
+ if (sinit)
+ rte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX);
+ else
+ s[0] = '\0';
+ }
+}
+
+void ntlog_helper_str_add(char *s, const char *format, ...)
+{
+ if (!s)
+ return;
+ va_list args;
+
+ va_start(args, format);
+ int len = strlen(s);
+
+ vsnprintf(&s[len], (NTLOG_HELPER_STR_SIZE_MAX - 1 - len), format, args);
+ va_end(args);
+}
+
+void ntlog_helper_str_free(char *s)
+{
+ free(s);
+}
diff --git a/drivers/net/ntnic/ntutil/include/nt_util.h b/drivers/net/ntnic/ntutil/include/nt_util.h
new file mode 100644
index 0000000000..3850ccd934
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/include/nt_util.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTOSS_SYSTEM_NT_UTIL_H
+#define NTOSS_SYSTEM_NT_UTIL_H
+
+#include <rte_cycles.h>
+#include <rte_string_fns.h>
+
+#define _unused __rte_unused
+
+#define PCIIDENT_TO_DOMAIN(pci_ident) \
+ ((uint16_t)(((unsigned int)(pci_ident) >> 16) & 0xFFFFU))
+#define PCIIDENT_TO_BUSNR(pci_ident) \
+ ((uint8_t)(((unsigned int)(pci_ident) >> 8) & 0xFFU))
+#define PCIIDENT_TO_DEVNR(pci_ident) \
+ ((uint8_t)(((unsigned int)(pci_ident) >> 3) & 0x1FU))
+#define PCIIDENT_TO_FUNCNR(pci_ident) \
+ ((uint8_t)(((unsigned int)(pci_ident) >> 0) & 0x7U))
+
+#define PCIIDENT_PRINT_STR "%04x:%02x:%02x.%x"
+#define BDF_TO_PCIIDENT(dom, bus, dev, fnc) \
+ (((dom) << 16) | ((bus) << 8) | ((dev) << 3) | (fnc))
+
+/* ALIGN: Align x to a boundary */
+#define ALIGN(x, a) \
+ ({ \
+ __typeof__(x) _a = (a); \
+ ((x) + (_a - 1)) & ~(_a - 1); \
+ })
+
+/* PALIGN: Align pointer p to a boundary */
+#define PALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a)))
+
+/* Allocation size matching minimum alignment of specified size */
+#define ALIGN_SIZE(_size_) (1 << rte_log2_u64(_size_))
+
+#define NT_OS_WAIT_USEC(x) \
+ rte_delay_us_sleep( \
+ x) /* uses usleep which schedules out the calling thread */
+/* spins in a waiting loop calling pause asm instruction uses RDTSC - precise wait */
+#define NT_OS_WAIT_USEC_POLL(x) \
+ rte_delay_us( \
+ x)
+
+#define NT_OS_GET_TIME_US() \
+ (rte_get_timer_cycles() / (rte_get_timer_hz() / 1000 / 1000))
+#define NT_OS_GET_TIME_NS() \
+ (rte_get_timer_cycles() * 10 / (rte_get_timer_hz() / 1000 / 1000 / 100))
+#define NT_OS_GET_TIME_MONOTONIC_COUNTER() (rte_get_timer_cycles())
+
+struct nt_dma_s {
+ uint64_t iova;
+ uint64_t addr;
+ uint64_t size;
+};
+
+struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa);
+void nt_dma_free(struct nt_dma_s *vfio_addr);
+
+struct nt_util_vfio_impl {
+ int (*vfio_dma_map)(int vf_num, void *virt_addr, uint64_t *iova_addr,
+ uint64_t size);
+ int (*vfio_dma_unmap)(int vf_num, void *virt_addr, uint64_t iova_addr,
+ uint64_t size);
+};
+
+void nt_util_vfio_init(struct nt_util_vfio_impl *impl);
+
+#endif /* NTOSS_SYSTEM_NT_UTIL_H */
diff --git a/drivers/net/ntnic/ntutil/nt_util.c b/drivers/net/ntnic/ntutil/nt_util.c
new file mode 100644
index 0000000000..8f5812bf8b
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/nt_util.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <rte_malloc.h>
+
+#include "ntlog.h"
+#include "nt_util.h"
+
+static struct nt_util_vfio_impl vfio_cb;
+
+void nt_util_vfio_init(struct nt_util_vfio_impl *impl)
+{
+ vfio_cb = *impl;
+}
+
+struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa)
+{
+ int res;
+ struct nt_dma_s *vfio_addr;
+
+ vfio_addr = rte_malloc(NULL, sizeof(struct nt_dma_s), 0);
+ if (!vfio_addr) {
+ NT_LOG(ERR, GENERAL, "VFIO rte_malloc failed\n");
+ return NULL;
+ }
+ void *addr = rte_malloc_socket(NULL, size, align, numa);
+
+ if (!addr) {
+ rte_free(vfio_addr);
+ NT_LOG(ERR, GENERAL, "VFIO rte_malloc_socket failed\n");
+ return NULL;
+ }
+ res = vfio_cb.vfio_dma_map(0, addr, &vfio_addr->iova,
+ ALIGN_SIZE(size));
+ if (res != 0) {
+ rte_free(addr);
+ rte_free(vfio_addr);
+ NT_LOG(ERR, GENERAL, "VFIO nt_dma_map failed\n");
+ return NULL;
+ }
+
+ vfio_addr->addr = (uint64_t)addr;
+ vfio_addr->size = ALIGN_SIZE(size);
+
+ NT_LOG(DBG, GENERAL,
+ "VFIO DMA alloc addr=%" PRIX64 ", iova=%" PRIX64
+ ", size=%u, align=0x%X\n",
+ vfio_addr->addr, vfio_addr->iova, vfio_addr->size, align);
+
+ return vfio_addr;
+}
+
+void nt_dma_free(struct nt_dma_s *vfio_addr)
+{
+ NT_LOG(DBG, GENERAL,
+ "VFIO DMA free addr=%" PRIX64 ", iova=%" PRIX64 ", size=%u\n",
+ vfio_addr->addr, vfio_addr->iova, vfio_addr->size);
+
+ int res = vfio_cb.vfio_dma_unmap(0, (void *)(vfio_addr->addr),
+ vfio_addr->iova, vfio_addr->size);
+ if (res != 0) {
+ NT_LOG(WRN, GENERAL,
+ "VFIO DMA free FAILED addr=%" PRIX64 ", iova=%" PRIX64
+ ", size=%u\n",
+ vfio_addr->addr, vfio_addr->iova, vfio_addr->size);
+ }
+ rte_free((void *)(vfio_addr->addr));
+ rte_free(vfio_addr);
+}
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 3/8] net/ntnic: adds NT200A02 adapter support
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
2023-08-16 13:25 ` [PATCH 2/8] net/ntnic: adds core registers and fpga functionality Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 13:25 ` [PATCH 4/8] net/ntnic: adds flow related FPGA functionality Mykola Kostenok
` (18 subsequent siblings)
20 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
The PMD is designed to support multiple different adapters, and this commit
adds support for NT200A02 2x100G. Sensor and NIM code is included.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
.../net/ntnic/adapter/common_adapter_defs.h | 14 +
drivers/net/ntnic/adapter/nt4ga_adapter.c | 477 ++++
drivers/net/ntnic/adapter/nt4ga_adapter.h | 108 +
drivers/net/ntnic/adapter/nt4ga_filter.h | 15 +
drivers/net/ntnic/adapter/nt4ga_link.c | 178 ++
drivers/net/ntnic/adapter/nt4ga_link.h | 179 ++
drivers/net/ntnic/adapter/nt4ga_link_100g.c | 825 +++++++
drivers/net/ntnic/adapter/nt4ga_link_100g.h | 12 +
drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c | 598 +++++
drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h | 41 +
drivers/net/ntnic/adapter/nt4ga_stat.c | 705 ++++++
drivers/net/ntnic/adapter/nt4ga_stat.h | 202 ++
drivers/net/ntnic/meson.build | 24 +
drivers/net/ntnic/nim/i2c_nim.c | 1974 +++++++++++++++++
drivers/net/ntnic/nim/i2c_nim.h | 122 +
drivers/net/ntnic/nim/nim_defines.h | 146 ++
drivers/net/ntnic/nim/nt_link_speed.c | 105 +
drivers/net/ntnic/nim/nt_link_speed.h | 34 +
drivers/net/ntnic/nim/qsfp_registers.h | 57 +
drivers/net/ntnic/nim/qsfp_sensors.c | 174 ++
drivers/net/ntnic/nim/qsfp_sensors.h | 18 +
drivers/net/ntnic/nim/sfp_p_registers.h | 100 +
drivers/net/ntnic/nim/sfp_sensors.c | 288 +++
drivers/net/ntnic/nim/sfp_sensors.h | 18 +
.../net/ntnic/nthw/core/nthw_clock_profiles.c | 11 +-
drivers/net/ntnic/nthw/core/nthw_core.h | 2 +
drivers/net/ntnic/nthw/core/nthw_gmf.c | 290 +++
drivers/net/ntnic/nthw/core/nthw_gmf.h | 93 +
.../nthw/core/nthw_nt200a02_u23_si5340_v5.h | 344 +++
drivers/net/ntnic/nthw/core/nthw_rmc.c | 156 ++
drivers/net/ntnic/nthw/core/nthw_rmc.h | 57 +
.../ntnic/sensors/avr_sensors/avr_sensors.c | 104 +
.../ntnic/sensors/avr_sensors/avr_sensors.h | 22 +
.../sensors/board_sensors/board_sensors.c | 48 +
.../sensors/board_sensors/board_sensors.h | 18 +
.../net/ntnic/sensors/board_sensors/tempmon.c | 42 +
.../net/ntnic/sensors/board_sensors/tempmon.h | 16 +
.../ntnic/sensors/nim_sensors/nim_sensors.c | 54 +
.../ntnic/sensors/nim_sensors/nim_sensors.h | 19 +
drivers/net/ntnic/sensors/ntavr/avr_intf.h | 89 +
drivers/net/ntnic/sensors/ntavr/ntavr.c | 78 +
drivers/net/ntnic/sensors/ntavr/ntavr.h | 32 +
drivers/net/ntnic/sensors/sensor_types.h | 259 +++
drivers/net/ntnic/sensors/sensors.c | 273 +++
drivers/net/ntnic/sensors/sensors.h | 127 ++
drivers/net/ntnic/sensors/stream_info.h | 86 +
46 files changed, 8632 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/ntnic/adapter/common_adapter_defs.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_adapter.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_adapter.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_filter.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link_100g.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link_100g.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_stat.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_stat.h
create mode 100644 drivers/net/ntnic/nim/i2c_nim.c
create mode 100644 drivers/net/ntnic/nim/i2c_nim.h
create mode 100644 drivers/net/ntnic/nim/nim_defines.h
create mode 100644 drivers/net/ntnic/nim/nt_link_speed.c
create mode 100644 drivers/net/ntnic/nim/nt_link_speed.h
create mode 100644 drivers/net/ntnic/nim/qsfp_registers.h
create mode 100644 drivers/net/ntnic/nim/qsfp_sensors.c
create mode 100644 drivers/net/ntnic/nim/qsfp_sensors.h
create mode 100644 drivers/net/ntnic/nim/sfp_p_registers.h
create mode 100644 drivers/net/ntnic/nim/sfp_sensors.c
create mode 100644 drivers/net/ntnic/nim/sfp_sensors.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gmf.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gmf.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_rmc.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_rmc.h
create mode 100644 drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c
create mode 100644 drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h
create mode 100644 drivers/net/ntnic/sensors/board_sensors/board_sensors.c
create mode 100644 drivers/net/ntnic/sensors/board_sensors/board_sensors.h
create mode 100644 drivers/net/ntnic/sensors/board_sensors/tempmon.c
create mode 100644 drivers/net/ntnic/sensors/board_sensors/tempmon.h
create mode 100644 drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c
create mode 100644 drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h
create mode 100644 drivers/net/ntnic/sensors/ntavr/avr_intf.h
create mode 100644 drivers/net/ntnic/sensors/ntavr/ntavr.c
create mode 100644 drivers/net/ntnic/sensors/ntavr/ntavr.h
create mode 100644 drivers/net/ntnic/sensors/sensor_types.h
create mode 100644 drivers/net/ntnic/sensors/sensors.c
create mode 100644 drivers/net/ntnic/sensors/sensors.h
create mode 100644 drivers/net/ntnic/sensors/stream_info.h
diff --git a/drivers/net/ntnic/adapter/common_adapter_defs.h b/drivers/net/ntnic/adapter/common_adapter_defs.h
new file mode 100644
index 0000000000..79167806f1
--- /dev/null
+++ b/drivers/net/ntnic/adapter/common_adapter_defs.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _COMMON_ADAPTER_DEFS_H_
+#define _COMMON_ADAPTER_DEFS_H_
+
+/*
+ * Declarations shared by NT adapter types.
+ */
+#define NUM_ADAPTER_MAX (8)
+#define NUM_ADAPTER_PORTS_MAX (128)
+
+#endif /* _COMMON_ADAPTER_DEFS_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
new file mode 100644
index 0000000000..259aae2831
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -0,0 +1,477 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+#include "nt4ga_adapter.h"
+#include "nt4ga_pci_ta_tg.h"
+#include "nt4ga_link_100g.h"
+
+/* Sensors includes */
+#include "board_sensors.h"
+#include "avr_sensors.h"
+
+/*
+ * Global variables shared by NT adapter types
+ */
+pthread_t monitor_tasks[NUM_ADAPTER_MAX];
+volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
+
+/*
+ * Signal-handler to stop all monitor threads
+ */
+static void stop_monitor_tasks(int signum)
+{
+ const size_t n = ARRAY_SIZE(monitor_task_is_running);
+ size_t i;
+
+ /* Stop all monitor tasks */
+ for (i = 0; i < n; i++) {
+ const int is_running = monitor_task_is_running[i];
+
+ monitor_task_is_running[i] = 0;
+ if (signum == -1 && is_running != 0) {
+ void *ret_val = NULL;
+
+ pthread_join(monitor_tasks[i], &ret_val);
+ memset(&monitor_tasks[i], 0, sizeof(monitor_tasks[0]));
+ }
+ }
+}
+
+int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh)
+{
+ const char *const p_dev_name = p_adapter_info->p_dev_name;
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *p_fpga_info = &p_adapter_info->fpga_info;
+ hw_info_t *p_hw_info = &p_adapter_info->hw_info;
+ char a_pci_ident_str[32];
+
+ snprintf(a_pci_ident_str, sizeof(a_pci_ident_str), "" PCIIDENT_PRINT_STR "",
+ PCIIDENT_TO_DOMAIN(p_fpga_info->pciident),
+ PCIIDENT_TO_BUSNR(p_fpga_info->pciident),
+ PCIIDENT_TO_DEVNR(p_fpga_info->pciident),
+ PCIIDENT_TO_FUNCNR(p_fpga_info->pciident));
+
+ fprintf(pfh, "%s: DeviceName: %s\n", p_adapter_id_str,
+ (p_dev_name ? p_dev_name : "NA"));
+ fprintf(pfh, "%s: PCI Details:\n", p_adapter_id_str);
+ fprintf(pfh, "%s: %s: %08X: %04X:%04X %04X:%04X\n", p_adapter_id_str,
+ a_pci_ident_str, p_fpga_info->pciident, p_hw_info->pci_vendor_id,
+ p_hw_info->pci_device_id, p_hw_info->pci_sub_vendor_id,
+ p_hw_info->pci_sub_device_id);
+ fprintf(pfh, "%s: FPGA Details:\n", p_adapter_id_str);
+ fprintf(pfh, "%s: %03d-%04d-%02d-%02d [%016" PRIX64 "] (%08X)\n",
+ p_adapter_id_str, p_fpga_info->n_fpga_type_id, p_fpga_info->n_fpga_prod_id,
+ p_fpga_info->n_fpga_ver_id, p_fpga_info->n_fpga_rev_id,
+ p_fpga_info->n_fpga_ident, p_fpga_info->n_fpga_build_time);
+ fprintf(pfh, "%s: FpgaDebugMode=0x%x\n", p_adapter_id_str,
+ p_fpga_info->n_fpga_debug_mode);
+ fprintf(pfh,
+ "%s: Nims=%d PhyPorts=%d PhyQuads=%d RxPorts=%d TxPorts=%d\n",
+ p_adapter_id_str, p_fpga_info->n_nims, p_fpga_info->n_phy_ports,
+ p_fpga_info->n_phy_quads, p_fpga_info->n_rx_ports, p_fpga_info->n_tx_ports);
+ fprintf(pfh, "%s: Hw=0x%02X_rev%d: %s\n", p_adapter_id_str,
+ p_hw_info->hw_platform_id, p_fpga_info->nthw_hw_info.hw_id,
+ p_fpga_info->nthw_hw_info.hw_plat_id_str);
+
+ nt4ga_stat_dump(p_adapter_info, pfh);
+
+ return 0;
+}
+
+/*
+ * SPI for sensors initialization
+ */
+static nthw_spi_v3_t *new_sensors_s_spi(struct nt_fpga_s *p_fpga)
+{
+ nthw_spi_v3_t *sensors_s_spi = nthw_spi_v3_new();
+
+ if (sensors_s_spi == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI allocation error\n", __func__);
+ return NULL;
+ }
+
+ if (nthw_spi_v3_init(sensors_s_spi, p_fpga, 0)) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI initialization error\n", __func__);
+ nthw_spi_v3_delete(sensors_s_spi);
+ return NULL;
+ }
+
+ return sensors_s_spi;
+}
+
+/*
+ * SPI for sensors reading
+ */
+nthw_spis_t *new_sensors_t_spi(struct nt_fpga_s *p_fpga)
+{
+ nthw_spis_t *sensors_t_spi = nthw_spis_new();
+ /* init SPI for sensor initialization process */
+ if (sensors_t_spi == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI allocation error\n", __func__);
+ return NULL;
+ }
+
+ if (nthw_spis_init(sensors_t_spi, p_fpga, 0)) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI initialization error\n", __func__);
+ nthw_spis_delete(sensors_t_spi);
+ return NULL;
+ }
+
+ return sensors_t_spi;
+}
+
+static void adapter_sensor_setup(hw_info_t *p_hw_info, struct adapter_info_s *adapter)
+{
+ struct nt_fpga_s *p_fpga = adapter->fpga_info.mp_fpga;
+ struct nt_sensor_group *sensors_list_ptr = NULL;
+ nthw_spi_v3_t *sensors_s_spi = new_sensors_s_spi(p_fpga);
+
+ adapter->adapter_sensors_cnt = 0;
+
+ /* FPGA */
+ adapter->adapter_sensors = fpga_temperature_sensor_init(p_hw_info->n_nthw_adapter_id,
+ NT_SENSOR_FPGA_TEMP, p_fpga);
+ sensors_list_ptr = adapter->adapter_sensors;
+ adapter->adapter_sensors_cnt++;
+
+ /* AVR */
+ if (sensors_s_spi) {
+ if (nt_avr_sensor_mon_ctrl(sensors_s_spi,
+ SENSOR_MON_CTRL_REM_ALL_SENSORS) != 0) {
+ /* stop sensor monitoring */
+ NT_LOG(ERR, ETHDEV,
+ "Failed to stop AVR sensors monitoring\n");
+ } else {
+ NT_LOG(DBG, ETHDEV, "AVR sensors init started\n");
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "FAN0",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_FAN,
+ NT_SENSOR_NT200E3_FAN_SPEED,
+ SENSOR_MON_FAN, 0,
+ SENSOR_MON_BIG_ENDIAN,
+ SENSOR_MON_UNSIGNED,
+ &fan, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "PSU0",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE,
+ NT_SENSOR_NT200E3_PSU0_TEMP,
+ SENSOR_MON_PSU_EXAR_7724_0, 0x15,
+ SENSOR_MON_LITTLE_ENDIAN,
+ SENSOR_MON_UNSIGNED,
+ &exar7724_tj, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "PSU1",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE,
+ NT_SENSOR_NT200A02_PSU1_TEMP,
+ SENSOR_MON_MP2886A, 0x8d,
+ SENSOR_MON_BIG_ENDIAN,
+ SENSOR_MON_UNSIGNED,
+ &mp2886a_tj, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "PCB",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE,
+ NT_SENSOR_NT200E3_PCB_TEMP,
+ SENSOR_MON_DS1775, 0,
+ SENSOR_MON_LITTLE_ENDIAN,
+ SENSOR_MON_SIGNED,
+ &ds1775_t, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ NT_LOG(DBG, ETHDEV, "AVR sensors init finished\n");
+
+ if (nt_avr_sensor_mon_ctrl(sensors_s_spi,
+ SENSOR_MON_CTRL_RUN) != 0) {
+ /* start sensor monitoring */
+ NT_LOG(ERR, ETHDEV,
+ "Failed to start AVR sensors monitoring\n");
+ } else {
+ NT_LOG(DBG, ETHDEV,
+ "AVR sensors monitoring starteed\n");
+ }
+ }
+
+ nthw_spi_v3_delete(sensors_s_spi);
+ }
+}
+
+int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info)
+{
+ char *const p_dev_name = malloc(24);
+ char *const p_adapter_id_str = malloc(24);
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ hw_info_t *p_hw_info = &p_adapter_info->hw_info;
+
+ /*
+ * IMPORTANT: Most variables cannot be determined before fpga model is instantiated
+ * (nthw_fpga_init())
+ */
+ int n_phy_ports = -1;
+ int n_nim_ports = -1;
+ int res = -1;
+ nt_fpga_t *p_fpga = NULL;
+
+ (void)n_nim_ports; /* currently UNUSED - prevent warning */
+
+ p_hw_info->n_nthw_adapter_id =
+ nthw_platform_get_nthw_adapter_id(p_hw_info->pci_device_id);
+
+ fpga_info->n_nthw_adapter_id = p_hw_info->n_nthw_adapter_id;
+ p_hw_info->hw_product_type = p_hw_info->pci_device_id &
+ 0x000f; /* ref: DN-0060 section 9 */
+ /* ref: DN-0060 section 9 */
+ p_hw_info->hw_platform_id = (p_hw_info->pci_device_id >> 4) & 0x00ff;
+ /* ref: DN-0060 section 9 */
+ p_hw_info->hw_reserved1 = (p_hw_info->pci_device_id >> 12) & 0x000f;
+
+ /* mp_dev_name */
+ p_adapter_info->p_dev_name = p_dev_name;
+ if (p_dev_name) {
+ snprintf(p_dev_name, 24, "" PCIIDENT_PRINT_STR "",
+ PCIIDENT_TO_DOMAIN(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_BUSNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_DEVNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_FUNCNR(p_adapter_info->fpga_info.pciident));
+ NT_LOG(DBG, ETHDEV, "%s: (0x%08X)\n", p_dev_name,
+ p_adapter_info->fpga_info.pciident);
+ }
+
+ /* mp_adapter_id_str */
+ p_adapter_info->mp_adapter_id_str = p_adapter_id_str;
+
+ p_adapter_info->fpga_info.mp_adapter_id_str = p_adapter_id_str;
+
+ if (p_adapter_id_str) {
+ snprintf(p_adapter_id_str, 24, "PCI:" PCIIDENT_PRINT_STR "",
+ PCIIDENT_TO_DOMAIN(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_BUSNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_DEVNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_FUNCNR(p_adapter_info->fpga_info.pciident));
+ NT_LOG(DBG, ETHDEV, "%s: %s\n", p_adapter_id_str, p_dev_name);
+ }
+
+ {
+ int i;
+
+ for (i = 0; i < (int)ARRAY_SIZE(p_adapter_info->mp_port_id_str);
+ i++) {
+ char *p = malloc(32);
+
+ if (p) {
+ snprintf(p, 32, "%s:intf_%d",
+ (p_adapter_id_str ? p_adapter_id_str : "NA"),
+ i);
+ NT_LOG(DBG, ETHDEV, "%s\n", p);
+ }
+ p_adapter_info->mp_port_id_str[i] = p;
+ }
+ }
+
+ res = nthw_fpga_init(&p_adapter_info->fpga_info);
+ if (res) {
+ NT_LOG(ERR, ETHDEV, "%s: %s: FPGA=%04d res=x%08X [%s:%u]\n",
+ p_adapter_id_str, p_dev_name, fpga_info->n_fpga_prod_id, res,
+ __func__, __LINE__);
+ return res;
+ }
+
+ assert(fpga_info);
+ p_fpga = fpga_info->mp_fpga;
+ assert(p_fpga);
+ n_phy_ports = fpga_info->n_phy_ports;
+ assert(n_phy_ports >= 1);
+ n_nim_ports = fpga_info->n_nims;
+ assert(n_nim_ports >= 1);
+
+ /*
+ * HIF/PCI TA/TG
+ */
+ {
+ res = nt4ga_pci_ta_tg_init(p_adapter_info);
+ if (res == 0) {
+ nt4ga_pci_ta_tg_measure_throughput_main(p_adapter_info,
+ 0, 0,
+ TG_PKT_SIZE,
+ TG_NUM_PACKETS,
+ TG_DELAY);
+ } else {
+ NT_LOG(WRN, ETHDEV,
+ "%s: PCI TA/TG is not available - skipping\n",
+ p_adapter_id_str);
+ }
+ }
+
+ adapter_sensor_setup(p_hw_info, p_adapter_info);
+
+ {
+ int i;
+
+ assert(fpga_info->n_fpga_prod_id > 0);
+ for (i = 0; i < NUM_ADAPTER_PORTS_MAX; i++) {
+ /* Disable all ports. Must be enabled later */
+ p_adapter_info->nt4ga_link.port_action[i].port_disable =
+ true;
+ }
+ switch (fpga_info->n_fpga_prod_id) {
+ /* NT200A02: 2x100G */
+ case 9563: /* NT200A02 */
+ res = nt4ga_link_100g_ports_init(p_adapter_info, p_fpga);
+ break;
+ default:
+ NT_LOG(ERR, ETHDEV,
+ "%s: Unsupported FPGA product: %04d\n", __func__,
+ fpga_info->n_fpga_prod_id);
+ res = -1;
+ break;
+ }
+
+ if (res) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: %s: %s: %u: FPGA=%04d res=x%08X\n",
+ p_adapter_id_str, p_dev_name, __func__, __LINE__,
+ fpga_info->n_fpga_prod_id, res);
+ return res;
+ }
+ }
+
+ /*
+ * HostBuffer Systems
+ */
+ p_adapter_info->n_rx_host_buffers = 0;
+ p_adapter_info->n_tx_host_buffers = 0;
+
+ p_adapter_info->fpga_info.mp_nthw_epp = NULL;
+ if (nthw_epp_present(p_adapter_info->fpga_info.mp_fpga, 0)) {
+ p_adapter_info->fpga_info.mp_nthw_epp = nthw_epp_new();
+ if (p_adapter_info->fpga_info.mp_nthw_epp == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot create EPP\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ res = nthw_epp_init(p_adapter_info->fpga_info.mp_nthw_epp,
+ p_adapter_info->fpga_info.mp_fpga, 0);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot initialize EPP\n",
+ p_adapter_id_str);
+ return res;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: Initialized EPP\n",
+ p_adapter_id_str);
+
+ res = nthw_epp_setup(p_adapter_info->fpga_info.mp_nthw_epp);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot setup EPP\n",
+ p_adapter_id_str);
+ return res;
+ }
+ }
+
+ /* Nt4ga Stat init/setup */
+ res = nt4ga_stat_init(p_adapter_info);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot initialize the statistics module\n",
+ p_adapter_id_str);
+ return res;
+ }
+ res = nt4ga_stat_setup(p_adapter_info);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot setup the statistics module\n",
+ p_adapter_id_str);
+ return res;
+ }
+
+ return 0;
+}
+
+int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info)
+{
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ int i;
+ int res;
+ struct nt_sensor_group *cur_adapter_sensor = NULL;
+ struct nt_sensor_group *next_adapter_sensor = NULL;
+ struct nim_sensor_group *cur_nim_sensor = NULL;
+ struct nim_sensor_group *next_nim_sensor = NULL;
+
+ stop_monitor_tasks(-1);
+
+ nt4ga_stat_stop(p_adapter_info);
+
+ nthw_fpga_shutdown(&p_adapter_info->fpga_info);
+
+ /* Rac rab reset flip flop */
+ res = nthw_rac_rab_reset(fpga_info->mp_nthw_rac);
+
+ /* Free adapter port ident strings */
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ if (p_adapter_info->mp_port_id_str[i]) {
+ free(p_adapter_info->mp_port_id_str[i]);
+ p_adapter_info->mp_port_id_str[i] = NULL;
+ }
+ }
+
+ /* Free adapter ident string */
+ if (p_adapter_info->mp_adapter_id_str) {
+ free(p_adapter_info->mp_adapter_id_str);
+ p_adapter_info->mp_adapter_id_str = NULL;
+ }
+
+ /* Free devname ident string */
+ if (p_adapter_info->p_dev_name) {
+ free(p_adapter_info->p_dev_name);
+ p_adapter_info->p_dev_name = NULL;
+ }
+
+ /* Free adapter sensors */
+ if (p_adapter_info->adapter_sensors != NULL) {
+ do {
+ cur_adapter_sensor = p_adapter_info->adapter_sensors;
+ next_adapter_sensor =
+ p_adapter_info->adapter_sensors->next;
+ p_adapter_info->adapter_sensors = next_adapter_sensor;
+
+ sensor_deinit(cur_adapter_sensor);
+ } while (next_adapter_sensor != NULL);
+ }
+
+ /* Free NIM sensors */
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ if (p_adapter_info->nim_sensors[i] != NULL) {
+ do {
+ cur_nim_sensor = p_adapter_info->nim_sensors[i];
+ next_nim_sensor =
+ p_adapter_info->nim_sensors[i]->next;
+ p_adapter_info->nim_sensors[i] = next_nim_sensor;
+ free(cur_nim_sensor->sensor);
+ free(cur_nim_sensor);
+ } while (next_nim_sensor != NULL);
+ }
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.h b/drivers/net/ntnic/adapter/nt4ga_adapter.h
new file mode 100644
index 0000000000..6ae78a3743
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NT4GA_ADAPTER_H_
+#define _NT4GA_ADAPTER_H_
+
+#include "common_adapter_defs.h"
+
+struct adapter_info_s;
+
+/*
+ * DN-0060 section 9
+ */
+typedef struct hw_info_s {
+ /* pciids */
+ uint16_t pci_vendor_id;
+ uint16_t pci_device_id;
+ uint16_t pci_sub_vendor_id;
+ uint16_t pci_sub_device_id;
+ uint16_t pci_class_id;
+
+ /* Derived from pciid */
+ nthw_adapter_id_t n_nthw_adapter_id;
+ int hw_platform_id;
+ int hw_product_type;
+ int hw_reserved1;
+} hw_info_t;
+
+/*
+ * Services provided by the adapter module
+ */
+#include "nt4ga_pci_ta_tg.h"
+#include "nt4ga_filter.h"
+#include "nt4ga_stat.h"
+#include "nt4ga_link.h"
+
+#include "sensors.h"
+#include "i2c_nim.h"
+#include "sensor_types.h"
+
+typedef struct adapter_info_s {
+ struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg;
+ struct nt4ga_stat_s nt4ga_stat;
+ struct nt4ga_filter_s nt4ga_filter;
+ struct nt4ga_link_s nt4ga_link;
+
+ struct hw_info_s hw_info;
+ struct fpga_info_s fpga_info;
+
+ uint16_t adapter_sensors_cnt;
+ uint16_t nim_sensors_cnt[NUM_ADAPTER_PORTS_MAX];
+ struct nt_sensor_group *adapter_sensors;
+ struct nim_sensor_group *nim_sensors[NUM_ADAPTER_PORTS_MAX];
+
+ char *mp_port_id_str[NUM_ADAPTER_PORTS_MAX];
+ char *mp_adapter_id_str;
+ char *p_dev_name;
+ volatile bool *pb_shutdown;
+
+ int adapter_no;
+ int n_rx_host_buffers;
+ int n_tx_host_buffers;
+} adapter_info_t;
+
+/*
+ * Monitor task operations. This structure defines the management hooks for
+ * Napatech network devices. The following hooks can be defined; unless noted
+ * otherwise, they are optional and can be filled with a null pointer.
+ *
+ * int (*mto_open)(int adapter, int port);
+ * The function to call when a network device transitions to the up state,
+ * e.g., `ip link set <interface> up`.
+ *
+ * int (*mto_stop)(int adapter, int port);
+ * The function to call when a network device transitions to the down state,
+ * e.g., `ip link set <interface> down`.
+ */
+struct monitor_task_ops {
+ int (*mto_open)(int adapter, int port);
+ int (*mto_stop)(int adapter, int port);
+};
+
+#include <pthread.h>
+#include <signal.h>
+
+/* The file nt4ga_adapter.c defines the next four variables. */
+extern pthread_t monitor_tasks[NUM_ADAPTER_MAX];
+extern volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
+
+/*
+ * Function that sets up signal handler(s) that stop the monitoring tasks.
+ */
+int set_up_signal_handlers_to_stop_monitoring_tasks(void);
+
+int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info);
+int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info);
+
+int nt4ga_adapter_status(struct adapter_info_s *p_adapter_info);
+int nt4ga_adapter_transmit_packet(struct adapter_info_s *p_adapter_info,
+ int n_intf_no, uint8_t *p_pkt, int n_pkt_len);
+
+int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh);
+
+/* SPI for sensors reading */
+nthw_spis_t *new_sensors_t_spi(struct nt_fpga_s *p_fpga);
+
+#endif /* _NT4GA_ADAPTER_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_filter.h b/drivers/net/ntnic/adapter/nt4ga_filter.h
new file mode 100644
index 0000000000..ad7e7d8c71
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_filter.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_FILTER_H_
+#define NT4GA_FILTER_H_
+
+typedef struct nt4ga_filter_s {
+ int n_intf_cnt;
+ int n_queues_per_intf_cnt;
+
+ struct flow_nic_dev *mp_flow_device;
+} nt4ga_filter_t;
+
+#endif /* NT4GA_FILTER_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_link.c b/drivers/net/ntnic/adapter/nt4ga_link.c
new file mode 100644
index 0000000000..7fbdb72897
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link.c
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nt4ga_adapter.h"
+
+#include "nt4ga_link.h"
+#include "nt_util.h"
+
+/*
+ * port: speed capabilitoes
+ * This is actually an adapter capability mapped onto every port
+ */
+uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p _unused,
+ int port _unused)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ const uint32_t nt_link_speed_capa = p_link->speed_capa;
+ return nt_link_speed_capa;
+}
+
+/*
+ * port: nim present
+ */
+bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ const bool nim_present = p_link->link_state[port].nim_present;
+ return nim_present;
+}
+
+/*
+ * port: link mode
+ */
+void nt4ga_port_set_adm_state(struct adapter_info_s *p, int port, bool adm_state)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_disable = !adm_state;
+}
+
+bool nt4ga_port_get_adm_state(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ const bool adm_state = !p_link->port_action[port].port_disable;
+ return adm_state;
+}
+
+/*
+ * port: link status
+ */
+void nt4ga_port_set_link_status(struct adapter_info_s *p, int port,
+ bool link_status)
+{
+ /* Setting link state/status is (currently) the same as controlling the port adm state */
+ nt4ga_port_set_adm_state(p, port, link_status);
+}
+
+bool nt4ga_port_get_link_status(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ bool status = p_link->link_state[port].link_up;
+ return status;
+}
+
+/*
+ * port: link speed
+ */
+void nt4ga_port_set_link_speed(struct adapter_info_s *p, int port,
+ nt_link_speed_t speed)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_speed = speed;
+ p_link->link_info[port].link_speed = speed;
+}
+
+nt_link_speed_t nt4ga_port_get_link_speed(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ nt_link_speed_t speed = p_link->link_info[port].link_speed;
+ return speed;
+}
+
+/*
+ * port: link autoneg
+ * Currently not fully supported by link code
+ */
+void nt4ga_port_set_link_autoneg(struct adapter_info_s *p _unused,
+ int port _unused, bool autoneg _unused)
+{
+ nt4ga_link_t *const p_link _unused = &p->nt4ga_link;
+}
+
+bool nt4ga_port_get_link_autoneg(struct adapter_info_s *p _unused,
+ int port _unused)
+{
+ nt4ga_link_t *const p_link _unused = &p->nt4ga_link;
+ return true;
+}
+
+/*
+ * port: link duplex
+ * Currently not fully supported by link code
+ */
+void nt4ga_port_set_link_duplex(struct adapter_info_s *p, int port,
+ nt_link_duplex_t duplex)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_duplex = duplex;
+}
+
+nt_link_duplex_t nt4ga_port_get_link_duplex(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ nt_link_duplex_t duplex = p_link->link_info[port].link_duplex;
+ return duplex;
+}
+
+/*
+ * port: loopback mode
+ */
+void nt4ga_port_set_loopback_mode(struct adapter_info_s *p, int port,
+ uint32_t mode)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_lpbk_mode = mode;
+}
+
+uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ return p_link->port_action[port].port_lpbk_mode;
+}
+
+/*
+ * port: nim capabilities
+ */
+nim_i2c_ctx_t nt4ga_port_get_nim_capabilities(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ nim_i2c_ctx_t nim_ctx = p_link->u.var100g.nim_ctx[port];
+ return nim_ctx;
+}
+
+/*
+ * port: tx power
+ */
+int nt4ga_port_tx_power(struct adapter_info_s *p, int port, bool disable)
+{
+ nt4ga_link_t *link_info = &p->nt4ga_link;
+
+ if (link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28_SR4 ||
+ link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28 ||
+ link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28_LR4) {
+ nim_i2c_ctx_t *nim_ctx = &link_info->u.var100g.nim_ctx[port];
+
+ if (!nim_ctx->specific_u.qsfp.rx_only) {
+ if (nim_qsfp_plus_nim_set_tx_laser_disable(nim_ctx, disable,
+ -1) != 0)
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_link.h b/drivers/net/ntnic/adapter/nt4ga_link.h
new file mode 100644
index 0000000000..2be9f49075
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_LINK_H_
+#define NT4GA_LINK_H_
+
+#include "common_adapter_defs.h"
+#include "nthw_drv.h"
+#include "i2c_nim.h"
+#include "nthw_fpga_rst_nt200a0x.h"
+
+/*
+ * Link state.\n
+ * Just after start of ntservice the link state might be unknown since the
+ * monitoring routine is busy reading NIM state and NIM data. This might also
+ * be the case after a NIM is plugged into an interface.
+ * The error state indicates a HW reading error.
+ */
+enum nt_link_state_e {
+ NT_LINK_STATE_UNKNOWN = 0, /* The link state has not been read yet */
+ NT_LINK_STATE_DOWN = 1, /* The link state is DOWN */
+ NT_LINK_STATE_UP = 2, /* The link state is UP */
+ NT_LINK_STATE_ERROR = 3 /* The link state could not be read */
+};
+
+typedef enum nt_link_state_e nt_link_state_t, *nt_link_state_p;
+
+/*
+ * Link duplex mode
+ */
+enum nt_link_duplex_e {
+ NT_LINK_DUPLEX_UNKNOWN = 0,
+ NT_LINK_DUPLEX_HALF = 0x01, /* Half duplex */
+ NT_LINK_DUPLEX_FULL = 0x02, /* Full duplex */
+};
+
+typedef enum nt_link_duplex_e nt_link_duplex_t;
+
+/*
+ * Link loopback mode
+ */
+enum nt_link_loopback_e {
+ NT_LINK_LOOPBACK_OFF = 0,
+ NT_LINK_LOOPBACK_HOST = 0x01, /* Host loopback mode */
+ NT_LINK_LOOPBACK_LINE = 0x02, /* Line loopback mode */
+};
+
+/*
+ * Link MDI mode
+ */
+enum nt_link_mdi_e {
+ NT_LINK_MDI_NA = 0,
+ NT_LINK_MDI_AUTO = 0x01, /* MDI auto */
+ NT_LINK_MDI_MDI = 0x02, /* MDI mode */
+ NT_LINK_MDI_MDIX = 0x04, /* MDIX mode */
+};
+
+typedef enum nt_link_mdi_e nt_link_mdi_t;
+
+/*
+ * Link Auto/Manual mode
+ */
+enum nt_link_auto_neg_e {
+ NT_LINK_AUTONEG_NA = 0,
+ NT_LINK_AUTONEG_MANUAL = 0x01,
+ NT_LINK_AUTONEG_OFF = NT_LINK_AUTONEG_MANUAL, /* Auto negotiation OFF */
+ NT_LINK_AUTONEG_AUTO = 0x02,
+ NT_LINK_AUTONEG_ON = NT_LINK_AUTONEG_AUTO, /* Auto negotiation ON */
+};
+
+typedef enum nt_link_auto_neg_e nt_link_auto_neg_t;
+
+/*
+ * Callback functions to setup mac, pcs and phy
+ */
+typedef struct link_state_s {
+ bool link_disabled;
+ bool nim_present;
+ bool lh_nim_absent;
+ bool link_up;
+ enum nt_link_state_e link_state;
+ enum nt_link_state_e link_state_latched;
+} link_state_t;
+
+typedef struct link_info_s {
+ enum nt_link_speed_e link_speed;
+ enum nt_link_duplex_e link_duplex;
+ enum nt_link_auto_neg_e link_auto_neg;
+} link_info_t;
+
+typedef struct port_action_s {
+ bool port_disable;
+ enum nt_link_speed_e port_speed;
+ enum nt_link_duplex_e port_duplex;
+ uint32_t port_lpbk_mode;
+} port_action_t;
+
+typedef struct adapter_100g_s {
+ nim_i2c_ctx_t
+ nim_ctx[NUM_ADAPTER_PORTS_MAX]; /* Should be the first field */
+ nthw_mac_pcs_t mac_pcs100g[NUM_ADAPTER_PORTS_MAX];
+ nthw_gpio_phy_t gpio_phy[NUM_ADAPTER_PORTS_MAX];
+} adapter_100g_t;
+
+typedef union adapter_var_s {
+ nim_i2c_ctx_t nim_ctx
+ [NUM_ADAPTER_PORTS_MAX]; /* First field in all the adaptors type */
+ adapter_100g_t var100g;
+} adapter_var_u;
+
+typedef struct nt4ga_link_s {
+ link_state_t link_state[NUM_ADAPTER_PORTS_MAX];
+ link_info_t link_info[NUM_ADAPTER_PORTS_MAX];
+ port_action_t port_action[NUM_ADAPTER_PORTS_MAX];
+ uint32_t speed_capa;
+ /* */
+ bool variables_initialized;
+ adapter_var_u u;
+} nt4ga_link_t;
+
+bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port);
+
+/*
+ * port:s link mode
+ */
+void nt4ga_port_set_adm_state(struct adapter_info_s *p, int port,
+ bool adm_state);
+bool nt4ga_port_get_adm_state(struct adapter_info_s *p, int port);
+
+/*
+ * port:s link status
+ */
+void nt4ga_port_set_link_status(struct adapter_info_s *p, int port, bool status);
+bool nt4ga_port_get_link_status(struct adapter_info_s *p, int port);
+
+/*
+ * port: link autoneg
+ */
+void nt4ga_port_set_link_autoneg(struct adapter_info_s *p, int port,
+ bool autoneg);
+bool nt4ga_port_get_link_autoneg(struct adapter_info_s *p, int port);
+
+/*
+ * port: link speed
+ */
+void nt4ga_port_set_link_speed(struct adapter_info_s *p, int port,
+ nt_link_speed_t speed);
+nt_link_speed_t nt4ga_port_get_link_speed(struct adapter_info_s *p, int port);
+
+/*
+ * port: link duplex
+ */
+void nt4ga_port_set_link_duplex(struct adapter_info_s *p, int port,
+ nt_link_duplex_t duplex);
+nt_link_duplex_t nt4ga_port_get_link_duplex(struct adapter_info_s *p, int port);
+
+/*
+ * port: loopback mode
+ */
+void nt4ga_port_set_loopback_mode(struct adapter_info_s *p, int port,
+ uint32_t mode);
+uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port);
+
+uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p,
+ int port);
+
+/*
+ * port: nim capabilities
+ */
+nim_i2c_ctx_t nt4ga_port_get_nim_capabilities(struct adapter_info_s *p,
+ int port);
+
+/*
+ * port: tx power
+ */
+int nt4ga_port_tx_power(struct adapter_info_s *p, int port, bool disable);
+
+#endif /* NT4GA_LINK_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_link_100g.c b/drivers/net/ntnic/adapter/nt4ga_link_100g.c
new file mode 100644
index 0000000000..8465b6a341
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link_100g.c
@@ -0,0 +1,825 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+#include "i2c_nim.h"
+#include "nt4ga_adapter.h"
+#include "nt4ga_link_100g.h"
+
+#include <string.h> /* memcmp, memset */
+
+/*
+ * Prototypes
+ */
+static int swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs,
+ int port, bool swap);
+static int reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs);
+
+/*
+ * Structs and types definitions
+ */
+enum link_up_state {
+ RESET, /* A valid signal is detected by NO local faults. */
+ EXPECT_NO_LF, /* After that we check NO latched local fault bit before */
+ /* de-asserting Remote fault indication. */
+ WAIT_STABLE_LINK, /* Now we expect the link is up. */
+ MONITOR_LINK /* After link-up we monitor link state. */
+};
+
+typedef struct _monitoring_state {
+ /* Fields below are set by monitoring thread */
+ enum link_up_state m_link_up_state;
+ enum nt_link_state_e link_state;
+ enum nt_link_state_e latch_link_state;
+ int m_time_out;
+} monitoring_state_t, *monitoring_state_p;
+
+/*
+ * Global variables
+ */
+
+/*
+ * External state, to be set by the network driver.
+ */
+
+/*
+ * Utility functions
+ */
+
+static void set_loopback(struct adapter_info_s *p_adapter_info,
+ nthw_mac_pcs_t *mac_pcs, int intf_no, uint32_t mode,
+ uint32_t last_mode)
+{
+ bool swap_polerity = true;
+
+ switch (mode) {
+ case 1:
+ NT_LOG(INF, ETHDEV, "%s: Applying host loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_fec(mac_pcs, true);
+ nthw_mac_pcs_set_host_loopback(mac_pcs, true);
+ swap_polerity = false;
+ break;
+ case 2:
+ NT_LOG(INF, ETHDEV, "%s: Applying line loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_line_loopback(mac_pcs, true);
+ break;
+ default:
+ switch (last_mode) {
+ case 1:
+ NT_LOG(INF, ETHDEV, "%s: Removing host loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_host_loopback(mac_pcs, false);
+ break;
+ case 2:
+ NT_LOG(INF, ETHDEV, "%s: Removing line loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_line_loopback(mac_pcs, false);
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+ break;
+ }
+
+ if ((p_adapter_info->fpga_info.nthw_hw_info.hw_id == 2 &&
+ p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01) ||
+ p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A02) {
+ (void)swap_tx_rx_polarity(p_adapter_info, mac_pcs, intf_no,
+ swap_polerity);
+ }
+
+ /* After changing the loopback the system must be properly reset */
+ reset_rx(p_adapter_info, mac_pcs);
+
+ NT_OS_WAIT_USEC(10000); /* 10ms - arbitrary choice */
+
+ if (!nthw_mac_pcs_is_rx_path_rst(mac_pcs)) {
+ nthw_mac_pcs_reset_bip_counters(mac_pcs);
+ if (!nthw_mac_pcs_get_fec_bypass(mac_pcs))
+ nthw_mac_pcs_reset_fec_counters(mac_pcs);
+ }
+}
+
+/*
+ * Function to retrieve the current state of a link (for one port)
+ */
+static int link_state_build(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs,
+ nthw_gpio_phy_t *gpio_phy, int port,
+ link_state_t *state, bool is_port_disabled)
+{
+ uint32_t abs;
+ uint32_t phy_link_state;
+ uint32_t lh_abs;
+ uint32_t ll_phy_link_state;
+ uint32_t link_down_cnt;
+ uint32_t nim_interr;
+ uint32_t lh_local_fault;
+ uint32_t lh_remote_fault;
+ uint32_t lh_internal_local_fault;
+ uint32_t lh_received_local_fault;
+
+ memset(state, 0, sizeof(*state));
+ state->link_disabled = is_port_disabled;
+ nthw_mac_pcs_get_link_summary(mac_pcs, &abs, &phy_link_state, &lh_abs,
+ &ll_phy_link_state, &link_down_cnt,
+ &nim_interr, &lh_local_fault,
+ &lh_remote_fault, &lh_internal_local_fault,
+ &lh_received_local_fault);
+
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ state->nim_present =
+ nthw_gpio_phy_is_module_present(gpio_phy, (uint8_t)port);
+ state->lh_nim_absent = !state->nim_present;
+ state->link_up = phy_link_state ? true : false;
+
+ {
+ static char lsbuf[NUM_ADAPTER_MAX][NUM_ADAPTER_PORTS_MAX][256];
+ char buf[255];
+ const int adapter_no = drv->adapter_no;
+
+ snprintf(buf, sizeof(buf),
+ "%s: Port = %d: abs = %u, phy_link_state = %u, lh_abs = %u, "
+ "ll_phy_link_state = %u, link_down_cnt = %u, nim_interr = %u, "
+ "lh_local_fault = %u, lh_remote_fault = %u, lh_internal_local_fault = %u, "
+ "lh_received_local_fault = %u",
+ drv->mp_adapter_id_str, mac_pcs->mn_instance, abs,
+ phy_link_state, lh_abs, ll_phy_link_state,
+ link_down_cnt, nim_interr, lh_local_fault,
+ lh_remote_fault, lh_internal_local_fault,
+ lh_received_local_fault);
+ if (strcmp(lsbuf[adapter_no][port], buf) != 0) {
+ rte_strscpy(lsbuf[adapter_no][port], buf,
+ sizeof(lsbuf[adapter_no][port]) - 1U);
+ lsbuf[adapter_no][port]
+ [sizeof(lsbuf[adapter_no][port]) - 1U] = '\0';
+ NT_LOG(DBG, ETHDEV, "%s\n", lsbuf[adapter_no][port]);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Check whether a NIM module is present
+ */
+static bool nim_is_present(nthw_gpio_phy_t *gpio_phy, uint8_t if_no)
+{
+ assert(if_no < NUM_ADAPTER_PORTS_MAX);
+
+ return nthw_gpio_phy_is_module_present(gpio_phy, if_no);
+}
+
+/*
+ * Enable RX
+ */
+static int enable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_rx_enable(mac_pcs, true);
+ return 0;
+}
+
+/*
+ * Enable TX
+ */
+static int enable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_tx_enable(mac_pcs, true);
+ nthw_mac_pcs_set_tx_sel_host(mac_pcs, true);
+ return 0;
+}
+
+/*
+ * Disable RX
+ */
+static int disable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_rx_enable(mac_pcs, false);
+ return 0;
+}
+
+/*
+ * Disable TX
+ */
+static int disable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_tx_enable(mac_pcs, false);
+ nthw_mac_pcs_set_tx_sel_host(mac_pcs, false);
+ return 0;
+}
+
+/*
+ * Reset RX
+ */
+static int reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv;
+
+ nthw_mac_pcs_rx_path_rst(mac_pcs, true);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+ nthw_mac_pcs_rx_path_rst(mac_pcs, false);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+
+ return 0;
+}
+
+/*
+ * Reset TX
+ */
+
+/*
+ * Swap tx/rx polarity
+ */
+static int swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs,
+ int port, bool swap)
+{
+ const bool tx_polarity_swap[2][4] = { { true, true, false, false },
+ { false, true, false, false }
+ };
+ const bool rx_polarity_swap[2][4] = { { false, true, true, true },
+ { false, true, true, false }
+ };
+ uint8_t lane;
+
+ (void)drv;
+ for (lane = 0U; lane < 4U; lane++) {
+ if (swap) {
+ nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane,
+ tx_polarity_swap[port][lane]);
+ nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane,
+ rx_polarity_swap[port][lane]);
+ } else {
+ nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane, false);
+ nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane, false);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Check link once NIM is installed and link can be expected.
+ */
+static int check_link_state(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ bool rst_required;
+ bool ber;
+ bool fec_all_locked;
+
+ rst_required = nthw_mac_pcs_reset_required(mac_pcs);
+
+ ber = nthw_mac_pcs_get_hi_ber(mac_pcs);
+
+ fec_all_locked = nthw_mac_pcs_get_fec_stat_all_am_locked(mac_pcs);
+
+ if (rst_required || ber || !fec_all_locked)
+ reset_rx(drv, mac_pcs);
+
+ return 0;
+}
+
+/*
+ * Initialize NIM, Code based on nt200e3_2_ptp.cpp: MyPort::createNim()
+ */
+static int create_nim(adapter_info_t *drv, nt_fpga_t *fpga, int port,
+ bool enable)
+{
+ int res = 0;
+ const uint8_t valid_nim_id = 17U;
+ nthw_gpio_phy_t *gpio_phy;
+ nim_i2c_ctx_t *nim_ctx;
+ sfp_nim_state_t nim;
+ nt4ga_link_t *link_info = &drv->nt4ga_link;
+ nthw_mac_pcs_t *mac_pcs = &link_info->u.var100g.mac_pcs100g[port];
+
+ (void)fpga; /* unused */
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ assert(link_info->variables_initialized);
+
+ gpio_phy = &link_info->u.var100g.gpio_phy[port];
+ nim_ctx = &link_info->u.var100g.nim_ctx[port];
+
+ /*
+ * Check NIM is present before doing GPIO PHY reset.
+ */
+ if (!nim_is_present(gpio_phy, (uint8_t)port)) {
+ NT_LOG(INF, ETHDEV, "%s: NIM module is absent\n",
+ drv->mp_port_id_str[port]);
+ return 0;
+ }
+
+ if (!enable) {
+ disable_rx(drv, mac_pcs);
+ disable_tx(drv, mac_pcs);
+ reset_rx(drv, mac_pcs);
+ }
+
+ /*
+ * Perform PHY reset.
+ */
+ NT_LOG(DBG, ETHDEV, "%s: Performing NIM reset\n",
+ drv->mp_port_id_str[port]);
+ nthw_gpio_phy_set_reset(gpio_phy, (uint8_t)port, true);
+ NT_OS_WAIT_USEC(100000); /* pause 0.1s */
+ nthw_gpio_phy_set_reset(gpio_phy, (uint8_t)port, false);
+
+ /*
+ * Wait a little after a module has been inserted before trying to access I2C
+ * data, otherwise the module will not respond correctly.
+ */
+ NT_OS_WAIT_USEC(1000000); /* pause 1.0s */
+
+ if (!nim_is_present(gpio_phy, (uint8_t)port)) {
+ NT_LOG(DBG, ETHDEV, "%s: NIM module is no longer absent!\n",
+ drv->mp_port_id_str[port]);
+ return -1;
+ }
+
+ res = construct_and_preinit_nim(nim_ctx, NULL, port,
+ ((struct adapter_info_s *)drv)->nim_sensors,
+ &((struct adapter_info_s *)drv)->nim_sensors_cnt[port]);
+ if (res)
+ return res;
+
+ res = nim_state_build(nim_ctx, &nim);
+ if (res)
+ return res;
+
+ NT_LOG(DBG, NTHW,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n",
+ drv->mp_port_id_str[port], nim_ctx->nim_id,
+ nim_id_to_text(nim_ctx->nim_id), nim.br, nim_ctx->vendor_name,
+ nim_ctx->prod_no, nim_ctx->serial_no);
+
+ /*
+ * Does the driver support the NIM module type?
+ */
+ if (nim_ctx->nim_id != valid_nim_id) {
+ NT_LOG(ERR, NTHW,
+ "%s: The driver does not support the NIM module type %s\n",
+ drv->mp_port_id_str[port], nim_id_to_text(nim_ctx->nim_id));
+ NT_LOG(DBG, NTHW,
+ "%s: The driver supports the NIM module type %s\n",
+ drv->mp_port_id_str[port], nim_id_to_text(valid_nim_id));
+ return -1;
+ }
+
+ if (enable) {
+ NT_LOG(DBG, ETHDEV, "%s: De-asserting low power\n",
+ drv->mp_port_id_str[port]);
+ nthw_gpio_phy_set_low_power(gpio_phy, (uint8_t)port, false);
+ } else {
+ NT_LOG(DBG, ETHDEV, "%s: Asserting low power\n",
+ drv->mp_port_id_str[port]);
+ nthw_gpio_phy_set_low_power(gpio_phy, (uint8_t)port, true);
+ }
+
+ return res;
+}
+
+/*
+ * Initialize one 100 Gbps port.
+ * The function shall not assume anything about the state of the adapter
+ * and/or port.
+ */
+static int port_init(adapter_info_t *drv, nt_fpga_t *fpga, int port)
+{
+ int adapter_id;
+ int hw_id;
+ int res;
+ nt4ga_link_t *link_info = &drv->nt4ga_link;
+
+ nthw_mac_pcs_t *mac_pcs;
+
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ assert(link_info->variables_initialized);
+
+ if (fpga && fpga->p_fpga_info) {
+ adapter_id = fpga->p_fpga_info->n_nthw_adapter_id;
+ hw_id = fpga->p_fpga_info->nthw_hw_info.hw_id;
+ } else {
+ adapter_id = -1;
+ hw_id = -1;
+ }
+
+ mac_pcs = &link_info->u.var100g.mac_pcs100g[port];
+
+ /*
+ * Phase 1. Pre-state machine (`port init` functions)
+ * 1.1) Nt4gaAdapter::portInit()
+ */
+
+ /* No adapter set-up here, only state variables */
+
+ /* 1.2) MyPort::init() */
+ link_info->link_info[port].link_speed = NT_LINK_SPEED_100G;
+ link_info->link_info[port].link_duplex = NT_LINK_DUPLEX_FULL;
+ link_info->link_info[port].link_auto_neg = NT_LINK_AUTONEG_OFF;
+ link_info->speed_capa |= NT_LINK_SPEED_100G;
+ nthw_mac_pcs_set_led_mode(mac_pcs, NTHW_MAC_PCS_LED_AUTO);
+ nthw_mac_pcs_set_receiver_equalization_mode(mac_pcs,
+ nthw_mac_pcs_receiver_mode_lpm);
+
+ /*
+ * NT200A01 build 2 HW and NT200A02 that require GTY polarity swap
+ * if (adapter is `NT200A01 build 2 HW or NT200A02`)
+ */
+ if (adapter_id == NT_HW_ADAPTER_ID_NT200A02 ||
+ (adapter_id == NT_HW_ADAPTER_ID_NT200A01 && hw_id == 2))
+ (void)swap_tx_rx_polarity(drv, mac_pcs, port, true);
+
+ nthw_mac_pcs_set_ts_eop(mac_pcs, true); /* end-of-frame timestamping */
+
+ /* Work in ABSOLUTE timing mode, don't set IFG mode. */
+
+ /* Phase 2. Pre-state machine (`setup` functions) */
+
+ /* 2.1) nt200a0x.cpp:Myport::setup() */
+ NT_LOG(DBG, ETHDEV, "%s: Setting up port %d\n", drv->mp_port_id_str[port],
+ port);
+
+ NT_LOG(DBG, ETHDEV, "%s: Port %d: PHY TX enable\n",
+ drv->mp_port_id_str[port], port);
+ enable_tx(drv, mac_pcs);
+ reset_rx(drv, mac_pcs);
+
+ /* 2.2) Nt4gaPort::setup() */
+ if (nthw_gmf_init(NULL, fpga, port) == 0) {
+ nthw_gmf_t gmf;
+
+ if (nthw_gmf_init(&gmf, fpga, port) == 0)
+ nthw_gmf_set_enable(&gmf, true);
+ }
+
+ /* Phase 3. Link state machine steps */
+
+ /* 3.1) Create NIM, ::createNim() */
+ res = create_nim(drv, fpga, port, true);
+
+ if (res) {
+ NT_LOG(WRN, ETHDEV, "%s: NIM initialization failed\n",
+ drv->mp_port_id_str[port]);
+ return res;
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: NIM initialized\n", drv->mp_port_id_str[port]);
+
+ /* 3.2) MyPort::nimReady() */
+
+ /* 3.3) MyPort::nimReady100Gb() */
+
+ /* Setting FEC resets the lane counter in one half of the GMF */
+ nthw_mac_pcs_set_fec(mac_pcs, true);
+ NT_LOG(DBG, ETHDEV, "%s: Port %d: HOST FEC enabled\n",
+ drv->mp_port_id_str[port], port);
+
+ if (adapter_id == NT_HW_ADAPTER_ID_NT200A01 && hw_id == 1) {
+ const uint8_t tuning_s_r4[2][4][3] = { { { 8, 15, 8 },
+ { 8, 15, 9 },
+ { 7, 15, 9 },
+ { 6, 15, 8 }
+ },
+ { { 6, 15, 8 },
+ { 3, 15, 12 },
+ { 7, 15, 9 },
+ { 7, 15, 8 }
+ }
+ };
+
+ uint8_t lane = 0;
+
+ for (lane = 0; lane < 4; lane++) {
+ uint8_t pre, diff, post;
+
+ /* Use short-range tuning values */
+ pre = tuning_s_r4[port][lane][0];
+ diff = tuning_s_r4[port][lane][1];
+ post = tuning_s_r4[port][lane][2];
+
+ nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff,
+ post);
+ }
+ } else if ((adapter_id == NT_HW_ADAPTER_ID_NT200A02) ||
+ ((adapter_id == NT_HW_ADAPTER_ID_NT200A01) &&
+ (hw_id == 2))) {
+ const uint8_t pre = 5;
+ const uint8_t diff = 25;
+ const uint8_t post = 12;
+
+ uint8_t lane = 0;
+
+ for (lane = 0; lane < 4; lane++) {
+ nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff,
+ post);
+ }
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Unhandled AdapterId/HwId: %02x_hwid%d\n", __func__,
+ adapter_id, hw_id);
+ assert(0);
+ }
+ reset_rx(drv, mac_pcs);
+
+ /*
+ * 3.4) MyPort::setLinkState()
+ *
+ * Compensation = 1640 - dly
+ * CMAC-core dly 188 ns
+ * FEC no correction 87 ns
+ * FEC active correction 211
+ */
+ if (nthw_mac_pcs_get_fec_valid(mac_pcs))
+ nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 211));
+
+ else
+ nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 87));
+
+ /* 3.5) uint32_t MyPort::macConfig(nt_link_state_t link_state) */
+ enable_rx(drv, mac_pcs);
+
+ nthw_mac_pcs_set_host_loopback(mac_pcs, false);
+
+ return res;
+}
+
+/*
+ * State machine shared between kernel and userland
+ */
+static int common_ptp_nim_state_machine(void *data)
+{
+ adapter_info_t *drv = (adapter_info_t *)data;
+ fpga_info_t *fpga_info = &drv->fpga_info;
+ nt4ga_link_t *link_info = &drv->nt4ga_link;
+ nt_fpga_t *fpga = fpga_info->mp_fpga;
+ const int adapter_no = drv->adapter_no;
+ const int nb_ports = fpga_info->n_phy_ports;
+ uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+
+ nim_i2c_ctx_t *nim_ctx;
+ link_state_t *link_state;
+ nthw_mac_pcs_t *mac_pcs;
+ nthw_gpio_phy_t *gpio_phy;
+
+ if (!fpga) {
+ NT_LOG(ERR, ETHDEV, "%s: fpga is NULL\n", drv->mp_adapter_id_str);
+ goto NT4GA_LINK_100G_MON_EXIT;
+ }
+
+ assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+ nim_ctx = link_info->u.var100g.nim_ctx;
+ link_state = link_info->link_state;
+ mac_pcs = link_info->u.var100g.mac_pcs100g;
+ gpio_phy = link_info->u.var100g.gpio_phy;
+
+ monitor_task_is_running[adapter_no] = 1;
+ memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+
+ if (monitor_task_is_running[adapter_no]) {
+ NT_LOG(DBG, ETHDEV, "%s: link state machine running...\n",
+ drv->mp_adapter_id_str);
+ }
+
+ while (monitor_task_is_running[adapter_no]) {
+ int i;
+ static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
+
+ /* Read sensors */
+ if (drv->adapter_sensors != NULL) {
+ nthw_spis_t *t_spi =
+ new_sensors_t_spi(drv->fpga_info.mp_fpga);
+ if (t_spi) {
+ for (struct nt_sensor_group *ptr =
+ drv->adapter_sensors;
+ ptr != NULL; ptr = ptr->next)
+ ptr->read(ptr, t_spi);
+ nthw_spis_delete(t_spi);
+ }
+ }
+
+ for (i = 0; i < nb_ports; i++) {
+ link_state_t new_link_state;
+ const bool is_port_disabled =
+ link_info->port_action[i].port_disable;
+ const bool was_port_disabled =
+ link_state[i].link_disabled;
+ const bool disable_port = is_port_disabled &&
+ !was_port_disabled;
+ const bool enable_port = !is_port_disabled &&
+ was_port_disabled;
+
+ if (!monitor_task_is_running[adapter_no]) /* stop quickly */
+ break;
+
+ /* Reading NIM sensors */
+ if (drv->nim_sensors[i] != NULL) {
+ nthw_spis_t *t_spi = new_sensors_t_spi(drv->fpga_info.mp_fpga);
+ if (t_spi) {
+ for (struct nim_sensor_group *ptr =
+ drv->nim_sensors[i];
+ ptr != NULL; ptr = ptr->next)
+ ptr->read(ptr, t_spi);
+ nthw_spis_delete(t_spi);
+ }
+ }
+
+ /* Has the administrative port state changed? */
+ assert(!(disable_port && enable_port));
+ if (disable_port) {
+ memset(&link_state[i], 0,
+ sizeof(link_state[i]));
+ link_state[i].link_disabled = true;
+ reported_link[i] = false;
+ /* Turn off laser and LED, etc. */
+ (void)create_nim(drv, fpga, i, false);
+ NT_LOG(DBG, ETHDEV, "%s: Port %i is disabled\n",
+ drv->mp_port_id_str[i], i);
+ continue;
+ }
+
+ if (enable_port) {
+ link_state[i].link_disabled = false;
+ NT_LOG(DBG, ETHDEV, "%s: Port %i is enabled\n",
+ drv->mp_port_id_str[i], i);
+ }
+
+ if (is_port_disabled)
+ continue;
+
+ if (link_info->port_action[i].port_lpbk_mode !=
+ last_lpbk_mode[i]) {
+ /* Loopback mode has changed. Do something */
+ if (!nim_is_present(&gpio_phy[i],
+ (uint8_t)i)) {
+ /*
+ * If there is no Nim present, we need to initialize the
+ * port anyway
+ */
+ port_init(drv, fpga, i);
+ }
+ NT_LOG(INF, ETHDEV,
+ "%s: Loopback mode changed=%u\n",
+ drv->mp_port_id_str[i],
+ link_info->port_action[i].port_lpbk_mode);
+ set_loopback(drv, &mac_pcs[i], i,
+ link_info->port_action[i].port_lpbk_mode,
+ last_lpbk_mode[i]);
+ if (link_info->port_action[i].port_lpbk_mode ==
+ 1)
+ link_state[i].link_up = true;
+ last_lpbk_mode[i] =
+ link_info->port_action[i].port_lpbk_mode;
+ continue;
+ }
+
+ (void)link_state_build(drv, &mac_pcs[i], &gpio_phy[i],
+ i, &new_link_state,
+ is_port_disabled);
+ if (!new_link_state.nim_present) {
+ if (link_state[i].nim_present) {
+ NT_LOG(INF, ETHDEV,
+ "%s: NIM module removed\n",
+ drv->mp_port_id_str[i]);
+ }
+ link_state[i] = new_link_state;
+ continue;
+ }
+
+ /* NIM module is present */
+ if (new_link_state.lh_nim_absent ||
+ !link_state[i].nim_present) {
+ sfp_nim_state_t new_state;
+
+ NT_LOG(DBG, ETHDEV, "%s: NIM module inserted\n",
+ drv->mp_port_id_str[i]);
+
+ if (port_init(drv, fpga, i)) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Failed to initialize NIM module\n",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
+ if (nim_state_build(&nim_ctx[i], &new_state)) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot read basic NIM data\n",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
+ assert(new_state.br); /* Cannot be zero if NIM is present */
+ NT_LOG(DBG, ETHDEV,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n",
+ drv->mp_port_id_str[i], nim_ctx->nim_id,
+ nim_id_to_text(nim_ctx->nim_id),
+ (unsigned int)new_state.br,
+ nim_ctx->vendor_name, nim_ctx->prod_no,
+ nim_ctx->serial_no);
+
+ (void)link_state_build(drv, &mac_pcs[i],
+ &gpio_phy[i], i,
+ &link_state[i],
+ is_port_disabled);
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: NIM module initialized\n",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
+ if (reported_link[i] != new_link_state.link_up) {
+ NT_LOG(INF, ETHDEV, "%s: link is %s\n",
+ drv->mp_port_id_str[i],
+ (new_link_state.link_up ? "up" :
+ "down"));
+ link_state[i].link_up = new_link_state.link_up;
+ reported_link[i] = new_link_state.link_up;
+ }
+ check_link_state(drv, &mac_pcs[i]);
+ } /* end-for */
+ if (monitor_task_is_running[adapter_no])
+ NT_OS_WAIT_USEC(5 * 100000U); /* 5 x 0.1s = 0.5s */
+ }
+
+NT4GA_LINK_100G_MON_EXIT:
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: Stopped NT4GA 100 Gbps link monitoring thread.\n",
+ drv->mp_adapter_id_str);
+
+ return 0;
+}
+
+/*
+ * Userland NIM state machine
+ */
+static void *nt4ga_link_100g_mon(void *data)
+{
+ (void)common_ptp_nim_state_machine(data);
+
+ return NULL;
+}
+
+/*
+ * Initialize all ports
+ * The driver calls this function during initialization (of the driver).
+ */
+int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
+ nt_fpga_t *fpga)
+{
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ const int adapter_no = p_adapter_info->adapter_no;
+ const int nb_ports = fpga_info->n_phy_ports;
+ int res = 0;
+
+ NT_LOG(DBG, ETHDEV, "%s: Initializing ports\n",
+ p_adapter_info->mp_adapter_id_str);
+
+ /*
+ * Initialize global variables
+ */
+ assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+
+ if (res == 0 && !p_adapter_info->nt4ga_link.variables_initialized) {
+ nthw_mac_pcs_t *mac_pcs =
+ p_adapter_info->nt4ga_link.u.var100g.mac_pcs100g;
+ nim_i2c_ctx_t *nim_ctx =
+ p_adapter_info->nt4ga_link.u.var100g.nim_ctx;
+ nthw_gpio_phy_t *gpio_phy =
+ p_adapter_info->nt4ga_link.u.var100g.gpio_phy;
+ int i;
+
+ for (i = 0; i < nb_ports; i++) {
+ const uint8_t instance =
+ (uint8_t)(2U + i); /* 2 + adapter port number */
+ res = nthw_mac_pcs_init(&mac_pcs[i], fpga,
+ i /* int nInstance */);
+ if (res != 0)
+ break;
+ res = nthw_iic_init(&nim_ctx[i].hwiic, fpga, instance,
+ 8 /* timing */);
+ if (res != 0)
+ break;
+ nim_ctx[i].instance = instance;
+ nim_ctx[i].devaddr = 0x50; /* 0xA0 / 2 */
+ nim_ctx[i].regaddr = 0U;
+ res = nthw_gpio_phy_init(&gpio_phy[i], fpga,
+ 0 /* Only one instance */);
+ if (res != 0)
+ break;
+ }
+ if (res == 0)
+ p_adapter_info->nt4ga_link.variables_initialized = true;
+ }
+
+ /* Create state-machine thread */
+ if (res == 0) {
+ if (!monitor_task_is_running[adapter_no]) {
+ res = pthread_create(&monitor_tasks[adapter_no], NULL,
+ nt4ga_link_100g_mon, p_adapter_info);
+ }
+ }
+ return res;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_link_100g.h b/drivers/net/ntnic/adapter/nt4ga_link_100g.h
new file mode 100644
index 0000000000..803b3454b7
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link_100g.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_LINK_100G_H_
+#define NT4GA_LINK_100G_H_
+
+#include "nthw_drv.h"
+
+int nt4ga_link_100g_ports_init(adapter_info_t *p_adapter_info, nt_fpga_t *p_fpga);
+
+#endif /* NT4GA_LINK_100G_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c
new file mode 100644
index 0000000000..aaacd11f1e
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c
@@ -0,0 +1,598 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nt_util.h"
+#include "nthw_drv.h"
+#include "nt4ga_adapter.h"
+#include "nt4ga_pci_ta_tg.h"
+#include "nthw_pci_ta.h"
+#include "nthw_pci_rd_tg.h"
+#include "nthw_pci_wr_tg.h"
+
+int nt4ga_pci_ta_tg_init(struct adapter_info_s *p_adapter_info)
+{
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ nt_fpga_t *p_fpga = fpga_info->mp_fpga;
+ nt4ga_pci_ta_tg_t *p = &p_adapter_info->nt4ga_pci_ta_tg;
+ int res;
+ int n_err_cnt = 0;
+
+ if (p) {
+ memset(p, 0, sizeof(nt4ga_pci_ta_tg_t));
+ } else {
+ NT_LOG(ERR, NTHW, "%s: %s: null ptr\n", p_adapter_id_str, __func__);
+ return -1;
+ }
+
+ assert(p_fpga);
+
+ p->mp_nthw_pci_rd_tg = nthw_pci_rd_tg_new();
+ assert(p->mp_nthw_pci_rd_tg);
+ res = nthw_pci_rd_tg_init(p->mp_nthw_pci_rd_tg, p_fpga, 0);
+ if (res) {
+ n_err_cnt++;
+ NT_LOG(WRN, NTHW, "%s: module PCI_RD_TG not found\n",
+ p_adapter_id_str);
+ }
+
+ p->mp_nthw_pci_wr_tg = nthw_pci_wr_tg_new();
+ assert(p->mp_nthw_pci_wr_tg);
+ res = nthw_pci_wr_tg_init(p->mp_nthw_pci_wr_tg, p_fpga, 0);
+ if (res) {
+ n_err_cnt++;
+ NT_LOG(WRN, NTHW, "%s: module PCI_WR_TG not found\n",
+ p_adapter_id_str);
+ }
+
+ p->mp_nthw_pci_ta = nthw_pci_ta_new();
+ assert(p->mp_nthw_pci_ta);
+ res = nthw_pci_ta_init(p->mp_nthw_pci_ta, p_fpga, 0);
+ if (res) {
+ n_err_cnt++;
+ NT_LOG(WRN, NTHW, "%s: module PCI_TA not found\n",
+ p_adapter_id_str);
+ }
+
+ return n_err_cnt;
+}
+
+static int nt4ga_pci_ta_tg_ta_write_control_enable(nt4ga_pci_ta_tg_t *p,
+ uint32_t enable)
+{
+ nthw_pci_ta_set_control_enable(p->mp_nthw_pci_ta, enable);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_length_error(nt4ga_pci_ta_tg_t *p, uint32_t *p_data)
+{
+ nthw_pci_ta_get_length_error(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_packet_bad(nt4ga_pci_ta_tg_t *p, uint32_t *p_data)
+{
+ nthw_pci_ta_get_packet_bad(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_packet_good(nt4ga_pci_ta_tg_t *p, uint32_t *p_data)
+{
+ nthw_pci_ta_get_packet_good(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_payload_error(nt4ga_pci_ta_tg_t *p,
+ uint32_t *p_data)
+{
+ nthw_pci_ta_get_payload_error(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_rd_tg_setup(nt4ga_pci_ta_tg_t *p, uint64_t iova,
+ int slot_addr, uint32_t req_size, bool wait,
+ bool wrap)
+{
+ const uint64_t n_phys_addr = (iova + (unsigned long)(slot_addr * req_size));
+
+ nthw_pci_rd_tg_set_ram_addr(p->mp_nthw_pci_rd_tg, slot_addr);
+ nthw_pci_rd_tg_set_phys_addr(p->mp_nthw_pci_rd_tg, n_phys_addr);
+ nthw_pci_rd_tg_set_ram_data(p->mp_nthw_pci_rd_tg, req_size, wait, wrap);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_rd_tg_run(nt4ga_pci_ta_tg_t *p, uint32_t num_iterations)
+{
+ nthw_pci_rd_tg_set_run(p->mp_nthw_pci_rd_tg, num_iterations);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_rd_tg_wait_ready(nt4ga_pci_ta_tg_t *p)
+{
+ int poll = 0;
+ uint32_t data = 0;
+
+ while (data == 0) {
+ /* NOTE: Deliberately start with a sleep - ensures that the FPGA pipe is empty */
+ NT_OS_WAIT_USEC(1000);
+ data = nthw_pci_rd_tg_get_ctrl_rdy(p->mp_nthw_pci_rd_tg);
+ poll++;
+ if (poll >= 1000) {
+ NT_LOG(ERR, NTHW,
+ "%s: FAILED waiting PCI RD TG ready: poll=%d\n",
+ __func__, poll);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_wr_tg_setup(nt4ga_pci_ta_tg_t *p, uint64_t iova,
+ int slot_addr, uint32_t req_size, bool wait,
+ bool wrap, bool inc)
+{
+ const uint64_t n_phys_addr = (iova + (unsigned long)(slot_addr * req_size));
+
+ nthw_pci_wr_tg_set_ram_addr(p->mp_nthw_pci_wr_tg, slot_addr);
+ nthw_pci_wr_tg_set_phys_addr(p->mp_nthw_pci_wr_tg, n_phys_addr);
+ nthw_pci_wr_tg_set_ram_data(p->mp_nthw_pci_wr_tg, req_size, wait, wrap, inc);
+
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_wr_tg_run(nt4ga_pci_ta_tg_t *p, uint32_t num_iterations)
+{
+ nthw_pci_wr_tg_set_run(p->mp_nthw_pci_wr_tg, num_iterations);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_wr_tg_wait_ready(nt4ga_pci_ta_tg_t *p)
+{
+ int poll = 0;
+ uint32_t data = 0;
+
+ while (data == 0) {
+ /* NOTE: Deliberately start with a sleep - ensures that the FPGA pipe is empty */
+ NT_OS_WAIT_USEC(1000);
+ data = nthw_pci_wr_tg_get_ctrl_rdy(p->mp_nthw_pci_wr_tg);
+ poll++;
+ if (poll >= 1000) {
+ NT_LOG(ERR, NTHW,
+ "%s: FAILED waiting PCI WR TG ready: poll=%d\n",
+ __func__, poll);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int nt4ga_pci_ta_tg_measure_throughput_run(struct adapter_info_s *p_adapter_info,
+ struct nthw_hif_end_point_counters *pri,
+ struct nthw_hif_end_point_counters *sla)
+{
+ nt4ga_pci_ta_tg_t *p = &p_adapter_info->nt4ga_pci_ta_tg;
+
+ const int delay = pri->n_tg_delay;
+ const int pkt_size = pri->n_tg_pkt_size;
+ const int num_pkts = pri->n_tg_num_pkts;
+ const int n_direction = pri->n_tg_direction;
+ const uint8_t n_numa_node = (uint8_t)pri->n_numa_node;
+ const int dma_buf_size = (4 * 1024 * 1024);
+
+ const size_t align_size = ALIGN_SIZE(dma_buf_size);
+ uint32_t *mem_addr;
+ uint64_t iova;
+
+ int bo_error = 0;
+
+ nthw_hif *p_master_instance = p_adapter_info->fpga_info.mp_nthw_hif;
+ nthw_hif *p_slave_instance = NULL;
+
+ nthw_pcie3 *p_pci_master = p_adapter_info->fpga_info.mp_nthw_pcie3;
+ nthw_pcie3 *p_pci_slave = NULL;
+
+ assert(p_master_instance || p_pci_master);
+
+ struct nt_dma_s *p_dma;
+ /* FPGA needs a Page alignment (4K on Intel) */
+ p_dma = nt_dma_alloc(align_size, 0x1000, n_numa_node);
+ if (p_dma == NULL) {
+ NT_LOG(DBG, ETHDEV, "%s: vfio_dma_alloc failed\n", __func__);
+ return 0;
+ }
+ mem_addr = (uint32_t *)p_dma->addr;
+ iova = p_dma->iova;
+
+ NT_LOG(DBG, NTHW,
+ "%s: Running HIF bandwidth measurements on NUMA node %d\n",
+ __func__, n_numa_node);
+
+ bo_error = 0;
+ {
+ int wrap;
+
+ /* Stop any existing running test */
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0);
+
+ /* Prepare the HIF Traffic generator */
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 1);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ /*
+ * Ensure that the hostbuffer memory contain data that can be read -
+ * For this we will ask the FPGA to write data to it. The last wrap packet
+ * does not generate any data it only wraps (unlike the PCIe2 TG)
+ */
+ {
+ int pkt;
+
+ for (pkt = 0; pkt < num_pkts; pkt++) {
+ if (pkt >= (num_pkts - 1))
+ wrap = 1;
+
+ else
+ wrap = 0;
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_setup(p, iova,
+ pkt, pkt_size,
+ 0, wrap, 1);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_setup(p, iova,
+ pkt, pkt_size,
+ 0, wrap);
+ }
+ }
+
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 1);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ /* Start WR TG Write once */
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 1);
+ /* Wait until WR TG ready */
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ /* Verify that we have a packet */
+ {
+ int pkt;
+
+ for (pkt = 0; pkt < num_pkts; pkt++) {
+ uint32_t value = 0;
+ int poll;
+
+ for (poll = 8; poll < pkt_size;
+ poll += 4, value++) {
+ if (*(uint32_t *)((uint8_t *)mem_addr +
+ (pkt * pkt_size) +
+ poll) != value) {
+ NT_LOG(ERR, NTHW,
+ "HIF TG: Prepare failed. Data write failed: #%d.%d: %016X:%08X\n",
+ pkt, poll,
+ *(uint32_t *)((uint8_t *)
+ mem_addr +
+ (pkt *
+ pkt_size) +
+ poll),
+ value);
+
+ /*
+ * Break out of the verification loop on first
+ * Ñompare error
+ */
+ bo_error |= 1;
+ break;
+ }
+ }
+ }
+ }
+
+ switch (n_direction) {
+ case 1: /* Read only test */
+ nt4ga_pci_ta_tg_wr_tg_run(p, 0xffff);
+ break;
+ case 2: /* Write only test */
+ nt4ga_pci_ta_tg_rd_tg_run(p, 0xffff);
+ break;
+ case 3: /* Combined read/write test */
+ nt4ga_pci_ta_tg_wr_tg_run(p, 0xffff);
+ nt4ga_pci_ta_tg_rd_tg_run(p, 0xffff);
+ break;
+ default: /* stop tests */
+ nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ break;
+ }
+
+ do {
+ /* prep */
+ if (p_pci_master) {
+ nthw_pcie3_end_point_counters_sample_pre(p_pci_master,
+ pri);
+ }
+ if (p_pci_slave) {
+ nthw_pcie3_end_point_counters_sample_pre(p_pci_slave,
+ sla);
+ }
+
+ /* start measure */
+ if (p_master_instance)
+ nthw_hif_stat_req_enable(p_master_instance);
+ if (p_pci_master)
+ nthw_pcie3_stat_req_enable(p_pci_master);
+
+ if (p_slave_instance)
+ nthw_hif_stat_req_enable(p_slave_instance);
+ if (p_pci_slave)
+ nthw_pcie3_stat_req_enable(p_pci_slave);
+
+ /* Wait */
+ NT_OS_WAIT_USEC(delay);
+
+ /* Stop measure */
+ if (p_master_instance)
+ nthw_hif_stat_req_disable(p_master_instance);
+ if (p_pci_master)
+ nthw_pcie3_stat_req_disable(p_pci_master);
+
+ if (p_slave_instance)
+ nthw_hif_stat_req_disable(p_slave_instance);
+ if (p_pci_slave)
+ nthw_pcie3_stat_req_disable(p_pci_slave);
+
+ /* Post process master */
+ if (p_master_instance) {
+ nthw_hif_end_point_counters_sample(p_master_instance,
+ pri);
+ }
+
+ if (p_pci_master) {
+ nthw_pcie3_end_point_counters_sample_post(p_pci_master,
+ pri);
+ }
+
+ /* Post process slave */
+ if (p_slave_instance) {
+ nthw_hif_end_point_counters_sample(p_slave_instance,
+ sla);
+ }
+
+ if (p_pci_slave) {
+ nthw_pcie3_end_point_counters_sample_post(p_pci_slave,
+ sla);
+ }
+
+ {
+ /* Check for TA transmit errors */
+ uint32_t dw_good_pkts, dw_bad_pkts, dw_bad_length,
+ dw_bad_payload;
+ nt4ga_pci_ta_tg_ta_read_packet_good(p,
+ &dw_good_pkts);
+ nt4ga_pci_ta_tg_ta_read_packet_bad(p, &dw_bad_pkts);
+ nt4ga_pci_ta_tg_ta_read_length_error(p,
+ &dw_bad_length);
+ nt4ga_pci_ta_tg_ta_read_payload_error(p, &dw_bad_payload);
+
+ NT_LOG(DBG, NTHW,
+ "%s: NUMA node %u: HIF: TA: Good pkts, Bad pkts, Bad length, Bad payload\n",
+ __func__, n_numa_node);
+ NT_LOG(DBG, NTHW,
+ "%s: NUMA node %u: HIF: TA: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ __func__, n_numa_node, dw_good_pkts,
+ dw_bad_pkts, dw_bad_length, dw_bad_payload);
+
+ if (dw_bad_pkts | dw_bad_length | dw_bad_payload) {
+ bo_error |= 1;
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: error detected\n",
+ __func__, n_numa_node);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Good packets received: %u\n",
+ __func__, n_numa_node, dw_good_pkts);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Bad packets received : %u\n",
+ __func__, n_numa_node, dw_bad_pkts);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Bad length received : %u\n",
+ __func__, n_numa_node,
+ dw_bad_length);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Bad payload received : %u\n",
+ __func__, n_numa_node,
+ dw_bad_payload);
+ }
+ }
+
+ if (bo_error != 0)
+ break;
+
+ break; /* for now only loop once */
+
+ /*
+ * Only do "signalstop" looping if a specific numa node and direction is to
+ * be tested.
+ */
+ } while ((bo_error == 0) && (n_numa_node != UINT8_MAX) &&
+ (n_direction != -1));
+
+ /* Stop the test */
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0);
+
+ /* PCIe3 sanity checks */
+ {
+#if defined(DEBUG)
+ int do_loop = 1;
+#else
+ int do_loop = 0;
+#endif
+
+ while (do_loop) {
+ do_loop = 0;
+
+ if (p_master_instance) {
+ nthw_hif_stat_req_enable(p_master_instance);
+ NT_OS_WAIT_USEC(100);
+ nthw_hif_stat_req_disable(p_master_instance);
+ }
+
+ if (do_loop == 0)
+ break;
+
+ NT_LOG(DBG, NTHW,
+ "%s: WARNING this is wrong - wait again\n",
+ __func__);
+ NT_OS_WAIT_USEC(200 * 1000);
+ }
+ }
+ }
+
+ /* Stop the test */
+
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0);
+
+ nt_dma_free(p_dma);
+
+ return bo_error;
+}
+
+int nt4ga_pci_ta_tg_measure_throughput_main(struct adapter_info_s *p_adapter_info,
+ const uint8_t numa_node,
+ const int direction, const int n_pkt_size,
+ const int n_batch_count, const int n_delay)
+{
+ /* All numa nodes is indicated by UINT8_MAX */
+ const uint8_t numa_begin = (numa_node == UINT8_MAX ? 0 : numa_node);
+ const uint8_t numa_end = numa_begin;
+
+ /* sanity check direction param */
+ const int dir_begin = (direction <= 0 ? 1 : direction);
+ const int dir_end = (direction <= 0 ? 3 : direction);
+
+ int bo_error = 0;
+ struct nthw_hif_end_points eps;
+
+ if (n_delay == 0)
+ return -1;
+
+ NT_LOG(DBG, NTHW, "HIF adapter throughput:\n");
+
+ /* Only do "signalstop"-looping if a specific numa node is to be tested. */
+ {
+ uint8_t numa;
+
+ for (numa = numa_begin; numa <= numa_end; numa++) {
+ {
+ int by_loop;
+
+ for (by_loop = dir_begin; by_loop <= dir_end;
+ by_loop++) {
+ struct nthw_hif_end_point_counters *pri =
+ &eps.pri;
+ struct nthw_hif_end_point_counters *sla =
+ &eps.sla;
+
+ pri->n_numa_node = numa;
+ pri->n_tg_direction = by_loop;
+ pri->n_tg_pkt_size = (n_pkt_size > 0 ?
+ n_pkt_size :
+ TG_PKT_SIZE);
+ pri->n_tg_num_pkts =
+ (n_batch_count > 0 ?
+ n_batch_count :
+ TG_NUM_PACKETS);
+ pri->n_tg_delay = (n_delay > 0 ? n_delay :
+ TG_DELAY);
+ pri->cur_rx = 0;
+ pri->cur_tx = 0;
+ pri->n_ref_clk_cnt = -1;
+ pri->bo_error = 0;
+
+ sla->n_numa_node = numa;
+ sla->n_tg_direction = by_loop;
+ sla->n_tg_pkt_size = (n_pkt_size > 0 ?
+ n_pkt_size :
+ TG_PKT_SIZE);
+ sla->n_tg_num_pkts =
+ (n_batch_count > 0 ?
+ n_batch_count :
+ TG_NUM_PACKETS);
+ sla->n_tg_delay = (n_delay > 0 ? n_delay :
+ TG_DELAY);
+ sla->cur_rx = 0;
+ sla->cur_tx = 0;
+ pri->n_ref_clk_cnt = -1;
+ sla->bo_error = 0;
+
+ bo_error +=
+ nt4ga_pci_ta_tg_measure_throughput_run(p_adapter_info,
+ pri, sla);
+#if defined(DEBUG) && (1)
+ {
+ NT_LOG(DBG, NTHW,
+ "%s: @ %d: %d %d %d %d: %016lX %016lX : %6ld Mbps %6ld Mbps\n",
+ __func__, pri->n_numa_node,
+ pri->n_tg_direction,
+ pri->n_tg_num_pkts,
+ pri->n_tg_pkt_size,
+ pri->n_tg_delay,
+ pri->cur_rx, pri->cur_tx,
+ (pri->cur_rx * 8UL /
+ 1000000UL),
+ (pri->cur_tx * 8UL /
+ 1000000UL));
+ }
+ {
+ NT_LOG(DBG, NTHW,
+ "%s: @ %d: %d %d %d %d: %016lX %016lX : %6ld Mbps %6ld Mbps\n",
+ __func__, sla->n_numa_node,
+ sla->n_tg_direction,
+ sla->n_tg_num_pkts,
+ sla->n_tg_pkt_size,
+ sla->n_tg_delay,
+ sla->cur_rx, sla->cur_tx,
+ (sla->cur_rx * 8UL /
+ 1000000UL),
+ (sla->cur_tx * 8UL /
+ 1000000UL));
+ }
+#endif
+
+ if (pri->bo_error != 0 || sla->bo_error != 0)
+ bo_error++;
+ if (bo_error)
+ break;
+ }
+ }
+ }
+ }
+
+ if (bo_error != 0) {
+ NT_LOG(ERR, NTHW, "%s: error during bandwidth measurement\n",
+ __func__);
+ }
+
+ NT_LOG(DBG, NTHW, "HIF adapter throughput: done\n");
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] done\n", __func__, __FILE__, __LINE__);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h
new file mode 100644
index 0000000000..8b46491f77
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NT4GA_PCI_TA_TG_H_
+#define _NT4GA_PCI_TA_TG_H_
+
+#include <stdint.h>
+
+#define TA_TG_DBG_SHOW_SUMMARY (1)
+
+#define TG_NUM_PACKETS (8)
+#define TG_PKT_SIZE (2048 * 1)
+#define TG_AREA_SIZE (TG_NUM_PACKETS * TG_PKT_SIZE)
+
+#define TG_DELAY (200000) /* usec */
+
+/* Struct predefinitions */
+struct adapter_info_s;
+struct nthw_hif_end_point_counters;
+
+struct nt4ga_pci_ta_tg_s {
+ struct nthw_pci_rd_tg *mp_nthw_pci_rd_tg;
+ struct nthw_pci_wr_tg *mp_nthw_pci_wr_tg;
+ struct nthw_pci_ta *mp_nthw_pci_ta;
+};
+
+typedef struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg_t;
+typedef struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg;
+
+int nt4ga_pci_ta_tg_init(struct adapter_info_s *p_adapter_info);
+
+int nt4ga_pci_ta_tg_measure_throughput_run(struct adapter_info_s *p_adapter_info,
+ struct nthw_hif_end_point_counters *pri,
+ struct nthw_hif_end_point_counters *sla);
+int nt4ga_pci_ta_tg_measure_throughput_main(struct adapter_info_s *p_adapter_info,
+ const uint8_t numa_node,
+ const int direction, const int n_pkt_size,
+ const int n_batch_count, const int n_delay);
+
+#endif /* _NT4GA_PCI_TA_TG_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.c b/drivers/net/ntnic/adapter/nt4ga_stat.c
new file mode 100644
index 0000000000..b61c73ea12
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_stat.c
@@ -0,0 +1,705 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nt_util.h"
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+#include "nt4ga_adapter.h"
+
+#define NO_FLAGS 0
+
+/* Inline timestamp format s pcap 32:32 bits. Convert to nsecs */
+static inline uint64_t timestamp2ns(uint64_t ts)
+{
+ return ((ts >> 32) * 1000000000) + (ts & 0xffffffff);
+}
+
+static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual);
+static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual);
+
+int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused,
+ nt4ga_stat_t *p_nt4ga_stat)
+{
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ if (p_nthw_stat->mb_is_vswitch) {
+ /*
+ * Set all bits in the DMA block timestamp since 9530-42-05 and other Vswitch FPGA
+ * images may only clear all bits in this memory location. TBV
+ * Consequently, last_timestamp must be constructed via a system call.
+ */
+ *p_nthw_stat->mp_timestamp = 0xFFFFFFFF;
+ p_nt4ga_stat->last_timestamp = NT_OS_GET_TIME_NS();
+ nt4ga_stat_collect_virt_v1_stats(p_nt4ga_stat,
+ p_nt4ga_stat->p_stat_dma_virtual);
+ } else {
+ p_nt4ga_stat->last_timestamp =
+ timestamp2ns(*p_nthw_stat->mp_timestamp);
+ nt4ga_stat_collect_cap_v1_stats(p_nt4ga_stat,
+ p_nt4ga_stat->p_stat_dma_virtual);
+ }
+ return 0;
+}
+
+int nt4ga_stat_init(struct adapter_info_s *p_adapter_info)
+{
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ nt_fpga_t *p_fpga = fpga_info->mp_fpga;
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+
+ if (p_nt4ga_stat) {
+ memset(p_nt4ga_stat, 0, sizeof(nt4ga_stat_t));
+ } else {
+ NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ {
+ nthw_stat_t *p_nthw_stat = nthw_stat_new();
+ nthw_rmc_t *p_nthw_rmc = nthw_rmc_new();
+
+ if (!p_nthw_stat) {
+ NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (!p_nthw_rmc) {
+ nthw_stat_delete(p_nthw_stat);
+
+ NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ p_nt4ga_stat->mp_nthw_stat = p_nthw_stat;
+ nthw_stat_init(p_nthw_stat, p_fpga, 0);
+
+ p_nt4ga_stat->mp_nthw_rmc = p_nthw_rmc;
+ nthw_rmc_init(p_nthw_rmc, p_fpga, 0);
+
+ p_nt4ga_stat->mn_rx_host_buffers = p_nthw_stat->m_nb_rx_host_buffers;
+ p_nt4ga_stat->mn_tx_host_buffers = p_nthw_stat->m_nb_tx_host_buffers;
+
+ p_nt4ga_stat->mn_rx_ports = p_nthw_stat->m_nb_rx_ports;
+ p_nt4ga_stat->mn_tx_ports = p_nthw_stat->m_nb_tx_ports;
+ }
+
+ return 0;
+}
+
+int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info)
+{
+ const int n_physical_adapter_no _unused = p_adapter_info->adapter_no;
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ nthw_rmc_t *p_nthw_rmc = p_nt4ga_stat->mp_nthw_rmc;
+
+ if (p_nthw_rmc)
+ nthw_rmc_block(p_nthw_rmc);
+
+ /* Allocate and map memory for fpga statistics */
+ {
+ uint32_t n_stat_size =
+ (uint32_t)(p_nthw_stat->m_nb_counters * sizeof(uint32_t) +
+ sizeof(p_nthw_stat->mp_timestamp));
+ struct nt_dma_s *p_dma;
+ int numa_node = p_adapter_info->fpga_info.numa_node;
+
+ /* FPGA needs a 16K alignment on Statistics */
+ p_dma = nt_dma_alloc(n_stat_size, 0x4000, numa_node);
+
+ if (!p_dma) {
+ NT_LOG(ERR, ETHDEV, "%s: pDma alloc failed\n",
+ __func__);
+ return -1;
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: %x @%d %p %" PRIX64 " %" PRIX64 "\n", __func__,
+ n_stat_size, numa_node, p_dma->addr, p_dma->iova);
+
+ NT_LOG(DBG, ETHDEV,
+ "DMA: Physical adapter %02ld, PA = 0x%016" PRIX64
+ " DMA = 0x%016" PRIX64 " size = 0x%" PRIX64 "\n",
+ n_physical_adapter_no, p_dma->iova, p_dma->addr, n_stat_size);
+
+ p_nt4ga_stat->p_stat_dma_virtual = (uint32_t *)p_dma->addr;
+ p_nt4ga_stat->n_stat_size = n_stat_size;
+ p_nt4ga_stat->p_stat_dma = p_dma;
+
+ memset(p_nt4ga_stat->p_stat_dma_virtual, 0xaa, n_stat_size);
+ nthw_stat_set_dma_address(p_nthw_stat, p_dma->iova,
+ p_nt4ga_stat->p_stat_dma_virtual);
+ }
+
+ if (p_nthw_rmc)
+ nthw_rmc_unblock(p_nthw_rmc, false);
+
+ p_nt4ga_stat->mp_stat_structs_color = calloc(p_nthw_stat->m_nb_color_counters,
+ sizeof(struct color_counters));
+ if (!p_nt4ga_stat->mp_stat_structs_color) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ p_nt4ga_stat->mp_stat_structs_hb =
+ calloc(p_nt4ga_stat->mn_rx_host_buffers + p_nt4ga_stat->mn_tx_host_buffers,
+ sizeof(struct host_buffer_counters));
+ if (!p_nt4ga_stat->mp_stat_structs_hb) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ /*
+ * Separate memory allocation for VSWITCH and Inline to appropriate port counter structures.
+ */
+ if (p_nthw_stat->mb_is_vswitch) {
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx =
+ calloc(p_nthw_stat->m_nb_rx_host_buffers,
+ sizeof(struct port_counters_vswitch_v1));
+ if (!p_nt4ga_stat->virt.mp_stat_structs_port_rx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx =
+ calloc(p_nthw_stat->m_nb_tx_host_buffers,
+ sizeof(struct port_counters_vswitch_v1));
+ if (!p_nt4ga_stat->virt.mp_stat_structs_port_tx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ p_nt4ga_stat->flm_stat_ver = 0;
+ p_nt4ga_stat->mp_stat_structs_flm = NULL;
+ } else { /* Inline */
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx =
+ calloc(NUM_ADAPTER_PORTS_MAX,
+ sizeof(struct port_counters_v2));
+ if (!p_nt4ga_stat->cap.mp_stat_structs_port_rx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx =
+ calloc(NUM_ADAPTER_PORTS_MAX,
+ sizeof(struct port_counters_v2));
+ if (!p_nt4ga_stat->cap.mp_stat_structs_port_tx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ p_nt4ga_stat->flm_stat_ver = 0;
+
+ p_nt4ga_stat->mp_stat_structs_flm =
+ calloc(1, sizeof(struct flm_counters_v1));
+ if (!p_nt4ga_stat->mp_stat_structs_flm) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ }
+
+ memset(p_nt4ga_stat->a_stat_structs_color_base, 0,
+ sizeof(struct color_counters) * NT_MAX_COLOR_FLOW_STATS);
+ p_nt4ga_stat->last_timestamp = 0;
+
+ nthw_stat_trigger(p_nthw_stat);
+
+ return 0;
+}
+
+int nt4ga_stat_stop(struct adapter_info_s *p_adapter_info)
+{
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+
+ if (p_nt4ga_stat->virt.mp_stat_structs_port_rx) {
+ free(p_nt4ga_stat->virt.mp_stat_structs_port_rx);
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx = NULL;
+ }
+ if (p_nt4ga_stat->cap.mp_stat_structs_port_rx) {
+ free(p_nt4ga_stat->cap.mp_stat_structs_port_rx);
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx = NULL;
+ }
+
+ if (p_nt4ga_stat->virt.mp_stat_structs_port_tx) {
+ free(p_nt4ga_stat->virt.mp_stat_structs_port_tx);
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx = NULL;
+ }
+ if (p_nt4ga_stat->cap.mp_stat_structs_port_tx) {
+ free(p_nt4ga_stat->cap.mp_stat_structs_port_tx);
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx = NULL;
+ }
+
+ if (p_nt4ga_stat->mp_stat_structs_color) {
+ free(p_nt4ga_stat->mp_stat_structs_color);
+ p_nt4ga_stat->mp_stat_structs_color = NULL;
+ }
+
+ if (p_nt4ga_stat->mp_stat_structs_hb) {
+ free(p_nt4ga_stat->mp_stat_structs_hb);
+ p_nt4ga_stat->mp_stat_structs_hb = NULL;
+ }
+
+ if (p_nt4ga_stat->mp_stat_structs_flm) {
+ free(p_nt4ga_stat->mp_stat_structs_flm);
+ p_nt4ga_stat->mp_stat_structs_flm = NULL;
+ }
+
+ if (p_nt4ga_stat->p_stat_dma) {
+ nt_dma_free(p_nt4ga_stat->p_stat_dma);
+ p_nt4ga_stat->p_stat_dma = NULL;
+ }
+
+ return 0;
+}
+
+int nt4ga_stat_dump(struct adapter_info_s *p_adapter_info, FILE *pfh)
+{
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+ int i;
+
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ fprintf(pfh,
+ "%s: Intf %02d: Rx: %016" PRIX64 " %016" PRIX64
+ " %016" PRIX64 " Tx: %016" PRIX64 " %016" PRIX64
+ " %016" PRIX64 "\n",
+ p_adapter_id_str, i, p_nt4ga_stat->a_port_rx_packets_total[i],
+ p_nt4ga_stat->a_port_rx_octets_total[i],
+ p_nt4ga_stat->a_port_rx_drops_total[i],
+ p_nt4ga_stat->a_port_tx_packets_total[i],
+ p_nt4ga_stat->a_port_tx_octets_total[i],
+ p_nt4ga_stat->a_port_tx_drops_total[i]);
+ }
+
+ return 0;
+}
+
+/* Called with stat mutex locked */
+static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual)
+{
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ const int n_rx_ports = p_nt4ga_stat->mn_rx_ports;
+ const int n_tx_ports = p_nt4ga_stat->mn_tx_ports;
+ int c, h, p;
+
+ if (!p_nthw_stat || !p_nt4ga_stat)
+ return -1;
+
+ if (p_nthw_stat->mn_stat_layout_version != 6) {
+ NT_LOG(ERR, ETHDEV, "HW STA module version not supported");
+ return -1;
+ }
+
+ /* RX ports */
+ for (c = 0; c < p_nthw_stat->m_nb_color_counters / 2; c++) {
+ const unsigned int tcp_flags_bits = 6U;
+ const uint32_t val_mask_dma = 0xffffffffULL >> tcp_flags_bits;
+
+ p_nt4ga_stat->mp_stat_structs_color[c].color_packets +=
+ p_stat_dma_virtual[c * 2] & val_mask_dma;
+ p_nt4ga_stat->mp_stat_structs_color[c].tcp_flags |=
+ (uint8_t)(p_stat_dma_virtual[c * 2] >>
+ (32 - tcp_flags_bits));
+ p_nt4ga_stat->mp_stat_structs_color[c].color_bytes +=
+ p_stat_dma_virtual[c * 2 + 1];
+ }
+
+ /* Move to Host buffer counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_color_counters;
+
+ /* Host buffer counters */
+ for (h = 0; h < p_nthw_stat->m_nb_rx_host_buffers; h++) {
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_packets +=
+ p_stat_dma_virtual[h * 8];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_packets +=
+ p_stat_dma_virtual[h * 8 + 1];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_packets +=
+ p_stat_dma_virtual[h * 8 + 2];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_packets +=
+ p_stat_dma_virtual[h * 8 + 3];
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_bytes +=
+ p_stat_dma_virtual[h * 8 + 4];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 5];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_bytes +=
+ p_stat_dma_virtual[h * 8 + 6];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 7];
+ }
+
+ /* Move to Rx Port counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_rx_hb_counters;
+
+ /* RX ports */
+ for (p = 0; p < n_rx_ports; p++) {
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].qos_drop_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 3];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].qos_drop_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 4];
+
+ /* Rx totals */
+ p_nt4ga_stat->a_port_rx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters];
+ p_nt4ga_stat->a_port_rx_packets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1];
+ p_nt4ga_stat->a_port_rx_drops_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2];
+ }
+
+ /* Move to Tx Port counters */
+ p_stat_dma_virtual += n_rx_ports * p_nthw_stat->m_nb_rx_port_counters;
+
+ /* TX ports */
+ for (p = 0; p < n_tx_ports; p++) {
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].qos_drop_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 3];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].qos_drop_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 4];
+
+ /* Tx totals */
+ p_nt4ga_stat->a_port_tx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters];
+ p_nt4ga_stat->a_port_tx_packets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1];
+ p_nt4ga_stat->a_port_tx_drops_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2];
+ }
+
+ return 0;
+}
+
+/* Called with stat mutex locked */
+static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual)
+{
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ const int n_rx_ports = p_nt4ga_stat->mn_rx_ports;
+ const int n_tx_ports = p_nt4ga_stat->mn_tx_ports;
+ int c, h, p;
+
+ if (!p_nthw_stat || !p_nt4ga_stat)
+ return -1;
+
+ if (p_nthw_stat->mn_stat_layout_version != 6) {
+ NT_LOG(ERR, ETHDEV, "HW STA module version not supported");
+ return -1;
+ }
+
+ /* RX ports */
+ for (c = 0; c < p_nthw_stat->m_nb_color_counters / 2; c++) {
+ p_nt4ga_stat->mp_stat_structs_color[c].color_packets +=
+ p_stat_dma_virtual[c * 2];
+ p_nt4ga_stat->mp_stat_structs_color[c].color_bytes +=
+ p_stat_dma_virtual[c * 2 + 1];
+ }
+
+ /* Move to Host buffer counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_color_counters;
+
+ for (h = 0; h < p_nthw_stat->m_nb_rx_host_buffers; h++) {
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_packets +=
+ p_stat_dma_virtual[h * 8];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_packets +=
+ p_stat_dma_virtual[h * 8 + 1];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_packets +=
+ p_stat_dma_virtual[h * 8 + 2];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_packets +=
+ p_stat_dma_virtual[h * 8 + 3];
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_bytes +=
+ p_stat_dma_virtual[h * 8 + 4];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 5];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_bytes +=
+ p_stat_dma_virtual[h * 8 + 6];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 7];
+ }
+
+ /* Move to Rx Port counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_rx_hb_counters;
+
+ /* RX ports */
+ for (p = 0; p < n_rx_ports; p++) {
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 0];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].broadcast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].multicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].unicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 3];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_alignment +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 4];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_code_violation +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 5];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_crc +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 6];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].undersize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 7];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].oversize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 8];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].fragments +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 9];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].jabbers_not_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 10];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].jabbers_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 11];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_64_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 12];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_65_to_127_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 13];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_128_to_255_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 14];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_256_to_511_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 15];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_512_to_1023_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 16];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_1024_to_1518_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 17];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_1519_to_2047_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 18];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_2048_to_4095_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 19];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_4096_to_8191_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 20];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_8192_to_max_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].mac_drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_lr +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 23];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].duplicate +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 24];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_ip_chksum_error +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 25];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_udp_chksum_error +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 26];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_tcp_chksum_error +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 27];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_giant_undersize +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 28];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_baby_giant +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 29];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_not_isl_vlan_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 30];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 31];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_vlan +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 32];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 33];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 34];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 35];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_vlan_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 36];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 37];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_no_filter +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 38];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_dedup_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 39];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_filter_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 40];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_overflow +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 41];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_dbs_drop +=
+ p_nthw_stat->m_dbs_present ?
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters +
+ 42] :
+ 0;
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_no_filter +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 43];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_dedup_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 44];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_filter_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 45];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_overflow +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 46];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_dbs_drop +=
+ p_nthw_stat->m_dbs_present ?
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters +
+ 47] :
+ 0;
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_first_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 48];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_first_not_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 49];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_mid_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 50];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_mid_not_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 51];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_last_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 52];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_last_not_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 53];
+
+ /* Rx totals */
+ uint64_t new_drop_events_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 38] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 39] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 40] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 41] +
+ (p_nthw_stat->m_dbs_present ?
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters +
+ 42] :
+ 0);
+
+ uint64_t new_packets_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 7] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 8] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 9] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 10] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 11] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 12] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 13] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 14] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 15] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 16] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 17] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 18] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 19] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 20] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].drop_events +=
+ new_drop_events_sum;
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts += new_packets_sum;
+
+ p_nt4ga_stat->a_port_rx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 0];
+ p_nt4ga_stat->a_port_rx_packets_total[p] += new_packets_sum;
+ p_nt4ga_stat->a_port_rx_drops_total[p] += new_drop_events_sum;
+ }
+
+ /* Move to Tx Port counters */
+ p_stat_dma_virtual += n_rx_ports * p_nthw_stat->m_nb_rx_port_counters;
+
+ for (p = 0; p < n_tx_ports; p++) {
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 0];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].broadcast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].multicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].unicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 3];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_alignment +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 4];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_code_violation +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 5];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_crc +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 6];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].undersize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 7];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].oversize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 8];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].fragments +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 9];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].jabbers_not_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 10];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].jabbers_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 11];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_64_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 12];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_65_to_127_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 13];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_128_to_255_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 14];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_256_to_511_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 15];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_512_to_1023_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 16];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_1024_to_1518_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 17];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_1519_to_2047_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 18];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_2048_to_4095_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 19];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_4096_to_8191_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 20];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_8192_to_max_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].mac_drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 22];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_lr +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 23];
+
+ /* Tx totals */
+ uint64_t new_drop_events_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22];
+
+ uint64_t new_packets_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 7] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 8] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 9] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 10] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 11] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 12] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 13] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 14] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 15] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 16] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 17] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 18] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 19] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 20] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].drop_events +=
+ new_drop_events_sum;
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts += new_packets_sum;
+
+ p_nt4ga_stat->a_port_tx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 0];
+ p_nt4ga_stat->a_port_tx_packets_total[p] += new_packets_sum;
+ p_nt4ga_stat->a_port_tx_drops_total[p] += new_drop_events_sum;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.h b/drivers/net/ntnic/adapter/nt4ga_stat.h
new file mode 100644
index 0000000000..4a1067200c
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_stat.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_STAT_H_
+#define NT4GA_STAT_H_
+
+#include "nt_util.h"
+#include "common_adapter_defs.h"
+
+#define NT_MAX_COLOR_FLOW_STATS 0x400
+
+struct color_counters {
+ uint64_t color_packets;
+ uint64_t color_bytes;
+ uint8_t tcp_flags;
+};
+
+struct host_buffer_counters {
+ uint64_t flush_packets;
+ uint64_t drop_packets;
+ uint64_t fwd_packets;
+ uint64_t dbs_drop_packets;
+ uint64_t flush_bytes;
+ uint64_t drop_bytes;
+ uint64_t fwd_bytes;
+ uint64_t dbs_drop_bytes;
+};
+
+struct port_counters_v2 {
+ /* Rx/Tx common port counters */
+ uint64_t drop_events;
+ uint64_t pkts;
+ /* FPGA counters */
+ uint64_t octets;
+ uint64_t broadcast_pkts;
+ uint64_t multicast_pkts;
+ uint64_t unicast_pkts;
+ uint64_t pkts_alignment;
+ uint64_t pkts_code_violation;
+ uint64_t pkts_crc;
+ uint64_t undersize_pkts;
+ uint64_t oversize_pkts;
+ uint64_t fragments;
+ uint64_t jabbers_not_truncated;
+ uint64_t jabbers_truncated;
+ uint64_t pkts_64_octets;
+ uint64_t pkts_65_to_127_octets;
+ uint64_t pkts_128_to_255_octets;
+ uint64_t pkts_256_to_511_octets;
+ uint64_t pkts_512_to_1023_octets;
+ uint64_t pkts_1024_to_1518_octets;
+ uint64_t pkts_1519_to_2047_octets;
+ uint64_t pkts_2048_to_4095_octets;
+ uint64_t pkts_4096_to_8191_octets;
+ uint64_t pkts_8192_to_max_octets;
+ uint64_t mac_drop_events;
+ uint64_t pkts_lr;
+ /* Rx only port counters */
+ uint64_t duplicate;
+ uint64_t pkts_ip_chksum_error;
+ uint64_t pkts_udp_chksum_error;
+ uint64_t pkts_tcp_chksum_error;
+ uint64_t pkts_giant_undersize;
+ uint64_t pkts_baby_giant;
+ uint64_t pkts_not_isl_vlan_mpls;
+ uint64_t pkts_isl;
+ uint64_t pkts_vlan;
+ uint64_t pkts_isl_vlan;
+ uint64_t pkts_mpls;
+ uint64_t pkts_isl_mpls;
+ uint64_t pkts_vlan_mpls;
+ uint64_t pkts_isl_vlan_mpls;
+ uint64_t pkts_no_filter;
+ uint64_t pkts_dedup_drop;
+ uint64_t pkts_filter_drop;
+ uint64_t pkts_overflow;
+ uint64_t pkts_dbs_drop;
+ uint64_t octets_no_filter;
+ uint64_t octets_dedup_drop;
+ uint64_t octets_filter_drop;
+ uint64_t octets_overflow;
+ uint64_t octets_dbs_drop;
+ uint64_t ipft_first_hit;
+ uint64_t ipft_first_not_hit;
+ uint64_t ipft_mid_hit;
+ uint64_t ipft_mid_not_hit;
+ uint64_t ipft_last_hit;
+ uint64_t ipft_last_not_hit;
+};
+
+struct port_counters_vswitch_v1 {
+ /* Rx/Tx common port counters */
+ uint64_t octets;
+ uint64_t pkts;
+ uint64_t drop_events;
+ uint64_t qos_drop_octets;
+ uint64_t qos_drop_pkts;
+};
+
+struct flm_counters_v1 {
+ /* FLM 0.17 */
+ uint64_t current;
+ uint64_t learn_done;
+ uint64_t learn_ignore;
+ uint64_t learn_fail;
+ uint64_t unlearn_done;
+ uint64_t unlearn_ignore;
+ uint64_t auto_unlearn_done;
+ uint64_t auto_unlearn_ignore;
+ uint64_t auto_unlearn_fail;
+ uint64_t timeout_unlearn_done;
+ uint64_t rel_done;
+ uint64_t rel_ignore;
+ /* FLM 0.20 */
+ uint64_t prb_done;
+ uint64_t prb_ignore;
+ uint64_t sta_done;
+ uint64_t inf_done;
+ uint64_t inf_skip;
+ uint64_t pck_hit;
+ uint64_t pck_miss;
+ uint64_t pck_unh;
+ uint64_t pck_dis;
+ uint64_t csh_hit;
+ uint64_t csh_miss;
+ uint64_t csh_unh;
+ uint64_t cuc_start;
+ uint64_t cuc_move;
+};
+
+struct nt4ga_stat_s {
+ nthw_stat_t *mp_nthw_stat;
+ nthw_rmc_t *mp_nthw_rmc;
+ struct nt_dma_s *p_stat_dma;
+ uint32_t *p_stat_dma_virtual;
+ uint32_t n_stat_size;
+
+ uint64_t last_timestamp;
+
+ int mn_rx_host_buffers;
+ int mn_tx_host_buffers;
+
+ int mn_rx_ports;
+ int mn_tx_ports;
+
+ struct color_counters *mp_stat_structs_color;
+ /* For calculating increments between stats polls */
+ struct color_counters a_stat_structs_color_base[NT_MAX_COLOR_FLOW_STATS];
+
+ union {
+ /*Port counters for VSWITCH/inline */
+ struct {
+ struct port_counters_vswitch_v1 *mp_stat_structs_port_rx;
+ struct port_counters_vswitch_v1 *mp_stat_structs_port_tx;
+ } virt;
+ struct {
+ struct port_counters_v2 *mp_stat_structs_port_rx;
+ struct port_counters_v2 *mp_stat_structs_port_tx;
+ } cap;
+ };
+
+ struct host_buffer_counters *mp_stat_structs_hb;
+
+ int flm_stat_ver;
+ struct flm_counters_v1 *mp_stat_structs_flm;
+
+ /* Rx/Tx totals: */
+ uint64_t n_totals_reset_timestamp; /* timestamp for last totals reset */
+
+ uint64_t a_port_rx_octets_total[NUM_ADAPTER_PORTS_MAX];
+ /* Base is for calculating increments between statistics reads */
+ uint64_t a_port_rx_octets_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_rx_packets_total[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_rx_packets_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_rx_drops_total[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_rx_drops_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_tx_octets_total[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_tx_octets_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_tx_packets_base[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_tx_packets_total[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_tx_drops_base[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_tx_drops_total[NUM_ADAPTER_PORTS_MAX];
+};
+
+typedef struct nt4ga_stat_s nt4ga_stat_t;
+
+int nt4ga_stat_init(struct adapter_info_s *p_adapter_info);
+int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info);
+int nt4ga_stat_stop(struct adapter_info_s *p_adapter_info);
+
+int nt4ga_stat_dump(struct adapter_info_s *p_adapter_info, FILE *pfh);
+
+int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info,
+ nt4ga_stat_t *p_nt4ga_stat);
+
+#endif /* NT4GA_STAT_H_ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 65064f44ab..383ff15390 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -9,22 +9,39 @@ cflags += [
# includes
includes = [
include_directories('.'),
+ include_directories('adapter'),
include_directories('include'),
+ include_directories('nim'),
include_directories('ntlog/include'),
include_directories('ntutil/include'),
include_directories('nthw'),
include_directories('nthw/core'),
include_directories('nthw/supported'),
+ include_directories('sensors'),
+ include_directories('sensors/avr_sensors'),
+ include_directories('sensors/board_sensors'),
+ include_directories('sensors/nim_sensors'),
+ include_directories('sensors/ntavr'),
]
# all sources
sources = files(
+ 'adapter/nt4ga_adapter.c',
+ 'adapter/nt4ga_link.c',
+ 'adapter/nt4ga_link_100g.c',
+ 'adapter/nt4ga_pci_ta_tg.c',
+ 'adapter/nt4ga_stat.c',
+ 'nim/i2c_nim.c',
+ 'nim/nt_link_speed.c',
+ 'nim/qsfp_sensors.c',
+ 'nim/sfp_sensors.c',
'nthw/core/nthw_clock_profiles.c',
'nthw/core/nthw_fpga.c',
'nthw/core/nthw_fpga_nt200a0x.c',
'nthw/core/nthw_fpga_rst.c',
'nthw/core/nthw_fpga_rst9563.c',
'nthw/core/nthw_fpga_rst_nt200a0x.c',
+ 'nthw/core/nthw_gmf.c',
'nthw/core/nthw_gpio_phy.c',
'nthw/core/nthw_hif.c',
'nthw/core/nthw_iic.c',
@@ -34,6 +51,7 @@ sources = files(
'nthw/core/nthw_pci_ta.c',
'nthw/core/nthw_pci_wr_tg.c',
'nthw/core/nthw_pcie3.c',
+ 'nthw/core/nthw_rmc.c',
'nthw/core/nthw_sdc.c',
'nthw/core/nthw_si5340.c',
'nthw/core/nthw_spi_v3.c',
@@ -49,6 +67,12 @@ sources = files(
'nthw/supported/nthw_fpga_9563_055_024_0000.c',
'ntlog/ntlog.c',
'ntutil/nt_util.c',
+ 'sensors/avr_sensors/avr_sensors.c',
+ 'sensors/board_sensors/board_sensors.c',
+ 'sensors/board_sensors/tempmon.c',
+ 'sensors/nim_sensors/nim_sensors.c',
+ 'sensors/ntavr/ntavr.c',
+ 'sensors/sensors.c',
)
if is_variable('default_cflags')
diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c
new file mode 100644
index 0000000000..55740e6de6
--- /dev/null
+++ b/drivers/net/ntnic/nim/i2c_nim.c
@@ -0,0 +1,1974 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_drv.h"
+#include "i2c_nim.h"
+#include "ntlog.h"
+#include "nt_util.h"
+
+#include "nim_sensors.h"
+#include "sfp_p_registers.h"
+#include "qsfp_registers.h"
+#include "sfp_sensors.h"
+#include "qsfp_sensors.h"
+
+#include <assert.h>
+#include <string.h> /* memcmp, memset */
+
+/*
+ * Nim functions
+ */
+#define QSFP_SUP_LEN_INFO_LIN_ADDR 142 /* 5bytes */
+#define QSFP_TRANSMITTER_TYPE_LIN_ADDR 147 /* 1byte */
+#define QSFP_CONTROL_STATUS_LIN_ADDR 86
+#define QSFP_SOFT_TX_ALL_DISABLE_BITS 0x0F
+#define QSFP_SPEC_COMPLIANCE_CODES_ADDR 131 /* 8 bytes */
+#define QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR 192 /* 1 byte */
+#define NIM_READ false
+#define NIM_WRITE true
+#define NIM_PAGE_SEL_REGISTER 127
+#define nim_i2c_0xa0 0xA0 /* Basic I2C address */
+#define QSFP_VENDOR_NAME_LIN_ADDR 148 /* 16bytes */
+#define QSFP_VENDOR_PN_LIN_ADDR 168 /* 16bytes */
+#define QSFP_VENDOR_SN_LIN_ADDR 196 /* 16bytes */
+#define QSFP_VENDOR_DATE_LIN_ADDR 212 /* 8bytes */
+#define QSFP_VENDOR_REV_LIN_ADDR 184 /* 2bytes */
+#define QSFP_DMI_OPTION_LIN_ADDR 220
+
+#define QSFP_EXTENDED_IDENTIFIER 129
+#define QSFP_POWER_CLASS_BITS_1_4 0xC0
+#define QSFP_POWER_CLASS_BITS_5_7 0x03
+
+static bool sfp_is_supported_tri_speed_pn(char *prod_no)
+{
+ static const char *const pn_trispeed_list[] = {
+ "FCMJ-8521-3", "FCLF-8521-3", "FCLF8521P2BTL", "EOLT-C12-02A",
+ "AMXP-24RJS", "ABCU-5710RZ", "ABCU-5740RZ", "FCLF8522P2BTL",
+ };
+
+ /* Determine if copper SFP is supported 3-speed type */
+ for (size_t i = 0; i < ARRAY_SIZE(pn_trispeed_list); i++)
+ if (strcmp(pn_trispeed_list[i], prod_no) == 0)
+ return true;
+
+ return false;
+}
+
+static bool page_addressing(nt_nim_identifier_t id)
+{
+ switch (id) {
+ case NT_NIM_SFP_SFP_PLUS:
+ return false;
+ case NT_NIM_XFP:
+ return true;
+ case NT_NIM_QSFP:
+ case NT_NIM_QSFP_PLUS:
+ case NT_NIM_QSFP28:
+ return true;
+ default:
+ NT_LOG(DBG, ETHDEV, "%s: Unknown NIM identifier %d\n", __func__,
+ id);
+ return false;
+ }
+}
+
+nt_nim_identifier_t translate_nimid(const nim_i2c_ctx_t *ctx)
+{
+ return (nt_nim_identifier_t)ctx->nim_id;
+}
+
+static int nim_read_write_i2c_data(nim_i2c_ctx_p ctx, bool do_write,
+ uint16_t lin_addr, uint8_t i2c_addr,
+ uint8_t reg_addr, uint8_t seq_cnt, uint8_t *p_data)
+{
+ /* Divide I2C_Addr by 2 because nthw_iic_read/writeData multiplies by 2 */
+ const uint8_t i2c_devaddr = i2c_addr / 2U;
+ (void)lin_addr; /* Unused */
+
+ if (do_write)
+ return nthw_iic_write_data(&ctx->hwiic, i2c_devaddr, reg_addr,
+ seq_cnt, p_data);
+ else
+ return nthw_iic_read_data(&ctx->hwiic, i2c_devaddr, reg_addr,
+ seq_cnt, p_data);
+}
+
+/*
+ * ------------------------------------------------------------------------------
+ * Selects a new page for page addressing. This is only relevant if the NIM
+ * supports this. Since page switching can take substantial time the current page
+ * select is read and subsequently only changed if necessary.
+ * Important:
+ * XFP Standard 8077, Ver 4.5, Page 61 states that:
+ * If the host attempts to write a table select value which is not supported in
+ * a particular module, the table select byte will revert to 01h.
+ * This can lead to some surprising result that some pages seems to be duplicated.
+ * ------------------------------------------------------------------------------
+ */
+
+static int nim_setup_page(nim_i2c_ctx_p ctx, uint8_t page_sel)
+{
+ uint8_t curr_page_sel;
+
+ /* Read the current page select value */
+ if (nim_read_write_i2c_data(ctx, NIM_READ, NIM_PAGE_SEL_REGISTER,
+ nim_i2c_0xa0, NIM_PAGE_SEL_REGISTER,
+ sizeof(curr_page_sel), &curr_page_sel) != 0)
+ return -1;
+
+ /* Only write new page select value if necessary */
+ if (page_sel != curr_page_sel) {
+ if (nim_read_write_i2c_data(ctx, NIM_WRITE, NIM_PAGE_SEL_REGISTER,
+ nim_i2c_0xa0, NIM_PAGE_SEL_REGISTER,
+ sizeof(page_sel), &page_sel) != 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int nim_nim_read_write_data_lin(nim_i2c_ctx_p ctx, bool m_page_addressing,
+ uint16_t lin_addr, uint16_t length,
+ uint8_t *p_data, bool do_write)
+{
+ uint16_t i;
+ uint8_t reg_addr; /* The actual register address in I2C device */
+ uint8_t i2c_addr;
+ int block_size = 128; /* Equal to size of MSA pages */
+ int seq_cnt;
+ int max_seq_cnt = 1;
+ int multi_byte = 1; /* One byte per I2C register is default */
+ const int m_port_no = ctx->instance - 2;
+
+ if (lin_addr >= SFP_PHY_LIN_ADDR) {
+ /*
+ * This represents an address space at I2C address 0xAC for SFP modules
+ * containing a PHY. (eg 1G Copper SFP). Each register is 16bit and is
+ * accessed MSByte first and this reading latches the LSByte that is
+ * subsequently read from the same address.
+ */
+ multi_byte = 2;
+ max_seq_cnt = 2;
+
+ /* Test for correct multibyte access */
+ if ((length % multi_byte) != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Uneven length (%d) for address range [0x%X..0x%X].",
+ m_port_no, __func__, length, SFP_PHY_LIN_ADDR,
+ SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG - 1);
+ return -1;
+ }
+
+ if (lin_addr + (length / 2) >
+ SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Access above address range [0x%X..0x%X].",
+ m_port_no, __func__, SFP_PHY_LIN_ADDR,
+ SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG - 1);
+ return -1;
+ }
+ } else if (lin_addr + length > 128) {
+ /*
+ * Page addressing could be relevant since the last byte is outside the
+ * basic range so check if it is enabled
+ */
+ if (m_page_addressing) {
+ /* Crossing into the PHY address range is not allowed */
+ if (lin_addr + length > SFP_PHY_LIN_ADDR) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Access above paged address range [0..0x%X].",
+ m_port_no, __func__, SFP_PHY_LIN_ADDR);
+ return -1;
+ }
+ } else {
+ /* Access outside 0xA2 address range not allowed */
+ if (lin_addr + length > 512) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Access above address range [0..511].",
+ m_port_no, __func__);
+ return -1;
+ }
+ }
+ }
+ /* No missing else here - all devices supports access to address [0..127] */
+
+ for (i = 0; i < length;) {
+ bool use_page_select = false;
+
+ /*
+ * Find out how much can be read from the current block in case of
+ * single byte access
+ */
+ if (multi_byte == 1)
+ max_seq_cnt = block_size - (lin_addr % block_size);
+
+ if (m_page_addressing) {
+ if (lin_addr >= 128) { /* Only page setup above this address */
+ use_page_select = true;
+
+ /* Map to [128..255] of 0xA0 device */
+ reg_addr = (uint8_t)(block_size +
+ (lin_addr % block_size));
+ } else {
+ reg_addr = (uint8_t)lin_addr;
+ }
+ i2c_addr = nim_i2c_0xa0; /* Base I2C address */
+ } else {
+ if (lin_addr >= SFP_PHY_LIN_ADDR) {
+ /* Map to address [0..31] of 0xAC device */
+ reg_addr = (uint8_t)(lin_addr - SFP_PHY_LIN_ADDR);
+ i2c_addr = nim_i2c_0xac;
+ } else if (lin_addr >= 256) {
+ /* Map to address [0..255] of 0xA2 device */
+ reg_addr = (uint8_t)(lin_addr - 256);
+ i2c_addr = nim_i2c_0xa2;
+ } else {
+ reg_addr = (uint8_t)lin_addr;
+ i2c_addr = nim_i2c_0xa0; /* Base I2C address */
+ }
+ }
+
+ /* Now actually do the reading/writing */
+ seq_cnt = length - i; /* Number of remaining bytes */
+
+ if (seq_cnt > max_seq_cnt)
+ seq_cnt = max_seq_cnt;
+
+ /*
+ * Read a number of bytes without explicitly specifying a new address.
+ * This can speed up I2C access since automatic incrementation of the
+ * I2C device internal address counter can be used. It also allows
+ * a HW implementation, that can deal with block access.
+ * Furthermore it also allows for access to data that must be accessed
+ * as 16bit words reading two bytes at each address eg PHYs.
+ */
+ if (use_page_select) {
+ if (nim_setup_page(ctx,
+ (uint8_t)((lin_addr / 128) - 1)) != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot set up page for linear address %u\n",
+ __func__, lin_addr);
+ return -1;
+ }
+ }
+ if (nim_read_write_i2c_data(ctx, do_write, lin_addr, i2c_addr,
+ reg_addr, (uint8_t)seq_cnt,
+ p_data) != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Call to NIM_ReadWriteI2cData failed\n",
+ __func__);
+ return -1;
+ }
+
+ p_data += seq_cnt;
+ i = (uint16_t)(i + seq_cnt);
+ lin_addr = (uint16_t)(lin_addr + (seq_cnt / multi_byte));
+ }
+ return 0;
+}
+
+int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
+ void *data)
+{
+ return nim_nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id),
+ lin_addr, length, data, NIM_READ);
+}
+
+static int write_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
+ void *data)
+{
+ return nim_nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id),
+ lin_addr, length, data, NIM_WRITE);
+}
+
+/* Read and return a single byte */
+static uint8_t read_byte(nim_i2c_ctx_p ctx, uint16_t addr)
+{
+ uint8_t data;
+
+ read_data_lin(ctx, addr, sizeof(data), &data);
+ return data;
+}
+
+static int nim_read_id(nim_i2c_ctx_t *ctx)
+{
+ /* We are only reading the first byte so we don't care about pages here. */
+ const bool use_page_addressing = false;
+
+ if (nim_nim_read_write_data_lin(ctx, use_page_addressing,
+ NIM_IDENTIFIER_ADDR, sizeof(ctx->nim_id),
+ &ctx->nim_id, NIM_READ) != 0)
+ return -1;
+ return 0;
+}
+
+static int i2c_nim_common_construct(nim_i2c_ctx_p ctx)
+{
+ ctx->nim_id = 0;
+ int res = nim_read_id(ctx);
+
+ if (res) {
+ NT_LOG(ERR, PMD, "Can't read NIM id.");
+ return res;
+ }
+ memset(ctx->vendor_name, 0, sizeof(ctx->vendor_name));
+ memset(ctx->prod_no, 0, sizeof(ctx->prod_no));
+ memset(ctx->serial_no, 0, sizeof(ctx->serial_no));
+ memset(ctx->date, 0, sizeof(ctx->date));
+ memset(ctx->rev, 0, sizeof(ctx->rev));
+
+ ctx->content_valid = false;
+ memset(ctx->len_info, 0, sizeof(ctx->len_info));
+ ctx->pwr_level_req = 0;
+ ctx->pwr_level_cur = 0;
+ ctx->avg_pwr = false;
+ ctx->tx_disable = false;
+ ctx->lane_idx = -1;
+ ctx->lane_count = 1;
+ ctx->options = 0;
+ return 0;
+}
+
+static int nim_read_vendor_info(nim_i2c_ctx_p ctx, uint16_t addr,
+ uint8_t max_len, char *p_data);
+
+#define XSFP_READ_VENDOR_INFO(x) \
+ static void x##sfp_read_vendor_info(nim_i2c_ctx_t *ctx) \
+ { \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_NAME_LIN_ADDR, \
+ sizeof(ctx->vendor_name), \
+ ctx->vendor_name); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_PN_LIN_ADDR, \
+ sizeof(ctx->prod_no), ctx->prod_no); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_SN_LIN_ADDR, \
+ sizeof(ctx->serial_no), ctx->serial_no); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_DATE_LIN_ADDR, \
+ sizeof(ctx->date), ctx->date); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_REV_LIN_ADDR, \
+ (uint8_t)(sizeof(ctx->rev) - 2), \
+ ctx->rev); /*OBS Only two bytes*/ \
+ }
+
+XSFP_READ_VENDOR_INFO()
+XSFP_READ_VENDOR_INFO(q)
+
+static int sfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state)
+{
+ int res;
+
+ assert(ctx && state);
+ assert(ctx->nim_id != NT_NIM_UNKNOWN && "Nim is not initialized");
+
+ (void)memset(state, 0, sizeof(*state));
+
+ res = nthw_iic_read_data(&ctx->hwiic, ctx->devaddr, SFP_BIT_RATE_ADDR,
+ sizeof(state->br), &state->br);
+ return res;
+}
+
+static int qsfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state)
+{
+ int res = 0; /* unused due to no readings from HW */
+
+ assert(ctx && state);
+ assert(ctx->nim_id != NT_NIM_UNKNOWN && "Nim is not initialized");
+
+ (void)memset(state, 0, sizeof(*state));
+
+ switch (ctx->nim_id) {
+ case 12U:
+ state->br = 10U; /* QSFP: 4 x 1G = 4G */
+ break;
+ case 13U:
+ state->br = 103U; /* QSFP+: 4 x 10G = 40G */
+ break;
+ case 17U:
+ state->br = 255U; /* QSFP28: 4 x 25G = 100G */
+ break;
+ default:
+ NT_LOG(INF, PMD,
+ "%s:%d nim_id = %u is not an QSFP/QSFP+/QSFP28 module\n",
+ __func__, __LINE__, ctx->nim_id);
+ res = -1;
+ }
+
+ return res;
+}
+
+int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state)
+{
+ if (translate_nimid(ctx) == NT_NIM_SFP_SFP_PLUS)
+ return sfp_nim_state_build(ctx, state);
+ else
+ return qsfp_nim_state_build(ctx, state);
+}
+
+const char *nim_id_to_text(uint8_t nim_id)
+{
+ switch (nim_id) {
+ case 0x0:
+ return "UNKNOWN";
+ case 0x1:
+ return "GBIC";
+ case 0x2:
+ return "FIXED";
+ case 0x3:
+ return "SFP/SFP+";
+ case 0x04:
+ return "300 pin XBI";
+ case 0x05:
+ return "XEN-PAK";
+ case 0x06:
+ return "XFP";
+ case 0x07:
+ return "XFF";
+ case 0x08:
+ return "XFP-E";
+ case 0x09:
+ return "XPAK";
+ case 0x0A:
+ return "X2";
+ case 0x0B:
+ return "DWDM";
+ case 0x0C:
+ return "QSFP";
+ case 0x0D:
+ return "QSFP+";
+ case 0x11:
+ return "QSFP28";
+ case 0x12:
+ return "CFP4";
+ default:
+ return "ILLEGAL!";
+ }
+}
+
+/*
+ * Read and check the validity of the NIM basic data.
+ * This will also preload the cache
+ */
+static void check_content_valid(nim_i2c_ctx_p ctx, uint16_t start_addr)
+{
+ uint32_t sum = 0;
+ uint8_t buf[96];
+
+ read_data_lin(ctx, start_addr, sizeof(buf), &buf[0]);
+
+ for (int i = 0; i < 63; i++)
+ sum += buf[i];
+
+ if ((sum & 0xFF) != buf[63]) {
+ ctx->content_valid = false;
+ } else {
+ sum = 0;
+
+ for (int i = 64; i < 95; i++)
+ sum += buf[i];
+
+ ctx->content_valid = ((sum & 0xFF) == buf[95]);
+ }
+ if (ctx->content_valid)
+ NT_LOG(DBG, NTHW, "NIM content validation passed");
+ else
+ NT_LOG(WRN, NTHW, "NIM content validation failed");
+}
+
+/*
+ * Set/reset Soft Rate__select bits (RS0 & RS1)
+ */
+static void nim_sfp_set_rate_sel_high(nim_i2c_ctx_p ctx, bool rx_rate_high,
+ bool tx_rate_high)
+{
+ const bool m_page_addressing = page_addressing(ctx->nim_id);
+ uint8_t data;
+
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_CONTROL_STATUS_LIN_ADDR, sizeof(data),
+ &data, NIM_READ);
+
+ if (rx_rate_high)
+ data |= SFP_SOFT_RATE0_BIT;
+ else
+ data &= (uint8_t)~(SFP_SOFT_RATE0_BIT);
+
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_CONTROL_STATUS_LIN_ADDR, sizeof(data),
+ &data, NIM_WRITE);
+
+ /* Read the Extended Status/Control and set/reset Soft RS1 bit */
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(data),
+ &data, NIM_READ);
+
+ if (tx_rate_high)
+ data |= SFP_SOFT_RATE1_BIT;
+ else
+ data &= (uint8_t)~(SFP_SOFT_RATE1_BIT);
+
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(data),
+ &data, NIM_WRITE);
+}
+
+/*
+ * Some NIM modules requires some changes to a rate setting.
+ */
+static int nim_sfp_set_rate_select(nim_i2c_ctx_p ctx, nt_link_speed_t speed)
+{
+ if ((speed & (int)ctx->speed_mask) == 0) {
+ char buf[128];
+
+ NT_LOG(ERR, ETHDEV, "%s - Speed (%s) not within SpeedMask (%s)",
+ nt_translate_link_speed(speed),
+ nt_translate_link_speed_mask(ctx->speed_mask, buf,
+ sizeof(buf)));
+ return -1;
+ }
+
+ if (ctx->specific_u.sfp.dual_rate) {
+ uint64_t req_speed = nt_get_link_speed(speed);
+ uint64_t other_speed =
+ nt_get_link_speed((nt_link_speed_t)(ctx->speed_mask ^ (uint32_t)speed));
+ bool rate_high = req_speed > other_speed;
+ /*
+ * Do this both for 1/10 and 10/25. For Sfp28 it is not known if
+ * this is necessary but it is believed not to do any harm.
+ */
+ nim_sfp_set_rate_sel_high(ctx, rate_high, rate_high);
+ }
+ return 0;
+}
+
+/*
+ * Disable TX laser.
+ */
+int nim_sfp_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable)
+{
+ int res;
+ uint8_t value;
+ const bool pg_addr = page_addressing(ctx->nim_id);
+
+ res = nim_nim_read_write_data_lin(ctx, pg_addr, SFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_READ);
+ if (res != 0)
+ return res;
+
+ if (disable)
+ value |= SFP_SOFT_TX_DISABLE_BIT;
+ else
+ value &= (uint8_t)~SFP_SOFT_TX_DISABLE_BIT;
+
+ res = nim_nim_read_write_data_lin(ctx, pg_addr, SFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_WRITE);
+
+ return res;
+}
+
+/*
+ * Disable laser for specific lane or all lanes
+ */
+int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable,
+ int lane_idx)
+{
+ uint8_t value;
+ uint8_t mask;
+ const bool pg_addr = page_addressing(ctx->nim_id);
+
+ if (lane_idx < 0) /* If no lane is specified then all lanes */
+ mask = QSFP_SOFT_TX_ALL_DISABLE_BITS;
+ else
+ mask = (uint8_t)(1U << lane_idx);
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_READ) != 0)
+ return -1;
+
+ if (disable)
+ value |= mask;
+ else
+ value &= (uint8_t)~mask;
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_WRITE) != 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * Read vendor information at a certain address. Any trailing whitespace is
+ * removed and a missing string termination in the NIM data is handled.
+ */
+static int nim_read_vendor_info(nim_i2c_ctx_p ctx, uint16_t addr,
+ uint8_t max_len, char *p_data)
+{
+ const bool pg_addr = page_addressing(ctx->nim_id);
+ int i;
+ /* Subtract "1" from maxLen that includes a terminating "0" */
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, addr, (uint8_t)(max_len - 1),
+ (uint8_t *)p_data, NIM_READ) != 0)
+ return -1;
+
+ /* Terminate at first found white space */
+ for (i = 0; i < max_len - 1; i++) {
+ if (*p_data == ' ' || *p_data == '\n' || *p_data == '\t' ||
+ *p_data == '\v' || *p_data == '\f' || *p_data == '\r') {
+ *p_data = '\0';
+ return 0;
+ }
+
+ p_data++;
+ }
+
+ /*
+ * Add line termination as the very last character, if it was missing in the
+ * NIM data
+ */
+ *p_data = '\0';
+ return 0;
+}
+
+/*
+ * Import length info in various units from NIM module data and convert to meters
+ */
+static void nim_import_len_info(nim_i2c_ctx_p ctx, uint8_t *p_nim_len_info,
+ uint16_t *p_nim_units)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->len_info); i++)
+ if (*(p_nim_len_info + i) == 255) {
+ ctx->len_info[i] = 65535;
+ } else {
+ uint32_t len = *(p_nim_len_info + i) * *(p_nim_units + i);
+
+ if (len > 65535)
+ ctx->len_info[i] = 65535;
+ else
+ ctx->len_info[i] = (uint16_t)len;
+ }
+}
+
+static int qsfpplus_read_basic_data(nim_i2c_ctx_t *ctx)
+{
+ const bool pg_addr = page_addressing(ctx->nim_id);
+ uint8_t options;
+ uint8_t value;
+ uint8_t nim_len_info[5];
+ uint16_t nim_units[5] = { 1000, 2, 1, 1,
+ 1
+ }; /* QSFP MSA units in meters */
+ const char *yes_no[2] _unused = { "No", "Yes" };
+
+ NT_LOG(DBG, ETHDEV, "Instance %d: NIM id: %s (%d)\n", ctx->instance,
+ nim_id_to_text(ctx->nim_id), ctx->nim_id);
+
+ /* Read DMI options */
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_DMI_OPTION_LIN_ADDR,
+ sizeof(options), &options, NIM_READ) != 0)
+ return -1;
+ ctx->avg_pwr = options & QSFP_DMI_AVG_PWR_BIT;
+ NT_LOG(DBG, ETHDEV,
+ "Instance %d: NIM options: (DMI: Yes, AvgPwr: %s)\n",
+ ctx->instance, yes_no[ctx->avg_pwr]);
+
+ qsfp_read_vendor_info(ctx);
+ NT_LOG(DBG, PMD,
+ "Instance %d: NIM info: (Vendor: %s, PN: %s, SN: %s, Date: %s, Rev: %s)\n",
+ ctx->instance, ctx->vendor_name, ctx->prod_no, ctx->serial_no,
+ ctx->date, ctx->rev);
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_SUP_LEN_INFO_LIN_ADDR,
+ sizeof(nim_len_info), nim_len_info,
+ NIM_READ) != 0)
+ return -1;
+
+ /*
+ * Returns supported length information in meters for various fibers as 5 indivi-
+ * dual values: [SM(9um), EBW(50um), MM(50um), MM(62.5um), Copper]
+ * If no length information is available for a certain entry, the returned value
+ * will be zero. This will be the case for SFP modules - EBW entry.
+ * If the MSBit is set the returned value in the lower 31 bits indicates that the
+ * supported length is greater than this.
+ */
+
+ nim_import_len_info(ctx, nim_len_info, nim_units);
+
+ /* Read required power level */
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_EXTENDED_IDENTIFIER,
+ sizeof(value), &value, NIM_READ) != 0)
+ return -1;
+
+ /*
+ * Get power class according to SFF-8636 Rev 2.7, Table 6-16, Page 43:
+ * If power class >= 5 setHighPower must be called for the module to be fully
+ * functional
+ */
+ if ((value & QSFP_POWER_CLASS_BITS_5_7) == 0) {
+ /* NIM in power class 1 - 4 */
+ ctx->pwr_level_req =
+ (uint8_t)(((value & QSFP_POWER_CLASS_BITS_1_4) >> 6) +
+ 1);
+ } else {
+ /* NIM in power class 5 - 7 */
+ ctx->pwr_level_req =
+ (uint8_t)((value & QSFP_POWER_CLASS_BITS_5_7) + 4);
+ }
+
+ return 0;
+}
+
+/*
+ * If true the user must actively select the desired rate. If false the module
+ * however can still support several rates without the user is required to select
+ * one of them. Supported rates must then be deduced from the product number.
+ * SFF-8636, Rev 2.10a:
+ * p40: 6.2.7 Rate Select
+ * p85: A.2 Rate Select
+ */
+static bool qsfp28_is_speed_selection_enabled(nim_i2c_ctx_p ctx)
+{
+ const uint8_t options_reg_addr = 195;
+ const uint8_t enh_options_reg_addr = 221;
+
+ uint8_t rate_select_ena = (read_byte(ctx, options_reg_addr) >> 5) &
+ 0x01; /* bit: 5 */
+
+ if (rate_select_ena == 0)
+ return false;
+
+ uint8_t rate_select_type = (read_byte(ctx, enh_options_reg_addr) >> 2) &
+ 0x03; /* bit 3..2 */
+
+ if (rate_select_type != 2) {
+ NT_LOG(DBG, NTHW, "NIM has unhandled rate select type (%d)",
+ rate_select_type);
+ return false;
+ }
+
+ return true; /* When true selectRate() can be used */
+}
+
+/*
+ * Select a speed that is supported for a multi rate module. The possible speed
+ * values must be obtained by setSpeedMask().
+ * Currently rate selection is assumed to be between 40Gb (10GBd) and 100G (25Gbd)
+ * The value in () are the baud rates for PAM-4 and are valid for extended rate
+ * select, version 2.
+ */
+static int qsfp28_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed)
+{
+ const uint8_t rx_rate_sel_addr = 87;
+ const uint8_t tx_rate_sel_addr = 88;
+
+ if (ctx->lane_idx < 0) {
+ /*
+ * All lanes together
+ * The condition below indicates that the module supports rate selection
+ */
+ if (ctx->speed_mask == (uint32_t)(NT_LINK_SPEED_40G | NT_LINK_SPEED_100G)) {
+ uint16_t data;
+
+ if (speed == NT_LINK_SPEED_100G) {
+ data = 0xAAAA;
+ } else if (speed == NT_LINK_SPEED_40G) {
+ data = 0x0000;
+ } else {
+ NT_LOG(ERR, NTHW, "Unhandled NIM speed (%s).",
+ nt_translate_link_speed(speed));
+ return -1;
+ }
+
+ /* Set speed for Rx and Tx on all lanes */
+ write_data_lin(ctx, rx_rate_sel_addr, sizeof(data), &data);
+ write_data_lin(ctx, tx_rate_sel_addr, sizeof(data), &data);
+ } else {
+ /* For ordinary modules only this speed is supported */
+ if (speed != NT_LINK_SPEED_100G) {
+ NT_LOG(ERR, NTHW,
+ "NIM cannot select this speed (%s).",
+ nt_translate_link_speed(speed));
+ return -1;
+ }
+ }
+ } else {
+ /*
+ * Individual lanes
+ * Currently we do not support QSFP28 modules that support rate selection when
+ * running on individual lanes but that might change in the future
+ */
+ if (speed != NT_LINK_SPEED_25G) {
+ NT_LOG(ERR, NTHW,
+ "NIM cannot select this lane speed (%s).",
+ nt_translate_link_speed(speed));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int nim_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed)
+{
+ if (translate_nimid(ctx) == NT_NIM_SFP_SFP_PLUS) {
+ return nim_sfp_set_rate_select(ctx, speed);
+ } else if (translate_nimid(ctx) == NT_NIM_QSFP28) {
+ if (qsfp28_is_speed_selection_enabled(ctx))
+ return qsfp28_set_link_speed(ctx, speed);
+
+ return 0; /* NIM picks up the speed automatically */
+ }
+ NT_LOG(ERR, ETHDEV,
+ "%s nim is not supported for adjustable link speed.",
+ nim_id_to_text(ctx->nim_id));
+ return -1;
+}
+
+/*
+ * Reads basic vendor and DMI information.
+ */
+static int sfp_read_basic_data(nim_i2c_ctx_p ctx)
+{
+ const char *yes_no[2] _unused = { "No", "Yes" };
+
+ check_content_valid(ctx, 0);
+ NT_LOG(DBG, PMD, "NIM id: %s (%d)", nim_id_to_text(ctx->nim_id),
+ ctx->nim_id);
+
+ /* Read DMI options */
+ uint8_t options;
+
+ read_data_lin(ctx, SFP_DMI_OPTION_LIN_ADDR, sizeof(options), &options);
+ ctx->avg_pwr = options & SFP_DMI_AVG_PWR_BIT;
+ ctx->dmi_supp = options & SFP_DMI_IMPL_BIT;
+ ctx->specific_u.sfp.ext_cal = options & SFP_DMI_EXT_CAL_BIT;
+ ctx->specific_u.sfp.addr_chg = options & SFP_DMI_ADDR_CHG_BIT;
+
+ if (ctx->dmi_supp) {
+ ctx->options |=
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ }
+
+ if (ctx->dmi_supp) {
+ NT_LOG(DBG, PMD,
+ "NIM options: (DMI: %s, AvgPwr: %s, ExtCal: %s, AddrChg: %s)",
+ yes_no[ctx->dmi_supp], yes_no[ctx->avg_pwr],
+ yes_no[ctx->specific_u.sfp.ext_cal],
+ yes_no[ctx->specific_u.sfp.addr_chg]);
+ } else {
+ NT_LOG(DBG, PMD, "NIM options: DMI not supported");
+ }
+ /* Read enhanced options */
+ read_data_lin(ctx, SFP_ENHANCED_OPTIONS_LIN_ADDR, sizeof(options),
+ &options);
+ ctx->tx_disable = options & SFP_SOFT_TX_DISABLE_IMPL_BIT;
+
+ if (ctx->tx_disable)
+ ctx->options |= (1 << NIM_OPTION_TX_DISABLE);
+
+ sfp_read_vendor_info(ctx);
+
+ uint8_t nim_len_info[5];
+
+ read_data_lin(ctx, SFP_SUP_LEN_INFO_LIN_ADDR, sizeof(nim_len_info),
+ nim_len_info);
+
+ /*
+ * Returns supported length information in meters for various fibers as 5 indivi-
+ * dual values: [SM(9um), EBW(50um), MM(50um), MM(62.5um), Copper]
+ * If no length information is available for a certain entry, the returned value
+ * will be zero. This will be the case for SFP modules - EBW entry.
+ * If the MSBit is set the returned value in the lower 31 bits indicates that the
+ * supported length is greater than this.
+ */
+
+ uint16_t nim_units[5] = { 1000, 100, 10, 10,
+ 1
+ }; /* SFP MSA units in meters */
+ nim_import_len_info(ctx, &nim_len_info[0], &nim_units[0]);
+
+ if (ctx->len_info[0] != 0 || ctx->len_info[1] != 0) {
+ /*
+ * Make sure that for SFP modules the supported length for SM fibers
+ * which is given in both km and 100m units is are equal to the greatest
+ * value.
+ * The following test will also be valid if NIM_LEN_MAX has been set!
+ */
+ if (ctx->len_info[1] > ctx->len_info[0])
+ ctx->len_info[0] = ctx->len_info[1];
+
+ ctx->len_info[1] = 0; /* EBW is not supported for SFP */
+ }
+
+ read_data_lin(ctx, SFP_OPTION0_LIN_ADDR, sizeof(options), &options);
+
+ if (options & SFP_POWER_LEVEL2_REQ_BIT)
+ ctx->pwr_level_req = 2;
+ else
+ ctx->pwr_level_req = 1;
+
+ ctx->pwr_level_cur = 1;
+
+ if (ctx->pwr_level_req == 2) {
+ /* Read the current power level status */
+ read_data_lin(ctx, SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(options),
+ &options);
+
+ if (options & SFP_POWER_LEVEL2_GET_BIT)
+ ctx->pwr_level_cur = 2;
+ else
+ ctx->pwr_level_cur = 1;
+ }
+ return 0;
+}
+
+/*
+ * Read the vendor product number and from this determine which QSFP DMI options
+ * that are present. This list also covers QSFP28 modules.
+ * This function should be used if automatic detection does not work.
+ */
+static bool qsfpplus_get_qsfp_options_from_pn(nim_i2c_ctx_p ctx)
+{
+ if (strcmp(ctx->prod_no, "FTL410QE1C") == 0) {
+ /* FINISAR FTL410QE1C, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_TX_BIAS) | (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FTL410QE2C") == 0) {
+ /* FINISAR FTL410QE2C, QSFP+ */
+ ctx->options = (1 << NIM_OPTION_TEMP) |
+ (1 << NIM_OPTION_SUPPLY);
+ } else if (strcmp(ctx->prod_no, "FTL4C1QE1C") == 0) {
+ /* FINISAR FTL4C1QE1C, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-79E4Z") == 0) {
+ /*
+ * AFBR-79E4Z: The digital diagnostic accuracy is not guaranteed so only
+ * the mandatory temperature sensor is made available (although it will
+ * also be inaccurate)
+ */
+ /* AVAGO 79E4Z, QSFP+ */
+ ctx->options = (1 << NIM_OPTION_TEMP);
+ } else if (strcmp(ctx->prod_no, "AFBR-79E4Z-D") == 0) {
+ /* AVAGO 79E4Z-D, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-79EQDZ") == 0) {
+ /* AVAGO 79EQDZ, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-79EBRZ") == 0) {
+ /*
+ * Avago RxOnly BiDi NIM
+ * No sensors available not even the normally mandatory temp sensor and this
+ * is ok since the temp sensor is not mandatory on active optical modules
+ */
+ /* SFF-8436_rev4.1, p67 */
+ ctx->options = (1 << NIM_OPTION_RX_ONLY);
+ } else if (strcmp(ctx->prod_no, "AFBR-79EBPZ-NU1") == 0) {
+ /*
+ * Avago RxTx BiDi NIM
+ * No sensors available not even the normally mandatory temp sensor and this
+ * is ok since the temp sensor is not mandatory on active optical modules
+ */
+ ctx->options = 0;
+ } else if (strcmp(ctx->prod_no, "AFBR-79EBPZ") == 0) {
+ /*
+ * Avago RxTx BiDi NIM
+ * No sensors available not even the normally mandatory temp sensor and this
+ * is ok since the temp sensor is not mandatory on active optical modules
+ */
+ ctx->options = 0;
+ } else if (strcmp(ctx->prod_no, "AFBR-89CDDZ") == 0) {
+ /* AVAGO 89CDDZ, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-89BDDZ") == 0) {
+ /* AVAGO 89BDDZ, QSFP28, BiDi */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-89BRDZ") == 0) {
+ /*
+ * AVAGO 89BRDZ, QSFP28, BiDi, RxOnly
+ * but sensors have been set as above except for Tx sensors
+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_RX_ONLY);
+ /*
+ * According to mail correspondence AFBR-89BRDZ is a RxOnly version of
+ * AFBR-89BDDZ with lasers default off.
+ * The lasers can be turned on however but should probably not because the
+ * receivers might be degraded, and this is the cause for selling them as RxOnly.
+ */
+ } else if (strcmp(ctx->prod_no, "SQF1000L4LNGG01P") == 0) {
+ /* Sumitomo SQF1000L4LNGG01P, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1000L4LNGG01B") == 0) {
+ /* Sumitomo SQF1000L4LNGG01B, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1001L4LNGG01P") == 0) {
+ /* Sumitomo SQF1001L4LNGG01P, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1001L4LNGG01B") == 0) {
+ /* Sumitomo SQF1001L4LNGG01B, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1002L4LNGG01B") == 0) {
+ /* Sumitomo SQF1002L4LNGG01B, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FIM37700/171") == 0) {
+ /* Fujitsu FIM37700/171, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FIM37700/172") == 0) {
+ /* Fujitsu FIM37700/172, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "TR-FC85S-NVS") == 0) {
+ /* InnoLight TR-FC85S-NVS, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "TR-FC13L-NVS") == 0) {
+ /* InnoLight TR-FC13L-NVS, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FTLC9551REPM") == 0) {
+ /* Finisar FTLC9551REPM, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FTLC9558REPM") == 0) {
+ /* Finisar FTLC9558REPM, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else {
+ /*
+ * DO NOTE: The temperature sensor is not mandatory on active/passive copper
+ * and active optical modules
+ */
+ ctx->options = (1 << NIM_OPTION_TEMP);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Try to figure out if a sensor is present by reading its value(s) and its limits.
+ * This is a highly impirical way that cannot be guaranteed to give the correct
+ * result but it was a wish not to be dependent on a PN table based solution.
+ */
+static void qsfpplus_find_qsfp_sensor_option(nim_i2c_ctx_p ctx,
+ uint16_t value_addr,
+ uint8_t lane_count,
+ uint16_t limit_addr, bool two_compl,
+ uint32_t sensor_option)
+{
+ uint8_t data[8];
+ int i, j;
+ int value;
+ int value_list[4];
+ int limit;
+ int limit_list[4];
+ bool present;
+
+ /* Read current value(s) */
+ read_data_lin(ctx, value_addr, (uint16_t)(lane_count * 2), data);
+
+ for (j = 0; j < lane_count; j++) {
+ value = 0;
+
+ for (i = 0; i < 2; i++) {
+ value = value << 8;
+ value += data[2 * j + i];
+ }
+
+ if (two_compl && value >= 0x8000)
+ value = value - 0x10000;
+
+ value_list[j] = value;
+ }
+
+ /* Read limits Warning high/low Alarm high/low 4 values each two bytes */
+ read_data_lin(ctx, limit_addr, 8, data);
+
+ for (j = 0; j < 4; j++) {
+ limit = 0;
+
+ for (i = 0; i < 2; i++) {
+ limit = limit << 8;
+ limit += data[2 * j + i];
+ }
+
+ if (two_compl && limit >= 0x8000)
+ limit = limit - 0x10000;
+
+ limit_list[j] = limit;
+ }
+
+ /* Find out if limits contradicts each other */
+ int alarm_high = limit_list[0];
+ int alarm_low = limit_list[1];
+ int warn_high = limit_list[2];
+ int warn_low = limit_list[3];
+
+ bool alarm_limits = false; /* Are they present - that is both not zero */
+ bool warn_limits = false;
+ bool limit_conflict = false;
+
+ if (alarm_high != 0 || alarm_low != 0) {
+ alarm_limits = true;
+
+ if (alarm_high <= alarm_low)
+ limit_conflict = true;
+ }
+
+ if (warn_high != 0 || warn_low != 0) {
+ warn_limits = true;
+
+ /* Warning limits must be least restrictive */
+ if (warn_high <= warn_low)
+ limit_conflict = true;
+ else if ((warn_high > alarm_high) || (warn_low < alarm_low))
+ limit_conflict = true;
+ }
+
+ /* Try to deduce if the sensor is present or not */
+ present = false;
+
+ if (limit_conflict) {
+ present = false;
+ } else if (warn_limits ||
+ alarm_limits) { /* Is one or both present and not contradictory */
+ present = true;
+ } else {
+ /*
+ * All limits are zero - look at the sensor value
+ * If one sensor is non-zero the sensor is set to be present
+ */
+ for (j = 0; j < lane_count; j++) {
+ if (value_list[j] != 0) {
+ present = true;
+ break;
+ }
+ }
+
+ /*
+ * If all limits and values are zero then present will be false here. In this
+ * case it is assumed that the sensor is not present:
+ * Experience indicates that for QSFP+ modules RxPwr will be non-zero even with
+ * no optical input. QSFP28 modules however can easily have RxPwr equal to zero
+ * with no optical input.
+ * For all investigated modules it was found that if RxPwr is implemented then
+ * the limits are also set. This is not always the case with TxBias and TxPwr
+ * but here the measured values will be non-zero when the laser is on what it
+ * will be just after initialization since it has no external hardware disable.
+ */
+ }
+
+ if (present)
+ ctx->options |= (1U << sensor_option);
+}
+
+/*
+ * Find active QSFP sensors.
+ */
+static void qsfpplus_get_qsfp_options_from_data(nim_i2c_ctx_p ctx)
+{
+ ctx->options = 0;
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TEMP_LIN_ADDR, 1,
+ QSFP_TEMP_THRESH_LIN_ADDR, true,
+ NIM_OPTION_TEMP);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_VOLT_LIN_ADDR, 1,
+ QSFP_VOLT_THRESH_LIN_ADDR, false,
+ NIM_OPTION_SUPPLY);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_RX_PWR_LIN_ADDR, 4,
+ QSFP_RX_PWR_THRESH_LIN_ADDR, false,
+ NIM_OPTION_RX_POWER);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TX_PWR_LIN_ADDR, 4,
+ QSFP_TX_PWR_THRESH_LIN_ADDR, false,
+ NIM_OPTION_TX_POWER);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TX_BIAS_LIN_ADDR, 4,
+ QSFP_BIAS_THRESH_LIN_ADDR, false,
+ NIM_OPTION_TX_BIAS);
+}
+
+static void sfp_find_port_params(nim_i2c_ctx_p ctx)
+{
+ uint8_t data;
+ uint16_t bit_rate_nom;
+ uint8_t connector;
+ uint8_t gig_eth_comp;
+ uint8_t dmi_opt;
+ uint8_t fiber_chan_tx_tech;
+ unsigned int len_sm;
+ unsigned int len_mm_50um;
+ unsigned int len_mm_62_5um;
+
+ ctx->specific_u.sfp.sfp28 = false;
+
+ /* gigEthComp: */
+ static const uint8_t eth_1000_b_t = 1 << 3;
+ static const uint8_t eth_1000_b_sx = 1 << 0;
+ static const uint8_t eth_1000_b_lx = 1 << 1;
+
+ /* fiberChanTxTech: */
+ static const uint8_t cu_passive = 1 << 2;
+ static const uint8_t cu_active = 1 << 3;
+
+ /* dmiOpt: */
+ static const uint8_t dd_present = 1 << 6;
+
+ /* connector: */
+ static const uint8_t cu_pig_tail = 0x21;
+
+ ctx->port_type = NT_PORT_TYPE_SFP_NOT_RECOGNISED;
+
+ read_data_lin(ctx, 12, sizeof(data), &data);
+ bit_rate_nom = (uint16_t)(data * 100);
+
+ read_data_lin(ctx, 2, sizeof(connector), &connector);
+ read_data_lin(ctx, 6, sizeof(gig_eth_comp), &gig_eth_comp);
+ read_data_lin(ctx, 92, sizeof(dmi_opt), &dmi_opt);
+ read_data_lin(ctx, 8, sizeof(fiber_chan_tx_tech), &fiber_chan_tx_tech);
+
+ read_data_lin(ctx, 15, sizeof(data), &data);
+ len_sm = (unsigned int)data * 100; /* Unit is 100m */
+
+ read_data_lin(ctx, 16, sizeof(data), &data);
+ len_mm_50um = (unsigned int)data * 10; /* Unit is 10m */
+
+ read_data_lin(ctx, 17, sizeof(data), &data);
+ len_mm_62_5um = (unsigned int)data * 10; /* Unit is 10m */
+
+ /* First find out if it is a SFP or a SFP+ NIM */
+ if (bit_rate_nom == 0) {
+ /*
+ * A Nominal bit rate of zero indicates that it has not been defined and must
+ * be deduced from transceiver technology
+ */
+ ctx->specific_u.sfp.sfpplus = !(gig_eth_comp & eth_1000_b_t);
+ } else if (bit_rate_nom == 25500) {
+ /* SFF-8024 - 4.4 Extended Specification Compliance References */
+ read_data_lin(ctx, 36, sizeof(data), &data);
+
+ if (data == 0x02)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_SR;
+ else if (data == 0x03)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_LR;
+ else if (data == 0x0B)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_L;
+ else if (data == 0x0C)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_S;
+ else if (data == 0x0D)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_N;
+ else
+ ctx->port_type = NT_PORT_TYPE_SFP_28;
+
+ ctx->specific_u.sfp.sfp28 = true;
+ ctx->specific_u.sfp.sfpplus = true;
+
+ /*
+ * Whitelist of 25G transceivers known to also support 10G.
+ * There is no way to inquire about this capability.
+ */
+ if ((strcmp(ctx->prod_no, "TR-PZ85S-N00") == 0) ||
+ (strcmp(ctx->prod_no, "TR-PZ13L-N00") == 0) ||
+ (strcmp(ctx->prod_no, "FTLF8536P4BCV") == 0) ||
+ (strcmp(ctx->prod_no, "FTLF1436P4BCV") == 0)) {
+ ctx->specific_u.sfp.dual_rate = true;
+
+ /* Change the port type for dual rate modules */
+ if (ctx->port_type == NT_PORT_TYPE_SFP_28_SR)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_SR_DR;
+ else if (ctx->port_type == NT_PORT_TYPE_SFP_28_LR)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_LR_DR;
+ }
+
+ return;
+ }
+ ctx->specific_u.sfp.sfpplus = (bit_rate_nom >= 10000);
+ /* Then find sub-types of each */
+ if (ctx->specific_u.sfp.sfpplus) {
+ if (fiber_chan_tx_tech & cu_active) {
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC;
+ } else if (fiber_chan_tx_tech & cu_passive) {
+ if (connector == cu_pig_tail)
+ ctx->port_type =
+ NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC;
+ else
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS_CU;
+ } else {
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS;
+ }
+ if (gig_eth_comp & (eth_1000_b_sx | eth_1000_b_lx)) {
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS_DUAL_RATE;
+ ctx->specific_u.sfp.dual_rate = true;
+ }
+
+ read_data_lin(ctx, 65, sizeof(data), &data);
+ /* Test hard RATE_SELECT bit */
+ ctx->specific_u.sfp.hw_rate_sel = ((data & (1 << 5)) != 0);
+
+ read_data_lin(ctx, 93, sizeof(data), &data);
+ /* Test soft RATE_SELECT bit */
+ ctx->specific_u.sfp.sw_rate_sel = ((data & (1 << 3)) != 0);
+ } else { /* SFP */
+ /* 100M */
+ if (bit_rate_nom != 0 && bit_rate_nom < 1000) {
+ ctx->port_type = NT_PORT_TYPE_SFP_FX;
+ /* 1G */
+ } else {
+ ctx->specific_u.sfp.cu_type = false;
+ if (gig_eth_comp & eth_1000_b_sx) {
+ ctx->port_type = NT_PORT_TYPE_SFP_SX;
+ } else if (gig_eth_comp & eth_1000_b_lx) {
+ ctx->port_type = NT_PORT_TYPE_SFP_LX;
+ } else if (gig_eth_comp & eth_1000_b_t) {
+ ctx->specific_u.sfp.tri_speed =
+ sfp_is_supported_tri_speed_pn(ctx->prod_no);
+
+ if (ctx->specific_u.sfp.tri_speed) {
+ ctx->port_type =
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED;
+ } else {
+ ctx->port_type = NT_PORT_TYPE_SFP_CU;
+ }
+ ctx->specific_u.sfp.cu_type = true;
+ } else {
+ /*
+ * Not all modules report their ethernet compliance correctly so use
+ * length indicators
+ */
+ if (len_sm > 0)
+ ctx->port_type = NT_PORT_TYPE_SFP_LX;
+ else if ((len_mm_50um > 0) || (len_mm_62_5um > 0))
+ ctx->port_type = NT_PORT_TYPE_SFP_SX;
+ }
+
+ /* Add Diagnostic Data suffix if necessary */
+ if (dmi_opt & dd_present) {
+ if (ctx->port_type == NT_PORT_TYPE_SFP_SX)
+ ctx->port_type = NT_PORT_TYPE_SFP_SX_DD;
+ else if (ctx->port_type == NT_PORT_TYPE_SFP_LX)
+ ctx->port_type = NT_PORT_TYPE_SFP_LX_DD;
+ else if (ctx->port_type == NT_PORT_TYPE_SFP_CU)
+ ctx->port_type = NT_PORT_TYPE_SFP_CU_DD;
+ else if (ctx->port_type ==
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED)
+ ctx->port_type =
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED_DD;
+ }
+ }
+ }
+}
+
+
+static void sfp_set_speed_mask(nim_i2c_ctx_p ctx)
+{
+ if (ctx->specific_u.sfp.sfp28) {
+ ctx->speed_mask = NT_LINK_SPEED_25G; /* Default for SFP28 */
+ if (ctx->specific_u.sfp.dual_rate)
+ ctx->speed_mask |= NT_LINK_SPEED_10G;
+ } else if (ctx->specific_u.sfp.sfpplus) {
+ ctx->speed_mask = NT_LINK_SPEED_10G; /* Default for SFP+ */
+ if (ctx->specific_u.sfp.dual_rate)
+ ctx->speed_mask |= NT_LINK_SPEED_1G;
+ if (ctx->port_type == NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC)
+ ctx->speed_mask |= NT_LINK_SPEED_1G;
+ if (ctx->port_type == NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC)
+ ctx->speed_mask |= NT_LINK_SPEED_1G;
+ } else { /* SFP */
+ if (ctx->port_type == NT_PORT_TYPE_SFP_FX) {
+ ctx->speed_mask = NT_LINK_SPEED_100M;
+ } else {
+ ctx->speed_mask = NT_LINK_SPEED_1G; /* Default for SFP */
+ if (ctx->specific_u.sfp.dual_rate ||
+ ctx->specific_u.sfp.tri_speed)
+ ctx->speed_mask |= NT_LINK_SPEED_100M;
+ if (ctx->specific_u.sfp.tri_speed)
+ ctx->speed_mask |= NT_LINK_SPEED_10M;
+ }
+ }
+ if (ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_L ||
+ ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_S ||
+ ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_N) {
+ /* Enable multiple speed setting for SFP28 DAC cables */
+ ctx->speed_mask = (NT_LINK_SPEED_25G | NT_LINK_SPEED_10G |
+ NT_LINK_SPEED_1G);
+ }
+}
+
+static void qsfp28_find_port_params(nim_i2c_ctx_p ctx)
+{
+ uint8_t fiber_chan_speed;
+
+ /* Table 6-17 SFF-8636 */
+ read_data_lin(ctx, QSFP_SPEC_COMPLIANCE_CODES_ADDR, 1, &fiber_chan_speed);
+
+ if (fiber_chan_speed & (1 << 7)) {
+ /* SFF-8024, Rev 4.7, Table 4-4 */
+ uint8_t extended_specification_compliance_code = 0;
+
+ read_data_lin(ctx, QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR, 1,
+ &extended_specification_compliance_code);
+
+ switch (extended_specification_compliance_code) {
+ case 0x02:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_SR4;
+ break;
+ case 0x03:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_LR4;
+ break;
+ case 0x0B:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_L;
+ break;
+ case 0x0C:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_S;
+ break;
+ case 0x0D:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_N;
+ break;
+ case 0x25:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_DR;
+ break;
+ case 0x26:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_FR;
+ break;
+ case 0x27:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_LR;
+ break;
+ default:
+ ctx->port_type = NT_PORT_TYPE_QSFP28;
+ }
+ } else {
+ ctx->port_type = NT_PORT_TYPE_QSFP28;
+ }
+}
+
+/*
+ * If true the user must actively select the desired rate. If false the module
+ * however can still support several rates without the user is required to select
+ * one of them. Supported rates must then be deduced from the product number.
+ * SFF-8636, Rev 2.10a:
+ * p40: 6.2.7 Rate Select
+ * p85: A.2 Rate Select
+ */
+static bool qsfp28_is_rate_selection_enabled(nim_i2c_ctx_p ctx)
+{
+ const uint8_t ext_rate_select_compl_reg_addr = 141;
+ const uint8_t options_reg_addr = 195;
+ const uint8_t enh_options_reg_addr = 221;
+
+ uint8_t rate_select_ena = (read_byte(ctx, options_reg_addr) >> 5) &
+ 0x01; /* bit: 5 */
+
+ if (rate_select_ena == 0)
+ return false;
+
+ uint8_t rate_select_type = (read_byte(ctx, enh_options_reg_addr) >> 2) &
+ 0x03; /* bit 3..2 */
+
+ if (rate_select_type != 2) {
+ NT_LOG(DBG, PMD, "NIM has unhandled rate select type (%d)",
+ rate_select_type);
+ return false;
+ }
+
+ uint8_t ext_rate_select_ver = read_byte(ctx, ext_rate_select_compl_reg_addr) &
+ 0x03; /* bit 1..0 */
+
+ if (ext_rate_select_ver != 0x02) {
+ NT_LOG(DBG, PMD,
+ "NIM has unhandled extended rate select version (%d)",
+ ext_rate_select_ver);
+ return false;
+ }
+
+ return true; /* When true selectRate() can be used */
+}
+
+static void qsfp28_set_speed_mask(nim_i2c_ctx_p ctx)
+{
+ if (ctx->port_type == NT_PORT_TYPE_QSFP28_FR ||
+ ctx->port_type == NT_PORT_TYPE_QSFP28_DR ||
+ ctx->port_type == NT_PORT_TYPE_QSFP28_LR) {
+ if (ctx->lane_idx < 0)
+ ctx->speed_mask = NT_LINK_SPEED_100G;
+ else
+ ctx->speed_mask =
+ 0; /* PAM-4 modules can only run on all lanes together */
+ } else {
+ if (ctx->lane_idx < 0)
+ ctx->speed_mask = NT_LINK_SPEED_100G;
+ else
+ ctx->speed_mask = NT_LINK_SPEED_25G;
+
+ if (qsfp28_is_rate_selection_enabled(ctx)) {
+ /*
+ * It is assumed that if the module supports dual rates then the other rate
+ * is 10G per lane or 40G for all lanes.
+ */
+ if (ctx->lane_idx < 0)
+ ctx->speed_mask |= NT_LINK_SPEED_40G;
+ else
+ ctx->speed_mask = NT_LINK_SPEED_10G;
+ }
+ }
+}
+
+static void qsfpplus_find_port_params(nim_i2c_ctx_p ctx)
+{
+ uint8_t device_tech;
+
+ read_data_lin(ctx, QSFP_TRANSMITTER_TYPE_LIN_ADDR, sizeof(device_tech),
+ &device_tech);
+
+ switch (device_tech & 0xF0) {
+ case 0xA0: /* Copper cable unequalized */
+ case 0xB0: /* Copper cable passive equalized */
+ ctx->port_type = NT_PORT_TYPE_QSFP_PASSIVE_DAC;
+ break;
+ case 0xC0: /* Copper cable, near and far end limiting active equalizers */
+ case 0xD0: /* Copper cable, far end limiting active equalizers */
+ case 0xE0: /* Copper cable, near end limiting active equalizers */
+ case 0xF0: /* Copper cable, linear active equalizers */
+ ctx->port_type = NT_PORT_TYPE_QSFP_ACTIVE_DAC;
+ break;
+ default: /* Optical */
+ ctx->port_type = NT_PORT_TYPE_QSFP_PLUS;
+ break;
+ }
+}
+
+static void qsfpplus_set_speed_mask(nim_i2c_ctx_p ctx)
+{
+ ctx->speed_mask = (ctx->lane_idx < 0) ? NT_LINK_SPEED_40G :
+ (NT_LINK_SPEED_10G);
+}
+
+static int sfp_preinit(nim_i2c_ctx_p ctx)
+{
+ int res = sfp_read_basic_data(ctx);
+
+ if (!res) {
+ sfp_find_port_params(ctx);
+ sfp_set_speed_mask(ctx);
+ }
+ return res;
+}
+
+static void qsfpplus_construct(nim_i2c_ctx_p ctx, int8_t lane_idx)
+{
+ assert(lane_idx < 4);
+ ctx->specific_u.qsfp.qsfp28 = false;
+ ctx->lane_idx = lane_idx;
+ ctx->lane_count = 4;
+}
+
+static int qsfpplus_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx)
+{
+ qsfpplus_construct(ctx, lane_idx);
+ int res = qsfpplus_read_basic_data(ctx);
+
+ if (!res) {
+ qsfpplus_find_port_params(ctx);
+ /*
+ * If not on the known modules list try to figure out which sensors that are present
+ */
+ if (!qsfpplus_get_qsfp_options_from_pn(ctx)) {
+ NT_LOG(DBG, NTHW,
+ "NIM options not known in advance - trying to detect");
+ qsfpplus_get_qsfp_options_from_data(ctx);
+ }
+
+ /*
+ * Read if TX_DISABLE has been implemented
+ * For passive optical modules this is required while it for copper and active
+ * optical modules is optional. Under all circumstances register 195.4 will
+ * indicate, if TX_DISABLE has been implemented in register 86.0-3
+ */
+ uint8_t value;
+
+ read_data_lin(ctx, QSFP_OPTION3_LIN_ADDR, sizeof(value), &value);
+
+ ctx->tx_disable = (value & QSFP_OPTION3_TX_DISABLE_BIT) != 0;
+
+ if (ctx->tx_disable)
+ ctx->options |= (1 << NIM_OPTION_TX_DISABLE);
+
+ /*
+ * Previously - considering AFBR-89BRDZ - code tried to establish if a module was
+ * RxOnly by testing the state of the lasers after reset. Lasers were for this
+ * module default disabled.
+ * However that code did not work for GigaLight, GQS-MPO400-SR4C so it was
+ * decided that this option should not be detected automatically but from PN
+ */
+ ctx->specific_u.qsfp.rx_only =
+ (ctx->options & (1 << NIM_OPTION_RX_ONLY)) != 0;
+ qsfpplus_set_speed_mask(ctx);
+ }
+ return res;
+}
+
+static void qsfp28_wait_for_ready_after_reset(nim_i2c_ctx_p ctx)
+{
+ uint8_t data;
+ bool init_complete_flag_present = false;
+
+ /*
+ * Revision compliance
+ * 7: SFF-8636 Rev 2.5, 2.6 and 2.7
+ * 8: SFF-8636 Rev 2.8, 2.9 and 2.10
+ */
+ read_data_lin(ctx, 1,
+ sizeof(ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance),
+ &ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance);
+ NT_LOG(DBG, NTHW, "NIM RevCompliance = %d",
+ ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance);
+
+ /* Wait if lane_idx == -1 (all lanes are used) or lane_idx == 0 (the first lane) */
+ if (ctx->lane_idx > 0)
+ return;
+
+ if (ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance >= 7) {
+ /* Check if init complete flag is implemented */
+ read_data_lin(ctx, 221, sizeof(data), &data);
+ init_complete_flag_present = (data & (1 << 4)) != 0;
+ }
+
+ NT_LOG(DBG, NTHW, "NIM InitCompleteFlagPresent = %d",
+ init_complete_flag_present);
+
+ /*
+ * If the init complete flag is not present then wait 500ms that together with 500ms
+ * after reset (in the adapter code) should be enough to read data from upper pages
+ * that otherwise would not be ready. Especially BiDi modules AFBR-89BDDZ have been
+ * prone to this when trying to read sensor options using getQsfpOptionsFromData()
+ * Probably because access to the paged address space is required.
+ */
+ if (!init_complete_flag_present) {
+ NT_OS_WAIT_USEC(500000);
+ return;
+ }
+
+ /* Otherwise wait for the init complete flag to be set */
+ int count = 0;
+
+ while (true) {
+ if (count > 10) { /* 1 s timeout */
+ NT_LOG(WRN, NTHW, "Timeout waiting for module ready");
+ break;
+ }
+
+ read_data_lin(ctx, 6, sizeof(data), &data);
+
+ if (data & 0x01) {
+ NT_LOG(DBG, NTHW, "Module ready after %dms",
+ count * 100);
+ break;
+ }
+
+ NT_OS_WAIT_USEC(100000); /* 100 ms */
+ count++;
+ }
+}
+
+static void qsfp28_get_fec_options(nim_i2c_ctx_p ctx)
+{
+ const char *const nim_list[] = {
+ "AFBR-89BDDZ", /* Avago BiDi */
+ "AFBR-89BRDZ", /* Avago BiDi, RxOnly */
+ "FTLC4352RKPL", /* Finisar QSFP28-LR */
+ "FTLC4352RHPL", /* Finisar QSFP28-DR */
+ "FTLC4352RJPL", /* Finisar QSFP28-FR */
+ "SFBR-89BDDZ-CS4", /* Foxconn, QSFP28 100G/40G BiDi */
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(nim_list); i++) {
+ if (ctx->prod_no == nim_list[i]) {
+ ctx->options |= (1 << NIM_OPTION_MEDIA_SIDE_FEC);
+ ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena =
+ true;
+ NT_LOG(DBG, NTHW, "Found FEC info via PN list");
+ return;
+ }
+ }
+
+ /*
+ * For modules not in the list find FEC info via registers
+ * Read if the module has controllable FEC
+ * SFF-8636, Rev 2.10a TABLE 6-28 Equalizer, Emphasis, Amplitude and Timing)
+ * (Page 03h, Bytes 224-229)
+ */
+ uint8_t data;
+ uint16_t addr = 227 + 3 * 128;
+
+ read_data_lin(ctx, addr, sizeof(data), &data);
+
+ /* Check if the module has FEC support that can be controlled */
+ ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl =
+ (data & (1 << 6)) != 0;
+ ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl =
+ (data & (1 << 7)) != 0;
+
+ if (ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl)
+ ctx->options |= (1 << NIM_OPTION_MEDIA_SIDE_FEC);
+
+ if (ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl)
+ ctx->options |= (1 << NIM_OPTION_HOST_SIDE_FEC);
+}
+
+static int qsfp28_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx)
+{
+ int res = qsfpplus_preinit(ctx, lane_idx);
+
+ if (!res) {
+ qsfp28_wait_for_ready_after_reset(ctx);
+ memset(&ctx->specific_u.qsfp.specific_u.qsfp28, 0,
+ sizeof(ctx->specific_u.qsfp.specific_u.qsfp28));
+ ctx->specific_u.qsfp.qsfp28 = true;
+ qsfp28_find_port_params(ctx);
+ qsfp28_get_fec_options(ctx);
+ qsfp28_set_speed_mask(ctx);
+ }
+ return res;
+}
+
+static void sfp_nim_add_all_sensors(uint8_t m_port_no, nim_i2c_ctx_t *ctx,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt)
+{
+ struct nim_sensor_group *sensor = NULL;
+ *nim_sensors_cnt = 0;
+
+ if (ctx == NULL || nim_sensors_ptr == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ /*
+ * If the user has not provided a name for the temperature sensor then apply
+ * one automatically
+ */
+ if (strlen(sfp_sensors_level0[0].name) == 0) {
+ if (ctx->specific_u.sfp.sfp28) {
+ rte_strscpy(sfp_sensors_level0[0].name, "SFP28",
+ sizeof(sfp_sensors_level0[0].name));
+ } else if (ctx->specific_u.sfp.sfpplus) {
+ rte_strscpy(sfp_sensors_level0[0].name, "SFP+",
+ sizeof(sfp_sensors_level0[0].name));
+ } else {
+ rte_strscpy(sfp_sensors_level0[0].name, "SFP",
+ sizeof(sfp_sensors_level0[0].name));
+ }
+ }
+
+ /* allocate temperature sensor */
+ nim_sensors_ptr[m_port_no] = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level0[0]);
+ sensor = nim_sensors_ptr[m_port_no];
+ sensor->read = &nim_read_sfp_temp;
+ (*nim_sensors_cnt)++;
+
+ /* voltage */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[0]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_voltage;
+ (*nim_sensors_cnt)++;
+
+ /* bias current */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[1]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_bias_current;
+ (*nim_sensors_cnt)++;
+
+ /* tx power */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[2]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_tx_power;
+ (*nim_sensors_cnt)++;
+
+ /* rx power */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[3]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_rx_power;
+ (*nim_sensors_cnt)++;
+}
+
+static void
+qsfp_plus_nim_add_all_sensors(uint8_t m_port_no, nim_i2c_ctx_t *ctx,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt)
+{
+ struct nim_sensor_group *sensor = NULL;
+
+ if (ctx == NULL || nim_sensors_ptr == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ /*
+ * If the user has not provided a name for the temperature sensor then apply
+ * one automatically
+ */
+ if (strlen(qsfp_sensor_level0[0].name) == 0) {
+ if (ctx->specific_u.qsfp.qsfp28)
+ rte_strscpy(qsfp_sensor_level0[0].name, "QSFP28",
+ sizeof(qsfp_sensor_level0[0].name));
+ else
+ rte_strscpy(qsfp_sensor_level0[0].name, "QSFP+",
+ sizeof(qsfp_sensor_level0[0].name));
+ }
+
+ /* temperature sensor */
+ nim_sensors_ptr[m_port_no] = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &qsfp_sensor_level0[0]);
+ sensor = nim_sensors_ptr[m_port_no];
+ sensor->read = &nim_read_qsfp_temp;
+ (*nim_sensors_cnt)++;
+
+ /* voltage */
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[0]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_voltage;
+ (*nim_sensors_cnt)++;
+
+ /* bias current sensors */
+ for (uint8_t i = 1; i < 5; i++) {
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[i]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_bias_current;
+ (*nim_sensors_cnt)++;
+ }
+
+ /* tx power */
+ for (uint8_t i = 5; i < 9; i++) {
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[i]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_tx_power;
+ (*nim_sensors_cnt)++;
+ }
+
+ /* rx power */
+ for (uint8_t i = 9; i < 13; i++) {
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[i]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_rx_power;
+ (*nim_sensors_cnt)++;
+ }
+}
+
+struct nim_sensor_group *
+allocate_nim_sensor_group(uint8_t port, struct nim_i2c_ctx *ctx,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *sd)
+{
+ struct nim_sensor_group *sg = malloc(sizeof(struct nim_sensor_group));
+
+ if (sg == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__);
+ return NULL;
+ }
+ sg->sensor = allocate_sensor_by_description(port, ssrc, sd);
+ sg->ctx = ctx;
+ sg->next = NULL;
+ return sg;
+}
+
+int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra, uint8_t port,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt)
+{
+ int res = i2c_nim_common_construct(ctx);
+
+ switch (translate_nimid(ctx)) {
+ case NT_NIM_SFP_SFP_PLUS:
+ sfp_preinit(ctx);
+ sfp_nim_add_all_sensors(port, ctx, nim_sensors_ptr,
+ nim_sensors_cnt);
+ break;
+ case NT_NIM_QSFP_PLUS:
+ qsfpplus_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1);
+ qsfp_plus_nim_add_all_sensors(port, ctx, nim_sensors_ptr,
+ nim_sensors_cnt);
+ break;
+ case NT_NIM_QSFP28:
+ qsfp28_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1);
+ qsfp_plus_nim_add_all_sensors(port, ctx, nim_sensors_ptr,
+ nim_sensors_cnt);
+ break;
+ default:
+ res = 1;
+ NT_LOG(ERR, NTHW, "NIM type %s is not supported.\n",
+ nim_id_to_text(ctx->nim_id));
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nim/i2c_nim.h b/drivers/net/ntnic/nim/i2c_nim.h
new file mode 100644
index 0000000000..f664e6b7ee
--- /dev/null
+++ b/drivers/net/ntnic/nim/i2c_nim.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef I2C_NIM_H_
+#define I2C_NIM_H_
+
+#include "nthw_drv.h"
+#include "nim_defines.h"
+#include "nt_link_speed.h"
+
+#include "sensors.h"
+
+typedef struct sfp_nim_state {
+ uint8_t br; /* bit rate, units of 100 MBits/sec */
+} sfp_nim_state_t, *sfp_nim_state_p;
+
+typedef struct nim_i2c_ctx {
+ nthw_iic_t hwiic; /* depends on *Fpga_t, instance number, and cycle time */
+ uint8_t instance;
+ uint8_t devaddr;
+ uint8_t regaddr;
+ uint8_t nim_id;
+ nt_port_type_t port_type;
+
+ char vendor_name[17];
+ char prod_no[17];
+ char serial_no[17];
+ char date[9];
+ char rev[5];
+ bool avg_pwr;
+ bool content_valid;
+ uint8_t pwr_level_req;
+ uint8_t pwr_level_cur;
+ uint16_t len_info[5];
+ uint32_t speed_mask; /* Speeds supported by the NIM */
+ int8_t lane_idx; /* Is this associated with a single lane or all lanes (-1) */
+ uint8_t lane_count;
+ uint32_t options;
+ bool tx_disable;
+ bool dmi_supp;
+
+ union {
+ struct {
+ bool sfp28;
+ bool sfpplus;
+ bool dual_rate;
+ bool hw_rate_sel;
+ bool sw_rate_sel;
+ bool cu_type;
+ bool tri_speed;
+ bool ext_cal;
+ bool addr_chg;
+ } sfp;
+
+ struct {
+ bool rx_only;
+ bool qsfp28;
+ union {
+ struct {
+ uint8_t rev_compliance;
+ bool media_side_fec_ctrl;
+ bool host_side_fec_ctrl;
+ bool media_side_fec_ena;
+ bool host_side_fec_ena;
+ } qsfp28;
+ } specific_u;
+ } qsfp;
+
+ } specific_u;
+} nim_i2c_ctx_t, *nim_i2c_ctx_p;
+
+struct nim_sensor_group {
+ struct nt_adapter_sensor *sensor;
+ void (*read)(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+ struct nim_i2c_ctx *ctx;
+ struct nim_sensor_group *next;
+};
+
+struct nim_sensor_group *
+allocate_nim_sensor_group(uint8_t port, struct nim_i2c_ctx *ctx,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *sd);
+
+/*
+ * Utility functions
+ */
+
+nt_nim_identifier_t translate_nimid(const nim_i2c_ctx_t *ctx);
+
+/*
+ * Builds an nim state for the port implied by `ctx`, returns zero
+ * if successful, and non-zero otherwise. SFP and QSFP nims are supported
+ */
+int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state);
+
+/*
+ * Returns a type name such as "SFP/SFP+" for a given NIM type identifier,
+ * or the string "ILLEGAL!".
+ */
+const char *nim_id_to_text(uint8_t nim_id);
+
+int nim_sfp_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable);
+
+int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_t *ctx, bool disable,
+ int lane_idx);
+
+int nim_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed);
+
+/*
+ * This function tries to classify NIM based on it's ID and some register reads
+ * and collects information into ctx structure. The @extra parameter could contain
+ * the initialization argument for specific type of NIMS.
+ */
+int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra, uint8_t port,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt);
+
+int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
+ void *data);
+
+#endif /* I2C_NIM_H_ */
diff --git a/drivers/net/ntnic/nim/nim_defines.h b/drivers/net/ntnic/nim/nim_defines.h
new file mode 100644
index 0000000000..da3567d073
--- /dev/null
+++ b/drivers/net/ntnic/nim/nim_defines.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NIM_DEFINES_H_
+#define NIM_DEFINES_H_
+
+#define NIM_IDENTIFIER_ADDR 0 /* 1 byte */
+
+#define SFP_BIT_RATE_ADDR 12 /* 1 byte */
+#define SFP_VENDOR_NAME_ADDR 20 /* 16bytes */
+#define SFP_VENDOR_PN_ADDR 40 /* 16bytes */
+#define SFP_VENDOR_REV_ADDR 56 /* 4bytes */
+#define SFP_VENDOR_SN_ADDR 68 /* 16bytes */
+#define SFP_VENDOR_DATE_ADDR 84 /* 8bytes */
+
+#define SFP_CONTROL_STATUS_LIN_ADDR (110U + 256U) /* 0xA2 */
+#define SFP_SOFT_TX_DISABLE_BIT (1U << 6)
+
+#define QSFP_EXTENDED_IDENTIFIER 129
+#define QSFP_SUP_LEN_INFO_ADDR 142 /* 5bytes */
+#define QSFP_TRANSMITTER_TYPE_ADDR 147 /* 1byte */
+#define QSFP_VENDOR_NAME_ADDR 148 /* 16bytes */
+#define QSFP_VENDOR_PN_ADDR 168 /* 16bytes */
+#define QSFP_VENDOR_REV_ADDR 184 /* 2bytes */
+#define QSFP_VENDOR_SN_ADDR 196 /* 16bytes */
+#define QSFP_VENDOR_DATE_ADDR 212 /* 8bytes */
+
+/* I2C addresses */
+#define nim_i2c_0xa0 0xA0 /* Basic I2C address */
+#define nim_i2c_0xa2 0xA2 /* Diagnostic monitoring */
+#define nim_i2c_0xac 0xAC /* Address of integrated PHY */
+
+typedef enum {
+ NIM_OPTION_TEMP = 0,
+ NIM_OPTION_SUPPLY,
+ NIM_OPTION_RX_POWER,
+ NIM_OPTION_TX_BIAS,
+ NIM_OPTION_TX_POWER,
+ NIM_OPTION_TX_DISABLE,
+ /* Indicates that the module should be checked for the two next FEC types */
+ NIM_OPTION_FEC,
+ NIM_OPTION_MEDIA_SIDE_FEC,
+ NIM_OPTION_HOST_SIDE_FEC,
+ NIM_OPTION_RX_ONLY
+} nim_option_t;
+
+enum nt_nim_identifier_e {
+ NT_NIM_UNKNOWN = 0x00, /* Nim type is unknown */
+ NT_NIM_GBIC = 0x01, /* Nim type = GBIC */
+ NT_NIM_FIXED = 0x02, /* Nim type = FIXED */
+ NT_NIM_SFP_SFP_PLUS = 0x03, /* Nim type = SFP/SFP+ */
+ NT_NIM_300_PIN_XBI = 0x04, /* Nim type = 300 pin XBI */
+ NT_NIM_XEN_PAK = 0x05, /* Nim type = XEN-PAK */
+ NT_NIM_XFP = 0x06, /* Nim type = XFP */
+ NT_NIM_XFF = 0x07, /* Nim type = XFF */
+ NT_NIM_XFP_E = 0x08, /* Nim type = XFP-E */
+ NT_NIM_XPAK = 0x09, /* Nim type = XPAK */
+ NT_NIM_X2 = 0x0A, /* Nim type = X2 */
+ NT_NIM_DWDM = 0x0B, /* Nim type = DWDM */
+ NT_NIM_QSFP = 0x0C, /* Nim type = QSFP */
+ NT_NIM_QSFP_PLUS = 0x0D, /* Nim type = QSFP+ */
+ NT_NIM_QSFP28 = 0x11, /* Nim type = QSFP28 */
+ NT_NIM_CFP4 = 0x12, /* Nim type = CFP4 */
+};
+
+typedef enum nt_nim_identifier_e nt_nim_identifier_t;
+
+/*
+ * Port types
+ * The use of all non-generic XX_NOT_PRESENT is deprecated - use
+ * NT_PORT_TYPE_NIM_NOT_PRESENT instead
+ */
+enum nt_port_type_e {
+ NT_PORT_TYPE_NOT_AVAILABLE =
+ 0, /* The NIM/port type is not available (unknown) */
+ NT_PORT_TYPE_NOT_RECOGNISED, /* The NIM/port type not recognized */
+ NT_PORT_TYPE_RJ45, /* RJ45 type */
+ NT_PORT_TYPE_SFP_NOT_PRESENT, /* SFP type but slot is empty */
+ NT_PORT_TYPE_SFP_SX, /* SFP SX */
+ NT_PORT_TYPE_SFP_SX_DD, /* SFP SX digital diagnostic */
+ NT_PORT_TYPE_SFP_LX, /* SFP LX */
+ NT_PORT_TYPE_SFP_LX_DD, /* SFP LX digital diagnostic */
+ NT_PORT_TYPE_SFP_ZX, /* SFP ZX */
+ NT_PORT_TYPE_SFP_ZX_DD, /* SFP ZX digital diagnostic */
+ NT_PORT_TYPE_SFP_CU, /* SFP copper */
+ NT_PORT_TYPE_SFP_CU_DD, /* SFP copper digital diagnostic */
+ NT_PORT_TYPE_SFP_NOT_RECOGNISED, /* SFP unknown */
+ NT_PORT_TYPE_XFP, /* XFP */
+ NT_PORT_TYPE_XPAK, /* XPAK */
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED, /* SFP copper tri-speed */
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED_DD, /* SFP copper tri-speed digital diagnostic */
+ NT_PORT_TYPE_SFP_PLUS, /* SFP+ type */
+ NT_PORT_TYPE_SFP_PLUS_NOT_PRESENT, /* SFP+ type but slot is empty */
+ NT_PORT_TYPE_XFP_NOT_PRESENT, /* XFP type but slot is empty */
+ NT_PORT_TYPE_QSFP_PLUS_NOT_PRESENT, /* QSFP type but slot is empty */
+ NT_PORT_TYPE_QSFP_PLUS, /* QSFP type */
+ NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC, /* SFP+ Passive DAC */
+ NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC, /* SFP+ Active DAC */
+ NT_PORT_TYPE_CFP4, /* CFP4 type */
+ NT_PORT_TYPE_CFP4_LR4 = NT_PORT_TYPE_CFP4, /* CFP4 100G, LR4 type */
+ NT_PORT_TYPE_CFP4_NOT_PRESENT, /* CFP4 type but slot is empty */
+ NT_PORT_TYPE_INITIALIZE, /* The port type is not fully established yet */
+ NT_PORT_TYPE_NIM_NOT_PRESENT, /* Generic "Not present" */
+ NT_PORT_TYPE_HCB, /* Test mode: Host Compliance Board */
+ NT_PORT_TYPE_NOT_SUPPORTED, /* The NIM type is not supported in this context */
+ NT_PORT_TYPE_SFP_PLUS_DUAL_RATE, /* SFP+ supports 1G/10G */
+ NT_PORT_TYPE_CFP4_SR4, /* CFP4 100G, SR4 type */
+ NT_PORT_TYPE_QSFP28_NOT_PRESENT, /* QSFP28 type but slot is empty */
+ NT_PORT_TYPE_QSFP28, /* QSFP28 type */
+ NT_PORT_TYPE_QSFP28_SR4, /* QSFP28-SR4 type */
+ NT_PORT_TYPE_QSFP28_LR4, /* QSFP28-LR4 type */
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ NT_PORT_TYPE_QSFP_PLUS_4X10,
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ NT_PORT_TYPE_QSFP_PASSIVE_DAC_4X10,
+ NT_PORT_TYPE_QSFP_PASSIVE_DAC =
+ NT_PORT_TYPE_QSFP_PASSIVE_DAC_4X10, /* QSFP passive DAC type */
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ NT_PORT_TYPE_QSFP_ACTIVE_DAC_4X10,
+ NT_PORT_TYPE_QSFP_ACTIVE_DAC =
+ NT_PORT_TYPE_QSFP_ACTIVE_DAC_4X10, /* QSFP active DAC type */
+ NT_PORT_TYPE_SFP_28, /* SFP28 type */
+ NT_PORT_TYPE_SFP_28_SR, /* SFP28-SR type */
+ NT_PORT_TYPE_SFP_28_LR, /* SFP28-LR type */
+ NT_PORT_TYPE_SFP_28_CR_CA_L, /* SFP28-CR-CA-L type */
+ NT_PORT_TYPE_SFP_28_CR_CA_S, /* SFP28-CR-CA-S type */
+ NT_PORT_TYPE_SFP_28_CR_CA_N, /* SFP28-CR-CA-N type */
+ NT_PORT_TYPE_QSFP28_CR_CA_L, /* QSFP28-CR-CA-L type */
+ NT_PORT_TYPE_QSFP28_CR_CA_S, /* QSFP28-CR-CA-S type */
+ NT_PORT_TYPE_QSFP28_CR_CA_N, /* QSFP28-CR-CA-N type */
+ NT_PORT_TYPE_SFP_28_SR_DR, /* SFP28-SR-DR type */
+ NT_PORT_TYPE_SFP_28_LR_DR, /* SFP28-LR-DR type */
+ NT_PORT_TYPE_SFP_FX, /* SFP FX */
+ NT_PORT_TYPE_SFP_PLUS_CU, /* SFP+ CU type */
+ /* QSFP28-FR type. Uses PAM4 modulation on one lane only */
+ NT_PORT_TYPE_QSFP28_FR,
+ /* QSFP28-DR type. Uses PAM4 modulation on one lane only */
+ NT_PORT_TYPE_QSFP28_DR,
+ /* QSFP28-LR type. Uses PAM4 modulation on one lane only */
+ NT_PORT_TYPE_QSFP28_LR,
+};
+
+typedef enum nt_port_type_e nt_port_type_t, *nt_port_type_p;
+
+#endif /* NIM_DEFINES_H_ */
diff --git a/drivers/net/ntnic/nim/nt_link_speed.c b/drivers/net/ntnic/nim/nt_link_speed.c
new file mode 100644
index 0000000000..35c75f5e56
--- /dev/null
+++ b/drivers/net/ntnic/nim/nt_link_speed.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "nt_link_speed.h"
+
+const char *nt_translate_link_speed(nt_link_speed_t link_speed)
+{
+ switch (link_speed) {
+ case NT_LINK_SPEED_UNKNOWN:
+ return "NotAvail";
+ case NT_LINK_SPEED_10M:
+ return "10M";
+ case NT_LINK_SPEED_100M:
+ return "100M";
+ case NT_LINK_SPEED_1G:
+ return "1G";
+ case NT_LINK_SPEED_10G:
+ return "10G";
+ case NT_LINK_SPEED_25G:
+ return "25G";
+ case NT_LINK_SPEED_40G:
+ return "40G";
+ case NT_LINK_SPEED_50G:
+ return "50G";
+ case NT_LINK_SPEED_100G:
+ return "100G";
+ default:
+ /* DEBUG assert: remind developer that a switch/case entry is needed here.... */
+ assert(false);
+ return "Unhandled";
+ }
+}
+
+uint64_t nt_get_link_speed(nt_link_speed_t e_link_speed)
+{
+ uint64_t n_link_speed = 0ULL;
+
+ switch (e_link_speed) {
+ case NT_LINK_SPEED_UNKNOWN:
+ n_link_speed = 0UL;
+ break;
+ case NT_LINK_SPEED_10M:
+ n_link_speed = (10ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_100M:
+ n_link_speed = (100ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_1G:
+ n_link_speed = (1ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_10G:
+ n_link_speed = (10ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_25G:
+ n_link_speed = (25ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_40G:
+ n_link_speed = (40ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_50G:
+ n_link_speed = (50ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_100G:
+ n_link_speed = (100ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ default:
+ /* DEBUG assert: remind developer that a switch/case entry is needed here.... */
+ assert(false);
+ n_link_speed = 0UL;
+ break;
+ }
+ return n_link_speed;
+}
+
+const char *nt_translate_link_speed_mask(uint32_t link_speed_mask, char *buffer,
+ uint32_t length)
+{
+ size_t len = 0;
+
+ buffer[0] = 0;
+
+ for (int i = 0; i < 32; i++) {
+ if ((1U << i) & link_speed_mask) {
+ len = strlen(buffer);
+
+ if (len > 0) {
+ if ((length - len - 1) > 2) {
+ strncat(buffer, ", ", length);
+ len = strlen(buffer);
+ }
+ }
+
+ if (len < (length - 1))
+ strncat(buffer, nt_translate_link_speed(1 << i),
+ length);
+ }
+ }
+
+ return buffer;
+}
diff --git a/drivers/net/ntnic/nim/nt_link_speed.h b/drivers/net/ntnic/nim/nt_link_speed.h
new file mode 100644
index 0000000000..969e3fb867
--- /dev/null
+++ b/drivers/net/ntnic/nim/nt_link_speed.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT_LINK_SPEED_H_
+#define NT_LINK_SPEED_H_
+
+#include <stdint.h>
+
+/*
+ * Link speed.
+ * Note this is a bitmask.
+ */
+enum nt_link_speed_e {
+ NT_LINK_SPEED_UNKNOWN = 0,
+ NT_LINK_SPEED_10M = 0x01, /* 10 Mbps */
+ NT_LINK_SPEED_100M = 0x02, /* 100 Mbps */
+ NT_LINK_SPEED_1G = 0x04, /* 1 Gbps (Autoneg only) */
+ NT_LINK_SPEED_10G = 0x08, /* 10 Gbps (Autoneg only) */
+ NT_LINK_SPEED_40G = 0x10, /* 40 Gbps (Autoneg only) */
+ NT_LINK_SPEED_100G = 0x20, /* 100 Gbps (Autoneg only) */
+ NT_LINK_SPEED_50G = 0x40, /* 50 Gbps (Autoneg only) */
+ NT_LINK_SPEED_25G = 0x80, /* 25 Gbps (Autoneg only) */
+ NT_LINK_SPEED_END /* always keep this entry as the last in enum */
+};
+
+typedef enum nt_link_speed_e nt_link_speed_t;
+
+const char *nt_translate_link_speed(nt_link_speed_t link_speed);
+const char *nt_translate_link_speed_mask(uint32_t link_speed_mask, char *buffer,
+ uint32_t length);
+uint64_t nt_get_link_speed(nt_link_speed_t e_link_speed);
+
+#endif /* NT_LINK_SPEED_H_ */
diff --git a/drivers/net/ntnic/nim/qsfp_registers.h b/drivers/net/ntnic/nim/qsfp_registers.h
new file mode 100644
index 0000000000..366dcbf06e
--- /dev/null
+++ b/drivers/net/ntnic/nim/qsfp_registers.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _QSFP_REGISTERS_H
+#define _QSFP_REGISTERS_H
+
+/*
+ * QSFP Registers
+ */
+#define QSFP_INT_STATUS_RX_LOS_ADDR 3
+#define QSFP_TEMP_LIN_ADDR 22
+#define QSFP_VOLT_LIN_ADDR 26
+#define QSFP_RX_PWR_LIN_ADDR 34 /* uint16_t [0..3] */
+#define QSFP_TX_BIAS_LIN_ADDR 42 /* uint16_t [0..3] */
+#define QSFP_TX_PWR_LIN_ADDR 50 /* uint16_t [0..3] */
+
+#define QSFP_CONTROL_STATUS_LIN_ADDR 86
+#define QSFP_SOFT_TX_ALL_DISABLE_BITS 0x0F
+
+#define QSFP_EXTENDED_IDENTIFIER 129
+#define QSFP_POWER_CLASS_BITS_1_4 0xC0
+#define QSFP_POWER_CLASS_BITS_5_7 0x03
+
+#define QSFP_SUP_LEN_INFO_LIN_ADDR 142 /* 5bytes */
+#define QSFP_TRANSMITTER_TYPE_LIN_ADDR 147 /* 1byte */
+#define QSFP_VENDOR_NAME_LIN_ADDR 148 /* 16bytes */
+#define QSFP_VENDOR_PN_LIN_ADDR 168 /* 16bytes */
+#define QSFP_VENDOR_SN_LIN_ADDR 196 /* 16bytes */
+#define QSFP_VENDOR_DATE_LIN_ADDR 212 /* 8bytes */
+#define QSFP_VENDOR_REV_LIN_ADDR 184 /* 2bytes */
+
+#define QSFP_SPEC_COMPLIANCE_CODES_ADDR 131 /* 8 bytes */
+#define QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR 192 /* 1 byte */
+
+#define QSFP_OPTION3_LIN_ADDR 195
+#define QSFP_OPTION3_TX_DISABLE_BIT (1 << 4)
+
+#define QSFP_DMI_OPTION_LIN_ADDR 220
+#define QSFP_DMI_AVG_PWR_BIT (1 << 3)
+
+#define QSFP_TEMP_THRESH_LIN_ADDR (128 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_VOLT_THRESH_LIN_ADDR (144 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_RX_PWR_THRESH_LIN_ADDR (176 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_BIAS_THRESH_LIN_ADDR (184 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_TX_PWR_THRESH_LIN_ADDR (192 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#endif /* _QSFP_REGISTERS_H */
diff --git a/drivers/net/ntnic/nim/qsfp_sensors.c b/drivers/net/ntnic/nim/qsfp_sensors.c
new file mode 100644
index 0000000000..8264f8fb62
--- /dev/null
+++ b/drivers/net/ntnic/nim/qsfp_sensors.c
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdbool.h>
+
+#include "qsfp_sensors.h"
+
+#include "ntlog.h"
+#include "qsfp_registers.h"
+
+static bool qsfp_plus_nim_get_sensor(nim_i2c_ctx_p ctx, uint16_t addr,
+ nim_option_t nim_option, uint8_t count,
+ uint16_t *p_lane_values)
+{
+ (void)nim_option;
+
+ read_data_lin(ctx, addr, (uint16_t)(sizeof(uint16_t) * count),
+ p_lane_values);
+
+ for (int i = 0; i < count; i++) {
+ *p_lane_values = (*p_lane_values); /* Swap to little endian */
+
+#ifdef NIM_DMI_TEST_VALUE
+ if (nim_option == NIM_OPTION_RX_POWER)
+ *p_lane_values = (uint16_t)NIM_DMI_RX_PWR_TEST_VALUE;
+ else
+ *p_lane_values = (uint16_t)NIM_DMI_TEST_VALUE;
+#endif
+
+ p_lane_values++;
+ }
+
+ return true;
+}
+
+/*
+ * Read NIM temperature
+ */
+static bool qsfp_plus_nim_get_temperature(nim_i2c_ctx_p ctx, int16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TEMP_LIN_ADDR, NIM_OPTION_TEMP,
+ 1, (uint16_t *)p_value);
+}
+
+/*
+ * Read NIM supply voltage
+ */
+static bool qsfp_plus_nim_get_supply_voltage(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_VOLT_LIN_ADDR,
+ NIM_OPTION_SUPPLY, 1, p_value);
+}
+
+/*
+ * Read NIM bias current for four lanes
+ */
+static bool qsfp_plus_nim_get_tx_bias_current(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_BIAS_LIN_ADDR,
+ NIM_OPTION_TX_BIAS, 4, p_value);
+}
+
+/*
+ * Read NIM TX optical power for four lanes
+ */
+static bool qsfp_plus_nim_get_tx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_PWR_LIN_ADDR,
+ NIM_OPTION_TX_POWER, 4, p_value);
+}
+
+/*
+ * Read NIM RX optical power for four lanes
+ */
+static bool qsfp_plus_nim_get_rx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_PWR_LIN_ADDR,
+ NIM_OPTION_RX_POWER, 4, p_value);
+}
+
+void nim_read_qsfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ int16_t res;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (qsfp_plus_nim_get_temperature(sg->ctx, &res))
+ update_sensor_value(sg->sensor, (int)(res * 10 / 256));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_qsfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t res;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (qsfp_plus_nim_get_supply_voltage(sg->ctx, &res))
+ update_sensor_value(sg->sensor, (int)((res) / 10));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_qsfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp[4] = { 0 };
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ bool res = qsfp_plus_nim_get_tx_bias_current(sg->ctx, temp);
+
+ if (res) {
+ for (uint8_t i = 0; i < sg->ctx->lane_count; i++)
+ update_sensor_value(sg->sensor, (int)temp[i] * 2);
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
+
+void nim_read_qsfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp[4] = { 0 };
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ bool res = qsfp_plus_nim_get_tx_power(sg->ctx, temp);
+
+ if (res) {
+ for (uint8_t i = 0; i < sg->ctx->lane_count; i++)
+ update_sensor_value(sg->sensor, (int)temp[i]);
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
+
+void nim_read_qsfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp[4] = { 0 };
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ bool res = qsfp_plus_nim_get_rx_power(sg->ctx, temp);
+
+ if (res) {
+ for (uint8_t i = 0; i < sg->ctx->lane_count; i++)
+ update_sensor_value(sg->sensor, (int)temp[i]);
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
diff --git a/drivers/net/ntnic/nim/qsfp_sensors.h b/drivers/net/ntnic/nim/qsfp_sensors.h
new file mode 100644
index 0000000000..de64b978cb
--- /dev/null
+++ b/drivers/net/ntnic/nim/qsfp_sensors.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _QSFP_H
+#define _QSFP_H
+
+#include "sensors.h"
+#include "i2c_nim.h"
+
+/* Read functions */
+void nim_read_qsfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+
+#endif /* _QSFP_H */
diff --git a/drivers/net/ntnic/nim/sfp_p_registers.h b/drivers/net/ntnic/nim/sfp_p_registers.h
new file mode 100644
index 0000000000..a0fbe2afd7
--- /dev/null
+++ b/drivers/net/ntnic/nim/sfp_p_registers.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SFP_P_REG_H
+#define _SFP_P_REG_H
+
+/*
+ * SFP/SFP+ Registers
+ */
+#define SFP_GB_ETH_COMP_CODES_LIN_ADDR 6
+#define SFP_GB_ETH_COMP_1000BASET_BIT (1 << 3)
+#define SFP_GB_ETH_COMP_1000BASECX_BIT (1 << 2)
+#define SFP_GB_ETH_COMP_1000BASELX_BIT (1 << 1)
+#define SFP_GB_ETH_COMP_1000BASESX_BIT (1 << 0)
+
+#define SFP_FIBER_CHAN_TRANS_TECH_LIN_ADDR 8
+#define SFP_FIBER_CHAN_TRANS_TECH_ACTIVE_CU_BIT (1 << 3)
+#define SFP_FIBER_CHAN_TRANS_TECH_PASSIVE_CU_BIT (1 << 2)
+
+#define SFP_FIBER_CHAN_TRANS_MEDIA_LIN_ADDR 9
+#define SFP_FIBER_CHAN_TRANS_MEDIA_MM62_BIT (1 << 3)
+#define SFP_FIBER_CHAN_TRANS_MEDIA_MM50_BIT (1 << 2)
+#define SFP_FIBER_CHAN_TRANS_MEDIA_SM_BIT (1 << 0)
+
+#define SFP_CU_LINK_LEN_LIN_ADDR 18 /* 1byte */
+#define SFP_SUP_LEN_INFO_LIN_ADDR 14 /* 5bytes */
+#define SFP_CU_LINK_LEN_LIN_ADDR 18 /* 1byte */
+#define SFP_VENDOR_NAME_LIN_ADDR 20 /* 16bytes */
+#define SFP_VENDOR_PN_LIN_ADDR 40 /* 16bytes */
+#define SFP_VENDOR_REV_LIN_ADDR 56 /* 4bytes */
+#define SFP_VENDOR_SN_LIN_ADDR 68 /* 16bytes */
+#define SFP_VENDOR_DATE_LIN_ADDR 84 /* 8bytes */
+
+/* The following field is only relevant to SFP+ and is marked as reserved for SFP */
+#define SFP_OPTION0_LIN_ADDR 64
+#define SFP_POWER_LEVEL2_REQ_BIT (1 << 1)
+
+#define SFP_DMI_OPTION_LIN_ADDR (92)
+#define SFP_DMI_IMPL_BIT (1 << 6)
+#define SFP_DMI_EXT_CAL_BIT (1 << 4)
+#define SFP_DMI_AVG_PWR_BIT (1 << 3)
+#define SFP_DMI_ADDR_CHG_BIT (1 << 2)
+
+#define SFP_ENHANCED_OPTIONS_LIN_ADDR (93)
+#define SFP_SOFT_TX_FAULT_IMPL_BIT (1 << 5)
+#define SFP_SOFT_TX_DISABLE_IMPL_BIT (1 << 6)
+
+#define SFP_SFF8472_COMPLIANCE_LIN_ADDR 94
+
+#define SFP_TEMP_THRESH_LIN_ADDR (0 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_VOLT_THRESH_LIN_ADDR (8 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_TX_BIAS_THRESH_LIN_ADDR (16 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_TX_PWR_THRESH_LIN_ADDR (24 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_RX_PWR_THRESH_LIN_ADDR (32 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+/* Calibration data addresses */
+#define SFP_RX_PWR_COEFF_LIN_ADDR (56 + 256) /* 5 x 32bit float values */
+
+#define SFP_TX_BIAS_SLOPE_LIN_ADDR (76 + 256)
+#define SFP_TX_BIAS_OFFSET_LIN_ADDR (78 + 256)
+
+#define SFP_TX_PWR_SLOPE_LIN_ADDR (80 + 256)
+#define SFP_TX_PWR_OFFSET_LIN_ADDR (82 + 256)
+
+#define SFP_TEMP_SLOPE_LIN_ADDR (84 + 256)
+#define SFP_TEMP_OFFSET_LIN_ADDR (86 + 256)
+
+#define SFP_VOLT_SLOPE_LIN_ADDR (88 + 256)
+#define SFP_VOLT_OFFSET_LIN_ADDR (90 + 256)
+
+/* Live data */
+#define SFP_TEMP_LIN_ADDR (96 + 256)
+#define SFP_VOLT_LIN_ADDR (98 + 256)
+#define SFP_TX_BIAS_LIN_ADDR (100 + 256)
+#define SFP_TX_PWR_LIN_ADDR (102 + 256)
+#define SFP_RX_PWR_LIN_ADDR (104 + 256)
+
+#define SFP_SOFT_RATE0_BIT (1 << 3)
+#define SFP_TX_FAULT_SET_BIT (1 << 2)
+
+#define SFP_EXT_CTRL_STAT0_LIN_ADDR (118 + 256) /* 0xA2 area */
+#define SFP_SOFT_RATE1_BIT (1 << 3)
+#define SFP_POWER_LEVEL2_GET_BIT (1 << 1) /* For reading the actual level */
+#define SFP_POWER_LEVEL2_SET_BIT (1 << 0) /* For setting the wanted level */
+
+/* PHY addresses */
+#define SFP_PHY_LIN_ADDR (12 * 128)
+#define SFP_PHY_LIN_RNG 32 /* 16bit words */
+
+#endif /* _SFP_P_REG_H */
diff --git a/drivers/net/ntnic/nim/sfp_sensors.c b/drivers/net/ntnic/nim/sfp_sensors.c
new file mode 100644
index 0000000000..766d6feaf3
--- /dev/null
+++ b/drivers/net/ntnic/nim/sfp_sensors.c
@@ -0,0 +1,288 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <arpa/inet.h>
+#include <stdbool.h>
+
+#include "ntlog.h"
+#include "sfp_sensors.h"
+
+#include "sfp_p_registers.h"
+
+/*
+ * Return calibrated data from an SFP module.
+ * It is first investigated if external calibration is to be used and if it is
+ * calibration data is retrieved. The function can only be used when calibration
+ * consists of a slope and offset factor. After function return p_data will point
+ * to 16bit data that can be either signed or unsigned.
+ */
+static bool sfp_nim_get_dmi_data(uint16_t data_addr, uint16_t slope_addr,
+ uint16_t offset_addr, void *p_value,
+ bool signed_data, nim_i2c_ctx_p ctx)
+{
+ int32_t value;
+ uint16_t slope = 1;
+ int16_t offset = 0;
+
+ if (!ctx->dmi_supp)
+ return false;
+
+ /* Read data in big endian format */
+ read_data_lin(ctx, data_addr, 2, p_value);
+ *(uint16_t *)p_value =
+ htons(*(uint16_t *)p_value); /* Swap to little endian */
+
+ /*
+ * Inject test value which can be both signed and unsigned but handle
+ * here as unsigned
+ */
+#ifdef NIM_DMI_TEST_VALUE
+ *(uint16_t *)p_value = (uint16_t)NIM_DMI_TEST_VALUE;
+#endif
+
+#if defined(NIM_DMI_TEST_SLOPE) || defined(NIM_DMI_TEST_OFFSET)
+ ctx->specific_u.sfp.ext_cal = true;
+#endif
+
+ if (ctx->specific_u.sfp.ext_cal) {
+ /* External calibration is needed */
+ read_data_lin(ctx, slope_addr, sizeof(slope), &slope);
+ read_data_lin(ctx, offset_addr, sizeof(offset), &offset);
+
+ /* Swap calibration to little endian */
+ slope = htons(slope);
+ offset = htons(offset);
+
+#ifdef NIM_DMI_TEST_SLOPE
+ slope = NIM_DMI_TEST_SLOPE;
+#endif
+
+#ifdef NIM_DMI_TEST_OFFSET
+ offset = NIM_DMI_TEST_OFFSET; /* 0x0140 equals 1.25 */
+#endif
+
+ if (signed_data) {
+ value = *(int16_t *)p_value * slope / 256 + offset;
+
+ if (value > INT16_MAX)
+ value = INT16_MAX;
+ else if (value < INT16_MIN)
+ value = INT16_MIN;
+
+ *(int16_t *)p_value = (int16_t)value;
+ } else {
+ value = *(uint16_t *)p_value * slope / 256 + offset;
+
+ if (value > UINT16_MAX)
+ value = UINT16_MAX;
+ else if (value < 0)
+ value = 0;
+
+ *(uint16_t *)p_value = (uint16_t)value;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Read NIM temperature
+ */
+static bool sfp_nim_get_temperature(nim_i2c_ctx_p ctx, int16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_TEMP_LIN_ADDR, SFP_TEMP_SLOPE_LIN_ADDR,
+ SFP_TEMP_OFFSET_LIN_ADDR, p_value, true, ctx);
+}
+
+/*
+ * Read NIM supply voltage
+ */
+static bool sfp_nim_get_supply_voltage(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_VOLT_LIN_ADDR, SFP_VOLT_SLOPE_LIN_ADDR,
+ SFP_VOLT_OFFSET_LIN_ADDR, p_value, false, ctx);
+}
+
+/*
+ * Read NIM bias current
+ */
+static bool sfp_nim_get_tx_bias_current(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_TX_BIAS_LIN_ADDR,
+ SFP_TX_BIAS_SLOPE_LIN_ADDR,
+ SFP_TX_BIAS_OFFSET_LIN_ADDR, p_value, false,
+ ctx);
+}
+
+/*
+ * Read NIM TX optical power
+ */
+static bool sfp_nim_get_tx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_TX_PWR_LIN_ADDR,
+ SFP_TX_PWR_SLOPE_LIN_ADDR,
+ SFP_TX_PWR_OFFSET_LIN_ADDR, p_value, false,
+ ctx);
+}
+
+/*
+ * Return the SFP received power in units of 0.1uW from DMI data.
+ * If external calibration is necessary, the calibration data is retrieved and
+ * the calibration is carried out.
+ */
+static bool sfp_nim_get_calibrated_rx_power(nim_i2c_ctx_p ctx, uint16_t addr,
+ uint16_t *p_value)
+{
+ float rx_pwr_cal[5];
+ float power_raised;
+ float rx_power;
+
+ /* Read data in big endian format */
+ read_data_lin(ctx, addr, sizeof(*p_value), p_value);
+ *(uint16_t *)p_value =
+ htons(*(uint16_t *)p_value); /* Swap to little endian */
+
+#ifdef NIM_DMI_RX_PWR_TEST_VALUE
+ *p_value = NIM_DMI_RX_PWR_TEST_VALUE;
+#endif
+
+#ifdef NIM_DMI_RX_PWR_CAL_DATA
+ ctx->specific_u.sfp.ext_cal = true;
+#endif
+
+ if (ctx->specific_u.sfp.ext_cal) {
+ /* Read calibration data in big endian format */
+ read_data_lin(ctx, SFP_RX_PWR_COEFF_LIN_ADDR, sizeof(rx_pwr_cal),
+ rx_pwr_cal);
+
+ for (int i = 0; i < 5; i++) {
+ uint32_t *p_val = (uint32_t *)&rx_pwr_cal[i];
+ *p_val = ntohl(*p_val); /* 32 bit swap */
+ }
+
+#ifdef NIM_DMI_RX_PWR_CAL_DATA
+ /* Testdata for verification */
+ NIM_DMI_RX_PWR_CAL_DATA
+#endif
+
+ /*
+ * If SFP module specifies external calibration - use calibration data
+ * according to the polynomial correction formula
+ * RxPwrCal = Coeff0 + Coeff1 * RxPwr + Coeff2 * RxPwr^2 +
+ * Coeff3 * RxPwr^3 + Coeff4 * RxPwr^4
+ */
+ power_raised = 1.0;
+ rx_power = rx_pwr_cal[4]; /* Coeff0 */
+
+ for (int i = 3; i >= 0; i--) {
+ power_raised *= (float)*p_value;
+ rx_power += rx_pwr_cal[i] * power_raised;
+ }
+
+ /* Check out for out of range */
+ if (rx_power > 65535)
+ return false;
+
+ if (rx_power < 0)
+ *p_value = 0;
+ else
+ *p_value = (uint16_t)rx_power;
+ }
+
+ return true;
+}
+
+/*
+ * Read RX optical power if it exists
+ */
+static bool sfp_nim_get_rx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_calibrated_rx_power(ctx, SFP_RX_PWR_LIN_ADDR, p_value);
+}
+
+void nim_read_sfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ int16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_temperature(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)(temp * 10 / 256));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_sfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_supply_voltage(sg->ctx, &temp)) {
+ update_sensor_value(sg->sensor,
+ (int)(temp / 10)); /* Unit: 100uV -> 1mV */
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
+
+void nim_read_sfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_tx_bias_current(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)(temp * 2));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_sfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_tx_power(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)temp);
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_sfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_rx_power(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)temp);
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
diff --git a/drivers/net/ntnic/nim/sfp_sensors.h b/drivers/net/ntnic/nim/sfp_sensors.h
new file mode 100644
index 0000000000..ab56027dc8
--- /dev/null
+++ b/drivers/net/ntnic/nim/sfp_sensors.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SFP_H
+#define _SFP_H
+
+#include "sensors.h"
+#include "i2c_nim.h"
+
+/* Read functions */
+void nim_read_sfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+
+#endif /* _SFP_H */
diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
index efdcc222a8..bd7cd2a27c 100644
--- a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
@@ -5,5 +5,12 @@
#include "nthw_clock_profiles.h"
/* Clock profile for NT200A02 2x40G, 2x100G */
-const int n_data_si5340_nt200a02_u23_v5;
-const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;
+#define si5340_revd_register_t type_si5340_nt200a02_u23_v5
+#define si5340_revd_registers data_si5340_nt200a02_u23_v5
+#include "nthw_nt200a02_u23_si5340_v5.h"
+const int n_data_si5340_nt200a02_u23_v5 = SI5340_REVD_REG_CONFIG_NUM_REGS;
+const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5 =
+ (const clk_profile_data_fmt2_t *)&data_si5340_nt200a02_u23_v5[0];
+#undef si5340_revd_registers
+#undef si5340_revd_register_t
+#undef SI5340_REVD_REG_CONFIG_HEADER /*Disable the include once protection */
diff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h
index 798a95d5cf..025b6b61cc 100644
--- a/drivers/net/ntnic/nthw/core/nthw_core.h
+++ b/drivers/net/ntnic/nthw/core/nthw_core.h
@@ -16,9 +16,11 @@
#include "nthw_pci_ta.h"
#include "nthw_iic.h"
+#include "nthw_gmf.h"
#include "nthw_gpio_phy.h"
#include "nthw_mac_pcs.h"
#include "nthw_mac_pcs_xxv.h"
+#include "nthw_rmc.h"
#include "nthw_sdc.h"
#include "nthw_spim.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.c b/drivers/net/ntnic/nthw/core/nthw_gmf.c
new file mode 100644
index 0000000000..fe63c461e5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gmf.c
@@ -0,0 +1,290 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <limits.h>
+#include <math.h>
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_gmf.h"
+
+nthw_gmf_t *nthw_gmf_new(void)
+{
+ nthw_gmf_t *p = malloc(sizeof(nthw_gmf_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_gmf_t));
+ return p;
+}
+
+void nthw_gmf_delete(nthw_gmf_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_gmf_t));
+ free(p);
+ }
+}
+
+int nthw_gmf_init(nthw_gmf_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_GMF, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: GMF %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_gmf = mod;
+
+ p->mp_ctrl = module_get_register(p->mp_mod_gmf, GMF_CTRL);
+ p->mp_ctrl_enable = register_get_field(p->mp_ctrl, GMF_CTRL_ENABLE);
+ p->mp_ctrl_ifg_enable = register_get_field(p->mp_ctrl, GMF_CTRL_IFG_ENABLE);
+ p->mp_ctrl_ifg_auto_adjust_enable =
+ register_get_field(p->mp_ctrl, GMF_CTRL_IFG_AUTO_ADJUST_ENABLE);
+
+ p->mp_speed = module_get_register(p->mp_mod_gmf, GMF_SPEED);
+ p->mp_speed_ifg_speed = register_get_field(p->mp_speed, GMF_SPEED_IFG_SPEED);
+
+ p->mp_ifg_clock_delta =
+ module_get_register(p->mp_mod_gmf, GMF_IFG_SET_CLOCK_DELTA);
+ p->mp_ifg_clock_delta_delta =
+ register_get_field(p->mp_ifg_clock_delta, GMF_IFG_SET_CLOCK_DELTA_DELTA);
+
+ p->mp_ifg_max_adjust_slack =
+ module_get_register(p->mp_mod_gmf, GMF_IFG_MAX_ADJUST_SLACK);
+ p->mp_ifg_max_adjust_slack_slack =
+ register_get_field(p->mp_ifg_max_adjust_slack, GMF_IFG_MAX_ADJUST_SLACK_SLACK);
+
+ p->mp_debug_lane_marker =
+ module_get_register(p->mp_mod_gmf, GMF_DEBUG_LANE_MARKER);
+ p->mp_debug_lane_marker_compensation =
+ register_get_field(p->mp_debug_lane_marker, GMF_DEBUG_LANE_MARKER_COMPENSATION);
+
+ p->mp_stat_sticky = module_get_register(p->mp_mod_gmf, GMF_STAT_STICKY);
+ p->mp_stat_sticky_data_underflowed =
+ register_get_field(p->mp_stat_sticky, GMF_STAT_STICKY_DATA_UNDERFLOWED);
+ p->mp_stat_sticky_ifg_adjusted =
+ register_get_field(p->mp_stat_sticky, GMF_STAT_STICKY_IFG_ADJUSTED);
+
+ p->mn_param_gmf_ifg_speed_mul =
+ fpga_get_product_param(p_fpga, NT_GMF_IFG_SPEED_MUL, 1);
+ p->mn_param_gmf_ifg_speed_div =
+ fpga_get_product_param(p_fpga, NT_GMF_IFG_SPEED_DIV, 1);
+
+ p->m_administrative_block = false;
+
+ p->mp_stat_next_pkt = module_query_register(p->mp_mod_gmf, GMF_STAT_NEXT_PKT);
+ if (p->mp_stat_next_pkt) {
+ p->mp_stat_next_pkt_ns =
+ register_query_field(p->mp_stat_next_pkt,
+ GMF_STAT_NEXT_PKT_NS);
+ } else {
+ p->mp_stat_next_pkt_ns = NULL;
+ }
+ p->mp_stat_max_delayed_pkt =
+ module_query_register(p->mp_mod_gmf, GMF_STAT_MAX_DELAYED_PKT);
+ if (p->mp_stat_max_delayed_pkt) {
+ p->mp_stat_max_delayed_pkt_ns =
+ register_query_field(p->mp_stat_max_delayed_pkt,
+ GMF_STAT_MAX_DELAYED_PKT_NS);
+ } else {
+ p->mp_stat_max_delayed_pkt_ns = NULL;
+ }
+ p->mp_ctrl_ifg_tx_now_always =
+ register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_NOW_ALWAYS);
+ p->mp_ctrl_ifg_tx_on_ts_always =
+ register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_ON_TS_ALWAYS);
+
+ p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock =
+ register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK);
+
+ p->mp_ifg_clock_delta_adjust =
+ module_query_register(p->mp_mod_gmf, GMF_IFG_SET_CLOCK_DELTA_ADJUST);
+ if (p->mp_ifg_clock_delta_adjust) {
+ p->mp_ifg_clock_delta_adjust_delta =
+ register_query_field(p->mp_ifg_clock_delta_adjust,
+ GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA);
+ } else {
+ p->mp_ifg_clock_delta_adjust_delta = NULL;
+ }
+ return 0;
+}
+
+void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable)
+{
+ if (!p->m_administrative_block)
+ field_set_val_flush32(p->mp_ctrl_enable, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_ifg_enable(nthw_gmf_t *p, bool enable)
+{
+ field_set_val_flush32(p->mp_ctrl_ifg_enable, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_tx_now_always_enable(nthw_gmf_t *p, bool enable)
+{
+ if (p->mp_ctrl_ifg_tx_now_always)
+ field_set_val_flush32(p->mp_ctrl_ifg_tx_now_always, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_tx_on_ts_always_enable(nthw_gmf_t *p, bool enable)
+{
+ if (p->mp_ctrl_ifg_tx_on_ts_always)
+ field_set_val_flush32(p->mp_ctrl_ifg_tx_on_ts_always, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_tx_on_ts_adjust_on_set_clock(nthw_gmf_t *p, bool enable)
+{
+ if (p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock) {
+ field_set_val_flush32(p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock,
+ enable ? 1 : 0);
+ }
+}
+
+void nthw_gmf_set_ifg_auto_adjust_enable(nthw_gmf_t *p, bool enable)
+{
+ field_set_val_flush32(p->mp_ctrl_ifg_auto_adjust_enable, enable);
+}
+
+int nthw_gmf_set_ifg_speed_raw(nthw_gmf_t *p, uint64_t n_speed_val)
+{
+ if (n_speed_val <=
+ (1ULL << (field_get_bit_width(p->mp_speed_ifg_speed) - 1))) {
+ field_set_val(p->mp_speed_ifg_speed, (uint32_t *)&n_speed_val,
+ (field_get_bit_width(p->mp_speed_ifg_speed) <= 32 ? 1 :
+ 2));
+ field_flush_register(p->mp_speed_ifg_speed);
+ return 0;
+ }
+ return -1;
+}
+
+int nthw_gmf_get_ifg_speed_bit_width(nthw_gmf_t *p)
+{
+ const int n_bit_width = field_get_bit_width(p->mp_speed_ifg_speed);
+
+ assert(n_bit_width >=
+ 22); /* Sanity check: GMF ver 1.2 is bw 22 - GMF ver 1.3 is bw 64 */
+ return n_bit_width;
+}
+
+int nthw_gmf_set_ifg_speed_bits(nthw_gmf_t *p, const uint64_t n_rate_limit_bits,
+ const uint64_t n_link_speed)
+{
+ const int n_bit_width = (nthw_gmf_get_ifg_speed_bit_width(p) / 2);
+ const double f_adj_rate =
+ ((double)((((double)n_rate_limit_bits) / (double)n_link_speed) *
+ p->mn_param_gmf_ifg_speed_mul) /
+ p->mn_param_gmf_ifg_speed_div);
+ const double f_speed = ((1UL / f_adj_rate) - 1) * exp2(n_bit_width);
+ uint64_t n_speed_val = (uint64_t)round(f_speed);
+
+ return nthw_gmf_set_ifg_speed_raw(p, n_speed_val);
+}
+
+int nthw_gmf_set_ifg_speed_percent(nthw_gmf_t *p, const double f_rate_limit_percent)
+{
+ uint64_t n_speed_val;
+
+ if (f_rate_limit_percent == 0.0 || f_rate_limit_percent == 100.0) {
+ n_speed_val = 0;
+ } else if (f_rate_limit_percent <= 99) {
+ const int n_bit_width = (nthw_gmf_get_ifg_speed_bit_width(p) / 2);
+ const double f_adj_rate =
+ ((double)(f_rate_limit_percent *
+ (double)p->mn_param_gmf_ifg_speed_mul) /
+ p->mn_param_gmf_ifg_speed_div / 100);
+ const double f_speed = ((1UL / f_adj_rate) - 1) * exp2(n_bit_width);
+
+ n_speed_val = (uint64_t)f_speed;
+ } else {
+ return -1;
+ }
+
+ return nthw_gmf_set_ifg_speed_raw(p, n_speed_val);
+}
+
+void nthw_gmf_set_delta(nthw_gmf_t *p, uint64_t delta)
+{
+ field_set_val(p->mp_ifg_clock_delta_delta, (uint32_t *)&delta, 2);
+ field_flush_register(p->mp_ifg_clock_delta_delta);
+}
+
+void nthw_gmf_set_delta_adjust(nthw_gmf_t *p, uint64_t delta_adjust)
+{
+ if (p->mp_ifg_clock_delta_adjust) {
+ field_set_val(p->mp_ifg_clock_delta_adjust_delta,
+ (uint32_t *)&delta_adjust, 2);
+ field_flush_register(p->mp_ifg_clock_delta_adjust_delta);
+ }
+}
+
+void nthw_gmf_set_slack(nthw_gmf_t *p, uint64_t slack)
+{
+ field_set_val(p->mp_ifg_max_adjust_slack_slack, (uint32_t *)&slack, 2);
+ field_flush_register(p->mp_ifg_max_adjust_slack_slack);
+}
+
+void nthw_gmf_set_compensation(nthw_gmf_t *p, uint32_t compensation)
+{
+ field_set_val_flush32(p->mp_debug_lane_marker_compensation, compensation);
+}
+
+uint32_t nthw_gmf_get_status_sticky(nthw_gmf_t *p)
+{
+ uint32_t status = 0;
+
+ register_update(p->mp_stat_sticky);
+
+ if (field_get_val32(p->mp_stat_sticky_data_underflowed))
+ status |= GMF_STATUS_MASK_DATA_UNDERFLOWED;
+ if (field_get_val32(p->mp_stat_sticky_ifg_adjusted))
+ status |= GMF_STATUS_MASK_IFG_ADJUSTED;
+
+ return status;
+}
+
+void nthw_gmf_set_status_sticky(nthw_gmf_t *p, uint32_t status)
+{
+ if (status & GMF_STATUS_MASK_DATA_UNDERFLOWED)
+ field_set_flush(p->mp_stat_sticky_data_underflowed);
+ if (status & GMF_STATUS_MASK_IFG_ADJUSTED)
+ field_set_flush(p->mp_stat_sticky_ifg_adjusted);
+}
+
+uint64_t nthw_gmf_get_stat_next_pkt_ns(nthw_gmf_t *p)
+{
+ uint64_t value = ULONG_MAX;
+
+ if (p->mp_stat_next_pkt) {
+ register_update(p->mp_stat_next_pkt);
+ field_get_val(p->mp_stat_next_pkt_ns, (uint32_t *)&value, 2);
+ }
+ return value;
+}
+
+uint64_t nthw_gmf_get_stat_max_pk_delayedt_ns(nthw_gmf_t *p)
+{
+ uint64_t value = ULONG_MAX;
+
+ if (p->mp_stat_max_delayed_pkt) {
+ register_update(p->mp_stat_max_delayed_pkt);
+ field_get_val(p->mp_stat_max_delayed_pkt_ns, (uint32_t *)&value, 2);
+ }
+ return value;
+}
+
+void nthw_gmf_administrative_block(nthw_gmf_t *p)
+{
+ nthw_gmf_set_enable(p, false);
+ p->m_administrative_block = true;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.h b/drivers/net/ntnic/nthw/core/nthw_gmf.h
new file mode 100644
index 0000000000..aec1342be7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gmf.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_GMF_H__
+#define __NTHW_GMF_H__
+
+enum gmf_status_mask {
+ GMF_STATUS_MASK_DATA_UNDERFLOWED = 1,
+ GMF_STATUS_MASK_IFG_ADJUSTED
+};
+
+struct nthw_gmf {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_gmf;
+ int mn_instance;
+ /* */
+
+ nt_register_t *mp_ctrl;
+ nt_field_t *mp_ctrl_enable;
+ nt_field_t *mp_ctrl_ifg_enable;
+ nt_field_t *mp_ctrl_ifg_tx_now_always;
+ nt_field_t *mp_ctrl_ifg_tx_on_ts_always;
+ nt_field_t *mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock;
+ nt_field_t *mp_ctrl_ifg_auto_adjust_enable;
+
+ nt_register_t *mp_speed;
+ nt_field_t *mp_speed_ifg_speed;
+
+ nt_register_t *mp_ifg_clock_delta;
+ nt_field_t *mp_ifg_clock_delta_delta;
+
+ nt_register_t *mp_ifg_clock_delta_adjust;
+ nt_field_t *mp_ifg_clock_delta_adjust_delta;
+
+ nt_register_t *mp_ifg_max_adjust_slack;
+ nt_field_t *mp_ifg_max_adjust_slack_slack;
+
+ nt_register_t *mp_debug_lane_marker;
+ nt_field_t *mp_debug_lane_marker_compensation;
+
+ nt_register_t *mp_stat_sticky;
+ nt_field_t *mp_stat_sticky_data_underflowed;
+ nt_field_t *mp_stat_sticky_ifg_adjusted;
+
+ nt_register_t *mp_stat_next_pkt;
+ nt_field_t *mp_stat_next_pkt_ns;
+
+ nt_register_t *mp_stat_max_delayed_pkt;
+ nt_field_t *mp_stat_max_delayed_pkt_ns;
+
+ int mn_param_gmf_ifg_speed_mul;
+ int mn_param_gmf_ifg_speed_div;
+
+ bool m_administrative_block; /* Used to enforce license expiry */
+};
+
+typedef struct nthw_gmf nthw_gmf_t;
+typedef struct nthw_gmf nthw_gmf;
+
+nthw_gmf_t *nthw_gmf_new(void);
+void nthw_gmf_delete(nthw_gmf_t *p);
+int nthw_gmf_init(nthw_gmf_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_ifg_enable(nthw_gmf_t *p, bool enable);
+
+void nthw_gmf_set_tx_now_always_enable(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_tx_on_ts_always_enable(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_tx_on_ts_adjust_on_set_clock(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_ifg_auto_adjust_enable(nthw_gmf_t *p, bool enable);
+
+int nthw_gmf_get_ifg_speed_bit_width(nthw_gmf_t *p);
+
+int nthw_gmf_set_ifg_speed_raw(nthw_gmf_t *p, uint64_t n_speed_val);
+int nthw_gmf_set_ifg_speed_bits(nthw_gmf_t *p, const uint64_t n_rate_limit_bits,
+ const uint64_t n_link_speed);
+int nthw_gmf_set_ifg_speed_percent(nthw_gmf_t *p, const double f_rate_limit_percent);
+
+void nthw_gmf_set_delta(nthw_gmf_t *p, uint64_t delta);
+void nthw_gmf_set_delta_adjust(nthw_gmf_t *p, uint64_t delta_adjust);
+void nthw_gmf_set_slack(nthw_gmf_t *p, uint64_t slack);
+void nthw_gmf_set_compensation(nthw_gmf_t *p, uint32_t compensation);
+
+uint32_t nthw_gmf_get_status_sticky(nthw_gmf_t *p);
+void nthw_gmf_set_status_sticky(nthw_gmf_t *p, uint32_t status);
+
+uint64_t nthw_gmf_get_stat_next_pkt_ns(nthw_gmf_t *p);
+uint64_t nthw_gmf_get_stat_max_pk_delayedt_ns(nthw_gmf_t *p);
+
+void nthw_gmf_administrative_block(nthw_gmf_t *p); /* Used to enforce license expiry blocking */
+
+#endif /* __NTHW_GMF_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h b/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h
new file mode 100644
index 0000000000..f063a1048a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h
@@ -0,0 +1,344 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef SI5340_REVD_REG_CONFIG_HEADER
+#define SI5340_REVD_REG_CONFIG_HEADER
+
+#define SI5340_REVD_REG_CONFIG_NUM_REGS 326
+
+typedef struct {
+ unsigned int address; /* 16-bit register address */
+ unsigned char value; /* 8-bit register data */
+} si5340_revd_register_t;
+
+si5340_revd_register_t const si5340_revd_registers[SI5340_REVD_REG_CONFIG_NUM_REGS] = {
+ { 0x0B24, 0xC0 },
+ { 0x0B25, 0x00 },
+ { 0x0502, 0x01 },
+ { 0x0505, 0x03 },
+ { 0x0957, 0x17 },
+ { 0x0B4E, 0x1A },
+ { 0x0006, 0x00 },
+ { 0x0007, 0x00 },
+ { 0x0008, 0x00 },
+ { 0x000B, 0x74 },
+ { 0x0017, 0xF0 },
+ { 0x0018, 0xFF },
+ { 0x0021, 0x0F },
+ { 0x0022, 0x00 },
+ { 0x002B, 0x0A },
+ { 0x002C, 0x20 },
+ { 0x002D, 0x00 },
+ { 0x002E, 0x00 },
+ { 0x002F, 0x00 },
+ { 0x0030, 0x00 },
+ { 0x0031, 0x00 },
+ { 0x0032, 0x00 },
+ { 0x0033, 0x00 },
+ { 0x0034, 0x00 },
+ { 0x0035, 0x00 },
+ { 0x0036, 0x00 },
+ { 0x0037, 0x00 },
+ { 0x0038, 0x00 },
+ { 0x0039, 0x00 },
+ { 0x003A, 0x00 },
+ { 0x003B, 0x00 },
+ { 0x003C, 0x00 },
+ { 0x003D, 0x00 },
+ { 0x0041, 0x00 },
+ { 0x0042, 0x00 },
+ { 0x0043, 0x00 },
+ { 0x0044, 0x00 },
+ { 0x009E, 0x00 },
+ { 0x0102, 0x01 },
+ { 0x0112, 0x02 },
+ { 0x0113, 0x09 },
+ { 0x0114, 0x3E },
+ { 0x0115, 0x19 },
+ { 0x0117, 0x06 },
+ { 0x0118, 0x09 },
+ { 0x0119, 0x3E },
+ { 0x011A, 0x18 },
+ { 0x0126, 0x06 },
+ { 0x0127, 0x09 },
+ { 0x0128, 0x3E },
+ { 0x0129, 0x18 },
+ { 0x012B, 0x06 },
+ { 0x012C, 0x09 },
+ { 0x012D, 0x3E },
+ { 0x012E, 0x1A },
+ { 0x013F, 0x00 },
+ { 0x0140, 0x00 },
+ { 0x0141, 0x40 },
+ { 0x0206, 0x00 },
+ { 0x0208, 0x00 },
+ { 0x0209, 0x00 },
+ { 0x020A, 0x00 },
+ { 0x020B, 0x00 },
+ { 0x020C, 0x00 },
+ { 0x020D, 0x00 },
+ { 0x020E, 0x00 },
+ { 0x020F, 0x00 },
+ { 0x0210, 0x00 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x00 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x00 },
+ { 0x0215, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x0218, 0x00 },
+ { 0x0219, 0x00 },
+ { 0x021A, 0x00 },
+ { 0x021B, 0x00 },
+ { 0x021C, 0x00 },
+ { 0x021D, 0x00 },
+ { 0x021E, 0x00 },
+ { 0x021F, 0x00 },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x00 },
+ { 0x0222, 0x00 },
+ { 0x0223, 0x00 },
+ { 0x0224, 0x00 },
+ { 0x0225, 0x00 },
+ { 0x0226, 0x00 },
+ { 0x0227, 0x00 },
+ { 0x0228, 0x00 },
+ { 0x0229, 0x00 },
+ { 0x022A, 0x00 },
+ { 0x022B, 0x00 },
+ { 0x022C, 0x00 },
+ { 0x022D, 0x00 },
+ { 0x022E, 0x00 },
+ { 0x022F, 0x00 },
+ { 0x0235, 0x00 },
+ { 0x0236, 0x00 },
+ { 0x0237, 0x00 },
+ { 0x0238, 0xA6 },
+ { 0x0239, 0x8B },
+ { 0x023A, 0x00 },
+ { 0x023B, 0x00 },
+ { 0x023C, 0x00 },
+ { 0x023D, 0x00 },
+ { 0x023E, 0x80 },
+ { 0x0250, 0x03 },
+ { 0x0251, 0x00 },
+ { 0x0252, 0x00 },
+ { 0x0253, 0x00 },
+ { 0x0254, 0x00 },
+ { 0x0255, 0x00 },
+ { 0x025C, 0x00 },
+ { 0x025D, 0x00 },
+ { 0x025E, 0x00 },
+ { 0x025F, 0x00 },
+ { 0x0260, 0x00 },
+ { 0x0261, 0x00 },
+ { 0x026B, 0x30 },
+ { 0x026C, 0x35 },
+ { 0x026D, 0x00 },
+ { 0x026E, 0x00 },
+ { 0x026F, 0x00 },
+ { 0x0270, 0x00 },
+ { 0x0271, 0x00 },
+ { 0x0272, 0x00 },
+ { 0x0302, 0x00 },
+ { 0x0303, 0x00 },
+ { 0x0304, 0x00 },
+ { 0x0305, 0x00 },
+ { 0x0306, 0x0D },
+ { 0x0307, 0x00 },
+ { 0x0308, 0x00 },
+ { 0x0309, 0x00 },
+ { 0x030A, 0x00 },
+ { 0x030B, 0x80 },
+ { 0x030C, 0x00 },
+ { 0x030D, 0x00 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0x00 },
+ { 0x0310, 0x61 },
+ { 0x0311, 0x08 },
+ { 0x0312, 0x00 },
+ { 0x0313, 0x00 },
+ { 0x0314, 0x00 },
+ { 0x0315, 0x00 },
+ { 0x0316, 0x80 },
+ { 0x0317, 0x00 },
+ { 0x0318, 0x00 },
+ { 0x0319, 0x00 },
+ { 0x031A, 0x00 },
+ { 0x031B, 0xD0 },
+ { 0x031C, 0x1A },
+ { 0x031D, 0x00 },
+ { 0x031E, 0x00 },
+ { 0x031F, 0x00 },
+ { 0x0320, 0x00 },
+ { 0x0321, 0xA0 },
+ { 0x0322, 0x00 },
+ { 0x0323, 0x00 },
+ { 0x0324, 0x00 },
+ { 0x0325, 0x00 },
+ { 0x0326, 0x00 },
+ { 0x0327, 0x00 },
+ { 0x0328, 0x00 },
+ { 0x0329, 0x00 },
+ { 0x032A, 0x00 },
+ { 0x032B, 0x00 },
+ { 0x032C, 0x00 },
+ { 0x032D, 0x00 },
+ { 0x0338, 0x00 },
+ { 0x0339, 0x1F },
+ { 0x033B, 0x00 },
+ { 0x033C, 0x00 },
+ { 0x033D, 0x00 },
+ { 0x033E, 0x00 },
+ { 0x033F, 0x00 },
+ { 0x0340, 0x00 },
+ { 0x0341, 0x00 },
+ { 0x0342, 0x00 },
+ { 0x0343, 0x00 },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x00 },
+ { 0x0349, 0x00 },
+ { 0x034A, 0x00 },
+ { 0x034B, 0x00 },
+ { 0x034C, 0x00 },
+ { 0x034D, 0x00 },
+ { 0x034E, 0x00 },
+ { 0x034F, 0x00 },
+ { 0x0350, 0x00 },
+ { 0x0351, 0x00 },
+ { 0x0352, 0x00 },
+ { 0x0359, 0x00 },
+ { 0x035A, 0x00 },
+ { 0x035B, 0x00 },
+ { 0x035C, 0x00 },
+ { 0x035D, 0x00 },
+ { 0x035E, 0x00 },
+ { 0x035F, 0x00 },
+ { 0x0360, 0x00 },
+ { 0x0802, 0x00 },
+ { 0x0803, 0x00 },
+ { 0x0804, 0x00 },
+ { 0x0805, 0x00 },
+ { 0x0806, 0x00 },
+ { 0x0807, 0x00 },
+ { 0x0808, 0x00 },
+ { 0x0809, 0x00 },
+ { 0x080A, 0x00 },
+ { 0x080B, 0x00 },
+ { 0x080C, 0x00 },
+ { 0x080D, 0x00 },
+ { 0x080E, 0x00 },
+ { 0x080F, 0x00 },
+ { 0x0810, 0x00 },
+ { 0x0811, 0x00 },
+ { 0x0812, 0x00 },
+ { 0x0813, 0x00 },
+ { 0x0814, 0x00 },
+ { 0x0815, 0x00 },
+ { 0x0816, 0x00 },
+ { 0x0817, 0x00 },
+ { 0x0818, 0x00 },
+ { 0x0819, 0x00 },
+ { 0x081A, 0x00 },
+ { 0x081B, 0x00 },
+ { 0x081C, 0x00 },
+ { 0x081D, 0x00 },
+ { 0x081E, 0x00 },
+ { 0x081F, 0x00 },
+ { 0x0820, 0x00 },
+ { 0x0821, 0x00 },
+ { 0x0822, 0x00 },
+ { 0x0823, 0x00 },
+ { 0x0824, 0x00 },
+ { 0x0825, 0x00 },
+ { 0x0826, 0x00 },
+ { 0x0827, 0x00 },
+ { 0x0828, 0x00 },
+ { 0x0829, 0x00 },
+ { 0x082A, 0x00 },
+ { 0x082B, 0x00 },
+ { 0x082C, 0x00 },
+ { 0x082D, 0x00 },
+ { 0x082E, 0x00 },
+ { 0x082F, 0x00 },
+ { 0x0830, 0x00 },
+ { 0x0831, 0x00 },
+ { 0x0832, 0x00 },
+ { 0x0833, 0x00 },
+ { 0x0834, 0x00 },
+ { 0x0835, 0x00 },
+ { 0x0836, 0x00 },
+ { 0x0837, 0x00 },
+ { 0x0838, 0x00 },
+ { 0x0839, 0x00 },
+ { 0x083A, 0x00 },
+ { 0x083B, 0x00 },
+ { 0x083C, 0x00 },
+ { 0x083D, 0x00 },
+ { 0x083E, 0x00 },
+ { 0x083F, 0x00 },
+ { 0x0840, 0x00 },
+ { 0x0841, 0x00 },
+ { 0x0842, 0x00 },
+ { 0x0843, 0x00 },
+ { 0x0844, 0x00 },
+ { 0x0845, 0x00 },
+ { 0x0846, 0x00 },
+ { 0x0847, 0x00 },
+ { 0x0848, 0x00 },
+ { 0x0849, 0x00 },
+ { 0x084A, 0x00 },
+ { 0x084B, 0x00 },
+ { 0x084C, 0x00 },
+ { 0x084D, 0x00 },
+ { 0x084E, 0x00 },
+ { 0x084F, 0x00 },
+ { 0x0850, 0x00 },
+ { 0x0851, 0x00 },
+ { 0x0852, 0x00 },
+ { 0x0853, 0x00 },
+ { 0x0854, 0x00 },
+ { 0x0855, 0x00 },
+ { 0x0856, 0x00 },
+ { 0x0857, 0x00 },
+ { 0x0858, 0x00 },
+ { 0x0859, 0x00 },
+ { 0x085A, 0x00 },
+ { 0x085B, 0x00 },
+ { 0x085C, 0x00 },
+ { 0x085D, 0x00 },
+ { 0x085E, 0x00 },
+ { 0x085F, 0x00 },
+ { 0x0860, 0x00 },
+ { 0x0861, 0x00 },
+ { 0x090E, 0x02 },
+ { 0x091C, 0x04 },
+ { 0x0943, 0x00 },
+ { 0x0949, 0x00 },
+ { 0x094A, 0x00 },
+ { 0x094E, 0x49 },
+ { 0x094F, 0x02 },
+ { 0x095E, 0x00 },
+ { 0x0A02, 0x00 },
+ { 0x0A03, 0x07 },
+ { 0x0A04, 0x01 },
+ { 0x0A05, 0x07 },
+ { 0x0A14, 0x00 },
+ { 0x0A1A, 0x00 },
+ { 0x0A20, 0x00 },
+ { 0x0A26, 0x00 },
+ { 0x0B44, 0x0F },
+ { 0x0B4A, 0x08 },
+ { 0x0B57, 0x0E },
+ { 0x0B58, 0x01 },
+ { 0x001C, 0x01 },
+ { 0x0B24, 0xC3 },
+ { 0x0B25, 0x02 },
+};
+
+#endif /* SI5340_REVD_REG_CONFIG_HEADER */
diff --git a/drivers/net/ntnic/nthw/core/nthw_rmc.c b/drivers/net/ntnic/nthw/core/nthw_rmc.c
new file mode 100644
index 0000000000..c4c6779ce0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_rmc.c
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_rmc.h"
+
+nthw_rmc_t *nthw_rmc_new(void)
+{
+ nthw_rmc_t *p = malloc(sizeof(nthw_rmc_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_rmc_t));
+ return p;
+}
+
+void nthw_rmc_delete(nthw_rmc_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_rmc_t));
+ free(p);
+ }
+}
+
+int nthw_rmc_init(nthw_rmc_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RMC, n_instance);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RMC %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_rmc = p_mod;
+
+ /* Params */
+ p->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH;
+ p->mn_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS,
+ fpga_get_product_param(p_fpga, NT_PORTS, 0));
+ p->mn_nims = fpga_get_product_param(p_fpga, NT_NIMS, 0);
+ p->mb_administrative_block = false;
+
+ NT_LOG(DBG, NTHW, "%s: RMC %d: vswitch=%d\n", p_adapter_id_str,
+ p->mn_instance, p->mb_is_vswitch);
+
+ p->mp_reg_ctrl = module_get_register(p->mp_mod_rmc, RMC_CTRL);
+
+ p->mp_fld_ctrl_block_stat_drop =
+ register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_STATT);
+ p->mp_fld_ctrl_block_keep_alive =
+ register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_KEEPA);
+ p->mp_fld_ctrl_block_mac_port =
+ register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_MAC_PORT);
+
+ p->mp_reg_status = module_query_register(p->mp_mod_rmc, RMC_STATUS);
+ if (p->mp_reg_status) {
+ p->mp_fld_sf_ram_of =
+ register_get_field(p->mp_reg_status, RMC_STATUS_SF_RAM_OF);
+ p->mp_fld_descr_fifo_of =
+ register_get_field(p->mp_reg_status, RMC_STATUS_DESCR_FIFO_OF);
+ }
+
+ p->mp_reg_dbg = module_query_register(p->mp_mod_rmc, RMC_DBG);
+ if (p->mp_reg_dbg) {
+ p->mp_fld_dbg_merge =
+ register_get_field(p->mp_reg_dbg, RMC_DBG_MERGE);
+ }
+
+ p->mp_reg_mac_if = module_query_register(p->mp_mod_rmc, RMC_MAC_IF);
+ if (p->mp_reg_mac_if) {
+ p->mp_fld_mac_if_err =
+ register_get_field(p->mp_reg_mac_if, RMC_MAC_IF_ERR);
+ }
+ return 0;
+}
+
+uint32_t nthw_rmc_get_mac_block(nthw_rmc_t *p)
+{
+ return field_get_updated(p->mp_fld_ctrl_block_mac_port);
+}
+
+uint32_t nthw_rmc_get_status_sf_ram_of(nthw_rmc_t *p)
+{
+ return (p->mp_reg_status) ? field_get_updated(p->mp_fld_sf_ram_of) :
+ 0xffffffff;
+}
+
+uint32_t nthw_rmc_get_status_descr_fifo_of(nthw_rmc_t *p)
+{
+ return (p->mp_reg_status) ? field_get_updated(p->mp_fld_descr_fifo_of) :
+ 0xffffffff;
+}
+
+uint32_t nthw_rmc_get_dbg_merge(nthw_rmc_t *p)
+{
+ return (p->mp_reg_dbg) ? field_get_updated(p->mp_fld_dbg_merge) : 0xffffffff;
+}
+
+uint32_t nthw_rmc_get_mac_if_err(nthw_rmc_t *p)
+{
+ return (p->mp_reg_mac_if) ? field_get_updated(p->mp_fld_mac_if_err) :
+ 0xffffffff;
+}
+
+void nthw_rmc_set_mac_block(nthw_rmc_t *p, uint32_t mask)
+{
+ field_set_val_flush32(p->mp_fld_ctrl_block_mac_port, mask);
+}
+
+void nthw_rmc_block(nthw_rmc_t *p)
+{
+ /* BLOCK_STATT(0)=1 BLOCK_KEEPA(1)=1 BLOCK_MAC_PORT(8:11)=~0 */
+ if (!p->mb_administrative_block) {
+ field_set_flush(p->mp_fld_ctrl_block_stat_drop);
+ field_set_flush(p->mp_fld_ctrl_block_keep_alive);
+ field_set_flush(p->mp_fld_ctrl_block_mac_port);
+ }
+}
+
+void nthw_rmc_unblock(nthw_rmc_t *p, bool b_is_slave)
+{
+ uint32_t n_block_mask = ~0U << (b_is_slave ? p->mn_nims : p->mn_ports);
+
+ if (p->mb_is_vswitch) {
+ /*
+ * VSWITCH: NFV: block bits: phy_nim_ports(2) + rtd_ports(4) +
+ * roa_recirculate_port(1)
+ */
+ n_block_mask = 1 << (2 + 4); /* block only ROA recirculate */
+ }
+
+ /* BLOCK_STATT(0)=0 BLOCK_KEEPA(1)=0 BLOCK_MAC_PORT(8:11)=0 */
+ if (!p->mb_administrative_block) {
+ field_clr_flush(p->mp_fld_ctrl_block_stat_drop);
+ field_clr_flush(p->mp_fld_ctrl_block_keep_alive);
+ field_set_val_flush32(p->mp_fld_ctrl_block_mac_port, n_block_mask);
+ }
+}
+
+void nthw_rmc_administrative_block(nthw_rmc_t *p)
+{
+ /* block all MAC ports */
+ field_set_flush(p->mp_fld_ctrl_block_mac_port);
+ p->mb_administrative_block = true;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_rmc.h b/drivers/net/ntnic/nthw/core/nthw_rmc.h
new file mode 100644
index 0000000000..b40f0a0994
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_rmc.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_RMC_H_
+#define NTHW_RMC_H_
+
+struct nthw_rmc {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_rmc;
+ int mn_instance;
+
+ int mn_ports;
+ int mn_nims;
+ bool mb_is_vswitch;
+
+ bool mb_administrative_block;
+
+ /* RMC CTRL register */
+ nt_register_t *mp_reg_ctrl;
+ nt_field_t *mp_fld_ctrl_block_stat_drop;
+ nt_field_t *mp_fld_ctrl_block_keep_alive;
+ nt_field_t *mp_fld_ctrl_block_mac_port;
+
+ /* RMC Status register */
+ nt_register_t *mp_reg_status;
+ nt_field_t *mp_fld_sf_ram_of;
+ nt_field_t *mp_fld_descr_fifo_of;
+
+ /* RMC DBG register */
+ nt_register_t *mp_reg_dbg;
+ nt_field_t *mp_fld_dbg_merge;
+
+ /* RMC MAC_IF register */
+ nt_register_t *mp_reg_mac_if;
+ nt_field_t *mp_fld_mac_if_err;
+};
+
+typedef struct nthw_rmc nthw_rmc_t;
+typedef struct nthw_rmc nthw_rmc;
+
+nthw_rmc_t *nthw_rmc_new(void);
+void nthw_rmc_delete(nthw_rmc_t *p);
+int nthw_rmc_init(nthw_rmc_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+uint32_t nthw_rmc_get_mac_block(nthw_rmc_t *p);
+void nthw_rmc_set_mac_block(nthw_rmc_t *p, uint32_t mask);
+void nthw_rmc_block(nthw_rmc_t *p);
+void nthw_rmc_unblock(nthw_rmc_t *p, bool b_is_slave);
+void nthw_rmc_administrative_block(nthw_rmc_t *p);
+
+uint32_t nthw_rmc_get_status_sf_ram_of(nthw_rmc_t *p);
+uint32_t nthw_rmc_get_status_descr_fifo_of(nthw_rmc_t *p);
+uint32_t nthw_rmc_get_dbg_merge(nthw_rmc_t *p);
+uint32_t nthw_rmc_get_mac_if_err(nthw_rmc_t *p);
+
+#endif /* NTHW_RMC_H_ */
diff --git a/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c
new file mode 100644
index 0000000000..bf120ccb39
--- /dev/null
+++ b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "avr_sensors.h"
+#include "ntlog.h"
+
+#define MAX_ADAPTERS 2
+
+uint8_t s_fpga_indexes[MAX_ADAPTERS] = { 0 }; /* _NTSD_MAX_NUM_ADAPTERS_ */
+static uint8_t get_fpga_idx(unsigned int adapter_no);
+
+/*
+ * This function setups monitoring of AVR sensors
+ */
+static uint8_t _avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no,
+ const char *p_name,
+ enum sensor_mon_device avr_dev,
+ uint8_t avr_dev_reg, enum sensor_mon_endian end,
+ enum sensor_mon_sign si, uint16_t mask)
+{
+ uint8_t fpga_idx = get_fpga_idx(m_adapter_no);
+ struct sensor_mon_setup16 avr_sensor_setup;
+
+ /* Setup monitoring in AVR placing results in FPGA */
+ avr_sensor_setup.setup_cnt = 1;
+ avr_sensor_setup.setup_data[0].fpga_idx = fpga_idx;
+ avr_sensor_setup.setup_data[0].device = avr_dev;
+ avr_sensor_setup.setup_data[0].device_register = avr_dev_reg;
+ avr_sensor_setup.setup_data[0].format = (uint16_t)(end | si << 2);
+
+ avr_sensor_setup.setup_data[0].mask = mask;
+ avr_sensor_setup.setup_data[0].pos =
+ 0; /* So far for all sensors in table */
+
+ /*
+ * At first it is the task of ntservice to test limit_low and limit_high on all
+ * board sensors. Later the test is going to be carried out by the AVR
+ */
+ if (si == SENSOR_MON_SIGNED) {
+ avr_sensor_setup.setup_data[0].int16.limit_low =
+ SENSOR_MON_INT16_NAN;
+ avr_sensor_setup.setup_data[0].int16.limit_high =
+ SENSOR_MON_INT16_NAN;
+ } else {
+ avr_sensor_setup.setup_data[0].uint16.limit_low =
+ SENSOR_MON_UINT16_NAN;
+ avr_sensor_setup.setup_data[0].uint16.limit_high =
+ SENSOR_MON_UINT16_NAN;
+ }
+
+ int result = nt_avr_sensor_mon_setup(&avr_sensor_setup, s_spi);
+
+ if (result)
+ NT_LOG(ERR, ETHDEV, "%s: sensor initialization error\n", p_name);
+
+ return fpga_idx;
+}
+
+static void avr_read(struct nt_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint32_t p_sensor_result;
+
+ if (sg == NULL || sg->sensor == NULL)
+ return;
+
+ sensor_read(t_spi, sg->sensor->fpga_idx, &p_sensor_result);
+ update_sensor_value(sg->sensor, sg->conv_func(p_sensor_result));
+}
+
+struct nt_sensor_group *
+avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum sensor_mon_device avr_dev,
+ uint8_t avr_dev_reg, enum sensor_mon_endian end,
+ enum sensor_mon_sign si, int (*conv_func)(uint32_t),
+ uint16_t mask)
+{
+ struct nt_sensor_group *sg = malloc(sizeof(struct nt_sensor_group));
+
+ if (sg == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__);
+ return NULL;
+ }
+ init_sensor_group(sg);
+ sg->sensor = allocate_sensor(m_adapter_no, p_name, ssrc, type, index,
+ NT_SENSOR_DISABLE_ALARM, si);
+ sg->sensor->fpga_idx = _avr_sensor_init(s_spi, m_adapter_no, p_name, avr_dev,
+ avr_dev_reg, end, si, mask);
+ sg->read = &avr_read;
+ sg->conv_func = conv_func;
+ sg->monitor = NULL;
+ sg->next = NULL;
+ return sg;
+}
+
+static uint8_t get_fpga_idx(unsigned int adapter_no)
+{
+ uint8_t tmp = s_fpga_indexes[adapter_no];
+
+ s_fpga_indexes[adapter_no] = (uint8_t)(tmp + 1);
+
+ return tmp;
+}
diff --git a/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h
new file mode 100644
index 0000000000..b8c37a12cb
--- /dev/null
+++ b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _AVR_SENSORS_H
+#define _AVR_SENSORS_H
+
+#include <stdint.h>
+
+#include "sensors.h"
+#include "avr_intf.h"
+#include "ntavr.h"
+
+struct nt_sensor_group *
+avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum sensor_mon_device avr_dev,
+ uint8_t avr_dev_reg, enum sensor_mon_endian end,
+ enum sensor_mon_sign si, int (*conv_func)(uint32_t),
+ uint16_t mask);
+
+#endif /* _AVR_SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/board_sensors/board_sensors.c b/drivers/net/ntnic/sensors/board_sensors/board_sensors.c
new file mode 100644
index 0000000000..8e52379df8
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/board_sensors.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stddef.h>
+#include <math.h>
+
+#include "tempmon.h"
+#include "board_sensors.h"
+#include "ntlog.h"
+
+static void fpga_temperature_sensor_read(struct nt_sensor_group *sg,
+ nthw_spis_t *t_spi)
+{
+ int temp = 0;
+ (void)t_spi;
+ if (sg == NULL || sg->sensor == NULL) {
+ NT_LOG(ERR, ETHDEV, "failed to read FPGA temperature\n");
+ return;
+ }
+ struct nt_fpga_sensor_monitor *temp_monitor = sg->monitor;
+ uint32_t val = field_get_updated(temp_monitor->fields[0]);
+
+ temp = (val * 20159 - 44752896) / 16384;
+
+ update_sensor_value(sg->sensor, temp);
+}
+
+struct nt_sensor_group *fpga_temperature_sensor_init(uint8_t adapter_no,
+ unsigned int sensor_idx,
+ nt_fpga_t *p_fpga)
+{
+ struct nt_sensor_group *sg = malloc(sizeof(struct nt_sensor_group));
+
+ if (sg == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__);
+ return NULL;
+ }
+ init_sensor_group(sg);
+ sg->monitor = tempmon_new();
+ tempmon_init(sg->monitor, p_fpga);
+ sg->sensor =
+ allocate_sensor(adapter_no, "FPGA", NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE, sensor_idx,
+ NT_SENSOR_DISABLE_ALARM, SENSOR_MON_UNSIGNED);
+ sg->read = &fpga_temperature_sensor_read;
+ return sg;
+}
diff --git a/drivers/net/ntnic/sensors/board_sensors/board_sensors.h b/drivers/net/ntnic/sensors/board_sensors/board_sensors.h
new file mode 100644
index 0000000000..a7f75b7ae4
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/board_sensors.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _BOARD_SENSORS_H
+#define _BOARD_SENSORS_H
+
+#include <stdint.h>
+
+#include "sensors.h"
+
+#include "nthw_fpga_model.h"
+
+struct nt_sensor_group *fpga_temperature_sensor_init(uint8_t adapter_no,
+ unsigned int sensor_idx,
+ nt_fpga_t *p_fpga);
+
+#endif /* _BOARD_SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/board_sensors/tempmon.c b/drivers/net/ntnic/sensors/board_sensors/tempmon.c
new file mode 100644
index 0000000000..2cd3709205
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/tempmon.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "tempmon.h"
+#include "ntlog.h"
+#include "nthw_register.h"
+
+struct nt_fpga_sensor_monitor *tempmon_new(void)
+{
+ struct nt_fpga_sensor_monitor *temp =
+ malloc(sizeof(struct nt_fpga_sensor_monitor));
+ if (temp == NULL)
+ NT_LOG(ERR, ETHDEV, "%s: monitor is NULL\n", __func__);
+ return temp;
+}
+
+void tempmon_init(struct nt_fpga_sensor_monitor *t, nt_fpga_t *p_fpga)
+{
+ if (t == NULL || p_fpga == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+ /* fetch initialized module */
+ t->fpga = p_fpga;
+ t->mod = nthw_get_module(t->fpga, MOD_TEMPMON, 0);
+ if (t->mod == NULL)
+ NT_LOG(ERR, ETHDEV, "module is NULL\n");
+ /* fetch register */
+ t->reg = module_get_register(t->mod, TEMPMON_STAT);
+ if (t->reg == NULL)
+ NT_LOG(ERR, ETHDEV, "register is NULL\n");
+ /* fetch fields */
+ t->fields = malloc(sizeof(nt_field_t *));
+ if (t->fields == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: field is NULL", __func__);
+ return;
+ }
+ t->fields[0] = register_get_field(t->reg, TEMPMON_STAT_TEMP);
+ if (t->fields[0] == NULL)
+ NT_LOG(ERR, ETHDEV, "field is NULL\n");
+}
diff --git a/drivers/net/ntnic/sensors/board_sensors/tempmon.h b/drivers/net/ntnic/sensors/board_sensors/tempmon.h
new file mode 100644
index 0000000000..6f2017b714
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/tempmon.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _TEMPMON_H
+#define _TEMPMON_H
+
+#include "nthw_fpga_model.h"
+#include <stdlib.h>
+
+#include "sensors.h"
+
+struct nt_fpga_sensor_monitor *tempmon_new(void);
+void tempmon_init(struct nt_fpga_sensor_monitor *t, nt_fpga_t *p_fpga);
+
+#endif /* _TEMPMON_H */
diff --git a/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c
new file mode 100644
index 0000000000..e130855a35
--- /dev/null
+++ b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <arpa/inet.h>
+
+#include "nim_sensors.h"
+#include "ntlog.h"
+
+#define TEMP NT_SENSOR_TYPE_TEMPERATURE
+#define VOLT NT_SENSOR_TYPE_VOLTAGE
+#define CURR NT_SENSOR_TYPE_CURRENT
+#define PWR NT_SENSOR_TYPE_POWER
+
+#define SNA NT_SENSOR_SUBTYPE_NA
+#define AVG NT_SENSOR_SUBTYPE_POWER_AVERAGE
+
+#define ENA NT_SENSOR_ENABLE_ALARM
+#define DIA NT_SENSOR_DISABLE_ALARM
+
+/*
+ * Sensors for SFP/SFP+/SFP28. The name of the level 0 temperature sensor is
+ * empty and will then be set automatically
+ */
+struct nt_adapter_sensor_description sfp_sensors_level0[1] = {
+ { TEMP, SNA, NT_SENSOR_SFP_TEMP, DIA, "" },
+};
+
+struct nt_adapter_sensor_description sfp_sensors_level1[4] = {
+ { VOLT, SNA, NT_SENSOR_SFP_SUPPLY, DIA, "Supply" },
+ { CURR, SNA, NT_SENSOR_SFP_TX_BIAS, DIA, "Tx Bias" },
+ { PWR, AVG, NT_SENSOR_SFP_TX_POWER, DIA, "Tx" },
+ { PWR, AVG, NT_SENSOR_SFP_RX_POWER, DIA, "Rx" }
+};
+
+struct nt_adapter_sensor_description qsfp_sensor_level0[1] = {
+ { TEMP, SNA, NT_SENSOR_QSFP_TEMP, DIA, "" },
+};
+
+struct nt_adapter_sensor_description qsfp_sensor_level1[13] = {
+ { VOLT, SNA, NT_SENSOR_QSFP_SUPPLY, DIA, "Supply" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS1, DIA, "Tx Bias 1" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS2, DIA, "Tx Bias 2" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS3, DIA, "Tx Bias 3" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS4, DIA, "Tx Bias 4" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER1, DIA, "Tx 1" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER2, DIA, "Tx 2" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER3, DIA, "Tx 3" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER4, DIA, "Tx 4" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER1, DIA, "Rx 1" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER2, DIA, "Rx 2" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER3, DIA, "Rx 3" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER4, DIA, "Rx 4" }
+};
diff --git a/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h
new file mode 100644
index 0000000000..c68c9aa924
--- /dev/null
+++ b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NIM_SENSORS_H
+#define _NIM_SENSORS_H
+
+#include <stdint.h>
+#include <string.h>
+#include "sensors.h"
+
+#define XFP_TEMP_LIN_ADDR 96
+
+extern struct nt_adapter_sensor_description sfp_sensors_level0[1];
+extern struct nt_adapter_sensor_description sfp_sensors_level1[4];
+extern struct nt_adapter_sensor_description qsfp_sensor_level0[1];
+extern struct nt_adapter_sensor_description qsfp_sensor_level1[13];
+
+#endif /* _NIM_SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/ntavr/avr_intf.h b/drivers/net/ntnic/sensors/ntavr/avr_intf.h
new file mode 100644
index 0000000000..feeec6e13a
--- /dev/null
+++ b/drivers/net/ntnic/sensors/ntavr/avr_intf.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _AVR_INTF
+#define _AVR_INTF
+
+#include <stdint.h>
+
+#define SENSOR_MON_UINT16_NAN 0xFFFF /* Most positive number used as NaN */
+#define SENSOR_MON_INT16_NAN \
+ ((int16_t)0x8000) /* Most negative number used as NaN */
+
+/*
+ * Specify the nature of the raw data. AVR and ntservice must use this
+ * information when comparing or converting to native format which is little endian
+ */
+enum sensor_mon_endian { SENSOR_MON_LITTLE_ENDIAN, SENSOR_MON_BIG_ENDIAN };
+
+enum sensor_mon_sign {
+ SENSOR_MON_UNSIGNED,
+ SENSOR_MON_SIGNED, /* 2's complement */
+};
+
+/* Define sensor devices */
+enum sensor_mon_device {
+ SENSOR_MON_PSU_EXAR_7724_0 = 0, /* NT40E3, NT100E3 */
+ SENSOR_MON_PSU_EXAR_7724_1, /* NT40E3, NT100E3 */
+ SENSOR_MON_PSU_LTM_4676_0, /* na NT100E3, page-0 */
+ SENSOR_MON_PSU_LTM_4676_1, /* na NT100E3, page-0 */
+ SENSOR_MON_INA219_1, /* NT40E3, NT100E3 */
+ SENSOR_MON_INA219_2, /* NT40E3, NT100E3 */
+ SENSOR_MON_MAX6642, /* NT40E3, NT100E3 */
+ SENSOR_MON_DS1775, /* NT40E3, NT100E3 */
+ SENSOR_MON_FAN, /* NT40E3, NT100E3 */
+ SENSOR_MON_AVR, /* NT40E3, NT100E3 */
+ SENSOR_MON_PEX8734, /* na NT100E3 */
+ SENSOR_MON_RATE_COUNT, /* NT40E3, NT100E3 */
+ SENSOR_MON_PSU_LTM_4676_0_1, /* na NT100E3, page-1 */
+ SENSOR_MON_PSU_LTM_4676_1_1, /* na NT100E3, page-1 */
+ SENSOR_MON_MP2886A, /* na, na, NT200A02, */
+ SENSOR_MON_PSU_EM2260_1, /* na, na, na, na, NT200D01^M */
+ SENSOR_MON_PSU_EM2120_2, /* na, na, na, na, NT200D01^M */
+ SENSOR_MON_MP2886A_PSU_1, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8869S_PSU_2, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8645PGVT_PSU_3, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8645PGVT_PSU_4, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8869S_PSU_5, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8869S_PSU_6, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_DEVICE_COUNT
+};
+
+#pragma pack(1)
+struct sensor_mon_setup_data16 {
+ uint8_t fpga_idx; /* Destination of results */
+ uint8_t device; /* Device to monitor */
+ uint8_t device_register; /* Sensor within device */
+ uint16_t mask; /* Indicates active bits */
+ uint8_t pos; /* Position of first active bit */
+ uint16_t format; /* b0,1:sensor_mon_endian_t endian */
+ /* b2,3:sensor_mon_sign_t sign */
+ union {
+ struct {
+ int16_t limit_low; /* Signed alarm limit low */
+ int16_t limit_high; /* Signed alarm limit high */
+ } int16;
+
+ struct {
+ uint16_t limit_low; /* Unsigned alarm limit low */
+ uint16_t limit_high; /* Unsigned alarm limit high */
+ } uint16;
+ };
+};
+
+#pragma pack()
+struct sensor_mon_setup16 {
+ uint8_t setup_cnt; /* Number of entries in setup_data */
+ struct sensor_mon_setup_data16 setup_data[40];
+};
+
+/* Define sensor monitoring control */
+enum sensor_mon_control {
+ SENSOR_MON_CTRL_STOP = 0, /* Stop sensor monitoring */
+ SENSOR_MON_CTRL_RUN = 1, /* Start sensor monitoring */
+ SENSOR_MON_CTRL_REM_ALL_SENSORS =
+ 2, /* Stop and remove all sensor monitoring setup */
+};
+
+#endif /* _AVR_INTF */
diff --git a/drivers/net/ntnic/sensors/ntavr/ntavr.c b/drivers/net/ntnic/sensors/ntavr/ntavr.c
new file mode 100644
index 0000000000..6d8c3042b1
--- /dev/null
+++ b/drivers/net/ntnic/sensors/ntavr/ntavr.c
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntavr.h"
+#include "ntlog.h"
+
+static int txrx(nthw_spi_v3_t *s_spi, enum avr_opcodes opcode, size_t txsz,
+ uint16_t *tx, size_t *rxsz, uint16_t *rx)
+{
+ int res = 1;
+ struct tx_rx_buf m_tx = { .size = (uint16_t)txsz, .p_buf = tx };
+ struct tx_rx_buf m_rx = { .size = (uint16_t)*rxsz, .p_buf = rx };
+
+ res = nthw_spi_v3_transfer(s_spi, opcode, &m_tx, &m_rx);
+ if (res) {
+ NT_LOG(ERR, ETHDEV, "%s transfer failed - %i", __func__, res);
+ return res;
+ }
+
+ if (rxsz != NULL)
+ *rxsz = m_rx.size;
+
+ return res;
+}
+
+uint32_t sensor_read(nthw_spis_t *t_spi, uint8_t fpga_idx,
+ uint32_t *p_sensor_result)
+{
+ return nthw_spis_read_sensor(t_spi, fpga_idx, p_sensor_result);
+}
+
+int nt_avr_sensor_mon_setup(struct sensor_mon_setup16 *p_setup, nthw_spi_v3_t *s_spi)
+{
+ int error;
+ size_t tx_size;
+ size_t rx_size = 0;
+
+ tx_size = sizeof(struct sensor_mon_setup16) - sizeof(p_setup->setup_data);
+ tx_size += sizeof(p_setup->setup_data[0]) * p_setup->setup_cnt;
+
+ error = txrx(s_spi, AVR_OP_SENSOR_MON_SETUP, tx_size, (uint16_t *)p_setup,
+ &rx_size, NULL);
+
+ if (error) {
+ NT_LOG(ERR, ETHDEV, "%s failed\n", __func__);
+ return error;
+ }
+
+ if (rx_size != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Returned data: Expected size = 0, Actual = %zu",
+ __func__, rx_size);
+ return 1;
+ }
+ return 0;
+}
+
+int nt_avr_sensor_mon_ctrl(nthw_spi_v3_t *s_spi, enum sensor_mon_control ctrl)
+{
+ int error;
+ size_t rx_size = 0;
+
+ error = txrx(s_spi, AVR_OP_SENSOR_MON_CONTROL, sizeof(ctrl),
+ (uint16_t *)(&ctrl), &rx_size, NULL);
+
+ if (error != 0)
+ return error;
+
+ if (rx_size != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Returned data: Expected size = 0, Actual = %zu",
+ __func__, rx_size);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/sensors/ntavr/ntavr.h b/drivers/net/ntnic/sensors/ntavr/ntavr.h
new file mode 100644
index 0000000000..b7a7aeb908
--- /dev/null
+++ b/drivers/net/ntnic/sensors/ntavr/ntavr.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTAVR_H
+#define _NTAVR_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "avr_intf.h"
+#include "nthw_drv.h"
+#include "nthw_spi_v3.h"
+
+/*
+ * @internal
+ * @brief AVR Device Enum
+ *
+ * Global names for identifying an AVR device for Generation2 adapters
+ */
+enum ntavr_device {
+ NTAVR_MAINBOARD, /* Mainboard AVR device */
+ NTAVR_FRONTBOARD /* Frontboard AVR device */
+};
+
+int nt_avr_sensor_mon_setup(struct sensor_mon_setup16 *p_setup,
+ nthw_spi_v3_t *s_spi);
+int nt_avr_sensor_mon_ctrl(nthw_spi_v3_t *s_spi, enum sensor_mon_control ctrl);
+uint32_t sensor_read(nthw_spis_t *t_spi, uint8_t fpga_idx,
+ uint32_t *p_sensor_result);
+
+#endif /* _NTAVR_H */
diff --git a/drivers/net/ntnic/sensors/sensor_types.h b/drivers/net/ntnic/sensors/sensor_types.h
new file mode 100644
index 0000000000..bac4e925f9
--- /dev/null
+++ b/drivers/net/ntnic/sensors/sensor_types.h
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SENSOR_TYPES_H
+#define _SENSOR_TYPES_H
+
+/*
+ * Sensor types
+ */
+enum nt_sensor_type_e {
+ NT_SENSOR_TYPE_UNKNOWN = 0,
+ NT_SENSOR_TYPE_TEMPERATURE = 1, /* Unit: 0.1 degree Celsius */
+ NT_SENSOR_TYPE_VOLTAGE = 2, /* Unit: 1 mV */
+ NT_SENSOR_TYPE_CURRENT = 3, /* Unit: 1 uA */
+ NT_SENSOR_TYPE_POWER = 4, /* Unit: 0.1 uW */
+ NT_SENSOR_TYPE_FAN = 5, /* Unit: 1 RPM (Revolutions Per Minute) */
+ NT_SENSOR_TYPE_HIGH_POWER = 6, /* Unit: 1 mW */
+ NT_SENSOR_TYPE_NUMBER = 7,
+};
+
+/*
+ * Generic SFP/SFP+/SFP28 sensors
+ *
+ * These sensors should be used instead of all adapter specific SFP sensors
+ * that have been deprecated..
+ */
+enum nt_sensors_sfp {
+ NT_SENSOR_SFP_TEMP,
+ NT_SENSOR_SFP_SUPPLY,
+ NT_SENSOR_SFP_TX_BIAS,
+ NT_SENSOR_SFP_TX_POWER,
+ NT_SENSOR_SFP_RX_POWER,
+};
+
+/*
+ * Generic QSFP/QSFP+/QSFP28 sensors
+ *
+ * These sensors should be used instead of all adapter specific QSFP sensors
+ * that have been deprecated..
+ */
+enum nt_sensors_qsfp {
+ NT_SENSOR_QSFP_TEMP,
+ NT_SENSOR_QSFP_SUPPLY,
+ NT_SENSOR_QSFP_TX_BIAS1,
+ NT_SENSOR_QSFP_TX_BIAS2,
+ NT_SENSOR_QSFP_TX_BIAS3,
+ NT_SENSOR_QSFP_TX_BIAS4,
+ NT_SENSOR_QSFP_TX_POWER1,
+ NT_SENSOR_QSFP_TX_POWER2,
+ NT_SENSOR_QSFP_TX_POWER3,
+ NT_SENSOR_QSFP_TX_POWER4,
+ NT_SENSOR_QSFP_RX_POWER1,
+ NT_SENSOR_QSFP_RX_POWER2,
+ NT_SENSOR_QSFP_RX_POWER3,
+ NT_SENSOR_QSFP_RX_POWER4,
+};
+
+typedef enum nt_sensor_type_e nt_sensor_type_t;
+
+/*
+ * Sensor subtypes
+ */
+enum nt_sensor_sub_type_e {
+ NT_SENSOR_SUBTYPE_NA = 0,
+ /*
+ * Subtype for NT_SENSOR_TYPE_POWER type on optical modules (optical modulation
+ * amplitude measured)
+ */
+ NT_SENSOR_SUBTYPE_POWER_OMA,
+ /* Subtype for NT_SENSOR_TYPE_POWER type on optical modules (average power measured) */
+ NT_SENSOR_SUBTYPE_POWER_AVERAGE,
+ /* Subtype for NT_SENSOR_TYPE_HIGH_POWER type on adapters (total power consumption) */
+ NT_SENSOR_SUBTYPE_POWER_TOTAL
+};
+
+typedef enum nt_sensor_sub_type_e nt_sensor_sub_type_t;
+
+/*
+ * Sensor source
+ */
+enum nt_sensor_source_e {
+ NT_SENSOR_SOURCE_UNKNOWN = 0x00, /* Unknown source */
+ /*
+ * Sensors located in a port. These are primary sensors - usually NIM temperature. Presence
+ * depends on adapter and NIM type.
+ */
+ NT_SENSOR_SOURCE_PORT =
+ 0x01,
+ /*
+ * Level 1 sensors located in a port. These are secondary sensors - usually NIM supply
+ * voltage, Tx bias and Rx/Tx optical power. Presence depends on adapter and NIM type.
+ */
+ NT_SENSOR_SOURCE_LEVEL1_PORT =
+ 0x02,
+#ifndef DOXYGEN_INTERNAL_ONLY
+ NT_SENSOR_SOURCE_LEVEL2_PORT =
+ 0x04, /* Level 2 sensors located in a port */
+#endif
+ NT_SENSOR_SOURCE_ADAPTER = 0x08, /* Sensors mounted on the adapter */
+ NT_SENSOR_SOURCE_LEVEL1_ADAPTER =
+ 0x10, /* Level 1 sensors mounted on the adapter */
+#ifndef DOXYGEN_INTERNAL_ONLY
+ NT_SENSOR_SOURCE_LEVEL2_ADAPTER =
+ 0x20, /* Level 2 sensors mounted on the adapter */
+#endif
+};
+
+/*
+ * Sensor state
+ */
+enum nt_sensor_state_e {
+ NT_SENSOR_STATE_UNKNOWN = 0, /* Unknown state */
+ NT_SENSOR_STATE_INITIALIZING = 1, /* The sensor is initializing */
+ NT_SENSOR_STATE_NORMAL = 2, /* Sensor values are within range */
+ NT_SENSOR_STATE_ALARM = 3, /* Sensor values are out of range */
+ NT_SENSOR_STATE_NOT_PRESENT =
+ 4 /* The sensor is not present, for example, SFP without diagnostics */
+};
+
+typedef enum nt_sensor_state_e nt_sensor_state_t;
+
+/*
+ * Sensor value
+ */
+#define NT_SENSOR_NAN \
+ (0x80000000) /* Indicates that sensor value or sensor limit is not valid (Not a Number) */
+
+/*
+ * Master/Slave
+ */
+enum nt_bonding_type_e {
+ NT_BONDING_UNKNOWN, /* Unknown bonding type */
+ NT_BONDING_MASTER, /* Adapter is master in the bonding */
+ NT_BONDING_SLAVE, /* Adapter is slave in the bonding */
+ NT_BONDING_PEER /* Adapter is bonded, but relationship is symmetric */
+};
+
+enum nt_sensors_e {
+ /* Public sensors (Level 0) */
+ NT_SENSOR_FPGA_TEMP, /* FPGA temperature sensor */
+};
+
+/*
+ * Adapter types
+ */
+enum nt_adapter_type_e {
+ NT_ADAPTER_TYPE_UNKNOWN = 0, /* Unknown adapter type */
+ NT_ADAPTER_TYPE_NT4E, /* NT4E network adapter */
+ NT_ADAPTER_TYPE_NT20E, /* NT20E network adapter */
+ NT_ADAPTER_TYPE_NT4E_STD, /* NT4E-STD network adapter */
+ NT_ADAPTER_TYPE_NT4E_PORT, /* NTPORT4E expansion adapter */
+ NT_ADAPTER_TYPE_NTBPE, /* NTBPE bypass adapter */
+ NT_ADAPTER_TYPE_NT20E2, /* NT20E2 network adapter */
+ NT_ADAPTER_TYPE_RESERVED1, /* Reserved */
+ NT_ADAPTER_TYPE_RESERVED2, /* Reserved */
+ NT_ADAPTER_TYPE_NT40E2_1, /* NT40E2-1 network adapter */
+ NT_ADAPTER_TYPE_NT40E2_4, /* NT40E2-4 network adapter */
+ NT_ADAPTER_TYPE_NT4E2_4T_BP, /* NT4E2-4T-BP bypass network adapter */
+ NT_ADAPTER_TYPE_NT4E2_4_PTP, /* NT4E2-4 PTP network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT20E2_PTP, /* NT20E2 PTP network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT40E3_4_PTP, /* NT40E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT100E3_1_PTP, /* NT100E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT20E3_2_PTP, /* NT20E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT80E3_2_PTP, /* NT80E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT200E3_2, /* NT200E3 network adapter */
+ NT_ADAPTER_TYPE_NT200A01, /* NT200A01 network adapter */
+ NT_ADAPTER_TYPE_NT200A01_2X100 =
+ NT_ADAPTER_TYPE_NT200A01, /* NT200A01 2 x 100 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT40A01_4X1, /* NT40A01_4X1 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT200A01_2X40, /* NT200A01 2 x 40 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT80E3_2_PTP_8X10, /* NT80E3 8 x 10 Gbps network adapter with IEEE1588 */
+ /* */
+ NT_ADAPTER_TYPE_INTEL_A10_4X10, /* Intel PAC A10 GX 4 x 10 Gbps network adapter */
+ NT_ADAPTER_TYPE_INTEL_A10_1X40, /* Intel PAC A10 GX 1 x 40 Gbps network adapter */
+ /* */
+ NT_ADAPTER_TYPE_NT200A01_8X10, /* NT200A01 8 x 10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X100, /* NT200A02 2 x 100 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X40, /* NT200A02 2 x 40 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A01_2X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT200A01_2X10_25 =
+ NT_ADAPTER_TYPE_NT200A01_2X25, /* NT200A01 2 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT200A02_2X10_25 =
+ NT_ADAPTER_TYPE_NT200A02_2X25, /* NT200A02 2 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_4X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT200A02_4X10_25 =
+ NT_ADAPTER_TYPE_NT200A02_4X25, /* NT200A02 4 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_8X10, /* NT200A02 8 x 10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT50B01_2X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT50B01_2X10_25 =
+ NT_ADAPTER_TYPE_NT50B01_2X25, /* NT50B01 2 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X1_10, /* NT200A02 2 x 1/10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT100A01_4X1_10, /* NT100A01 4 x 1/10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT100A01_4X10_25, /* NT100A01 4 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT50B01_2X1_10, /* NT50B01 2 x 1/10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT40A11_4X1_10, /* NT40A11 4 x 1/10 Gbps network adapter */
+#ifndef DOXYGEN_INTERNAL_ONLY
+ NT_ADAPTER_TYPE_ML605 = 10000, /* NT20E2 eval board */
+#endif
+ NT_ADAPTER_TYPE_4GARCH_HAMOA =
+ (1U
+ << 29), /* Bit to mark to adapters as a 4GArch Hamoa adapter */
+ NT_ADAPTER_TYPE_4GARCH =
+ (1U << 30), /* Bit to mark to adapters as a 4GArch adapter */
+ /* NOTE: do *NOT* add normal adapters after the group bit mark enums */
+};
+
+/* The NT200E3 adapter sensor id's */
+typedef enum nt_sensors_adapter_nt200_e3_e {
+ /* Public sensors (Level 0) */
+ NT_SENSOR_NT200E3_FPGA_TEMP, /* FPGA temperature sensor */
+ NT_SENSOR_NT200E3_FAN_SPEED, /* FAN speed sensor */
+ /* MCU (Micro Controller Unit) temperature sensor located inside enclosure below FAN */
+ NT_SENSOR_NT200E3_MCU_TEMP,
+ NT_SENSOR_NT200E3_PSU0_TEMP, /* Power supply 0 temperature sensor */
+ NT_SENSOR_NT200E3_PSU1_TEMP, /* Power supply 1 temperature sensor */
+ NT_SENSOR_NT200E3_PCB_TEMP, /* PCB temperature sensor */
+
+ /* Diagnostic sensors (Level 1) */
+ /* Total power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_NT200E3_POWER,
+ /* FPGA power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_FPGA_POWER,
+ /* DDR4 RAM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_DDR4_POWER,
+ /* NIM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_NIM_POWER,
+
+ NT_SENSOR_NT200E3_L1_MAX, /* Number of NT200E3 level 0,1 board sensors */
+} nt_sensors_adapter_nt200_e3_t;
+
+/*
+ * The following sensors are deprecated - generic types should be used instead
+ * The NIM temperature sensor must be the one with the lowest sensor_index
+ * (enum value) in order to be shown by the monitoring tool in port mode
+ */
+enum nt_sensors_port_nt200_e3_2_e {
+ /* Public sensors */
+ NT_SENSOR_NT200E3_NIM, /* QSFP28 temperature sensor */
+
+ /* Diagnostic sensors (Level 1) */
+ NT_SENSOR_NT200E3_SUPPLY, /* QSFP28 supply voltage sensor */
+ NT_SENSOR_NT200E3_TX_BIAS1, /* QSFP28 TX bias line 0 current sensor */
+ NT_SENSOR_NT200E3_TX_BIAS2, /* QSFP28 TX bias line 1 current sensor */
+ NT_SENSOR_NT200E3_TX_BIAS3, /* QSFP28 TX bias line 2 current sensor */
+ NT_SENSOR_NT200E3_TX_BIAS4, /* QSFP28 TX bias line 3 current sensor */
+ NT_SENSOR_NT200E3_RX1, /* QSFP28 RX line 0 power sensor */
+ NT_SENSOR_NT200E3_RX2, /* QSFP28 RX line 1 power sensor */
+ NT_SENSOR_NT200E3_RX3, /* QSFP28 RX line 2 power sensor */
+ NT_SENSOR_NT200E3_RX4, /* QSFP28 RX line 3 power sensor */
+ NT_SENSOR_NT200E3_TX1, /* QSFP28 TX line 0 power sensor */
+ NT_SENSOR_NT200E3_TX2, /* QSFP28 TX line 1 power sensor */
+ NT_SENSOR_NT200E3_TX3, /* QSFP28 TX line 2 power sensor */
+ NT_SENSOR_NT200E3_TX4, /* QSFP28 TX line 3 power sensor */
+ NT_SENSOR_NT200E3_PORT_MAX, /* Number of NT200E3 port sensors */
+};
+
+#endif
diff --git a/drivers/net/ntnic/sensors/sensors.c b/drivers/net/ntnic/sensors/sensors.c
new file mode 100644
index 0000000000..2a85843196
--- /dev/null
+++ b/drivers/net/ntnic/sensors/sensors.c
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "sensors.h"
+#include "ntlog.h"
+
+void sensor_deinit(struct nt_sensor_group *sg)
+{
+ if (sg) {
+ if (sg->sensor)
+ free(sg->sensor);
+ if (sg->monitor)
+ free(sg->monitor);
+ free(sg);
+ }
+}
+
+struct nt_adapter_sensor *
+allocate_sensor(uint8_t adapter_or_port_index, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum nt_sensor_event_alarm_e event_alarm,
+ enum sensor_mon_sign si)
+{
+ struct nt_adapter_sensor *sensor =
+ (struct nt_adapter_sensor *)malloc(sizeof(struct nt_adapter_sensor));
+ if (sensor == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor is NULL", __func__);
+ return NULL;
+ }
+
+ sensor->alarm = event_alarm;
+ sensor->m_enable_alarm = true;
+ sensor->m_intf_no = 0xFF;
+ sensor->m_adapter_no = 0xFF;
+ sensor->si = si;
+
+ sensor->info.source = ssrc;
+ sensor->info.source_index = adapter_or_port_index;
+ sensor->info.sensor_index = index;
+ sensor->info.type = type;
+ sensor->info.sub_type = NT_SENSOR_SUBTYPE_NA;
+ sensor->info.state = NT_SENSOR_STATE_INITIALIZING;
+ sensor->info.value = NT_SENSOR_NAN;
+ sensor->info.value_lowest = NT_SENSOR_NAN;
+ sensor->info.value_highest = NT_SENSOR_NAN;
+ memset(sensor->info.name, 0, NT_INFO_SENSOR_NAME);
+ memcpy(sensor->info.name, p_name,
+ (strlen(p_name) > NT_INFO_SENSOR_NAME) ? NT_INFO_SENSOR_NAME :
+ strlen(p_name));
+ sensor->info.name[NT_INFO_SENSOR_NAME] = '\0';
+
+ return sensor;
+}
+
+void update_sensor_value(struct nt_adapter_sensor *sensor, int32_t value)
+{
+ if (sensor == NULL)
+ return;
+ sensor->info.value = value;
+ if (sensor->info.value_highest < value ||
+ (unsigned int)sensor->info.value_highest == NT_SENSOR_NAN)
+ sensor->info.value_highest = value;
+ if (sensor->info.value_lowest > value ||
+ (unsigned int)sensor->info.value_lowest == NT_SENSOR_NAN)
+ sensor->info.value_lowest = value;
+}
+
+struct nt_adapter_sensor *
+allocate_sensor_by_description(uint8_t adapter_or_port_index,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *descr)
+{
+ struct nt_adapter_sensor *sensor =
+ (struct nt_adapter_sensor *)malloc(sizeof(struct nt_adapter_sensor));
+ if (sensor == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor is NULL", __func__);
+ return NULL;
+ }
+
+ sensor->alarm = descr->event_alarm;
+ sensor->m_enable_alarm = true;
+ sensor->m_intf_no = 0xFF;
+ sensor->m_adapter_no = 0xFF;
+ sensor->si = SENSOR_MON_UNSIGNED;
+
+ sensor->info.source_index = adapter_or_port_index;
+ sensor->info.source = ssrc;
+ sensor->info.type = descr->type;
+ sensor->info.sensor_index = descr->index;
+ memset(sensor->info.name, 0, NT_INFO_SENSOR_NAME);
+ memcpy(sensor->info.name, descr->name,
+ (strlen(descr->name) > NT_INFO_SENSOR_NAME) ?
+ NT_INFO_SENSOR_NAME :
+ strlen(descr->name));
+ sensor->info.name[NT_INFO_SENSOR_NAME] = '\0';
+
+ return sensor;
+}
+
+void init_sensor_group(struct nt_sensor_group *sg)
+{
+ /* Set all pointers to NULL */
+ sg->sensor = NULL;
+ sg->monitor = NULL;
+ sg->next = NULL;
+ sg->read = NULL;
+ sg->conv_func = NULL;
+}
+
+/* Getters */
+int32_t get_value(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.value;
+};
+
+int32_t get_lowest(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.value_lowest;
+};
+
+int32_t get_highest(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.value_highest;
+};
+
+char *get_name(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.name;
+};
+
+/* Conversion functions */
+int null_signed(uint32_t p_sensor_result)
+{
+ return (int16_t)p_sensor_result;
+}
+
+int null_unsigned(uint32_t p_sensor_result)
+{
+ return (uint16_t)p_sensor_result;
+}
+
+/*
+ * ******************************************************************************
+ * For EXAR7724: Convert a read Vch value to Napatech internal representation
+ * Doc: Vout = ReadVal * 0.015 (PRESCALE is accounted for)
+ * ******************************************************************************
+ */
+int exar7724_vch(uint32_t p_sensor_result)
+{
+ return p_sensor_result * 15; /* NT unit: 1mV */
+}
+
+/*
+ * ******************************************************************************
+ * For EXAR7724: Convert a read Vin value to Napatech internal representation
+ * Doc: Vout = ReadVal * 0.0125
+ * ******************************************************************************
+ */
+int exar7724_vin(uint32_t p_sensor_result)
+{
+ return (p_sensor_result * 25) / 2; /* NT unit: 1mV */
+}
+
+/*
+ * ******************************************************************************
+ * For EXAR7724: Convert a read Tj value to Napatech internal representation
+ * Doc: Temp (in Kelvin) = (((ReadVal * 10mV) - 600mV) / (2mV/K)) + 300K =
+ * = ReadVal * 5K
+ * ******************************************************************************
+ */
+int exar7724_tj(uint32_t p_sensor_result)
+{
+ /*
+ * A value of 2730 is used instead of 2732 which is more correct but since
+ * the temperature step is 5 degrees it is more natural to show these steps
+ */
+ return p_sensor_result * 50 - 2730; /* NT unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * Conversion function for Linear Tecnology Linear_5s_11s format.
+ * The functions returns Y * 2**N, where N = b[15:11] is a 5-bit two's complement
+ * integer and Y = b[10:0] is an 11-bit two's complement integer.
+ * The multiplier value is used for scaling to Napatech units.
+ * ******************************************************************************
+ */
+static int conv5s_11s(uint16_t value, int multiplier)
+{
+ int n, y;
+
+ y = value & 0x07FF;
+
+ if (value & 0x0400)
+ y -= 0x0800; /* The MSBit is a sign bit */
+
+ n = (value >> 11) & 0x1F;
+
+ if (n & 0x10)
+ n -= 0x20; /* The MSBit is a sign bit */
+
+ y *= multiplier;
+
+ if (n > 0)
+ y *= (1 << n);
+
+ else if (n < 0)
+ y /= (1 << (-n));
+
+ return y;
+}
+
+/*
+ * ******************************************************************************
+ * Temperature conversion from Linear_5s_11s format.
+ * ******************************************************************************
+ */
+int ltm4676_tj(uint32_t p_sensor_result)
+{
+ return (uint16_t)conv5s_11s(p_sensor_result, 10); /* NT unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * For MP2886a: Convert a read Tj value to Napatech internal representation
+ * ******************************************************************************
+ */
+int mp2886a_tj(uint32_t p_sensor_result)
+{
+ /*
+ * MPS-2886p: READ_TEMPERATURE (register 0x8Dh)
+ * READ_TEMPERATURE is a 2-byte, unsigned integer.
+ */
+ return (uint16_t)p_sensor_result; /* NT unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * For MAX6642: Convert a read temperature value to Napatech internal representation
+ * ******************************************************************************
+ */
+int max6642_t(uint32_t p_sensor_result)
+{
+ if ((p_sensor_result >> 8) == 0xFF)
+ return NT_SENSOR_NAN;
+
+ /* The six lower bits are not used */
+ return (int)(((p_sensor_result >> 6) * 5) /
+ 2); /* NT unit: 0.25 deg, Native unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * For DS1775: Convert a read temperature value to Napatech internal representation
+ * ******************************************************************************
+ */
+int ds1775_t(uint32_t p_sensor_result)
+{
+ return (p_sensor_result * 10) /
+ 256; /* NT unit: 0.1 deg, Native unit: 1/256 C */
+}
+
+/*
+ * ******************************************************************************
+ * For FAN: Convert a tick count to RPM
+ * NT unit: RPM, Native unit: 2 ticks/revolution
+ * ******************************************************************************
+ */
+int fan(uint32_t p_sensor_result)
+{
+ return (p_sensor_result * 60U / 4);
+}
diff --git a/drivers/net/ntnic/sensors/sensors.h b/drivers/net/ntnic/sensors/sensors.h
new file mode 100644
index 0000000000..1424b8bc83
--- /dev/null
+++ b/drivers/net/ntnic/sensors/sensors.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SENSORS_H
+#define _SENSORS_H
+
+#include "sensor_types.h"
+#include "stream_info.h"
+#include "nthw_platform_drv.h"
+#include "nthw_drv.h"
+#include "nthw_spi_v3.h"
+#include "nthw_fpga_model.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "avr_intf.h"
+
+enum nt_sensor_event_alarm_e {
+ NT_SENSOR_ENABLE_ALARM,
+ NT_SENSOR_LOG_ALARM,
+ NT_SENSOR_DISABLE_ALARM,
+};
+
+/*
+ * Sensor Class types
+ */
+enum nt_sensor_class_e {
+ NT_SENSOR_CLASS_FPGA =
+ 0, /* Class for FPGA based sensors e.g FPGA temperature */
+ NT_SENSOR_CLASS_MCU =
+ 1, /* Class for MCU based sensors e.g MCU temperature */
+ NT_SENSOR_CLASS_PSU =
+ 2, /* Class for PSU based sensors e.g PSU temperature */
+ NT_SENSOR_CLASS_PCB =
+ 3, /* Class for PCB based sensors e.g PCB temperature */
+ NT_SENSOR_CLASS_NIM =
+ 4, /* Class for NIM based sensors e.g NIM temperature */
+ NT_SENSOR_CLASS_ANY = 5, /* Class for ANY sensors e.g any sensors */
+};
+
+typedef enum nt_sensor_class_e nt_sensor_class_t;
+
+/*
+ * Port of the sensor class
+ */
+struct nt_adapter_sensor {
+ uint8_t m_adapter_no;
+ uint8_t m_intf_no;
+ uint8_t fpga_idx; /* for AVR sensors */
+ enum sensor_mon_sign si;
+ struct nt_info_sensor_s info;
+ enum nt_sensor_event_alarm_e alarm;
+ bool m_enable_alarm;
+};
+
+struct nt_fpga_sensor_monitor {
+ nt_fpga_t *fpga;
+ nt_module_t *mod;
+
+ nt_register_t *reg;
+ nt_field_t **fields;
+ uint8_t fields_num;
+};
+
+/*
+ * Sensor description.
+ * Describe the static behavior of the sensor.
+ */
+struct nt_adapter_sensor_description {
+ enum nt_sensor_type_e type; /* Sensor type. */
+ enum nt_sensor_sub_type_e sub_type; /* Sensor subtype (if any applicable) */
+ unsigned int index; /* Sensor group index. */
+ enum nt_sensor_event_alarm_e event_alarm; /* Enable/Disable event alarm */
+ char name[20]; /* Sensor name. */
+};
+
+struct nt_sensor_group {
+ struct nt_adapter_sensor *sensor;
+ struct nt_fpga_sensor_monitor *monitor;
+ void (*read)(struct nt_sensor_group *sg, nthw_spis_t *t_spi);
+
+ /* conv params are needed to call current conversion functions */
+ int (*conv_func)(uint32_t p_sensor_result);
+ /* i2c interface for NIM sensors */
+
+ struct nt_sensor_group *next;
+};
+
+void init_sensor_group(struct nt_sensor_group *sg);
+
+void update_sensor_value(struct nt_adapter_sensor *sensor, int32_t value);
+
+void sensor_deinit(struct nt_sensor_group *sg);
+
+/* getters */
+int32_t get_value(struct nt_sensor_group *sg);
+int32_t get_lowest(struct nt_sensor_group *sg);
+int32_t get_highest(struct nt_sensor_group *sg);
+char *get_name(struct nt_sensor_group *sg);
+
+struct nt_adapter_sensor *
+allocate_sensor(uint8_t adapter_or_port_index, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum nt_sensor_event_alarm_e event_alarm,
+ enum sensor_mon_sign si);
+struct nt_adapter_sensor *
+allocate_sensor_by_description(uint8_t adapter_or_port_index,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *descr);
+
+/* conversion functions */
+int null_signed(uint32_t p_sensor_result);
+int null_unsigned(uint32_t p_sensor_result);
+int exar7724_tj(uint32_t p_sensor_result);
+int max6642_t(uint32_t p_sensor_result);
+int ds1775_t(uint32_t p_sensor_result);
+int ltm4676_tj(uint32_t p_sensor_result);
+int exar7724_vch(uint32_t p_sensor_result);
+int exar7724_vin(uint32_t p_sensor_result);
+int mp2886a_tj(uint32_t p_sensor_result);
+int fan(uint32_t p_sensor_result);
+
+#endif /* _SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/stream_info.h b/drivers/net/ntnic/sensors/stream_info.h
new file mode 100644
index 0000000000..b94231fd8b
--- /dev/null
+++ b/drivers/net/ntnic/sensors/stream_info.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _STREAM_INFO_H
+#define _STREAM_INFO_H
+
+#include "sensor_types.h"
+
+#include <stdint.h>
+
+/*
+ * This structure will return the sensor specific information
+ *
+ * The units used for the fields: value, value_lowest, value_highest, limit_low and
+ * limit_high depend on the type field. See @ref nt_sensor_type_e.
+ *
+ * For the limit_low and limit_high fields the following applies:\n
+ * If the sensor is located in a NIM (Network Interface Module), the limits are read
+ * from the NIM module via the DMI (Diagnostic Monitoring Interface) from the alarm
+ * and warning thresholds section, and the units are changed to internal representation.
+ * Only the alarm thresholds are used and are read only once during initialization.
+ * The limits cannot be changed.
+ *
+ * The value field is updated internally on a regular basis and is also based on a
+ * value read from the NIM which is also changed to internal representation.
+ *
+ * Not all NIM types support DMI data, and its presence must be determined by reading an
+ * option flag. In general, a NIM can read out: temperature, supply voltage,
+ * TX bias, TX optical power and RX optical power but not all NIM types support all
+ * 5 values.
+ *
+ * If external calibration is used (most NIM use internal calibration), both the
+ * current value and the threshold values are subjected to the specified calibration
+ * along with the change to internal calibration.
+ */
+#define NT_INFO_SENSOR_NAME 50
+struct nt_info_sensor_s {
+ enum nt_sensor_source_e
+ source; /* The source of the sensor (port or adapter on which the sensor resides) */
+ /*
+ * The source index - the adapter number for adapter sensors and port number for port
+ * sensors
+ */
+ uint32_t source_index;
+ /*
+ * The sensor index within the source index (sensor number on the adapter or sensor number
+ * on the port)
+ */
+ uint32_t sensor_index;
+ enum nt_sensor_type_e type; /* The sensor type */
+ enum nt_sensor_sub_type_e sub_type; /* The sensor subtype (if applicable) */
+ enum nt_sensor_state_e state; /* The current state (normal or alarm) */
+ int32_t value; /* The current value */
+ int32_t value_lowest; /* The lowest value registered */
+ int32_t value_highest; /* The highest value registered */
+ char name[NT_INFO_SENSOR_NAME + 1]; /* The sensor name */
+ enum nt_adapter_type_e
+ adapter_type; /* The adapter type where the sensor resides */
+};
+
+/* The NT200A02 adapter sensor id's */
+enum nt_sensors_adapter_nt200a02_e {
+ /* Public sensors (Level 0) */
+ NT_SENSOR_NT200A02_FPGA_TEMP, /* FPGA temperature sensor */
+ NT_SENSOR_NT200A02_FAN_SPEED, /* FAN speed sensor */
+
+ NT_SENSOR_NT200A02_MCU_TEMP,
+ NT_SENSOR_NT200A02_PSU0_TEMP, /* Power supply 0 temperature sensor */
+ NT_SENSOR_NT200A02_PSU1_TEMP, /* Power supply 1 temperature sensor */
+ NT_SENSOR_NT200A02_PCB_TEMP, /* PCB temperature sensor */
+
+ /* Diagnostic sensors (Level 1) */
+ /* Total power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_NT200A02_POWER,
+ /* FPGA power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_FPGA_POWER,
+ /* DDR4 RAM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_DDR4_POWER,
+ /* NIM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_NIM_POWER,
+
+ NT_SENSOR_NT200A02_L1_MAX, /* Number of NT200A01 level 0,1 board sensors */
+};
+
+#endif
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 4/8] net/ntnic: adds flow related FPGA functionality
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
2023-08-16 13:25 ` [PATCH 2/8] net/ntnic: adds core registers and fpga functionality Mykola Kostenok
2023-08-16 13:25 ` [PATCH 3/8] net/ntnic: adds NT200A02 adapter support Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 13:25 ` [PATCH 5/8] net/ntnic: adds FPGA abstraction layer Mykola Kostenok
` (17 subsequent siblings)
20 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
The PMD will control the registers used for flow programming,
and this commit adds support for this.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/ntnic/meson.build | 21 +
.../ntnic/nthw/flow_filter/flow_nthw_cat.c | 1107 ++++++++++++++++
.../ntnic/nthw/flow_filter/flow_nthw_cat.h | 372 ++++++
.../ntnic/nthw/flow_filter/flow_nthw_csu.c | 146 +++
.../ntnic/nthw/flow_filter/flow_nthw_csu.h | 42 +
.../ntnic/nthw/flow_filter/flow_nthw_flm.c | 1140 +++++++++++++++++
.../ntnic/nthw/flow_filter/flow_nthw_flm.h | 422 ++++++
.../ntnic/nthw/flow_filter/flow_nthw_hfu.c | 293 +++++
.../ntnic/nthw/flow_filter/flow_nthw_hfu.h | 100 ++
.../ntnic/nthw/flow_filter/flow_nthw_hsh.c | 254 ++++
.../ntnic/nthw/flow_filter/flow_nthw_hsh.h | 81 ++
.../ntnic/nthw/flow_filter/flow_nthw_hst.c | 202 +++
.../ntnic/nthw/flow_filter/flow_nthw_hst.h | 72 ++
.../ntnic/nthw/flow_filter/flow_nthw_ifr.c | 93 ++
.../ntnic/nthw/flow_filter/flow_nthw_ifr.h | 39 +
.../ntnic/nthw/flow_filter/flow_nthw_info.c | 341 +++++
.../ntnic/nthw/flow_filter/flow_nthw_info.h | 104 ++
.../ntnic/nthw/flow_filter/flow_nthw_ioa.c | 234 ++++
.../ntnic/nthw/flow_filter/flow_nthw_ioa.h | 80 ++
.../net/ntnic/nthw/flow_filter/flow_nthw_km.c | 686 ++++++++++
.../net/ntnic/nthw/flow_filter/flow_nthw_km.h | 224 ++++
.../ntnic/nthw/flow_filter/flow_nthw_pdb.c | 230 ++++
.../ntnic/nthw/flow_filter/flow_nthw_pdb.h | 84 ++
.../ntnic/nthw/flow_filter/flow_nthw_qsl.c | 355 +++++
.../ntnic/nthw/flow_filter/flow_nthw_qsl.h | 121 ++
.../ntnic/nthw/flow_filter/flow_nthw_rmc.c | 112 ++
.../ntnic/nthw/flow_filter/flow_nthw_rmc.h | 40 +
.../ntnic/nthw/flow_filter/flow_nthw_roa.c | 294 +++++
.../ntnic/nthw/flow_filter/flow_nthw_roa.h | 109 ++
.../ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c | 132 ++
.../ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h | 53 +
.../ntnic/nthw/flow_filter/flow_nthw_slc.c | 109 ++
.../ntnic/nthw/flow_filter/flow_nthw_slc.h | 46 +
.../ntnic/nthw/flow_filter/flow_nthw_slc_lr.c | 109 ++
.../ntnic/nthw/flow_filter/flow_nthw_slc_lr.h | 46 +
.../ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c | 394 ++++++
.../ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h | 72 ++
.../ntnic/nthw/flow_filter/flow_nthw_tx_ins.c | 96 ++
.../ntnic/nthw/flow_filter/flow_nthw_tx_ins.h | 42 +
.../ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c | 165 +++
.../ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h | 70 +
41 files changed, 8732 insertions(+)
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 383ff15390..c184d5d4b5 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -17,6 +17,7 @@ includes = [
include_directories('nthw'),
include_directories('nthw/core'),
include_directories('nthw/supported'),
+ include_directories('nthw/flow_filter'),
include_directories('sensors'),
include_directories('sensors/avr_sensors'),
include_directories('sensors/board_sensors'),
@@ -58,6 +59,26 @@ sources = files(
'nthw/core/nthw_spim.c',
'nthw/core/nthw_spis.c',
'nthw/core/nthw_tsm.c',
+ 'nthw/flow_filter/flow_nthw_cat.c',
+ 'nthw/flow_filter/flow_nthw_csu.c',
+ 'nthw/flow_filter/flow_nthw_flm.c',
+ 'nthw/flow_filter/flow_nthw_hfu.c',
+ 'nthw/flow_filter/flow_nthw_hsh.c',
+ 'nthw/flow_filter/flow_nthw_hst.c',
+ 'nthw/flow_filter/flow_nthw_ifr.c',
+ 'nthw/flow_filter/flow_nthw_info.c',
+ 'nthw/flow_filter/flow_nthw_ioa.c',
+ 'nthw/flow_filter/flow_nthw_km.c',
+ 'nthw/flow_filter/flow_nthw_pdb.c',
+ 'nthw/flow_filter/flow_nthw_qsl.c',
+ 'nthw/flow_filter/flow_nthw_rmc.c',
+ 'nthw/flow_filter/flow_nthw_roa.c',
+ 'nthw/flow_filter/flow_nthw_rpp_lr.c',
+ 'nthw/flow_filter/flow_nthw_slc.c',
+ 'nthw/flow_filter/flow_nthw_slc_lr.c',
+ 'nthw/flow_filter/flow_nthw_tx_cpy.c',
+ 'nthw/flow_filter/flow_nthw_tx_ins.c',
+ 'nthw/flow_filter/flow_nthw_tx_rpl.c',
'nthw/nthw_fpga_model.c',
'nthw/nthw_dbs.c',
'nthw/nthw_epp.c',
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c
new file mode 100644
index 0000000000..91376363c1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c
@@ -0,0 +1,1107 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_cat.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+struct cat_nthw *cat_nthw_new(void)
+{
+ struct cat_nthw *p = malloc(sizeof(struct cat_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void cat_nthw_delete(struct cat_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+void cat_nthw_set_debug_mode(struct cat_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_cat, n_debug_mode);
+}
+
+int cat_nthw_init(struct cat_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_CAT, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Cat %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_cat = p_mod;
+
+ p->m_km_if_cnt = fpga_get_product_param(p->mp_fpga, NT_CAT_KM_IF_CNT, -1);
+
+ /* CFN */
+ p->mp_cfn_ctrl = module_get_register(p->m_cat, CAT_CFN_CTRL);
+ p->mp_cfn_addr = register_get_field(p->mp_cfn_ctrl, CAT_CFN_CTRL_ADR);
+ p->mp_cfn_cnt = register_get_field(p->mp_cfn_ctrl, CAT_CFN_CTRL_CNT);
+ p->mp_cfn_data = module_get_register(p->m_cat, CAT_CFN_DATA);
+ p->mp_cfn_data_enable =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ENABLE);
+ p->mp_cfn_data_inv = register_get_field(p->mp_cfn_data, CAT_CFN_DATA_INV);
+ p->mp_cfn_data_ptc_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_INV);
+ p->mp_cfn_data_ptc_isl =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_ISL);
+ p->mp_cfn_data_ptc_mac =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_MAC);
+ p->mp_cfn_data_ptc_l2 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L2);
+ p->mp_cfn_data_ptc_vn_tag =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_VNTAG);
+ p->mp_cfn_data_ptc_vlan =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_VLAN);
+ p->mp_cfn_data_ptc_mpls =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_MPLS);
+ p->mp_cfn_data_ptc_l3 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L3);
+ p->mp_cfn_data_ptc_frag =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_FRAG);
+ p->mp_cfn_data_ptc_ip_prot =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_IP_PROT);
+ p->mp_cfn_data_ptc_l4 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L4);
+ p->mp_cfn_data_ptc_tunnel =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TUNNEL);
+ p->mp_cfn_data_ptc_tnl_l2 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L2);
+ p->mp_cfn_data_ptc_tnl_vlan =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_VLAN);
+ p->mp_cfn_data_ptc_tnl_mpls =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_MPLS);
+ p->mp_cfn_data_ptc_tnl_l3 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L3);
+ p->mp_cfn_data_ptc_tnl_frag =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_FRAG);
+ p->mp_cfn_data_ptc_tnl_ip_prot =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_IP_PROT);
+ p->mp_cfn_data_ptc_tnl_l4 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L4);
+ p->mp_cfn_data_err_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_INV);
+ p->mp_cfn_data_err_cv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_CV);
+ p->mp_cfn_data_err_fcs =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_FCS);
+ p->mp_cfn_data_err_trunc =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TRUNC);
+ p->mp_cfn_data_mac_port =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_MAC_PORT);
+ p->mp_cfn_data_pm_cmp =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_CMP);
+ p->mp_cfn_data_pm_dct =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_DCT);
+ p->mp_cfn_data_pm_ext_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_EXT_INV);
+ p->mp_cfn_data_pm_cmb =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_CMB);
+ p->mp_cfn_data_pm_and_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_AND_INV);
+ p->mp_cfn_data_pm_or_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_OR_INV);
+ p->mp_cfn_data_pm_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_INV);
+ p->mp_cfn_data_lc = register_get_field(p->mp_cfn_data, CAT_CFN_DATA_LC);
+ p->mp_cfn_data_lc_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_LC_INV);
+
+ if (p->m_km_if_cnt == -1) {
+ p->mp_cfn_data_km0_or =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_KM_OR);
+ } else {
+ p->mp_cfn_data_km0_or =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_KM0_OR);
+ p->mp_cfn_data_km1_or =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_KM1_OR);
+ }
+
+ if (p->m_km_if_cnt < 0) {
+ /* KCE */
+ p->mp_kce_ctrl[0] = module_get_register(p->m_cat, CAT_KCE_CTRL);
+ p->mp_kce_addr[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE_CTRL_ADR);
+ p->mp_kce_cnt[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE_CTRL_CNT);
+ p->mp_kce_data[0] = module_get_register(p->m_cat, CAT_KCE_DATA);
+ p->mp_kce_data_enable[0] =
+ register_get_field(p->mp_kce_data[0], CAT_KCE_DATA_ENABLE);
+ /* KCS */
+ p->mp_kcs_ctrl[0] = module_get_register(p->m_cat, CAT_KCS_CTRL);
+ p->mp_kcs_addr[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS_CTRL_ADR);
+ p->mp_kcs_cnt[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS_CTRL_CNT);
+ p->mp_kcs_data[0] = module_get_register(p->m_cat, CAT_KCS_DATA);
+ p->mp_kcs_data_category[0] =
+ register_get_field(p->mp_kcs_data[0], CAT_KCS_DATA_CATEGORY);
+ /* FTE */
+ p->mp_fte_ctrl[0] = module_get_register(p->m_cat, CAT_FTE_CTRL);
+ p->mp_fte_addr[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE_CTRL_ADR);
+ p->mp_fte_cnt[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE_CTRL_CNT);
+ p->mp_fte_data[0] = module_get_register(p->m_cat, CAT_FTE_DATA);
+ p->mp_fte_data_enable[0] =
+ register_get_field(p->mp_fte_data[0], CAT_FTE_DATA_ENABLE);
+ } else {
+ /* KCE 0 */
+ p->mp_kce_ctrl[0] = module_get_register(p->m_cat, CAT_KCE0_CTRL);
+ p->mp_kce_addr[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE0_CTRL_ADR);
+ p->mp_kce_cnt[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE0_CTRL_CNT);
+ p->mp_kce_data[0] = module_get_register(p->m_cat, CAT_KCE0_DATA);
+ p->mp_kce_data_enable[0] = register_get_field(p->mp_kce_data[0],
+ CAT_KCE0_DATA_ENABLE);
+ /* KCS 0 */
+ p->mp_kcs_ctrl[0] = module_get_register(p->m_cat, CAT_KCS0_CTRL);
+ p->mp_kcs_addr[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS0_CTRL_ADR);
+ p->mp_kcs_cnt[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS0_CTRL_CNT);
+ p->mp_kcs_data[0] = module_get_register(p->m_cat, CAT_KCS0_DATA);
+ p->mp_kcs_data_category[0] =
+ register_get_field(p->mp_kcs_data[0], CAT_KCS0_DATA_CATEGORY);
+ /* FTE 0 */
+ p->mp_fte_ctrl[0] = module_get_register(p->m_cat, CAT_FTE0_CTRL);
+ p->mp_fte_addr[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE0_CTRL_ADR);
+ p->mp_fte_cnt[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE0_CTRL_CNT);
+ p->mp_fte_data[0] = module_get_register(p->m_cat, CAT_FTE0_DATA);
+ p->mp_fte_data_enable[0] = register_get_field(p->mp_fte_data[0],
+ CAT_FTE0_DATA_ENABLE);
+ /* KCE 1 */
+ p->mp_kce_ctrl[1] = module_get_register(p->m_cat, CAT_KCE1_CTRL);
+ p->mp_kce_addr[1] =
+ register_get_field(p->mp_kce_ctrl[1], CAT_KCE1_CTRL_ADR);
+ p->mp_kce_cnt[1] =
+ register_get_field(p->mp_kce_ctrl[1], CAT_KCE1_CTRL_CNT);
+ p->mp_kce_data[1] = module_get_register(p->m_cat, CAT_KCE1_DATA);
+ p->mp_kce_data_enable[1] = register_get_field(p->mp_kce_data[1],
+ CAT_KCE1_DATA_ENABLE);
+ /* KCS 1 */
+ p->mp_kcs_ctrl[1] = module_get_register(p->m_cat, CAT_KCS1_CTRL);
+ p->mp_kcs_addr[1] =
+ register_get_field(p->mp_kcs_ctrl[1], CAT_KCS1_CTRL_ADR);
+ p->mp_kcs_cnt[1] =
+ register_get_field(p->mp_kcs_ctrl[1], CAT_KCS1_CTRL_CNT);
+ p->mp_kcs_data[1] = module_get_register(p->m_cat, CAT_KCS1_DATA);
+ p->mp_kcs_data_category[1] =
+ register_get_field(p->mp_kcs_data[1], CAT_KCS1_DATA_CATEGORY);
+ /* FTE 1 */
+ p->mp_fte_ctrl[1] = module_get_register(p->m_cat, CAT_FTE1_CTRL);
+ p->mp_fte_addr[1] =
+ register_get_field(p->mp_fte_ctrl[1], CAT_FTE1_CTRL_ADR);
+ p->mp_fte_cnt[1] =
+ register_get_field(p->mp_fte_ctrl[1], CAT_FTE1_CTRL_CNT);
+ p->mp_fte_data[1] = module_get_register(p->m_cat, CAT_FTE1_DATA);
+ p->mp_fte_data_enable[1] = register_get_field(p->mp_fte_data[1],
+ CAT_FTE1_DATA_ENABLE);
+ }
+
+ /* CTE */
+ p->mp_cte_ctrl = module_get_register(p->m_cat, CAT_CTE_CTRL);
+ p->mp_cte_addr = register_get_field(p->mp_cte_ctrl, CAT_CTE_CTRL_ADR);
+ p->mp_cte_cnt = register_get_field(p->mp_cte_ctrl, CAT_CTE_CTRL_CNT);
+ p->mp_cte_data = module_get_register(p->m_cat, CAT_CTE_DATA);
+ p->mp_cte_data_col =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_COL_ENABLE);
+ p->mp_cte_data_cor =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_COR_ENABLE);
+ p->mp_cte_data_hsh =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_HSH_ENABLE);
+ p->mp_cte_data_qsl =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_QSL_ENABLE);
+ p->mp_cte_data_ipf =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_IPF_ENABLE);
+ p->mp_cte_data_slc =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_SLC_ENABLE);
+ p->mp_cte_data_pdb =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_PDB_ENABLE);
+ p->mp_cte_data_msk =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_MSK_ENABLE);
+ p->mp_cte_data_hst =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_HST_ENABLE);
+ p->mp_cte_data_epp =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_EPP_ENABLE);
+ p->mp_cte_data_tpe =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_TPE_ENABLE);
+ p->mp_cte_data_rrb =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_RRB_ENABLE);
+ /* CTS */
+ p->mp_cts_ctrl = module_get_register(p->m_cat, CAT_CTS_CTRL);
+ p->mp_cts_addr = register_get_field(p->mp_cts_ctrl, CAT_CTS_CTRL_ADR);
+ p->mp_cts_cnt = register_get_field(p->mp_cts_ctrl, CAT_CTS_CTRL_CNT);
+ p->mp_cts_data = module_get_register(p->m_cat, CAT_CTS_DATA);
+ p->mp_cts_data_cat_a = register_get_field(p->mp_cts_data, CAT_CTS_DATA_CAT_A);
+ p->mp_cts_data_cat_b = register_get_field(p->mp_cts_data, CAT_CTS_DATA_CAT_B);
+ /* COT */
+ p->mp_cot_ctrl = module_get_register(p->m_cat, CAT_COT_CTRL);
+ p->mp_cot_addr = register_get_field(p->mp_cot_ctrl, CAT_COT_CTRL_ADR);
+ p->mp_cot_cnt = register_get_field(p->mp_cot_ctrl, CAT_COT_CTRL_CNT);
+ p->mp_cot_data = module_get_register(p->m_cat, CAT_COT_DATA);
+ p->mp_cot_data_color = register_get_field(p->mp_cot_data, CAT_COT_DATA_COLOR);
+ p->mp_cot_data_km = register_get_field(p->mp_cot_data, CAT_COT_DATA_KM);
+ p->mp_cot_data_nfv_sb =
+ register_query_field(p->mp_cot_data, CAT_COT_DATA_NFV_SB);
+ /* CCT */
+ p->mp_cct_ctrl = module_get_register(p->m_cat, CAT_CCT_CTRL);
+ p->mp_cct_addr = register_get_field(p->mp_cct_ctrl, CAT_CCT_CTRL_ADR);
+ p->mp_cct_cnt = register_get_field(p->mp_cct_ctrl, CAT_CCT_CTRL_CNT);
+ p->mp_cct_data = module_get_register(p->m_cat, CAT_CCT_DATA);
+ p->mp_cct_data_color = register_get_field(p->mp_cct_data, CAT_CCT_DATA_COLOR);
+ p->mp_cct_data_km = register_get_field(p->mp_cct_data, CAT_CCT_DATA_KM);
+ /* EXO */
+ p->mp_exo_ctrl = module_get_register(p->m_cat, CAT_EXO_CTRL);
+ p->mp_exo_addr = register_get_field(p->mp_exo_ctrl, CAT_EXO_CTRL_ADR);
+ p->mp_exo_cnt = register_get_field(p->mp_exo_ctrl, CAT_EXO_CTRL_CNT);
+ p->mp_exo_data = module_get_register(p->m_cat, CAT_EXO_DATA);
+ p->mp_exo_data_dyn = register_get_field(p->mp_exo_data, CAT_EXO_DATA_DYN);
+ p->mp_exo_data_ofs = register_get_field(p->mp_exo_data, CAT_EXO_DATA_OFS);
+ /* RCK */
+ p->mp_rck_ctrl = module_get_register(p->m_cat, CAT_RCK_CTRL);
+ p->mp_rck_addr = register_get_field(p->mp_rck_ctrl, CAT_RCK_CTRL_ADR);
+ p->mp_rck_cnt = register_get_field(p->mp_rck_ctrl, CAT_RCK_CTRL_CNT);
+ p->mp_rck_data = module_get_register(p->m_cat, CAT_RCK_DATA);
+ /* LEN */
+ p->mp_len_ctrl = module_get_register(p->m_cat, CAT_LEN_CTRL);
+ p->mp_len_addr = register_get_field(p->mp_len_ctrl, CAT_LEN_CTRL_ADR);
+ p->mp_len_cnt = register_get_field(p->mp_len_ctrl, CAT_LEN_CTRL_CNT);
+ p->mp_len_data = module_get_register(p->m_cat, CAT_LEN_DATA);
+ p->mp_len_data_lower = register_get_field(p->mp_len_data, CAT_LEN_DATA_LOWER);
+ p->mp_len_data_upper = register_get_field(p->mp_len_data, CAT_LEN_DATA_UPPER);
+ p->mp_len_data_dyn1 = register_get_field(p->mp_len_data, CAT_LEN_DATA_DYN1);
+ p->mp_len_data_dyn2 = register_get_field(p->mp_len_data, CAT_LEN_DATA_DYN2);
+ p->mp_len_data_inv = register_get_field(p->mp_len_data, CAT_LEN_DATA_INV);
+
+ p->mp_cfn_data_ptc_cfp =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_CFP);
+ p->mp_cfn_data_err_l3_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_L3_CS);
+ p->mp_cfn_data_err_l4_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_L4_CS);
+ p->mp_cfn_data_err_tnl_l3_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_L3_CS);
+ p->mp_cfn_data_err_tnl_l4_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_L4_CS);
+ p->mp_cfn_data_err_ttl_exp =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TTL_EXP);
+ p->mp_cfn_data_err_tnl_ttl_exp =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_TTL_EXP);
+
+ p->mp_kcc_ctrl = module_query_register(p->m_cat, CAT_KCC_CTRL);
+ if (p->mp_kcc_ctrl != NULL) {
+ p->mp_kcc_addr =
+ register_query_field(p->mp_kcc_ctrl, CAT_KCC_CTRL_ADR);
+ p->mp_kcc_cnt =
+ register_query_field(p->mp_kcc_ctrl, CAT_KCC_CTRL_CNT);
+ }
+ p->mp_kcc_data = module_query_register(p->m_cat, CAT_KCC_DATA);
+ if (p->mp_kcc_data != NULL) {
+ p->mp_kcc_data_key =
+ register_query_field(p->mp_kcc_data, CAT_KCC_DATA_KEY);
+ p->mp_kcc_data_category =
+ register_query_field(p->mp_kcc_data, CAT_KCC_DATA_CATEGORY);
+ p->mp_kcc_data_id =
+ register_query_field(p->mp_kcc_data, CAT_KCC_DATA_ID);
+ }
+
+ p->mp_cce_ctrl = module_query_register(p->m_cat, CAT_CCE_CTRL);
+ if (p->mp_cce_ctrl != NULL) {
+ p->mp_cce_addr =
+ register_query_field(p->mp_cce_ctrl, CAT_CCE_CTRL_ADR);
+ p->mp_cce_cnt =
+ register_query_field(p->mp_cce_ctrl, CAT_CCE_CTRL_CNT);
+ }
+ p->mp_cce_data = module_query_register(p->m_cat, CAT_CCE_DATA);
+ if (p->mp_cce_data != NULL) {
+ p->mp_cce_data_imm =
+ register_query_field(p->mp_cce_data, CAT_CCE_DATA_IMM);
+ p->mp_cce_data_ind =
+ register_query_field(p->mp_cce_data, CAT_CCE_DATA_IND);
+ }
+
+ p->mp_ccs_ctrl = module_query_register(p->m_cat, CAT_CCS_CTRL);
+ if (p->mp_ccs_ctrl != NULL) {
+ p->mp_ccs_addr =
+ register_query_field(p->mp_ccs_ctrl, CAT_CCS_CTRL_ADR);
+ p->mp_ccs_cnt =
+ register_query_field(p->mp_ccs_ctrl, CAT_CCS_CTRL_CNT);
+ }
+ p->mp_ccs_data = module_query_register(p->m_cat, CAT_CCS_DATA);
+ if (p->mp_ccs_data != NULL) {
+ p->mp_ccs_data_cor_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_COR_EN);
+ p->mp_ccs_data_cor =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_COR);
+ p->mp_ccs_data_hsh_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HSH_EN);
+ p->mp_ccs_data_hsh =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HSH);
+ p->mp_ccs_data_qsl_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_QSL_EN);
+ p->mp_ccs_data_qsl =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_QSL);
+ p->mp_ccs_data_ipf_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_IPF_EN);
+ p->mp_ccs_data_ipf =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_IPF);
+ p->mp_ccs_data_slc_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SLC_EN);
+ p->mp_ccs_data_slc =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SLC);
+ p->mp_ccs_data_pdb_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_PDB_EN);
+ p->mp_ccs_data_pdb =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_PDB);
+ p->mp_ccs_data_msk_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_MSK_EN);
+ p->mp_ccs_data_msk =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_MSK);
+ p->mp_ccs_data_hst_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HST_EN);
+ p->mp_ccs_data_hst =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HST);
+ p->mp_ccs_data_epp_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_EPP_EN);
+ p->mp_ccs_data_epp =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_EPP);
+ p->mp_ccs_data_tpe_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_TPE_EN);
+ p->mp_ccs_data_tpe =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_TPE);
+ p->mp_ccs_data_rrb_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_RRB_EN);
+ p->mp_ccs_data_rrb =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_RRB);
+ p->mp_ccs_data_sb0_type =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB0_TYPE);
+ p->mp_ccs_data_sb0_data =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB0_DATA);
+ p->mp_ccs_data_sb1_type =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB1_TYPE);
+ p->mp_ccs_data_sb1_data =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB1_DATA);
+ p->mp_ccs_data_sb2_type =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB2_TYPE);
+ p->mp_ccs_data_sb2_data =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB2_DATA);
+ }
+
+ return 0;
+}
+
+/* CFN */
+void cat_nthw_cfn_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_addr, val);
+}
+
+void r(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_cnt, val);
+}
+
+void cat_nthw_cfn_enable(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_enable, val);
+}
+
+void cat_nthw_cfn_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_inv, val);
+}
+
+void cat_nthw_cfn_ptc_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_inv, val);
+}
+
+void cat_nthw_cfn_ptc_isl(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_isl, val);
+}
+
+void cat_nthw_cfn_ptc_mac(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_mac, val);
+}
+
+void cat_nthw_cfn_ptc_l2(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_l2, val);
+}
+
+void cat_nthw_cfn_ptc_vn_tag(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_vn_tag, val);
+}
+
+void cat_nthw_cfn_ptc_vlan(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_vlan, val);
+}
+
+void cat_nthw_cfn_ptc_mpls(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_mpls, val);
+}
+
+void cat_nthw_cfn_ptc_l3(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_l3, val);
+}
+
+void cat_nthw_cfn_ptc_frag(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_frag, val);
+}
+
+void cat_nthw_cfn_ptc_ip_prot(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_ip_prot, val);
+}
+
+void cat_nthw_cfn_ptc_l4(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_l4, val);
+}
+
+void cat_nthw_cfn_ptc_tunnel(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tunnel, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_l2(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_l2, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_vlan(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_vlan, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_mpls(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_mpls, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_l3(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_l3, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_frag(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_frag, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_ip_prot(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_ip_prot, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_l4(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_l4, val);
+}
+
+void cat_nthw_cfn_ptc_cfp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_ptc_cfp);
+ field_set_val32(p->mp_cfn_data_ptc_cfp, val);
+}
+
+void cat_nthw_cfn_err_l3_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_l3_cs);
+ field_set_val32(p->mp_cfn_data_err_l3_cs, val);
+}
+
+void cat_nthw_cfn_err_l4_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_l4_cs);
+ field_set_val32(p->mp_cfn_data_err_l4_cs, val);
+}
+
+void cat_nthw_cfn_err_tnl_l3_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_tnl_l3_cs);
+ field_set_val32(p->mp_cfn_data_err_tnl_l3_cs, val);
+}
+
+void cat_nthw_cfn_err_tnl_l4_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_tnl_l4_cs);
+ field_set_val32(p->mp_cfn_data_err_tnl_l4_cs, val);
+}
+
+void cat_nthw_cfn_err_ttl_exp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_ttl_exp);
+ field_set_val32(p->mp_cfn_data_err_ttl_exp, val);
+}
+
+void cat_nthw_cfn_err_tnl_ttl_exp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_tnl_ttl_exp);
+ field_set_val32(p->mp_cfn_data_err_tnl_ttl_exp, val);
+}
+
+void cat_nthw_cfn_err_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_inv, val);
+}
+
+void cat_nthw_cfn_err_cv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_cv, val);
+}
+
+void cat_nthw_cfn_err_fcs(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_fcs, val);
+}
+
+void cat_nthw_cfn_err_trunc(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_trunc, val);
+}
+
+void cat_nthw_cfn_mac_port(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_mac_port, val);
+}
+
+void cat_nthw_cfn_pm_cmp(const struct cat_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_cfn_data_pm_cmp, val, p->mp_cfn_data_pm_cmp->mn_words);
+}
+
+void cat_nthw_cfn_pm_dct(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_dct, val);
+}
+
+void cat_nthw_cfn_pm_ext_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_ext_inv, val);
+}
+
+void cat_nthw_cfn_pm_cmb(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_cmb, val);
+}
+
+void cat_nthw_cfn_pm_and_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_and_inv, val);
+}
+
+void cat_nthw_cfn_pm_or_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_or_inv, val);
+}
+
+void cat_nthw_cfn_pm_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_inv, val);
+}
+
+void cat_nthw_cfn_lc(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_lc, val);
+}
+
+void cat_nthw_cfn_lc_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_lc_inv, val);
+}
+
+void cat_nthw_cfn_km0_or(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_km0_or, val);
+}
+
+void cat_nthw_cfn_km1_or(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_km1_or);
+ field_set_val32(p->mp_cfn_data_km1_or, val);
+}
+
+void cat_nthw_cfn_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cfn_ctrl, 1);
+ register_flush(p->mp_cfn_data, 1);
+}
+
+void cat_nthw_kce_select(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kce_addr[index], val);
+}
+
+void cat_nthw_kce_cnt(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kce_cnt[index], val);
+}
+
+void cat_nthw_kce_enable(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kce_data_enable[index], val);
+}
+
+void cat_nthw_kce_flush(const struct cat_nthw *p, int index)
+{
+ register_flush(p->mp_kce_ctrl[index], 1);
+ register_flush(p->mp_kce_data[index], 1);
+}
+
+void cat_nthw_kcs_select(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kcs_addr[index], val);
+}
+
+void cat_nthw_kcs_cnt(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kcs_cnt[index], val);
+}
+
+void cat_nthw_kcs_category(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kcs_data_category[index], val);
+}
+
+void cat_nthw_kcs_flush(const struct cat_nthw *p, int index)
+{
+ register_flush(p->mp_kcs_ctrl[index], 1);
+ register_flush(p->mp_kcs_data[index], 1);
+}
+
+void cat_nthw_fte_select(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_fte_addr[index], val);
+}
+
+void cat_nthw_fte_cnt(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_fte_cnt[index], val);
+}
+
+void cat_nthw_fte_enable(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_fte_data_enable[index], val);
+}
+
+void cat_nthw_fte_flush(const struct cat_nthw *p, int index)
+{
+ register_flush(p->mp_fte_ctrl[index], 1);
+ register_flush(p->mp_fte_data[index], 1);
+}
+
+void cat_nthw_cte_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_addr, val);
+}
+
+void cat_nthw_cte_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_cnt, val);
+}
+
+void cat_nthw_cte_enable_col(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_col, val);
+}
+
+void cat_nthw_cte_enable_cor(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_cor, val);
+}
+
+void cat_nthw_cte_enable_hsh(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_hsh, val);
+}
+
+void cat_nthw_cte_enable_qsl(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_qsl, val);
+}
+
+void cat_nthw_cte_enable_ipf(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_ipf, val);
+}
+
+void cat_nthw_cte_enable_slc(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_slc, val);
+}
+
+void cat_nthw_cte_enable_pdb(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_pdb, val);
+}
+
+void cat_nthw_cte_enable_msk(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_msk);
+ field_set_val32(p->mp_cte_data_msk, val);
+}
+
+void cat_nthw_cte_enable_hst(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_hst);
+ field_set_val32(p->mp_cte_data_hst, val);
+}
+
+void cat_nthw_cte_enable_epp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_epp);
+ field_set_val32(p->mp_cte_data_epp, val);
+}
+
+void cat_nthw_cte_enable_tpe(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_tpe);
+ field_set_val32(p->mp_cte_data_tpe, val);
+}
+
+void cat_nthw_cte_enable_rrb(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_rrb);
+ field_set_val32(p->mp_cte_data_rrb, val);
+}
+
+void cat_nthw_cte_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cte_ctrl, 1);
+ register_flush(p->mp_cte_data, 1);
+}
+
+void cat_nthw_cts_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_addr, val);
+}
+
+void cat_nthw_cts_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_cnt, val);
+}
+
+void cat_nthw_cts_cat_a(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_data_cat_a, val);
+}
+
+void cat_nthw_cts_cat_b(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_data_cat_b, val);
+}
+
+void cat_nthw_cts_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cts_ctrl, 1);
+ register_flush(p->mp_cts_data, 1);
+}
+
+void cat_nthw_cot_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_addr, val);
+}
+
+void cat_nthw_cot_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_cnt, val);
+}
+
+void cat_nthw_cot_color(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_data_color, val);
+}
+
+void cat_nthw_cot_km(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_data_km, val);
+}
+
+void cat_nthw_cot_nfv_sb(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cot_data_nfv_sb);
+ field_set_val32(p->mp_cot_data_nfv_sb, val);
+}
+
+void cat_nthw_cot_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cot_ctrl, 1);
+ register_flush(p->mp_cot_data, 1);
+}
+
+void cat_nthw_cct_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_addr, val);
+}
+
+void cat_nthw_cct_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_cnt, val);
+}
+
+void cat_nthw_cct_color(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_data_color, val);
+}
+
+void cat_nthw_cct_km(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_data_km, val);
+}
+
+void cat_nthw_cct_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cct_ctrl, 1);
+ register_flush(p->mp_cct_data, 1);
+}
+
+void cat_nthw_exo_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_exo_addr, val);
+}
+
+void cat_nthw_exo_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_exo_cnt, val);
+}
+
+void cat_nthw_exo_dyn(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_exo_data_dyn, val);
+}
+
+void cat_nthw_exo_ofs(const struct cat_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_exo_data_ofs, val);
+}
+
+void cat_nthw_exo_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_exo_ctrl, 1);
+ register_flush(p->mp_exo_data, 1);
+}
+
+void cat_nthw_rck_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rck_addr, val);
+}
+
+void cat_nthw_rck_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rck_cnt, val);
+}
+
+void cat_nthw_rck_data(const struct cat_nthw *p, uint32_t val)
+{
+ register_set_val(p->mp_rck_data, &val, 1);
+ register_make_dirty(p->mp_rck_data);
+}
+
+void cat_nthw_rck_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_rck_ctrl, 1);
+ register_flush(p->mp_rck_data, 1);
+}
+
+void cat_nthw_len_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_addr, val);
+}
+
+void cat_nthw_len_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_cnt, val);
+}
+
+void cat_nthw_len_lower(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_lower, val);
+}
+
+void cat_nthw_len_upper(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_upper, val);
+}
+
+void cat_nthw_len_dyn1(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_dyn1, val);
+}
+
+void cat_nthw_len_dyn2(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_dyn2, val);
+}
+
+void cat_nthw_len_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_inv, val);
+}
+
+void cat_nthw_len_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_len_ctrl, 1);
+ register_flush(p->mp_len_data, 1);
+}
+
+void cat_nthw_kcc_select(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_addr);
+ field_set_val32(p->mp_kcc_addr, val);
+}
+
+void cat_nthw_kcc_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_cnt);
+ field_set_val32(p->mp_kcc_cnt, val);
+}
+
+void cat_nthw_kcc_key(const struct cat_nthw *p, uint32_t *val)
+{
+ assert(p->mp_kcc_data_key);
+ field_set_val(p->mp_kcc_data_key, val, 2);
+}
+
+void cat_nthw_kcc_category(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_data_category);
+ field_set_val32(p->mp_kcc_data_category, val);
+}
+
+void cat_nthw_kcc_id(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_data_id);
+ field_set_val32(p->mp_kcc_data_id, val);
+}
+
+void cat_nthw_kcc_flush(const struct cat_nthw *p)
+{
+ assert(p->mp_kcc_ctrl);
+ assert(p->mp_kcc_data);
+ register_flush(p->mp_kcc_ctrl, 1);
+ register_flush(p->mp_kcc_data, 1);
+}
+
+void cat_nthw_cce_select(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_addr);
+ field_set_val32(p->mp_cce_addr, val);
+}
+
+void cat_nthw_cce_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_cnt);
+ field_set_val32(p->mp_cce_cnt, val);
+}
+
+void cat_nthw_cce_data_imm(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_data_imm);
+ field_set_val32(p->mp_cce_data_imm, val);
+}
+
+void cat_nthw_cce_data_ind(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_data_ind);
+ field_set_val32(p->mp_cce_data_ind, val);
+}
+
+void cat_nthw_cce_flush(const struct cat_nthw *p)
+{
+ assert(p->mp_cce_ctrl);
+ assert(p->mp_cce_data);
+ register_flush(p->mp_cce_ctrl, 1);
+ register_flush(p->mp_cce_data, 1);
+}
+
+void cat_nthw_ccs_select(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_ccs_addr);
+ field_set_val32(p->mp_ccs_addr, val);
+}
+
+void cat_nthw_ccs_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_ccs_cnt);
+ field_set_val32(p->mp_ccs_cnt, val);
+}
+
+#define CATNTHW_CCS_SET(name) \
+ void cat_nthw_ccs_data_##name(const struct cat_nthw *p, uint32_t val) \
+ { \
+ assert(p->mp_ccs_data_##name); \
+ field_set_val32(p->mp_ccs_data_##name, val); \
+ }
+
+CATNTHW_CCS_SET(cor_en);
+CATNTHW_CCS_SET(cor);
+CATNTHW_CCS_SET(hsh_en);
+CATNTHW_CCS_SET(hsh);
+CATNTHW_CCS_SET(qsl_en);
+CATNTHW_CCS_SET(qsl);
+CATNTHW_CCS_SET(ipf_en);
+CATNTHW_CCS_SET(ipf);
+CATNTHW_CCS_SET(slc_en);
+CATNTHW_CCS_SET(slc);
+CATNTHW_CCS_SET(pdb_en);
+CATNTHW_CCS_SET(pdb);
+CATNTHW_CCS_SET(msk_en);
+CATNTHW_CCS_SET(msk);
+CATNTHW_CCS_SET(hst_en);
+CATNTHW_CCS_SET(hst);
+CATNTHW_CCS_SET(epp_en);
+CATNTHW_CCS_SET(epp);
+CATNTHW_CCS_SET(tpe_en);
+CATNTHW_CCS_SET(tpe);
+CATNTHW_CCS_SET(rrb_en);
+CATNTHW_CCS_SET(rrb);
+CATNTHW_CCS_SET(sb0_type);
+CATNTHW_CCS_SET(sb0_data);
+CATNTHW_CCS_SET(sb1_type);
+CATNTHW_CCS_SET(sb1_data);
+CATNTHW_CCS_SET(sb2_type);
+CATNTHW_CCS_SET(sb2_data);
+
+void cat_nthw_ccs_flush(const struct cat_nthw *p)
+{
+ assert(p->mp_ccs_ctrl);
+ assert(p->mp_ccs_data);
+ register_flush(p->mp_ccs_ctrl, 1);
+ register_flush(p->mp_ccs_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h
new file mode 100644
index 0000000000..41ac891a93
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_CAT_H__
+#define __FLOW_NTHW_CAT_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct cat_nthw;
+
+typedef struct cat_nthw cat_nthw_t;
+
+struct cat_nthw *cat_nthw_new(void);
+void cat_nthw_delete(struct cat_nthw *p);
+int cat_nthw_init(struct cat_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int cat_nthw_setup(struct cat_nthw *p, int n_idx, int n_idx_cnt);
+void cat_nthw_set_debug_mode(struct cat_nthw *p, unsigned int n_debug_mode);
+
+/* CFN */
+void cat_nthw_cfn_select(const struct cat_nthw *p, uint32_t val);
+void r(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_enable(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_isl(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_cfp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_mac(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_l2(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_vn_tag(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_vlan(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_mpls(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_l3(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_frag(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_ip_prot(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_l4(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tunnel(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_l2(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_vlan(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_mpls(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_l3(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_frag(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_ip_prot(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_l4(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_cv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_fcs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_trunc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_l3_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_l4_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_tnl_l3_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_tnl_l4_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_ttl_exp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_tnl_ttl_exp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_mac_port(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_cmp(const struct cat_nthw *p, const uint32_t *val);
+void cat_nthw_cfn_pm_dct(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_ext_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_cmb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_and_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_or_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_lc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_lc_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_km0_or(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_km1_or(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_flush(const struct cat_nthw *p);
+/* KCE 0/1 */
+void cat_nthw_kce_select(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kce_cnt(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kce_enable(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kce_flush(const struct cat_nthw *p, int index);
+/* KCS 0/1 */
+void cat_nthw_kcs_select(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kcs_cnt(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kcs_category(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kcs_flush(const struct cat_nthw *p, int index);
+/* FTE 0/1 */
+void cat_nthw_fte_select(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_fte_cnt(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_fte_enable(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_fte_flush(const struct cat_nthw *p, int index);
+/* CTE */
+void cat_nthw_cte_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_col(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_cor(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_hsh(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_qsl(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_ipf(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_slc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_pdb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_msk(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_hst(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_epp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_tpe(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_rrb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_flush(const struct cat_nthw *p);
+/* CTS */
+void cat_nthw_cts_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cts_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cts_flush(const struct cat_nthw *p);
+void cat_nthw_cts_cat_a(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cts_cat_b(const struct cat_nthw *p, uint32_t val);
+/* COT */
+void cat_nthw_cot_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_color(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_km(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_nfv_sb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_flush(const struct cat_nthw *p);
+/* CCT */
+void cat_nthw_cct_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_color(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_km(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_flush(const struct cat_nthw *p);
+/* EXO */
+void cat_nthw_exo_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_exo_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_exo_dyn(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_exo_ofs(const struct cat_nthw *p, int32_t val);
+void cat_nthw_exo_flush(const struct cat_nthw *p);
+/* RCK */
+void cat_nthw_rck_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_rck_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_rck_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_rck_flush(const struct cat_nthw *p);
+/* LEN */
+void cat_nthw_len_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_lower(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_upper(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_dyn1(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_dyn2(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_flush(const struct cat_nthw *p);
+/* KCC */
+void cat_nthw_kcc_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_key(const struct cat_nthw *p, uint32_t *val);
+void cat_nthw_kcc_category(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_id(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_flush(const struct cat_nthw *p);
+/* CCE */
+void cat_nthw_cce_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_data_imm(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_data_ind(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_flush(const struct cat_nthw *p);
+/* CCS */
+void cat_nthw_ccs_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_cor_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_cor(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hsh_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hsh(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_qsl_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_qsl(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_ipf_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_ipf(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_slc_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_slc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_pdb_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_pdb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_msk_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_msk(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hst_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hst(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_epp_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_epp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_tpe_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_tpe(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_rrb_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_rrb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb0_type(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb0_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb1_type(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb1_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb2_type(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb2_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_flush(const struct cat_nthw *p);
+
+struct cat_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+ nt_module_t *m_cat;
+ int m_km_if_cnt;
+
+ nt_register_t *mp_cfn_ctrl;
+ nt_field_t *mp_cfn_addr;
+ nt_field_t *mp_cfn_cnt;
+ nt_register_t *mp_cfn_data;
+ nt_field_t *mp_cfn_data_enable;
+ nt_field_t *mp_cfn_data_inv;
+ nt_field_t *mp_cfn_data_ptc_inv;
+ nt_field_t *mp_cfn_data_ptc_isl;
+ nt_field_t *mp_cfn_data_ptc_cfp;
+ nt_field_t *mp_cfn_data_ptc_mac;
+ nt_field_t *mp_cfn_data_ptc_l2;
+ nt_field_t *mp_cfn_data_ptc_vn_tag;
+ nt_field_t *mp_cfn_data_ptc_vlan;
+ nt_field_t *mp_cfn_data_ptc_mpls;
+ nt_field_t *mp_cfn_data_ptc_l3;
+ nt_field_t *mp_cfn_data_ptc_frag;
+ nt_field_t *mp_cfn_data_ptc_ip_prot;
+ nt_field_t *mp_cfn_data_ptc_l4;
+ nt_field_t *mp_cfn_data_ptc_tunnel;
+ nt_field_t *mp_cfn_data_ptc_tnl_l2;
+ nt_field_t *mp_cfn_data_ptc_tnl_vlan;
+ nt_field_t *mp_cfn_data_ptc_tnl_mpls;
+ nt_field_t *mp_cfn_data_ptc_tnl_l3;
+ nt_field_t *mp_cfn_data_ptc_tnl_frag;
+ nt_field_t *mp_cfn_data_ptc_tnl_ip_prot;
+ nt_field_t *mp_cfn_data_ptc_tnl_l4;
+ nt_field_t *mp_cfn_data_err_inv;
+ nt_field_t *mp_cfn_data_err_cv;
+ nt_field_t *mp_cfn_data_err_fcs;
+ nt_field_t *mp_cfn_data_err_trunc;
+ nt_field_t *mp_cfn_data_err_l3_cs;
+ nt_field_t *mp_cfn_data_err_l4_cs;
+ nt_field_t *mp_cfn_data_err_tnl_l3_cs;
+ nt_field_t *mp_cfn_data_err_tnl_l4_cs;
+ nt_field_t *mp_cfn_data_err_ttl_exp;
+ nt_field_t *mp_cfn_data_err_tnl_ttl_exp;
+ nt_field_t *mp_cfn_data_mac_port;
+ nt_field_t *mp_cfn_data_pm_cmp;
+ nt_field_t *mp_cfn_data_pm_dct;
+ nt_field_t *mp_cfn_data_pm_ext_inv;
+ nt_field_t *mp_cfn_data_pm_cmb;
+ nt_field_t *mp_cfn_data_pm_and_inv;
+ nt_field_t *mp_cfn_data_pm_or_inv;
+ nt_field_t *mp_cfn_data_pm_inv;
+ nt_field_t *mp_cfn_data_lc;
+ nt_field_t *mp_cfn_data_lc_inv;
+ nt_field_t *mp_cfn_data_km0_or;
+ nt_field_t *mp_cfn_data_km1_or;
+
+ nt_register_t *mp_kce_ctrl[2];
+ nt_field_t *mp_kce_addr[2];
+ nt_field_t *mp_kce_cnt[2];
+ nt_register_t *mp_kce_data[2];
+ nt_field_t *mp_kce_data_enable[2];
+
+ nt_register_t *mp_kcs_ctrl[2];
+ nt_field_t *mp_kcs_addr[2];
+ nt_field_t *mp_kcs_cnt[2];
+ nt_register_t *mp_kcs_data[2];
+ nt_field_t *mp_kcs_data_category[2];
+
+ nt_register_t *mp_fte_ctrl[2];
+ nt_field_t *mp_fte_addr[2];
+ nt_field_t *mp_fte_cnt[2];
+ nt_register_t *mp_fte_data[2];
+ nt_field_t *mp_fte_data_enable[2];
+
+ nt_register_t *mp_cte_ctrl;
+ nt_field_t *mp_cte_addr;
+ nt_field_t *mp_cte_cnt;
+ nt_register_t *mp_cte_data;
+ nt_field_t *mp_cte_data_col;
+ nt_field_t *mp_cte_data_cor;
+ nt_field_t *mp_cte_data_hsh;
+ nt_field_t *mp_cte_data_qsl;
+ nt_field_t *mp_cte_data_ipf;
+ nt_field_t *mp_cte_data_slc;
+ nt_field_t *mp_cte_data_pdb;
+ nt_field_t *mp_cte_data_msk;
+ nt_field_t *mp_cte_data_hst;
+ nt_field_t *mp_cte_data_epp;
+ nt_field_t *mp_cte_data_tpe;
+ nt_field_t *mp_cte_data_rrb;
+
+ nt_register_t *mp_cts_ctrl;
+ nt_field_t *mp_cts_addr;
+ nt_field_t *mp_cts_cnt;
+ nt_register_t *mp_cts_data;
+ nt_field_t *mp_cts_data_cat_a;
+ nt_field_t *mp_cts_data_cat_b;
+
+ nt_register_t *mp_cot_ctrl;
+ nt_field_t *mp_cot_addr;
+ nt_field_t *mp_cot_cnt;
+ nt_register_t *mp_cot_data;
+ nt_field_t *mp_cot_data_color;
+ nt_field_t *mp_cot_data_km;
+ nt_field_t *mp_cot_data_nfv_sb;
+
+ nt_register_t *mp_cct_ctrl;
+ nt_field_t *mp_cct_addr;
+ nt_field_t *mp_cct_cnt;
+ nt_register_t *mp_cct_data;
+ nt_field_t *mp_cct_data_color;
+ nt_field_t *mp_cct_data_km;
+
+ nt_register_t *mp_exo_ctrl;
+ nt_field_t *mp_exo_addr;
+ nt_field_t *mp_exo_cnt;
+ nt_register_t *mp_exo_data;
+ nt_field_t *mp_exo_data_dyn;
+ nt_field_t *mp_exo_data_ofs;
+
+ nt_register_t *mp_rck_ctrl;
+ nt_field_t *mp_rck_addr;
+ nt_field_t *mp_rck_cnt;
+ nt_register_t *mp_rck_data;
+
+ nt_register_t *mp_len_ctrl;
+ nt_field_t *mp_len_addr;
+ nt_field_t *mp_len_cnt;
+ nt_register_t *mp_len_data;
+ nt_field_t *mp_len_data_lower;
+ nt_field_t *mp_len_data_upper;
+ nt_field_t *mp_len_data_dyn1;
+ nt_field_t *mp_len_data_dyn2;
+ nt_field_t *mp_len_data_inv;
+ nt_register_t *mp_kcc_ctrl;
+ nt_field_t *mp_kcc_addr;
+ nt_field_t *mp_kcc_cnt;
+
+ nt_register_t *mp_kcc_data;
+ nt_field_t *mp_kcc_data_key;
+ nt_field_t *mp_kcc_data_category;
+ nt_field_t *mp_kcc_data_id;
+
+ nt_register_t *mp_cce_ctrl;
+ nt_field_t *mp_cce_addr;
+ nt_field_t *mp_cce_cnt;
+
+ nt_register_t *mp_cce_data;
+ nt_field_t *mp_cce_data_imm;
+ nt_field_t *mp_cce_data_ind;
+
+ nt_register_t *mp_ccs_ctrl;
+ nt_field_t *mp_ccs_addr;
+ nt_field_t *mp_ccs_cnt;
+
+ nt_register_t *mp_ccs_data;
+ nt_field_t *mp_ccs_data_cor_en;
+ nt_field_t *mp_ccs_data_cor;
+
+ nt_field_t *mp_ccs_data_hsh_en;
+ nt_field_t *mp_ccs_data_hsh;
+ nt_field_t *mp_ccs_data_qsl_en;
+ nt_field_t *mp_ccs_data_qsl;
+ nt_field_t *mp_ccs_data_ipf_en;
+ nt_field_t *mp_ccs_data_ipf;
+ nt_field_t *mp_ccs_data_slc_en;
+ nt_field_t *mp_ccs_data_slc;
+ nt_field_t *mp_ccs_data_pdb_en;
+ nt_field_t *mp_ccs_data_pdb;
+ nt_field_t *mp_ccs_data_msk_en;
+ nt_field_t *mp_ccs_data_msk;
+ nt_field_t *mp_ccs_data_hst_en;
+ nt_field_t *mp_ccs_data_hst;
+ nt_field_t *mp_ccs_data_epp_en;
+ nt_field_t *mp_ccs_data_epp;
+ nt_field_t *mp_ccs_data_tpe_en;
+ nt_field_t *mp_ccs_data_tpe;
+ nt_field_t *mp_ccs_data_rrb_en;
+ nt_field_t *mp_ccs_data_rrb;
+ nt_field_t *mp_ccs_data_sb0_type;
+ nt_field_t *mp_ccs_data_sb0_data;
+ nt_field_t *mp_ccs_data_sb1_type;
+ nt_field_t *mp_ccs_data_sb1_data;
+ nt_field_t *mp_ccs_data_sb2_type;
+ nt_field_t *mp_ccs_data_sb2_data;
+};
+
+#endif /* __FLOW_NTHW_CAT_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c
new file mode 100644
index 0000000000..5a7f90ad69
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_csu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void csu_nthw_set_debug_mode(struct csu_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_csu, n_debug_mode);
+}
+
+struct csu_nthw *csu_nthw_new(void)
+{
+ struct csu_nthw *p = malloc(sizeof(struct csu_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void csu_nthw_delete(struct csu_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int csu_nthw_init(struct csu_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_CSU, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Csu %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_csu = p_mod;
+
+ p->mp_rcp_ctrl = module_get_register(p->m_csu, CSU_RCP_CTRL);
+ p->mp_rcp_ctrl_adr = register_get_field(p->mp_rcp_ctrl, CSU_RCP_CTRL_ADR);
+ p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, CSU_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_csu, CSU_RCP_DATA);
+ p->mp_rcp_data_ol3_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_OL3_CMD);
+ p->mp_rcp_data_ol4_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_OL4_CMD);
+ p->mp_rcp_data_il3_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_IL3_CMD);
+ p->mp_rcp_data_il4_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_IL4_CMD);
+
+ return 0;
+}
+
+void csu_nthw_rcp_select(const struct csu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_adr, val);
+}
+
+void csu_nthw_rcp_cnt(const struct csu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_cnt, val);
+}
+
+void csu_nthw_rcp_outer_l3_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L3 calc method for outer layer3.
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_ol3_cmd, val);
+}
+
+void csu_nthw_rcp_outer_l4_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L4 calc method for outer layer4.
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ * 4: Set UDP checksum value of ZERO for both IPv4/IPv6, set good checksum for TCP.
+ * 5: Set UDP checksum value of ZERO for IPv4, set good checksum for TCP.
+ * 6: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4/IPv6 and UDP,
+ * otherwise GOOD checksum.
+ * 7: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4 and UDP, otherwise
+ * GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_ol4_cmd, val);
+}
+
+void csu_nthw_rcp_inner_l3_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L3 calc method for inner layer3 (tunneled).
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_il3_cmd, val);
+}
+
+void csu_nthw_rcp_inner_l4_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L4 calc method for inner layer4 (tunneled).
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ * 4: Set UDP checksum value of ZERO for both IPv4/IPv6, set good checksum for TCP.
+ * 5: Set UDP checksum value of ZERO for IPv4, set good checksum for TCP.
+ * 6: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4/IPv6 and UDP,
+ * otherwise GOOD checksum.
+ * 7: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4 and UDP, otherwise
+ * GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_il4_cmd, val);
+}
+
+void csu_nthw_rcp_flush(const struct csu_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h
new file mode 100644
index 0000000000..6cb0e1f781
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_NTHW_CSU_H_
+#define _FLOW_NTHW_CSU_H_
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct csu_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_csu;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_ctrl_adr;
+ nt_field_t *mp_rcp_ctrl_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_ol3_cmd;
+ nt_field_t *mp_rcp_data_ol4_cmd;
+ nt_field_t *mp_rcp_data_il3_cmd;
+ nt_field_t *mp_rcp_data_il4_cmd;
+};
+
+struct csu_nthw *csu_nthw_new(void);
+void csu_nthw_delete(struct csu_nthw *p);
+int csu_nthw_init(struct csu_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int csu_nthw_setup(struct csu_nthw *p, int n_idx, int n_idx_cnt);
+void csu_nthw_set_debug_mode(struct csu_nthw *p, unsigned int n_debug_mode);
+
+void csu_nthw_rcp_select(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_cnt(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_outer_l3_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_outer_l4_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_inner_l3_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_inner_l4_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_flush(const struct csu_nthw *p);
+
+#endif /* _FLOW_NTHW_CSU_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c
new file mode 100644
index 0000000000..4549898cc1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c
@@ -0,0 +1,1140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_rac.h"
+
+#include "flow_nthw_flm.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+struct flm_nthw *flm_nthw_new(void)
+{
+ struct flm_nthw *p = malloc(sizeof(struct flm_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void flm_nthw_delete(struct flm_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+void flm_nthw_set_debug_mode(struct flm_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_flm, n_debug_mode);
+}
+
+int flm_nthw_init(struct flm_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_FLM, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Flm %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_rac = p_fpga->p_fpga_info->mp_nthw_rac;
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_flm = p_mod;
+
+ p->mp_control = module_get_register(p->m_flm, FLM_CONTROL);
+ p->mp_control_enable =
+ register_get_field(p->mp_control, FLM_CONTROL_ENABLE);
+ p->mp_control_init = register_get_field(p->mp_control, FLM_CONTROL_INIT);
+ p->mp_control_lds = register_get_field(p->mp_control, FLM_CONTROL_LDS);
+ p->mp_control_lfs = register_get_field(p->mp_control, FLM_CONTROL_LFS);
+ p->mp_control_lis = register_get_field(p->mp_control, FLM_CONTROL_LIS);
+ p->mp_control_uds = register_get_field(p->mp_control, FLM_CONTROL_UDS);
+ p->mp_control_uis = register_get_field(p->mp_control, FLM_CONTROL_UIS);
+ p->mp_control_rds = register_get_field(p->mp_control, FLM_CONTROL_RDS);
+ p->mp_control_ris = register_get_field(p->mp_control, FLM_CONTROL_RIS);
+ p->mp_control_pds = register_query_field(p->mp_control, FLM_CONTROL_PDS);
+ p->mp_control_pis = register_query_field(p->mp_control, FLM_CONTROL_PIS);
+ p->mp_control_crcwr = register_get_field(p->mp_control, FLM_CONTROL_CRCWR);
+ p->mp_control_crcrd = register_get_field(p->mp_control, FLM_CONTROL_CRCRD);
+ p->mp_control_rbl = register_get_field(p->mp_control, FLM_CONTROL_RBL);
+ p->mp_control_eab = register_get_field(p->mp_control, FLM_CONTROL_EAB);
+ p->mp_control_split_sdram_usage =
+ register_get_field(p->mp_control, FLM_CONTROL_SPLIT_SDRAM_USAGE);
+
+ p->mp_status = module_get_register(p->m_flm, FLM_STATUS);
+ p->mp_status_calibdone =
+ register_get_field(p->mp_status, FLM_STATUS_CALIBDONE);
+ p->mp_status_initdone =
+ register_get_field(p->mp_status, FLM_STATUS_INITDONE);
+ p->mp_status_idle = register_get_field(p->mp_status, FLM_STATUS_IDLE);
+ p->mp_status_critical =
+ register_get_field(p->mp_status, FLM_STATUS_CRITICAL);
+ p->mp_status_panic = register_get_field(p->mp_status, FLM_STATUS_PANIC);
+ p->mp_status_crcerr = register_get_field(p->mp_status, FLM_STATUS_CRCERR);
+ p->mp_status_eft_bp = register_get_field(p->mp_status, FLM_STATUS_EFT_BP);
+
+ p->mp_timeout = module_get_register(p->m_flm, FLM_TIMEOUT);
+ p->mp_timeout_t = register_get_field(p->mp_timeout, FLM_TIMEOUT_T);
+
+ p->mp_scrub = module_get_register(p->m_flm, FLM_SCRUB);
+ p->mp_scrub_i = register_get_field(p->mp_scrub, FLM_SCRUB_I);
+
+ p->mp_load_bin = module_get_register(p->m_flm, FLM_LOAD_BIN);
+ p->mp_load_bin_bin = register_get_field(p->mp_load_bin, FLM_LOAD_BIN_BIN);
+
+ p->mp_load_pps = module_get_register(p->m_flm, FLM_LOAD_PPS);
+ p->mp_load_pps_pps = register_get_field(p->mp_load_pps, FLM_LOAD_PPS_PPS);
+
+ p->mp_load_lps = module_get_register(p->m_flm, FLM_LOAD_LPS);
+ p->mp_load_lps_lps = register_get_field(p->mp_load_lps, FLM_LOAD_LPS_LPS);
+
+ p->mp_load_aps = module_get_register(p->m_flm, FLM_LOAD_APS);
+ p->mp_load_aps_aps = register_get_field(p->mp_load_aps, FLM_LOAD_APS_APS);
+
+ p->mp_prio = module_get_register(p->m_flm, FLM_PRIO);
+ p->mp_prio_limit0 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT0);
+ p->mp_prio_ft0 = register_get_field(p->mp_prio, FLM_PRIO_FT0);
+ p->mp_prio_limit1 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT1);
+ p->mp_prio_ft1 = register_get_field(p->mp_prio, FLM_PRIO_FT1);
+ p->mp_prio_limit2 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT2);
+ p->mp_prio_ft2 = register_get_field(p->mp_prio, FLM_PRIO_FT2);
+ p->mp_prio_limit3 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT3);
+ p->mp_prio_ft3 = register_get_field(p->mp_prio, FLM_PRIO_FT3);
+
+ p->mp_pst_ctrl = module_get_register(p->m_flm, FLM_PST_CTRL);
+ p->mp_pst_ctrl_adr = register_get_field(p->mp_pst_ctrl, FLM_PST_CTRL_ADR);
+ p->mp_pst_ctrl_cnt = register_get_field(p->mp_pst_ctrl, FLM_PST_CTRL_CNT);
+ p->mp_pst_data = module_get_register(p->m_flm, FLM_PST_DATA);
+ p->mp_pst_data_bp = register_get_field(p->mp_pst_data, FLM_PST_DATA_BP);
+ p->mp_pst_data_pp = register_get_field(p->mp_pst_data, FLM_PST_DATA_PP);
+ p->mp_pst_data_tp = register_get_field(p->mp_pst_data, FLM_PST_DATA_TP);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_flm, FLM_RCP_CTRL);
+ p->mp_rcp_ctrl_adr = register_get_field(p->mp_rcp_ctrl, FLM_RCP_CTRL_ADR);
+ p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, FLM_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_flm, FLM_RCP_DATA);
+ p->mp_rcp_data_lookup =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_LOOKUP);
+ p->mp_rcp_data_qw0_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_DYN);
+ p->mp_rcp_data_qw0_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_OFS);
+ p->mp_rcp_data_qw0_sel =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_SEL);
+ p->mp_rcp_data_qw4_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW4_DYN);
+ p->mp_rcp_data_qw4_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW4_OFS);
+ p->mp_rcp_data_sw8_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_DYN);
+ p->mp_rcp_data_sw8_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_OFS);
+ p->mp_rcp_data_sw8_sel =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_SEL);
+ p->mp_rcp_data_sw9_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW9_DYN);
+ p->mp_rcp_data_sw9_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW9_OFS);
+ p->mp_rcp_data_mask = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_MASK);
+ p->mp_rcp_data_kid = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_KID);
+ p->mp_rcp_data_opn = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_OPN);
+ p->mp_rcp_data_ipn = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_IPN);
+ p->mp_rcp_data_byt_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_BYT_DYN);
+ p->mp_rcp_data_byt_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_BYT_OFS);
+ p->mp_rcp_data_txplm = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_TXPLM);
+ p->mp_rcp_data_auto_ipv4_mask =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_AUTO_IPV4_MASK);
+
+ p->mp_buf_ctrl = module_get_register(p->m_flm, FLM_BUF_CTRL);
+
+ p->mp_lrn_data = module_get_register(p->m_flm, FLM_LRN_DATA);
+ p->mp_inf_data = module_get_register(p->m_flm, FLM_INF_DATA);
+ p->mp_sta_data = module_get_register(p->m_flm, FLM_STA_DATA);
+
+ p->mp_stat_lrn_done = module_get_register(p->m_flm, FLM_STAT_LRN_DONE);
+ p->mp_stat_lrn_done_cnt =
+ register_get_field(p->mp_stat_lrn_done, FLM_STAT_LRN_DONE_CNT);
+
+ p->mp_stat_lrn_ignore = module_get_register(p->m_flm, FLM_STAT_LRN_IGNORE);
+ p->mp_stat_lrn_ignore_cnt =
+ register_get_field(p->mp_stat_lrn_ignore, FLM_STAT_LRN_IGNORE_CNT);
+
+ p->mp_stat_lrn_fail = module_get_register(p->m_flm, FLM_STAT_LRN_FAIL);
+ p->mp_stat_lrn_fail_cnt =
+ register_get_field(p->mp_stat_lrn_fail, FLM_STAT_LRN_FAIL_CNT);
+
+ p->mp_stat_unl_done = module_get_register(p->m_flm, FLM_STAT_UNL_DONE);
+ p->mp_stat_unl_done_cnt =
+ register_get_field(p->mp_stat_unl_done, FLM_STAT_UNL_DONE_CNT);
+
+ p->mp_stat_unl_ignore = module_get_register(p->m_flm, FLM_STAT_UNL_IGNORE);
+ p->mp_stat_unl_ignore_cnt =
+ register_get_field(p->mp_stat_unl_ignore, FLM_STAT_UNL_IGNORE_CNT);
+
+ p->mp_stat_prb_done = module_query_register(p->m_flm, FLM_STAT_PRB_DONE);
+ p->mp_stat_prb_done_cnt =
+ register_query_field(p->mp_stat_prb_done, FLM_STAT_PRB_DONE_CNT);
+
+ p->mp_stat_prb_ignore = module_query_register(p->m_flm, FLM_STAT_PRB_IGNORE);
+ p->mp_stat_prb_ignore_cnt = register_query_field(p->mp_stat_prb_ignore,
+ FLM_STAT_PRB_IGNORE_CNT);
+
+ p->mp_stat_rel_done = module_get_register(p->m_flm, FLM_STAT_REL_DONE);
+ p->mp_stat_rel_done_cnt =
+ register_get_field(p->mp_stat_rel_done, FLM_STAT_REL_DONE_CNT);
+
+ p->mp_stat_rel_ignore = module_get_register(p->m_flm, FLM_STAT_REL_IGNORE);
+ p->mp_stat_rel_ignore_cnt =
+ register_get_field(p->mp_stat_rel_ignore, FLM_STAT_REL_IGNORE_CNT);
+
+ p->mp_stat_aul_done = module_get_register(p->m_flm, FLM_STAT_AUL_DONE);
+ p->mp_stat_aul_done_cnt =
+ register_get_field(p->mp_stat_aul_done, FLM_STAT_AUL_DONE_CNT);
+
+ p->mp_stat_aul_ignore = module_get_register(p->m_flm, FLM_STAT_AUL_IGNORE);
+ p->mp_stat_aul_ignore_cnt =
+ register_get_field(p->mp_stat_aul_ignore, FLM_STAT_AUL_IGNORE_CNT);
+
+ p->mp_stat_aul_fail = module_get_register(p->m_flm, FLM_STAT_AUL_FAIL);
+ p->mp_stat_aul_fail_cnt =
+ register_get_field(p->mp_stat_aul_fail, FLM_STAT_AUL_FAIL_CNT);
+
+ p->mp_stat_tul_done = module_get_register(p->m_flm, FLM_STAT_TUL_DONE);
+ p->mp_stat_tul_done_cnt =
+ register_get_field(p->mp_stat_tul_done, FLM_STAT_TUL_DONE_CNT);
+
+ p->mp_stat_flows = module_get_register(p->m_flm, FLM_STAT_FLOWS);
+ p->mp_stat_flows_cnt =
+ register_get_field(p->mp_stat_flows, FLM_STAT_FLOWS_CNT);
+
+ p->mp_stat_sta_done = module_query_register(p->m_flm, FLM_STAT_STA_DONE);
+ p->mp_stat_sta_done_cnt =
+ register_query_field(p->mp_stat_sta_done, FLM_STAT_STA_DONE_CNT);
+
+ p->mp_stat_inf_done = module_query_register(p->m_flm, FLM_STAT_INF_DONE);
+ p->mp_stat_inf_done_cnt =
+ register_query_field(p->mp_stat_inf_done, FLM_STAT_INF_DONE_CNT);
+
+ p->mp_stat_inf_skip = module_query_register(p->m_flm, FLM_STAT_INF_SKIP);
+ p->mp_stat_inf_skip_cnt =
+ register_query_field(p->mp_stat_inf_skip, FLM_STAT_INF_SKIP_CNT);
+
+ p->mp_stat_pck_hit = module_query_register(p->m_flm, FLM_STAT_PCK_HIT);
+ p->mp_stat_pck_hit_cnt =
+ register_query_field(p->mp_stat_pck_hit, FLM_STAT_PCK_HIT_CNT);
+
+ p->mp_stat_pck_miss = module_query_register(p->m_flm, FLM_STAT_PCK_MISS);
+ p->mp_stat_pck_miss_cnt =
+ register_query_field(p->mp_stat_pck_miss, FLM_STAT_PCK_MISS_CNT);
+
+ p->mp_stat_pck_unh = module_query_register(p->m_flm, FLM_STAT_PCK_UNH);
+ p->mp_stat_pck_unh_cnt =
+ register_query_field(p->mp_stat_pck_unh, FLM_STAT_PCK_UNH_CNT);
+
+ p->mp_stat_pck_dis = module_query_register(p->m_flm, FLM_STAT_PCK_DIS);
+ p->mp_stat_pck_dis_cnt =
+ register_query_field(p->mp_stat_pck_dis, FLM_STAT_PCK_DIS_CNT);
+
+ p->mp_stat_csh_hit = module_query_register(p->m_flm, FLM_STAT_CSH_HIT);
+ p->mp_stat_csh_hit_cnt =
+ register_query_field(p->mp_stat_csh_hit, FLM_STAT_CSH_HIT_CNT);
+
+ p->mp_stat_csh_miss = module_query_register(p->m_flm, FLM_STAT_CSH_MISS);
+ p->mp_stat_csh_miss_cnt =
+ register_query_field(p->mp_stat_csh_miss, FLM_STAT_CSH_MISS_CNT);
+
+ p->mp_stat_csh_unh = module_query_register(p->m_flm, FLM_STAT_CSH_UNH);
+ p->mp_stat_csh_unh_cnt =
+ register_query_field(p->mp_stat_csh_unh, FLM_STAT_CSH_UNH_CNT);
+
+ p->mp_stat_cuc_start = module_query_register(p->m_flm, FLM_STAT_CUC_START);
+ p->mp_stat_cuc_start_cnt =
+ register_query_field(p->mp_stat_cuc_start, FLM_STAT_CUC_START_CNT);
+
+ p->mp_stat_cuc_move = module_query_register(p->m_flm, FLM_STAT_CUC_MOVE);
+ p->mp_stat_cuc_move_cnt =
+ register_query_field(p->mp_stat_cuc_move, FLM_STAT_CUC_MOVE_CNT);
+
+ return 0;
+}
+
+void flm_nthw_control_enable(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_enable, val);
+}
+
+void flm_nthw_control_init(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_init, val);
+}
+
+void flm_nthw_control_lds(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_lds, val);
+}
+
+void flm_nthw_control_lfs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_lfs, val);
+}
+
+void flm_nthw_control_lis(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_lis, val);
+}
+
+void flm_nthw_control_uds(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_uds, val);
+}
+
+void flm_nthw_control_uis(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_uis, val);
+}
+
+void flm_nthw_control_rds(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_rds, val);
+}
+
+void flm_nthw_control_ris(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_ris, val);
+}
+
+void flm_nthw_control_pds(const struct flm_nthw *p, uint32_t val)
+{
+ assert(p->mp_control_pds);
+ field_set_val32(p->mp_control_pds, val);
+}
+
+void flm_nthw_control_pis(const struct flm_nthw *p, uint32_t val)
+{
+ assert(p->mp_control_pis);
+ field_set_val32(p->mp_control_pis, val);
+}
+
+void flm_nthw_control_crcwr(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_crcwr, val);
+}
+
+void flm_nthw_control_crcrd(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_crcrd, val);
+}
+
+void flm_nthw_control_rbl(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_rbl, val);
+}
+
+void flm_nthw_control_eab(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_eab, val);
+}
+
+void flm_nthw_control_split_sdram_usage(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_split_sdram_usage, val);
+}
+
+void flm_nthw_control_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_control, 1);
+}
+
+void flm_nthw_status_calibdone(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_calibdone);
+}
+
+void flm_nthw_status_initdone(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_initdone);
+}
+
+void flm_nthw_status_idle(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_idle);
+}
+
+void flm_nthw_status_critical(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_critical);
+
+ else
+ field_set_val32(p->mp_status_critical, *val);
+}
+
+void flm_nthw_status_panic(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_panic);
+
+ else
+ field_set_val32(p->mp_status_panic, *val);
+}
+
+void flm_nthw_status_crcerr(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_crcerr);
+
+ else
+ field_set_val32(p->mp_status_crcerr, *val);
+}
+
+void flm_nthw_status_eft_bp(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_eft_bp);
+}
+
+void flm_nthw_status_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_status, 1);
+}
+
+void flm_nthw_status_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_status);
+}
+
+void flm_nthw_timeout_t(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_timeout_t, val);
+}
+
+void flm_nthw_timeout_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_timeout, 1);
+}
+
+void flm_nthw_scrub_i(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_scrub_i, val);
+}
+
+void flm_nthw_scrub_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_scrub, 1);
+}
+
+void flm_nthw_load_bin(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_bin_bin, val);
+}
+
+void flm_nthw_load_bin_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_bin, 1);
+}
+
+void flm_nthw_load_pps(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_pps_pps, val);
+}
+
+void flm_nthw_load_pps_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_pps, 1);
+}
+
+void flm_nthw_load_lps(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_lps_lps, val);
+}
+
+void flm_nthw_load_lps_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_lps, 1);
+}
+
+void flm_nthw_load_aps(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_aps_aps, val);
+}
+
+void flm_nthw_load_aps_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_aps, 1);
+}
+
+void flm_nthw_prio_limit0(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit0, val);
+}
+
+void flm_nthw_prio_ft0(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft0, val);
+}
+
+void flm_nthw_prio_limit1(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit1, val);
+}
+
+void flm_nthw_prio_ft1(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft1, val);
+}
+
+void flm_nthw_prio_limit2(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit2, val);
+}
+
+void flm_nthw_prio_ft2(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft2, val);
+}
+
+void flm_nthw_prio_limit3(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit3, val);
+}
+
+void flm_nthw_prio_ft3(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft3, val);
+}
+
+void flm_nthw_prio_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_prio, 1);
+}
+
+void flm_nthw_pst_select(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_ctrl_adr, val);
+}
+
+void flm_nthw_pst_cnt(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_ctrl_cnt, val);
+}
+
+void flm_nthw_pst_bp(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_data_bp, val);
+}
+
+void flm_nthw_pst_pp(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_data_pp, val);
+}
+
+void flm_nthw_pst_tp(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_data_tp, val);
+}
+
+void flm_nthw_pst_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_pst_ctrl, 1);
+ register_flush(p->mp_pst_data, 1);
+}
+
+void flm_nthw_rcp_select(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_adr, val);
+}
+
+void flm_nthw_rcp_cnt(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_cnt, val);
+}
+
+void flm_nthw_rcp_lookup(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_lookup, val);
+}
+
+void flm_nthw_rcp_qw0_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_dyn, val);
+}
+
+void flm_nthw_rcp_qw0_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_ofs, val);
+}
+
+void flm_nthw_rcp_qw0_sel(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_sel, val);
+}
+
+void flm_nthw_rcp_qw4_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_dyn, val);
+}
+
+void flm_nthw_rcp_qw4_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_ofs, val);
+}
+
+void flm_nthw_rcp_sw8_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw8_dyn, val);
+}
+
+void flm_nthw_rcp_sw8_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw8_ofs, val);
+}
+
+void flm_nthw_rcp_sw8_sel(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw8_sel, val);
+}
+
+void flm_nthw_rcp_sw9_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw9_dyn, val);
+}
+
+void flm_nthw_rcp_sw9_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw9_ofs, val);
+}
+
+void flm_nthw_rcp_mask(const struct flm_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask, val, 10);
+}
+
+void flm_nthw_rcp_kid(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_kid, val);
+}
+
+void flm_nthw_rcp_opn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_opn, val);
+}
+
+void flm_nthw_rcp_ipn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ipn, val);
+}
+
+void flm_nthw_rcp_byt_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_byt_dyn, val);
+}
+
+void flm_nthw_rcp_byt_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_byt_ofs, val);
+}
+
+void flm_nthw_rcp_txplm(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_txplm, val);
+}
+
+void flm_nthw_rcp_auto_ipv4_mask(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_auto_ipv4_mask, val);
+}
+
+void flm_nthw_rcp_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+int flm_nthw_buf_ctrl_update(const struct flm_nthw *p, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr bc_buf;
+
+ ret = nthw_rac_rab_dma_begin(rac);
+ if (ret == 0) {
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+int flm_nthw_lrn_data_flush(const struct flm_nthw *p, const uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address = register_get_address(p->mp_lrn_data);
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr bc_buf;
+
+ if (nthw_rac_rab_dma_begin(rac) == 0) {
+ /* Announce the number of words to write to LRN_DATA */
+ uint32_t bufctrl_data[2];
+
+ bufctrl_data[0] = word_count;
+ bufctrl_data[1] = 0;
+ nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2,
+ bufctrl_data);
+ nthw_rac_rab_write32_dma(rac, address, bus_id, word_count, data);
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+int flm_nthw_inf_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address_infdata = register_get_address(p->mp_inf_data);
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr buf;
+ struct dma_buf_ptr bc_buf;
+
+ ret = nthw_rac_rab_dma_begin(rac);
+ if (ret == 0) {
+ /* Announce the number of words to read from INF_DATA */
+ uint32_t bufctrl_data[2];
+
+ bufctrl_data[0] = word_count << 16;
+ bufctrl_data[1] = 0;
+ nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2,
+ bufctrl_data);
+ nthw_rac_rab_read32_dma(rac, address_infdata, bus_id, word_count,
+ &buf);
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t mask = buf.size - 1;
+ uint32_t index = buf.index;
+
+ for (uint32_t i = 0; i < word_count; ++index, ++i)
+ data[i] = buf.base[index & mask];
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+int flm_nthw_sta_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address_stadata = register_get_address(p->mp_sta_data);
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr buf;
+ struct dma_buf_ptr bc_buf;
+
+ ret = nthw_rac_rab_dma_begin(rac);
+ if (ret == 0) {
+ /* Announce the number of words to read from STA_DATA */
+ uint32_t bufctrl_data[2];
+
+ bufctrl_data[0] = 0;
+ bufctrl_data[1] = word_count;
+ nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2,
+ bufctrl_data);
+ nthw_rac_rab_read32_dma(rac, address_stadata, bus_id, word_count,
+ &buf);
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t mask = buf.size - 1;
+ uint32_t index = buf.index;
+
+ for (uint32_t i = 0; i < word_count; ++index, ++i)
+ data[i] = buf.base[index & mask];
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+void flm_nthw_stat_lrn_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_lrn_done_cnt);
+}
+
+void flm_nthw_stat_lrn_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_lrn_done);
+}
+
+void flm_nthw_stat_lrn_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_lrn_ignore_cnt);
+}
+
+void flm_nthw_stat_lrn_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_lrn_ignore);
+}
+
+void flm_nthw_stat_lrn_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_lrn_fail_cnt);
+}
+
+void flm_nthw_stat_lrn_fail_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_lrn_fail);
+}
+
+void flm_nthw_stat_unl_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_unl_done_cnt);
+}
+
+void flm_nthw_stat_unl_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_unl_done);
+}
+
+void flm_nthw_stat_unl_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_unl_ignore_cnt);
+}
+
+void flm_nthw_stat_unl_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_unl_ignore);
+}
+
+void flm_nthw_stat_prb_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_prb_done_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_prb_done_cnt);
+}
+
+void flm_nthw_stat_prb_done_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_prb_done);
+ register_update(p->mp_stat_prb_done);
+}
+
+void flm_nthw_stat_prb_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_prb_ignore_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_prb_ignore_cnt);
+}
+
+void flm_nthw_stat_prb_ignore_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_prb_ignore);
+ register_update(p->mp_stat_prb_ignore);
+}
+
+void flm_nthw_stat_rel_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_rel_done_cnt);
+}
+
+void flm_nthw_stat_rel_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_rel_done);
+}
+
+void flm_nthw_stat_rel_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_rel_ignore_cnt);
+}
+
+void flm_nthw_stat_rel_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_rel_ignore);
+}
+
+void flm_nthw_stat_aul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_aul_done_cnt);
+}
+
+void flm_nthw_stat_aul_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_aul_done);
+}
+
+void flm_nthw_stat_aul_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_aul_ignore_cnt);
+}
+
+void flm_nthw_stat_aul_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_aul_ignore);
+}
+
+void flm_nthw_stat_aul_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_aul_fail_cnt);
+}
+
+void flm_nthw_stat_aul_fail_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_aul_fail);
+}
+
+void flm_nthw_stat_tul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_tul_done_cnt);
+}
+
+void flm_nthw_stat_tul_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_tul_done);
+}
+
+void flm_nthw_stat_flows_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_flows_cnt);
+}
+
+void flm_nthw_stat_flows_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_flows);
+}
+
+void flm_nthw_stat_sta_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_sta_done_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_sta_done_cnt);
+}
+
+void flm_nthw_stat_sta_done_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_sta_done);
+ register_update(p->mp_stat_sta_done);
+}
+
+void flm_nthw_stat_inf_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_inf_done_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_inf_done_cnt);
+}
+
+void flm_nthw_stat_inf_done_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_inf_done);
+ register_update(p->mp_stat_inf_done);
+}
+
+void flm_nthw_stat_inf_skip_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_inf_skip_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_inf_skip_cnt);
+}
+
+void flm_nthw_stat_inf_skip_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_inf_skip);
+ register_update(p->mp_stat_inf_skip);
+}
+
+void flm_nthw_stat_pck_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_hit_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_hit_cnt);
+}
+
+void flm_nthw_stat_pck_hit_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_hit);
+ register_update(p->mp_stat_pck_hit);
+}
+
+void flm_nthw_stat_pck_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_miss_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_miss_cnt);
+}
+
+void flm_nthw_stat_pck_miss_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_miss);
+ register_update(p->mp_stat_pck_miss);
+}
+
+void flm_nthw_stat_pck_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_unh_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_unh_cnt);
+}
+
+void flm_nthw_stat_pck_unh_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_unh);
+ register_update(p->mp_stat_pck_unh);
+}
+
+void flm_nthw_stat_pck_dis_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_dis_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_dis_cnt);
+}
+
+void flm_nthw_stat_pck_dis_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_dis);
+ register_update(p->mp_stat_pck_dis);
+}
+
+void flm_nthw_stat_csh_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_csh_hit_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_csh_hit_cnt);
+}
+
+void flm_nthw_stat_csh_hit_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_csh_hit);
+ register_update(p->mp_stat_csh_hit);
+}
+
+void flm_nthw_stat_csh_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_csh_miss_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_csh_miss_cnt);
+}
+
+void flm_nthw_stat_csh_miss_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_csh_miss);
+ register_update(p->mp_stat_csh_miss);
+}
+
+void flm_nthw_stat_csh_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_csh_unh_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_csh_unh_cnt);
+}
+
+void flm_nthw_stat_csh_unh_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_csh_unh);
+ register_update(p->mp_stat_csh_unh);
+}
+
+void flm_nthw_stat_cuc_start_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_cuc_start_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_cuc_start_cnt);
+}
+
+void flm_nthw_stat_cuc_start_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_cuc_start);
+ register_update(p->mp_stat_cuc_start);
+}
+
+void flm_nthw_stat_cuc_move_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_cuc_move_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_cuc_move_cnt);
+}
+
+void flm_nthw_stat_cuc_move_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_cuc_move);
+ register_update(p->mp_stat_cuc_move);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h
new file mode 100644
index 0000000000..4796d43940
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h
@@ -0,0 +1,422 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_FLM_H__
+#define __FLOW_NTHW_FLM_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct flm_nthw;
+
+typedef struct flm_nthw flm_nthw_t;
+
+struct flm_nthw *flm_nthw_new(void);
+void flm_nthw_delete(struct flm_nthw *p);
+int flm_nthw_init(struct flm_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+void flm_nthw_set_debug_mode(struct flm_nthw *p, unsigned int n_debug_mode);
+
+/* Control */
+void flm_nthw_control_enable(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_init(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_lds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_lfs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_lis(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_uds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_uis(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_rds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_ris(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_pds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_pis(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_crcwr(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_crcrd(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_rbl(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_eab(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_split_sdram_usage(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_flush(const struct flm_nthw *p);
+
+/* Status */
+void flm_nthw_status_calibdone(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_initdone(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_idle(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_critical(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_panic(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_crcerr(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_eft_bp(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_flush(const struct flm_nthw *p);
+void flm_nthw_status_update(const struct flm_nthw *p);
+
+/* Timeout */
+void flm_nthw_timeout_t(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_timeout_flush(const struct flm_nthw *p);
+
+/* Scrub */
+void flm_nthw_scrub_i(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_scrub_flush(const struct flm_nthw *p);
+
+/* Load BIN */
+void flm_nthw_load_bin(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_bin_flush(const struct flm_nthw *p);
+
+/* Load PPS */
+void flm_nthw_load_pps(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_pps_flush(const struct flm_nthw *p);
+
+/* Load LPS */
+void flm_nthw_load_lps(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_lps_flush(const struct flm_nthw *p);
+
+/* Load APS */
+void flm_nthw_load_aps(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_aps_flush(const struct flm_nthw *p);
+
+/* Prio */
+void flm_nthw_prio_limit0(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft0(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_limit1(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft1(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_limit2(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft2(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_limit3(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft3(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_flush(const struct flm_nthw *p);
+
+/* PST */
+void flm_nthw_pst_select(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_cnt(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_bp(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_pp(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_tp(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_flush(const struct flm_nthw *p);
+
+/* RCP */
+void flm_nthw_rcp_select(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_cnt(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_lookup(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw0_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw0_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw0_sel(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw4_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw4_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw8_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw8_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw8_sel(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw9_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw9_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_mask(const struct flm_nthw *p, const uint32_t *val);
+void flm_nthw_rcp_kid(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_opn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_ipn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_byt_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_byt_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_txplm(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_auto_ipv4_mask(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_flush(const struct flm_nthw *p);
+
+/* Buf Ctrl */
+int flm_nthw_buf_ctrl_update(const struct flm_nthw *p, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Lrn Data */
+int flm_nthw_lrn_data_flush(const struct flm_nthw *p, const uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Inf Data */
+int flm_nthw_inf_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Sta Data */
+int flm_nthw_sta_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Stat Lrn _done */
+void flm_nthw_stat_lrn_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_lrn_done_update(const struct flm_nthw *p);
+
+/* Stat Lrn Ignore */
+void flm_nthw_stat_lrn_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_lrn_ignore_update(const struct flm_nthw *p);
+
+/* Stat Lrn Fail */
+void flm_nthw_stat_lrn_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_lrn_fail_update(const struct flm_nthw *p);
+
+/* Stat Unl _done */
+void flm_nthw_stat_unl_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_unl_done_update(const struct flm_nthw *p);
+
+/* Stat Unl Ignore */
+void flm_nthw_stat_unl_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_unl_ignore_update(const struct flm_nthw *p);
+
+/* Stat Prb _done */
+void flm_nthw_stat_prb_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_prb_done_update(const struct flm_nthw *p);
+
+/* Stat Prb Ignore */
+void flm_nthw_stat_prb_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_prb_ignore_update(const struct flm_nthw *p);
+
+/* Stat Rel _done */
+void flm_nthw_stat_rel_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_rel_done_update(const struct flm_nthw *p);
+
+/* Stat Rel Ignore */
+void flm_nthw_stat_rel_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_rel_ignore_update(const struct flm_nthw *p);
+
+/* Stat Aul _done */
+void flm_nthw_stat_aul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_aul_done_update(const struct flm_nthw *p);
+
+/* Stat Aul Ignore */
+void flm_nthw_stat_aul_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_aul_ignore_update(const struct flm_nthw *p);
+
+/* Stat Aul Fail */
+void flm_nthw_stat_aul_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_aul_fail_update(const struct flm_nthw *p);
+
+/* Stat Tul _done */
+void flm_nthw_stat_tul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_tul_done_update(const struct flm_nthw *p);
+
+/* Stat Flows */
+void flm_nthw_stat_flows_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_flows_update(const struct flm_nthw *p);
+
+/* Stat Sta _done */
+void flm_nthw_stat_sta_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_sta_done_update(const struct flm_nthw *p);
+
+/* Stat Inf _done */
+void flm_nthw_stat_inf_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_inf_done_update(const struct flm_nthw *p);
+
+/* Stat Inf Skip */
+void flm_nthw_stat_inf_skip_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_inf_skip_update(const struct flm_nthw *p);
+
+/* Stat Pck Hit */
+void flm_nthw_stat_pck_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_hit_update(const struct flm_nthw *p);
+
+/* Stat Pck Miss */
+void flm_nthw_stat_pck_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_miss_update(const struct flm_nthw *p);
+
+/* Stat Pck Unh */
+void flm_nthw_stat_pck_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_unh_update(const struct flm_nthw *p);
+
+/* Stat Pck Dis */
+void flm_nthw_stat_pck_dis_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_dis_update(const struct flm_nthw *p);
+
+/* Stat Csh Hit */
+void flm_nthw_stat_csh_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_csh_hit_update(const struct flm_nthw *p);
+
+/* Stat Csh Miss */
+void flm_nthw_stat_csh_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_csh_miss_update(const struct flm_nthw *p);
+
+/* Stat Csh Unh */
+void flm_nthw_stat_csh_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_csh_unh_update(const struct flm_nthw *p);
+
+/* Stat Cuc Start */
+void flm_nthw_stat_cuc_start_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_cuc_start_update(const struct flm_nthw *p);
+
+/* Stat Cuc Move */
+void flm_nthw_stat_cuc_move_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_cuc_move_update(const struct flm_nthw *p);
+
+struct flm_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+ void *mp_rac;
+
+ nt_module_t *m_flm;
+
+ nt_register_t *mp_control;
+ nt_field_t *mp_control_enable;
+ nt_field_t *mp_control_init;
+ nt_field_t *mp_control_lds;
+ nt_field_t *mp_control_lfs;
+ nt_field_t *mp_control_lis;
+ nt_field_t *mp_control_uds;
+ nt_field_t *mp_control_uis;
+ nt_field_t *mp_control_rds;
+ nt_field_t *mp_control_ris;
+ nt_field_t *mp_control_pds;
+ nt_field_t *mp_control_pis;
+ nt_field_t *mp_control_crcwr;
+ nt_field_t *mp_control_crcrd;
+ nt_field_t *mp_control_rbl;
+ nt_field_t *mp_control_eab;
+ nt_field_t *mp_control_split_sdram_usage;
+
+ nt_register_t *mp_status;
+ nt_field_t *mp_status_calibdone;
+ nt_field_t *mp_status_initdone;
+ nt_field_t *mp_status_idle;
+ nt_field_t *mp_status_critical;
+ nt_field_t *mp_status_panic;
+ nt_field_t *mp_status_crcerr;
+ nt_field_t *mp_status_eft_bp;
+
+ nt_register_t *mp_timeout;
+ nt_field_t *mp_timeout_t;
+
+ nt_register_t *mp_scrub;
+ nt_field_t *mp_scrub_i;
+
+ nt_register_t *mp_load_bin;
+ nt_field_t *mp_load_bin_bin;
+
+ nt_register_t *mp_load_pps;
+ nt_field_t *mp_load_pps_pps;
+
+ nt_register_t *mp_load_lps;
+ nt_field_t *mp_load_lps_lps;
+
+ nt_register_t *mp_load_aps;
+ nt_field_t *mp_load_aps_aps;
+
+ nt_register_t *mp_prio;
+ nt_field_t *mp_prio_limit0;
+ nt_field_t *mp_prio_ft0;
+ nt_field_t *mp_prio_limit1;
+ nt_field_t *mp_prio_ft1;
+ nt_field_t *mp_prio_limit2;
+ nt_field_t *mp_prio_ft2;
+ nt_field_t *mp_prio_limit3;
+ nt_field_t *mp_prio_ft3;
+
+ nt_register_t *mp_pst_ctrl;
+ nt_field_t *mp_pst_ctrl_adr;
+ nt_field_t *mp_pst_ctrl_cnt;
+ nt_register_t *mp_pst_data;
+ nt_field_t *mp_pst_data_bp;
+ nt_field_t *mp_pst_data_pp;
+ nt_field_t *mp_pst_data_tp;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_ctrl_adr;
+ nt_field_t *mp_rcp_ctrl_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_lookup;
+ nt_field_t *mp_rcp_data_qw0_dyn;
+ nt_field_t *mp_rcp_data_qw0_ofs;
+ nt_field_t *mp_rcp_data_qw0_sel;
+ nt_field_t *mp_rcp_data_qw4_dyn;
+ nt_field_t *mp_rcp_data_qw4_ofs;
+ nt_field_t *mp_rcp_data_sw8_dyn;
+ nt_field_t *mp_rcp_data_sw8_ofs;
+ nt_field_t *mp_rcp_data_sw8_sel;
+ nt_field_t *mp_rcp_data_sw9_dyn;
+ nt_field_t *mp_rcp_data_sw9_ofs;
+ nt_field_t *mp_rcp_data_mask;
+ nt_field_t *mp_rcp_data_kid;
+ nt_field_t *mp_rcp_data_opn;
+ nt_field_t *mp_rcp_data_ipn;
+ nt_field_t *mp_rcp_data_byt_dyn;
+ nt_field_t *mp_rcp_data_byt_ofs;
+ nt_field_t *mp_rcp_data_txplm;
+ nt_field_t *mp_rcp_data_auto_ipv4_mask;
+
+ nt_register_t *mp_buf_ctrl;
+ nt_field_t *mp_buf_ctrl_lrn_free;
+ nt_field_t *mp_buf_ctrl_inf_avail;
+ nt_field_t *mp_buf_ctrl_sta_avail;
+
+ nt_register_t *mp_lrn_data;
+ nt_register_t *mp_inf_data;
+ nt_register_t *mp_sta_data;
+
+ nt_register_t *mp_stat_lrn_done;
+ nt_field_t *mp_stat_lrn_done_cnt;
+
+ nt_register_t *mp_stat_lrn_ignore;
+ nt_field_t *mp_stat_lrn_ignore_cnt;
+
+ nt_register_t *mp_stat_lrn_fail;
+ nt_field_t *mp_stat_lrn_fail_cnt;
+
+ nt_register_t *mp_stat_unl_done;
+ nt_field_t *mp_stat_unl_done_cnt;
+
+ nt_register_t *mp_stat_unl_ignore;
+ nt_field_t *mp_stat_unl_ignore_cnt;
+
+ nt_register_t *mp_stat_prb_done;
+ nt_field_t *mp_stat_prb_done_cnt;
+
+ nt_register_t *mp_stat_prb_ignore;
+ nt_field_t *mp_stat_prb_ignore_cnt;
+
+ nt_register_t *mp_stat_rel_done;
+ nt_field_t *mp_stat_rel_done_cnt;
+
+ nt_register_t *mp_stat_rel_ignore;
+ nt_field_t *mp_stat_rel_ignore_cnt;
+
+ nt_register_t *mp_stat_aul_done;
+ nt_field_t *mp_stat_aul_done_cnt;
+
+ nt_register_t *mp_stat_aul_ignore;
+ nt_field_t *mp_stat_aul_ignore_cnt;
+
+ nt_register_t *mp_stat_aul_fail;
+ nt_field_t *mp_stat_aul_fail_cnt;
+
+ nt_register_t *mp_stat_tul_done;
+ nt_field_t *mp_stat_tul_done_cnt;
+
+ nt_register_t *mp_stat_flows;
+ nt_field_t *mp_stat_flows_cnt;
+
+ nt_register_t *mp_stat_sta_done;
+ nt_field_t *mp_stat_sta_done_cnt;
+
+ nt_register_t *mp_stat_inf_done;
+ nt_field_t *mp_stat_inf_done_cnt;
+
+ nt_register_t *mp_stat_inf_skip;
+ nt_field_t *mp_stat_inf_skip_cnt;
+
+ nt_register_t *mp_stat_pck_hit;
+ nt_field_t *mp_stat_pck_hit_cnt;
+
+ nt_register_t *mp_stat_pck_miss;
+ nt_field_t *mp_stat_pck_miss_cnt;
+
+ nt_register_t *mp_stat_pck_unh;
+ nt_field_t *mp_stat_pck_unh_cnt;
+
+ nt_register_t *mp_stat_pck_dis;
+ nt_field_t *mp_stat_pck_dis_cnt;
+
+ nt_register_t *mp_stat_csh_hit;
+ nt_field_t *mp_stat_csh_hit_cnt;
+
+ nt_register_t *mp_stat_csh_miss;
+ nt_field_t *mp_stat_csh_miss_cnt;
+
+ nt_register_t *mp_stat_csh_unh;
+ nt_field_t *mp_stat_csh_unh_cnt;
+
+ nt_register_t *mp_stat_cuc_start;
+ nt_field_t *mp_stat_cuc_start_cnt;
+
+ nt_register_t *mp_stat_cuc_move;
+ nt_field_t *mp_stat_cuc_move_cnt;
+};
+
+#endif /* __FLOW_NTHW_FLM_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c
new file mode 100644
index 0000000000..b7fe7c5863
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_hfu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void hfu_nthw_set_debug_mode(struct hfu_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_hfu, n_debug_mode);
+}
+
+struct hfu_nthw *hfu_nthw_new(void)
+{
+ struct hfu_nthw *p = malloc(sizeof(struct hfu_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void hfu_nthw_delete(struct hfu_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int hfu_nthw_init(struct hfu_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HFU, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Hfu %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_hfu = fpga_query_module(p_fpga, MOD_HFU, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_hfu, HFU_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HFU_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HFU_RCP_CTRL_CNT);
+
+ p->mp_rcp_data = module_get_register(p->m_hfu, HFU_RCP_DATA);
+ p->mp_rcp_data_len_a_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_WR);
+ p->mp_rcp_data_len_a_ol4len =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_OL4LEN);
+ p->mp_rcp_data_len_a_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_POS_DYN);
+ p->mp_rcp_data_len_a_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_POS_OFS);
+ p->mp_rcp_data_len_a_add_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_ADD_DYN);
+ p->mp_rcp_data_len_a_add_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_ADD_OFS);
+ p->mp_rcp_data_len_a_sub_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_SUB_DYN);
+ p->mp_rcp_data_len_b_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_WR);
+ p->mp_rcp_data_len_b_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_POS_DYN);
+ p->mp_rcp_data_len_b_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_POS_OFS);
+ p->mp_rcp_data_len_b_add_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_ADD_DYN);
+ p->mp_rcp_data_len_b_add_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_ADD_OFS);
+ p->mp_rcp_data_len_b_sub_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_SUB_DYN);
+ p->mp_rcp_data_len_c_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_WR);
+ p->mp_rcp_data_len_c_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_POS_DYN);
+ p->mp_rcp_data_len_c_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_POS_OFS);
+ p->mp_rcp_data_len_c_add_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_ADD_DYN);
+ p->mp_rcp_data_len_c_add_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_ADD_OFS);
+ p->mp_rcp_data_len_c_sub_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_SUB_DYN);
+ p->mp_rcp_data_ttl_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_WR);
+ p->mp_rcp_data_ttl_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_POS_DYN);
+ p->mp_rcp_data_ttl_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_POS_OFS);
+ p->mp_rcp_data_csinf = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_CSINF);
+ p->mp_rcp_data_l3prt = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L3PRT);
+ p->mp_rcp_data_l3frag =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L3FRAG);
+ p->mp_rcp_data_tunnel =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TUNNEL);
+ p->mp_rcp_data_l4prt = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L4PRT);
+ p->mp_rcp_data_ol3ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_OL3OFS);
+ p->mp_rcp_data_ol4ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_OL4OFS);
+ p->mp_rcp_data_il3ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_IL3OFS);
+ p->mp_rcp_data_il4ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_IL4OFS);
+
+ return 0;
+}
+
+void hfu_nthw_rcp_select(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void hfu_nthw_rcp_cnt(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void hfu_nthw_rcp_len_a_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_wr, val);
+}
+
+void hfu_nthw_rcp_len_a_ol4len(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_ol4len, val);
+}
+
+void hfu_nthw_rcp_len_a_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_len_a_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_len_a_add_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_add_dyn, val);
+}
+
+void hfu_nthw_rcp_len_a_add_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_add_ofs, val);
+}
+
+void hfu_nthw_rcp_len_a_sub_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_sub_dyn, val);
+}
+
+void hfu_nthw_rcp_len_b_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_wr, val);
+}
+
+void hfu_nthw_rcp_len_b_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_len_b_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_len_b_add_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_add_dyn, val);
+}
+
+void hfu_nthw_rcp_len_b_add_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_add_ofs, val);
+}
+
+void hfu_nthw_rcp_len_b_sub_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_sub_dyn, val);
+}
+
+void hfu_nthw_rcp_len_c_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_wr, val);
+}
+
+void hfu_nthw_rcp_len_c_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_len_c_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_len_c_add_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_add_dyn, val);
+}
+
+void hfu_nthw_rcp_len_c_add_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_add_ofs, val);
+}
+
+void hfu_nthw_rcp_len_c_sub_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_sub_dyn, val);
+}
+
+void hfu_nthw_rcp_ttl_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ttl_wr, val);
+}
+
+void hfu_nthw_rcp_ttl_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ttl_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_ttl_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ttl_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_csinf(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_csinf, val);
+}
+
+void hfu_nthw_rcp_l3prt(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_l3prt, val);
+}
+
+void hfu_nthw_rcp_l3frag(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_l3frag, val);
+}
+
+void hfu_nthw_rcp_tunnel(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tunnel, val);
+}
+
+void hfu_nthw_rcp_l4prt(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_l4prt, val);
+}
+
+void hfu_nthw_rcp_ol3ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ol3ofs, val);
+}
+
+void hfu_nthw_rcp_ol4ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ol4ofs, val);
+}
+
+void hfu_nthw_rcp_il3ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_il3ofs, val);
+}
+
+void hfu_nthw_rcp_il4ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_il4ofs, val);
+}
+
+void hfu_nthw_rcp_flush(const struct hfu_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h
new file mode 100644
index 0000000000..ecba1a8822
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_HFU_H__
+#define __FLOW_NTHW_HFU_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct hfu_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_hfu;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_len_a_wr;
+ nt_field_t *mp_rcp_data_len_a_ol4len;
+ nt_field_t *mp_rcp_data_len_a_pos_dyn;
+ nt_field_t *mp_rcp_data_len_a_pos_ofs;
+ nt_field_t *mp_rcp_data_len_a_add_dyn;
+ nt_field_t *mp_rcp_data_len_a_add_ofs;
+ nt_field_t *mp_rcp_data_len_a_sub_dyn;
+ nt_field_t *mp_rcp_data_len_b_wr;
+ nt_field_t *mp_rcp_data_len_b_pos_dyn;
+ nt_field_t *mp_rcp_data_len_b_pos_ofs;
+ nt_field_t *mp_rcp_data_len_b_add_dyn;
+ nt_field_t *mp_rcp_data_len_b_add_ofs;
+ nt_field_t *mp_rcp_data_len_b_sub_dyn;
+ nt_field_t *mp_rcp_data_len_c_wr;
+ nt_field_t *mp_rcp_data_len_c_pos_dyn;
+ nt_field_t *mp_rcp_data_len_c_pos_ofs;
+ nt_field_t *mp_rcp_data_len_c_add_dyn;
+ nt_field_t *mp_rcp_data_len_c_add_ofs;
+ nt_field_t *mp_rcp_data_len_c_sub_dyn;
+ nt_field_t *mp_rcp_data_ttl_wr;
+ nt_field_t *mp_rcp_data_ttl_pos_dyn;
+ nt_field_t *mp_rcp_data_ttl_pos_ofs;
+ nt_field_t *mp_rcp_data_csinf;
+ nt_field_t *mp_rcp_data_l3prt;
+ nt_field_t *mp_rcp_data_l3frag;
+ nt_field_t *mp_rcp_data_tunnel;
+ nt_field_t *mp_rcp_data_l4prt;
+ nt_field_t *mp_rcp_data_ol3ofs;
+ nt_field_t *mp_rcp_data_ol4ofs;
+ nt_field_t *mp_rcp_data_il3ofs;
+ nt_field_t *mp_rcp_data_il4ofs;
+};
+
+struct hfu_nthw *hfu_nthw_new(void);
+void hfu_nthw_delete(struct hfu_nthw *p);
+int hfu_nthw_init(struct hfu_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int hfu_nthw_setup(struct hfu_nthw *p, int n_idx, int n_idx_cnt);
+void hfu_nthw_set_debug_mode(struct hfu_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void hfu_nthw_rcp_select(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_cnt(const struct hfu_nthw *p, uint32_t val);
+
+void hfu_nthw_rcp_len_a_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_ol4len(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_add_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_add_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_sub_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_add_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_add_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_sub_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_add_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_add_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_sub_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ttl_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ttl_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ttl_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_csinf(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_l3prt(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_l3frag(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_tunnel(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_l4prt(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ol3ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ol4ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_il3ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_il4ofs(const struct hfu_nthw *p, uint32_t val);
+
+void hfu_nthw_rcp_flush(const struct hfu_nthw *p);
+
+#endif /* __FLOW_NTHW_HFU_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c
new file mode 100644
index 0000000000..0dc6434e88
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_hsh.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void hsh_nthw_set_debug_mode(struct hsh_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_hsh, n_debug_mode);
+}
+
+struct hsh_nthw *hsh_nthw_new(void)
+{
+ struct hsh_nthw *p = malloc(sizeof(struct hsh_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void hsh_nthw_delete(struct hsh_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int hsh_nthw_init(struct hsh_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HSH, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Hsh %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_hsh = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_hsh, HSH_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HSH_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HSH_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_hsh, HSH_RCP_DATA);
+ p->mp_rcp_data_load_dist_type =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_LOAD_DIST_TYPE);
+ p->mp_rcp_data_mac_port_mask =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_MAC_PORT_MASK);
+ p->mp_rcp_data_sort = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_SORT);
+ p->mp_rcp_data_qw0_pe =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW0_PE);
+ p->mp_rcp_data_qw0_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW0_OFS);
+ p->mp_rcp_data_qw4_pe =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW4_PE);
+ p->mp_rcp_data_qw4_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW4_OFS);
+ p->mp_rcp_data_w8_pe = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_PE);
+ p->mp_rcp_data_w8_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_OFS);
+ p->mp_rcp_data_w8_sort =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_SORT);
+ p->mp_rcp_data_w9_pe = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_PE);
+ p->mp_rcp_data_w9_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_OFS);
+ p->mp_rcp_data_w9_sort =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_SORT);
+ p->mp_rcp_data_w9_p = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_P);
+ p->mp_rcp_data_p_mask =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_P_MASK);
+ p->mp_rcp_data_word_mask =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_WORD_MASK);
+ p->mp_rcp_data_seed = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_SEED);
+ p->mp_rcp_data_tnl_p = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_TNL_P);
+ p->mp_rcp_data_hsh_valid =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_HSH_VALID);
+ p->mp_rcp_data_hsh_type =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_HSH_TYPE);
+ p->mp_rcp_data_auto_ipv4_mask =
+ register_query_field(p->mp_rcp_data, HSH_RCP_DATA_AUTO_IPV4_MASK);
+
+ /* Init */
+ uint32_t val[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ field_set_val32(p->mp_rcp_addr, 0);
+ field_set_val32(p->mp_rcp_cnt, 1);
+
+ field_set_val32(p->mp_rcp_data_load_dist_type, 0);
+ field_set_val(p->mp_rcp_data_mac_port_mask, val,
+ p->mp_rcp_data_mac_port_mask->mn_words);
+ field_set_val32(p->mp_rcp_data_sort, 0);
+ field_set_val32(p->mp_rcp_data_qw0_pe, 0);
+ field_set_val32(p->mp_rcp_data_qw0_ofs, 0);
+ field_set_val32(p->mp_rcp_data_qw4_pe, 0);
+ field_set_val32(p->mp_rcp_data_qw4_ofs, 0);
+ field_set_val32(p->mp_rcp_data_w8_pe, 0);
+ field_set_val32(p->mp_rcp_data_w8_ofs, 0);
+ field_set_val32(p->mp_rcp_data_w8_sort, 0);
+ field_set_val32(p->mp_rcp_data_w9_pe, 0);
+ field_set_val32(p->mp_rcp_data_w9_ofs, 0);
+ field_set_val32(p->mp_rcp_data_w9_sort, 0);
+ field_set_val32(p->mp_rcp_data_w9_p, 0);
+ field_set_val(p->mp_rcp_data_word_mask, val, 10);
+ field_set_val32(p->mp_rcp_data_seed, 0);
+ field_set_val32(p->mp_rcp_data_tnl_p, 0);
+ field_set_val32(p->mp_rcp_data_hsh_valid, 0);
+ field_set_val32(p->mp_rcp_data_hsh_type, 31);
+
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+
+ return 0;
+}
+
+void hsh_nthw_rcp_select(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void hsh_nthw_rcp_cnt(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void hsh_nthw_rcp_load_dist_type(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_load_dist_type, val);
+}
+
+void hsh_nthw_rcp_mac_port_mask(const struct hsh_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mac_port_mask, val,
+ p->mp_rcp_data_mac_port_mask->mn_words);
+}
+
+void hsh_nthw_rcp_sort(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sort, val);
+}
+
+void hsh_nthw_rcp_qw0_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_pe, val);
+}
+
+void hsh_nthw_rcp_qw0_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_ofs, val);
+}
+
+void hsh_nthw_rcp_qw4_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_pe, val);
+}
+
+void hsh_nthw_rcp_qw4_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_ofs, val);
+}
+
+void hsh_nthw_rcp_w8_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w8_pe, val);
+}
+
+void hsh_nthw_rcp_w8_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w8_ofs, val);
+}
+
+void hsh_nthw_rcp_w8_sort(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w8_sort, val);
+}
+
+void hsh_nthw_rcp_w9_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_pe, val);
+}
+
+void hsh_nthw_rcp_w9_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_ofs, val);
+}
+
+void hsh_nthw_rcp_w9_sort(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_sort, val);
+}
+
+void hsh_nthw_rcp_w9_p(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_p, val);
+}
+
+void hsh_nthw_rcp_p_mask(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_p_mask, val);
+}
+
+void hsh_nthw_rcp_word_mask(const struct hsh_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_word_mask, val, 10);
+}
+
+void hsh_nthw_rcp_seed(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_seed, val);
+}
+
+void hsh_nthw_rcp_tnl_p(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tnl_p, val);
+}
+
+void hsh_nthw_rcp_hsh_valid(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_hsh_valid, val);
+}
+
+void hsh_nthw_rcp_hsh_type(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_hsh_type, val);
+}
+
+void hsh_nthw_rcp_auto_ipv4_mask(const struct hsh_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_auto_ipv4_mask)
+ field_set_val32(p->mp_rcp_data_auto_ipv4_mask, val);
+}
+
+void hsh_nthw_rcp_flush(const struct hsh_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h
new file mode 100644
index 0000000000..7cb7dbb743
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_HSH_H__
+#define __FLOW_NTHW_HSH_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct hsh_nthw;
+
+typedef struct hsh_nthw hsh_nthw_t;
+
+struct hsh_nthw *hsh_nthw_new(void);
+void hsh_nthw_delete(struct hsh_nthw *p);
+int hsh_nthw_init(struct hsh_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int hsh_nthw_setup(struct hsh_nthw *p, int n_idx, int n_idx_cnt);
+void hsh_nthw_set_debug_mode(struct hsh_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void hsh_nthw_rcp_select(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_cnt(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_load_dist_type(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_mac_port_mask(const struct hsh_nthw *p, uint32_t *val);
+void hsh_nthw_rcp_sort(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_qw0_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_qw0_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_qw4_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_qw4_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_w8_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w8_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_w8_sort(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w9_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w9_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_w9_sort(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w9_p(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_p_mask(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_word_mask(const struct hsh_nthw *p, uint32_t *val);
+void hsh_nthw_rcp_seed(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_tnl_p(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_hsh_valid(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_hsh_type(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_auto_ipv4_mask(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_flush(const struct hsh_nthw *p);
+
+struct hsh_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_hsh;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_load_dist_type;
+ nt_field_t *mp_rcp_data_mac_port_mask;
+ nt_field_t *mp_rcp_data_sort;
+ nt_field_t *mp_rcp_data_qw0_pe;
+ nt_field_t *mp_rcp_data_qw0_ofs;
+ nt_field_t *mp_rcp_data_qw4_pe;
+ nt_field_t *mp_rcp_data_qw4_ofs;
+ nt_field_t *mp_rcp_data_w8_pe;
+ nt_field_t *mp_rcp_data_w8_ofs;
+ nt_field_t *mp_rcp_data_w8_sort;
+ nt_field_t *mp_rcp_data_w9_pe;
+ nt_field_t *mp_rcp_data_w9_ofs;
+ nt_field_t *mp_rcp_data_w9_sort;
+ nt_field_t *mp_rcp_data_w9_p;
+ nt_field_t *mp_rcp_data_p_mask;
+ nt_field_t *mp_rcp_data_word_mask;
+ nt_field_t *mp_rcp_data_seed;
+ nt_field_t *mp_rcp_data_tnl_p;
+ nt_field_t *mp_rcp_data_hsh_valid;
+ nt_field_t *mp_rcp_data_hsh_type;
+ nt_field_t *mp_rcp_data_auto_ipv4_mask;
+};
+
+#endif /* __FLOW_NTHW_HSH_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c
new file mode 100644
index 0000000000..fc3dc443a2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_hst.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void hst_nthw_set_debug_mode(struct hst_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_hst, n_debug_mode);
+}
+
+struct hst_nthw *hst_nthw_new(void)
+{
+ struct hst_nthw *p = malloc(sizeof(struct hst_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void hst_nthw_delete(struct hst_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int hst_nthw_init(struct hst_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HST, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Hst %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_hst = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_hst, HST_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HST_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HST_RCP_CTRL_CNT);
+
+ p->mp_rcp_data = module_get_register(p->m_hst, HST_RCP_DATA);
+ p->mp_rcp_data_strip_mode =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_STRIP_MODE);
+ p->mp_rcp_data_start_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_START_DYN);
+ p->mp_rcp_data_start_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_START_OFS);
+ p->mp_rcp_data_end_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_END_DYN);
+ p->mp_rcp_data_end_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_END_OFS);
+ p->mp_rcp_data_modif0_cmd =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_CMD);
+ p->mp_rcp_data_modif0_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_DYN);
+ p->mp_rcp_data_modif0_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_OFS);
+ p->mp_rcp_data_modif0_value =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_VALUE);
+ p->mp_rcp_data_modif1_cmd =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_CMD);
+ p->mp_rcp_data_modif1_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_DYN);
+ p->mp_rcp_data_modif1_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_OFS);
+ p->mp_rcp_data_modif1_value =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_VALUE);
+ p->mp_rcp_data_modif2_cmd =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_CMD);
+ p->mp_rcp_data_modif2_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_DYN);
+ p->mp_rcp_data_modif2_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_OFS);
+ p->mp_rcp_data_modif2_value =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_VALUE);
+
+ return 0;
+}
+
+/* RCP */
+void hst_nthw_rcp_select(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void hst_nthw_rcp_cnt(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void hst_nthw_rcp_strip_mode(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_strip_mode, val);
+}
+
+void hst_nthw_rcp_start_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_start_dyn, val);
+}
+
+void hst_nthw_rcp_start_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_start_ofs, val);
+}
+
+void hst_nthw_rcp_end_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_end_dyn, val);
+}
+
+void hst_nthw_rcp_end_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_end_ofs, val);
+}
+
+void hst_nthw_rcp_modif0_cmd(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_cmd, val);
+}
+
+void hst_nthw_rcp_modif0_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_dyn, val);
+}
+
+void hst_nthw_rcp_modif0_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_ofs, val);
+}
+
+void hst_nthw_rcp_modif0_value(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_value, val);
+}
+
+void hst_nthw_rcp_modif1_cmd(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_cmd, val);
+}
+
+void hst_nthw_rcp_modif1_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_dyn, val);
+}
+
+void hst_nthw_rcp_modif1_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_ofs, val);
+}
+
+void hst_nthw_rcp_modif1_value(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_value, val);
+}
+
+void hst_nthw_rcp_modif2_cmd(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_cmd, val);
+}
+
+void hst_nthw_rcp_modif2_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_dyn, val);
+}
+
+void hst_nthw_rcp_modif2_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_ofs, val);
+}
+
+void hst_nthw_rcp_modif2_value(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_value, val);
+}
+
+void hst_nthw_rcp_flush(const struct hst_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h
new file mode 100644
index 0000000000..5bc7eb6e55
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_HST_H__
+#define __FLOW_NTHW_HST_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct hst_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_hst;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_strip_mode;
+ nt_field_t *mp_rcp_data_start_dyn;
+ nt_field_t *mp_rcp_data_start_ofs;
+ nt_field_t *mp_rcp_data_end_dyn;
+ nt_field_t *mp_rcp_data_end_ofs;
+ nt_field_t *mp_rcp_data_modif0_cmd;
+ nt_field_t *mp_rcp_data_modif0_dyn;
+ nt_field_t *mp_rcp_data_modif0_ofs;
+ nt_field_t *mp_rcp_data_modif0_value;
+ nt_field_t *mp_rcp_data_modif1_cmd;
+ nt_field_t *mp_rcp_data_modif1_dyn;
+ nt_field_t *mp_rcp_data_modif1_ofs;
+ nt_field_t *mp_rcp_data_modif1_value;
+ nt_field_t *mp_rcp_data_modif2_cmd;
+ nt_field_t *mp_rcp_data_modif2_dyn;
+ nt_field_t *mp_rcp_data_modif2_ofs;
+ nt_field_t *mp_rcp_data_modif2_value;
+};
+
+typedef struct hst_nthw hst_nthw_t;
+
+struct hst_nthw *hst_nthw_new(void);
+void hst_nthw_delete(struct hst_nthw *p);
+int hst_nthw_init(struct hst_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int hst_nthw_setup(struct hst_nthw *p, int n_idx, int n_idx_cnt);
+void hst_nthw_set_debug_mode(struct hst_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void hst_nthw_rcp_select(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_cnt(const struct hst_nthw *p, uint32_t val);
+
+void hst_nthw_rcp_strip_mode(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_start_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_start_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_end_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_end_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_cmd(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_value(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_cmd(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_value(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_cmd(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_value(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_flush(const struct hst_nthw *p);
+
+#endif /* __FLOW_NTHW_HST_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c
new file mode 100644
index 0000000000..0f51a36e57
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_ifr.h"
+
+void ifr_nthw_set_debug_mode(struct ifr_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_ifr, n_debug_mode);
+}
+
+struct ifr_nthw *ifr_nthw_new(void)
+{
+ struct ifr_nthw *p = malloc(sizeof(struct ifr_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void ifr_nthw_delete(struct ifr_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int ifr_nthw_init(struct ifr_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_IFR, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Ifr %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_ifr = fpga_query_module(p_fpga, MOD_IFR, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_ifr, IFR_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, IFR_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, IFR_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_ifr, IFR_RCP_DATA);
+ p->mp_rcp_data_en = register_get_field(p->mp_rcp_data, IFR_RCP_DATA_EN);
+ p->mp_rcp_data_mtu = register_get_field(p->mp_rcp_data, IFR_RCP_DATA_MTU);
+
+ return 0;
+}
+
+void ifr_nthw_rcp_select(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_addr);
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void ifr_nthw_rcp_cnt(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_cnt);
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void ifr_nthw_rcp_en(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_data_en);
+ field_set_val32(p->mp_rcp_data_en, val);
+}
+
+void ifr_nthw_rcp_mtu(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_data_en);
+ field_set_val32(p->mp_rcp_data_mtu, val);
+}
+
+void ifr_nthw_rcp_flush(const struct ifr_nthw *p)
+{
+ assert(p->mp_rcp_ctrl);
+ assert(p->mp_rcp_data);
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h
new file mode 100644
index 0000000000..626ca3d193
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_IFR_H__
+#define __FLOW_NTHW_IFR_H__
+
+#include "nthw_fpga_model.h"
+
+struct ifr_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_ifr;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_en;
+ nt_field_t *mp_rcp_data_mtu;
+};
+
+struct ifr_nthw *ifr_nthw_new(void);
+void ifr_nthw_delete(struct ifr_nthw *p);
+int ifr_nthw_init(struct ifr_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int ifr_nthw_setup(struct ifr_nthw *p, int n_idx, int n_idx_cnt);
+void ifr_nthw_set_debug_mode(struct ifr_nthw *p, unsigned int n_debug_mode);
+
+/* IFR */
+void ifr_nthw_rcp_select(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_cnt(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_en(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_mtu(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_flush(const struct ifr_nthw *p);
+
+#endif /* __FLOW_NTHW_IFR_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c
new file mode 100644
index 0000000000..27b55e3b7c
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga_model.h"
+
+#include "flow_nthw_info.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+static inline unsigned int clamp_one(unsigned int val)
+{
+ return val > 1 ? 1 : val;
+}
+
+struct info_nthw *info_nthw_new(void)
+{
+ struct info_nthw *p = malloc(sizeof(struct info_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void info_nthw_delete(struct info_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int info_nthw_init(struct info_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ assert(n_instance >= 0 && n_instance < 256);
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+
+ unsigned int km_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_KM_PRESENT, 0));
+ unsigned int kcc_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_CAT_KCC_PRESENT, 0));
+ unsigned int ioa_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0));
+ unsigned int roa_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_ROA_PRESENT, 0));
+ unsigned int dbs_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0));
+ unsigned int flm_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_FLM_PRESENT, 0));
+ unsigned int hst_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_HST_PRESENT, 0));
+
+ /* Modules for Tx Packet Edit function */
+ unsigned int hfu_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_HFU_PRESENT, 0));
+ unsigned int tx_cpy_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_TX_CPY_PRESENT, 0));
+ unsigned int tx_ins_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_TX_INS_PRESENT, 0));
+ unsigned int tx_rpl_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_TX_RPL_PRESENT, 0));
+ unsigned int csu_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_CSU_PRESENT, 0));
+ unsigned int tpe_present = (hfu_present && tx_cpy_present && tx_ins_present &&
+ tx_rpl_present && csu_present) ?
+ 1 :
+ 0;
+
+ p->n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0);
+ p->n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, 0);
+ p->n_ltx_avail = fpga_get_product_param(p_fpga, NT_LR_PRESENT, 0);
+ p->nb_cat_func = fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0);
+ p->nb_categories = fpga_get_product_param(p_fpga, NT_CATEGORIES, 0);
+ p->nb_queues = fpga_get_product_param(p_fpga, NT_QUEUES, 0);
+ p->nb_flow_types = fpga_get_product_param(p_fpga, NT_KM_FLOW_TYPES, 0) *
+ clamp_one(km_present + flm_present);
+ p->nb_pm_ext = fpga_get_product_param(p_fpga, NT_CAT_N_EXT, 0);
+ p->nb_len = fpga_get_product_param(p_fpga, NT_CAT_N_LEN, 0);
+ p->nb_kcc_size =
+ fpga_get_product_param(p_fpga, NT_CAT_KCC_SIZE, 0) * kcc_present;
+ p->nb_kcc_banks =
+ fpga_get_product_param(p_fpga, NT_CAT_KCC_BANKS, 0) * kcc_present;
+ p->nb_km_categories =
+ fpga_get_product_param(p_fpga, NT_KM_CATEGORIES, 0) * km_present;
+ p->nb_km_cam_banks =
+ fpga_get_product_param(p_fpga, NT_KM_CAM_BANKS, 0) * km_present;
+ p->nb_km_cam_record_words =
+ fpga_get_product_param(p_fpga, NT_KM_CAM_REC_WORDS, 0) * km_present;
+ p->nb_km_cam_records =
+ fpga_get_product_param(p_fpga, NT_KM_CAM_RECORDS, 0) * km_present;
+ p->nb_km_tcam_banks =
+ fpga_get_product_param(p_fpga, NT_KM_TCAM_BANKS, 0) * km_present;
+ p->nb_km_tcam_bank_width =
+ fpga_get_product_param(p_fpga, NT_KM_TCAM_BANK_WIDTH, 0) *
+ km_present;
+ p->nb_flm_categories =
+ fpga_get_product_param(p_fpga, NT_FLM_CATEGORIES, 0) * flm_present;
+ p->nb_flm_size_mb = fpga_get_product_param(p_fpga, NT_FLM_SIZE_MB, 0);
+ p->nb_flm_entry_size = fpga_get_product_param(p_fpga, NT_FLM_ENTRY_SIZE, 0);
+ p->nb_flm_variant = fpga_get_product_param(p_fpga, NT_FLM_VARIANT, 0);
+ p->nb_flm_prios =
+ fpga_get_product_param(p_fpga, NT_FLM_PRIOS, 0) * flm_present;
+ p->nb_flm_pst_profiles =
+ fpga_get_product_param(p_fpga, NT_FLM_PST_PROFILES, 0) *
+ flm_present;
+ p->nb_hst_categories =
+ fpga_get_product_param(p_fpga, NT_HST_CATEGORIES, 0) * hst_present;
+ p->nb_qsl_categories = fpga_get_product_param(p_fpga, NT_QSL_CATEGORIES, 0);
+ p->nb_qsl_qst_entries = fpga_get_product_param(p_fpga, NT_QSL_QST_SIZE, 0);
+ p->nb_pdb_categories = fpga_get_product_param(p_fpga, NT_PDB_CATEGORIES, 0);
+ p->nb_ioa_categories =
+ fpga_get_product_param(p_fpga, NT_IOA_CATEGORIES, 0) * ioa_present;
+ p->nb_roa_categories =
+ fpga_get_product_param(p_fpga, NT_ROA_CATEGORIES, 0) * roa_present;
+ p->nb_dbs_categories =
+ RTE_MIN(fpga_get_product_param(p_fpga, NT_DBS_RX_QUEUES, 0),
+ fpga_get_product_param(p_fpga, NT_DBS_TX_QUEUES, 0)) *
+ dbs_present;
+ p->nb_cat_km_if_cnt = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_CNT,
+ km_present + flm_present);
+ p->m_cat_km_if_m0 = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_M0, -1);
+ p->m_cat_km_if_m1 = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_M1, -1);
+ p->nb_tpe_categories =
+ fpga_get_product_param(p_fpga, NT_TPE_CATEGORIES, 0) * tpe_present;
+ p->nb_tx_cpy_writers =
+ fpga_get_product_param(p_fpga, NT_TX_CPY_WRITERS, 0) * tpe_present;
+ p->nb_tx_cpy_mask_mem =
+ fpga_get_product_param(p_fpga, NT_CPY_MASK_MEM, 0) * tpe_present;
+ p->nb_tx_rpl_depth =
+ fpga_get_product_param(p_fpga, NT_TX_RPL_DEPTH, 0) * tpe_present;
+ p->nb_tx_rpl_ext_categories =
+ fpga_get_product_param(p_fpga, NT_TX_RPL_EXT_CATEGORIES, 0) *
+ tpe_present;
+ p->nb_tpe_ifr_categories =
+ fpga_get_product_param(p_fpga, NT_TX_MTU_PROFILE_IFR, 0);
+ return 0;
+}
+
+unsigned int info_nthw_get_nb_phy_ports(const struct info_nthw *p)
+{
+ return p->n_phy_ports;
+}
+
+unsigned int info_nthw_get_nb_rx_ports(const struct info_nthw *p)
+{
+ return p->n_rx_ports;
+}
+
+unsigned int info_nthw_get_ltx_avail(const struct info_nthw *p)
+{
+ return p->n_ltx_avail;
+}
+
+unsigned int info_nthw_get_nb_categories(const struct info_nthw *p)
+{
+ return p->nb_categories;
+}
+
+unsigned int info_nthw_get_kcc_size(const struct info_nthw *p)
+{
+ return p->nb_kcc_size;
+}
+
+unsigned int info_nthw_get_kcc_banks(const struct info_nthw *p)
+{
+ return p->nb_kcc_banks;
+}
+
+unsigned int info_nthw_get_nb_queues(const struct info_nthw *p)
+{
+ return p->nb_queues;
+}
+
+unsigned int info_nthw_get_nb_cat_funcs(const struct info_nthw *p)
+{
+ return p->nb_cat_func;
+}
+
+unsigned int info_nthw_get_nb_km_flow_types(const struct info_nthw *p)
+{
+ return p->nb_flow_types;
+}
+
+unsigned int info_nthw_get_nb_pm_ext(const struct info_nthw *p)
+{
+ return p->nb_pm_ext;
+}
+
+unsigned int info_nthw_get_nb_len(const struct info_nthw *p)
+{
+ return p->nb_len;
+}
+
+unsigned int info_nthw_get_nb_km_categories(const struct info_nthw *p)
+{
+ return p->nb_km_categories;
+}
+
+unsigned int info_nthw_get_nb_km_cam_banks(const struct info_nthw *p)
+{
+ return p->nb_km_cam_banks;
+}
+
+unsigned int info_nthw_get_nb_km_cam_record_words(const struct info_nthw *p)
+{
+ return p->nb_km_cam_record_words;
+}
+
+unsigned int info_nthw_get_nb_km_cam_records(const struct info_nthw *p)
+{
+ return p->nb_km_cam_records;
+}
+
+unsigned int info_nthw_get_nb_km_tcam_banks(const struct info_nthw *p)
+{
+ return p->nb_km_tcam_banks;
+}
+
+unsigned int info_nthw_get_nb_km_tcam_bank_width(const struct info_nthw *p)
+{
+ return p->nb_km_tcam_bank_width;
+}
+
+unsigned int info_nthw_get_nb_flm_categories(const struct info_nthw *p)
+{
+ return p->nb_flm_categories;
+}
+
+unsigned int info_nthw_get_nb_flm_size_mb(const struct info_nthw *p)
+{
+ return p->nb_flm_size_mb;
+}
+
+unsigned int info_nthw_get_nb_flm_entry_size(const struct info_nthw *p)
+{
+ return p->nb_flm_entry_size;
+}
+
+unsigned int info_nthw_get_nb_flm_variant(const struct info_nthw *p)
+{
+ return p->nb_flm_variant;
+}
+
+unsigned int info_nthw_get_nb_flm_prios(const struct info_nthw *p)
+{
+ return p->nb_flm_prios;
+}
+
+unsigned int info_nthw_get_nb_flm_pst_profiles(const struct info_nthw *p)
+{
+ return p->nb_flm_pst_profiles;
+}
+
+unsigned int info_nthw_get_nb_hst_categories(const struct info_nthw *p)
+{
+ return p->nb_hst_categories;
+}
+
+unsigned int info_nthw_get_nb_qsl_categories(const struct info_nthw *p)
+{
+ return p->nb_qsl_categories;
+}
+
+unsigned int info_nthw_get_nb_qsl_qst_entries(const struct info_nthw *p)
+{
+ return p->nb_qsl_qst_entries;
+}
+
+unsigned int info_nthw_get_nb_pdb_categories(const struct info_nthw *p)
+{
+ return p->nb_pdb_categories;
+}
+
+unsigned int info_nthw_get_nb_ioa_categories(const struct info_nthw *p)
+{
+ return p->nb_ioa_categories;
+}
+
+unsigned int info_nthw_get_nb_roa_categories(const struct info_nthw *p)
+{
+ return p->nb_roa_categories;
+}
+
+unsigned int info_nthw_get_nb_dbs_categories(const struct info_nthw *p)
+{
+ return p->nb_dbs_categories;
+}
+
+unsigned int info_nthw_get_nb_cat_km_if_cnt(const struct info_nthw *p)
+{
+ return p->nb_cat_km_if_cnt;
+}
+
+unsigned int info_nthw_get_nb_cat_km_if_m0(const struct info_nthw *p)
+{
+ return p->m_cat_km_if_m0;
+}
+
+unsigned int info_nthw_get_nb_cat_km_if_m1(const struct info_nthw *p)
+{
+ return p->m_cat_km_if_m1;
+}
+
+unsigned int info_nthw_get_nb_tpe_categories(const struct info_nthw *p)
+{
+ return p->nb_tpe_categories;
+}
+
+unsigned int info_nthw_get_nb_tx_cpy_writers(const struct info_nthw *p)
+{
+ return p->nb_tx_cpy_writers;
+}
+
+unsigned int info_nthw_get_nb_tx_cpy_mask_mem(const struct info_nthw *p)
+{
+ return p->nb_tx_cpy_mask_mem;
+}
+
+unsigned int info_nthw_get_nb_tx_rpl_depth(const struct info_nthw *p)
+{
+ return p->nb_tx_rpl_depth;
+}
+
+unsigned int info_nthw_get_nb_tx_rpl_ext_categories(const struct info_nthw *p)
+{
+ return p->nb_tx_rpl_ext_categories;
+}
+
+unsigned int info_nthw_get_nb_tpe_ifr_categories(const struct info_nthw *p)
+{
+ return p->nb_tpe_ifr_categories;
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h
new file mode 100644
index 0000000000..c697ba84e9
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_INFO_H__
+#define __FLOW_NTHW_INFO_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct info_nthw;
+
+struct info_nthw *info_nthw_new(void);
+void info_nthw_delete(struct info_nthw *p);
+int info_nthw_init(struct info_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int info_nthw_setup(struct info_nthw *p, int n_idx, int n_idx_cnt);
+
+unsigned int info_nthw_get_nb_phy_ports(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_rx_ports(const struct info_nthw *p);
+unsigned int info_nthw_get_ltx_avail(const struct info_nthw *p);
+
+unsigned int info_nthw_get_nb_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_queues(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_funcs(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_flow_types(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_pm_ext(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_len(const struct info_nthw *p);
+unsigned int info_nthw_get_kcc_size(const struct info_nthw *p);
+unsigned int info_nthw_get_kcc_banks(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_cam_banks(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_cam_record_words(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_cam_records(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_tcam_banks(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_tcam_bank_width(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_size_mb(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_entry_size(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_variant(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_prios(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_pst_profiles(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_hst_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_qsl_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_qsl_qst_entries(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_pdb_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_ioa_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_roa_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_dbs_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_km_if_cnt(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_km_if_m0(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_km_if_m1(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tpe_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_cpy_writers(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_cpy_mask_mem(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_rpl_depth(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_rpl_ext_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tpe_ifr_categories(const struct info_nthw *p);
+
+struct info_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+ unsigned int n_phy_ports;
+ unsigned int n_rx_ports;
+ unsigned int n_ltx_avail;
+ unsigned int nb_cat_func;
+ unsigned int nb_categories;
+ unsigned int nb_queues;
+ unsigned int nb_flow_types;
+ unsigned int nb_pm_ext;
+ unsigned int nb_len;
+ unsigned int nb_kcc_size;
+ unsigned int nb_kcc_banks;
+ unsigned int nb_km_categories;
+ unsigned int nb_km_cam_banks;
+ unsigned int nb_km_cam_record_words;
+ unsigned int nb_km_cam_records;
+ unsigned int nb_km_tcam_banks;
+ unsigned int nb_km_tcam_bank_width;
+ unsigned int nb_flm_categories;
+ unsigned int nb_flm_size_mb;
+ unsigned int nb_flm_entry_size;
+ unsigned int nb_flm_variant;
+ unsigned int nb_flm_prios;
+ unsigned int nb_flm_pst_profiles;
+ unsigned int nb_hst_categories;
+ unsigned int nb_qsl_categories;
+ unsigned int nb_qsl_qst_entries;
+ unsigned int nb_pdb_categories;
+ unsigned int nb_ioa_categories;
+ unsigned int nb_roa_categories;
+ unsigned int nb_dbs_categories;
+ unsigned int nb_cat_km_if_cnt;
+ unsigned int m_cat_km_if_m0;
+ unsigned int m_cat_km_if_m1;
+ unsigned int nb_tpe_categories;
+ unsigned int nb_tx_cpy_writers;
+ unsigned int nb_tx_cpy_mask_mem;
+ unsigned int nb_tx_rpl_depth;
+ unsigned int nb_tx_rpl_ext_categories;
+ unsigned int nb_tpe_ifr_categories;
+};
+
+#endif /* __FLOW_NTHW_INFO_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c
new file mode 100644
index 0000000000..a83d443f6f
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_ioa.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void ioa_nthw_set_debug_mode(struct ioa_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_ioa, n_debug_mode);
+}
+
+struct ioa_nthw *ioa_nthw_new(void)
+{
+ struct ioa_nthw *p = malloc(sizeof(struct ioa_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void ioa_nthw_delete(struct ioa_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int ioa_nthw_init(struct ioa_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_IOA, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Ioa %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_ioa = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_ioa, IOA_RECIPE_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, IOA_RECIPE_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, IOA_RECIPE_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_ioa, IOA_RECIPE_DATA);
+ p->mp_rcp_data_tunnel_pop =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_TUNNEL_POP);
+ p->mp_rcp_data_vlan_pop =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_POP);
+ p->mp_rcp_data_vlan_push =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_PUSH);
+ p->mp_rcp_data_vlan_vid =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_VID);
+ p->mp_rcp_data_vlan_dei =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_DEI);
+ p->mp_rcp_data_vlan_pcp =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_PCP);
+ p->mp_rcp_data_vlan_tpid_sel =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_TPID_SEL);
+ p->mp_rcp_data_queue_override_en =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_QUEUE_OVERRIDE_EN);
+ p->mp_rcp_data_queue_id =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_QUEUE_ID);
+
+ /* Special Vlan Tpid */
+ p->mp_special = module_get_register(p->m_ioa, IOA_VLAN_TPID_SPECIAL);
+ p->mp_special_vlan_tpid_cust_tpid0 =
+ register_get_field(p->mp_special, IOA_VLAN_TPID_SPECIAL_CUSTTPID0);
+ p->mp_special_vlan_tpid_cust_tpid1 =
+ register_get_field(p->mp_special, IOA_VLAN_TPID_SPECIAL_CUSTTPID1);
+ {
+ /*
+ * This extension in IOA is a messy way FPGA have chosen to
+ * put control bits for EPP module in IOA. It is accepted as
+ * we are going towards exchange IOA and ROA modules later
+ * to get higher scalability in future.
+ */
+ p->mp_roa_epp_ctrl =
+ module_query_register(p->m_ioa, IOA_ROA_EPP_CTRL);
+ if (p->mp_roa_epp_ctrl) {
+ p->mp_roa_epp_addr =
+ register_get_field(p->mp_roa_epp_ctrl,
+ IOA_ROA_EPP_CTRL_ADR);
+ p->mp_roa_epp_cnt =
+ register_get_field(p->mp_roa_epp_ctrl,
+ IOA_ROA_EPP_CTRL_CNT);
+ } else {
+ p->mp_roa_epp_addr = NULL;
+ p->mp_roa_epp_cnt = NULL;
+ }
+
+ p->mp_roa_epp_data =
+ module_query_register(p->m_ioa, IOA_ROA_EPP_DATA);
+ if (p->mp_roa_epp_data) {
+ p->mp_roa_epp_data_push_tunnel =
+ register_get_field(p->mp_roa_epp_data,
+ IOA_ROA_EPP_DATA_PUSH_TUNNEL);
+ p->mp_roa_epp_data_tx_port =
+ register_get_field(p->mp_roa_epp_data,
+ IOA_ROA_EPP_DATA_TX_PORT);
+ } else {
+ p->mp_roa_epp_data_push_tunnel = NULL;
+ p->mp_roa_epp_data_tx_port = NULL;
+ }
+ }
+ return 0;
+}
+
+/* RCP */
+void ioa_nthw_rcp_select(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void ioa_nthw_rcp_cnt(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void ioa_nthw_rcp_tunnel_pop(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tunnel_pop, val);
+}
+
+void ioa_nthw_rcp_vlan_pop(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_pop, val);
+}
+
+void ioa_nthw_rcp_vlan_push(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_push, val);
+}
+
+void ioa_nthw_rcp_vlan_vid(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_vid, val);
+}
+
+void ioa_nthw_rcp_vlan_dei(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_dei, val);
+}
+
+void ioa_nthw_rcp_vlan_pcp(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_pcp, val);
+}
+
+void ioa_nthw_rcp_vlan_tpid_sel(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_tpid_sel, val);
+}
+
+void ioa_nthw_rcp_queue_override_en(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_queue_override_en, val);
+}
+
+void ioa_nthw_rcp_queue_id(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_queue_id, val);
+}
+
+void ioa_nthw_rcp_flush(const struct ioa_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+/* Vlan Tpid Special */
+void ioa_nthw_special_vlan_tpid_cust_tpid0(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_special_vlan_tpid_cust_tpid0, val);
+}
+
+void ioa_nthw_special_vlan_tpid_cust_tpid1(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_special_vlan_tpid_cust_tpid1, val);
+}
+
+void ioa_nthw_special_vlan_tpid_flush(const struct ioa_nthw *p)
+{
+ register_flush(p->mp_special, 1);
+}
+
+void ioa_nthw_roa_epp_select(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_addr)
+ field_set_val32(p->mp_roa_epp_addr, val);
+}
+
+void ioa_nthw_roa_epp_cnt(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_cnt)
+ field_set_val32(p->mp_roa_epp_cnt, val);
+}
+
+void ioa_nthw_roa_epp_push_tunnel(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_data_push_tunnel)
+ field_set_val32(p->mp_roa_epp_data_push_tunnel, val);
+}
+
+void ioa_nthw_roa_epp_tx_port(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_data_tx_port)
+ field_set_val32(p->mp_roa_epp_data_tx_port, val);
+}
+
+void ioa_nthw_roa_epp_flush(const struct ioa_nthw *p)
+{
+ if (p->mp_roa_epp_ctrl)
+ register_flush(p->mp_roa_epp_ctrl, 1);
+ if (p->mp_roa_epp_data)
+ register_flush(p->mp_roa_epp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h
new file mode 100644
index 0000000000..8ab30d2d28
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_IOA_H__
+#define __FLOW_NTHW_IOA_H__
+
+#include "nthw_fpga_model.h"
+
+#include <stdint.h> /* uint32_t */
+
+struct ioa_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_ioa;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+
+ nt_field_t *mp_rcp_data_tunnel_pop;
+ nt_field_t *mp_rcp_data_vlan_pop;
+ nt_field_t *mp_rcp_data_vlan_push;
+ nt_field_t *mp_rcp_data_vlan_vid;
+ nt_field_t *mp_rcp_data_vlan_dei;
+ nt_field_t *mp_rcp_data_vlan_pcp;
+ nt_field_t *mp_rcp_data_vlan_tpid_sel;
+ nt_field_t *mp_rcp_data_queue_override_en;
+ nt_field_t *mp_rcp_data_queue_id;
+
+ nt_register_t *mp_special;
+ nt_field_t *mp_special_vlan_tpid_cust_tpid0;
+ nt_field_t *mp_special_vlan_tpid_cust_tpid1;
+
+ nt_register_t *mp_roa_epp_ctrl;
+ nt_field_t *mp_roa_epp_addr;
+ nt_field_t *mp_roa_epp_cnt;
+ nt_register_t *mp_roa_epp_data;
+ nt_field_t *mp_roa_epp_data_push_tunnel;
+ nt_field_t *mp_roa_epp_data_tx_port;
+};
+
+typedef struct ioa_nthw ioa_nthw_t;
+
+struct ioa_nthw *ioa_nthw_new(void);
+void ioa_nthw_delete(struct ioa_nthw *p);
+int ioa_nthw_init(struct ioa_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int ioa_nthw_setup(struct ioa_nthw *p, int n_idx, int n_idx_cnt);
+void ioa_nthw_set_debug_mode(struct ioa_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void ioa_nthw_rcp_select(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_cnt(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_tunnel_pop(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_pop(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_push(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_vid(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_dei(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_pcp(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_tpid_sel(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_queue_override_en(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_queue_id(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_flush(const struct ioa_nthw *p);
+
+/* Vlan Tpid Special */
+void ioa_nthw_special_vlan_tpid_cust_tpid0(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_special_vlan_tpid_cust_tpid1(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_special_vlan_tpid_flush(const struct ioa_nthw *p);
+
+/* EPP module */
+void ioa_nthw_roa_epp_select(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_cnt(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_push_tunnel(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_tx_port(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_flush(const struct ioa_nthw *p);
+
+#endif /* __FLOW_NTHW_IOA_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c
new file mode 100644
index 0000000000..6477debd46
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c
@@ -0,0 +1,686 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_km.h"
+
+#include <stdint.h>
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+#define CHECK_AND_SET_VALUE(_a, _val) \
+ do { \
+ __typeof__(_a) (a) = (_a); \
+ __typeof__(_val) (val) = (_val); \
+ if (a) { \
+ field_set_val32(a, val); \
+ } \
+ } while (0)
+
+void km_nthw_set_debug_mode(struct km_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_km, n_debug_mode);
+}
+
+struct km_nthw *km_nthw_new(void)
+{
+ struct km_nthw *p = malloc(sizeof(struct km_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void km_nthw_delete(struct km_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int km_nthw_init(struct km_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_KM, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Km %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_km = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_km, KM_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, KM_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, KM_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_km, KM_RCP_DATA);
+ p->mp_rcp_data_qw0_dyn =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_DYN);
+ p->mp_rcp_data_qw0_ofs =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_OFS);
+ p->mp_rcp_data_qw0_sel_a =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_SEL_A);
+ p->mp_rcp_data_qw0_sel_b =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_SEL_B);
+ p->mp_rcp_data_qw4_dyn =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_DYN);
+ p->mp_rcp_data_qw4_ofs =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_OFS);
+ p->mp_rcp_data_qw4_sel_a =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_SEL_A);
+ p->mp_rcp_data_qw4_sel_b =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_SEL_B);
+
+ p->mp_rcp_data_sw8_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_DYN);
+ p->mp_rcp_data_dw8_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_DYN);
+
+ p->mp_rcp_data_swx_ovs_sb =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SWX_OVS_SB);
+ p->mp_rcp_data_swx_cch =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SWX_CCH);
+ p->mp_rcp_data_swx_sel_a =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_SWX_SEL_A);
+ p->mp_rcp_data_swx_sel_b =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_SWX_SEL_B);
+ p->mp_rcp_data_mask_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_MASK_A);
+ p->mp_rcp_data_mask_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_MASK_B);
+ p->mp_rcp_data_dual = register_get_field(p->mp_rcp_data, KM_RCP_DATA_DUAL);
+ p->mp_rcp_data_paired =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_PAIRED);
+ p->mp_rcp_data_el_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_EL_A);
+ p->mp_rcp_data_el_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_EL_B);
+ p->mp_rcp_data_info_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_INFO_A);
+ p->mp_rcp_data_info_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_INFO_B);
+ p->mp_rcp_data_ftm_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_FTM_A);
+ p->mp_rcp_data_ftm_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_FTM_B);
+ p->mp_rcp_data_bank_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_BANK_A);
+ p->mp_rcp_data_bank_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_BANK_B);
+ p->mp_rcp_data_kl_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_KL_A);
+ p->mp_rcp_data_kl_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_KL_B);
+ p->mp_rcp_data_flow_set =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_FLOW_SET);
+ p->mp_rcp_data_keyway_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_KEYWAY_A);
+ p->mp_rcp_data_keyway_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_KEYWAY_B);
+ p->mp_rcp_data_synergy_mode =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_SYNERGY_MODE);
+
+ /* CAM */
+ p->mp_cam_ctrl = module_get_register(p->m_km, KM_CAM_CTRL);
+ p->mp_cam_addr = register_get_field(p->mp_cam_ctrl, KM_CAM_CTRL_ADR);
+ p->mp_cam_cnt = register_get_field(p->mp_cam_ctrl, KM_CAM_CTRL_CNT);
+ p->mp_cam_data = module_get_register(p->m_km, KM_CAM_DATA);
+ p->mp_cam_data_w0 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W0);
+ p->mp_cam_data_w1 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W1);
+ p->mp_cam_data_w2 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W2);
+ p->mp_cam_data_w3 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W3);
+ p->mp_cam_data_w4 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W4);
+ p->mp_cam_data_w5 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W5);
+ p->mp_cam_data_ft0 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT0);
+ p->mp_cam_data_ft1 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT1);
+ p->mp_cam_data_ft2 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT2);
+ p->mp_cam_data_ft3 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT3);
+ p->mp_cam_data_ft4 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT4);
+ p->mp_cam_data_ft5 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT5);
+ /* TCAM */
+ p->mp_tcam_ctrl = module_get_register(p->m_km, KM_TCAM_CTRL);
+ p->mp_tcam_addr = register_get_field(p->mp_tcam_ctrl, KM_TCAM_CTRL_ADR);
+ p->mp_tcam_cnt = register_get_field(p->mp_tcam_ctrl, KM_TCAM_CTRL_CNT);
+ p->mp_tcam_data = module_get_register(p->m_km, KM_TCAM_DATA);
+ p->mp_tcam_data_t = register_get_field(p->mp_tcam_data, KM_TCAM_DATA_T);
+ /* TCI */
+ p->mp_tci_ctrl = module_get_register(p->m_km, KM_TCI_CTRL);
+ p->mp_tci_addr = register_get_field(p->mp_tci_ctrl, KM_TCI_CTRL_ADR);
+ p->mp_tci_cnt = register_get_field(p->mp_tci_ctrl, KM_TCI_CTRL_CNT);
+ p->mp_tci_data = module_get_register(p->m_km, KM_TCI_DATA);
+ p->mp_tci_data_color = register_get_field(p->mp_tci_data, KM_TCI_DATA_COLOR);
+ p->mp_tci_data_ft = register_get_field(p->mp_tci_data, KM_TCI_DATA_FT);
+ /* TCQ */
+ p->mp_tcq_ctrl = module_get_register(p->m_km, KM_TCQ_CTRL);
+ p->mp_tcq_addr = register_get_field(p->mp_tcq_ctrl, KM_TCQ_CTRL_ADR);
+ p->mp_tcq_cnt = register_get_field(p->mp_tcq_ctrl, KM_TCQ_CTRL_CNT);
+ p->mp_tcq_data = module_get_register(p->m_km, KM_TCQ_DATA);
+ p->mp_tcq_data_bank_mask =
+ register_query_field(p->mp_tcq_data, KM_TCQ_DATA_BANK_MASK);
+ p->mp_tcq_data_qual = register_get_field(p->mp_tcq_data, KM_TCQ_DATA_QUAL);
+
+ p->mp_rcp_data_dw0_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW0_B_DYN);
+ p->mp_rcp_data_dw0_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW0_B_OFS);
+ p->mp_rcp_data_dw2_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW2_B_DYN);
+ p->mp_rcp_data_dw2_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW2_B_OFS);
+ p->mp_rcp_data_sw4_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW4_B_DYN);
+ p->mp_rcp_data_sw4_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW4_B_OFS);
+ p->mp_rcp_data_sw5_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW5_B_DYN);
+ p->mp_rcp_data_sw5_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW5_B_OFS);
+ if (!p->mp_rcp_data_dw0_b_dyn) {
+ /* old field defines */
+ p->mp_rcp_data_dw0_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW0_B_DYN);
+ p->mp_rcp_data_dw0_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW0_B_OFS);
+ p->mp_rcp_data_dw2_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW4_B_DYN);
+ p->mp_rcp_data_dw2_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW4_B_OFS);
+ p->mp_rcp_data_sw4_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_B_DYN);
+ p->mp_rcp_data_sw4_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_B_OFS);
+ p->mp_rcp_data_sw5_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_B_DYN);
+ p->mp_rcp_data_sw5_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_B_OFS);
+ }
+
+ /* v0.6+ */
+ if (p->mp_rcp_data_dw8_dyn) {
+ p->mp_rcp_data_dw8_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_OFS);
+ p->mp_rcp_data_dw8_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_SEL_A);
+ p->mp_rcp_data_dw8_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_SEL_B);
+ p->mp_rcp_data_dw10_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_DYN);
+ p->mp_rcp_data_dw10_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_OFS);
+ p->mp_rcp_data_dw10_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_SEL_A);
+ p->mp_rcp_data_dw10_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_SEL_B);
+ } else if (p->mp_rcp_data_sw8_dyn) {
+ p->mp_rcp_data_sw8_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_OFS);
+ p->mp_rcp_data_sw8_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_SEL_A);
+ p->mp_rcp_data_sw8_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_SEL_B);
+ p->mp_rcp_data_sw9_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_DYN);
+ p->mp_rcp_data_sw9_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_OFS);
+ p->mp_rcp_data_sw9_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_SEL_A);
+ p->mp_rcp_data_sw9_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_SEL_B);
+ }
+
+ return 0;
+}
+
+/* RCP */
+void km_nthw_rcp_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+};
+
+void km_nthw_rcp_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+};
+
+void km_nthw_rcp_qw0_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_dyn, val);
+};
+
+void km_nthw_rcp_qw0_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_ofs, val);
+};
+
+void km_nthw_rcp_qw0_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_sel_a, val);
+};
+
+void km_nthw_rcp_qw0_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_sel_b, val);
+};
+
+void km_nthw_rcp_qw4_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_dyn, val);
+};
+
+void km_nthw_rcp_qw4_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_ofs, val);
+};
+
+void km_nthw_rcp_qw4_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_sel_a, val);
+};
+
+void km_nthw_rcp_qw4_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_sel_b, val);
+};
+
+void km_nthw_rcp_dw8_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_dyn, val);
+};
+
+void km_nthw_rcp_sw8_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_dyn, val);
+};
+
+void km_nthw_rcp_sw8_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_ofs, val);
+};
+
+void km_nthw_rcp_sw8_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_sel_a, val);
+};
+
+void km_nthw_rcp_sw8_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_sel_b, val);
+};
+
+void km_nthw_rcp_sw9_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_dyn, val);
+};
+
+void km_nthw_rcp_sw9_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_ofs, val);
+};
+
+void km_nthw_rcp_sw9_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_sel_a, val);
+};
+
+void km_nthw_rcp_sw9_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_sel_b, val);
+};
+
+void km_nthw_rcp_swx_ovs_sb(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_swx_ovs_sb, val);
+};
+
+void km_nthw_rcp_swx_cch(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_swx_cch, val);
+};
+
+void km_nthw_rcp_dw8_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_ofs, val);
+};
+
+void km_nthw_rcp_dw8_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_sel_a, val);
+};
+
+void km_nthw_rcp_dw8_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_sel_b, val);
+};
+
+void km_nthw_rcp_dw10_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_dyn, val);
+};
+
+void km_nthw_rcp_dw10_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_ofs, val);
+};
+
+void km_nthw_rcp_dw10_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_sel_a, val);
+};
+
+void km_nthw_rcp_dw10_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_sel_b, val);
+};
+
+void km_nthw_rcp_swx_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_swx_sel_a, val);
+};
+
+void km_nthw_rcp_swx_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_swx_sel_b, val);
+};
+
+void km_nthw_rcp_mask_a(const struct km_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask_a, val, p->mp_rcp_data_mask_a->mn_words);
+};
+
+void km_nthw_rcp_mask_b(const struct km_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask_b, val, p->mp_rcp_data_mask_b->mn_words);
+};
+
+void km_nthw_rcp_mask_d_a(const struct km_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask_a, val, p->mp_rcp_data_mask_a->mn_words);
+}; /* for DW8/DW10 from v6+ */
+
+void km_nthw_rcp_dual(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dual, val);
+};
+
+void km_nthw_rcp_paired(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_paired, val);
+};
+
+void km_nthw_rcp_el_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_el_a, val);
+};
+
+void km_nthw_rcp_el_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_el_b, val);
+};
+
+void km_nthw_rcp_info_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_info_a, val);
+};
+
+void km_nthw_rcp_info_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_info_b, val);
+};
+
+void km_nthw_rcp_ftm_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ftm_a, val);
+};
+
+void km_nthw_rcp_ftm_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ftm_b, val);
+};
+
+void km_nthw_rcp_bank_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_bank_a, val);
+};
+
+void km_nthw_rcp_bank_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_bank_b, val);
+};
+
+void km_nthw_rcp_kl_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_kl_a, val);
+};
+
+void km_nthw_rcp_kl_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_kl_b, val);
+};
+
+void km_nthw_rcp_flow_set(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_flow_set, val);
+};
+
+void km_nthw_rcp_keyway_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_keyway_a, val);
+};
+
+void km_nthw_rcp_keyway_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_keyway_b, val);
+};
+
+void km_nthw_rcp_synergy_mode(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_synergy_mode, val);
+};
+
+void km_nthw_rcp_dw0_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw0_b_dyn, val);
+};
+
+void km_nthw_rcp_dw0_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw0_b_ofs, val);
+};
+
+void km_nthw_rcp_dw2_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw2_b_dyn, val);
+};
+
+void km_nthw_rcp_dw2_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw2_b_ofs, val);
+};
+
+void km_nthw_rcp_sw4_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw4_b_dyn, val);
+};
+
+void km_nthw_rcp_sw4_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw4_b_ofs, val);
+};
+
+void km_nthw_rcp_sw5_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw5_b_dyn, val);
+};
+
+void km_nthw_rcp_sw5_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw5_b_ofs, val);
+};
+
+void km_nthw_rcp_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+};
+
+/* CAM */
+void km_nthw_cam_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_addr, val);
+};
+
+void km_nthw_cam_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_cnt, val);
+};
+
+void km_nthw_cam_w0(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w0, val);
+};
+
+void km_nthw_cam_w1(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w1, val);
+};
+
+void km_nthw_cam_w2(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w2, val);
+};
+
+void km_nthw_cam_w3(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w3, val);
+};
+
+void km_nthw_cam_w4(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w4, val);
+};
+
+void km_nthw_cam_w5(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w5, val);
+};
+
+void km_nthw_cam_ft0(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft0, val);
+};
+
+void km_nthw_cam_ft1(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft1, val);
+};
+
+void km_nthw_cam_ft2(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft2, val);
+};
+
+void km_nthw_cam_ft3(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft3, val);
+};
+
+void km_nthw_cam_ft4(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft4, val);
+};
+
+void km_nthw_cam_ft5(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft5, val);
+};
+
+void km_nthw_cam_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_cam_ctrl, 1);
+ register_flush(p->mp_cam_data, 1);
+};
+
+/* TCAM */
+void km_nthw_tcam_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcam_addr, val);
+};
+
+void km_nthw_tcam_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcam_cnt, val);
+};
+
+void km_nthw_tcam_t(const struct km_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_tcam_data_t, val, 3);
+};
+
+void km_nthw_tcam_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_tcam_ctrl, 1);
+ register_flush(p->mp_tcam_data, 1);
+};
+
+/* TCI */
+void km_nthw_tci_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_addr, val);
+};
+
+void km_nthw_tci_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_cnt, val);
+};
+
+void km_nthw_tci_color(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_data_color, val);
+};
+
+void km_nthw_tci_ft(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_data_ft, val);
+};
+
+void km_nthw_tci_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_tci_ctrl, 1);
+ register_flush(p->mp_tci_data, 1);
+};
+
+/* TCQ */
+void km_nthw_tcq_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcq_addr, val);
+};
+
+void km_nthw_tcq_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcq_cnt, val);
+};
+
+void km_nthw_tcq_bank_mask(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_tcq_data_bank_mask, val);
+};
+
+void km_nthw_tcq_qual(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcq_data_qual, val);
+};
+
+void km_nthw_tcq_qual72(const struct km_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_tcq_data_qual, val, 3);
+}; /* to use in v4 */
+
+void km_nthw_tcq_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_tcq_ctrl, 1);
+ register_flush(p->mp_tcq_data, 1);
+};
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h
new file mode 100644
index 0000000000..61f9ed2ae4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_KM_H__
+#define __FLOW_NTHW_KM_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct km_nthw;
+
+typedef struct km_nthw km_nthw_t;
+
+struct km_nthw *km_nthw_new(void);
+void km_nthw_delete(struct km_nthw *p);
+int km_nthw_init(struct km_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int km_nthw_setup(struct km_nthw *p, int n_idx, int n_idx_cnt);
+void km_nthw_set_debug_mode(struct km_nthw *p, unsigned int n_debug_mode);
+
+/* RCP initial v3 */
+void km_nthw_rcp_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw0_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw0_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_qw0_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw0_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw4_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw4_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_qw4_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw4_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw8_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw8_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw8_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw8_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw9_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw9_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw9_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw9_sel_b(const struct km_nthw *p, uint32_t val);
+/* subst in v6 */
+void km_nthw_rcp_dw8_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw8_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_dw8_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw8_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw10_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw10_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_dw10_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw10_sel_b(const struct km_nthw *p, uint32_t val);
+
+void km_nthw_rcp_swx_ovs_sb(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_swx_cch(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_swx_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_swx_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_mask_a(const struct km_nthw *p, const uint32_t *val);
+void km_nthw_rcp_mask_d_a(const struct km_nthw *p, const uint32_t *val);
+void km_nthw_rcp_mask_b(const struct km_nthw *p, const uint32_t *val);
+void km_nthw_rcp_dual(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_paired(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_el_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_el_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_info_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_info_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_ftm_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_ftm_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_bank_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_bank_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_kl_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_kl_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_flow_set(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_keyway_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_keyway_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_synergy_mode(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw0_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw0_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_dw2_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw2_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw4_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw4_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw5_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw5_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_flush(const struct km_nthw *p);
+/* CAM */
+void km_nthw_cam_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w0(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w1(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w2(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w3(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w4(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w5(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft0(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft1(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft2(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft3(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft4(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft5(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_flush(const struct km_nthw *p);
+/* TCAM */
+void km_nthw_tcam_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcam_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcam_t(const struct km_nthw *p, uint32_t *val);
+void km_nthw_tcam_flush(const struct km_nthw *p);
+/* TCI */
+void km_nthw_tci_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_color(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_ft(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_flush(const struct km_nthw *p);
+/* TCQ */
+void km_nthw_tcq_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_bank_mask(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_qual(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_qual72(const struct km_nthw *p, uint32_t *val);
+
+void km_nthw_tcq_flush(const struct km_nthw *p);
+
+struct km_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_km;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_qw0_dyn;
+ nt_field_t *mp_rcp_data_qw0_ofs;
+ nt_field_t *mp_rcp_data_qw0_sel_a;
+ nt_field_t *mp_rcp_data_qw0_sel_b;
+ nt_field_t *mp_rcp_data_qw4_dyn;
+ nt_field_t *mp_rcp_data_qw4_ofs;
+ nt_field_t *mp_rcp_data_qw4_sel_a;
+ nt_field_t *mp_rcp_data_qw4_sel_b;
+ nt_field_t *mp_rcp_data_sw8_dyn;
+ nt_field_t *mp_rcp_data_sw8_ofs;
+ nt_field_t *mp_rcp_data_sw8_sel_a;
+ nt_field_t *mp_rcp_data_sw8_sel_b;
+ nt_field_t *mp_rcp_data_sw9_dyn;
+ nt_field_t *mp_rcp_data_sw9_ofs;
+ nt_field_t *mp_rcp_data_sw9_sel_a;
+ nt_field_t *mp_rcp_data_sw9_sel_b;
+
+ nt_field_t *mp_rcp_data_dw8_dyn; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw8_ofs; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw8_sel_a; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw8_sel_b; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_dyn; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_ofs; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_sel_a; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_sel_b; /* substituted Sw<x> from v6+ */
+
+ nt_field_t *mp_rcp_data_swx_ovs_sb;
+ nt_field_t *mp_rcp_data_swx_cch;
+ nt_field_t *mp_rcp_data_swx_sel_a;
+ nt_field_t *mp_rcp_data_swx_sel_b;
+ nt_field_t *mp_rcp_data_mask_a;
+ nt_field_t *mp_rcp_data_mask_b;
+ nt_field_t *mp_rcp_data_dual;
+ nt_field_t *mp_rcp_data_paired;
+ nt_field_t *mp_rcp_data_el_a;
+ nt_field_t *mp_rcp_data_el_b;
+ nt_field_t *mp_rcp_data_info_a;
+ nt_field_t *mp_rcp_data_info_b;
+ nt_field_t *mp_rcp_data_ftm_a;
+ nt_field_t *mp_rcp_data_ftm_b;
+ nt_field_t *mp_rcp_data_bank_a;
+ nt_field_t *mp_rcp_data_bank_b;
+ nt_field_t *mp_rcp_data_kl_a;
+ nt_field_t *mp_rcp_data_kl_b;
+ nt_field_t *mp_rcp_data_flow_set;
+ nt_field_t *mp_rcp_data_keyway_a;
+ nt_field_t *mp_rcp_data_keyway_b;
+ nt_field_t *mp_rcp_data_synergy_mode;
+ nt_field_t *mp_rcp_data_dw0_b_dyn;
+ nt_field_t *mp_rcp_data_dw0_b_ofs;
+ nt_field_t *mp_rcp_data_dw2_b_dyn;
+ nt_field_t *mp_rcp_data_dw2_b_ofs;
+ nt_field_t *mp_rcp_data_sw4_b_dyn;
+ nt_field_t *mp_rcp_data_sw4_b_ofs;
+ nt_field_t *mp_rcp_data_sw5_b_dyn;
+ nt_field_t *mp_rcp_data_sw5_b_ofs;
+
+ nt_register_t *mp_cam_ctrl;
+ nt_field_t *mp_cam_addr;
+ nt_field_t *mp_cam_cnt;
+ nt_register_t *mp_cam_data;
+ nt_field_t *mp_cam_data_w0;
+ nt_field_t *mp_cam_data_w1;
+ nt_field_t *mp_cam_data_w2;
+ nt_field_t *mp_cam_data_w3;
+ nt_field_t *mp_cam_data_w4;
+ nt_field_t *mp_cam_data_w5;
+ nt_field_t *mp_cam_data_ft0;
+ nt_field_t *mp_cam_data_ft1;
+ nt_field_t *mp_cam_data_ft2;
+ nt_field_t *mp_cam_data_ft3;
+ nt_field_t *mp_cam_data_ft4;
+ nt_field_t *mp_cam_data_ft5;
+
+ nt_register_t *mp_tcam_ctrl;
+ nt_field_t *mp_tcam_addr;
+ nt_field_t *mp_tcam_cnt;
+ nt_register_t *mp_tcam_data;
+ nt_field_t *mp_tcam_data_t;
+
+ nt_register_t *mp_tci_ctrl;
+ nt_field_t *mp_tci_addr;
+ nt_field_t *mp_tci_cnt;
+ nt_register_t *mp_tci_data;
+ nt_field_t *mp_tci_data_color;
+ nt_field_t *mp_tci_data_ft;
+
+ nt_register_t *mp_tcq_ctrl;
+ nt_field_t *mp_tcq_addr;
+ nt_field_t *mp_tcq_cnt;
+ nt_register_t *mp_tcq_data;
+ nt_field_t *mp_tcq_data_bank_mask;
+ nt_field_t *mp_tcq_data_qual;
+};
+
+#endif /* __FLOW_NTHW_KM_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c
new file mode 100644
index 0000000000..e823a527bb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_pdb.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void pdb_nthw_set_debug_mode(struct pdb_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_pdb, n_debug_mode);
+}
+
+struct pdb_nthw *pdb_nthw_new(void)
+{
+ struct pdb_nthw *p = malloc(sizeof(struct pdb_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void pdb_nthw_delete(struct pdb_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int pdb_nthw_init(struct pdb_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_PDB, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Pdb %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_pdb = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_pdb, PDB_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, PDB_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, PDB_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_pdb, PDB_RCP_DATA);
+ p->mp_rcp_data_descriptor =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DESCRIPTOR);
+ p->mp_rcp_data_desc_len =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DESC_LEN);
+ p->mp_rcp_data_tx_port =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_PORT);
+ p->mp_rcp_data_tx_ignore =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_IGNORE);
+ p->mp_rcp_data_tx_now =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_NOW);
+ p->mp_rcp_data_crc_overwrite =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_CRC_OVERWRITE);
+ p->mp_rcp_data_align = register_get_field(p->mp_rcp_data, PDB_RCP_DATA_ALIGN);
+ p->mp_rcp_data_ofs0_dyn =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS0_DYN);
+ p->mp_rcp_data_ofs0_rel =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS0_REL);
+ p->mp_rcp_data_ofs1_dyn =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS1_DYN);
+ p->mp_rcp_data_ofs1_rel =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS1_REL);
+ p->mp_rcp_data_ofs2_dyn =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS2_DYN);
+ p->mp_rcp_data_ofs2_rel =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS2_REL);
+ p->mp_rcp_data_ip_prot_tnl =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_IP_PROT_TNL);
+ p->mp_rcp_data_ppc_hsh =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_PPC_HSH);
+ p->mp_rcp_data_duplicate_en =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DUPLICATE_EN);
+ p->mp_rcp_data_duplicate_bit =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DUPLICATE_BIT);
+ p->mp_rcp_data_pcap_keep_fcs =
+ register_query_field(p->mp_rcp_data, PDB_RCP_DATA_PCAP_KEEP_FCS);
+ /* CONFIG */
+ p->mp_config = module_get_register(p->m_pdb, PDB_CONFIG);
+ p->mp_config_ts_format =
+ register_get_field(p->mp_config, PDB_CONFIG_TS_FORMAT);
+ p->mp_config_port_ofs =
+ register_get_field(p->mp_config, PDB_CONFIG_PORT_OFS);
+
+ return 0;
+}
+
+/* RCP */
+void pdb_nthw_rcp_select(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void pdb_nthw_rcp_cnt(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void pdb_nthw_rcp_descriptor(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_descriptor, val);
+}
+
+void pdb_nthw_rcp_desc_len(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_desc_len, val);
+}
+
+void pdb_nthw_rcp_tx_port(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tx_port, val);
+}
+
+void pdb_nthw_rcp_tx_ignore(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tx_ignore, val);
+}
+
+void pdb_nthw_rcp_tx_now(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tx_now, val);
+}
+
+void pdb_nthw_rcp_crc_overwrite(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_crc_overwrite, val);
+}
+
+void pdb_nthw_rcp_align(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_align, val);
+}
+
+void pdb_nthw_rcp_ofs0_dyn(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs0_dyn, val);
+}
+
+void pdb_nthw_rcp_ofs0_rel(const struct pdb_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs0_rel, val);
+}
+
+void pdb_nthw_rcp_ofs1_dyn(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs1_dyn, val);
+}
+
+void pdb_nthw_rcp_ofs1_rel(const struct pdb_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs1_rel, val);
+}
+
+void pdb_nthw_rcp_ofs2_dyn(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs2_dyn, val);
+}
+
+void pdb_nthw_rcp_ofs2_rel(const struct pdb_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs2_rel, val);
+}
+
+void pdb_nthw_rcp_ip_prot_tnl(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ip_prot_tnl, val);
+}
+
+void pdb_nthw_rcp_ppc_hsh(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ppc_hsh, val);
+}
+
+void pdb_nthw_rcp_duplicate_en(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_duplicate_en, val);
+}
+
+void pdb_nthw_rcp_duplicate_bit(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_duplicate_bit, val);
+}
+
+void pdb_nthw_rcp_data_pcap_keep_fcs(const struct pdb_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_pcap_keep_fcs)
+ field_set_val32(p->mp_rcp_data_pcap_keep_fcs, val);
+}
+
+void pdb_nthw_rcp_flush(const struct pdb_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+/* CONFIG */
+void pdb_nthw_config_ts_format(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_ts_format, val);
+}
+
+void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_port_ofs, val);
+}
+
+void pdb_nthw_config_flush(const struct pdb_nthw *p)
+{
+ register_flush(p->mp_config, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h
new file mode 100644
index 0000000000..aed050eca5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_PDB_H__
+#define __FLOW_NTHW_PDB_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct pdb_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_pdb;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_descriptor;
+ nt_field_t *mp_rcp_data_desc_len;
+ nt_field_t *mp_rcp_data_tx_port;
+ nt_field_t *mp_rcp_data_tx_ignore;
+ nt_field_t *mp_rcp_data_tx_now;
+ nt_field_t *mp_rcp_data_crc_overwrite;
+ nt_field_t *mp_rcp_data_align;
+ nt_field_t *mp_rcp_data_ofs0_dyn;
+ nt_field_t *mp_rcp_data_ofs0_rel;
+ nt_field_t *mp_rcp_data_ofs1_dyn;
+ nt_field_t *mp_rcp_data_ofs1_rel;
+ nt_field_t *mp_rcp_data_ofs2_dyn;
+ nt_field_t *mp_rcp_data_ofs2_rel;
+ nt_field_t *mp_rcp_data_ip_prot_tnl;
+ nt_field_t *mp_rcp_data_ppc_hsh;
+ nt_field_t *mp_rcp_data_duplicate_en;
+ nt_field_t *mp_rcp_data_duplicate_bit;
+ nt_field_t *mp_rcp_data_pcap_keep_fcs;
+
+ nt_register_t *mp_config;
+ nt_field_t *mp_config_ts_format;
+ nt_field_t *mp_config_port_ofs;
+};
+
+typedef struct pdb_nthw pdb_nthw_t;
+
+struct pdb_nthw *pdb_nthw_new(void);
+void pdb_nthw_delete(struct pdb_nthw *p);
+int pdb_nthw_init(struct pdb_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int pdb_nthw_setup(struct pdb_nthw *p, int n_idx, int n_idx_cnt);
+void pdb_nthw_set_debug_mode(struct pdb_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void pdb_nthw_rcp_select(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_cnt(const struct pdb_nthw *p, uint32_t val);
+
+void pdb_nthw_rcp_descriptor(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_desc_len(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_tx_port(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_tx_ignore(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_tx_now(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_crc_overwrite(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_align(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs0_dyn(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs0_rel(const struct pdb_nthw *p, int32_t val);
+void pdb_nthw_rcp_ofs1_dyn(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs1_rel(const struct pdb_nthw *p, int32_t val);
+void pdb_nthw_rcp_ofs2_dyn(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs2_rel(const struct pdb_nthw *p, int32_t val);
+void pdb_nthw_rcp_ip_prot_tnl(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ppc_hsh(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_duplicate_en(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_duplicate_bit(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_data_pcap_keep_fcs(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_flush(const struct pdb_nthw *p);
+
+/* CONFIG */
+void pdb_nthw_config_ts_format(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_config_flush(const struct pdb_nthw *p);
+
+#endif /* __FLOW_NTHW_PDB_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c
new file mode 100644
index 0000000000..6c13824df6
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c
@@ -0,0 +1,355 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_qsl.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void qsl_nthw_set_debug_mode(struct qsl_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_qsl, n_debug_mode);
+}
+
+struct qsl_nthw *qsl_nthw_new(void)
+{
+ struct qsl_nthw *p = malloc(sizeof(struct qsl_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void qsl_nthw_delete(struct qsl_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int qsl_nthw_init(struct qsl_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_QSL, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: QSL %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_qsl = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_qsl, QSL_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, QSL_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, QSL_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_qsl, QSL_RCP_DATA);
+ p->mp_rcp_data_discard =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_DISCARD);
+ p->mp_rcp_data_drop = register_get_field(p->mp_rcp_data, QSL_RCP_DATA_DROP);
+ p->mp_rcp_data_tbl_lo =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_LO);
+ p->mp_rcp_data_tbl_hi =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_HI);
+ p->mp_rcp_data_tbl_idx =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_IDX);
+ p->mp_rcp_data_tbl_msk =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_MSK);
+ p->mp_rcp_data_cao = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_CAO);
+ p->mp_rcp_data_lr = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_LR);
+ p->mp_rcp_data_tsa = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_TSA);
+ p->mp_rcp_data_vli = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_VLI);
+
+ /* QST */
+ p->mp_qst_ctrl = module_get_register(p->m_qsl, QSL_QST_CTRL);
+ p->mp_qst_addr = register_get_field(p->mp_qst_ctrl, QSL_QST_CTRL_ADR);
+ p->mp_qst_cnt = register_get_field(p->mp_qst_ctrl, QSL_QST_CTRL_CNT);
+ p->mp_qst_data = module_get_register(p->m_qsl, QSL_QST_DATA);
+ p->mp_qst_data_queue = register_get_field(p->mp_qst_data, QSL_QST_DATA_QUEUE);
+ p->mp_qst_data_en = register_query_field(p->mp_qst_data, QSL_QST_DATA_EN);
+ p->mp_qst_data_tx_port =
+ register_query_field(p->mp_qst_data, QSL_QST_DATA_TX_PORT);
+ p->mp_qst_data_lre = register_query_field(p->mp_qst_data, QSL_QST_DATA_LRE);
+ p->mp_qst_data_tci = register_query_field(p->mp_qst_data, QSL_QST_DATA_TCI);
+ p->mp_qst_data_ven = register_query_field(p->mp_qst_data, QSL_QST_DATA_VEN);
+ /* QEN */
+ p->mp_qen_ctrl = module_get_register(p->m_qsl, QSL_QEN_CTRL);
+ p->mp_qen_addr = register_get_field(p->mp_qen_ctrl, QSL_QEN_CTRL_ADR);
+ p->mp_qen_cnt = register_get_field(p->mp_qen_ctrl, QSL_QEN_CTRL_CNT);
+ p->mp_qen_data = module_get_register(p->m_qsl, QSL_QEN_DATA);
+ p->mp_qen_data_en = register_get_field(p->mp_qen_data, QSL_QEN_DATA_EN);
+ /* UNMQ */
+ p->mp_unmq_ctrl = module_get_register(p->m_qsl, QSL_UNMQ_CTRL);
+ p->mp_unmq_addr = register_get_field(p->mp_unmq_ctrl, QSL_UNMQ_CTRL_ADR);
+ p->mp_unmq_cnt = register_get_field(p->mp_unmq_ctrl, QSL_UNMQ_CTRL_CNT);
+ p->mp_unmq_data = module_get_register(p->m_qsl, QSL_UNMQ_DATA);
+ p->mp_unmq_data_dest_queue =
+ register_get_field(p->mp_unmq_data, QSL_UNMQ_DATA_DEST_QUEUE);
+ p->mp_unmq_data_en = register_get_field(p->mp_unmq_data, QSL_UNMQ_DATA_EN);
+
+ if (!p->mp_qst_data_en) {
+ /* changed name from EN to QEN in v0.7 */
+ p->mp_qst_data_en =
+ register_get_field(p->mp_qst_data, QSL_QST_DATA_QEN);
+ }
+
+ /* LTX - not there anymore from v0.7+ */
+ p->mp_ltx_ctrl = module_query_register(p->m_qsl, QSL_LTX_CTRL);
+ if (p->mp_ltx_ctrl) {
+ p->mp_ltx_addr =
+ register_get_field(p->mp_ltx_ctrl, QSL_LTX_CTRL_ADR);
+ p->mp_ltx_cnt = register_get_field(p->mp_ltx_ctrl, QSL_LTX_CTRL_CNT);
+ } else {
+ p->mp_ltx_addr = NULL;
+ p->mp_ltx_cnt = NULL;
+ }
+ p->mp_ltx_data = module_query_register(p->m_qsl, QSL_LTX_DATA);
+ if (p->mp_ltx_data) {
+ p->mp_ltx_data_lr =
+ register_get_field(p->mp_ltx_data, QSL_LTX_DATA_LR);
+ p->mp_ltx_data_tx_port =
+ register_get_field(p->mp_ltx_data, QSL_LTX_DATA_TX_PORT);
+ p->mp_ltx_data_tsa =
+ register_get_field(p->mp_ltx_data, QSL_LTX_DATA_TSA);
+ } else {
+ p->mp_ltx_data_lr = NULL;
+ p->mp_ltx_data_tx_port = NULL;
+ p->mp_ltx_data_tsa = NULL;
+ }
+ return 0;
+}
+
+int qsl_nthw_setup(struct qsl_nthw *p, int n_idx, int n_idx_cnt)
+{
+ (void)p;
+ (void)n_idx;
+ (void)n_idx_cnt;
+
+ return 0;
+}
+
+/* RCP */
+void qsl_nthw_rcp_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+};
+
+void qsl_nthw_rcp_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void qsl_nthw_rcp_discard(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_discard, val);
+}
+
+void qsl_nthw_rcp_drop(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_drop, val);
+}
+
+void qsl_nthw_rcp_tbl_lo(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tbl_lo, val);
+}
+
+void qsl_nthw_rcp_tbl_hi(const struct qsl_nthw *p, uint32_t val)
+
+{
+ field_set_val32(p->mp_rcp_data_tbl_hi, val);
+}
+
+void qsl_nthw_rcp_tbl_idx(const struct qsl_nthw *p, uint32_t val)
+
+{
+ field_set_val32(p->mp_rcp_data_tbl_idx, val);
+}
+
+void qsl_nthw_rcp_tbl_msk(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tbl_msk, val);
+}
+
+void qsl_nthw_rcp_cao(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_cao)
+ field_set_val32(p->mp_rcp_data_cao, val);
+}
+
+void qsl_nthw_rcp_lr(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_lr)
+ field_set_val32(p->mp_rcp_data_lr, val);
+}
+
+void qsl_nthw_rcp_tsa(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_tsa)
+ field_set_val32(p->mp_rcp_data_tsa, val);
+}
+
+void qsl_nthw_rcp_vli(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_vli)
+ field_set_val32(p->mp_rcp_data_vli, val);
+}
+
+void qsl_nthw_rcp_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+/* LTX */
+void qsl_nthw_ltx_select(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_addr)
+ field_set_val32(p->mp_ltx_addr, val);
+}
+
+void qsl_nthw_ltx_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_addr)
+ field_set_val32(p->mp_ltx_cnt, val);
+}
+
+void qsl_nthw_ltx_lr(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_data_lr)
+ field_set_val32(p->mp_ltx_data_lr, val);
+}
+
+void qsl_nthw_ltx_tx_port(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_data_tx_port)
+ field_set_val32(p->mp_ltx_data_tx_port, val);
+}
+
+void qsl_nthw_ltx_tsa(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_data_tsa)
+ field_set_val32(p->mp_ltx_data_tsa, val);
+};
+
+void qsl_nthw_ltx_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_ltx_ctrl, 1);
+ register_flush(p->mp_ltx_data, 1);
+}
+
+/* QST */
+void qsl_nthw_qst_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_addr, val);
+}
+
+void qsl_nthw_qst_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_cnt, val);
+}
+
+void qsl_nthw_qst_queue(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_data_queue, val);
+}
+
+void qsl_nthw_qst_en(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_data_en, val);
+}
+
+void qsl_nthw_qst_tx_port(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_tx_port)
+ field_set_val32(p->mp_qst_data_tx_port, val);
+}
+
+void qsl_nthw_qst_lre(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_lre)
+ field_set_val32(p->mp_qst_data_lre, val);
+}
+
+void qsl_nthw_qst_tci(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_tci)
+ field_set_val32(p->mp_qst_data_tci, val);
+}
+
+void qsl_nthw_qst_ven(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_ven)
+ field_set_val32(p->mp_qst_data_ven, val);
+}
+
+void qsl_nthw_qst_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_qst_ctrl, 1);
+ register_flush(p->mp_qst_data, 1);
+}
+
+/* QEN */
+void qsl_nthw_qen_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qen_addr, val);
+}
+
+void qsl_nthw_qen_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qen_cnt, val);
+}
+
+void qsl_nthw_qen_en(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qen_data_en, val);
+}
+
+void qsl_nthw_qen_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_qen_ctrl, 1);
+ register_flush(p->mp_qen_data, 1);
+}
+
+/* UNMQ */
+void qsl_nthw_unmq_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_addr, val);
+}
+
+void qsl_nthw_unmq_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_cnt, val);
+}
+
+void qsl_nthw_unmq_dest_queue(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_data_dest_queue, val);
+}
+
+void qsl_nthw_unmq_en(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_data_en, val);
+}
+
+void qsl_nthw_unmq_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_unmq_ctrl, 1);
+ register_flush(p->mp_unmq_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h
new file mode 100644
index 0000000000..eeebbcf1c4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_QSL_H__
+#define __FLOW_NTHW_QSL_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct qsl_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_qsl;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_discard;
+ nt_field_t *mp_rcp_data_drop;
+ nt_field_t *mp_rcp_data_tbl_lo;
+ nt_field_t *mp_rcp_data_tbl_hi;
+ nt_field_t *mp_rcp_data_tbl_idx;
+ nt_field_t *mp_rcp_data_tbl_msk;
+ nt_field_t *mp_rcp_data_cao;
+ nt_field_t *mp_rcp_data_lr;
+ nt_field_t *mp_rcp_data_tsa;
+ nt_field_t *mp_rcp_data_vli;
+
+ nt_register_t *mp_ltx_ctrl;
+ nt_field_t *mp_ltx_addr;
+ nt_field_t *mp_ltx_cnt;
+ nt_register_t *mp_ltx_data;
+ nt_field_t *mp_ltx_data_lr;
+ nt_field_t *mp_ltx_data_tx_port;
+ nt_field_t *mp_ltx_data_tsa;
+
+ nt_register_t *mp_qst_ctrl;
+ nt_field_t *mp_qst_addr;
+ nt_field_t *mp_qst_cnt;
+ nt_register_t *mp_qst_data;
+ nt_field_t *mp_qst_data_queue;
+ nt_field_t *mp_qst_data_en;
+ nt_field_t *mp_qst_data_tx_port;
+ nt_field_t *mp_qst_data_lre;
+ nt_field_t *mp_qst_data_tci;
+ nt_field_t *mp_qst_data_ven;
+
+ nt_register_t *mp_qen_ctrl;
+ nt_field_t *mp_qen_addr;
+ nt_field_t *mp_qen_cnt;
+ nt_register_t *mp_qen_data;
+ nt_field_t *mp_qen_data_en;
+
+ nt_register_t *mp_unmq_ctrl;
+ nt_field_t *mp_unmq_addr;
+ nt_field_t *mp_unmq_cnt;
+ nt_register_t *mp_unmq_data;
+ nt_field_t *mp_unmq_data_dest_queue;
+ nt_field_t *mp_unmq_data_en;
+};
+
+typedef struct qsl_nthw qsl_nthw_t;
+
+struct qsl_nthw *qsl_nthw_new(void);
+void qsl_nthw_delete(struct qsl_nthw *p);
+int qsl_nthw_init(struct qsl_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int qsl_nthw_setup(struct qsl_nthw *p, int n_idx, int n_idx_cnt);
+void qsl_nthw_set_debug_mode(struct qsl_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void qsl_nthw_rcp_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_discard(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_drop(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_lo(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_hi(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_idx(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_msk(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_cao(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_lr(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tsa(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_vli(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_flush(const struct qsl_nthw *p);
+
+/* LTX */
+void qsl_nthw_ltx_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_lr(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_tx_port(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_tsa(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_flush(const struct qsl_nthw *p);
+
+/* QST */
+void qsl_nthw_qst_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_queue(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_en(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_tx_port(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_lre(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_tci(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_ven(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_flush(const struct qsl_nthw *p);
+
+/* QEN */
+void qsl_nthw_qen_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qen_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qen_en(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qen_flush(const struct qsl_nthw *p);
+
+/* UNMQ */
+void qsl_nthw_unmq_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_dest_queue(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_en(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_flush(const struct qsl_nthw *p);
+
+#endif /* __FLOW_NTHW_QSL_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c
new file mode 100644
index 0000000000..8f519b7728
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_rmc.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void rmc_nthw_set_debug_mode(struct rmc_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_rmc, n_debug_mode);
+}
+
+struct rmc_nthw *rmc_nthw_new(void)
+{
+ struct rmc_nthw *p = malloc(sizeof(struct rmc_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void rmc_nthw_delete(struct rmc_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int rmc_nthw_init(struct rmc_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RMC, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RMC %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_rmc = p_mod;
+
+ /* CTRL */
+ p->mp_ctrl = module_get_register(p->m_rmc, RMC_CTRL);
+ p->mp_ctrl_block_statt =
+ register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_STATT);
+ p->mp_ctrl_block_keep_a =
+ register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_KEEPA);
+ p->mp_ctrl_block_rpp_slice =
+ register_query_field(p->mp_ctrl, RMC_CTRL_BLOCK_RPP_SLICE);
+ p->mp_ctrl_block_mac_port =
+ register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_MAC_PORT);
+ p->mp_ctrl_lag_phy_odd_even =
+ register_get_field(p->mp_ctrl, RMC_CTRL_LAG_PHY_ODD_EVEN);
+ return 0;
+}
+
+int rmc_nthw_setup(struct rmc_nthw *p, int n_idx, int n_idx_cnt)
+{
+ (void)p;
+ (void)n_idx;
+ (void)n_idx_cnt;
+
+ return 0;
+}
+
+/* CTRL */
+void rmc_nthw_ctrl_block_statt(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_block_statt, val);
+}
+
+void rmc_nthw_ctrl_block_keep_a(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_block_keep_a, val);
+}
+
+void rmc_nthw_ctrl_block_rpp_slice(const struct rmc_nthw *p, uint32_t val)
+{
+ if (p->mp_ctrl_block_rpp_slice)
+ field_set_val32(p->mp_ctrl_block_rpp_slice, val);
+}
+
+void rmc_nthw_ctrl_block_mac_port(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_block_mac_port, val);
+}
+
+void rmc_nthw_ctrl_lag_phy_odd_even(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_lag_phy_odd_even, val);
+}
+
+void rmc_nthw_ctrl_flush(const struct rmc_nthw *p)
+{
+ register_flush(p->mp_ctrl, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h
new file mode 100644
index 0000000000..57d5776002
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_RMC_H__
+#define __FLOW_NTHW_RMC_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct rmc_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_rmc;
+
+ nt_register_t *mp_ctrl;
+ nt_field_t *mp_ctrl_block_statt;
+ nt_field_t *mp_ctrl_block_keep_a;
+ nt_field_t *mp_ctrl_block_rpp_slice;
+ nt_field_t *mp_ctrl_block_mac_port;
+ nt_field_t *mp_ctrl_lag_phy_odd_even;
+};
+
+struct rmc_nthw *rmc_nthw_new(void);
+void rmc_nthw_delete(struct rmc_nthw *p);
+int rmc_nthw_init(struct rmc_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int rmc_nthw_setup(struct rmc_nthw *p, int n_idx, int n_idx_cnt);
+void rmc_nthw_set_debug_mode(struct rmc_nthw *p, unsigned int n_debug_mode);
+
+/* CTRL */
+void rmc_nthw_ctrl_block_statt(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_block_keep_a(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_block_rpp_slice(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_block_mac_port(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_lag_phy_odd_even(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_flush(const struct rmc_nthw *p);
+
+#endif /* __FLOW_NTHW_RMC_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c
new file mode 100644
index 0000000000..934778f426
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c
@@ -0,0 +1,294 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_roa.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void roa_nthw_set_debug_mode(struct roa_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_roa, n_debug_mode);
+}
+
+struct roa_nthw *roa_nthw_new(void)
+{
+ struct roa_nthw *p = malloc(sizeof(struct roa_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void roa_nthw_delete(struct roa_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int roa_nthw_init(struct roa_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_ROA, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: ROA %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_roa = p_mod;
+
+ /* TUN HDR */
+ p->mp_tun_hdr_ctrl = module_get_register(p->m_roa, ROA_TUNHDR_CTRL);
+ p->mp_tun_hdr_addr =
+ register_get_field(p->mp_tun_hdr_ctrl, ROA_TUNHDR_CTRL_ADR);
+ p->mp_tun_hdr_cnt =
+ register_get_field(p->mp_tun_hdr_ctrl, ROA_TUNHDR_CTRL_CNT);
+ p->mp_tun_hdr_data = module_get_register(p->m_roa, ROA_TUNHDR_DATA);
+ p->mp_tun_hdr_data_tunnel_hdr =
+ register_get_field(p->mp_tun_hdr_data, ROA_TUNHDR_DATA_TUNNEL_HDR);
+ /* TUN CFG */
+ p->mp_tun_cfg_ctrl = module_get_register(p->m_roa, ROA_TUNCFG_CTRL);
+ p->mp_tun_cfg_addr =
+ register_get_field(p->mp_tun_cfg_ctrl, ROA_TUNCFG_CTRL_ADR);
+ p->mp_tun_cfg_cnt =
+ register_get_field(p->mp_tun_cfg_ctrl, ROA_TUNCFG_CTRL_CNT);
+ p->mp_tun_cfg_data = module_get_register(p->m_roa, ROA_TUNCFG_DATA);
+ p->mp_tun_cfg_data_tun_len =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_LEN);
+ p->mp_tun_cfg_data_tun_type =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_TYPE);
+ p->mp_tun_cfg_data_tun_vlan =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_VLAN);
+ p->mp_tun_cfg_data_ip_type =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IP_TYPE);
+ p->mp_tun_cfg_data_ipcs_upd =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPCS_UPD);
+ p->mp_tun_cfg_data_ipcs_precalc =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPCS_PRECALC);
+ p->mp_tun_cfg_data_iptl_upd =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPTL_UPD);
+ p->mp_tun_cfg_data_iptl_precalc =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPTL_PRECALC);
+ p->mp_tun_cfg_data_vxlan_udp_len_upd =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_VXLAN_UDP_LEN_UPD);
+ p->mp_tun_cfg_data_tx_lag_ix =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TX_LAG_IX);
+ p->mp_tun_cfg_data_recirculate =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRCULATE);
+ p->mp_tun_cfg_data_push_tunnel =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_PUSH_TUNNEL);
+ p->mp_tun_cfg_data_recirc_port =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRC_PORT);
+ p->mp_tun_cfg_data_recirc_bypass =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRC_BYPASS);
+ /* CONFIG */
+ p->mp_config = module_get_register(p->m_roa, ROA_CONFIG);
+ p->mp_config_fwd_recirculate =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_RECIRCULATE);
+ p->mp_config_fwd_normal_pcks =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_NORMAL_PCKS);
+ p->mp_config_fwd_tx_port0 =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_TXPORT0);
+ p->mp_config_fwd_tx_port1 =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_TXPORT1);
+ p->mp_config_fwd_cell_builder_pcks =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_CELLBUILDER_PCKS);
+ p->mp_config_fwd_non_normal_pcks =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_NON_NORMAL_PCKS);
+ /* LAG */
+ p->mp_lag_cfg_ctrl = module_get_register(p->m_roa, ROA_LAGCFG_CTRL);
+ p->mp_lag_cfg_addr =
+ register_get_field(p->mp_lag_cfg_ctrl, ROA_LAGCFG_CTRL_ADR);
+ p->mp_lag_cfg_cnt =
+ register_get_field(p->mp_lag_cfg_ctrl, ROA_LAGCFG_CTRL_CNT);
+ p->mp_lag_cfg_data = module_get_register(p->m_roa, ROA_LAGCFG_DATA);
+ p->mp_lag_cfg_data_tx_phy_port =
+ register_get_field(p->mp_lag_cfg_data, ROA_LAGCFG_DATA_TXPHY_PORT);
+
+ return 0;
+}
+
+/* TUN HDR */
+void roa_nthw_tun_hdr_select(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_hdr_addr, val);
+}
+
+void roa_nthw_tun_hdr_cnt(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_hdr_cnt, val);
+}
+
+void roa_nthw_tun_hdr_tunnel_hdr(const struct roa_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_tun_hdr_data_tunnel_hdr, val, 4);
+}
+
+void roa_nthw_tun_hdr_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_tun_hdr_ctrl, 1);
+ register_flush(p->mp_tun_hdr_data, 1);
+}
+
+/* TUN CFG */
+void roa_nthw_tun_cfg_select(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_addr, val);
+}
+
+void roa_nthw_tun_cfg_cnt(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_cnt, val);
+}
+
+void roa_nthw_tun_cfg_tun_len(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tun_len, val);
+}
+
+void roa_nthw_tun_cfg_tun_type(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tun_type, val);
+}
+
+void roa_nthw_tun_cfg_tun_vlan(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tun_vlan, val);
+}
+
+void roa_nthw_tun_cfg_ip_type(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_ip_type, val);
+}
+
+void roa_nthw_tun_cfg_ipcs_upd(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_ipcs_upd, val);
+}
+
+void roa_nthw_tun_cfg_ipcs_precalc(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_ipcs_precalc, val);
+}
+
+void roa_nthw_tun_cfg_iptl_upd(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_iptl_upd, val);
+}
+
+void roa_nthw_tun_cfg_iptl_precalc(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_iptl_precalc, val);
+}
+
+void roa_nthw_tun_cfg_vxlan_udp_len_upd(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_vxlan_udp_len_upd, val);
+}
+
+void roa_nthw_tun_cfg_tx_lag_ix(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tx_lag_ix, val);
+};
+
+void roa_nthw_tun_cfg_recirculate(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_recirculate, val);
+}
+
+void roa_nthw_tun_cfg_push_tunnel(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_push_tunnel, val);
+}
+
+void roa_nthw_tun_cfg_recirc_port(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_recirc_port, val);
+}
+
+void roa_nthw_tun_cfg_recirc_bypass(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_recirc_bypass, val);
+}
+
+void roa_nthw_tun_cfg_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_tun_cfg_ctrl, 1);
+ register_flush(p->mp_tun_cfg_data, 1);
+}
+
+/* ROA CONFIG */
+void roa_nthw_config_fwd_recirculate(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_recirculate, val);
+}
+
+void roa_nthw_config_fwd_normal_pcks(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_normal_pcks, val);
+}
+
+void roa_nthw_config_fwd_tx_port0(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_tx_port0, val);
+}
+
+void roa_nthw_config_fwd_tx_port1(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_tx_port1, val);
+}
+
+void roa_nthw_config_fwd_cell_builder_pcks(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_cell_builder_pcks, val);
+}
+
+void roa_nthw_config_fwd_non_normal_pcks(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_non_normal_pcks, val);
+}
+
+void roa_nthw_config_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_config, 1);
+}
+
+/* LAG */
+void roa_nthw_lag_cfg_select(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_lag_cfg_addr, val);
+}
+
+void roa_nthw_lag_cfg_cnt(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_lag_cfg_cnt, val);
+}
+
+void roa_nthw_lag_cfg_tx_phy_port(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_lag_cfg_data_tx_phy_port, val);
+}
+
+void roa_nthw_lag_cfg_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_lag_cfg_ctrl, 1);
+ register_flush(p->mp_lag_cfg_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h
new file mode 100644
index 0000000000..9398ef5ae9
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_ROA_H__
+#define __FLOW_NTHW_ROA_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct roa_nthw;
+
+typedef struct roa_nthw roa_nthw_t;
+
+struct roa_nthw *roa_nthw_new(void);
+void roa_nthw_delete(struct roa_nthw *p);
+int roa_nthw_init(struct roa_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int roa_nthw_setup(struct roa_nthw *p, int n_idx, int n_idx_cnt);
+void roa_nthw_set_debug_mode(struct roa_nthw *p, unsigned int n_debug_mode);
+
+/* TUN HDR */
+void roa_nthw_tun_hdr_select(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_hdr_cnt(const struct roa_nthw *p, uint32_t val);
+
+void roa_nthw_tun_hdr_tunnel_hdr(const struct roa_nthw *p, uint32_t *val);
+void roa_nthw_tun_hdr_flush(const struct roa_nthw *p);
+
+/* TUN CFG */
+void roa_nthw_tun_cfg_select(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_cnt(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tun_len(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tun_type(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tun_vlan(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_ip_type(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_ipcs_upd(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_ipcs_precalc(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_iptl_upd(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_iptl_precalc(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_vxlan_udp_len_upd(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tx_lag_ix(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_recirculate(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_push_tunnel(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_recirc_port(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_recirc_bypass(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_flush(const struct roa_nthw *p);
+
+/* ROA CONFIG */
+void roa_nthw_config_fwd_recirculate(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_normal_pcks(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_tx_port0(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_tx_port1(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_cell_builder_pcks(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_non_normal_pcks(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_flush(const struct roa_nthw *p);
+
+/* LAG */
+void roa_nthw_lag_cfg_select(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_lag_cfg_cnt(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_lag_cfg_tx_phy_port(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_lag_cfg_flush(const struct roa_nthw *p);
+
+struct roa_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_roa;
+
+ nt_register_t *mp_tun_hdr_ctrl;
+ nt_field_t *mp_tun_hdr_addr;
+ nt_field_t *mp_tun_hdr_cnt;
+ nt_register_t *mp_tun_hdr_data;
+ nt_field_t *mp_tun_hdr_data_tunnel_hdr;
+
+ nt_register_t *mp_tun_cfg_ctrl;
+ nt_field_t *mp_tun_cfg_addr;
+ nt_field_t *mp_tun_cfg_cnt;
+ nt_register_t *mp_tun_cfg_data;
+ nt_field_t *mp_tun_cfg_data_tun_len;
+ nt_field_t *mp_tun_cfg_data_tun_type;
+ nt_field_t *mp_tun_cfg_data_tun_vlan;
+ nt_field_t *mp_tun_cfg_data_ip_type;
+ nt_field_t *mp_tun_cfg_data_ipcs_upd;
+ nt_field_t *mp_tun_cfg_data_ipcs_precalc;
+ nt_field_t *mp_tun_cfg_data_iptl_upd;
+ nt_field_t *mp_tun_cfg_data_iptl_precalc;
+ nt_field_t *mp_tun_cfg_data_vxlan_udp_len_upd;
+ nt_field_t *mp_tun_cfg_data_tx_lag_ix;
+ nt_field_t *mp_tun_cfg_data_recirculate;
+ nt_field_t *mp_tun_cfg_data_push_tunnel;
+ nt_field_t *mp_tun_cfg_data_recirc_port;
+ nt_field_t *mp_tun_cfg_data_recirc_bypass;
+
+ nt_register_t *mp_config;
+ nt_field_t *mp_config_fwd_recirculate;
+ nt_field_t *mp_config_fwd_normal_pcks;
+ nt_field_t *mp_config_fwd_tx_port0;
+ nt_field_t *mp_config_fwd_tx_port1;
+ nt_field_t *mp_config_fwd_cell_builder_pcks;
+ nt_field_t *mp_config_fwd_non_normal_pcks;
+
+ nt_register_t *mp_lag_cfg_ctrl;
+ nt_field_t *mp_lag_cfg_addr;
+ nt_field_t *mp_lag_cfg_cnt;
+ nt_register_t *mp_lag_cfg_data;
+ nt_field_t *mp_lag_cfg_data_tx_phy_port;
+};
+
+#endif /* __FLOW_NTHW_ROA_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c
new file mode 100644
index 0000000000..2ce3ce6cf8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_rpp_lr.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void rpp_lr_nthw_set_debug_mode(struct rpp_lr_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_rpp_lr, n_debug_mode);
+}
+
+struct rpp_lr_nthw *rpp_lr_nthw_new(void)
+{
+ struct rpp_lr_nthw *p = malloc(sizeof(struct rpp_lr_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void rpp_lr_nthw_delete(struct rpp_lr_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int rpp_lr_nthw_init(struct rpp_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RPP_LR, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RppLr %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_rpp_lr = fpga_query_module(p_fpga, MOD_RPP_LR, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_rpp_lr, RPP_LR_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, RPP_LR_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, RPP_LR_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_rpp_lr, RPP_LR_RCP_DATA);
+ p->mp_rcp_data_exp = register_get_field(p->mp_rcp_data, RPP_LR_RCP_DATA_EXP);
+
+ p->mp_ifr_rcp_ctrl = module_query_register(p->m_rpp_lr, RPP_LR_IFR_RCP_CTRL);
+ p->mp_ifr_rcp_addr =
+ register_query_field(p->mp_ifr_rcp_ctrl, RPP_LR_IFR_RCP_CTRL_ADR);
+ p->mp_ifr_rcp_cnt =
+ register_query_field(p->mp_ifr_rcp_ctrl, RPP_LR_IFR_RCP_CTRL_CNT);
+ p->mp_ifr_rcp_data = module_query_register(p->m_rpp_lr, RPP_LR_IFR_RCP_DATA);
+ p->mp_ifr_rcp_data_en =
+ register_query_field(p->mp_ifr_rcp_data, RPP_LR_IFR_RCP_DATA_EN);
+ p->mp_ifr_rcp_data_mtu =
+ register_query_field(p->mp_ifr_rcp_data, RPP_LR_IFR_RCP_DATA_MTU);
+
+ return 0;
+}
+
+void rpp_lr_nthw_rcp_select(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_addr);
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void rpp_lr_nthw_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_cnt);
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void rpp_lr_nthw_rcp_exp(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_data_exp);
+ field_set_val32(p->mp_rcp_data_exp, val);
+}
+
+void rpp_lr_nthw_rcp_flush(const struct rpp_lr_nthw *p)
+{
+ assert(p->mp_rcp_ctrl);
+ assert(p->mp_rcp_data);
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+void rpp_lr_nthw_ifr_rcp_select(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_addr);
+ field_set_val32(p->mp_ifr_rcp_addr, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_cnt);
+ field_set_val32(p->mp_ifr_rcp_cnt, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_en(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_data_en);
+ field_set_val32(p->mp_ifr_rcp_data_en, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_mtu(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_data_mtu);
+ field_set_val32(p->mp_ifr_rcp_data_mtu, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_flush(const struct rpp_lr_nthw *p)
+{
+ assert(p->mp_ifr_rcp_ctrl);
+ assert(p->mp_ifr_rcp_data);
+ register_flush(p->mp_ifr_rcp_ctrl, 1);
+ register_flush(p->mp_ifr_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h
new file mode 100644
index 0000000000..e442c9d8d2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_RPP_LR_H__
+#define __FLOW_NTHW_RPP_LR_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct rpp_lr_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_rpp_lr;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_exp;
+
+ nt_register_t *mp_ifr_rcp_ctrl;
+ nt_field_t *mp_ifr_rcp_addr;
+ nt_field_t *mp_ifr_rcp_cnt;
+
+ nt_register_t *mp_ifr_rcp_data;
+ nt_field_t *mp_ifr_rcp_data_en;
+ nt_field_t *mp_ifr_rcp_data_mtu;
+};
+
+struct rpp_lr_nthw *rpp_lr_nthw_new(void);
+void rpp_lr_nthw_delete(struct rpp_lr_nthw *p);
+int rpp_lr_nthw_init(struct rpp_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int rpp_lr_nthw_setup(struct rpp_lr_nthw *p, int n_idx, int n_idx_cnt);
+void rpp_lr_nthw_set_debug_mode(struct rpp_lr_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void rpp_lr_nthw_rcp_select(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_rcp_exp(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_rcp_flush(const struct rpp_lr_nthw *p);
+
+/* RCP IFR */
+void rpp_lr_nthw_ifr_rcp_select(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_en(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_mtu(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_flush(const struct rpp_lr_nthw *p);
+
+#endif /* __FLOW_NTHW_RPP_LR_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c
new file mode 100644
index 0000000000..a409e68869
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_slc.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void slc_nthw_set_debug_mode(struct slc_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_slc, n_debug_mode);
+}
+
+struct slc_nthw *slc_nthw_new(void)
+{
+ struct slc_nthw *p = malloc(sizeof(struct slc_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void slc_nthw_delete(struct slc_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int slc_nthw_init(struct slc_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_SLC, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Slc %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_slc = fpga_query_module(p_fpga, MOD_SLC, n_instance);
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_slc, SLC_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_slc, SLC_RCP_DATA);
+ p->mp_rcp_data_tail_slc_en =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_SLC_EN);
+ p->mp_rcp_data_tail_dyn =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_DYN);
+ p->mp_rcp_data_tail_ofs =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_OFS);
+ p->mp_rcp_data_pcap = register_get_field(p->mp_rcp_data, SLC_RCP_DATA_PCAP);
+
+ return 0;
+}
+
+/* RCP */
+void slc_nthw_rcp_select(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void slc_nthw_rcp_cnt(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void slc_nthw_rcp_tail_slc_en(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_slc_en, val);
+}
+
+void slc_nthw_rcp_tail_dyn(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_dyn, val);
+}
+
+void slc_nthw_rcp_tail_ofs(const struct slc_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_ofs, val);
+}
+
+void slc_nthw_rcp_pcap(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_pcap, val);
+}
+
+void slc_nthw_rcp_flush(const struct slc_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h
new file mode 100644
index 0000000000..e0f58e27e4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_SLC_H__
+#define __FLOW_NTHW_SLC_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct slc_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_slc;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+
+ nt_field_t *mp_rcp_data_tail_slc_en;
+ nt_field_t *mp_rcp_data_tail_dyn;
+ nt_field_t *mp_rcp_data_tail_ofs;
+ nt_field_t *mp_rcp_data_pcap;
+};
+
+typedef struct slc_nthw slc_nthw_t;
+
+struct slc_nthw *slc_nthw_new(void);
+void slc_nthw_delete(struct slc_nthw *p);
+int slc_nthw_init(struct slc_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int slc_nthw_setup(struct slc_nthw *p, int n_idx, int n_idx_cnt);
+void slc_nthw_set_debug_mode(struct slc_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void slc_nthw_rcp_select(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_cnt(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_tail_slc_en(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_tail_dyn(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_tail_ofs(const struct slc_nthw *p, int32_t val);
+void slc_nthw_rcp_pcap(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_flush(const struct slc_nthw *p);
+
+#endif /* __FLOW_NTHW_SLC_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c
new file mode 100644
index 0000000000..f106974bdd
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_slc_lr.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void slc_lr_nthw_set_debug_mode(struct slc_lr_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_slc_lr, n_debug_mode);
+}
+
+struct slc_lr_nthw *slc_lr_nthw_new(void)
+{
+ struct slc_lr_nthw *p = malloc(sizeof(struct slc_lr_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void slc_lr_nthw_delete(struct slc_lr_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int slc_lr_nthw_init(struct slc_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_SLC_LR, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Slc %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_slc_lr = fpga_query_module(p_fpga, MOD_SLC_LR, n_instance);
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_slc_lr, SLC_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_slc_lr, SLC_RCP_DATA);
+ p->mp_rcp_data_tail_slc_en =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_SLC_EN);
+ p->mp_rcp_data_tail_dyn =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_DYN);
+ p->mp_rcp_data_tail_ofs =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_OFS);
+ p->mp_rcp_data_pcap = register_get_field(p->mp_rcp_data, SLC_RCP_DATA_PCAP);
+
+ return 0;
+}
+
+/* RCP */
+void slc_lr_nthw_rcp_select(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void slc_lr_nthw_rcp_cnt(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void slc_lr_nthw_rcp_tail_slc_en(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_slc_en, val);
+}
+
+void slc_lr_nthw_rcp_tail_dyn(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_dyn, val);
+}
+
+void slc_lr_nthw_rcp_tail_ofs(const struct slc_lr_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_ofs, val);
+}
+
+void slc_lr_nthw_rcp_pcap(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_pcap, val);
+}
+
+void slc_lr_nthw_rcp_flush(const struct slc_lr_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h
new file mode 100644
index 0000000000..533f2efbeb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_SLC_LR_H__
+#define __FLOW_NTHW_SLC_LR_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct slc_lr_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_slc_lr;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+
+ nt_field_t *mp_rcp_data_tail_slc_en;
+ nt_field_t *mp_rcp_data_tail_dyn;
+ nt_field_t *mp_rcp_data_tail_ofs;
+ nt_field_t *mp_rcp_data_pcap;
+};
+
+typedef struct slc_lr_nthw slc_lr_nthw_t;
+
+struct slc_lr_nthw *slc_lr_nthw_new(void);
+void slc_lr_nthw_delete(struct slc_lr_nthw *p);
+int slc_lr_nthw_init(struct slc_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int slc_lr_nthw_setup(struct slc_lr_nthw *p, int n_idx, int n_idx_cnt);
+void slc_lr_nthw_set_debug_mode(struct slc_lr_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void slc_lr_nthw_rcp_select(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_cnt(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_tail_slc_en(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_tail_dyn(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_tail_ofs(const struct slc_lr_nthw *p, int32_t val);
+void slc_lr_nthw_rcp_pcap(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_flush(const struct slc_lr_nthw *p);
+
+#endif /* __FLOW_NTHW_SLC_LR_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c
new file mode 100644
index 0000000000..4d28d8cc3d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c
@@ -0,0 +1,394 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_tx_cpy.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void tx_cpy_nthw_set_debug_mode(struct tx_cpy_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_tx_cpy, n_debug_mode);
+}
+
+struct tx_cpy_nthw *tx_cpy_nthw_new(void)
+{
+ struct tx_cpy_nthw *p = malloc(sizeof(struct tx_cpy_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void tx_cpy_nthw_delete(struct tx_cpy_nthw *p)
+{
+ if (p) {
+ free(p->m_writers);
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int tx_cpy_nthw_init(struct tx_cpy_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_CPY, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TxCpy %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_tx_cpy = fpga_query_module(p_fpga, MOD_TX_CPY, n_instance);
+
+ const int writers_cnt =
+ fpga_get_product_param(p->mp_fpga, NT_TX_CPY_WRITERS, 0);
+ if (writers_cnt < 1)
+ return -1;
+
+ p->m_writers_cnt = (unsigned int)writers_cnt;
+ p->m_writers = calloc(p->m_writers_cnt, sizeof(struct tx_cpy_writers_s));
+ if (p->m_writers == NULL)
+ return -1;
+
+ const int variant =
+ fpga_get_product_param(p->mp_fpga, NT_TX_CPY_VARIANT, 0);
+
+ switch (p->m_writers_cnt) {
+ default:
+ case 6:
+ p->m_writers[5].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_CTRL);
+ p->m_writers[5].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[5].mp_writer_ctrl,
+ CPY_WRITER5_CTRL_ADR);
+ p->m_writers[5].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[5].mp_writer_ctrl,
+ CPY_WRITER5_CTRL_CNT);
+ p->m_writers[5].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_DATA);
+ p->m_writers[5].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_READER_SELECT);
+ p->m_writers[5].mp_writer_data_dyn =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_DYN);
+ p->m_writers[5].mp_writer_data_ofs =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_OFS);
+ p->m_writers[5].mp_writer_data_len =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[5].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_MASK_POINTER);
+ p->m_writers[5].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_MASK_CTRL);
+ p->m_writers[5].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[5].mp_writer_mask_ctrl,
+ CPY_WRITER5_MASK_CTRL_ADR);
+ p->m_writers[5].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[5].mp_writer_mask_ctrl,
+ CPY_WRITER5_MASK_CTRL_CNT);
+ p->m_writers[5].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_MASK_DATA);
+ p->m_writers[5].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[5].mp_writer_mask_data,
+ CPY_WRITER5_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 5:
+ p->m_writers[4].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_CTRL);
+ p->m_writers[4].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[4].mp_writer_ctrl, CPY_WRITER4_CTRL_ADR);
+ p->m_writers[4].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[4].mp_writer_ctrl, CPY_WRITER4_CTRL_CNT);
+ p->m_writers[4].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_DATA);
+ p->m_writers[4].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[4].mp_writer_data,
+ CPY_WRITER4_DATA_READER_SELECT);
+ p->m_writers[4].mp_writer_data_dyn =
+ register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_DYN);
+ p->m_writers[4].mp_writer_data_ofs =
+ register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_OFS);
+ p->m_writers[4].mp_writer_data_len =
+ register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[4].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[4].mp_writer_data,
+ CPY_WRITER4_DATA_MASK_POINTER);
+ p->m_writers[4].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_MASK_CTRL);
+ p->m_writers[4].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[4].mp_writer_mask_ctrl,
+ CPY_WRITER4_MASK_CTRL_ADR);
+ p->m_writers[4].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[4].mp_writer_mask_ctrl,
+ CPY_WRITER4_MASK_CTRL_CNT);
+ p->m_writers[4].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_MASK_DATA);
+ p->m_writers[4].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[4].mp_writer_mask_data,
+ CPY_WRITER4_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 4:
+ p->m_writers[3].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_CTRL);
+ p->m_writers[3].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[3].mp_writer_ctrl, CPY_WRITER3_CTRL_ADR);
+ p->m_writers[3].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[3].mp_writer_ctrl, CPY_WRITER3_CTRL_CNT);
+ p->m_writers[3].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_DATA);
+ p->m_writers[3].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[3].mp_writer_data,
+ CPY_WRITER3_DATA_READER_SELECT);
+ p->m_writers[3].mp_writer_data_dyn =
+ register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_DYN);
+ p->m_writers[3].mp_writer_data_ofs =
+ register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_OFS);
+ p->m_writers[3].mp_writer_data_len =
+ register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[3].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[3].mp_writer_data,
+ CPY_WRITER3_DATA_MASK_POINTER);
+ p->m_writers[3].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_MASK_CTRL);
+ p->m_writers[3].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[3].mp_writer_mask_ctrl,
+ CPY_WRITER3_MASK_CTRL_ADR);
+ p->m_writers[3].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[3].mp_writer_mask_ctrl,
+ CPY_WRITER3_MASK_CTRL_CNT);
+ p->m_writers[3].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_MASK_DATA);
+ p->m_writers[3].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[3].mp_writer_mask_data,
+ CPY_WRITER3_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 3:
+ p->m_writers[2].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_CTRL);
+ p->m_writers[2].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[2].mp_writer_ctrl, CPY_WRITER2_CTRL_ADR);
+ p->m_writers[2].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[2].mp_writer_ctrl, CPY_WRITER2_CTRL_CNT);
+ p->m_writers[2].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_DATA);
+ p->m_writers[2].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[2].mp_writer_data,
+ CPY_WRITER2_DATA_READER_SELECT);
+ p->m_writers[2].mp_writer_data_dyn =
+ register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_DYN);
+ p->m_writers[2].mp_writer_data_ofs =
+ register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_OFS);
+ p->m_writers[2].mp_writer_data_len =
+ register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[2].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[2].mp_writer_data,
+ CPY_WRITER2_DATA_MASK_POINTER);
+ p->m_writers[2].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_MASK_CTRL);
+ p->m_writers[2].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[2].mp_writer_mask_ctrl,
+ CPY_WRITER2_MASK_CTRL_ADR);
+ p->m_writers[2].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[2].mp_writer_mask_ctrl,
+ CPY_WRITER2_MASK_CTRL_CNT);
+ p->m_writers[2].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_MASK_DATA);
+ p->m_writers[2].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[2].mp_writer_mask_data,
+ CPY_WRITER2_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 2:
+ p->m_writers[1].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_CTRL);
+ p->m_writers[1].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[1].mp_writer_ctrl, CPY_WRITER1_CTRL_ADR);
+ p->m_writers[1].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[1].mp_writer_ctrl, CPY_WRITER1_CTRL_CNT);
+ p->m_writers[1].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_DATA);
+ p->m_writers[1].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[1].mp_writer_data,
+ CPY_WRITER1_DATA_READER_SELECT);
+ p->m_writers[1].mp_writer_data_dyn =
+ register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_DYN);
+ p->m_writers[1].mp_writer_data_ofs =
+ register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_OFS);
+ p->m_writers[1].mp_writer_data_len =
+ register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[1].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[1].mp_writer_data,
+ CPY_WRITER1_DATA_MASK_POINTER);
+ p->m_writers[1].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_MASK_CTRL);
+ p->m_writers[1].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[1].mp_writer_mask_ctrl,
+ CPY_WRITER1_MASK_CTRL_ADR);
+ p->m_writers[1].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[1].mp_writer_mask_ctrl,
+ CPY_WRITER1_MASK_CTRL_CNT);
+ p->m_writers[1].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_MASK_DATA);
+ p->m_writers[1].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[1].mp_writer_mask_data,
+ CPY_WRITER1_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 1:
+ p->m_writers[0].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_CTRL);
+ p->m_writers[0].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[0].mp_writer_ctrl, CPY_WRITER0_CTRL_ADR);
+ p->m_writers[0].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[0].mp_writer_ctrl, CPY_WRITER0_CTRL_CNT);
+ p->m_writers[0].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_DATA);
+ p->m_writers[0].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[0].mp_writer_data,
+ CPY_WRITER0_DATA_READER_SELECT);
+ p->m_writers[0].mp_writer_data_dyn =
+ register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_DYN);
+ p->m_writers[0].mp_writer_data_ofs =
+ register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_OFS);
+ p->m_writers[0].mp_writer_data_len =
+ register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[0].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[0].mp_writer_data,
+ CPY_WRITER0_DATA_MASK_POINTER);
+ p->m_writers[0].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_MASK_CTRL);
+ p->m_writers[0].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[0].mp_writer_mask_ctrl,
+ CPY_WRITER0_MASK_CTRL_ADR);
+ p->m_writers[0].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[0].mp_writer_mask_ctrl,
+ CPY_WRITER0_MASK_CTRL_CNT);
+ p->m_writers[0].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_MASK_DATA);
+ p->m_writers[0].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[0].mp_writer_mask_data,
+ CPY_WRITER0_MASK_DATA_BYTE_MASK);
+ }
+ break;
+ case 0:
+ return -1;
+ }
+
+ return 0;
+}
+
+void tx_cpy_nthw_writer_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_ctrl_addr, val);
+}
+
+void tx_cpy_nthw_writer_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_ctrl_cnt, val);
+}
+
+void tx_cpy_nthw_writer_reader_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_reader_select, val);
+}
+
+void tx_cpy_nthw_writer_dyn(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_dyn, val);
+}
+
+void tx_cpy_nthw_writer_ofs(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_ofs, val);
+}
+
+void tx_cpy_nthw_writer_len(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_len, val);
+}
+
+void tx_cpy_nthw_writer_mask_pointer(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_data_mask_pointer);
+ field_set_val32(p->m_writers[index].mp_writer_data_mask_pointer, val);
+}
+
+void tx_cpy_nthw_writer_flush(const struct tx_cpy_nthw *p, unsigned int index)
+{
+ assert(index < p->m_writers_cnt);
+ register_flush(p->m_writers[index].mp_writer_ctrl, 1);
+ register_flush(p->m_writers[index].mp_writer_data, 1);
+}
+
+void tx_cpy_nthw_writer_mask_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_ctrl_addr);
+ field_set_val32(p->m_writers[index].mp_writer_mask_ctrl_addr, val);
+}
+
+void tx_cpy_nthw_writer_mask_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_ctrl_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_mask_ctrl_cnt, val);
+}
+
+void tx_cpy_nthw_writer_mask(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_data_byte_mask);
+ field_set_val32(p->m_writers[index].mp_writer_mask_data_byte_mask, val);
+}
+
+void tx_cpy_nthw_writer_mask_flush(const struct tx_cpy_nthw *p, unsigned int index)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_ctrl);
+ assert(p->m_writers[index].mp_writer_mask_data);
+ register_flush(p->m_writers[index].mp_writer_mask_ctrl, 1);
+ register_flush(p->m_writers[index].mp_writer_mask_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h
new file mode 100644
index 0000000000..f97983b29a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_TX_CPY_H__
+#define __FLOW_NTHW_TX_CPY_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct tx_cpy_writers_s {
+ nt_register_t *mp_writer_ctrl;
+ nt_field_t *mp_writer_ctrl_addr;
+ nt_field_t *mp_writer_ctrl_cnt;
+
+ nt_register_t *mp_writer_data;
+ nt_field_t *mp_writer_data_reader_select;
+ nt_field_t *mp_writer_data_dyn;
+ nt_field_t *mp_writer_data_ofs;
+ nt_field_t *mp_writer_data_len;
+ nt_field_t *mp_writer_data_mask_pointer;
+
+ nt_register_t *mp_writer_mask_ctrl;
+ nt_field_t *mp_writer_mask_ctrl_addr;
+ nt_field_t *mp_writer_mask_ctrl_cnt;
+
+ nt_register_t *mp_writer_mask_data;
+ nt_field_t *mp_writer_mask_data_byte_mask;
+};
+
+struct tx_cpy_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_tx_cpy;
+
+ unsigned int m_writers_cnt;
+ struct tx_cpy_writers_s *m_writers;
+};
+
+struct tx_cpy_nthw *tx_cpy_nthw_new(void);
+void tx_cpy_nthw_delete(struct tx_cpy_nthw *p);
+int tx_cpy_nthw_init(struct tx_cpy_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int tx_cpy_nthw_setup(struct tx_cpy_nthw *p, int n_idx, int n_idx_cnt);
+void tx_cpy_nthw_set_debug_mode(struct tx_cpy_nthw *p, unsigned int n_debug_mode);
+
+void tx_cpy_nthw_writer_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_reader_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_dyn(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_ofs(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_len(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask_pointer(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_flush(const struct tx_cpy_nthw *p, unsigned int index);
+
+void tx_cpy_nthw_writer_mask_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask_flush(const struct tx_cpy_nthw *p, unsigned int index);
+
+#endif /* __FLOW_NTHW_TX_CPY_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c
new file mode 100644
index 0000000000..998c3613ee
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_tx_ins.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void tx_ins_nthw_set_debug_mode(struct tx_ins_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_tx_ins, n_debug_mode);
+}
+
+struct tx_ins_nthw *tx_ins_nthw_new(void)
+{
+ struct tx_ins_nthw *p = malloc(sizeof(struct tx_ins_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void tx_ins_nthw_delete(struct tx_ins_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int tx_ins_nthw_init(struct tx_ins_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_INS, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TxIns %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_tx_ins = fpga_query_module(p_fpga, MOD_TX_INS, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_tx_ins, INS_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, INS_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, INS_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_tx_ins, INS_RCP_DATA);
+ p->mp_rcp_data_dyn = register_get_field(p->mp_rcp_data, INS_RCP_DATA_DYN);
+ p->mp_rcp_data_ofs = register_get_field(p->mp_rcp_data, INS_RCP_DATA_OFS);
+ p->mp_rcp_data_len = register_get_field(p->mp_rcp_data, INS_RCP_DATA_LEN);
+
+ return 0;
+}
+
+void tx_ins_nthw_rcp_select(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void tx_ins_nthw_rcp_cnt(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void tx_ins_nthw_rcp_dyn(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dyn, val);
+}
+
+void tx_ins_nthw_rcp_ofs(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs, val);
+}
+
+void tx_ins_nthw_rcp_len(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len, val);
+}
+
+void tx_ins_nthw_rcp_flush(const struct tx_ins_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h
new file mode 100644
index 0000000000..813bd30c62
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_TX_INS_H__
+#define __FLOW_NTHW_TX_INS_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct tx_ins_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_tx_ins;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_dyn;
+ nt_field_t *mp_rcp_data_ofs;
+ nt_field_t *mp_rcp_data_len;
+};
+
+struct tx_ins_nthw *tx_ins_nthw_new(void);
+void tx_ins_nthw_delete(struct tx_ins_nthw *p);
+int tx_ins_nthw_init(struct tx_ins_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int tx_ins_nthw_setup(struct tx_ins_nthw *p, int n_idx, int n_idx_cnt);
+void tx_ins_nthw_set_debug_mode(struct tx_ins_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void tx_ins_nthw_rcp_select(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_cnt(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_dyn(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_ofs(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_len(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_flush(const struct tx_ins_nthw *p);
+
+#endif /* __FLOW_NTHW_TX_INS_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c
new file mode 100644
index 0000000000..5e7e26f74d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_tx_rpl.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void tx_rpl_nthw_set_debug_mode(struct tx_rpl_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_tx_rpl, n_debug_mode);
+}
+
+struct tx_rpl_nthw *tx_rpl_nthw_new(void)
+{
+ struct tx_rpl_nthw *p = malloc(sizeof(struct tx_rpl_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void tx_rpl_nthw_delete(struct tx_rpl_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int tx_rpl_nthw_init(struct tx_rpl_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_RPL, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TxRpl %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_tx_rpl = fpga_query_module(p_fpga, MOD_TX_RPL, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_tx_rpl, RPL_RCP_CTRL);
+ p->mp_rcp_ctrl_addr = register_get_field(p->mp_rcp_ctrl, RPL_RCP_CTRL_ADR);
+ p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, RPL_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_tx_rpl, RPL_RCP_DATA);
+ p->mp_rcp_data_dyn = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_DYN);
+ p->mp_rcp_data_ofs = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_OFS);
+ p->mp_rcp_data_len = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_LEN);
+ p->mp_rcp_data_rpl_ptr =
+ register_get_field(p->mp_rcp_data, RPL_RCP_DATA_RPL_PTR);
+ p->mp_rcp_data_ext_prio =
+ register_get_field(p->mp_rcp_data, RPL_RCP_DATA_EXT_PRIO);
+
+ p->mp_ext_ctrl = module_get_register(p->m_tx_rpl, RPL_EXT_CTRL);
+ p->mp_ext_ctrl_addr = register_get_field(p->mp_ext_ctrl, RPL_EXT_CTRL_ADR);
+ p->mp_ext_ctrl_cnt = register_get_field(p->mp_ext_ctrl, RPL_EXT_CTRL_CNT);
+ p->mp_ext_data = module_get_register(p->m_tx_rpl, RPL_EXT_DATA);
+ p->mp_ext_data_rpl_ptr =
+ register_get_field(p->mp_ext_data, RPL_EXT_DATA_RPL_PTR);
+
+ p->mp_rpl_ctrl = module_get_register(p->m_tx_rpl, RPL_RPL_CTRL);
+ p->mp_rpl_ctrl_addr = register_get_field(p->mp_rpl_ctrl, RPL_RPL_CTRL_ADR);
+ p->mp_rpl_ctrl_cnt = register_get_field(p->mp_rpl_ctrl, RPL_RPL_CTRL_CNT);
+ p->mp_rpl_data = module_get_register(p->m_tx_rpl, RPL_RPL_DATA);
+ p->mp_rpl_data_value = register_get_field(p->mp_rpl_data, RPL_RPL_DATA_VALUE);
+
+ return 0;
+}
+
+void tx_rpl_nthw_rcp_select(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_addr, val);
+}
+
+void tx_rpl_nthw_rcp_cnt(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_cnt, val);
+}
+
+void tx_rpl_nthw_rcp_dyn(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dyn, val);
+}
+
+void tx_rpl_nthw_rcp_ofs(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs, val);
+}
+
+void tx_rpl_nthw_rcp_len(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len, val);
+}
+
+void tx_rpl_nthw_rcp_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_rpl_ptr, val);
+}
+
+void tx_rpl_nthw_rcp_ext_prio(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ext_prio, val);
+}
+
+void tx_rpl_nthw_rcp_flush(const struct tx_rpl_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+void tx_rpl_nthw_ext_select(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ext_ctrl_addr, val);
+}
+
+void tx_rpl_nthw_ext_cnt(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ext_ctrl_cnt, val);
+}
+
+void tx_rpl_nthw_ext_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ext_data_rpl_ptr, val);
+}
+
+void tx_rpl_nthw_ext_flush(const struct tx_rpl_nthw *p)
+{
+ register_flush(p->mp_ext_ctrl, 1);
+ register_flush(p->mp_ext_data, 1);
+}
+
+void tx_rpl_nthw_rpl_select(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rpl_ctrl_addr, val);
+}
+
+void tx_rpl_nthw_rpl_cnt(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rpl_ctrl_cnt, val);
+}
+
+void tx_rpl_nthw_rpl_value(const struct tx_rpl_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rpl_data_value, val, 4);
+}
+
+void tx_rpl_nthw_rpl_flush(const struct tx_rpl_nthw *p)
+{
+ register_flush(p->mp_rpl_ctrl, 1);
+ register_flush(p->mp_rpl_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h
new file mode 100644
index 0000000000..e5f724361b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_TX_RPL_H__
+#define __FLOW_NTHW_TX_RPL_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct tx_rpl_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_tx_rpl;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_ctrl_addr;
+ nt_field_t *mp_rcp_ctrl_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_dyn;
+ nt_field_t *mp_rcp_data_ofs;
+ nt_field_t *mp_rcp_data_len;
+ nt_field_t *mp_rcp_data_rpl_ptr;
+ nt_field_t *mp_rcp_data_ext_prio;
+
+ nt_register_t *mp_ext_ctrl;
+ nt_field_t *mp_ext_ctrl_addr;
+ nt_field_t *mp_ext_ctrl_cnt;
+
+ nt_register_t *mp_ext_data;
+ nt_field_t *mp_ext_data_rpl_ptr;
+
+ nt_register_t *mp_rpl_ctrl;
+ nt_field_t *mp_rpl_ctrl_addr;
+ nt_field_t *mp_rpl_ctrl_cnt;
+
+ nt_register_t *mp_rpl_data;
+ nt_field_t *mp_rpl_data_value;
+};
+
+struct tx_rpl_nthw *tx_rpl_nthw_new(void);
+void tx_rpl_nthw_delete(struct tx_rpl_nthw *p);
+int tx_rpl_nthw_init(struct tx_rpl_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int tx_rpl_nthw_setup(struct tx_rpl_nthw *p, int n_idx, int n_idx_cnt);
+void tx_rpl_nthw_set_debug_mode(struct tx_rpl_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void tx_rpl_nthw_rcp_select(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_cnt(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_dyn(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_ofs(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_len(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_ext_prio(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_flush(const struct tx_rpl_nthw *p);
+
+void tx_rpl_nthw_ext_select(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_ext_cnt(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_ext_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_ext_flush(const struct tx_rpl_nthw *p);
+
+void tx_rpl_nthw_rpl_select(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rpl_cnt(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rpl_value(const struct tx_rpl_nthw *p, const uint32_t *val);
+void tx_rpl_nthw_rpl_flush(const struct tx_rpl_nthw *p);
+
+#endif /* __FLOW_NTHW_TX_RPL_H__ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 5/8] net/ntnic: adds FPGA abstraction layer
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (2 preceding siblings ...)
2023-08-16 13:25 ` [PATCH 4/8] net/ntnic: adds flow related FPGA functionality Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 13:25 ` [PATCH 6/8] net/ntnic: adds flow logic Mykola Kostenok
` (16 subsequent siblings)
20 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
The FPGA abstraction layer limits the need to rewrite flow logic
when new FPGA modules are created.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/ntnic/meson.build | 21 +
.../ntnic/nthw/flow_api/flow_api_actions.c | 205 ++
.../ntnic/nthw/flow_api/flow_api_actions.h | 284 +++
.../ntnic/nthw/flow_api/flow_api_backend.c | 182 ++
.../ntnic/nthw/flow_api/flow_api_backend.h | 1818 +++++++++++++++++
.../net/ntnic/nthw/flow_api/flow_api_engine.h | 475 +++++
.../ntnic/nthw/flow_api/flow_api_nic_setup.h | 32 +
.../nthw/flow_api/flow_engine/flow_group.c | 125 ++
.../nthw/flow_api/flow_engine/flow_hasher.c | 213 ++
.../nthw/flow_api/flow_engine/flow_hasher.h | 20 +
.../nthw/flow_api/flow_engine/flow_kcc.c | 434 ++++
.../ntnic/nthw/flow_api/flow_engine/flow_km.c | 1438 +++++++++++++
.../nthw/flow_api/flow_engine/flow_tunnel.c | 787 +++++++
.../ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c | 1789 ++++++++++++++++
.../nthw/flow_api/hw_mod/hw_mod_cat_v18.h | 138 ++
.../nthw/flow_api/hw_mod/hw_mod_cat_v21.h | 88 +
.../nthw/flow_api/hw_mod/hw_mod_cat_v22.h | 83 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c | 1099 ++++++++++
.../nthw/flow_api/hw_mod/hw_mod_flm_v17.h | 274 +++
.../nthw/flow_api/hw_mod/hw_mod_flm_v20.h | 102 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c | 195 ++
.../nthw/flow_api/hw_mod/hw_mod_hsh_v5.h | 36 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c | 178 ++
.../nthw/flow_api/hw_mod/hw_mod_hst_v2.h | 32 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c | 271 +++
.../nthw/flow_api/hw_mod/hw_mod_ioa_v4.h | 36 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_km.c | 629 ++++++
.../ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h | 93 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c | 219 ++
.../nthw/flow_api/hw_mod/hw_mod_pdb_v9.h | 39 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c | 348 ++++
.../nthw/flow_api/hw_mod/hw_mod_qsl_v7.h | 45 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c | 112 +
.../nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h | 20 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c | 358 ++++
.../nthw/flow_api/hw_mod/hw_mod_roa_v6.h | 49 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c | 132 ++
.../nthw/flow_api/hw_mod/hw_mod_slc_lr.c | 132 ++
.../nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h | 19 +
.../nthw/flow_api/hw_mod/hw_mod_slc_v1.h | 19 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c | 983 +++++++++
.../nthw/flow_api/hw_mod/hw_mod_tpe_v1.h | 103 +
.../nthw/flow_api/hw_mod/hw_mod_tpe_v2.h | 37 +
.../nthw/flow_api/stream_binary_flow_api.h | 697 +++++++
44 files changed, 14389 insertions(+)
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_engine.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index c184d5d4b5..387481bb4a 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -17,6 +17,7 @@ includes = [
include_directories('nthw'),
include_directories('nthw/core'),
include_directories('nthw/supported'),
+ include_directories('nthw/flow_api'),
include_directories('nthw/flow_filter'),
include_directories('sensors'),
include_directories('sensors/avr_sensors'),
@@ -59,6 +60,26 @@ sources = files(
'nthw/core/nthw_spim.c',
'nthw/core/nthw_spis.c',
'nthw/core/nthw_tsm.c',
+ 'nthw/flow_api/flow_api_actions.c',
+ 'nthw/flow_api/flow_api_backend.c',
+ 'nthw/flow_api/flow_engine/flow_group.c',
+ 'nthw/flow_api/flow_engine/flow_hasher.c',
+ 'nthw/flow_api/flow_engine/flow_kcc.c',
+ 'nthw/flow_api/flow_engine/flow_km.c',
+ 'nthw/flow_api/flow_engine/flow_tunnel.c',
+ 'nthw/flow_api/hw_mod/hw_mod_cat.c',
+ 'nthw/flow_api/hw_mod/hw_mod_flm.c',
+ 'nthw/flow_api/hw_mod/hw_mod_hsh.c',
+ 'nthw/flow_api/hw_mod/hw_mod_hst.c',
+ 'nthw/flow_api/hw_mod/hw_mod_ioa.c',
+ 'nthw/flow_api/hw_mod/hw_mod_km.c',
+ 'nthw/flow_api/hw_mod/hw_mod_pdb.c',
+ 'nthw/flow_api/hw_mod/hw_mod_qsl.c',
+ 'nthw/flow_api/hw_mod/hw_mod_rmc.c',
+ 'nthw/flow_api/hw_mod/hw_mod_roa.c',
+ 'nthw/flow_api/hw_mod/hw_mod_slc.c',
+ 'nthw/flow_api/hw_mod/hw_mod_slc_lr.c',
+ 'nthw/flow_api/hw_mod/hw_mod_tpe.c',
'nthw/flow_filter/flow_nthw_cat.c',
'nthw/flow_filter/flow_nthw_csu.c',
'nthw/flow_filter/flow_nthw_flm.c',
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c
new file mode 100644
index 0000000000..945ab7d743
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+
+#include "ntlog.h"
+
+#include "stream_binary_flow_api.h"
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index,
+ struct tunnel_header_s *tun)
+{
+ int err = 0;
+ int num_writes = (tun->ip_version == 4) ? 4 : 8;
+
+ /*
+ * Write 4 * 4 words = 64 bytes (IPv4) or 8 * 4 words = 128 bytes (IPv6)
+ */
+ for (int i = 0; (i < num_writes) && !err; i++) {
+ for (int ii = 0; (ii < 4) && !err; ii++) {
+ /* must write each 4 words backwards! */
+ err |= hw_mod_roa_tunhdr_set(be, HW_ROA_TUNHDR,
+ index, i * 4 + ii,
+ ntohl(tun->d.hdr32[(i + 1) * 4 - ii - 1]));
+ }
+ }
+
+ return err;
+}
+
+int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions)
+{
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PRESET_ALL, index, 0);
+ /*
+ * If tunnel header specified
+ */
+ int tun_len = get_roa_tunhdr_len(color_actions);
+
+ if (tun_len) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_LEN, index,
+ tun_len);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_TYPE, index,
+ roa_get_tun_type(color_actions));
+
+ /* set the total tunnel IP header length */
+ if (get_roa_tun_ip_type(color_actions) == 1) {
+ /* IPv6 */
+ if ((size_t)tun_len > (sizeof(struct flow_elem_eth) +
+ sizeof(struct flow_elem_ipv6))) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD, index, 1);
+ /* tunnel header length excludes the IPv6 header itself */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index,
+ (uint32_t)(tun_len -
+ (sizeof(struct flow_elem_eth) +
+ sizeof(struct flow_elem_ipv6))));
+ }
+ } else {
+ /* IPv4 */
+ if ((size_t)tun_len > sizeof(struct flow_elem_eth)) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD,
+ index, 1);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index,
+ (uint32_t)(tun_len -
+ sizeof(struct flow_elem_eth)));
+ }
+ }
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IP_TYPE, index,
+ get_roa_tun_ip_type(color_actions));
+
+ if (get_roa_tun_ip_type(color_actions) == 1) {
+ /* IPv6 - Do not update the IP checksum in the tunnel header */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD, index,
+ 0);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC,
+ index, 0);
+ } else {
+ /* IPv4 */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD,
+ index, 1);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC,
+ index,
+ get_roa_tun_ip_csum(color_actions));
+ }
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD,
+ index, 1);
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PUSH_TUNNEL, index, 1);
+ }
+
+ /* bypass must be > 0 or recirculate_port >= 0 - bypass wins */
+ uint8_t recirculate_bypass = roa_get_recirc_bypass_port(color_actions);
+
+ if (recirculate_bypass) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index,
+ recirculate_bypass);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE, index, 1);
+
+ } else {
+ int32_t recirculate_port = roa_get_recirc_port(color_actions);
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index,
+ 255);
+
+ if (recirculate_port >= 0) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_PORT,
+ index, recirculate_port);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE,
+ index, 1);
+ }
+ }
+
+ uint8_t tx = roa_get_tx(color_actions);
+
+ if (tx) {
+ if (tx == DESTINATION_TX_PHY0) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,
+ index, ROA_TX_PHY0);
+ } else if (tx == DESTINATION_TX_PHY1) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,
+ index, ROA_TX_PHY1);
+ } else if (tx == (DESTINATION_TX_PHY0 | DESTINATION_TX_PHY1)) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,
+ index, ROA_TX_PHY0);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS,
+ index, 0x81); /* port 1 - only port left */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE,
+ index, 1);
+
+ } else {
+ return -1; /* ERR */
+ }
+ }
+
+ /*
+ * Special IOA memory that contains ROA information - bad FPGA design
+ */
+ if (tx || tun_len) {
+ if (be->ioa.ver > 3 && tun_len &&
+ get_roa_tun_ip_type(color_actions) == 1) {
+ /* IPv6 VxLAN tunnel. Select EPP recipe 2 */
+ hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL,
+ index, 2);
+ } else {
+ /* IPv4 VxLAN tunnel or no tunnel (select recipe 1 or 0) */
+ hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL,
+ index, !!tun_len);
+ }
+ hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_TX_PORT, index, tx);
+ }
+
+ return 0;
+}
+
+int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions)
+{
+ if (color_actions & ioa_set_vxlan_pop(0)) {
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_TUNNEL_POP, index, 1);
+ NT_LOG(DBG, FILTER, "Pop outer Tunnel (Vxlan)\n");
+ }
+
+ if (color_actions & ioa_set_vlan_pop(0)) {
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_POP, index, 1);
+ NT_LOG(DBG, FILTER, "Pop outer Vlan\n");
+ }
+
+ int tpid_sel = ioa_get_tpid_sel(color_actions);
+
+ if (color_actions & ioa_set_vlan_push(0, 0)) {
+ uint16_t tci = ioa_get_vlan_tci(color_actions);
+
+ NT_LOG(DBG, FILTER, "Push Vlan with TPID/TCI %04x/%04x\n",
+ tpid_sel ? 0x88a8 : 0x8100, tci);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_VID, index,
+ tci & 0x0FFF);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_DEI, index,
+ (tci >> 12) & 0x1);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PCP, index,
+ (tci >> 13) & 0x7);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PUSH, index, 1);
+ }
+
+ int queue = ioa_get_queue(color_actions);
+
+ if (queue >= 0) {
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_OVERRIDE_EN, index, 1);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_ID, index, queue);
+ }
+
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_TPID_SEL, index, tpid_sel);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h
new file mode 100644
index 0000000000..400066e817
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_ACTIONS_H_
+#define _FLOW_ACTIONS_H_
+
+struct flow_api_backend_s;
+struct tunnel_header_s;
+
+#define MAX_COLOR_FLOW_STATS 0x400
+
+#define ROA_RECIRC_BYPASS_PHY_OFFSET 0x80
+#define MAX_REPLICATION_PORTS 2
+
+enum {
+ DESTINATION_TX_NONE = 0,
+ DESTINATION_TX_PHY0 = 1,
+ DESTINATION_TX_PHY1 = 2
+};
+
+enum { TUN_IPV4 = 0, TUN_IPV6 };
+
+enum {
+ VLAN_TPID_802_1Q = 0,
+ VLAN_TPID_802_1AD,
+ VLAN_TPID_CUSTOM_0,
+ VLAN_TPID_CUSTOM_1
+};
+
+enum { ROA_TX_NO_RETRANSMIT = 0, ROA_TX_PHY0, ROA_TX_PHY1, ROA_TX_RESERVED };
+
+/*
+ * before version 6 of QSL
+ */
+#if (MAX_COLOR_FLOW_STATS == 0x4000)
+#define MAX_HW_FLOW_STATS_OLD 0x3fff
+
+#else
+#if (MAX_COLOR_FLOW_STATS == 0x400)
+#define MAX_HW_FLOW_STATS_OLD 0x03ff
+#else
+#error *** Unsupported number of color statistics counter ***
+#endif
+#endif
+
+/*
+ * OLD behavior substituted from 4.1+
+ *
+ * 13:0 Mark (color) 16384 flow stats
+ * 21:14 IOA index 256 entries
+ * 29:22 ROA index 256 entries
+ * 31:30 1 to indicate this layout
+ * or
+ * 9:0 Mark (color) 1024 flow stats
+ * 19:10 IOA index 1024 entries
+ * 29:20 ROA index 1024 entries
+ * 31:30 0 to indicate this layout
+ */
+static inline uint32_t set_color_action_old(uint32_t color, uint32_t ioa_rcp,
+ uint32_t roa_rcp)
+{
+#if (MAX_COLOR_FLOW_STATS == 0x400)
+ uint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) |
+ ((ioa_rcp & 0x3ff) << 10) |
+ ((roa_rcp & 0x3ff) << 20) | (0 << 30);
+#else
+ uint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) |
+ ((ioa_rcp & 0xff) << 14) |
+ ((roa_rcp & 0xff) << 22) | (1 << 30);
+#endif
+ return color_action;
+}
+
+#define BITMASK(a, b) ((1U << ((a) - (b) + 1)) - 1)
+
+/*
+ * 9:0 Mark (color) 1024 flow stats
+ * 17:10 IOA index 256 entries
+ * 25:18 ROA index 256 entries
+ * 30:26 QSL and HSH 32 recipes indexable
+ * 31:31 CAO implicitly when color_action is set
+ */
+#define FLOW_MARK_MASK BITMASK(9, 0)
+#define IOA_RCP_MASK BITMASK(17, 10)
+#define ROA_RCP_MASK BITMASK(25, 18)
+#define QSL_HSH_MASK BITMASK(30, 26)
+
+static inline uint32_t set_color_action(uint32_t mark, uint32_t ioa_rcp,
+ uint32_t roa_rcp, uint32_t qsl_hsh)
+{
+ uint32_t color_action = (mark & FLOW_MARK_MASK) |
+ ((ioa_rcp & IOA_RCP_MASK) << 10) |
+ ((roa_rcp & ROA_RCP_MASK) << 18) |
+ ((qsl_hsh & QSL_HSH_MASK) << 26) | (1 << 31);
+ return color_action;
+}
+
+/*
+ * This is a bitmask representation in SW for
+ * roa config settings. It is mostly done for
+ * effective cache matching
+ *
+ * ROA config bit offs bits
+ * ----------------------------
+ * recirc port 7:0 8 -> uses hbx > 0
+ * recirc bypass 15:8 8 -> uses hbx > 0 if set, will override
+ * tunnel type 19:16 4
+ * tx port 23:20 4 -> txport + 1
+ * tun_ip_type 24:24 1
+ * recirculate 25:25 1 -> recirculate port set
+ * tunhdr_len 33:26 8 -> tunnel header length - 0 if none
+ * ip_csum_prec 49:34 16 -> tunnel ip header checksum pre-calculated
+ * new_recirc_port 50:50 1 -> indication of a new port for recirculate has been allocated.
+ * Needs default queue
+ */
+
+static inline uint64_t set_roa_new_recirc_port(uint64_t actions)
+{
+ actions |= 1ULL << 50;
+ return actions;
+}
+
+static inline uint8_t get_roa_new_recirc_port(uint64_t actions)
+{
+ return (uint8_t)((actions >> 50) & 1);
+}
+
+static inline uint64_t set_roa_tun_ip_type(uint64_t actions, uint8_t ip_type)
+{
+ actions |= (uint64_t)(ip_type & 1) << 24;
+ return actions;
+}
+
+static inline uint8_t get_roa_tun_ip_type(uint64_t actions)
+{
+ return (uint8_t)((actions >> 24) & 1);
+}
+
+static inline uint64_t set_roa_tun_ip_csum(uint64_t actions, uint16_t csum)
+{
+ actions |= (uint64_t)csum << 34;
+ return actions;
+}
+
+static inline uint16_t get_roa_tun_ip_csum(uint64_t actions)
+{
+ return (uint16_t)((actions >> 34) & 0xffff);
+}
+
+static inline uint64_t set_roa_tunhdr_len(uint64_t actions, uint8_t length)
+{
+ actions |= (uint64_t)length << 26;
+ return actions;
+}
+
+static inline uint8_t get_roa_tunhdr_len(uint64_t actions)
+{
+ return (uint8_t)((actions >> 26) & 0xff);
+}
+
+static inline uint64_t set_roa_tx(uint64_t actions, uint8_t txport)
+{
+ actions |= ((txport + ROA_TX_PHY0) & 0x0f) << 20;
+ return actions;
+}
+
+static inline uint8_t roa_get_tx(uint64_t actions)
+{
+ return (actions >> 20) & 0x0f;
+}
+
+static inline uint64_t set_roa_tun_type(uint64_t actions, uint8_t type)
+{
+ actions |= (type & 0x0f) << 16;
+ return actions;
+}
+
+static inline uint8_t roa_get_tun_type(uint64_t actions)
+{
+ return (actions >> 16) & 0x0f;
+}
+
+static inline uint64_t set_roa_recirculate(uint64_t actions, uint8_t port)
+{
+ actions |= (1ULL << 25) | port;
+ return actions;
+}
+
+static inline int32_t roa_get_recirc_port(uint64_t actions)
+{
+ if (!((1ULL << 25) & actions))
+ return -1;
+ return (actions & 0xff);
+}
+
+static inline uint64_t set_roa_recirc_bypass(uint64_t actions, uint8_t port)
+{
+ actions |= ((uint64_t)port & 0xff) << 8;
+ return actions;
+}
+
+static inline uint8_t roa_get_recirc_bypass_port(uint64_t actions)
+{
+ return ((actions >> 8) & 0xff);
+}
+
+/*
+ * This is a bitmask representation in SW for
+ * ioa action settings. It is mostly done for
+ * effective cache matching
+ *
+ * IOA action bit offs bits
+ * --------------------------------
+ * tci 15:0 16
+ * queue 23:16 8 uses hbx
+ * tpid select 27:24 4
+ * pop vxlan 28 1
+ * pop vlan 29 1
+ * push vlan 30 1
+ * queue override 31 1
+ */
+
+static inline uint64_t ioa_set_queue(uint64_t actions, uint8_t hb)
+{
+ actions |= (1 << 31) | ((uint64_t)hb << 16);
+ return actions;
+}
+
+static inline int ioa_get_queue(uint64_t actions)
+{
+ if (!(actions & (1 << 31)))
+ return -1;
+ return ((actions >> 16) & 0xff);
+}
+
+static inline uint64_t ioa_set_vxlan_pop(uint64_t actions)
+{
+ actions |= 1 << 28;
+ return actions;
+}
+
+static inline uint64_t ioa_set_vlan_pop(uint64_t actions)
+{
+ actions |= 1 << 29;
+ return actions;
+}
+
+static inline uint64_t ioa_set_vlan_push_qinq(uint64_t actions)
+{
+ actions |= (VLAN_TPID_802_1AD & 0x0f) << 24;
+ return actions;
+}
+
+static inline uint8_t ioa_get_tpid_sel(uint64_t actions)
+{
+ return (uint8_t)((actions >> 24) & 0x0f);
+}
+
+static inline uint64_t ioa_set_vlan_push(uint64_t actions, uint16_t tci)
+{
+ actions |= (1 << 30) | tci;
+ return actions;
+}
+
+static inline uint64_t ioa_set_vlan_pcp(uint64_t actions, uint8_t pcp)
+{
+ actions |= (1 << 30) | ((uint16_t)(pcp & 7) << 13);
+ return actions;
+}
+
+static inline uint16_t ioa_get_vlan_tci(uint64_t actions)
+{
+ return (uint16_t)(actions & 0xffff);
+}
+
+int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index,
+ struct tunnel_header_s *tun);
+int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions);
+int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions);
+
+#endif /* _FLOW_ACTIONS_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c
new file mode 100644
index 0000000000..a36168a115
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+
+#include "flow_api_backend.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct {
+ const char *name;
+ int (*allocate)(struct flow_api_backend_s *be);
+ void (*free)(struct flow_api_backend_s *be);
+ int (*reset)(struct flow_api_backend_s *be);
+ bool (*present)(struct flow_api_backend_s *be);
+} module[] = {
+ { "CAT", hw_mod_cat_alloc, hw_mod_cat_free, hw_mod_cat_reset,
+ hw_mod_cat_present
+ },
+ { "KM", hw_mod_km_alloc, hw_mod_km_free, hw_mod_km_reset,
+ hw_mod_km_present
+ },
+ { "FLM", hw_mod_flm_alloc, hw_mod_flm_free, hw_mod_flm_reset,
+ hw_mod_flm_present
+ },
+ { "HSH", hw_mod_hsh_alloc, hw_mod_hsh_free, hw_mod_hsh_reset,
+ hw_mod_hsh_present
+ },
+ { "HST", hw_mod_hst_alloc, hw_mod_hst_free, hw_mod_hst_reset,
+ hw_mod_hst_present
+ },
+ { "QSL", hw_mod_qsl_alloc, hw_mod_qsl_free, hw_mod_qsl_reset,
+ hw_mod_qsl_present
+ },
+ { "SLC", hw_mod_slc_alloc, hw_mod_slc_free, hw_mod_slc_reset,
+ hw_mod_slc_present
+ },
+ { "SLC LR", hw_mod_slc_lr_alloc, hw_mod_slc_lr_free,
+ hw_mod_slc_lr_reset, hw_mod_slc_lr_present
+ },
+ { "PDB", hw_mod_pdb_alloc, hw_mod_pdb_free, hw_mod_pdb_reset,
+ hw_mod_pdb_present
+ },
+ { "IOA", hw_mod_ioa_alloc, hw_mod_ioa_free, hw_mod_ioa_reset,
+ hw_mod_ioa_present
+ },
+ { "ROA", hw_mod_roa_alloc, hw_mod_roa_free, hw_mod_roa_reset,
+ hw_mod_roa_present
+ },
+ { "RMC", hw_mod_rmc_alloc, hw_mod_rmc_free, hw_mod_rmc_reset,
+ hw_mod_rmc_present
+ },
+ { "TPE", hw_mod_tpe_alloc, hw_mod_tpe_free, hw_mod_tpe_reset,
+ hw_mod_tpe_present
+ },
+};
+
+#define MOD_COUNT (ARRAY_SIZE(module))
+
+void *callocate_mod(struct common_func_s *mod, int sets, ...)
+{
+#define MAX_SETS 38
+ void *base = NULL;
+ void **plist[MAX_SETS];
+ int len[MAX_SETS];
+ int offs[MAX_SETS];
+ unsigned int total_bytes = 0;
+ int cnt, elem_size;
+
+ assert(sets <= MAX_SETS);
+ assert(sets > 0);
+
+ va_list args;
+
+ va_start(args, sets);
+
+ for (int i = 0; i < sets; i++) {
+ plist[i] = va_arg(args, void *);
+ cnt = va_arg(args, int);
+ elem_size = va_arg(args, int);
+ offs[i] = EXTRA_INDEXES * elem_size;
+ len[i] = offs[i] + cnt * elem_size;
+ total_bytes += len[i];
+ }
+ base = calloc(1, total_bytes);
+ if (base) {
+ char *p_b = (char *)base;
+
+ for (int i = 0; i < sets; i++) {
+ (*plist[i]) = (void *)((char *)p_b + offs[i]);
+ p_b += len[i];
+ }
+ } else {
+ NT_LOG(ERR, FILTER, "ERROR: module memory allocation failed\n");
+ }
+
+ va_end(args);
+
+ mod->base = base;
+ mod->alloced_size = total_bytes;
+
+ return base;
+}
+
+void zero_module_cache(struct common_func_s *mod)
+{
+ memset(mod->base, 0, mod->alloced_size);
+}
+
+int flow_api_backend_init(struct flow_api_backend_s *dev,
+ const struct flow_api_backend_ops *iface,
+ void *be_dev)
+{
+ assert(dev);
+ dev->iface = iface;
+ dev->be_dev = be_dev;
+ dev->num_phy_ports = iface->get_nb_phy_port(be_dev);
+ dev->num_rx_ports = iface->get_nb_rx_port(be_dev);
+ dev->max_categories = iface->get_nb_categories(be_dev);
+ dev->max_queues = iface->get_nb_queues(be_dev);
+
+ NT_LOG(DBG, FILTER,
+ "*************** FLOW REGISTER MODULES AND INITIALIZE - SET ALL TO DEFAULT *****************\n");
+ /*
+ * Create Cache and SW, version independent, NIC module representation
+ */
+ for (unsigned int mod = 0; mod < MOD_COUNT; mod++) {
+ if (!module[mod].present(dev))
+ continue;
+ if (module[mod].allocate(dev) == 0 &&
+ module[mod].reset(dev) == 0) {
+ /* OK */
+ continue;
+ } else {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Initialization of NIC module failed : [ %s ]\n",
+ module[mod].name);
+ flow_api_backend_done(dev);
+ NT_LOG(ERR, FILTER,
+ "*************** Failed to create Binary Flow API *******************\n");
+ NT_LOG(ERR, FILTER,
+ "******** ERROR ERROR: Binary Flow API will not be available ********\n");
+ NT_LOG(ERR, FILTER,
+ "********************************************************************\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int flow_api_backend_reset(struct flow_api_backend_s *dev)
+{
+ assert(dev);
+
+ for (unsigned int mod = 0; mod < MOD_COUNT; mod++) {
+ if (module[mod].reset(dev) == 0) {
+ /* OK */
+ continue;
+ } else {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Resetting NIC module failed : [ %s ]\n",
+ module[mod].name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int flow_api_backend_done(struct flow_api_backend_s *dev)
+{
+ for (unsigned int mod = 0; mod < MOD_COUNT; mod++)
+ module[mod].free(dev);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h
new file mode 100644
index 0000000000..099e790c81
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h
@@ -0,0 +1,1818 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_API_BACKEND_H__
+#define __FLOW_API_BACKEND_H__
+
+/*
+ * Flow API
+ * Direct access to NIC HW module memory and register fields in a
+ * module version independent representation
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "ntlog.h"
+
+/* supported module versions */
+#include "../flow_api/hw_mod/hw_mod_km_v7.h"
+#include "flow_api/hw_mod/hw_mod_cat_v18.h"
+#include "flow_api/hw_mod/hw_mod_cat_v21.h"
+#include "flow_api/hw_mod/hw_mod_cat_v22.h"
+#include "flow_api/hw_mod/hw_mod_flm_v17.h"
+#include "flow_api/hw_mod/hw_mod_flm_v20.h"
+#include "flow_api/hw_mod/hw_mod_hst_v2.h"
+#include "flow_api/hw_mod/hw_mod_km_v7.h"
+#include "flow_api/hw_mod/hw_mod_qsl_v7.h"
+#include "flow_api/hw_mod/hw_mod_pdb_v9.h"
+#include "flow_api/hw_mod/hw_mod_slc_v1.h"
+#include "flow_api/hw_mod/hw_mod_slc_lr_v2.h"
+#include "flow_api/hw_mod/hw_mod_roa_v6.h"
+#include "flow_api/hw_mod/hw_mod_hsh_v5.h"
+#include "flow_api/hw_mod/hw_mod_ioa_v4.h"
+#include "flow_api/hw_mod/hw_mod_rmc_v1_3.h"
+#include "flow_api/hw_mod/hw_mod_tpe_v1.h"
+#include "flow_api/hw_mod/hw_mod_tpe_v2.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_PHYS_ADAPTERS 8
+
+#define VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
+#define VER_MINOR(ver) ((ver) & 0xffff)
+
+struct flow_api_backend_s;
+struct common_func_s;
+
+#define CAST_COMMON(mod) ((struct common_func_s *)(mod))
+
+void *callocate_mod(struct common_func_s *mod, int sets, ...);
+void zero_module_cache(struct common_func_s *mod);
+
+#define ZERO_MOD_CACHE(mod) (zero_module_cache(CAST_COMMON(mod)))
+
+#define ALL_ENTRIES -1000
+#define ALL_BANK_ENTRIES -1001
+
+static inline int error_index_too_large(const char *func)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Index too large\n", func);
+ return -2;
+}
+
+static inline int error_word_off_too_large(const char *func)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Word offset too large\n", func);
+ return -3;
+}
+
+static inline int error_unsup_ver(const char *func, const char *mod, int ver)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Unsupported NIC module: %s ver %i.%i\n",
+ func, mod, VER_MAJOR(ver), VER_MINOR(ver));
+ return -4;
+}
+
+static inline int error_unsup_field(const char *func)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Unsupported field in NIC module\n",
+ func);
+ return -5;
+}
+
+static inline int error_resource_count(const char *func, const char *resource,
+ const char *mod, int ver)
+{
+ NT_LOG(INF, FILTER,
+ "ERROR:%s: Insufficient resource [ %s ] : NIC module:"
+ "%s ver %i.%i\n",
+ func, resource, mod, VER_MAJOR(ver), VER_MINOR(ver));
+ return -4;
+}
+
+#define NOT_FOUND 0xffffffff
+
+enum { EXTRA_INDEXES };
+#define COPY_INDEX (EXTRA_INDEX_COPY - EXTRA_INDEXES)
+
+static inline void get_set(uint32_t *cached_val, uint32_t *val, int get)
+{
+ if (get)
+ *val = *cached_val;
+ else
+ *cached_val = *val;
+}
+
+static inline void get_set_signed(int32_t *cached_val, uint32_t *val, int get)
+{
+ if (get)
+ *val = (uint32_t)*cached_val;
+ else
+ *cached_val = (int32_t)*val;
+}
+
+static inline int find_equal_index(void *be_module_reg,
+ unsigned int type_size, unsigned int idx, unsigned int start,
+ unsigned int nb_elements, uint32_t *value, int get, const char *func)
+{
+ unsigned int i;
+ if (!get)
+ return error_unsup_field(func);
+ *value = NOT_FOUND;
+ if (start >= nb_elements)
+ return error_index_too_large(func);
+ for (i = start; i < nb_elements; i++) {
+ if (idx == i)
+ continue;
+ if (memcmp((uint8_t *)be_module_reg + idx * type_size,
+ (uint8_t *)be_module_reg + i * type_size,
+ type_size) == 0) {
+ *value = i;
+ break;
+ }
+ }
+ return 0;
+}
+
+static inline int do_compare_indexes(void *be_module_reg,
+ unsigned int type_size, unsigned int idx, unsigned int cmp_idx,
+ unsigned int nb_elements, int get, const char *func)
+{
+ if (!get)
+ return error_unsup_field(func);
+ if (cmp_idx >= nb_elements)
+ return error_index_too_large(func);
+ if (idx != cmp_idx &&
+ (memcmp((uint8_t *)be_module_reg + idx * type_size,
+ (uint8_t *)be_module_reg + cmp_idx * type_size,
+ type_size) == 0))
+ return 1;
+ return 0;
+}
+
+static inline int is_non_zero(const void *addr, size_t n)
+{
+ size_t i = 0;
+ const uint8_t *p = (const uint8_t *)addr;
+
+ for (i = 0; i < n; i++) {
+ if (p[i] != 0)
+ return 1;
+ }
+ return 0;
+}
+
+static inline int is_all_bits_set(const void *addr, size_t n)
+{
+ size_t i = 0;
+ const uint8_t *p = (const uint8_t *)addr;
+
+ for (i = 0; i < n; i++) {
+ if (p[i] != 0xff)
+ return 0;
+ }
+ return 1;
+}
+
+enum cte_index_e {
+ CT_COL = 0,
+ CT_COR = 1,
+ CT_HSH = 2,
+ CT_QSL = 3,
+ CT_IPF = 4,
+ CT_SLC = 5,
+ CT_PDB = 6,
+ CT_MSK = 7,
+ CT_HST = 8,
+ CT_EPP = 9,
+ CT_TPE = 10,
+ CT_RRB = 11,
+ CT_CNT
+};
+
+/* Sideband info bit indicator */
+#define SWX_INFO (1 << 6)
+
+enum frame_offs_e {
+ DYN_SOF = 0,
+ DYN_L2 = 1,
+ DYN_FIRST_VLAN = 2,
+ DYN_MPLS = 3,
+ DYN_L3 = 4,
+ DYN_ID_IPV4_6 = 5,
+ DYN_FINAL_IP_DST = 6,
+ DYN_L4 = 7,
+ DYN_L4_PAYLOAD = 8,
+ DYN_TUN_PAYLOAD = 9,
+ DYN_TUN_L2 = 10,
+ DYN_TUN_VLAN = 11,
+ DYN_TUN_MPLS = 12,
+ DYN_TUN_L3 = 13,
+ DYN_TUN_ID_IPV4_6 = 14,
+ DYN_TUN_FINAL_IP_DST = 15,
+ DYN_TUN_L4 = 16,
+ DYN_TUN_L4_PAYLOAD = 17,
+ DYN_EOF = 18,
+ DYN_L3_PAYLOAD_END = 19,
+ DYN_TUN_L3_PAYLOAD_END = 20,
+ SB_VNI = SWX_INFO | 1,
+ SB_MAC_PORT = SWX_INFO | 2,
+ SB_KCC_ID = SWX_INFO | 3
+};
+
+enum km_flm_if_select_e { KM_FLM_IF_FIRST = 0, KM_FLM_IF_SECOND = 1 };
+
+enum {
+ QW0_SEL_EXCLUDE = 0,
+ QW0_SEL_FIRST32 = 1,
+ QW0_SEL_SECOND32 = 2,
+ QW0_SEL_FIRST64 = 3,
+ QW0_SEL_ALL128 = 4,
+};
+
+enum {
+ QW4_SEL_EXCLUDE = 0,
+ QW4_SEL_FIRST32 = 1,
+ QW4_SEL_FIRST64 = 2,
+ QW4_SEL_ALL128 = 3,
+};
+
+enum {
+ SW8_SEL_EXCLUDE = 0,
+ SW8_SEL_FIRST16 = 1,
+ SW8_SEL_SECOND16 = 2,
+ SW8_SEL_ALL32 = 3,
+};
+
+enum {
+ DW8_SEL_EXCLUDE = 0,
+ DW8_SEL_FIRST16 = 1,
+ DW8_SEL_SECOND16 = 2,
+ DW8_SEL_FIRST32 = 3,
+ DW8_SEL_FIRST32_SWAP16 = 4,
+ DW8_SEL_ALL64 = 5,
+};
+
+enum {
+ SW9_SEL_EXCLUDE = 0,
+ SW9_SEL_FIRST16 = 1,
+ SW9_SEL_ALL32 = 2,
+};
+
+enum {
+ DW10_SEL_EXCLUDE = 0,
+ DW10_SEL_FIRST16 = 1,
+ DW10_SEL_FIRST32 = 2,
+ DW10_SEL_ALL64 = 3,
+};
+
+enum {
+ SWX_SEL_EXCLUDE = 0,
+ SWX_SEL_ALL32 = 1,
+};
+
+enum {
+ PROT_OTHER = 0,
+ PROT_L2_ETH2 = 1,
+ PROT_L2_SNAP = 2,
+ PROT_L2_LLC = 3,
+ PROT_L2_RAW = 4,
+ PROT_L2_PPPOE_D = 5,
+ PROT_L2_PPOE_S = 6
+};
+
+enum { PROT_L3_IPV4 = 1, PROT_L3_IPV6 = 2 };
+
+enum { PROT_L4_TCP = 1, PROT_L4_UDP = 2, PROT_L4_SCTP = 3, PROT_L4_ICMP = 4 };
+
+enum {
+ PROT_TUN_IP_IN_IP = 1,
+ PROT_TUN_ETHER_IP = 2,
+ PROT_TUN_GREV0 = 3,
+ PROT_TUN_GREV1 = 4,
+ PROT_TUN_GTPV0U = 5,
+ PROT_TUN_GTPV1U = 6,
+ PROT_TUN_GTPV1C = 7,
+ PROT_TUN_GTPV2C = 8,
+ PROT_TUN_VXLAN = 9,
+ PROT_TUN_PSEUDO_WIRE = 10
+};
+
+enum { PROT_TUN_L2_OTHER = 0, PROT_TUN_L2_ETH2 = 1 };
+
+enum { PROT_TUN_L3_OTHER = 0, PROT_TUN_L3_IPV4 = 1, PROT_TUN_L3_IPV6 = 2 };
+
+enum {
+ PROT_TUN_L4_OTHER = 0,
+ PROT_TUN_L4_TCP = 1,
+ PROT_TUN_L4_UDP = 2,
+ PROT_TUN_L4_SCTP = 3,
+ PROT_TUN_L4_ICMP = 4
+};
+
+enum {
+ IP_FRAG_NOT_A_FRAG = 0,
+ IP_FRAG_FIRST = 1,
+ IP_FRAG_MIDDLE = 2,
+ IP_FRAG_LAST = 3
+};
+
+enum {
+ HASH_HASH_NONE = 0,
+ HASH_USER_DEFINED = 1,
+ HASH_LAST_MPLS_LABEL = 2,
+ HASH_ALL_MPLS_LABELS = 3,
+ HASH_2TUPLE = 4,
+ HASH_2TUPLESORTED = 5,
+ HASH_LAST_VLAN_ID = 6,
+ HASH_ALL_VLAN_IDS = 7,
+ HASH_5TUPLE = 8,
+ HASH_5TUPLESORTED = 9,
+ HASH_3TUPLE_GRE_V0 = 10,
+ HASH_3TUPLE_GRE_V0_SORTED = 11,
+ HASH_5TUPLE_SCTP = 12,
+ HASH_5TUPLE_SCTP_SORTED = 13,
+ HASH_3TUPLE_GTP_V0 = 14,
+ HASH_3TUPLE_GTP_V0_SORTED = 15,
+ HASH_3TUPLE_GTP_V1V2 = 16,
+ HASH_3TUPLE_GTP_V1V2_SORTED = 17,
+ HASH_HASHINNER_2TUPLE = 18,
+ HASH_HASHINNER_2TUPLESORTED = 19,
+ HASH_HASHINNER_5TUPLE = 20,
+ HASH_HASHINNER_5TUPLESORTED = 21,
+ HASH_KM = 30,
+ HASH_ROUND_ROBIN = 31,
+ HASH_OUTER_DST_IP = 32,
+ HASH_INNER_SRC_IP = 33,
+};
+
+enum {
+ CPY_SELECT_DSCP_IPV4 = 0,
+ CPY_SELECT_DSCP_IPV6 = 1,
+ CPY_SELECT_RQI_QFI = 2,
+ CPY_SELECT_IPV4 = 3,
+ CPY_SELECT_PORT = 4,
+ CPY_SELECT_TEID = 5,
+};
+
+#define RCK_CML(_comp_) (1 << ((_comp_) * 4))
+#define RCK_CMU(_comp_) (1 << ((_comp_) * 4 + 1))
+#define RCK_SEL(_comp_) (1 << ((_comp_) * 4 + 2))
+#define RCK_SEU(_comp_) (1 << ((_comp_) * 4 + 3))
+
+#define RCK_EXT(x) (((uint32_t)(x) << 6))
+
+#define FIELD_START_INDEX 100
+
+#define COMMON_FUNC_INFO_S \
+ int ver; \
+ void *base; \
+ unsigned int alloced_size; \
+ int debug
+
+struct common_func_s {
+ COMMON_FUNC_INFO_S;
+};
+
+struct cat_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_cat_funcs;
+ uint32_t nb_flow_types;
+ uint32_t nb_pm_ext;
+ uint32_t nb_len;
+ uint32_t kcc_size;
+ uint32_t cts_num;
+ uint32_t kcc_banks;
+ uint32_t kcc_id_bit_size;
+ uint32_t kcc_records;
+ uint32_t km_if_count;
+ int32_t km_if_m0;
+ int32_t km_if_m1;
+
+ union {
+ struct hw_mod_cat_v18_s v18;
+ struct hw_mod_cat_v21_s v21;
+ struct hw_mod_cat_v22_s v22;
+ };
+};
+
+enum hw_cat_e {
+ /*
+ * functions initial CAT v18
+ */
+ /* 00 */ HW_CAT_CFN_SET_ALL_DEFAULTS = 0,
+ /* 01 */ HW_CAT_CFN_PRESET_ALL,
+ /* 02 */ HW_CAT_CFN_COMPARE,
+ /* 03 */ HW_CAT_CFN_FIND,
+ /* 04 */ HW_CAT_CFN_COPY_FROM,
+ /* 05 */ HW_CAT_COT_PRESET_ALL,
+ /* 06 */ HW_CAT_COT_COMPARE,
+ /* 07 */ HW_CAT_COT_FIND,
+ /* fields */
+ /* 00 */ HW_CAT_CFN_ENABLE = FIELD_START_INDEX,
+ /* 01 */ HW_CAT_CFN_INV,
+ /* 02 */ HW_CAT_CFN_PTC_INV,
+ /* 03 */ HW_CAT_CFN_PTC_ISL,
+ /* 04 */ HW_CAT_CFN_PTC_CFP,
+ /* 05 */ HW_CAT_CFN_PTC_MAC,
+ /* 06 */ HW_CAT_CFN_PTC_L2,
+ /* 07 */ HW_CAT_CFN_PTC_VNTAG,
+ /* 08 */ HW_CAT_CFN_PTC_VLAN,
+ /* 09 */ HW_CAT_CFN_PTC_MPLS,
+ /* 10 */ HW_CAT_CFN_PTC_L3,
+ /* 11 */ HW_CAT_CFN_PTC_FRAG,
+ /* 12 */ HW_CAT_CFN_PTC_IP_PROT,
+ /* 13 */ HW_CAT_CFN_PTC_L4,
+ /* 14 */ HW_CAT_CFN_PTC_TUNNEL,
+ /* 15 */ HW_CAT_CFN_PTC_TNL_L2,
+ /* 16 */ HW_CAT_CFN_PTC_TNL_VLAN,
+ /* 17 */ HW_CAT_CFN_PTC_TNL_MPLS,
+ /* 18 */ HW_CAT_CFN_PTC_TNL_L3,
+ /* 19 */ HW_CAT_CFN_PTC_TNL_FRAG,
+ /* 20 */ HW_CAT_CFN_PTC_TNL_IP_PROT,
+ /* 21 */ HW_CAT_CFN_PTC_TNL_L4,
+ /* 22 */ HW_CAT_CFN_ERR_INV,
+ /* 23 */ HW_CAT_CFN_ERR_CV,
+ /* 24 */ HW_CAT_CFN_ERR_FCS,
+ /* 25 */ HW_CAT_CFN_ERR_TRUNC,
+ /* 26 */ HW_CAT_CFN_ERR_L3_CS,
+ /* 27 */ HW_CAT_CFN_ERR_L4_CS,
+ /* 28 */ HW_CAT_CFN_MAC_PORT,
+ /* 29 */ HW_CAT_CFN_PM_CMP,
+ /* 30 */ HW_CAT_CFN_PM_DCT,
+ /* 31 */ HW_CAT_CFN_PM_EXT_INV,
+ /* 32 */ HW_CAT_CFN_PM_CMB,
+ /* 33 */ HW_CAT_CFN_PM_AND_INV,
+ /* 34 */ HW_CAT_CFN_PM_OR_INV,
+ /* 35 */ HW_CAT_CFN_PM_INV,
+ /* 36 */ HW_CAT_CFN_LC,
+ /* 37 */ HW_CAT_CFN_LC_INV,
+ /* 38 */ HW_CAT_CFN_KM0_OR,
+ /* 39 */ HW_CAT_CFN_KM1_OR,
+ /* 40 */ HW_CAT_KCE_ENABLE_BM,
+ /* 41 */ HW_CAT_KCS_CATEGORY,
+ /* 42 */ HW_CAT_FTE_ENABLE_BM,
+ /* 43 */ HW_CAT_CTE_ENABLE_BM,
+ /* 44 */ HW_CAT_CTS_CAT_A,
+ /* 45 */ HW_CAT_CTS_CAT_B,
+ /* 46 */ HW_CAT_COT_COLOR,
+ /* 47 */ HW_CAT_COT_KM,
+ /* 48 */ HW_CAT_CCT_COLOR,
+ /* 49 */ HW_CAT_CCT_KM,
+ /* 50 */ HW_CAT_KCC_KEY,
+ /* 51 */ HW_CAT_KCC_CATEGORY,
+ /* 52 */ HW_CAT_KCC_ID,
+ /* 53 */ HW_CAT_EXO_DYN,
+ /* 54 */ HW_CAT_EXO_OFS,
+ /* 55 */ HW_CAT_RCK_DATA,
+ /* 56 */ HW_CAT_LEN_LOWER,
+ /* 57 */ HW_CAT_LEN_UPPER,
+ /* 58 */ HW_CAT_LEN_DYN1,
+ /* 59 */ HW_CAT_LEN_DYN2,
+ /* 60 */ HW_CAT_LEN_INV,
+ /* 61 */ HW_CAT_CFN_ERR_TNL_L3_CS,
+ /* 62 */ HW_CAT_CFN_ERR_TNL_L4_CS,
+ /* 63 */ HW_CAT_CFN_ERR_TTL_EXP,
+ /* 64 */ HW_CAT_CFN_ERR_TNL_TTL_EXP,
+
+ /* 65 */ HW_CAT_CCE_IMM,
+ /* 66 */ HW_CAT_CCE_IND,
+ /* 67 */ HW_CAT_CCS_COR_EN,
+ /* 68 */ HW_CAT_CCS_COR,
+ /* 69 */ HW_CAT_CCS_HSH_EN,
+ /* 70 */ HW_CAT_CCS_HSH,
+ /* 71 */ HW_CAT_CCS_QSL_EN,
+ /* 72 */ HW_CAT_CCS_QSL,
+ /* 73 */ HW_CAT_CCS_IPF_EN,
+ /* 74 */ HW_CAT_CCS_IPF,
+ /* 75 */ HW_CAT_CCS_SLC_EN,
+ /* 76 */ HW_CAT_CCS_SLC,
+ /* 77 */ HW_CAT_CCS_PDB_EN,
+ /* 78 */ HW_CAT_CCS_PDB,
+ /* 79 */ HW_CAT_CCS_MSK_EN,
+ /* 80 */ HW_CAT_CCS_MSK,
+ /* 81 */ HW_CAT_CCS_HST_EN,
+ /* 82 */ HW_CAT_CCS_HST,
+ /* 83 */ HW_CAT_CCS_EPP_EN,
+ /* 84 */ HW_CAT_CCS_EPP,
+ /* 85 */ HW_CAT_CCS_TPE_EN,
+ /* 86 */ HW_CAT_CCS_TPE,
+ /* 87 */ HW_CAT_CCS_RRB_EN,
+ /* 88 */ HW_CAT_CCS_RRB,
+ /* 89 */ HW_CAT_CCS_SB0_TYPE,
+ /* 90 */ HW_CAT_CCS_SB0_DATA,
+ /* 91 */ HW_CAT_CCS_SB1_TYPE,
+ /* 92 */ HW_CAT_CCS_SB1_DATA,
+ /* 93 */ HW_CAT_CCS_SB2_TYPE,
+ /* 94 */ HW_CAT_CCS_SB2_DATA,
+
+};
+
+bool hw_mod_cat_present(struct flow_api_backend_s *be);
+int hw_mod_cat_alloc(struct flow_api_backend_s *be);
+void hw_mod_cat_free(struct flow_api_backend_s *be);
+int hw_mod_cat_reset(struct flow_api_backend_s *be);
+int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value);
+int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value);
+/* KCE/KCS/FTE KM */
+int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+/* KCE/KCS/FTE FLM */
+int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+
+int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value);
+int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value);
+
+int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+/* added in v22 */
+int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+
+struct km_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_categories;
+ uint32_t nb_cam_banks;
+ uint32_t nb_cam_record_words;
+ uint32_t nb_cam_records;
+ uint32_t nb_tcam_banks;
+ uint32_t nb_tcam_bank_width;
+ /* not read from backend, but rather set using version */
+ uint32_t nb_km_rcp_mask_a_word_size;
+ uint32_t nb_km_rcp_mask_b_word_size;
+ union {
+ struct hw_mod_km_v7_s v7;
+ };
+};
+
+enum hw_km_e {
+ /* functions */
+ HW_KM_RCP_PRESET_ALL = 0,
+ HW_KM_CAM_PRESET_ALL,
+ /* to sync and reset hw with cache - force write all entries in a bank */
+ HW_KM_TCAM_BANK_RESET,
+ /* fields */
+ HW_KM_RCP_QW0_DYN = FIELD_START_INDEX,
+ HW_KM_RCP_QW0_OFS,
+ HW_KM_RCP_QW0_SEL_A,
+ HW_KM_RCP_QW0_SEL_B,
+ HW_KM_RCP_QW4_DYN,
+ HW_KM_RCP_QW4_OFS,
+ HW_KM_RCP_QW4_SEL_A,
+ HW_KM_RCP_QW4_SEL_B,
+ HW_KM_RCP_DW8_DYN,
+ HW_KM_RCP_DW8_OFS,
+ HW_KM_RCP_DW8_SEL_A,
+ HW_KM_RCP_DW8_SEL_B,
+ HW_KM_RCP_DW10_DYN,
+ HW_KM_RCP_DW10_OFS,
+ HW_KM_RCP_DW10_SEL_A,
+ HW_KM_RCP_DW10_SEL_B,
+ HW_KM_RCP_SWX_CCH,
+ HW_KM_RCP_SWX_SEL_A,
+ HW_KM_RCP_SWX_SEL_B,
+ HW_KM_RCP_MASK_A,
+ HW_KM_RCP_MASK_B,
+ HW_KM_RCP_DUAL,
+ HW_KM_RCP_PAIRED,
+ HW_KM_RCP_EL_A,
+ HW_KM_RCP_EL_B,
+ HW_KM_RCP_INFO_A,
+ HW_KM_RCP_INFO_B,
+ HW_KM_RCP_FTM_A,
+ HW_KM_RCP_FTM_B,
+ HW_KM_RCP_BANK_A,
+ HW_KM_RCP_BANK_B,
+ HW_KM_RCP_KL_A,
+ HW_KM_RCP_KL_B,
+ HW_KM_RCP_KEYWAY_A,
+ HW_KM_RCP_KEYWAY_B,
+ HW_KM_RCP_SYNERGY_MODE,
+ HW_KM_RCP_DW0_B_DYN,
+ HW_KM_RCP_DW0_B_OFS,
+ HW_KM_RCP_DW2_B_DYN,
+ HW_KM_RCP_DW2_B_OFS,
+ HW_KM_RCP_SW4_B_DYN,
+ HW_KM_RCP_SW4_B_OFS,
+ HW_KM_RCP_SW5_B_DYN,
+ HW_KM_RCP_SW5_B_OFS,
+ HW_KM_CAM_W0,
+ HW_KM_CAM_W1,
+ HW_KM_CAM_W2,
+ HW_KM_CAM_W3,
+ HW_KM_CAM_W4,
+ HW_KM_CAM_W5,
+ HW_KM_CAM_FT0,
+ HW_KM_CAM_FT1,
+ HW_KM_CAM_FT2,
+ HW_KM_CAM_FT3,
+ HW_KM_CAM_FT4,
+ HW_KM_CAM_FT5,
+ HW_KM_TCAM_T,
+ HW_KM_TCI_COLOR,
+ HW_KM_TCI_FT,
+ HW_KM_TCQ_BANK_MASK,
+ HW_KM_TCQ_QUAL
+};
+
+bool hw_mod_km_present(struct flow_api_backend_s *be);
+int hw_mod_km_alloc(struct flow_api_backend_s *be);
+void hw_mod_km_free(struct flow_api_backend_s *be);
+int hw_mod_km_reset(struct flow_api_backend_s *be);
+int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t value);
+int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t *value);
+int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count);
+int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value);
+int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank,
+ int count);
+int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set);
+int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set);
+int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count);
+int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value);
+int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count);
+int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+
+struct hst_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_hst_rcp_categories;
+ union {
+ struct hw_mod_hst_v2_s v2;
+ };
+};
+
+enum hw_hst_e {
+ /* functions */
+ HW_HST_RCP_PRESET_ALL = 0,
+ HW_HST_RCP_FIND,
+ HW_HST_RCP_COMPARE,
+ /* Control fields */
+ HW_HST_RCP_STRIP_MODE = FIELD_START_INDEX,
+ HW_HST_RCP_START_DYN,
+ HW_HST_RCP_START_OFS,
+ HW_HST_RCP_END_DYN,
+ HW_HST_RCP_END_OFS,
+ HW_HST_RCP_MODIF0_CMD,
+ HW_HST_RCP_MODIF0_DYN,
+ HW_HST_RCP_MODIF0_OFS,
+ HW_HST_RCP_MODIF0_VALUE,
+ HW_HST_RCP_MODIF1_CMD,
+ HW_HST_RCP_MODIF1_DYN,
+ HW_HST_RCP_MODIF1_OFS,
+ HW_HST_RCP_MODIF1_VALUE,
+ HW_HST_RCP_MODIF2_CMD,
+ HW_HST_RCP_MODIF2_DYN,
+ HW_HST_RCP_MODIF2_OFS,
+ HW_HST_RCP_MODIF2_VALUE,
+
+};
+
+bool hw_mod_hst_present(struct flow_api_backend_s *be);
+int hw_mod_hst_alloc(struct flow_api_backend_s *be);
+void hw_mod_hst_free(struct flow_api_backend_s *be);
+int hw_mod_hst_reset(struct flow_api_backend_s *be);
+
+int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t value);
+int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t *value);
+
+struct flm_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_categories;
+ uint32_t nb_size_mb;
+ uint32_t nb_entry_size;
+ uint32_t nb_variant;
+ uint32_t nb_prios;
+ uint32_t nb_pst_profiles;
+ union {
+ struct hw_mod_flm_v17_s v17;
+ struct hw_mod_flm_v20_s v20;
+ };
+};
+
+enum hw_flm_e {
+ /* functions */
+ HW_FLM_CONTROL_PRESET_ALL = 0,
+ HW_FLM_RCP_PRESET_ALL,
+ HW_FLM_FLOW_LRN_DATA_V17,
+ HW_FLM_FLOW_INF_DATA_V17,
+ HW_FLM_FLOW_STA_DATA_V17,
+ /* Control fields */
+ HW_FLM_CONTROL_ENABLE = FIELD_START_INDEX,
+ HW_FLM_CONTROL_INIT,
+ HW_FLM_CONTROL_LDS,
+ HW_FLM_CONTROL_LFS,
+ HW_FLM_CONTROL_LIS,
+ HW_FLM_CONTROL_UDS,
+ HW_FLM_CONTROL_UIS,
+ HW_FLM_CONTROL_RDS,
+ HW_FLM_CONTROL_RIS,
+ HW_FLM_CONTROL_PDS,
+ HW_FLM_CONTROL_PIS,
+ HW_FLM_CONTROL_CRCWR,
+ HW_FLM_CONTROL_CRCRD,
+ HW_FLM_CONTROL_RBL,
+ HW_FLM_CONTROL_EAB,
+ HW_FLM_CONTROL_SPLIT_SDRAM_USAGE,
+ HW_FLM_STATUS_CALIBDONE,
+ HW_FLM_STATUS_INITDONE,
+ HW_FLM_STATUS_IDLE,
+ HW_FLM_STATUS_CRITICAL,
+ HW_FLM_STATUS_PANIC,
+ HW_FLM_STATUS_CRCERR,
+ HW_FLM_STATUS_EFT_BP,
+ HW_FLM_TIMEOUT_T,
+ HW_FLM_SCRUB_I,
+ HW_FLM_LOAD_BIN,
+ HW_FLM_LOAD_PPS,
+ HW_FLM_LOAD_LPS,
+ HW_FLM_LOAD_APS,
+ HW_FLM_PRIO_LIMIT0,
+ HW_FLM_PRIO_FT0,
+ HW_FLM_PRIO_LIMIT1,
+ HW_FLM_PRIO_FT1,
+ HW_FLM_PRIO_LIMIT2,
+ HW_FLM_PRIO_FT2,
+ HW_FLM_PRIO_LIMIT3,
+ HW_FLM_PRIO_FT3,
+ HW_FLM_PST_PRESET_ALL,
+ HW_FLM_PST_BP,
+ HW_FLM_PST_PP,
+ HW_FLM_PST_TP,
+ HW_FLM_RCP_LOOKUP,
+ HW_FLM_RCP_QW0_DYN,
+ HW_FLM_RCP_QW0_OFS,
+ HW_FLM_RCP_QW0_SEL,
+ HW_FLM_RCP_QW4_DYN,
+ HW_FLM_RCP_QW4_OFS,
+ HW_FLM_RCP_SW8_DYN,
+ HW_FLM_RCP_SW8_OFS,
+ HW_FLM_RCP_SW8_SEL,
+ HW_FLM_RCP_SW9_DYN,
+ HW_FLM_RCP_SW9_OFS,
+ HW_FLM_RCP_MASK,
+ HW_FLM_RCP_KID,
+ HW_FLM_RCP_OPN,
+ HW_FLM_RCP_IPN,
+ HW_FLM_RCP_BYT_DYN,
+ HW_FLM_RCP_BYT_OFS,
+ HW_FLM_RCP_TXPLM,
+ HW_FLM_RCP_AUTO_IPV4_MASK,
+ HW_FLM_BUF_CTRL_LRN_FREE,
+ HW_FLM_BUF_CTRL_INF_AVAIL,
+ HW_FLM_BUF_CTRL_STA_AVAIL,
+ HW_FLM_STAT_LRN_DONE,
+ HW_FLM_STAT_LRN_IGNORE,
+ HW_FLM_STAT_LRN_FAIL,
+ HW_FLM_STAT_UNL_DONE,
+ HW_FLM_STAT_UNL_IGNORE,
+ HW_FLM_STAT_REL_DONE,
+ HW_FLM_STAT_REL_IGNORE,
+ HW_FLM_STAT_PRB_DONE,
+ HW_FLM_STAT_PRB_IGNORE,
+ HW_FLM_STAT_AUL_DONE,
+ HW_FLM_STAT_AUL_IGNORE,
+ HW_FLM_STAT_AUL_FAIL,
+ HW_FLM_STAT_TUL_DONE,
+ HW_FLM_STAT_FLOWS,
+ HW_FLM_STAT_STA_DONE, /* module ver 0.20 */
+ HW_FLM_STAT_INF_DONE, /* module ver 0.20 */
+ HW_FLM_STAT_INF_SKIP, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_HIT, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_MISS, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_UNH, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_DIS, /* module ver 0.20 */
+ HW_FLM_STAT_CSH_HIT, /* module ver 0.20 */
+ HW_FLM_STAT_CSH_MISS, /* module ver 0.20 */
+ HW_FLM_STAT_CSH_UNH, /* module ver 0.20 */
+ HW_FLM_STAT_CUC_START, /* module ver 0.20 */
+ HW_FLM_STAT_CUC_MOVE, /* module ver 0.20 */
+};
+
+bool hw_mod_flm_present(struct flow_api_backend_s *be);
+int hw_mod_flm_alloc(struct flow_api_backend_s *be);
+void hw_mod_flm_free(struct flow_api_backend_s *be);
+int hw_mod_flm_reset(struct flow_api_backend_s *be);
+
+int hw_mod_flm_control_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_status_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_status_update(struct flow_api_backend_s *be);
+int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_prio_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value);
+int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value);
+
+int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value);
+int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value);
+int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value);
+
+int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be);
+int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_stat_update(struct flow_api_backend_s *be);
+int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be,
+ enum hw_flm_e field, const uint32_t *value);
+int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ uint32_t word_cnt);
+int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value);
+
+struct hsh_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp;
+ union {
+ struct hw_mod_hsh_v5_s v5;
+ };
+};
+
+enum hw_hsh_e {
+ /* functions */
+ HW_HSH_RCP_PRESET_ALL = 0,
+ HW_HSH_RCP_COMPARE,
+ HW_HSH_RCP_FIND,
+ /* fields */
+ HW_HSH_RCP_LOAD_DIST_TYPE = FIELD_START_INDEX,
+ HW_HSH_RCP_MAC_PORT_MASK,
+ HW_HSH_RCP_SORT,
+ HW_HSH_RCP_QW0_PE,
+ HW_HSH_RCP_QW0_OFS,
+ HW_HSH_RCP_QW4_PE,
+ HW_HSH_RCP_QW4_OFS,
+ HW_HSH_RCP_W8_PE,
+ HW_HSH_RCP_W8_OFS,
+ HW_HSH_RCP_W8_SORT,
+ HW_HSH_RCP_W9_PE,
+ HW_HSH_RCP_W9_OFS,
+ HW_HSH_RCP_W9_SORT,
+ HW_HSH_RCP_W9_P,
+ HW_HSH_RCP_P_MASK,
+ HW_HSH_RCP_WORD_MASK,
+ HW_HSH_RCP_SEED,
+ HW_HSH_RCP_TNL_P,
+ HW_HSH_RCP_HSH_VALID,
+ HW_HSH_RCP_HSH_TYPE,
+ HW_HSH_RCP_AUTO_IPV4_MASK
+
+};
+
+bool hw_mod_hsh_present(struct flow_api_backend_s *be);
+int hw_mod_hsh_alloc(struct flow_api_backend_s *be);
+void hw_mod_hsh_free(struct flow_api_backend_s *be);
+int hw_mod_hsh_reset(struct flow_api_backend_s *be);
+int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t value);
+int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value);
+
+struct qsl_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp_categories;
+ uint32_t nb_qst_entries;
+ union {
+ struct hw_mod_qsl_v7_s v7;
+ };
+};
+
+enum hw_qsl_e {
+ /* functions */
+ HW_QSL_RCP_PRESET_ALL = 0,
+ HW_QSL_RCP_COMPARE,
+ HW_QSL_RCP_FIND,
+ HW_QSL_QST_PRESET_ALL,
+ /* fields */
+ HW_QSL_RCP_DISCARD = FIELD_START_INDEX,
+ HW_QSL_RCP_DROP,
+ HW_QSL_RCP_TBL_LO,
+ HW_QSL_RCP_TBL_HI,
+ HW_QSL_RCP_TBL_IDX,
+ HW_QSL_RCP_TBL_MSK,
+ HW_QSL_RCP_LR,
+ HW_QSL_RCP_TSA,
+ HW_QSL_RCP_VLI,
+ HW_QSL_QST_QUEUE,
+ HW_QSL_QST_EN, /* Alias: HW_QSL_QST_QEN */
+ HW_QSL_QST_TX_PORT,
+ HW_QSL_QST_LRE,
+ HW_QSL_QST_TCI,
+ HW_QSL_QST_VEN,
+ HW_QSL_QEN_EN,
+ HW_QSL_UNMQ_DEST_QUEUE,
+ HW_QSL_UNMQ_EN,
+
+};
+
+bool hw_mod_qsl_present(struct flow_api_backend_s *be);
+int hw_mod_qsl_alloc(struct flow_api_backend_s *be);
+void hw_mod_qsl_free(struct flow_api_backend_s *be);
+int hw_mod_qsl_reset(struct flow_api_backend_s *be);
+int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+
+struct slc_func_s {
+ COMMON_FUNC_INFO_S;
+ union {
+ struct hw_mod_slc_v1_s v1;
+ };
+};
+
+enum hw_slc_e {
+ /* functions */
+ HW_SLC_RCP_PRESET_ALL = 0,
+ HW_SLC_RCP_COMPARE,
+ HW_SLC_RCP_FIND,
+ /* fields */
+ HW_SLC_RCP_SLC_EN = FIELD_START_INDEX,
+ HW_SLC_RCP_DYN,
+ HW_SLC_RCP_OFS,
+ HW_SLC_RCP_PCAP
+};
+
+bool hw_mod_slc_present(struct flow_api_backend_s *be);
+int hw_mod_slc_alloc(struct flow_api_backend_s *be);
+void hw_mod_slc_free(struct flow_api_backend_s *be);
+int hw_mod_slc_reset(struct flow_api_backend_s *be);
+int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t *value);
+
+struct slc_lr_func_s {
+ COMMON_FUNC_INFO_S;
+ union {
+ struct hw_mod_slc_lr_v2_s v2;
+ };
+};
+
+enum hw_slc_lr_e {
+ /* functions */
+ HW_SLC_LR_RCP_PRESET_ALL = 0,
+ HW_SLC_LR_RCP_COMPARE,
+ HW_SLC_LR_RCP_FIND,
+ /* fields */
+ HW_SLC_LR_RCP_SLC_EN = FIELD_START_INDEX,
+ HW_SLC_LR_RCP_DYN,
+ HW_SLC_LR_RCP_OFS,
+ HW_SLC_LR_RCP_PCAP
+};
+
+bool hw_mod_slc_lr_present(struct flow_api_backend_s *be);
+int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be);
+void hw_mod_slc_lr_free(struct flow_api_backend_s *be);
+int hw_mod_slc_lr_reset(struct flow_api_backend_s *be);
+int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t *value);
+
+struct pdb_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_pdb_rcp_categories;
+
+ union {
+ struct hw_mod_pdb_v9_s v9;
+ };
+};
+
+enum hw_pdb_e {
+ /* functions */
+ HW_PDB_RCP_PRESET_ALL = 0,
+ HW_PDB_RCP_COMPARE,
+ HW_PDB_RCP_FIND,
+ /* fields */
+ HW_PDB_RCP_DESCRIPTOR = FIELD_START_INDEX,
+ HW_PDB_RCP_DESC_LEN,
+ HW_PDB_RCP_TX_PORT,
+ HW_PDB_RCP_TX_IGNORE,
+ HW_PDB_RCP_TX_NOW,
+ HW_PDB_RCP_CRC_OVERWRITE,
+ HW_PDB_RCP_ALIGN,
+ HW_PDB_RCP_OFS0_DYN,
+ HW_PDB_RCP_OFS0_REL,
+ HW_PDB_RCP_OFS1_DYN,
+ HW_PDB_RCP_OFS1_REL,
+ HW_PDB_RCP_OFS2_DYN,
+ HW_PDB_RCP_OFS2_REL,
+ HW_PDB_RCP_IP_PROT_TNL,
+ HW_PDB_RCP_PPC_HSH,
+ HW_PDB_RCP_DUPLICATE_EN,
+ HW_PDB_RCP_DUPLICATE_BIT,
+ HW_PDB_RCP_PCAP_KEEP_FCS,
+ HW_PDB_CONFIG_TS_FORMAT,
+ HW_PDB_CONFIG_PORT_OFS,
+};
+
+bool hw_mod_pdb_present(struct flow_api_backend_s *be);
+int hw_mod_pdb_alloc(struct flow_api_backend_s *be);
+void hw_mod_pdb_free(struct flow_api_backend_s *be);
+int hw_mod_pdb_reset(struct flow_api_backend_s *be);
+int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_pdb_config_flush(struct flow_api_backend_s *be);
+int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t value);
+
+struct ioa_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp_categories;
+ uint32_t nb_roa_epp_entries;
+ union {
+ struct hw_mod_ioa_v4_s v4;
+ };
+};
+
+enum hw_ioa_e {
+ /* functions */
+ HW_IOA_RCP_PRESET_ALL = 0,
+ HW_IOA_RCP_COMPARE,
+ HW_IOA_RCP_FIND,
+ HW_IOA_ROA_EPP_PRESET_ALL,
+ HW_IOA_ROA_EPP_COMPARE,
+ HW_IOA_ROA_EPP_FIND,
+ /* fields */
+ HW_IOA_RCP_TUNNEL_POP = FIELD_START_INDEX,
+ HW_IOA_RCP_VLAN_POP,
+ HW_IOA_RCP_VLAN_PUSH,
+ HW_IOA_RCP_VLAN_VID,
+ HW_IOA_RCP_VLAN_DEI,
+ HW_IOA_RCP_VLAN_PCP,
+ HW_IOA_RCP_VLAN_TPID_SEL,
+ HW_IOA_RCP_QUEUE_OVERRIDE_EN,
+ HW_IOA_RCP_QUEUE_ID,
+ HW_IOA_CONFIG_CUST_TPID_0,
+ HW_IOA_CONFIG_CUST_TPID_1,
+ HW_IOA_ROA_EPP_PUSH_TUNNEL,
+ HW_IOA_ROA_EPP_TX_PORT,
+};
+
+bool hw_mod_ioa_present(struct flow_api_backend_s *be);
+int hw_mod_ioa_alloc(struct flow_api_backend_s *be);
+void hw_mod_ioa_free(struct flow_api_backend_s *be);
+int hw_mod_ioa_reset(struct flow_api_backend_s *be);
+int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_ioa_config_flush(struct flow_api_backend_s *be);
+int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t value);
+
+int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+
+struct roa_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_tun_categories;
+ uint32_t nb_lag_entries;
+ union {
+ struct hw_mod_roa_v6_s v6;
+ };
+};
+
+enum hw_roa_e {
+ /* functions */
+ HW_ROA_TUNHDR_COMPARE = 0,
+ HW_ROA_TUNCFG_PRESET_ALL,
+ HW_ROA_TUNCFG_COMPARE,
+ HW_ROA_TUNCFG_FIND,
+ /* fields */
+ HW_ROA_TUNHDR = FIELD_START_INDEX,
+ HW_ROA_TUNCFG_TUN_LEN,
+ HW_ROA_TUNCFG_TUN_TYPE,
+ HW_ROA_TUNCFG_TUN_VLAN,
+ HW_ROA_TUNCFG_IP_TYPE,
+ HW_ROA_TUNCFG_IPCS_UPD,
+ HW_ROA_TUNCFG_IPCS_PRECALC,
+ HW_ROA_TUNCFG_IPTL_UPD,
+ HW_ROA_TUNCFG_IPTL_PRECALC,
+ HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD,
+ HW_ROA_TUNCFG_TX_LAG_IX,
+ HW_ROA_TUNCFG_RECIRCULATE,
+ HW_ROA_TUNCFG_PUSH_TUNNEL,
+ HW_ROA_TUNCFG_RECIRC_PORT,
+ HW_ROA_TUNCFG_RECIRC_BYPASS,
+ HW_ROA_CONFIG_FWD_RECIRCULATE,
+ HW_ROA_CONFIG_FWD_NORMAL_PCKS,
+ HW_ROA_CONFIG_FWD_TXPORT0,
+ HW_ROA_CONFIG_FWD_TXPORT1,
+ HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS,
+ HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS,
+ HW_ROA_LAGCFG_TXPHY_PORT,
+ HW_ROA_IGS_PKT_DROP,
+ HW_ROA_IGS_BYTE_DROP,
+ HW_ROA_RCC_PKT_DROP,
+ HW_ROA_RCC_BYTE_DROP,
+};
+
+bool hw_mod_roa_present(struct flow_api_backend_s *be);
+int hw_mod_roa_alloc(struct flow_api_backend_s *be);
+void hw_mod_roa_free(struct flow_api_backend_s *be);
+int hw_mod_roa_reset(struct flow_api_backend_s *be);
+int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t value);
+int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value);
+int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_roa_config_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_roa_igs_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_igs_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_igs_pkt_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_igs_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_igs_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_igs_byte_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_rcc_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_rcc_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_rcc_pkt_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_rcc_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_rcc_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_rcc_byte_flush(struct flow_api_backend_s *be);
+
+struct rmc_func_s {
+ COMMON_FUNC_INFO_S;
+ union {
+ struct hw_mod_rmc_v1_3_s v1_3;
+ };
+};
+
+enum hw_rmc_e {
+ HW_RMC_BLOCK_STATT = FIELD_START_INDEX,
+ HW_RMC_BLOCK_KEEPA,
+ HW_RMC_BLOCK_RPP_SLICE,
+ HW_RMC_BLOCK_MAC_PORT,
+ HW_RMC_LAG_PHY_ODD_EVEN,
+};
+
+bool hw_mod_rmc_present(struct flow_api_backend_s *be);
+int hw_mod_rmc_alloc(struct flow_api_backend_s *be);
+void hw_mod_rmc_free(struct flow_api_backend_s *be);
+int hw_mod_rmc_reset(struct flow_api_backend_s *be);
+int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t value);
+int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t *value);
+int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be);
+
+struct tpe_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp_categories;
+ uint32_t nb_ifr_categories;
+ uint32_t nb_cpy_writers;
+ uint32_t nb_rpl_depth;
+ uint32_t nb_rpl_ext_categories;
+ union {
+ struct hw_mod_tpe_v1_s v1;
+ struct hw_mod_tpe_v2_s v2;
+ };
+};
+
+enum hw_tpe_e {
+ /* functions */
+ HW_TPE_PRESET_ALL = 0,
+ HW_TPE_FIND,
+ HW_TPE_COMPARE,
+ /* Control fields */
+ HW_TPE_RPP_RCP_EXP = FIELD_START_INDEX,
+ HW_TPE_IFR_RCP_EN,
+ HW_TPE_IFR_RCP_MTU,
+ HW_TPE_INS_RCP_DYN,
+ HW_TPE_INS_RCP_OFS,
+ HW_TPE_INS_RCP_LEN,
+ HW_TPE_RPL_RCP_DYN,
+ HW_TPE_RPL_RCP_OFS,
+ HW_TPE_RPL_RCP_LEN,
+ HW_TPE_RPL_RCP_RPL_PTR,
+ HW_TPE_RPL_RCP_EXT_PRIO,
+ HW_TPE_RPL_EXT_RPL_PTR,
+ HW_TPE_RPL_EXT_META_RPL_LEN, /* SW only */
+ HW_TPE_RPL_RPL_VALUE,
+ HW_TPE_CPY_RCP_READER_SELECT,
+ HW_TPE_CPY_RCP_DYN,
+ HW_TPE_CPY_RCP_OFS,
+ HW_TPE_CPY_RCP_LEN,
+ HW_TPE_HFU_RCP_LEN_A_WR,
+ HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN,
+ HW_TPE_HFU_RCP_LEN_A_POS_DYN,
+ HW_TPE_HFU_RCP_LEN_A_POS_OFS,
+ HW_TPE_HFU_RCP_LEN_A_ADD_DYN,
+ HW_TPE_HFU_RCP_LEN_A_ADD_OFS,
+ HW_TPE_HFU_RCP_LEN_A_SUB_DYN,
+ HW_TPE_HFU_RCP_LEN_B_WR,
+ HW_TPE_HFU_RCP_LEN_B_POS_DYN,
+ HW_TPE_HFU_RCP_LEN_B_POS_OFS,
+ HW_TPE_HFU_RCP_LEN_B_ADD_DYN,
+ HW_TPE_HFU_RCP_LEN_B_ADD_OFS,
+ HW_TPE_HFU_RCP_LEN_B_SUB_DYN,
+ HW_TPE_HFU_RCP_LEN_C_WR,
+ HW_TPE_HFU_RCP_LEN_C_POS_DYN,
+ HW_TPE_HFU_RCP_LEN_C_POS_OFS,
+ HW_TPE_HFU_RCP_LEN_C_ADD_DYN,
+ HW_TPE_HFU_RCP_LEN_C_ADD_OFS,
+ HW_TPE_HFU_RCP_LEN_C_SUB_DYN,
+ HW_TPE_HFU_RCP_TTL_WR,
+ HW_TPE_HFU_RCP_TTL_POS_DYN,
+ HW_TPE_HFU_RCP_TTL_POS_OFS,
+ HW_TPE_HFU_RCP_CS_INF,
+ HW_TPE_HFU_RCP_L3_PRT,
+ HW_TPE_HFU_RCP_L3_FRAG,
+ HW_TPE_HFU_RCP_TUNNEL,
+ HW_TPE_HFU_RCP_L4_PRT,
+ HW_TPE_HFU_RCP_OUTER_L3_OFS,
+ HW_TPE_HFU_RCP_OUTER_L4_OFS,
+ HW_TPE_HFU_RCP_INNER_L3_OFS,
+ HW_TPE_HFU_RCP_INNER_L4_OFS,
+ HW_TPE_CSU_RCP_OUTER_L3_CMD,
+ HW_TPE_CSU_RCP_OUTER_L4_CMD,
+ HW_TPE_CSU_RCP_INNER_L3_CMD,
+ HW_TPE_CSU_RCP_INNER_L4_CMD,
+};
+
+bool hw_mod_tpe_present(struct flow_api_backend_s *be);
+int hw_mod_tpe_alloc(struct flow_api_backend_s *be);
+void hw_mod_tpe_free(struct flow_api_backend_s *be);
+int hw_mod_tpe_reset(struct flow_api_backend_s *be);
+
+int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t value);
+int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t *value);
+
+int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+enum debug_mode_e {
+ FLOW_BACKEND_DEBUG_MODE_NONE = 0x0000,
+ FLOW_BACKEND_DEBUG_MODE_WRITE = 0x0001
+};
+
+struct flow_api_backend_ops {
+ int version;
+ int (*set_debug_mode)(void *dev, enum debug_mode_e mode);
+ int (*get_nb_phy_port)(void *dev);
+ int (*get_nb_rx_port)(void *dev);
+ int (*get_ltx_avail)(void *dev);
+ int (*get_nb_cat_funcs)(void *dev);
+ int (*get_nb_categories)(void *dev);
+ int (*get_nb_cat_km_if_cnt)(void *dev);
+ int (*get_nb_cat_km_if_m0)(void *dev);
+ int (*get_nb_cat_km_if_m1)(void *dev);
+
+ int (*get_nb_queues)(void *dev);
+ int (*get_nb_km_flow_types)(void *dev);
+ int (*get_nb_pm_ext)(void *dev);
+ int (*get_nb_len)(void *dev);
+ int (*get_kcc_size)(void *dev);
+ int (*get_kcc_banks)(void *dev);
+ int (*get_nb_km_categories)(void *dev);
+ int (*get_nb_km_cam_banks)(void *dev);
+ int (*get_nb_km_cam_record_words)(void *dev);
+ int (*get_nb_km_cam_records)(void *dev);
+ int (*get_nb_km_tcam_banks)(void *dev);
+ int (*get_nb_km_tcam_bank_width)(void *dev);
+ int (*get_nb_flm_categories)(void *dev);
+ int (*get_nb_flm_size_mb)(void *dev);
+ int (*get_nb_flm_entry_size)(void *dev);
+ int (*get_nb_flm_variant)(void *dev);
+ int (*get_nb_flm_prios)(void *dev);
+ int (*get_nb_flm_pst_profiles)(void *dev);
+ int (*get_nb_hst_categories)(void *dev);
+ int (*get_nb_qsl_categories)(void *dev);
+ int (*get_nb_qsl_qst_entries)(void *dev);
+ int (*get_nb_pdb_categories)(void *dev);
+ int (*get_nb_ioa_categories)(void *dev);
+ int (*get_nb_roa_categories)(void *dev);
+ int (*get_nb_tpe_categories)(void *dev);
+ int (*get_nb_tx_cpy_writers)(void *dev);
+ int (*get_nb_tx_cpy_mask_mem)(void *dev);
+ int (*get_nb_tx_rpl_depth)(void *dev);
+ int (*get_nb_tx_rpl_ext_categories)(void *dev);
+ int (*get_nb_tpe_ifr_categories)(void *dev);
+
+ int (*alloc_rx_queue)(void *dev, int queue_id);
+ int (*free_rx_queue)(void *dev, int hw_queue);
+
+ /* CAT */
+ bool (*get_cat_present)(void *dev);
+ uint32_t (*get_cat_version)(void *dev);
+ int (*cat_cfn_flush)(void *dev, const struct cat_func_s *cat,
+ int cat_func, int cnt);
+ int (*cat_kce_flush)(void *dev, const struct cat_func_s *cat,
+ int km_if_idx, int index, int cnt);
+ int (*cat_kcs_flush)(void *dev, const struct cat_func_s *cat,
+ int km_if_idx, int cat_func, int cnt);
+ int (*cat_fte_flush)(void *dev, const struct cat_func_s *cat,
+ int km_if_idx, int index, int cnt);
+ int (*cat_cte_flush)(void *dev, const struct cat_func_s *cat,
+ int cat_func, int cnt);
+ int (*cat_cts_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_cot_flush)(void *dev, const struct cat_func_s *cat,
+ int cat_func, int cnt);
+ int (*cat_cct_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_exo_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_rck_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_len_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_kcc_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_cce_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_ccs_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+
+ /* KM */
+ bool (*get_km_present)(void *dev);
+ uint32_t (*get_km_version)(void *dev);
+ int (*km_rcp_flush)(void *dev, const struct km_func_s *km, int category,
+ int cnt);
+ int (*km_cam_flush)(void *dev, const struct km_func_s *km, int bank,
+ int record, int cnt);
+ int (*km_tcam_flush)(void *dev, const struct km_func_s *km, int bank,
+ int byte, int value, int cnt);
+ int (*km_tci_flush)(void *dev, const struct km_func_s *km, int bank,
+ int record, int cnt);
+ int (*km_tcq_flush)(void *dev, const struct km_func_s *km, int bank,
+ int record, int cnt);
+
+ /* FLM */
+ bool (*get_flm_present)(void *dev);
+ uint32_t (*get_flm_version)(void *dev);
+ int (*flm_control_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_status_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_status_update)(void *dev, const struct flm_func_s *flm);
+ int (*flm_timeout_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_scrub_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_bin_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_pps_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_lps_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_aps_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_prio_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_pst_flush)(void *dev, const struct flm_func_s *flm, int index,
+ int cnt);
+ int (*flm_rcp_flush)(void *dev, const struct flm_func_s *flm, int index,
+ int cnt);
+ int (*flm_buf_ctrl_update)(void *dev, const struct flm_func_s *flm);
+ int (*flm_stat_update)(void *dev, const struct flm_func_s *flm);
+ int (*flm_lrn_data_flush)(void *be_dev, const struct flm_func_s *flm,
+ const uint32_t *lrn_data, uint32_t size);
+ int (*flm_inf_data_update)(void *be_dev, const struct flm_func_s *flm,
+ uint32_t *lrn_data, uint32_t size);
+ int (*flm_sta_data_update)(void *be_dev, const struct flm_func_s *flm,
+ uint32_t *lrn_data, uint32_t size);
+
+ /* HSH */
+ bool (*get_hsh_present)(void *dev);
+ uint32_t (*get_hsh_version)(void *dev);
+ int (*hsh_rcp_flush)(void *dev, const struct hsh_func_s *hsh,
+ int category, int cnt);
+
+ /* HST */
+ bool (*get_hst_present)(void *dev);
+ uint32_t (*get_hst_version)(void *dev);
+ int (*hst_rcp_flush)(void *dev, const struct hst_func_s *hst,
+ int category, int cnt);
+
+ /* QSL */
+ bool (*get_qsl_present)(void *dev);
+ uint32_t (*get_qsl_version)(void *dev);
+ int (*qsl_rcp_flush)(void *dev, const struct qsl_func_s *qsl,
+ int category, int cnt);
+ int (*qsl_qst_flush)(void *dev, const struct qsl_func_s *qsl, int entry,
+ int cnt);
+ int (*qsl_qen_flush)(void *dev, const struct qsl_func_s *qsl, int entry,
+ int cnt);
+ int (*qsl_unmq_flush)(void *dev, const struct qsl_func_s *qsl,
+ int entry, int cnt);
+
+ /* SLC */
+ bool (*get_slc_present)(void *dev);
+ uint32_t (*get_slc_version)(void *dev);
+ int (*slc_rcp_flush)(void *dev, const struct slc_func_s *slc,
+ int category, int cnt);
+
+ /* SLC LR */
+ bool (*get_slc_lr_present)(void *dev);
+ uint32_t (*get_slc_lr_version)(void *dev);
+ int (*slc_lr_rcp_flush)(void *dev, const struct slc_lr_func_s *slc_lr,
+ int category, int cnt);
+
+ /* PDB */
+ bool (*get_pdb_present)(void *dev);
+ uint32_t (*get_pdb_version)(void *dev);
+ int (*pdb_rcp_flush)(void *dev, const struct pdb_func_s *pdb,
+ int category, int cnt);
+ int (*pdb_config_flush)(void *dev, const struct pdb_func_s *pdb);
+
+ /* IOA */
+ bool (*get_ioa_present)(void *dev);
+ uint32_t (*get_ioa_version)(void *dev);
+ int (*ioa_rcp_flush)(void *dev, const struct ioa_func_s *ioa, int index,
+ int cnt);
+ int (*ioa_special_tpid_flush)(void *dev, const struct ioa_func_s *ioa);
+ int (*ioa_roa_epp_flush)(void *dev, const struct ioa_func_s *ioa,
+ int index, int cnt);
+
+ /* ROA */
+ bool (*get_roa_present)(void *dev);
+ uint32_t (*get_roa_version)(void *dev);
+ int (*roa_tunhdr_flush)(void *dev, const struct roa_func_s *roa,
+ int index, int cnt);
+ int (*roa_tuncfg_flush)(void *dev, const struct roa_func_s *roa,
+ int index, int cnt);
+ int (*roa_config_flush)(void *dev, const struct roa_func_s *roa);
+ int (*roa_lagcfg_flush)(void *dev, const struct roa_func_s *roa,
+ int index, int cnt);
+
+ /* RMC */
+ bool (*get_rmc_present)(void *dev);
+ uint32_t (*get_rmc_version)(void *dev);
+ int (*rmc_ctrl_flush)(void *dev, const struct rmc_func_s *rmc);
+
+ /* TPE */
+ bool (*get_tpe_present)(void *dev);
+ uint32_t (*get_tpe_version)(void *dev);
+ int (*tpe_rpp_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpp_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_ins_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpl_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpl_ext_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpl_rpl_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_cpy_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_hfu_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_csu_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+};
+
+struct flow_api_backend_s {
+ void *be_dev;
+ const struct flow_api_backend_ops *iface;
+
+ /* flow filter FPGA modules */
+ struct cat_func_s cat;
+ struct km_func_s km;
+ struct flm_func_s flm;
+ struct hsh_func_s hsh;
+ struct hst_func_s hst;
+ struct qsl_func_s qsl;
+ struct slc_func_s slc;
+ struct slc_lr_func_s slc_lr;
+ struct pdb_func_s pdb;
+ struct ioa_func_s ioa;
+ struct roa_func_s roa;
+ struct rmc_func_s rmc;
+ struct tpe_func_s tpe;
+
+ /* NIC attributes */
+ unsigned int num_phy_ports;
+ unsigned int num_rx_ports;
+
+ /* flow filter resource capacities */
+ unsigned int max_categories;
+ unsigned int max_queues;
+};
+
+int flow_api_backend_init(struct flow_api_backend_s *dev,
+ const struct flow_api_backend_ops *iface,
+ void *be_dev);
+int flow_api_backend_reset(struct flow_api_backend_s *dev);
+int flow_api_backend_done(struct flow_api_backend_s *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FLOW_API_BACKEND_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h
new file mode 100644
index 0000000000..bee12b71f7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h
@@ -0,0 +1,475 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_API_ENGINE_H_
+#define _FLOW_API_ENGINE_H_
+
+#include <stdint.h>
+#include "stream_binary_flow_api.h"
+
+struct flow_elem;
+/*
+ * ****************************************************
+ * Resource management
+ * ****************************************************
+ */
+#define BIT_CONTAINER_8_ALIGN(x) (((x) + 7) / 8)
+
+/*
+ * Resource management
+ * These are free resources in FPGA
+ * Other FPGA memory lists are linked to one of these
+ * and will implicitly follow them
+ */
+enum res_type_e {
+ RES_QUEUE,
+ RES_CAT_CFN,
+ RES_CAT_COT,
+ RES_CAT_EXO,
+ RES_CAT_LEN,
+ RES_KM_FLOW_TYPE,
+ RES_KM_CATEGORY,
+ RES_HSH_RCP,
+ RES_PDB_RCP,
+ RES_QSL_RCP,
+ RES_QSL_QST,
+ RES_SLC_RCP,
+ RES_IOA_RCP,
+ RES_ROA_RCP,
+ RES_FLM_FLOW_TYPE,
+ RES_FLM_RCP,
+ RES_HST_RCP,
+ RES_TPE_RCP,
+ RES_TPE_EXT,
+ RES_TPE_RPL,
+ RES_COUNT,
+ RES_INVALID
+};
+
+/*
+ * ****************************************************
+ * Flow NIC offload management
+ * ****************************************************
+ */
+#define MAX_OUTPUT_DEST (128)
+#define NB_QSL_QEN_ADDR 32
+
+#define INVALID_FLOW_STAT_ID 0xffffffff
+
+#define MAX_WORD_NUM 24
+#define MAX_BANKS 6
+
+#define MAX_TCAM_START_OFFSETS 4
+
+#define MAX_TAG_INDEX 8
+
+#define MAX_FLM_MTRS_SUPPORTED 4
+#define MAX_CPY_WRITERS_SUPPORTED 8
+
+/*
+ * 128 128 32 32 32
+ * Have | QW0 || QW4 || SW8 || SW9 | SWX in FPGA
+ *
+ * Each word may start at any offset, though
+ * they are combined in chronological order, with all enabled to
+ * build the extracted match data, thus that is how the match key
+ * must be build
+ *
+ */
+enum extractor_e {
+ KM_USE_EXTRACTOR_UNDEF,
+ KM_USE_EXTRACTOR_QWORD,
+ KM_USE_EXTRACTOR_SWORD,
+};
+
+struct match_elem_s {
+ enum extractor_e extr;
+ int masked_for_tcam; /* if potentially selected for TCAM */
+ uint32_t e_word[4];
+ uint32_t e_mask[4];
+
+ int extr_start_offs_id;
+ int8_t rel_offs;
+ uint32_t word_len;
+};
+
+enum cam_tech_use_e { KM_CAM, KM_TCAM, KM_SYNERGY };
+
+#define MAX_MATCH_FIELDS 16
+
+struct km_flow_def_s {
+ struct flow_api_backend_s *be;
+
+ /* For keeping track of identical entries */
+ struct km_flow_def_s *reference;
+ struct km_flow_def_s *root;
+
+ /* For collect flow elements and sorting */
+ struct match_elem_s match[MAX_MATCH_FIELDS];
+ struct match_elem_s *match_map[MAX_MATCH_FIELDS];
+ int num_ftype_elem;
+
+ /* Finally formatted CAM/TCAM entry */
+ enum cam_tech_use_e target;
+ uint32_t entry_word[MAX_WORD_NUM];
+ uint32_t entry_mask[MAX_WORD_NUM];
+ int key_word_size;
+
+ /* TCAM calculated possible bank start offsets */
+ int start_offsets[MAX_TCAM_START_OFFSETS];
+ int num_start_offsets;
+
+ /* Flow information */
+
+ /*
+ * HW input port ID needed for compare. In port must be identical on flow
+ * types
+ */
+ uint32_t port_id;
+ uint32_t info; /* used for color (actions) */
+ int info_set;
+ int flow_type; /* 0 is illegal and used as unset */
+ int flushed_to_target; /* if this km entry has been finally programmed into NIC hw */
+
+ /* CAM specific bank management */
+ int cam_paired;
+ int record_indexes[MAX_BANKS];
+ int bank_used;
+ uint32_t *cuckoo_moves; /* for CAM statistics only */
+ struct cam_distrib_s *cam_dist;
+ struct hasher_s *hsh;
+
+ /* TCAM specific bank management */
+ struct tcam_distrib_s *tcam_dist;
+ int tcam_start_bank;
+ int tcam_record;
+};
+
+/*
+ * KCC-CAM
+ */
+struct kcc_key_s {
+ uint64_t sb_data : 32;
+ uint64_t sb_type : 8;
+ uint64_t cat_cfn : 8;
+ uint64_t port : 16;
+};
+
+#define KCC_ID_INVALID 0xffffffff
+
+struct kcc_flow_def_s {
+ struct flow_api_backend_s *be;
+ union {
+ uint64_t key64;
+ uint32_t key32[2];
+ struct kcc_key_s key;
+ };
+ uint32_t km_category;
+ uint32_t id;
+
+ uint8_t *kcc_unique_ids;
+
+ int flushed_to_target;
+ int record_indexes[MAX_BANKS];
+ int bank_used;
+ uint32_t *cuckoo_moves; /* for CAM statistics only */
+ struct kcc_cam_distrib_s *cam_dist;
+ struct hasher_s *hsh;
+};
+
+/*
+ * Tunnel encapsulation header definition
+ */
+enum { TUN_TYPE_VXLAN = 0, TUN_TYPE_NVGRE = 1 };
+
+#define MAX_TUN_HDR_SIZE 128
+
+struct tunnel_header_s {
+ union {
+ uint8_t hdr8[MAX_TUN_HDR_SIZE];
+ uint32_t hdr32[(MAX_TUN_HDR_SIZE + 3) / 4];
+ } d;
+ uint32_t user_port_id;
+ uint8_t len;
+
+ uint8_t nb_vlans;
+
+ uint8_t ip_version; /* 4: v4, 6: v6 */
+ uint16_t ip_csum_precalc;
+
+ uint8_t new_outer;
+ uint8_t l2_len;
+ uint8_t l3_len;
+ uint8_t l4_len;
+};
+
+enum port_type_e {
+ PORT_NONE, /* not defined or drop */
+ PORT_INTERNAL, /* no queues attached */
+ PORT_PHY, /* MAC phy output queue */
+ PORT_VIRT, /* Memory queues to Host */
+};
+
+enum special_partial_match_e {
+ SPCIAL_MATCH_NONE,
+ SPECIAL_MATCH_LACP,
+};
+
+#define PORT_ID_NONE 0xffffffff
+
+struct output_s {
+ uint32_t owning_port_id; /* the port who owns this output destination */
+ enum port_type_e type;
+ int id; /* depending on port type: queue ID or physical port id or not used */
+ int active; /* activated */
+};
+
+struct nic_flow_def {
+ /*
+ * Frame Decoder match info collected
+ */
+ int l2_prot;
+ int l3_prot;
+ int l4_prot;
+ int tunnel_prot;
+ int tunnel_l3_prot;
+ int tunnel_l4_prot;
+ int vlans;
+ int fragmentation;
+ /*
+ * Additional meta data for various functions
+ */
+ int in_port_override;
+ int l4_dst_port;
+ /*
+ * Output destination info collection
+ */
+ struct output_s dst_id[MAX_OUTPUT_DEST]; /* define the output to use */
+ /* total number of available queues defined for all outputs - i.e. number of dst_id's */
+ int dst_num_avail;
+
+ /*
+ * To identify high priority match with mark for special SW processing (non-OVS)
+ */
+ enum special_partial_match_e special_match;
+
+ /*
+ * Mark or Action info collection
+ */
+ uint32_t mark;
+ uint64_t roa_actions;
+ uint64_t ioa_actions;
+
+ uint32_t jump_to_group;
+
+ uint32_t mtr_ids[MAX_FLM_MTRS_SUPPORTED];
+
+ int full_offload;
+ /*
+ * Action push tunnel
+ */
+ struct tunnel_header_s tun_hdr;
+
+ /*
+ * If DPDK RTE tunnel helper API used
+ * this holds the tunnel if used in flow
+ */
+ struct tunnel_s *tnl;
+
+ /*
+ * Header Stripper
+ */
+ int header_strip_start_dyn;
+ int header_strip_start_ofs;
+ int header_strip_end_dyn;
+ int header_strip_end_ofs;
+ int header_strip_removed_outer_ip;
+
+ /*
+ * Modify field
+ */
+ struct {
+ uint32_t select;
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+ uint32_t level;
+ union {
+ uint8_t value8[16];
+ uint16_t value16[8];
+ uint32_t value32[4];
+ };
+ } modify_field[MAX_CPY_WRITERS_SUPPORTED];
+
+ uint32_t modify_field_count;
+ uint8_t ttl_sub_enable;
+ uint8_t ttl_sub_ipv4;
+ uint8_t ttl_sub_outer;
+
+ /*
+ * Key Matcher flow definitions
+ */
+ struct km_flow_def_s km;
+
+ /*
+ * Key Matcher Category CAM
+ */
+ struct kcc_flow_def_s *kcc;
+ int kcc_referenced;
+
+ /*
+ * TX fragmentation IFR/RPP_LR MTU recipe
+ */
+ uint8_t flm_mtu_fragmentation_recipe;
+};
+
+enum flow_handle_type {
+ FLOW_HANDLE_TYPE_FLOW,
+ FLOW_HANDLE_TYPE_FLM,
+};
+
+struct flow_handle {
+ enum flow_handle_type type;
+
+ struct flow_eth_dev *dev;
+ struct flow_handle *next;
+ struct flow_handle *prev;
+
+ union {
+ struct {
+ /*
+ * 1st step conversion and validation of flow
+ * verified and converted flow match + actions structure
+ */
+ struct nic_flow_def *fd;
+ /*
+ * 2nd step NIC HW resource allocation and configuration
+ * NIC resource management structures
+ */
+ struct {
+ int index; /* allocation index into NIC raw resource table */
+ /* number of contiguous allocations needed for this resource */
+ int count;
+ /*
+ * This resource if not initially created by this flow, but reused
+ * by it
+ */
+ int referenced;
+ } resource[RES_COUNT];
+ int flushed;
+
+ uint32_t flow_stat_id;
+ uint32_t color;
+ int cao_enabled;
+ uint32_t cte;
+
+ uint32_t port_id; /* MAC port ID or override of virtual in_port */
+ uint32_t flm_ref_count;
+ uint8_t flm_group_index;
+ uint8_t flm_ft_index;
+ };
+
+ struct {
+ uint32_t flm_data[10];
+ uint8_t flm_prot;
+ uint8_t flm_kid;
+ uint8_t flm_prio;
+
+ uint16_t flm_rpl_ext_ptr;
+ uint32_t flm_nat_ipv4;
+ uint16_t flm_nat_port;
+ uint8_t flm_dscp;
+ uint32_t flm_teid;
+ uint8_t flm_rqi;
+ uint8_t flm_qfi;
+
+ uint8_t flm_mtu_fragmentation_recipe;
+
+ struct flow_handle *flm_owner;
+ };
+ };
+};
+
+void km_attach_ndev_resource_management(struct km_flow_def_s *km,
+ void **handle);
+void km_free_ndev_resource_management(void **handle);
+
+int km_get_cam_population_level(void *cam_dist, uint32_t *cam_elem,
+ uint32_t *cuckoo_moves);
+
+int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4],
+ uint32_t e_mask[4], uint32_t word_len,
+ enum frame_offs_e start, int8_t offset);
+
+int km_key_create(struct km_flow_def_s *km, uint32_t port_id);
+/*
+ * Compares 2 KM key definitions after first collect validate and optimization.
+ * km is compared against an existing km1.
+ * if identical, km1 flow_type is returned
+ */
+int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1);
+
+void km_set_info(struct km_flow_def_s *km, int on);
+int km_rcp_set(struct km_flow_def_s *km, int index);
+
+int km_refer_data_match_entry(struct km_flow_def_s *km,
+ struct km_flow_def_s *km1);
+int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color);
+int km_clear_data_match_entry(struct km_flow_def_s *km);
+
+void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc,
+ void **handle);
+void kcc_free_ndev_resource_management(void **handle);
+int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc);
+void kcc_free_unique_id(struct kcc_flow_def_s *kcc);
+int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1);
+int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category);
+
+int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc);
+int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid);
+int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni);
+int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port);
+int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn);
+uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc);
+
+int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc);
+int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc);
+int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc);
+
+/*
+ * Group management
+ */
+int flow_group_handle_create(void **handle, uint32_t group_count);
+int flow_group_handle_destroy(void **handle);
+
+int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in,
+ uint32_t *group_out);
+int flow_group_translate_release(void *handle, uint32_t translated_group);
+
+/*
+ * Actions management
+ */
+uint8_t flow_tunnel_alloc_virt_port(void);
+uint8_t flow_tunnel_free_virt_port(uint8_t virt_port);
+struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx,
+ uint32_t *vni);
+int tunnel_release(struct tunnel_s *tnl);
+uint8_t get_tunnel_vport(struct tunnel_s *rtnl);
+void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id);
+int tunnel_get_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,
+ uint8_t vport);
+
+int is_virtual_port(uint8_t virt_port);
+int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be,
+ struct nic_flow_def *fd,
+ const struct flow_elem *elem);
+
+/*
+ * statistics
+ */
+uint32_t flow_actions_create_flow_stat_id(uint32_t *stat_map, uint32_t mark);
+void flow_actions_delete_flow_stat_id(uint32_t *stat_map,
+ uint32_t flow_stat_id);
+
+#endif /* _FLOW_API_ENGINE_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h
new file mode 100644
index 0000000000..c4db0f4c5c
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_API_NIC_SETUP_H__
+#define __FLOW_API_NIC_SETUP_H__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct flow_api_backend_ops; /* Operation list for common FPGA module API for backend */
+struct flow_nic_dev; /* adapter device */
+
+/*
+ * Flow capable NIC backend - creating flow api instance for adapter nr (backend)
+ */
+struct flow_nic_dev *flow_api_create(uint8_t adapter_no,
+ const struct flow_api_backend_ops *be_if,
+ void *be_dev);
+int flow_api_done(struct flow_nic_dev *dev);
+void *flow_api_get_be_dev(struct flow_nic_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FLOW_API_NIC_SETUP_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c
new file mode 100644
index 0000000000..9b6e5484a0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define OWNER_ID_COUNT 256
+
+struct group_lookup_entry_s {
+ uint64_t ref_counter;
+ uint32_t *reverse_lookup;
+};
+
+struct group_handle_s {
+ uint32_t group_count;
+
+ uint32_t *translation_table;
+
+ struct group_lookup_entry_s *lookup_entries;
+};
+
+int flow_group_handle_create(void **handle, uint32_t group_count)
+{
+ struct group_handle_s *group_handle;
+
+ *handle = calloc(1, sizeof(struct group_handle_s));
+ group_handle = *handle;
+
+ group_handle->group_count = group_count;
+ group_handle->translation_table = calloc((uint32_t)(group_count * OWNER_ID_COUNT),
+ sizeof(uint32_t));
+ group_handle->lookup_entries =
+ calloc(group_count, sizeof(struct group_lookup_entry_s));
+
+ return *handle != NULL ? 0 : -1;
+}
+
+int flow_group_handle_destroy(void **handle)
+{
+ if (*handle) {
+ struct group_handle_s *group_handle =
+ (struct group_handle_s *)*handle;
+
+ free(group_handle->translation_table);
+ free(group_handle->lookup_entries);
+
+ free(*handle);
+ *handle = NULL;
+ }
+
+ return 0;
+}
+
+int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in,
+ uint32_t *group_out)
+{
+ struct group_handle_s *group_handle = (struct group_handle_s *)handle;
+ uint32_t *table_ptr;
+ uint32_t lookup;
+
+ if (group_handle == NULL || group_in >= group_handle->group_count)
+ return -1;
+
+ /* Don't translate group 0 */
+ if (group_in == 0) {
+ *group_out = 0;
+ return 0;
+ }
+
+ table_ptr = &group_handle->translation_table[owner_id * OWNER_ID_COUNT +
+ group_in];
+ lookup = *table_ptr;
+
+ if (lookup == 0) {
+ for (lookup = 1;
+ lookup < group_handle->group_count &&
+ group_handle->lookup_entries[lookup].ref_counter > 0;
+ ++lookup)
+ ;
+
+ if (lookup < group_handle->group_count) {
+ group_handle->lookup_entries[lookup].reverse_lookup =
+ table_ptr;
+ group_handle->lookup_entries[lookup].ref_counter += 1;
+
+ *table_ptr = lookup;
+ } else {
+ return -1;
+ }
+ } else {
+ group_handle->lookup_entries[lookup].ref_counter += 1;
+ }
+ *group_out = lookup;
+ return 0;
+}
+
+int flow_group_translate_release(void *handle, uint32_t translated_group)
+{
+ struct group_handle_s *group_handle = (struct group_handle_s *)handle;
+ struct group_lookup_entry_s *lookup;
+
+ if (group_handle == NULL ||
+ translated_group >= group_handle->group_count)
+ return -1;
+
+ /* Don't translate group 0 */
+ if (translated_group == 0)
+ return 0;
+
+ lookup = &group_handle->lookup_entries[translated_group];
+
+ if (lookup->reverse_lookup && lookup->ref_counter > 0) {
+ lookup->ref_counter -= 1;
+ if (lookup->ref_counter == 0) {
+ *lookup->reverse_lookup = 0;
+ lookup->reverse_lookup = NULL;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c
new file mode 100644
index 0000000000..6982129e17
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "flow_hasher.h"
+
+#include <math.h>
+
+/* #define TESTING */
+
+#ifdef TESTING
+#include <stdio.h>
+int hash_test(struct hasher_s *hsh, int banks, int record_bw);
+#endif
+
+static uint32_t shuffle(uint32_t x)
+{
+ return (((x & 0x00000002) << 29) | ((x & 0xAAAAAAA8) >> 3) |
+ ((x & 0x15555555) << 3) | ((x & 0x40000000) >> 29));
+}
+
+static uint32_t ror_inv(uint32_t x, const int s)
+{
+ return ((x >> s) | ((~x) << (32 - s)));
+}
+
+static uint32_t combine(uint32_t x, uint32_t y)
+{
+ uint32_t x1 = ror_inv(x, 15);
+ uint32_t x2 = ror_inv(x, 13);
+ uint32_t y1 = ror_inv(y, 3);
+ uint32_t y2 = ror_inv(y, 27);
+
+ return (x ^ y ^
+ ((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) |
+ (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) |
+ (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2)));
+}
+
+static uint32_t mix(uint32_t x, uint32_t y)
+{
+ return shuffle(combine(x, y));
+}
+
+static uint64_t ror_inv3(uint64_t x)
+{
+ const uint64_t m = 0xE0000000E0000000ULL;
+
+ return (((x >> 3) | m) ^ ((x << 29) & m));
+}
+
+static uint64_t ror_inv13(uint64_t x)
+{
+ const uint64_t m = 0xFFF80000FFF80000ULL;
+
+ return (((x >> 13) | m) ^ ((x << 19) & m));
+}
+
+static uint64_t ror_inv15(uint64_t x)
+{
+ const uint64_t m = 0xFFFE0000FFFE0000ULL;
+
+ return (((x >> 15) | m) ^ ((x << 17) & m));
+}
+
+static uint64_t ror_inv27(uint64_t x)
+{
+ const uint64_t m = 0xFFFFFFE0FFFFFFE0ULL;
+
+ return (((x >> 27) | m) ^ ((x << 5) & m));
+}
+
+static uint64_t shuffle64(uint64_t x)
+{
+ return (((x & 0x0000000200000002) << 29) |
+ ((x & 0xAAAAAAA8AAAAAAA8) >> 3) |
+ ((x & 0x1555555515555555) << 3) |
+ ((x & 0x4000000040000000) >> 29));
+}
+
+static uint64_t pair(uint32_t x, uint32_t y)
+{
+ return (((uint64_t)x << 32) | y);
+}
+
+static uint64_t combine64(uint64_t x, uint64_t y)
+{
+ uint64_t x1 = ror_inv15(x);
+ uint64_t x2 = ror_inv13(x);
+ uint64_t y1 = ror_inv3(y);
+ uint64_t y2 = ror_inv27(y);
+
+ return (x ^ y ^
+ ((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) |
+ (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) |
+ (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2)));
+}
+
+static uint64_t mix64(uint64_t x, uint64_t y)
+{
+ return shuffle64(combine64(x, y));
+}
+
+static uint32_t calc16(const uint32_t key[16])
+{
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Layer 0 */
+ /* \./ \./ \./ \./ \./ \./ \./ \./ */
+ /* 0 1 2 3 4 5 6 7 Layer 1 */
+ /* \__.__/ \__.__/ \__.__/ \__.__/ */
+ /* 0 1 2 3 Layer 2 */
+ /* \______.______/ \______.______/ */
+ /* 0 1 Layer 3 */
+ /* \______________.______________/ */
+ /* 0 Layer 4 */
+ /* / \ */
+ /* \./ */
+ /* 0 Layer 5 */
+ /* / \ */
+ /* \./ Layer 6 */
+ /* value */
+
+ uint64_t z;
+ uint32_t x;
+
+ z = mix64(mix64(mix64(pair(key[0], key[8]), pair(key[1], key[9])),
+ mix64(pair(key[2], key[10]), pair(key[3], key[11]))),
+ mix64(mix64(pair(key[4], key[12]), pair(key[5], key[13])),
+ mix64(pair(key[6], key[14]), pair(key[7], key[15]))));
+
+ x = mix((uint32_t)(z >> 32), (uint32_t)z);
+ x = mix(x, ror_inv(x, 17));
+ x = combine(x, ror_inv(x, 17));
+
+ return x;
+}
+
+uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result)
+{
+ uint64_t val;
+ uint32_t res;
+
+ val = calc16(key);
+ res = (uint32_t)val;
+
+ if (hsh->cam_bw > 32)
+ val = (val << (hsh->cam_bw - 32)) ^ val;
+
+ for (int i = 0; i < hsh->banks; i++) {
+ result[i] = (unsigned int)(val & hsh->cam_records_bw_mask);
+ val = val >> hsh->cam_records_bw;
+ }
+ return res;
+}
+
+int init_hasher(struct hasher_s *hsh, int banks, int nb_records)
+{
+ hsh->banks = banks;
+ hsh->cam_records_bw = (int)(log2(nb_records - 1) + 1);
+ hsh->cam_records_bw_mask = (1U << hsh->cam_records_bw) - 1;
+ hsh->cam_bw = hsh->banks * hsh->cam_records_bw;
+
+#ifdef TESTING
+ int res = hash_test(hsh, _banks, (int)log2(nb_records - 1) + 1);
+
+ if (res)
+ printf("ERROR: testing hasher\n");
+#endif
+
+ return 0;
+}
+
+#ifdef TESTING
+int hash_test(struct hasher_s *hsh, int banks, int record_bw)
+{
+ int res = 0;
+ int val[10], resval[10];
+ uint32_t bits = 0;
+
+ uint32_t inval[16] = { 0xaaaabbbb, 0xccccdddd, 0xeeeeffff, 0x88881111 };
+ const uint32_t result = 0xACECAE65;
+
+ for (int i = 0; i < 16; i++)
+ printf("%08x,", inval[i]);
+ printf("\nbanks %i, records bit width: %i\n", banks, record_bw);
+
+ uint32_t ret = gethash(hsh, inval, val);
+
+ printf("Return VAL = %08X == %08X\n", ret, result);
+ res += (ret != result) ? 1 : 0;
+
+ int shft = (banks * record_bw) - 32;
+ int mask = (1 << record_bw) - 1;
+
+ if (shft > 0) {
+ bits = (ret >> (32 - shft));
+ ret ^= ret << shft;
+ }
+
+ resval[0] = ret & mask;
+ ret >>= record_bw;
+ resval[1] = ret & mask;
+ ret >>= record_bw;
+ resval[2] = ret & mask;
+ resval[2] |= (bits << (record_bw - shft));
+
+ for (int i = 0; i < 3; i++) {
+ printf("HASH %i: %i == %i\n", i, val[i], resval[i]);
+ res += (val[i] != resval[i]) ? 1 : 0;
+ }
+
+ return res;
+}
+#endif
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h
new file mode 100644
index 0000000000..6365a396d2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_HASHER_H_
+#define _FLOW_HASHER_H_
+
+#include <stdint.h>
+
+struct hasher_s {
+ int banks;
+ int cam_records_bw;
+ uint32_t cam_records_bw_mask;
+ int cam_bw;
+};
+
+int init_hasher(struct hasher_s *hsh, int banks, int nb_records);
+uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result);
+
+#endif /* _FLOW_HASHER_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c
new file mode 100644
index 0000000000..ddf1742588
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+#include "flow_hasher.h"
+
+/*
+ * KCC-CAM structures and defines
+ */
+struct kcc_cam_distrib_s {
+ struct kcc_flow_def_s *kcc_owner;
+ int ref_cnt;
+};
+
+#define BE_CAM_KCC_DIST_IDX(bnk) \
+ ({ \
+ int _temp_bnk = (bnk); \
+ (_temp_bnk * kcc->be->cat.kcc_records + kcc->record_indexes[_temp_bnk]); \
+ })
+
+
+#define BE_CAM_ENTRIES \
+ (kcc->be->cat.kcc_size * sizeof(struct kcc_cam_distrib_s))
+#define BE_UNIQUE_IDS_SIZE ((1U << kcc->be->cat.kcc_id_bit_size) / 8)
+
+#define KCC_CUCKOO_MOVE_MAX_DEPTH 8
+static int kcc_cam_addr_reserved_stack[KCC_CUCKOO_MOVE_MAX_DEPTH];
+
+void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc,
+ void **handle)
+{
+ /*
+ * KCC entries occupied in CAM - to manage the cuckoo shuffling
+ * and manage CAM population and usage
+ */
+ if (!*handle) {
+ *handle = calloc(1, BE_CAM_ENTRIES + sizeof(uint32_t) +
+ BE_UNIQUE_IDS_SIZE +
+ sizeof(struct hasher_s));
+ NT_LOG(DBG, FILTER,
+ "Allocate NIC DEV KCC-CAM record manager\n");
+ }
+ kcc->cam_dist = (struct kcc_cam_distrib_s *)*handle;
+ kcc->cuckoo_moves =
+ (uint32_t *)((char *)kcc->cam_dist + BE_CAM_ENTRIES);
+ kcc->kcc_unique_ids = (uint8_t *)((char *)kcc->cam_dist +
+ BE_CAM_ENTRIES + sizeof(uint32_t));
+
+ kcc->hsh = (struct hasher_s *)((char *)kcc->kcc_unique_ids +
+ BE_UNIQUE_IDS_SIZE);
+ init_hasher(kcc->hsh, kcc->be->cat.kcc_banks, kcc->be->cat.kcc_records);
+}
+
+void kcc_free_ndev_resource_management(void **handle)
+{
+ if (*handle) {
+ free(*handle);
+ NT_LOG(DBG, FILTER, "Free NIC DEV KCC-CAM record manager\n");
+ }
+ *handle = NULL;
+}
+
+/*
+ * Key for KCC CAM
+ */
+int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc)
+{
+ kcc->key.sb_data = 0xffffffff;
+ kcc->key.sb_type = 0;
+ return 0;
+}
+
+int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid)
+{
+ kcc->key.sb_data = ((uint32_t)tpid << 16) | (vid & 0x0fff);
+ kcc->key.sb_type = 1;
+ return 0;
+}
+
+int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni)
+{
+ kcc->key.sb_data = (vni & 0x00ffffff) | 0x02000000;
+ kcc->key.sb_type = 2;
+ return 0;
+}
+
+int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port)
+{
+ kcc->key.port = port;
+ return 0;
+}
+
+int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn)
+{
+ kcc->key.cat_cfn = cat_cfn;
+ return 0;
+}
+
+uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc)
+{
+ return kcc->key.cat_cfn;
+}
+
+/*
+ * other settings for KCC CAM
+ */
+int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category)
+{
+ kcc->km_category = category;
+ return 0;
+}
+
+int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc)
+{
+ uint32_t i, ii;
+ /* search a free unique ID in allocation bitmap */
+ for (i = 0; i < BE_UNIQUE_IDS_SIZE; i++)
+ if (kcc->kcc_unique_ids[i] != 0xff)
+ break;
+
+ if (i == BE_UNIQUE_IDS_SIZE)
+ return -1;
+
+ for (ii = 0; ii < 8; ii++) {
+ if ((kcc->kcc_unique_ids[i] & (uint8_t)(1U << ii)) == 0) {
+ kcc->kcc_unique_ids[i] =
+ (uint8_t)(kcc->kcc_unique_ids[i] |
+ (uint8_t)(1U << ii));
+ kcc->id = (uint16_t)(i * 8 + ii);
+ NT_LOG(DBG, FILTER, "Allocate new KCC ID : %i\n",
+ kcc->id);
+ return (int)kcc->id;
+ }
+ }
+ return -1;
+}
+
+void kcc_free_unique_id(struct kcc_flow_def_s *kcc)
+{
+ if (kcc->id == KCC_ID_INVALID)
+ return;
+
+ uint32_t idx = kcc->id >> 3;
+ uint8_t shft = (uint8_t)(kcc->id & 7);
+
+ assert(idx < BE_UNIQUE_IDS_SIZE);
+ if (idx < BE_UNIQUE_IDS_SIZE) {
+ assert(kcc->kcc_unique_ids[idx] & (uint8_t)(1 << shft));
+ kcc->kcc_unique_ids[idx] &= (uint8_t)~(1 << shft);
+ NT_LOG(DBG, FILTER, "Free KCC ID : %i\n", kcc->id);
+ kcc->id = KCC_ID_INVALID;
+ }
+}
+
+int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1)
+{
+ if (kcc->key64 == kcc1->key64)
+ return 1;
+ return 0;
+}
+
+static int kcc_cam_populate(struct kcc_flow_def_s *kcc, int bank)
+{
+ int res;
+ int idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank];
+
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0,
+ kcc->key32[0]);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1,
+ kcc->key32[1]);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0,
+ kcc->km_category);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, kcc->id);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_flush(kcc->be, idx, 1);
+
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = kcc;
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 1;
+ return res;
+}
+
+static int kcc_cam_reset_entry(struct kcc_flow_def_s *kcc, int bank)
+{
+ int res = 0;
+ int idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank];
+
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_flush(kcc->be, idx, 1);
+
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = NULL;
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 0;
+
+ kcc->key64 = 0UL;
+ kcc->km_category = 0;
+ /* "kcc->id" holds an allocated unique id, so cleared/freed later */
+ return res;
+}
+
+static int kcc_move_cuckoo_index(struct kcc_flow_def_s *kcc)
+{
+ assert(kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)].kcc_owner);
+
+ for (uint32_t bank = 0; bank < kcc->be->cat.kcc_banks; bank++) {
+ /* It will not select itself */
+ if (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner ==
+ NULL) {
+ /*
+ * Populate in new position
+ */
+ int res = kcc_cam_populate(kcc, bank);
+
+ if (res) {
+ NT_LOG(DBG, FILTER,
+ "Error: failed to write to KM CAM in cuckoo move\n");
+ return 0;
+ }
+
+ /*
+ * Reset/free entry in old bank
+ * HW flushes are really not needed, the old addresses are always taken over
+ * by the caller If you change this code in future updates, this may no
+ * longer be true then!
+ */
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)]
+ .kcc_owner = NULL;
+ NT_LOG(DBG, FILTER,
+ "KCC Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\n",
+ kcc->bank_used, bank,
+ BE_CAM_KCC_DIST_IDX(kcc->bank_used),
+ BE_CAM_KCC_DIST_IDX(bank));
+
+ kcc->bank_used = bank;
+ (*kcc->cuckoo_moves)++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int kcc_move_cuckoo_index_level(struct kcc_flow_def_s *kcc_parent,
+ int bank_idx, int levels,
+ int cam_adr_list_len)
+{
+ struct kcc_flow_def_s *kcc = kcc_parent->cam_dist[bank_idx].kcc_owner;
+
+ assert(levels <= KCC_CUCKOO_MOVE_MAX_DEPTH);
+
+ if (kcc_move_cuckoo_index(kcc))
+ return 1;
+ if (levels <= 1)
+ return 0;
+
+ assert(cam_adr_list_len < KCC_CUCKOO_MOVE_MAX_DEPTH);
+
+ kcc_cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx;
+
+ for (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++) {
+ int reserved = 0;
+ int new_idx = BE_CAM_KCC_DIST_IDX(i);
+
+ for (int i_reserved = 0; i_reserved < cam_adr_list_len;
+ i_reserved++) {
+ if (kcc_cam_addr_reserved_stack[i_reserved] ==
+ new_idx) {
+ reserved = 1;
+ break;
+ }
+ }
+ if (reserved)
+ continue;
+
+ int res = kcc_move_cuckoo_index_level(kcc, new_idx, levels - 1,
+ cam_adr_list_len);
+ if (res) {
+ if (kcc_move_cuckoo_index(kcc))
+ return 1;
+
+ else
+ assert(0);
+ }
+ }
+
+ return 0;
+}
+
+static uint32_t kcc_hsh_key[16];
+
+static int kcc_write_data_to_cam(struct kcc_flow_def_s *kcc)
+{
+ int res = 0;
+ int val[MAX_BANKS];
+
+ kcc_hsh_key[0] = kcc->key32[1];
+ kcc_hsh_key[1] = kcc->key32[0];
+ NT_LOG(DBG, FILTER, "TEMP TEMP TEMP");
+ NT_LOG(DBG, FILTER, "Hash key[0] %08x", kcc_hsh_key[0]);
+ NT_LOG(DBG, FILTER, "Hash key[1] %08x", kcc_hsh_key[1]);
+ NT_LOG(DBG, FILTER, "TEMP TEMP TEMP - swapped");
+
+ /* 2-15 never changed - remains zero */
+
+ gethash(kcc->hsh, kcc_hsh_key, val);
+
+ for (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++)
+ kcc->record_indexes[i] = val[i];
+ NT_LOG(DBG, FILTER, "KCC HASH [%03X, %03X, %03X]\n",
+ kcc->record_indexes[0], kcc->record_indexes[1],
+ kcc->record_indexes[2]);
+
+ int bank = -1;
+ /*
+ * first step, see if any of the banks are free
+ */
+ for (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks; i_bank++) {
+ if (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(i_bank)].kcc_owner ==
+ NULL) {
+ bank = i_bank;
+ break;
+ }
+ }
+
+ if (bank < 0) {
+ /*
+ * Second step - cuckoo move existing flows if possible
+ */
+ for (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks;
+ i_bank++) {
+ if (kcc_move_cuckoo_index_level(kcc,
+ BE_CAM_KCC_DIST_IDX(i_bank),
+ 4, 0)) {
+ bank = i_bank;
+ break;
+ }
+ }
+
+ if (bank < 0)
+ return -1;
+ }
+
+ /* populate CAM */
+ NT_LOG(DBG, FILTER, "KCC Bank = %i (addr %04X)\n", bank,
+ BE_CAM_KCC_DIST_IDX(bank));
+ res = kcc_cam_populate(kcc, bank);
+ if (res == 0) {
+ kcc->flushed_to_target = 1;
+ kcc->bank_used = bank;
+ } else {
+ NT_LOG(DBG, FILTER, "KCC CAM populate failed\n");
+ }
+ return res;
+}
+
+int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc)
+{
+ int res = -1;
+
+ NT_LOG(DBG, FILTER,
+ "KCC Write Data entry. Create New Key: %016lx, KM category %i, id %i\n",
+ kcc->key64, kcc->km_category, kcc->id);
+ res = kcc_write_data_to_cam(kcc);
+ return res;
+}
+
+static int kcc_clear_data_match_entry(struct kcc_flow_def_s *kcc)
+{
+ int res = 0;
+
+ if (kcc->flushed_to_target) {
+ res = kcc_cam_reset_entry(kcc, kcc->bank_used);
+ kcc->flushed_to_target = 0;
+ kcc->bank_used = 0;
+ }
+ return res;
+}
+
+int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc)
+{
+ assert(kcc->bank_used >= 0 &&
+ kcc->bank_used < (int)kcc->be->cat.kcc_banks);
+
+ struct kcc_cam_distrib_s *cam_entry =
+ &kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)];
+
+ NT_LOG(DBG, FILTER,
+ "KCC ADD Ref existing Key: %016lx, KM category %i, id %i (new ref count %i)\n",
+ kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt + 1);
+ return ++cam_entry->ref_cnt;
+}
+
+int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc)
+{
+ if (kcc->bank_used < 0 || kcc->bank_used >= (int)kcc->be->cat.kcc_banks)
+ return -1;
+
+ struct kcc_cam_distrib_s *cam_entry =
+ &kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)];
+
+ if (cam_entry->ref_cnt) {
+ if (--cam_entry->ref_cnt == 0) {
+ kcc_clear_data_match_entry(kcc);
+ NT_LOG(DBG, FILTER,
+ "KCC DEC Ref on Key became zero - Delete\n");
+ }
+ }
+
+ NT_LOG(DBG, FILTER,
+ "KCC DEC Ref on Key: %016lx, KM category %i, id %i (new ref count %i)\n",
+ kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt);
+ return cam_entry->ref_cnt;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c
new file mode 100644
index 0000000000..3727707446
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c
@@ -0,0 +1,1438 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+#include "flow_hasher.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct cam_match_masks_s {
+ uint32_t word_len;
+ uint32_t key_mask[4];
+} cam_masks[] = {
+ { 4,
+ { 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff
+ }
+ }, /* IP6_SRC, IP6_DST */
+ { 4,
+ { 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000
+ }
+ }, /* DMAC,SMAC,ethtype */
+ { 4,
+ { 0xffffffff, 0xffff0000, 0x00000000,
+ 0xffff0000
+ }
+ }, /* DMAC,ethtype */
+ { 4,
+ { 0x00000000, 0x0000ffff, 0xffffffff,
+ 0xffff0000
+ }
+ }, /* SMAC,ethtype */
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 } }, /* ETH_128 */
+ { 2,
+ { 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000
+ }
+ }, /* IP4_COMBINED */
+ { 1, { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 } },
+ /*
+ * ETH_TYPE, IP4_TTL_PROTO, IP4_SRC, IP4_DST, IP6_FLOW_TC,
+ * IP6_NEXT_HDR_HOP, TP_PORT_COMBINED, SIDEBAND_VNI
+ */
+ { 1,
+ { 0xffff0000, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* IP4_IHL_TOS, TP_PORT_SRC32_OR_ICMP, TCP_CTRL */
+ { 1,
+ { 0x0000ffff, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* TP_PORT_DST32 */
+ { 1,
+ { 0x00030000, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* IPv4 TOS mask bits used often by OVS */
+ { 1,
+ { 0x00300000, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* IPv6 TOS mask bits used often by OVS */
+};
+
+#define NUM_CAM_MASKS (ARRAY_SIZE(cam_masks))
+
+/*
+ * CAM structures and defines
+ */
+struct cam_distrib_s {
+ struct km_flow_def_s *km_owner;
+};
+
+#define CAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_cam_records + (rec))
+#define CAM_KM_DIST_IDX(bnk) \
+ ({ \
+ int _temp_bnk = (bnk); \
+ CAM_DIST_IDX(_temp_bnk, km->record_indexes[_temp_bnk]); \
+ })
+
+#define CUCKOO_MOVE_MAX_DEPTH 8
+static int cam_addr_reserved_stack[CUCKOO_MOVE_MAX_DEPTH];
+
+/*
+ * TCAM structures and defines
+ */
+struct tcam_distrib_s {
+ struct km_flow_def_s *km_owner;
+};
+
+#define TCAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_tcam_bank_width + (rec))
+
+static int tcam_find_mapping(struct km_flow_def_s *km);
+
+void km_attach_ndev_resource_management(struct km_flow_def_s *km, void **handle)
+{
+#define CAM_ENTRIES \
+ (km->be->km.nb_cam_banks * km->be->km.nb_cam_records * \
+ sizeof(struct cam_distrib_s))
+#define TCAM_ENTRIES \
+ (km->be->km.nb_tcam_bank_width * km->be->km.nb_tcam_banks * \
+ sizeof(struct tcam_distrib_s))
+ /*
+ * KM entries occupied in CAM - to manage the cuckoo shuffling
+ * and manage CAM population and usage
+ * KM entries occupied in TCAM - to manage population and usage
+ */
+ if (!*handle) {
+ *handle = calloc(1, (size_t)CAM_ENTRIES + sizeof(uint32_t) +
+ (size_t)TCAM_ENTRIES +
+ sizeof(struct hasher_s));
+ NT_LOG(DBG, FILTER,
+ "Allocate NIC DEV CAM and TCAM record manager\n");
+ }
+ km->cam_dist = (struct cam_distrib_s *)*handle;
+ km->cuckoo_moves = (uint32_t *)((char *)km->cam_dist + CAM_ENTRIES);
+ km->tcam_dist =
+ (struct tcam_distrib_s *)((char *)km->cam_dist + CAM_ENTRIES +
+ sizeof(uint32_t));
+
+ km->hsh = (struct hasher_s *)((char *)km->tcam_dist + TCAM_ENTRIES);
+ init_hasher(km->hsh, km->be->km.nb_cam_banks,
+ km->be->km.nb_cam_records);
+}
+
+void km_free_ndev_resource_management(void **handle)
+{
+ if (*handle) {
+ free(*handle);
+ NT_LOG(DBG, FILTER,
+ "Free NIC DEV CAM and TCAM record manager\n");
+ }
+ *handle = NULL;
+}
+
+int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4],
+ uint32_t e_mask[4], uint32_t word_len,
+ enum frame_offs_e start_id, int8_t offset)
+{
+#ifdef FLOW_DEBUG
+ char *s = ntlog_helper_str_alloc("MATCH: ");
+
+ for (unsigned int i = 0; i < word_len; i++)
+ ntlog_helper_str_add(s, "%08x, ", e_word[i]);
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_reset(s, "MASK : ");
+ for (unsigned int i = 0; i < word_len; i++)
+ ntlog_helper_str_add(s, "%08x, ", e_mask[i]);
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_free(s);
+#endif
+
+ /* valid word_len 1,2,4 */
+ if (word_len == 3) {
+ word_len = 4;
+ e_word[3] = 0;
+ e_mask[3] = 0;
+ }
+ if (word_len < 1 || word_len > 4) {
+ assert(0);
+ return -1;
+ }
+
+ for (unsigned int i = 0; i < word_len; i++) {
+ km->match[km->num_ftype_elem].e_word[i] = e_word[i];
+ km->match[km->num_ftype_elem].e_mask[i] = e_mask[i];
+ }
+
+ km->match[km->num_ftype_elem].word_len = word_len;
+ km->match[km->num_ftype_elem].rel_offs = offset;
+ km->match[km->num_ftype_elem].extr_start_offs_id = start_id;
+
+ /*
+ * Determine here if this flow may better be put into TCAM
+ * Otherwise it will go into CAM
+ * This is dependent on a cam_masks list defined above
+ */
+ km->match[km->num_ftype_elem].masked_for_tcam = 1;
+ for (unsigned int msk = 0; msk < NUM_CAM_MASKS; msk++) {
+ if (word_len == cam_masks[msk].word_len) {
+ int match = 1;
+
+ for (unsigned int wd = 0; wd < word_len; wd++) {
+ if (e_mask[wd] != cam_masks[msk].key_mask[wd]) {
+ match = 0;
+ break;
+ }
+ }
+ if (match) {
+ /* Can go into CAM */
+ km->match[km->num_ftype_elem].masked_for_tcam =
+ 0;
+ }
+ }
+ }
+
+ km->num_ftype_elem++;
+ return 0;
+}
+
+void km_set_info(struct km_flow_def_s *km, int on)
+{
+ km->info_set = !!on;
+}
+
+static int get_word(struct km_flow_def_s *km, uint32_t size, int marked[])
+{
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (!marked[i] &&
+ !(km->match[i].extr_start_offs_id & SWX_INFO) &&
+ km->match[i].word_len == size)
+ return i;
+ }
+ return -1;
+}
+
+#ifdef FLOW_DEBUG
+static const char *get_prot_offset_descr(int idx)
+{
+ switch (idx) {
+ case DYN_SOF:
+ return "SOF";
+ case DYN_L2:
+ return "L2 header";
+ case DYN_FIRST_VLAN:
+ return "First VLAN";
+ case DYN_MPLS:
+ return "First MPLS";
+ case DYN_L3:
+ return "L3 header";
+ case DYN_ID_IPV4_6:
+ return "ID field IPv4/6";
+ case DYN_FINAL_IP_DST:
+ return "Final IP dest";
+ case DYN_L4:
+ return "L4 header";
+ case DYN_L4_PAYLOAD:
+ return "L4 payload";
+ case DYN_TUN_PAYLOAD:
+ return "Tunnel payload";
+ case DYN_TUN_L2:
+ return "Tunnel L2 header";
+ case DYN_TUN_VLAN:
+ return "First tunneled VLAN";
+ case DYN_TUN_MPLS:
+ return "First tunneled MPLS";
+ case DYN_TUN_L3:
+ return "Tunnel L3 header";
+ case DYN_TUN_ID_IPV4_6:
+ return "Tunnel ID field IPv4/6";
+ case DYN_TUN_FINAL_IP_DST:
+ return "Tunnel final IP dest";
+ case DYN_TUN_L4:
+ return "Tunnel L4 header";
+ case DYN_TUN_L4_PAYLOAD:
+ return "Tunnel L4 payload";
+ case SB_VNI:
+ return "VNI";
+ case SB_MAC_PORT:
+ return "In Port";
+ case SB_KCC_ID:
+ return "KCC ID";
+ default:
+ break;
+ }
+ return "<unknown>";
+}
+#endif
+
+#define MAX_QWORDS 2
+#define MAX_SWORDS 2
+
+int km_key_create(struct km_flow_def_s *km, uint32_t port_id)
+{
+ /*
+ * Create combined extractor mappings
+ * if key fields may be changed to cover un-mappable otherwise?
+ * split into cam and tcam and use synergy mode when available
+ *
+ */
+ int match_marked[MAX_MATCH_FIELDS];
+ int idx = 0;
+ int next = 0;
+ int m_idx;
+ int size;
+ int num_qwords = 0;
+ int num_swords = 0;
+
+ memset(match_marked, 0, sizeof(match_marked));
+
+ /* build QWords */
+ for (int qwords = 0; qwords < MAX_QWORDS; qwords++) {
+ size = 4;
+ m_idx = get_word(km, size, match_marked);
+ if (m_idx < 0) {
+ size = 2;
+ m_idx = get_word(km, size, match_marked);
+
+ if (m_idx < 0) {
+ size = 1;
+ m_idx = get_word(km, 1, match_marked);
+ }
+ }
+ if (m_idx < 0) {
+ /* no more defined */
+ break;
+ }
+
+ match_marked[m_idx] = 1;
+ num_qwords++;
+
+ /* build match map list and set final extractor to use */
+ km->match_map[next] = &km->match[m_idx];
+ km->match[m_idx].extr = KM_USE_EXTRACTOR_QWORD;
+
+ /* build final entry words and mask array */
+ for (int i = 0; i < size; i++) {
+ km->entry_word[idx + i] = km->match[m_idx].e_word[i];
+ km->entry_mask[idx + i] = km->match[m_idx].e_mask[i];
+ }
+
+ idx += size;
+ next++;
+ }
+
+ m_idx = get_word(km, 4, match_marked);
+ if (m_idx >= 0) {
+ /* cannot match more QWords */
+ return -1;
+ }
+
+ /*
+ * On km v6+ we have DWORDs here instead. However, we only use them as SWORDs for now
+ * No match would be able to exploit these as DWORDs because of maximum length of 12 words
+ * in CAM
+ * The last 2 words are taken by KCC-ID/SWX and Color. You could have one or none QWORDs
+ * where then both these DWORDs were possible in 10 words, but we don't have such use case
+ * built in yet
+ */
+ /* build SWords */
+ for (int swords = 0; swords < MAX_SWORDS; swords++) {
+ m_idx = get_word(km, 1, match_marked);
+ if (m_idx < 0) {
+ /* no more defined */
+ break;
+ }
+
+ num_swords++;
+ match_marked[m_idx] = 1;
+ /* build match map list and set final extractor to use */
+ km->match_map[next] = &km->match[m_idx];
+ km->match[m_idx].extr = KM_USE_EXTRACTOR_SWORD;
+
+ /* build final entry words and mask array */
+ km->entry_word[idx] = km->match[m_idx].e_word[0];
+ km->entry_mask[idx] = km->match[m_idx].e_mask[0];
+ idx++;
+ next++;
+ }
+
+ /*
+ * Make sure we took them all
+ */
+ m_idx = get_word(km, 1, match_marked);
+ if (m_idx >= 0) {
+ /* cannot match more SWords */
+ return -1;
+ }
+
+ /*
+ * Handle SWX words specially
+ */
+ int swx_found = 0;
+
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (km->match[i].extr_start_offs_id & SWX_INFO) {
+ km->match_map[next] = &km->match[i];
+ km->match[i].extr = KM_USE_EXTRACTOR_SWORD;
+ /* build final entry words and mask array */
+ km->entry_word[idx] = km->match[i].e_word[0];
+ km->entry_mask[idx] = km->match[i].e_mask[0];
+ idx++;
+ next++;
+ swx_found = 1;
+ }
+ }
+
+ assert(next == km->num_ftype_elem);
+
+ km->key_word_size = idx;
+ km->port_id = port_id;
+
+ km->target = KM_CAM;
+ /*
+ * Finally decide if we want to put this match->action into the TCAM
+ * When SWX word used we need to put it into CAM always, no matter what mask pattern
+ * Later, when synergy mode is applied, we can do a split
+ */
+ if (!swx_found && km->key_word_size <= 6) {
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (km->match_map[i]->masked_for_tcam) {
+ /* At least one */
+ km->target = KM_TCAM;
+ }
+ }
+ }
+
+ NT_LOG(DBG, FILTER, "This flow goes into %s\n",
+ (km->target == KM_TCAM) ? "TCAM" : "CAM");
+
+ if (km->target == KM_TCAM) {
+ if (km->key_word_size > 10) {
+ /* do not support SWX in TCAM */
+ return -1;
+ }
+ /*
+ * adjust for unsupported key word size in TCAM
+ */
+ if ((km->key_word_size == 5 || km->key_word_size == 7 ||
+ km->key_word_size == 9)) {
+ km->entry_mask[km->key_word_size] = 0;
+ km->key_word_size++;
+ }
+
+ /*
+ * 1. the fact that the length of a key cannot change among the same used banks
+ *
+ * calculate possible start indexes
+ * unfortunately restrictions in TCAM lookup
+ * makes it hard to handle key lengths larger than 6
+ * when other sizes should be possible too
+ */
+ switch (km->key_word_size) {
+ case 1:
+ for (int i = 0; i < 4; i++)
+ km->start_offsets[0] = 8 + i;
+ km->num_start_offsets = 4;
+ break;
+ case 2:
+ km->start_offsets[0] = 6;
+ km->num_start_offsets = 1;
+ break;
+ case 3:
+ km->start_offsets[0] = 0;
+ km->num_start_offsets = 1;
+ /* enlarge to 6 */
+ km->entry_mask[km->key_word_size++] = 0;
+ km->entry_mask[km->key_word_size++] = 0;
+ km->entry_mask[km->key_word_size++] = 0;
+ break;
+ case 4:
+ km->start_offsets[0] = 0;
+ km->num_start_offsets = 1;
+ /* enlarge to 6 */
+ km->entry_mask[km->key_word_size++] = 0;
+ km->entry_mask[km->key_word_size++] = 0;
+ break;
+ case 6:
+ km->start_offsets[0] = 0;
+ km->num_start_offsets = 1;
+ break;
+
+ default:
+ NT_LOG(DBG, FILTER,
+ "Final Key word size too large: %i\n",
+ km->key_word_size);
+ return -1;
+ }
+
+#ifdef FLOW_DEBUG
+ char *s = ntlog_helper_str_alloc("TCAM offs: ");
+
+ for (int i = 0; i < km->num_start_offsets; i++)
+ ntlog_helper_str_add(s, "%i,", km->start_offsets[i]);
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_free(s);
+#endif
+ }
+
+#ifdef FLOW_DEBUG
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ NT_LOG(DBG, FILTER,
+ "size %i -> Extr: %s, offset id: %s, rel offset: %i\n",
+ km->match_map[i]->word_len,
+ (km->match_map[i]->extr_start_offs_id & SWX_INFO) ?
+ "SIDEBAND" :
+ km->match_map[i]->extr == KM_USE_EXTRACTOR_SWORD ?
+ "SWORD" :
+ "QWORD",
+ get_prot_offset_descr(km->match_map[i]->extr_start_offs_id),
+ km->match_map[i]->rel_offs);
+ }
+ char *s = ntlog_helper_str_alloc("");
+
+ for (int i = 0; i < km->key_word_size; i++)
+ ntlog_helper_str_add(s, "%08x,", km->entry_word[i]);
+
+ NT_LOG(DBG, FILTER, "%s", s);
+
+ ntlog_helper_str_reset(s, "");
+ for (int i = 0; i < km->key_word_size; i++)
+ ntlog_helper_str_add(s, "%08x,", km->entry_mask[i]);
+
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_free(s);
+#endif
+
+ return 0;
+}
+
+int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1)
+{
+ if (km->target != km1->target ||
+ km->num_ftype_elem != km1->num_ftype_elem ||
+ km->key_word_size != km1->key_word_size ||
+ km->info_set != km1->info_set)
+ return 0;
+
+ /*
+ * before KCC-CAM:
+ * if port is added to match, then we can have different ports in CAT
+ * that reuses this flow type
+ */
+ int port_match_included = 0, kcc_swx_used = 0;
+
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (km->match[i].extr_start_offs_id == SB_MAC_PORT) {
+ port_match_included = 1;
+ break;
+ } else if (km->match_map[i]->extr_start_offs_id == SB_KCC_ID) {
+ kcc_swx_used = 1;
+ break;
+ }
+ }
+
+ /*
+ * If not using KCC and if port match is not included in CAM,
+ * we need to have same port_id to reuse
+ */
+ if (!kcc_swx_used && !port_match_included &&
+ km->port_id != km1->port_id)
+ return 0;
+
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ /* using same extractor types in same sequence */
+ if (km->match_map[i]->extr_start_offs_id != km1->match_map[i]->extr_start_offs_id ||
+ km->match_map[i]->rel_offs != km1->match_map[i]->rel_offs ||
+ km->match_map[i]->extr != km1->match_map[i]->extr ||
+ km->match_map[i]->word_len != km1->match_map[i]->word_len)
+ return 0;
+ }
+
+ if (km->target == KM_CAM) {
+ /* in CAM must exactly match on all masks */
+ for (int i = 0; i < km->key_word_size; i++) {
+ if (km->entry_mask[i] != km1->entry_mask[i])
+ return 0;
+ }
+
+ /* Would be set later if not reusing from km1 */
+ km->cam_paired = km1->cam_paired;
+ } else if (km->target == KM_TCAM) {
+ /*
+ * If TCAM, we must make sure Recipe Key Mask does not
+ * mask out enable bits in masks
+ * Note: it is important that km1 is the original creator
+ * of the KM Recipe, since it contains its true masks
+ */
+ for (int i = 0; i < km->key_word_size; i++) {
+ if ((km->entry_mask[i] & km1->entry_mask[i]) !=
+ km->entry_mask[i])
+ return 0;
+ }
+
+ km->tcam_start_bank = km1->tcam_start_bank;
+ km->tcam_record = -1; /* needs to be found later */
+ } else {
+ NT_LOG(DBG, FILTER,
+ "ERROR - KM target not defined or supported\n");
+ return 0;
+ }
+
+ /*
+ * Check for a flow clash. If already programmed return with -1
+ */
+ int double_match = 1;
+
+ for (int i = 0; i < km->key_word_size; i++) {
+ if ((km->entry_word[i] & km->entry_mask[i]) !=
+ (km1->entry_word[i] & km1->entry_mask[i])) {
+ double_match = 0;
+ break;
+ }
+ }
+
+ if (double_match)
+ return -1;
+
+ /*
+ * Note that TCAM and CAM may reuse same RCP and flow type
+ * when this happens, CAM entry wins on overlap
+ */
+
+ /* Use same KM Recipe and same flow type - return flow type */
+ return km1->flow_type;
+}
+
+int km_rcp_set(struct km_flow_def_s *km, int index)
+{
+ int qw = 0;
+ int sw = 0;
+ int swx = 0;
+
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_PRESET_ALL, index, 0, 0);
+
+ /* set extractor words, offs, contrib */
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ switch (km->match_map[i]->extr) {
+ case KM_USE_EXTRACTOR_SWORD:
+ if (km->match_map[i]->extr_start_offs_id & SWX_INFO) {
+ if (km->target == KM_CAM && swx == 0) {
+ /* SWX */
+ if (km->match_map[i]
+ ->extr_start_offs_id ==
+ SB_VNI) {
+ NT_LOG(DBG, FILTER,
+ "Set KM SWX sel A - VNI\n");
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_CCH,
+ index, 0, 1);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_SEL_A,
+ index, 0,
+ SWX_SEL_ALL32);
+ } else if (km->match_map[i]
+ ->extr_start_offs_id ==
+ SB_MAC_PORT) {
+ NT_LOG(DBG, FILTER,
+ "Set KM SWX sel A - PTC + MAC\n");
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_SEL_A,
+ index, 0,
+ SWX_SEL_ALL32);
+ } else if (km->match_map[i]
+ ->extr_start_offs_id ==
+ SB_KCC_ID) {
+ NT_LOG(DBG, FILTER,
+ "Set KM SWX sel A - KCC ID\n");
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_CCH,
+ index, 0, 1);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_SEL_A,
+ index, 0,
+ SWX_SEL_ALL32);
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ swx++;
+ } else {
+ if (sw == 0) {
+ /* DW8 */
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW8_DYN,
+ index, 0,
+ km->match_map[i]
+ ->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW8_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW8_SEL_A,
+ index, 0,
+ DW8_SEL_FIRST32);
+ NT_LOG(DBG, FILTER,
+ "Set KM DW8 sel A: dyn: %i, offs: %i\n",
+ km->match_map[i]
+ ->extr_start_offs_id,
+ km->match_map[i]->rel_offs);
+ } else if (sw == 1) {
+ /* DW10 */
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW10_DYN,
+ index, 0,
+ km->match_map[i]
+ ->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW10_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW10_SEL_A,
+ index, 0,
+ DW10_SEL_FIRST32);
+ NT_LOG(DBG, FILTER,
+ "Set KM DW10 sel A: dyn: %i, offs: %i\n",
+ km->match_map[i]
+ ->extr_start_offs_id,
+ km->match_map[i]->rel_offs);
+ } else {
+ return -1;
+ }
+ sw++;
+ }
+ break;
+
+ case KM_USE_EXTRACTOR_QWORD:
+ if (qw == 0) {
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_DYN,
+ index, 0,
+ km->match_map[i]->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ switch (km->match_map[i]->word_len) {
+ case 1:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_SEL_A,
+ index, 0,
+ QW0_SEL_FIRST32);
+ break;
+ case 2:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_SEL_A,
+ index, 0,
+ QW0_SEL_FIRST64);
+ break;
+ case 4:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_SEL_A,
+ index, 0,
+ QW0_SEL_ALL128);
+ break;
+ default:
+ return -1;
+ }
+ NT_LOG(DBG, FILTER,
+ "Set KM QW0 sel A: dyn: %i, offs: %i, size: %i\n",
+ km->match_map[i]->extr_start_offs_id,
+ km->match_map[i]->rel_offs,
+ km->match_map[i]->word_len);
+ } else if (qw == 1) {
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_DYN,
+ index, 0,
+ km->match_map[i]->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ switch (km->match_map[i]->word_len) {
+ case 1:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_SEL_A,
+ index, 0,
+ QW4_SEL_FIRST32);
+ break;
+ case 2:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_SEL_A,
+ index, 0,
+ QW4_SEL_FIRST64);
+ break;
+ case 4:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_SEL_A,
+ index, 0,
+ QW4_SEL_ALL128);
+ break;
+ default:
+ return -1;
+ }
+ NT_LOG(DBG, FILTER,
+ "Set KM QW4 sel A: dyn: %i, offs: %i, size: %i\n",
+ km->match_map[i]->extr_start_offs_id,
+ km->match_map[i]->rel_offs,
+ km->match_map[i]->word_len);
+ } else {
+ return -1;
+ }
+ qw++;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ /* set mask A */
+ for (int i = 0; i < km->key_word_size; i++) {
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_MASK_A, index,
+ (km->be->km.nb_km_rcp_mask_a_word_size - 1) -
+ i,
+ km->entry_mask[i]);
+ NT_LOG(DBG, FILTER, "Set KM mask A: %08x\n", km->entry_mask[i]);
+ }
+
+ if (km->target == KM_CAM) {
+ /* set info - Color */
+ if (km->info_set) {
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_INFO_A, index, 0,
+ 1);
+ NT_LOG(DBG, FILTER, "Set KM info A\n");
+ }
+ /* set key length A */
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_EL_A, index, 0,
+ km->key_word_size + !!km->info_set -
+ 1); /* select id is -1 */
+ /* set Flow Type for Key A */
+ NT_LOG(DBG, FILTER, "Set KM EL A: %i\n",
+ km->key_word_size + !!km->info_set - 1);
+
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_FTM_A, index, 0,
+ 1 << km->flow_type);
+
+ NT_LOG(DBG, FILTER, "Set KM FTM A - ft: %i\n", km->flow_type);
+
+ /* Set Paired - only on the CAM part though... */
+ if ((uint32_t)(km->key_word_size + !!km->info_set) >
+ km->be->km.nb_cam_record_words) {
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_PAIRED,
+ index, 0, 1);
+ NT_LOG(DBG, FILTER, "Set KM CAM Paired\n");
+ km->cam_paired = 1;
+ }
+ } else if (km->target == KM_TCAM) {
+ uint32_t bank_bm = 0;
+
+ if (tcam_find_mapping(km) < 0) {
+ /* failed mapping into TCAM */
+ NT_LOG(DBG, FILTER, "INFO: TCAM mapping flow failed\n");
+ return -1;
+ }
+
+ assert((uint32_t)(km->tcam_start_bank + km->key_word_size) <=
+ km->be->km.nb_tcam_banks);
+
+ for (int i = 0; i < km->key_word_size; i++) {
+ bank_bm |= (1 << (km->be->km.nb_tcam_banks - 1 -
+ (km->tcam_start_bank + i)));
+ }
+
+ /* Set BANK_A */
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_BANK_A, index, 0, bank_bm);
+ /* Set Kl_A */
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_KL_A, index, 0,
+ km->key_word_size - 1);
+
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int cam_populate(struct km_flow_def_s *km, int bank)
+{
+ int res = 0;
+ int cnt = km->key_word_size + !!km->info_set;
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,
+ km->record_indexes[bank],
+ km->entry_word[i]);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank,
+ km->record_indexes[bank],
+ km->flow_type);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = km;
+
+ if (cnt) {
+ assert(km->cam_paired);
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be,
+ HW_KM_CAM_W0 + i,
+ bank,
+ km->record_indexes[bank] + 1,
+ km->entry_word[km->be->km.nb_cam_record_words +
+ i]);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i,
+ bank,
+ km->record_indexes[bank] + 1,
+ km->flow_type);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = km;
+ }
+
+ res |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank],
+ km->cam_paired ? 2 : 1);
+
+ return res;
+}
+
+static int cam_reset_entry(struct km_flow_def_s *km, int bank)
+{
+ int res = 0;
+ int cnt = km->key_word_size + !!km->info_set;
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,
+ km->record_indexes[bank], 0);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank,
+ km->record_indexes[bank], 0);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = NULL;
+
+ if (cnt) {
+ assert(km->cam_paired);
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,
+ km->record_indexes[bank] + 1,
+ 0);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i,
+ bank,
+ km->record_indexes[bank] + 1,
+ 0);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = NULL;
+ }
+ res |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank],
+ km->cam_paired ? 2 : 1);
+ return res;
+}
+
+static int move_cuckoo_index(struct km_flow_def_s *km)
+{
+ assert(km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner);
+
+ for (uint32_t bank = 0; bank < km->be->km.nb_cam_banks; bank++) {
+ /* It will not select itself */
+ if (km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner == NULL) {
+ if (km->cam_paired) {
+ if (km->cam_dist[CAM_KM_DIST_IDX(bank) + 1]
+ .km_owner != NULL)
+ continue;
+ }
+
+ /*
+ * Populate in new position
+ */
+ int res = cam_populate(km, bank);
+
+ if (res) {
+ NT_LOG(DBG, FILTER,
+ "Error: failed to write to KM CAM in cuckoo move\n");
+ return 0;
+ }
+
+ /*
+ * Reset/free entry in old bank
+ * HW flushes are really not needed, the old addresses are always taken over
+ * by the caller
+ * If you change this code in future updates, this may no longer be true
+ * then!
+ */
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner =
+ NULL;
+ if (km->cam_paired)
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1]
+ .km_owner = NULL;
+
+ NT_LOG(DBG, FILTER,
+ "KM Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\n",
+ km->bank_used, bank,
+ CAM_KM_DIST_IDX(km->bank_used),
+ CAM_KM_DIST_IDX(bank));
+ km->bank_used = bank;
+ (*km->cuckoo_moves)++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int move_cuckoo_index_level(struct km_flow_def_s *km_parent,
+ int bank_idx, int levels,
+ int cam_adr_list_len)
+{
+ struct km_flow_def_s *km = km_parent->cam_dist[bank_idx].km_owner;
+
+ assert(levels <= CUCKOO_MOVE_MAX_DEPTH);
+
+ /*
+ * Only move if same pairness
+ * Can be extended later to handle both move of paired and single entries
+ */
+ if (!km || km_parent->cam_paired != km->cam_paired)
+ return 0;
+
+ if (move_cuckoo_index(km))
+ return 1;
+ if (levels <= 1)
+ return 0;
+
+ assert(cam_adr_list_len < CUCKOO_MOVE_MAX_DEPTH);
+
+ cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx;
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) {
+ int reserved = 0;
+ int new_idx = CAM_KM_DIST_IDX(i);
+
+ for (int i_reserved = 0; i_reserved < cam_adr_list_len;
+ i_reserved++) {
+ if (cam_addr_reserved_stack[i_reserved] == new_idx) {
+ reserved = 1;
+ break;
+ }
+ }
+ if (reserved)
+ continue;
+
+ int res = move_cuckoo_index_level(km, new_idx, levels - 1,
+ cam_adr_list_len);
+ if (res) {
+ if (move_cuckoo_index(km))
+ return 1;
+
+ else
+ assert(0);
+ }
+ }
+
+ return 0;
+}
+
+static int km_write_data_to_cam(struct km_flow_def_s *km)
+{
+ int res = 0;
+ int val[MAX_BANKS];
+
+ assert(km->be->km.nb_cam_banks <= MAX_BANKS);
+ assert(km->cam_dist);
+
+ /* word list without info set */
+ gethash(km->hsh, km->entry_word, val);
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) {
+ /* if paired we start always on an even address - reset bit 0 */
+ km->record_indexes[i] = (km->cam_paired) ? val[i] & ~1 : val[i];
+ }
+ NT_LOG(DBG, FILTER, "KM HASH [%03X, %03X, %03X]\n",
+ km->record_indexes[0], km->record_indexes[1],
+ km->record_indexes[2]);
+
+ if (km->info_set) {
+ km->entry_word[km->key_word_size] =
+ km->info; /* finally set info */
+ }
+
+ int bank = -1;
+ /*
+ * first step, see if any of the banks are free
+ */
+ for (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks; i_bank++) {
+ if (km->cam_dist[CAM_KM_DIST_IDX(i_bank)].km_owner == NULL) {
+ if (km->cam_paired == 0 ||
+ (km->cam_dist[CAM_KM_DIST_IDX(i_bank) + 1]
+ .km_owner == NULL)) {
+ bank = i_bank;
+ break;
+ }
+ }
+ }
+
+ if (bank < 0) {
+ /*
+ * Second step - cuckoo move existing flows if possible
+ */
+ for (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks;
+ i_bank++) {
+ if (move_cuckoo_index_level(km, CAM_KM_DIST_IDX(i_bank),
+ 4, 0)) {
+ bank = i_bank;
+ break;
+ }
+ }
+ }
+ if (bank < 0)
+ return -1;
+
+ /* populate CAM */
+ NT_LOG(DBG, FILTER, "KM Bank = %i (addr %04X)\n", bank,
+ CAM_KM_DIST_IDX(bank));
+ res = cam_populate(km, bank);
+ if (res == 0) {
+ km->flushed_to_target = 1;
+ km->bank_used = bank;
+ }
+
+ return res;
+}
+
+/*
+ * TCAM
+ */
+static int tcam_find_free_record(struct km_flow_def_s *km, int start_bank)
+{
+ for (uint32_t rec = 0; rec < km->be->km.nb_tcam_bank_width; rec++) {
+ if (km->tcam_dist[TCAM_DIST_IDX(start_bank, rec)].km_owner ==
+ NULL) {
+ int pass = 1;
+
+ for (int ii = 1; ii < km->key_word_size; ii++) {
+ if (km->tcam_dist[TCAM_DIST_IDX(start_bank + ii,
+ rec)]
+ .km_owner != NULL) {
+ pass = 0;
+ break;
+ }
+ }
+ if (pass) {
+ km->tcam_record = rec;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int tcam_find_mapping(struct km_flow_def_s *km)
+{
+ /* Search record and start index for this flow */
+ for (int bs_idx = 0; bs_idx < km->num_start_offsets; bs_idx++) {
+ if (tcam_find_free_record(km, km->start_offsets[bs_idx])) {
+ km->tcam_start_bank = km->start_offsets[bs_idx];
+ NT_LOG(DBG, FILTER,
+ "Found space in TCAM start bank %i, record %i\n",
+ km->tcam_start_bank, km->tcam_record);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int tcam_write_word(struct km_flow_def_s *km, int bank, int record,
+ uint32_t word, uint32_t mask)
+{
+ int err = 0;
+ uint32_t all_recs[3];
+
+ int rec_val = record / 32;
+ int rec_bit_shft = record % 32;
+ uint32_t rec_bit = (1 << rec_bit_shft);
+
+ assert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3);
+
+ for (int byte = 0; byte < 4; byte++) {
+ uint8_t a = (uint8_t)((word >> (24 - (byte * 8))) & 0xff);
+ uint8_t a_m = (uint8_t)((mask >> (24 - (byte * 8))) & 0xff);
+ /* calculate important value bits */
+ a = a & a_m;
+
+#ifdef FLOW_DEBUG
+ if (a_m == 0) {
+ NT_LOG(DBG, FILTER,
+ "bank %i, byte %i, All values, rec_val %i rec bit %08x\n",
+ bank, byte, rec_val, rec_bit);
+ }
+#endif
+
+ for (int val = 0; val < 256; val++) {
+ err |= hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if ((val & a_m) == a) {
+ all_recs[rec_val] |= rec_bit;
+#ifdef FLOW_DEBUG
+ if (a_m) {
+ NT_LOG(DBG, FILTER,
+ "bank %i, byte %i, val %i(%02x), "
+ "rec_val %i rec bit %08x\n",
+ bank, byte, val, val, rec_val,
+ rec_bit);
+ }
+#endif
+ } else {
+ all_recs[rec_val] &= ~rec_bit;
+ }
+ err |= hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if (err)
+ break;
+ }
+ }
+ /* flush bank */
+ err |= hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES);
+ if (err == 0) {
+ assert(km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner ==
+ NULL);
+ km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = km;
+ }
+ return err;
+}
+
+static int km_write_data_to_tcam(struct km_flow_def_s *km)
+{
+ int err = 0;
+
+ if (km->tcam_record < 0) {
+ tcam_find_free_record(km, km->tcam_start_bank);
+ if (km->tcam_record < 0) {
+ NT_LOG(DBG, FILTER,
+ "FAILED to find space in TCAM for flow\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER,
+ "Reused RCP: Found space in TCAM start bank %i, record %i\n",
+ km->tcam_start_bank, km->tcam_record);
+ }
+
+ /* Write KM_TCI */
+ err |= hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank,
+ km->tcam_record, km->info);
+ err |= hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank,
+ km->tcam_record, km->flow_type);
+ err |= hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record,
+ 1);
+
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ for (int i = 0; i < km->key_word_size && !err; i++) {
+ err = tcam_write_word(km, km->tcam_start_bank + i,
+ km->tcam_record, km->entry_word[i],
+ km->entry_mask[i]);
+ }
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ if (err == 0)
+ km->flushed_to_target = 1;
+
+ return err;
+}
+
+static int tcam_reset_bank(struct km_flow_def_s *km, int bank, int record)
+{
+ int err = 0;
+ uint32_t all_recs[3];
+
+ int rec_val = record / 32;
+ int rec_bit_shft = record % 32;
+ uint32_t rec_bit = (1 << rec_bit_shft);
+
+ assert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3);
+
+ for (int byte = 0; byte < 4; byte++) {
+ for (int val = 0; val < 256; val++) {
+ err = hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if (err)
+ break;
+ all_recs[rec_val] &= ~rec_bit;
+ err = hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if (err)
+ break;
+ }
+ }
+ if (err)
+ return err;
+
+ /* flush bank */
+ err = hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES);
+ km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = NULL;
+
+ NT_LOG(DBG, FILTER, "Reset TCAM bank %i, rec_val %i rec bit %08x\n",
+ bank, rec_val, rec_bit);
+
+ return err;
+}
+
+static int tcam_reset_entry(struct km_flow_def_s *km)
+{
+ int err = 0;
+
+ if (km->tcam_start_bank < 0 || km->tcam_record < 0) {
+ NT_LOG(DBG, FILTER, "FAILED to find space in TCAM for flow\n");
+ return -1;
+ }
+
+ /* Write KM_TCI */
+ hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank,
+ km->tcam_record, 0);
+ hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank,
+ km->tcam_record, 0);
+ hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record, 1);
+
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ for (int i = 0; i < km->key_word_size && !err; i++) {
+ err = tcam_reset_bank(km, km->tcam_start_bank + i,
+ km->tcam_record);
+ }
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ return err;
+}
+
+int km_refer_data_match_entry(struct km_flow_def_s *km,
+ struct km_flow_def_s *km1)
+{
+ int res = 0;
+
+ km->root = km1->root ? km1->root : km1;
+ while (km1->reference)
+ km1 = km1->reference;
+ km1->reference = km;
+
+ km->info = km1->info;
+
+ switch (km->target) {
+ case KM_CAM:
+ km->cam_paired = km1->cam_paired;
+ km->bank_used = km1->bank_used;
+ km->flushed_to_target = km1->flushed_to_target;
+ break;
+ case KM_TCAM:
+ km->tcam_start_bank = km1->tcam_start_bank;
+ km->tcam_record = km1->tcam_record;
+ km->flushed_to_target = km1->flushed_to_target;
+ break;
+ case KM_SYNERGY:
+ default:
+ res = -1;
+ break;
+ }
+
+ return res;
+}
+
+int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color)
+{
+ int res = -1;
+
+ km->info = color;
+ NT_LOG(DBG, FILTER, "Write Data entry Color: %08x\n", color);
+
+ switch (km->target) {
+ case KM_CAM:
+ res = km_write_data_to_cam(km);
+ break;
+ case KM_TCAM:
+ res = km_write_data_to_tcam(km);
+ break;
+ case KM_SYNERGY:
+ default:
+ break;
+ }
+ return res;
+}
+
+int km_clear_data_match_entry(struct km_flow_def_s *km)
+{
+ int res = 0;
+
+ if (km->root) {
+ struct km_flow_def_s *km1 = km->root;
+
+ while (km1->reference != km)
+ km1 = km1->reference;
+
+ km1->reference = km->reference;
+
+ km->flushed_to_target = 0;
+ km->bank_used = 0;
+ } else if (km->reference) {
+ km->reference->root = NULL;
+
+ switch (km->target) {
+ case KM_CAM:
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner =
+ km->reference;
+ if (km->key_word_size + !!km->info_set > 1) {
+ assert(km->cam_paired);
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1]
+ .km_owner = km->reference;
+ }
+ break;
+ case KM_TCAM:
+ for (int i = 0; i < km->key_word_size; i++) {
+ km->tcam_dist[TCAM_DIST_IDX(km->tcam_start_bank + i,
+ km->tcam_record)].km_owner = km->reference;
+ }
+ break;
+ case KM_SYNERGY:
+ default:
+ res = -1;
+ break;
+ }
+
+ km->flushed_to_target = 0;
+ km->bank_used = 0;
+ } else if (km->flushed_to_target) {
+ switch (km->target) {
+ case KM_CAM:
+ res = cam_reset_entry(km, km->bank_used);
+ break;
+ case KM_TCAM:
+ res = tcam_reset_entry(km);
+ break;
+ case KM_SYNERGY:
+ default:
+ res = -1;
+ break;
+ }
+ km->flushed_to_target = 0;
+ km->bank_used = 0;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c
new file mode 100644
index 0000000000..17717da8e2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c
@@ -0,0 +1,787 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+#include <stdio.h>
+#include "stream_binary_flow_api.h"
+
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+#define MAX_HW_VIRT_PORTS 127 /* 255 reserved */
+#define VIRTUAL_TUNNEL_PORT_OFFSET 72
+
+struct tunnel_s {
+ struct tunnel_cfg_s cfg;
+ struct tunnel_cfg_s cfg_mask;
+ uint32_t flow_stat_id;
+ uint8_t vport;
+ int refcnt;
+ struct tunnel_s *next; /* linked list of defined tunnels */
+};
+
+int is_virtual_port(uint8_t virt_port)
+{
+ return !!(virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET &&
+ virt_port < MAX_HW_VIRT_PORTS);
+}
+
+/*
+ * New function for use with OVS 2.17.2
+ */
+static struct tunnel_s *tunnels;
+
+static uint8_t vport[MAX_HW_VIRT_PORTS - VIRTUAL_TUNNEL_PORT_OFFSET + 1];
+
+uint8_t flow_tunnel_alloc_virt_port(void)
+{
+ for (uint8_t i = VIRTUAL_TUNNEL_PORT_OFFSET; i < MAX_HW_VIRT_PORTS;
+ i++) {
+ if (!vport[i - VIRTUAL_TUNNEL_PORT_OFFSET]) {
+ vport[i - VIRTUAL_TUNNEL_PORT_OFFSET] = 1;
+ return i;
+ }
+ }
+
+ /* no more virtual ports */
+ return 255;
+}
+
+uint8_t flow_tunnel_free_virt_port(uint8_t virt_port)
+{
+ if (virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET &&
+ virt_port < MAX_HW_VIRT_PORTS) {
+ vport[virt_port - VIRTUAL_TUNNEL_PORT_OFFSET] = 0;
+ return 0;
+ }
+ return -1;
+}
+
+#define check(_v1, _v2, _msk1, _msk2) ({ \
+ __typeof__(_v1) (v1) = (_v1); \
+ __typeof__(_v2) (v2) = (_v2); \
+ __typeof__(_msk1) (msk1) = (_msk1); \
+ __typeof__(_msk2) (msk2) = (_msk2); \
+ (((v1) & (msk1) & (msk2)) == ((v2) & (msk1) & (msk2))); \
+})
+
+#define check_tun_v4_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({ \
+ __typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \
+ __typeof__(_tun_msk) (tun_msk) = (_tun_msk); \
+ __typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \
+ __typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \
+ (check((tun_cfg)->v4.src_ip, (tun1_cfg)->v4.src_ip, \
+ (tun_msk)->v4.src_ip, (tun1_msk)->v4.src_ip) && \
+ check((tun_cfg)->v4.dst_ip, (tun1_cfg)->v4.dst_ip, \
+ (tun_msk)->v4.dst_ip, (tun1_msk)->v4.dst_ip) && \
+ check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \
+ (tun1_msk)->s_port) && \
+ check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \
+ (tun1_msk)->d_port)); \
+})
+
+#define check_tun_v6_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({ \
+ __typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \
+ __typeof__(_tun_msk) (tun_msk) = (_tun_msk); \
+ __typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \
+ __typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \
+ (check((tun_cfg)->v6_long.src_ip[0], (tun1_cfg)->v6_long.src_ip[0], \
+ (tun_msk)->v6_long.src_ip[0], (tun1_msk)->v6_long.src_ip[0]) && \
+ check((tun_cfg)->v6_long.src_ip[1], (tun1_cfg)->v6_long.src_ip[1], \
+ (tun_msk)->v6_long.src_ip[1], (tun1_msk)->v6_long.src_ip[1]) && \
+ check((tun_cfg)->v6_long.dst_ip[0], (tun1_cfg)->v6_long.dst_ip[0], \
+ (tun_msk)->v6_long.dst_ip[0], (tun1_msk)->v6_long.dst_ip[0]) && \
+ check((tun_cfg)->v6_long.dst_ip[1], (tun1_cfg)->v6_long.dst_ip[1], \
+ (tun_msk)->v6_long.dst_ip[1], (tun1_msk)->v6_long.dst_ip[1]) && \
+ check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \
+ (tun1_msk)->s_port) && \
+ check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \
+ (tun1_msk)->d_port)); \
+})
+
+static int check_tun_match(struct tunnel_s *tun,
+ const struct tunnel_cfg_s *tnlcfg,
+ const struct tunnel_cfg_s *tnlcfg_mask)
+{
+ if (tun->cfg.tun_type == tnlcfg->tun_type) {
+ if (tun->cfg.ipversion == 4) {
+ return check_tun_v4_equal(&tun->cfg, &tun->cfg_mask,
+ tnlcfg, tnlcfg_mask);
+ } else {
+ return check_tun_v6_equal(&tun->cfg, &tun->cfg_mask,
+ tnlcfg, tnlcfg_mask);
+ }
+ }
+ return 0;
+}
+
+static struct tunnel_s *tunnel_get(const struct tunnel_cfg_s *tnlcfg,
+ const struct tunnel_cfg_s *tnlcfg_mask,
+ int tun_set)
+{
+ struct tunnel_s *tun = tunnels;
+
+ while (tun) {
+ if (tun->flow_stat_id != (uint32_t)-1) {
+ /* This tun is already defined and set */
+ if (tun_set) {
+ /*
+ * A tunnel full match definition - search for duplicate
+ */
+ if (memcmp(&tun->cfg, tnlcfg,
+ sizeof(struct tunnel_cfg_s)) == 0 &&
+ memcmp(&tun->cfg_mask, tnlcfg_mask,
+ sizeof(struct tunnel_cfg_s)) == 0)
+ break;
+ } else {
+ /*
+ * A tunnel match search
+ */
+ if (check_tun_match(tun, tnlcfg, tnlcfg_mask))
+ break;
+ }
+
+ } else if (tun_set) {
+ /*
+ * Check if this is a pre-configured tunnel for this one to be set
+ * try match them
+ */
+ if (check_tun_match(tun, tnlcfg, tnlcfg_mask)) {
+ /*
+ * Change the tun into the defining one - flow_stat_id is set later
+ */
+ memcpy(&tun->cfg, tnlcfg,
+ sizeof(struct tunnel_cfg_s));
+ memcpy(&tun->cfg_mask, tnlcfg_mask,
+ sizeof(struct tunnel_cfg_s));
+
+ break;
+ }
+
+ } /* else ignore - both unset */
+ tun = tun->next;
+ }
+
+ /*
+ * If not found, create and add it to db
+ */
+ if (!tun) {
+ uint8_t vport = flow_tunnel_alloc_virt_port();
+
+ NT_LOG(DBG, FILTER, "Create NEW tunnel allocate vport %i\n",
+ vport);
+
+ if (vport < 0xff) {
+ tun = calloc(1, sizeof(struct tunnel_s));
+ memcpy(&tun->cfg, tnlcfg, sizeof(struct tunnel_cfg_s));
+ memcpy(&tun->cfg_mask, tnlcfg_mask,
+ sizeof(struct tunnel_cfg_s));
+
+ /* flow_stat_id is set later from flow code */
+ tun->flow_stat_id = (uint32_t)-1;
+ tun->vport = vport;
+ tun->refcnt = 1;
+
+ tun->next = tunnels;
+ tunnels = tun;
+ }
+ } else {
+ tun->refcnt++;
+ NT_LOG(DBG, FILTER, "Found tunnel has vport %i - ref %i\n",
+ tun->vport, tun->refcnt);
+ }
+
+ return tun;
+}
+
+int tunnel_release(struct tunnel_s *tnl)
+{
+ struct tunnel_s *tun = tunnels, *prev = NULL;
+
+ NT_LOG(DBG, FILTER, "release tunnel vport %i, ref cnt %i..\n",
+ tnl->vport, tnl->refcnt);
+ /* find tunnel in list */
+ while (tun) {
+ if (tun == tnl)
+ break;
+ prev = tun;
+ tun = tun->next;
+ }
+
+ if (!tun) {
+ NT_LOG(DBG, FILTER,
+ "ERROR: Tunnel not found in tunnel release!\n");
+ return -1;
+ }
+
+ /* if last ref, take out of list */
+ if (--tun->refcnt == 0) {
+ if (prev)
+ prev->next = tun->next;
+ else
+ tunnels = tun->next;
+ flow_tunnel_free_virt_port(tun->vport);
+
+ NT_LOG(DBG, FILTER,
+ "tunnel ref count == 0 remove tunnel vport %i\n",
+ tun->vport);
+ free(tun);
+ }
+
+ return 0;
+}
+
+struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx,
+ uint32_t *vni)
+{
+ int eidx = *idx;
+ struct tunnel_cfg_s tnlcfg;
+ struct tunnel_cfg_s tnlcfg_mask;
+ struct tunnel_s *rtnl = NULL;
+
+ if (elem) {
+ eidx++;
+ memset(&tnlcfg, 0, sizeof(struct tunnel_cfg_s));
+ int valid = 1;
+ enum flow_elem_type last_type = FLOW_ELEM_TYPE_END;
+
+ tnlcfg.d_port = 0xffff;
+ tnlcfg.tun_type = -1;
+
+ if (vni)
+ *vni = (uint32_t)-1;
+
+ while (elem[eidx].type != FLOW_ELEM_TYPE_END &&
+ elem[eidx].type >= last_type && valid) {
+ switch (elem[eidx].type) {
+ case FLOW_ELEM_TYPE_ANY:
+ case FLOW_ELEM_TYPE_ETH:
+ /* Ignore */
+ break;
+ case FLOW_ELEM_TYPE_IPV4: {
+ const struct flow_elem_ipv4 *ipv4 =
+ (const struct flow_elem_ipv4 *)elem[eidx]
+ .spec;
+ const struct flow_elem_ipv4 *ipv4_mask =
+ (const struct flow_elem_ipv4 *)elem[eidx]
+ .mask;
+
+ tnlcfg.v4.src_ip = ipv4->hdr.src_ip;
+ tnlcfg.v4.dst_ip = ipv4->hdr.dst_ip;
+ tnlcfg_mask.v4.src_ip = ipv4_mask->hdr.src_ip;
+ tnlcfg_mask.v4.dst_ip = ipv4_mask->hdr.dst_ip;
+
+ tnlcfg.ipversion = 4;
+ }
+ break;
+ case FLOW_ELEM_TYPE_IPV6: {
+ const struct flow_elem_ipv6 *ipv6 =
+ (const struct flow_elem_ipv6 *)elem[eidx]
+ .spec;
+ const struct flow_elem_ipv6 *ipv6_mask =
+ (const struct flow_elem_ipv6 *)elem[eidx]
+ .mask;
+
+ memcpy(tnlcfg.v6.src_ip, ipv6->hdr.src_addr,
+ sizeof(tnlcfg.v6.src_ip));
+ memcpy(tnlcfg.v6.dst_ip, ipv6->hdr.dst_addr,
+ sizeof(tnlcfg.v6.dst_ip));
+ memcpy(tnlcfg_mask.v6.src_ip,
+ ipv6_mask->hdr.src_addr,
+ sizeof(tnlcfg.v6.src_ip));
+ memcpy(tnlcfg_mask.v6.dst_ip,
+ ipv6_mask->hdr.dst_addr,
+ sizeof(tnlcfg.v6.dst_ip));
+
+ tnlcfg.ipversion = 6;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_UDP: {
+ const struct flow_elem_udp *udp =
+ (const struct flow_elem_udp *)elem[eidx]
+ .spec;
+ const struct flow_elem_udp *udp_mask =
+ (const struct flow_elem_udp *)elem[eidx]
+ .mask;
+
+ tnlcfg.s_port = udp->hdr.src_port;
+ tnlcfg.d_port = udp->hdr.dst_port;
+ tnlcfg_mask.s_port = udp_mask->hdr.src_port;
+ tnlcfg_mask.d_port = udp_mask->hdr.dst_port;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VXLAN: {
+ const struct flow_elem_vxlan *vxlan =
+ (const struct flow_elem_vxlan *)
+ elem[eidx]
+ .spec;
+ if (vni)
+ *vni = (uint32_t)(((uint32_t)
+ vxlan->vni[0]
+ << 16) |
+ ((uint32_t)
+ vxlan->vni[1]
+ << 8) |
+ ((uint32_t)vxlan
+ ->vni[2]));
+
+ tnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN;
+ }
+ break;
+ default:
+ valid = 0;
+ break;
+ }
+
+ last_type = elem[eidx].type;
+ eidx++;
+ }
+
+ /*
+ * vxlan ports : 4789 or 8472
+ */
+ if (tnlcfg.tun_type < 0 &&
+ (tnlcfg.d_port == 0xb512 || tnlcfg.d_port == 0x1821))
+ tnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN;
+
+ if (!valid || tnlcfg.ipversion == 0 || tnlcfg.tun_type < 0 ||
+ tnlcfg.d_port == 0xffff) {
+ NT_LOG(DBG, FILTER, "Invalid tunnel received\n");
+ return NULL;
+ }
+
+ /* search/add to DB */
+ rtnl = tunnel_get(&tnlcfg, &tnlcfg_mask,
+ vni ? 0 :
+ 1); /* if vni == NULL it is a tun set command */
+
+#ifdef FLOW_DEBUG
+ if (rtnl) {
+ if (vni)
+ NT_LOG(DBG, FILTER,
+ "MATCH A TUNNEL DEFINITION - PRESET "
+ "(PREALLOC VPORT) IF NOT FOUND:\n");
+ else
+ NT_LOG(DBG, FILTER,
+ "SET A TUNNEL DEFINITION:\n");
+ struct in_addr addr, mask;
+ char buf[64];
+
+ addr.s_addr = rtnl->cfg.v4.src_ip;
+ sprintf(buf, "%s", inet_ntoa(addr));
+ mask.s_addr = rtnl->cfg_mask.v4.src_ip;
+ NT_LOG(DBG, FILTER, " tun src IP: %s / %s\n", buf,
+ inet_ntoa(mask));
+ addr.s_addr = rtnl->cfg.v4.dst_ip;
+ sprintf(buf, "%s", inet_ntoa(addr));
+ mask.s_addr = rtnl->cfg_mask.v4.dst_ip;
+ NT_LOG(DBG, FILTER, " tun dst IP: %s / %s\n", buf,
+ inet_ntoa(mask));
+ NT_LOG(DBG, FILTER, " tun tp_src: %i / %04x\n",
+ htons(rtnl->cfg.s_port),
+ htons(rtnl->cfg_mask.s_port));
+ NT_LOG(DBG, FILTER, " tun tp_dst: %i / %04x\n",
+ htons(rtnl->cfg.d_port),
+ htons(rtnl->cfg_mask.d_port));
+ NT_LOG(DBG, FILTER, " tun ipver: %i\n",
+ rtnl->cfg.ipversion);
+ NT_LOG(DBG, FILTER, " tun flow_stat_id: %i\n",
+ rtnl->flow_stat_id);
+ NT_LOG(DBG, FILTER, " tun vport: %i\n",
+ rtnl->vport);
+ NT_LOG(DBG, FILTER, " tun refcnt: %i\n",
+ rtnl->refcnt);
+ }
+#endif
+
+ *idx = eidx; /* pointing to next or END */
+ }
+
+ return rtnl;
+}
+
+uint8_t get_tunnel_vport(struct tunnel_s *rtnl)
+{
+ return rtnl->vport;
+}
+
+void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id)
+{
+ rtnl->flow_stat_id = flow_stat_id;
+}
+
+int tunnel_get_definition(struct tunnel_cfg_s *tuncfg, uint32_t flow_stat_id,
+ uint8_t vport)
+{
+ struct tunnel_s *tun = tunnels;
+
+ while (tun) {
+ if (tun->vport == vport && (flow_stat_id == tun->flow_stat_id ||
+ flow_stat_id == (uint32_t)-1)) {
+ memcpy(tuncfg, &tun->cfg, sizeof(struct tunnel_cfg_s));
+ return 0;
+ }
+ tun = tun->next;
+ }
+
+ return -1;
+}
+
+static be16_t ip_checksum_sum(const be16_t *data, unsigned int size,
+ be16_t seed)
+{
+ unsigned int sum = seed;
+ unsigned int idx;
+
+ for (idx = 0; idx < size / 2; idx++)
+ sum += (unsigned int)(data[idx]);
+ if (size & 1)
+ sum += (unsigned char)data[idx];
+ /* unfold */
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+ return (be16_t)sum;
+}
+
+static void copy_unmasked(uint8_t *result, const struct flow_elem *elem,
+ uint8_t size)
+{
+ for (uint8_t i = 0; i < size; i++)
+ result[i] = ((const uint8_t *)elem->spec)[i];
+}
+
+int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be,
+ struct nic_flow_def *fd,
+ const struct flow_elem *elem)
+{
+ uint32_t eidx = 0;
+ uint8_t size;
+ struct ipv4_hdr_s *tun_ipv4 = NULL;
+ uint16_t *tun_hdr_eth_type_p = NULL;
+
+ if (elem) {
+ while (elem[eidx].type != FLOW_ELEM_TYPE_END) {
+ switch (elem[eidx].type) {
+ case FLOW_ELEM_TYPE_ETH: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_ETH\n");
+ struct flow_elem_eth eth;
+
+ size = sizeof(struct flow_elem_eth);
+
+ copy_unmasked((uint8_t *)ð, &elem[eidx],
+ size);
+
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ ð, size);
+
+ /*
+ * Save a pointer to the tun header ethtype field
+ * (needed later in the IPv4 and IPv6 flow elem cases)
+ */
+ tun_hdr_eth_type_p =
+ (uint16_t *)&fd->tun_hdr.d
+ .hdr8[fd->tun_hdr.len + 12];
+
+#ifdef FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "dmac : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth.d_addr.addr_b[0],
+ eth.d_addr.addr_b[1],
+ eth.d_addr.addr_b[2],
+ eth.d_addr.addr_b[3],
+ eth.d_addr.addr_b[5],
+ eth.d_addr.addr_b[5]);
+ NT_LOG(DBG, FILTER,
+ "smac : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth.s_addr.addr_b[0],
+ eth.s_addr.addr_b[1],
+ eth.s_addr.addr_b[2],
+ eth.s_addr.addr_b[3],
+ eth.s_addr.addr_b[5],
+ eth.s_addr.addr_b[5]);
+ NT_LOG(DBG, FILTER, "type : %04x\n",
+ ntohs(eth.ether_type));
+#endif
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ }
+ break;
+ /* VLAN is not supported */
+
+ case FLOW_ELEM_TYPE_IPV4: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_IPV4\n");
+ struct flow_elem_ipv4 ipv4;
+
+ size = sizeof(struct flow_elem_ipv4);
+
+ copy_unmasked((uint8_t *)&ipv4, &elem[eidx],
+ size);
+
+ if (ipv4.hdr.version_ihl != 0x45)
+ ipv4.hdr.version_ihl = 0x45;
+
+ if (ipv4.hdr.ttl == 0)
+ ipv4.hdr.ttl = 64;
+
+ if (ipv4.hdr.next_proto_id !=
+ 17) /* must be UDP */
+ ipv4.hdr.next_proto_id = 17;
+
+ ipv4.hdr.frag_offset =
+ htons(1 << 14); /* DF flag */
+
+ size = sizeof(struct ipv4_hdr_s);
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &ipv4.hdr, size);
+
+ /* Set the tun header ethtype field to IPv4 (if empty) */
+ if (tun_hdr_eth_type_p &&
+ (*tun_hdr_eth_type_p == 0)) {
+ *tun_hdr_eth_type_p =
+ htons(0x0800); /* IPv4 */
+ }
+
+ tun_ipv4 = (struct ipv4_hdr_s *)&fd->tun_hdr.d
+ .hdr8[fd->tun_hdr.len];
+
+ NT_LOG(DBG, FILTER, "v_ihl : %02x\n",
+ tun_ipv4->version_ihl);
+ NT_LOG(DBG, FILTER, "tos : %02x\n",
+ tun_ipv4->tos);
+ NT_LOG(DBG, FILTER, "len : %d\n",
+ ntohs(tun_ipv4->length));
+ NT_LOG(DBG, FILTER, "id : %02x\n",
+ tun_ipv4->id);
+ NT_LOG(DBG, FILTER, "fl/frg : %04x\n",
+ ntohs(tun_ipv4->frag_offset));
+ NT_LOG(DBG, FILTER, "ttl : %02x\n",
+ tun_ipv4->ttl);
+ NT_LOG(DBG, FILTER, "prot : %02x\n",
+ tun_ipv4->next_proto_id);
+ NT_LOG(DBG, FILTER, "chksum : %04x\n",
+ ntohs(tun_ipv4->hdr_csum));
+ NT_LOG(DBG, FILTER, "src : %d.%d.%d.%d\n",
+ (tun_ipv4->src_ip & 0xff),
+ ((tun_ipv4->src_ip >> 8) & 0xff),
+ ((tun_ipv4->src_ip >> 16) & 0xff),
+ ((tun_ipv4->src_ip >> 24) & 0xff));
+ NT_LOG(DBG, FILTER, "dst : %d.%d.%d.%d\n",
+ (tun_ipv4->dst_ip & 0xff),
+ ((tun_ipv4->dst_ip >> 8) & 0xff),
+ ((tun_ipv4->dst_ip >> 16) & 0xff),
+ ((tun_ipv4->dst_ip >> 24) & 0xff));
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ fd->tun_hdr.ip_version = 4;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_IPV6: {
+ if (be->roa.ver < 6) {
+ NT_LOG(ERR, FILTER,
+ "Tunnel flow element type IPv6 requires ROA version 6 or higher (current version=%d)\n",
+ be->roa.ver);
+ return -1;
+ }
+
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_IPV6\n");
+ struct flow_elem_ipv6 ipv6;
+
+ size = sizeof(struct flow_elem_ipv6);
+
+ copy_unmasked((uint8_t *)&ipv6, &elem[eidx],
+ size);
+
+ /*
+ * Make sure the version field (the 4 most significant bits of
+ * "vtc_flow") is set to 6
+ */
+ if ((ipv6.hdr.vtc_flow & htonl(0x60000000)) ==
+ 0) {
+ ipv6.hdr.vtc_flow |= htonl(0x60000000); /* Version = 6 */
+ }
+
+ if (ipv6.hdr.proto != 17) /* must be UDP */
+ ipv6.hdr.proto = 17;
+
+ if (ipv6.hdr.hop_limits == 0)
+ ipv6.hdr.hop_limits = 64;
+
+ size = sizeof(struct ipv6_hdr_s);
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &ipv6.hdr, size);
+
+ /* Set the tun header ethtype field to IPv6 (if empty) */
+ if (tun_hdr_eth_type_p &&
+ (*tun_hdr_eth_type_p == 0)) {
+ *tun_hdr_eth_type_p =
+ htons(0x86DD); /* IPv6 */
+ }
+
+ NT_LOG(DBG, FILTER, "vtc_flow : %08x\n",
+ ntohl(ipv6.hdr.vtc_flow));
+ NT_LOG(DBG, FILTER, "payload_len : %04x\n",
+ ntohs(ipv6.hdr.payload_len));
+ NT_LOG(DBG, FILTER, "proto : %02x\n",
+ ipv6.hdr.proto);
+ NT_LOG(DBG, FILTER, "hop_limits : %02x\n",
+ ipv6.hdr.hop_limits);
+ NT_LOG(DBG, FILTER,
+ "src : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ ipv6.hdr.src_addr[0],
+ ipv6.hdr.src_addr[1],
+ ipv6.hdr.src_addr[2],
+ ipv6.hdr.src_addr[3],
+ ipv6.hdr.src_addr[4],
+ ipv6.hdr.src_addr[5],
+ ipv6.hdr.src_addr[6],
+ ipv6.hdr.src_addr[7],
+ ipv6.hdr.src_addr[8],
+ ipv6.hdr.src_addr[9],
+ ipv6.hdr.src_addr[10],
+ ipv6.hdr.src_addr[11],
+ ipv6.hdr.src_addr[12],
+ ipv6.hdr.src_addr[13],
+ ipv6.hdr.src_addr[14],
+ ipv6.hdr.src_addr[15]);
+ NT_LOG(DBG, FILTER,
+ "dst : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ ipv6.hdr.dst_addr[0],
+ ipv6.hdr.dst_addr[1],
+ ipv6.hdr.dst_addr[2],
+ ipv6.hdr.dst_addr[3],
+ ipv6.hdr.dst_addr[4],
+ ipv6.hdr.dst_addr[5],
+ ipv6.hdr.dst_addr[6],
+ ipv6.hdr.dst_addr[7],
+ ipv6.hdr.dst_addr[8],
+ ipv6.hdr.dst_addr[9],
+ ipv6.hdr.dst_addr[10],
+ ipv6.hdr.dst_addr[11],
+ ipv6.hdr.dst_addr[12],
+ ipv6.hdr.dst_addr[13],
+ ipv6.hdr.dst_addr[14],
+ ipv6.hdr.dst_addr[15]);
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ fd->tun_hdr.ip_version = 6;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_UDP: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_UDP\n");
+ struct flow_elem_udp udp;
+
+ size = sizeof(struct flow_elem_udp);
+
+ copy_unmasked((uint8_t *)&udp, &elem[eidx],
+ size);
+
+ udp.hdr.cksum =
+ 0; /* set always the UDP checksum to 0 */
+
+ size = sizeof(struct udp_hdr_s);
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &udp.hdr, size);
+
+ NT_LOG(DBG, FILTER, "src p : %d\n",
+ ntohs(udp.hdr.src_port));
+ NT_LOG(DBG, FILTER, "dst p : %d\n",
+ ntohs(udp.hdr.dst_port));
+ NT_LOG(DBG, FILTER, "len : %d\n",
+ ntohs(udp.hdr.len));
+ NT_LOG(DBG, FILTER, "chksum : %04x\n",
+ ntohs(udp.hdr.cksum));
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VXLAN: {
+ struct flow_elem_vxlan vxlan_m;
+
+ size = sizeof(struct flow_elem_vxlan);
+
+ copy_unmasked((uint8_t *)&vxlan_m, &elem[eidx],
+ size);
+
+ vxlan_m.flags =
+ 0x08; /* set always I-flag - valid VNI */
+
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_VXLAN - vni %u\n",
+ (vxlan_m.vni[0] << 16) +
+ (vxlan_m.vni[1] << 8) +
+ vxlan_m.vni[2]);
+
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &vxlan_m, size);
+
+ NT_LOG(DBG, FILTER, "flags : %02x\n",
+ vxlan_m.flags);
+ NT_LOG(DBG, FILTER, "vni : %d\n",
+ (vxlan_m.vni[0] << 16) +
+ (vxlan_m.vni[1] << 8) +
+ vxlan_m.vni[2]);
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_PORT_ID: {
+ const struct flow_elem_port_id *port =
+ (const struct flow_elem_port_id *)
+ elem[eidx]
+ .spec;
+ fd->tun_hdr.user_port_id = port->id;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VOID: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_VOID (ignoring)\n");
+ }
+ break;
+
+ default:
+ NT_LOG(INF, FILTER,
+ "unsupported Tunnel flow element type %u\n",
+ elem[eidx].type);
+ return -1;
+ }
+
+ eidx++;
+ }
+ }
+
+ if (tun_ipv4) {
+ tun_ipv4->hdr_csum = 0;
+ tun_ipv4->length = 0;
+ fd->tun_hdr.ip_csum_precalc = ntohs(ip_checksum_sum((const be16_t *)&fd->tun_hdr.d
+ .hdr8[14],
+ (unsigned int)sizeof(struct ipv4_hdr_s),
+ (be16_t)htons((uint16_t)(fd->tun_hdr.len - sizeof(struct flow_elem_eth)))));
+
+ NT_LOG(DBG, FILTER,
+ "chksum precalc: %04x, precalc hdr len %u\n",
+ fd->tun_hdr.ip_csum_precalc,
+ fd->tun_hdr.len - sizeof(struct flow_elem_eth));
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c
new file mode 100644
index 0000000000..5a62343718
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c
@@ -0,0 +1,1789 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "CAT"
+#define _VER_ be->cat.ver
+
+static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count);
+static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count);
+static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count);
+
+bool hw_mod_cat_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_cat_present(be->be_dev);
+}
+
+int hw_mod_cat_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_cat_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "CAT MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ int nb = be->iface->get_nb_cat_funcs(be->be_dev);
+
+ if (nb <= 0)
+ return error_resource_count(__func__, "cat_funcs", _MOD_, _VER_);
+ be->cat.nb_cat_funcs = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_flow_types(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "km_flow_types", _MOD_, _VER_);
+ be->cat.nb_flow_types = (uint32_t)nb;
+
+ nb = be->iface->get_nb_pm_ext(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "pm_ext", _MOD_, _VER_);
+ be->cat.nb_pm_ext = (uint32_t)nb;
+
+ nb = be->iface->get_nb_len(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "len", _MOD_, _VER_);
+ be->cat.nb_len = (uint32_t)nb;
+
+ nb = be->iface->get_kcc_size(be->be_dev);
+ if (nb < 0)
+ return error_resource_count(__func__, "kcc_size", _MOD_, _VER_);
+ be->cat.kcc_size = (uint32_t)nb;
+
+ nb = be->iface->get_kcc_banks(be->be_dev);
+ if (nb < 0)
+ return error_resource_count(__func__, "kcc_banks", _MOD_, _VER_);
+ be->cat.kcc_banks = (uint32_t)nb;
+
+ nb = be->iface->get_nb_cat_km_if_cnt(be->be_dev);
+ if (nb < 0)
+ return error_resource_count(__func__, "km_if_count", _MOD_, _VER_);
+ be->cat.km_if_count = (uint32_t)nb;
+
+ int idx = be->iface->get_nb_cat_km_if_m0(be->be_dev);
+
+ be->cat.km_if_m0 = idx;
+
+ idx = be->iface->get_nb_cat_km_if_m1(be->be_dev);
+ be->cat.km_if_m1 = idx;
+
+ if (be->cat.kcc_banks)
+ be->cat.kcc_records = be->cat.kcc_size / be->cat.kcc_banks;
+ else
+ be->cat.kcc_records = 0;
+
+ be->cat.kcc_id_bit_size = 10;
+
+ switch (_VER_) {
+ case 18:
+ be->cat.cts_num = 11;
+ if (!callocate_mod(CAST_COMMON(&be->cat), 12,
+ &be->cat.v18.cfn,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_cfn_s),
+ &be->cat.v18.kce,
+ (be->cat.nb_cat_funcs / 8),
+ sizeof(struct cat_v18_kce_s),
+ &be->cat.v18.kcs,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_kcs_s),
+ &be->cat.v18.fte,
+ (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 2,
+ sizeof(struct cat_v18_fte_s),
+ &be->cat.v18.cte,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_cte_s),
+ &be->cat.v18.cts,
+ be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),
+ sizeof(struct cat_v18_cts_s),
+ &be->cat.v18.cot,
+ be->max_categories,
+ sizeof(struct cat_v18_cot_s),
+ &be->cat.v18.cct,
+ be->max_categories * 4,
+ sizeof(struct cat_v18_cct_s),
+ &be->cat.v18.exo,
+ be->cat.nb_pm_ext,
+ sizeof(struct cat_v18_exo_s),
+ &be->cat.v18.rck,
+ be->cat.nb_pm_ext * 64,
+ sizeof(struct cat_v18_rck_s),
+ &be->cat.v18.len,
+ be->cat.nb_len,
+ sizeof(struct cat_v18_len_s),
+ &be->cat.v18.kcc_cam,
+ be->cat.kcc_size,
+ sizeof(struct cat_v18_kcc_s)))
+ return -1;
+
+ break;
+ /* end case 18 */
+ case 21:
+ be->cat.cts_num = 11;
+ if (!callocate_mod(CAST_COMMON(&be->cat), 12,
+ &be->cat.v21.cfn,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_cfn_s),
+ &be->cat.v21.kce,
+ (be->cat.nb_cat_funcs / 8),
+ sizeof(struct cat_v21_kce_s),
+ &be->cat.v21.kcs,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_kcs_s),
+ &be->cat.v21.fte,
+ (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4,
+ sizeof(struct cat_v21_fte_s),
+ &be->cat.v21.cte,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_cte_s),
+ &be->cat.v21.cts,
+ be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),
+ sizeof(struct cat_v18_cts_s),
+ &be->cat.v21.cot,
+ be->max_categories,
+ sizeof(struct cat_v18_cot_s),
+ &be->cat.v21.cct,
+ be->max_categories * 4,
+ sizeof(struct cat_v18_cct_s),
+ &be->cat.v21.exo,
+ be->cat.nb_pm_ext,
+ sizeof(struct cat_v18_exo_s),
+ &be->cat.v21.rck,
+ be->cat.nb_pm_ext * 64,
+ sizeof(struct cat_v18_rck_s),
+ &be->cat.v21.len,
+ be->cat.nb_len,
+ sizeof(struct cat_v18_len_s),
+ &be->cat.v21.kcc_cam,
+ be->cat.kcc_size,
+ sizeof(struct cat_v18_kcc_s)))
+ return -1;
+
+ break;
+ /* end case 21 */
+ case 22:
+ be->cat.cts_num = 12;
+ if (!callocate_mod(CAST_COMMON(&be->cat), 14,
+ &be->cat.v22.cfn,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_cfn_s),
+ &be->cat.v22.kce,
+ (be->cat.nb_cat_funcs / 8),
+ sizeof(struct cat_v21_kce_s),
+ &be->cat.v22.kcs,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_kcs_s),
+ &be->cat.v22.fte,
+ (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4,
+ sizeof(struct cat_v21_fte_s),
+ &be->cat.v22.cte,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v22_cte_s),
+ &be->cat.v22.cts,
+ be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),
+ sizeof(struct cat_v18_cts_s),
+ &be->cat.v22.cot,
+ be->max_categories,
+ sizeof(struct cat_v18_cot_s),
+ &be->cat.v22.cct,
+ be->max_categories * 4,
+ sizeof(struct cat_v18_cct_s),
+ &be->cat.v22.exo,
+ be->cat.nb_pm_ext,
+ sizeof(struct cat_v18_exo_s),
+ &be->cat.v22.rck,
+ be->cat.nb_pm_ext * 64,
+ sizeof(struct cat_v18_rck_s),
+ &be->cat.v22.len,
+ be->cat.nb_len,
+ sizeof(struct cat_v18_len_s),
+ &be->cat.v22.kcc_cam,
+ be->cat.kcc_size,
+ sizeof(struct cat_v18_kcc_s),
+ &be->cat.v22.cce,
+ 4,
+ sizeof(struct cat_v22_cce_s),
+ &be->cat.v22.ccs,
+ 1024,
+ sizeof(struct cat_v22_ccs_s)))
+ return -1;
+
+ break;
+ /* end case 22 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_cat_free(struct flow_api_backend_s *be)
+{
+ if (be->cat.base) {
+ free(be->cat.base);
+ be->cat.base = NULL;
+ }
+}
+
+static int cfn_reset(struct flow_api_backend_s *be, int i)
+{
+ int err = hw_mod_cat_cfn_set(be, HW_CAT_CFN_PRESET_ALL, i, 0, 0);
+
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_ISL, i, 0,
+ 0xffffffff); /* accept both ISL or not ISL */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_CFP, i, 0,
+ 0xffffffff); /* accept both CFP or not CFP */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MAC, i, 0,
+ 0xffffffff); /* accept all MACs */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L2, i, 0,
+ 0xffffffff); /* accept all L2 prot */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VNTAG, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VLAN, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MPLS, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L3, i, 0,
+ 0xffffffff); /* accept all L3 prot */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_FRAG, i, 0,
+ 0xffffffff); /* accept all fragments */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_IP_PROT, i, 0,
+ 0xffffffff); /* IP prot check disabled */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L4, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TUNNEL, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L2, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_VLAN, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_MPLS, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L3, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_FRAG, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_IP_PROT, i, 0,
+ 0xffffffff); /* inner IP prot check disabled */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L4, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_CV, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_FCS, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TRUNC, i, 0,
+ 0xffffffff); /* accept all truncations */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L3_CS, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L4_CS, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PM_OR_INV, i, 0, 1); /* */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_LC_INV, i, 0, 1); /* */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_KM0_OR, i, 0,
+ 0xffffffff); /* or all */
+ if (_VER_ >= 21) {
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_KM1_OR, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L3_CS, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L4_CS, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TTL_EXP, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_TTL_EXP, i, 0,
+ 0xffffffff); /* or all */
+ }
+ return err;
+}
+
+int hw_mod_cat_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->cat);
+
+ NT_LOG(DBG, FILTER, "INIT CAT CFN\n");
+ if (hw_mod_cat_cfn_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ if (_VER_ <= 18) {
+ NT_LOG(DBG, FILTER, "INIT CAT KCE\n");
+ if (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, 0, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT KCS\n");
+ if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, 0, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT FTE\n");
+ if (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, 0, 0,
+ ALL_ENTRIES))
+ return -1;
+ } else {
+ NT_LOG(DBG, FILTER, "INIT CAT KCE 0\n");
+ if (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,
+ 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT KCS 0\n");
+ if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,
+ 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT FTE 0\n");
+ if (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,
+ 0, ALL_ENTRIES))
+ return -1;
+
+ if (be->cat.km_if_count > 1) {
+ NT_LOG(DBG, FILTER, "INIT CAT KCE 1\n");
+ if (hw_mod_cat_kce_flush(be, KM_FLM_IF_SECOND,
+ be->cat.km_if_m1, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT KCS 1\n");
+ if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_SECOND,
+ be->cat.km_if_m1, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT FTE 1\n");
+ if (hw_mod_cat_fte_flush(be, KM_FLM_IF_SECOND,
+ be->cat.km_if_m1, 0,
+ ALL_ENTRIES))
+ return -1;
+ }
+ }
+
+ NT_LOG(DBG, FILTER, "INIT CAT CTE\n");
+ if (hw_mod_cat_cte_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT CTS\n");
+ if (hw_mod_cat_cts_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT COT\n");
+ if (hw_mod_cat_cot_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT CCT\n");
+ if (hw_mod_cat_cct_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT EXO\n");
+ if (hw_mod_cat_exo_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT RCK\n");
+ if (hw_mod_cat_rck_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT LEN\n");
+ if (hw_mod_cat_len_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ if (be->cat.kcc_size) {
+ NT_LOG(DBG, FILTER, "INIT CAT KCC\n");
+ if (hw_mod_cat_kcc_flush(be, 0, ALL_ENTRIES))
+ return -1;
+ }
+
+ if (_VER_ > 21) {
+ NT_LOG(DBG, FILTER, "INIT CAT CCE\n");
+ if (hw_mod_cat_cce_flush(be, 0, ALL_ENTRIES))
+ return -1;
+ NT_LOG(DBG, FILTER, "INIT CAT CCS\n");
+ if (hw_mod_cat_ccs_flush(be, 0, ALL_ENTRIES))
+ return -1;
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ switch (count) {
+ case ALL_ENTRIES:
+ if (start_idx != 0)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx,
+ be->cat.nb_cat_funcs);
+
+ default:
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx,
+ count);
+ }
+}
+
+static int hw_mod_cat_cfn_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, int word_off,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if ((unsigned int)index >= be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_CFN_SET_ALL_DEFAULTS:
+ if (get)
+ return error_unsup_field(__func__);
+ return cfn_reset(be, index);
+ case HW_CAT_CFN_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->cat.v18.cfn[index], (uint8_t)*value,
+ sizeof(struct cat_v18_cfn_s));
+ break;
+ case HW_CAT_CFN_COMPARE:
+ rv = do_compare_indexes(be->cat.v18.cfn,
+ sizeof(struct cat_v18_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_FIND:
+ rv = find_equal_index(be->cat.v18.cfn,
+ sizeof(struct cat_v18_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_ENABLE:
+ get_set(&be->cat.v18.cfn[index].enable, value, get);
+ break;
+ case HW_CAT_CFN_INV:
+ get_set(&be->cat.v18.cfn[index].inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_INV:
+ get_set(&be->cat.v18.cfn[index].ptc_inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_ISL:
+ get_set(&be->cat.v18.cfn[index].ptc_isl, value, get);
+ break;
+ case HW_CAT_CFN_PTC_CFP:
+ get_set(&be->cat.v18.cfn[index].ptc_cfp, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MAC:
+ get_set(&be->cat.v18.cfn[index].ptc_mac, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L2:
+ get_set(&be->cat.v18.cfn[index].ptc_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VNTAG:
+ get_set(&be->cat.v18.cfn[index].ptc_vntag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VLAN:
+ get_set(&be->cat.v18.cfn[index].ptc_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MPLS:
+ get_set(&be->cat.v18.cfn[index].ptc_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L3:
+ get_set(&be->cat.v18.cfn[index].ptc_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_FRAG:
+ get_set(&be->cat.v18.cfn[index].ptc_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_IP_PROT:
+ get_set(&be->cat.v18.cfn[index].ptc_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L4:
+ get_set(&be->cat.v18.cfn[index].ptc_l4, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TUNNEL:
+ get_set(&be->cat.v18.cfn[index].ptc_tunnel, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L2:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_VLAN:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_MPLS:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L3:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_FRAG:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_IP_PROT:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L4:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_l4, value, get);
+ break;
+ case HW_CAT_CFN_ERR_INV:
+ get_set(&be->cat.v18.cfn[index].err_inv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_CV:
+ get_set(&be->cat.v18.cfn[index].err_cv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_FCS:
+ get_set(&be->cat.v18.cfn[index].err_fcs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TRUNC:
+ get_set(&be->cat.v18.cfn[index].err_trunc, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L3_CS:
+ get_set(&be->cat.v18.cfn[index].err_l3_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L4_CS:
+ get_set(&be->cat.v18.cfn[index].err_l4_cs, value, get);
+ break;
+ case HW_CAT_CFN_MAC_PORT:
+ get_set(&be->cat.v18.cfn[index].mac_port, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMP:
+ if (word_off > 1)
+ return error_word_off_too_large(__func__);
+ get_set(&be->cat.v18.cfn[index].pm_cmp[word_off], value, get);
+ break;
+ case HW_CAT_CFN_PM_DCT:
+ get_set(&be->cat.v18.cfn[index].pm_dct, value, get);
+ break;
+ case HW_CAT_CFN_PM_EXT_INV:
+ get_set(&be->cat.v18.cfn[index].pm_ext_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMB:
+ get_set(&be->cat.v18.cfn[index].pm_cmb, value, get);
+ break;
+ case HW_CAT_CFN_PM_AND_INV:
+ get_set(&be->cat.v18.cfn[index].pm_and_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_OR_INV:
+ get_set(&be->cat.v18.cfn[index].pm_or_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_INV:
+ get_set(&be->cat.v18.cfn[index].pm_inv, value, get);
+ break;
+ case HW_CAT_CFN_LC:
+ get_set(&be->cat.v18.cfn[index].lc, value, get);
+ break;
+ case HW_CAT_CFN_LC_INV:
+ get_set(&be->cat.v18.cfn[index].lc_inv, value, get);
+ break;
+ case HW_CAT_CFN_KM0_OR:
+ get_set(&be->cat.v18.cfn[index].km_or, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CFN_SET_ALL_DEFAULTS:
+ if (get)
+ return error_unsup_field(__func__);
+ return cfn_reset(be, index);
+ case HW_CAT_CFN_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->cat.v21.cfn[index], (uint8_t)*value,
+ sizeof(struct cat_v21_cfn_s));
+ break;
+ case HW_CAT_CFN_COMPARE:
+ rv = do_compare_indexes(be->cat.v21.cfn,
+ sizeof(struct cat_v21_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_FIND:
+ rv = find_equal_index(be->cat.v21.cfn,
+ sizeof(struct cat_v21_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_COPY_FROM:
+ if (get)
+ return error_unsup_field(__func__);
+ memcpy(&be->cat.v21.cfn[index],
+ &be->cat.v21.cfn[*value],
+ sizeof(struct cat_v21_cfn_s));
+ break;
+ case HW_CAT_CFN_ENABLE:
+ get_set(&be->cat.v21.cfn[index].enable, value, get);
+ break;
+ case HW_CAT_CFN_INV:
+ get_set(&be->cat.v21.cfn[index].inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_INV:
+ get_set(&be->cat.v21.cfn[index].ptc_inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_ISL:
+ get_set(&be->cat.v21.cfn[index].ptc_isl, value, get);
+ break;
+ case HW_CAT_CFN_PTC_CFP:
+ get_set(&be->cat.v21.cfn[index].ptc_cfp, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MAC:
+ get_set(&be->cat.v21.cfn[index].ptc_mac, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L2:
+ get_set(&be->cat.v21.cfn[index].ptc_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VNTAG:
+ get_set(&be->cat.v21.cfn[index].ptc_vntag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VLAN:
+ get_set(&be->cat.v21.cfn[index].ptc_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MPLS:
+ get_set(&be->cat.v21.cfn[index].ptc_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L3:
+ get_set(&be->cat.v21.cfn[index].ptc_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_FRAG:
+ get_set(&be->cat.v21.cfn[index].ptc_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_IP_PROT:
+ get_set(&be->cat.v21.cfn[index].ptc_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L4:
+ get_set(&be->cat.v21.cfn[index].ptc_l4, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TUNNEL:
+ get_set(&be->cat.v21.cfn[index].ptc_tunnel, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L2:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_VLAN:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_MPLS:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L3:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_FRAG:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_IP_PROT:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L4:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_l4, value, get);
+ break;
+ case HW_CAT_CFN_ERR_INV:
+ get_set(&be->cat.v21.cfn[index].err_inv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_CV:
+ get_set(&be->cat.v21.cfn[index].err_cv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_FCS:
+ get_set(&be->cat.v21.cfn[index].err_fcs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TRUNC:
+ get_set(&be->cat.v21.cfn[index].err_trunc, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L3_CS:
+ get_set(&be->cat.v21.cfn[index].err_l3_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L4_CS:
+ get_set(&be->cat.v21.cfn[index].err_l4_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TNL_L3_CS:
+ get_set(&be->cat.v21.cfn[index].err_tnl_l3_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TNL_L4_CS:
+ get_set(&be->cat.v21.cfn[index].err_tnl_l4_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TTL_EXP:
+ get_set(&be->cat.v21.cfn[index].err_ttl_exp, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TNL_TTL_EXP:
+ get_set(&be->cat.v21.cfn[index].err_tnl_ttl_exp, value, get);
+ break;
+ case HW_CAT_CFN_MAC_PORT:
+ get_set(&be->cat.v21.cfn[index].mac_port, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMP:
+ if (word_off > 1)
+ return error_word_off_too_large(__func__);
+ get_set(&be->cat.v21.cfn[index].pm_cmp[word_off], value, get);
+ break;
+ case HW_CAT_CFN_PM_DCT:
+ get_set(&be->cat.v21.cfn[index].pm_dct, value, get);
+ break;
+ case HW_CAT_CFN_PM_EXT_INV:
+ get_set(&be->cat.v21.cfn[index].pm_ext_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMB:
+ get_set(&be->cat.v21.cfn[index].pm_cmb, value, get);
+ break;
+ case HW_CAT_CFN_PM_AND_INV:
+ get_set(&be->cat.v21.cfn[index].pm_and_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_OR_INV:
+ get_set(&be->cat.v21.cfn[index].pm_or_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_INV:
+ get_set(&be->cat.v21.cfn[index].pm_inv, value, get);
+ break;
+ case HW_CAT_CFN_LC:
+ get_set(&be->cat.v21.cfn[index].lc, value, get);
+ break;
+ case HW_CAT_CFN_LC_INV:
+ get_set(&be->cat.v21.cfn[index].lc_inv, value, get);
+ break;
+ case HW_CAT_CFN_KM0_OR:
+ get_set(&be->cat.v21.cfn[index].km0_or, value, get);
+ break;
+ case HW_CAT_CFN_KM1_OR:
+ get_set(&be->cat.v21.cfn[index].km1_or, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value)
+{
+ return hw_mod_cat_cfn_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value)
+{
+ return hw_mod_cat_cfn_mod(be, field, index, word_off, value, 1);
+}
+
+static inline int
+find_km_flm_module_interface_index(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id)
+{
+ int km_if_idx;
+
+ if (_VER_ == 18) {
+ km_if_idx = 0;
+ } else {
+ if (if_num == KM_FLM_IF_SECOND) {
+ if (be->cat.km_if_m1 == km_if_id)
+ km_if_idx = 1;
+ else
+ return error_unsup_field(__func__);
+ } else {
+ if (be->cat.km_if_m0 == km_if_id)
+ km_if_idx = 0;
+ else if (be->cat.km_if_m1 == km_if_id)
+ km_if_idx = 1;
+ else
+ return error_unsup_field(__func__);
+ }
+ }
+ return km_if_idx;
+}
+
+/*
+ * KCE
+ */
+
+static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count)
+{
+ /* writes 8 bits - one for each cfn - at a time */
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs / 8;
+ if ((unsigned int)(start_idx + count) > (be->cat.nb_cat_funcs / 8))
+ return error_index_too_large(__func__);
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ return be->iface->cat_kce_flush(be->be_dev, &be->cat, km_if_idx,
+ start_idx, count);
+}
+
+int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kce_flush(be, if_num, 0, start_idx, count);
+}
+
+int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kce_flush(be, if_num, 1, start_idx, count);
+}
+
+static int hw_mod_cat_kce_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int index, uint32_t *value, int get)
+{
+ if ((unsigned int)index >= (be->cat.nb_cat_funcs / 8))
+ return error_index_too_large(__func__);
+
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_KCE_ENABLE_BM:
+ get_set(&be->cat.v18.kce[index].enable_bm, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_KCE_ENABLE_BM:
+ get_set(&be->cat.v21.kce[index].enable_bm[km_if_idx],
+ value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 0, index, &value, 0);
+}
+
+int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 0, index, value, 1);
+}
+
+int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 1, index, &value, 0);
+}
+
+int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 1, index, value, 1);
+}
+
+/*
+ * KCS
+ */
+static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ return be->iface->cat_kcs_flush(be->be_dev, &be->cat, km_if_idx,
+ start_idx, count);
+}
+
+int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kcs_flush(be, if_num, 0, start_idx, count);
+}
+
+int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kcs_flush(be, if_num, 1, start_idx, count);
+}
+
+static int hw_mod_cat_kcs_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int index, uint32_t *value, int get)
+{
+ if ((unsigned int)index >= be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_KCS_CATEGORY:
+ get_set(&be->cat.v18.kcs[index].category, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_KCS_CATEGORY:
+ get_set(&be->cat.v21.kcs[index].category[km_if_idx],
+ value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 0, index, &value, 0);
+}
+
+int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 0, index, value, 1);
+}
+
+int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 1, index, &value, 0);
+}
+
+int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 1, index, value, 1);
+}
+
+/*
+ * FTE
+ */
+static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count)
+{
+ const uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2;
+
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types *
+ key_cnt;
+ if ((unsigned int)(start_idx + count) >
+ (be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt))
+ return error_index_too_large(__func__);
+
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ return be->iface->cat_fte_flush(be->be_dev, &be->cat, km_if_idx,
+ start_idx, count);
+}
+
+int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_fte_flush(be, if_num, 0, start_idx, count);
+}
+
+int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_fte_flush(be, if_num, 1, start_idx, count);
+}
+
+static int hw_mod_cat_fte_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int index, uint32_t *value, int get)
+{
+ const uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2;
+
+ if ((unsigned int)index >=
+ (be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt))
+ return error_index_too_large(__func__);
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_FTE_ENABLE_BM:
+ get_set(&be->cat.v18.fte[index].enable_bm, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_FTE_ENABLE_BM:
+ get_set(&be->cat.v21.fte[index].enable_bm[km_if_idx],
+ value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 0, index, &value, 0);
+}
+
+int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 0, index, value, 1);
+}
+
+int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 1, index, &value, 0);
+}
+
+int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 1, index, value, 1);
+}
+
+int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cte_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cte_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CTE_ENABLE_BM:
+ get_set(&be->cat.v18.cte[index].enable_bm, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cte_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cte_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ int addr_size = (_VER_ < 15) ? 8 : ((be->cat.cts_num + 1) / 2);
+
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs * addr_size;
+ if ((unsigned int)(start_idx + count) >
+ (be->cat.nb_cat_funcs * addr_size))
+ return error_index_too_large(__func__);
+ return be->iface->cat_cts_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cts_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ int addr_size = (be->cat.cts_num + 1) / 2;
+
+ if ((unsigned int)index >= (be->cat.nb_cat_funcs * addr_size))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CTS_CAT_A:
+ get_set(&be->cat.v18.cts[index].cat_a, value, get);
+ break;
+ case HW_CAT_CTS_CAT_B:
+ get_set(&be->cat.v18.cts[index].cat_b, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cts_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cts_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->max_categories;
+ if ((unsigned int)(start_idx + count) > be->max_categories)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cot_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cot_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ int rv = 0;
+ if ((unsigned int)index >= be->max_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_COT_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->cat.v18.cot[index], (uint8_t)*value,
+ sizeof(struct cat_v18_cot_s));
+ break;
+ case HW_CAT_COT_COMPARE:
+ rv = do_compare_indexes(be->cat.v18.cot,
+ sizeof(struct cat_v18_cot_s), index, *value,
+ be->max_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_COT_FIND:
+ rv = find_equal_index(be->cat.v18.cot,
+ sizeof(struct cat_v18_cot_s), index, *value,
+ be->max_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_COT_COLOR:
+ get_set(&be->cat.v18.cot[index].color, value, get);
+ break;
+ case HW_CAT_COT_KM:
+ get_set(&be->cat.v18.cot[index].km, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cot_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cot_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs * 4;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs * 4)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cct_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cct_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_cat_funcs * 4)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CCT_COLOR:
+ get_set(&be->cat.v18.cct[index].color, value, get);
+ break;
+ case HW_CAT_CCT_KM:
+ get_set(&be->cat.v18.cct[index].km, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cct_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cct_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.kcc_size;
+ if ((unsigned int)(start_idx + count) > be->cat.kcc_size)
+ return error_index_too_large(__func__);
+ return be->iface->cat_kcc_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_kcc_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, int word_off,
+ uint32_t *value, int get)
+{
+ if ((unsigned int)index >= be->cat.kcc_size)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_KCC_KEY:
+ if (word_off > 1)
+ return error_word_off_too_large(__func__);
+ get_set(&be->cat.v18.kcc_cam[index].key[word_off], value,
+ get);
+ break;
+
+ case HW_CAT_KCC_CATEGORY:
+ get_set(&be->cat.v18.kcc_cam[index].category, value, get);
+ break;
+
+ case HW_CAT_KCC_ID:
+ get_set(&be->cat.v18.kcc_cam[index].id, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value)
+{
+ return hw_mod_cat_kcc_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value)
+{
+ return hw_mod_cat_kcc_mod(be, field, index, word_off, value, 1);
+}
+
+int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_pm_ext;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_pm_ext)
+ return error_index_too_large(__func__);
+ return be->iface->cat_exo_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_exo_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_pm_ext)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_EXO_DYN:
+ get_set(&be->cat.v18.exo[index].dyn, value, get);
+ break;
+ case HW_CAT_EXO_OFS:
+ get_set_signed(&be->cat.v18.exo[index].ofs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_exo_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_exo_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_pm_ext * 64;
+ if ((unsigned int)(start_idx + count) > (be->cat.nb_pm_ext * 64))
+ return error_index_too_large(__func__);
+ return be->iface->cat_rck_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_rck_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= (be->cat.nb_pm_ext * 64))
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_RCK_DATA:
+ get_set(&be->cat.v18.rck[index].rck_data, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_rck_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_rck_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_len;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_len)
+ return error_index_too_large(__func__);
+ return be->iface->cat_len_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_len_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_len)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_LEN_LOWER:
+ get_set(&be->cat.v18.len[index].lower, value, get);
+ break;
+ case HW_CAT_LEN_UPPER:
+ get_set(&be->cat.v18.len[index].upper, value, get);
+ break;
+ case HW_CAT_LEN_DYN1:
+ get_set(&be->cat.v18.len[index].dyn1, value, get);
+ break;
+ case HW_CAT_LEN_DYN2:
+ get_set(&be->cat.v18.len[index].dyn2, value, get);
+ break;
+ case HW_CAT_LEN_INV:
+ get_set(&be->cat.v18.len[index].inv, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_len_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_len_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = 4;
+ if ((unsigned int)(start_idx + count) > 4)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cce_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cce_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_len)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 22:
+ switch (field) {
+ case HW_CAT_CCE_IMM:
+ get_set(&be->cat.v22.cce[index].imm, value, get);
+ break;
+ case HW_CAT_CCE_IND:
+ get_set(&be->cat.v22.cce[index].ind, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cce_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cce_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = 1024;
+ if ((unsigned int)(start_idx + count) > 1024)
+ return error_index_too_large(__func__);
+ return be->iface->cat_ccs_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_ccs_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_len)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 22:
+ switch (field) {
+ case HW_CAT_CCS_COR_EN:
+ get_set(&be->cat.v22.ccs[index].cor_en, value, get);
+ break;
+ case HW_CAT_CCS_COR:
+ get_set(&be->cat.v22.ccs[index].cor, value, get);
+ break;
+ case HW_CAT_CCS_HSH_EN:
+ get_set(&be->cat.v22.ccs[index].hsh_en, value, get);
+ break;
+ case HW_CAT_CCS_HSH:
+ get_set(&be->cat.v22.ccs[index].hsh, value, get);
+ break;
+ case HW_CAT_CCS_QSL_EN:
+ get_set(&be->cat.v22.ccs[index].qsl_en, value, get);
+ break;
+ case HW_CAT_CCS_QSL:
+ get_set(&be->cat.v22.ccs[index].qsl, value, get);
+ break;
+ case HW_CAT_CCS_IPF_EN:
+ get_set(&be->cat.v22.ccs[index].ipf_en, value, get);
+ break;
+ case HW_CAT_CCS_IPF:
+ get_set(&be->cat.v22.ccs[index].ipf, value, get);
+ break;
+ case HW_CAT_CCS_SLC_EN:
+ get_set(&be->cat.v22.ccs[index].slc_en, value, get);
+ break;
+ case HW_CAT_CCS_SLC:
+ get_set(&be->cat.v22.ccs[index].slc, value, get);
+ break;
+ case HW_CAT_CCS_PDB_EN:
+ get_set(&be->cat.v22.ccs[index].pdb_en, value, get);
+ break;
+ case HW_CAT_CCS_PDB:
+ get_set(&be->cat.v22.ccs[index].pdb, value, get);
+ break;
+ case HW_CAT_CCS_MSK_EN:
+ get_set(&be->cat.v22.ccs[index].msk_en, value, get);
+ break;
+ case HW_CAT_CCS_MSK:
+ get_set(&be->cat.v22.ccs[index].msk, value, get);
+ break;
+ case HW_CAT_CCS_HST_EN:
+ get_set(&be->cat.v22.ccs[index].hst_en, value, get);
+ break;
+ case HW_CAT_CCS_HST:
+ get_set(&be->cat.v22.ccs[index].hst, value, get);
+ break;
+ case HW_CAT_CCS_EPP_EN:
+ get_set(&be->cat.v22.ccs[index].epp_en, value, get);
+ break;
+ case HW_CAT_CCS_EPP:
+ get_set(&be->cat.v22.ccs[index].epp, value, get);
+ break;
+ case HW_CAT_CCS_TPE_EN:
+ get_set(&be->cat.v22.ccs[index].tpe_en, value, get);
+ break;
+ case HW_CAT_CCS_TPE:
+ get_set(&be->cat.v22.ccs[index].tpe, value, get);
+ break;
+ case HW_CAT_CCS_RRB_EN:
+ get_set(&be->cat.v22.ccs[index].rrb_en, value, get);
+ break;
+ case HW_CAT_CCS_RRB:
+ get_set(&be->cat.v22.ccs[index].rrb, value, get);
+ break;
+ case HW_CAT_CCS_SB0_TYPE:
+ get_set(&be->cat.v22.ccs[index].sb0_type, value, get);
+ break;
+ case HW_CAT_CCS_SB0_DATA:
+ get_set(&be->cat.v22.ccs[index].sb0_data, value, get);
+ break;
+ case HW_CAT_CCS_SB1_TYPE:
+ get_set(&be->cat.v22.ccs[index].sb1_type, value, get);
+ break;
+ case HW_CAT_CCS_SB1_DATA:
+ get_set(&be->cat.v22.ccs[index].sb1_data, value, get);
+ break;
+ case HW_CAT_CCS_SB2_TYPE:
+ get_set(&be->cat.v22.ccs[index].sb2_type, value, get);
+ break;
+ case HW_CAT_CCS_SB2_DATA:
+ get_set(&be->cat.v22.ccs[index].sb2_data, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_ccs_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_ccs_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h
new file mode 100644
index 0000000000..3dc4a0aac7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_CAT_V18_H_
+#define _HW_MOD_CAT_V18_H_
+
+struct cat_v18_cfn_s {
+ uint32_t enable;
+ uint32_t inv;
+ /* protocol checks */
+ uint32_t ptc_inv;
+ uint32_t ptc_isl;
+ uint32_t ptc_cfp;
+ uint32_t ptc_mac;
+ uint32_t ptc_l2;
+ uint32_t ptc_vntag;
+ uint32_t ptc_vlan;
+ uint32_t ptc_mpls;
+ uint32_t ptc_l3;
+ uint32_t ptc_frag;
+ uint32_t ptc_ip_prot;
+ uint32_t ptc_l4;
+ uint32_t ptc_tunnel;
+ uint32_t ptc_tnl_l2;
+ uint32_t ptc_tnl_vlan;
+ uint32_t ptc_tnl_mpls;
+ uint32_t ptc_tnl_l3;
+ uint32_t ptc_tnl_frag;
+ uint32_t ptc_tnl_ip_prot;
+ uint32_t ptc_tnl_l4;
+ /* error checks */
+ uint32_t err_inv;
+ uint32_t err_cv;
+ uint32_t err_fcs;
+ uint32_t err_trunc;
+ uint32_t err_l3_cs;
+ uint32_t err_l4_cs;
+ /* in port */
+ uint32_t mac_port;
+ /* pattern matcher */
+ uint32_t pm_cmp[2];
+ uint32_t pm_dct;
+ uint32_t pm_ext_inv;
+ uint32_t pm_cmb;
+ uint32_t pm_and_inv;
+ uint32_t pm_or_inv;
+ uint32_t pm_inv;
+ uint32_t lc;
+ uint32_t lc_inv;
+ uint32_t km_or;
+};
+
+struct cat_v18_kce_s {
+ uint32_t enable_bm;
+};
+
+struct cat_v18_kcs_s {
+ uint32_t category;
+};
+
+struct cat_v18_fte_s {
+ uint32_t enable_bm;
+};
+
+struct cat_v18_cte_s {
+ union {
+ uint32_t enable_bm;
+ struct {
+ uint32_t col : 1;
+ uint32_t cor : 1;
+ uint32_t hsh : 1;
+ uint32_t qsl : 1;
+ uint32_t ipf : 1;
+ uint32_t slc : 1;
+ uint32_t pdb : 1;
+ uint32_t msk : 1;
+ uint32_t hst : 1;
+ uint32_t epp : 1;
+ uint32_t tpe : 1;
+ } b;
+ };
+};
+
+struct cat_v18_cts_s {
+ uint32_t cat_a;
+ uint32_t cat_b;
+};
+
+struct cat_v18_cot_s {
+ uint32_t color;
+ uint32_t km;
+};
+
+struct cat_v18_cct_s {
+ uint32_t color;
+ uint32_t km;
+};
+
+struct cat_v18_exo_s {
+ uint32_t dyn;
+ int32_t ofs;
+};
+
+struct cat_v18_rck_s {
+ uint32_t rck_data;
+};
+
+struct cat_v18_len_s {
+ uint32_t lower;
+ uint32_t upper;
+ uint32_t dyn1;
+ uint32_t dyn2;
+ uint32_t inv;
+};
+
+struct cat_v18_kcc_s {
+ uint32_t key[2];
+ uint32_t category;
+ uint32_t id;
+};
+
+struct hw_mod_cat_v18_s {
+ struct cat_v18_cfn_s *cfn;
+ struct cat_v18_kce_s *kce;
+ struct cat_v18_kcs_s *kcs;
+ struct cat_v18_fte_s *fte;
+ struct cat_v18_cte_s *cte;
+ struct cat_v18_cts_s *cts;
+ struct cat_v18_cot_s *cot;
+ struct cat_v18_cct_s *cct;
+ struct cat_v18_exo_s *exo;
+ struct cat_v18_rck_s *rck;
+ struct cat_v18_len_s *len;
+ struct cat_v18_kcc_s *kcc_cam;
+};
+
+#endif /* _HW_MOD_CAT_V18_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h
new file mode 100644
index 0000000000..fa69ec11f3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_CAT_V21_H_
+#define _HW_MOD_CAT_V21_H_
+
+#include "hw_mod_cat_v18.h"
+
+struct cat_v21_cfn_s {
+ uint32_t enable;
+ uint32_t inv;
+ /* protocol checks */
+ uint32_t ptc_inv;
+ uint32_t ptc_isl;
+ uint32_t ptc_cfp;
+ uint32_t ptc_mac;
+ uint32_t ptc_l2;
+ uint32_t ptc_vntag;
+ uint32_t ptc_vlan;
+ uint32_t ptc_mpls;
+ uint32_t ptc_l3;
+ uint32_t ptc_frag;
+ uint32_t ptc_ip_prot;
+ uint32_t ptc_l4;
+ uint32_t ptc_tunnel;
+ uint32_t ptc_tnl_l2;
+ uint32_t ptc_tnl_vlan;
+ uint32_t ptc_tnl_mpls;
+ uint32_t ptc_tnl_l3;
+ uint32_t ptc_tnl_frag;
+ uint32_t ptc_tnl_ip_prot;
+ uint32_t ptc_tnl_l4;
+ /* error checks */
+ uint32_t err_inv;
+ uint32_t err_cv;
+ uint32_t err_fcs;
+ uint32_t err_trunc;
+ uint32_t err_l3_cs;
+ uint32_t err_l4_cs;
+ uint32_t err_tnl_l3_cs;
+ uint32_t err_tnl_l4_cs;
+ uint32_t err_ttl_exp;
+ uint32_t err_tnl_ttl_exp;
+ /* in port */
+ uint32_t mac_port;
+ /* pattern matcher */
+ uint32_t pm_cmp[2];
+ uint32_t pm_dct;
+ uint32_t pm_ext_inv;
+ uint32_t pm_cmb;
+ uint32_t pm_and_inv;
+ uint32_t pm_or_inv;
+ uint32_t pm_inv;
+ uint32_t lc;
+ uint32_t lc_inv;
+ uint32_t km0_or;
+ uint32_t km1_or;
+};
+
+struct cat_v21_kce_s {
+ uint32_t enable_bm[2];
+};
+
+struct cat_v21_kcs_s {
+ uint32_t category[2];
+};
+
+struct cat_v21_fte_s {
+ uint32_t enable_bm[2];
+};
+
+struct hw_mod_cat_v21_s {
+ struct cat_v21_cfn_s *cfn;
+ struct cat_v21_kce_s *kce;
+ struct cat_v21_kcs_s *kcs;
+ struct cat_v21_fte_s *fte;
+ struct cat_v18_cte_s *cte;
+ struct cat_v18_cts_s *cts;
+ struct cat_v18_cot_s *cot;
+ struct cat_v18_cct_s *cct;
+ struct cat_v18_exo_s *exo;
+ struct cat_v18_rck_s *rck;
+ struct cat_v18_len_s *len;
+ struct cat_v18_kcc_s *kcc_cam;
+};
+
+#endif /* _HW_MOD_CAT_V21_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h
new file mode 100644
index 0000000000..fa7dc6f441
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_CAT_V22_H_
+#define _HW_MOD_CAT_V22_H_
+
+#include "hw_mod_cat_v21.h"
+
+struct cat_v22_cte_s {
+ union {
+ uint32_t enable_bm;
+ struct {
+ uint32_t col : 1;
+ uint32_t cor : 1;
+ uint32_t hsh : 1;
+ uint32_t qsl : 1;
+ uint32_t ipf : 1;
+ uint32_t slc : 1;
+ uint32_t pdb : 1;
+ uint32_t msk : 1;
+ uint32_t hst : 1;
+ uint32_t epp : 1;
+ uint32_t tpe : 1;
+ uint32_t rrb : 1;
+ } b;
+ };
+};
+
+struct cat_v22_cce_s {
+ uint32_t imm;
+ uint32_t ind;
+};
+
+struct cat_v22_ccs_s {
+ uint32_t cor_en;
+ uint32_t cor;
+ uint32_t hsh_en;
+ uint32_t hsh;
+ uint32_t qsl_en;
+ uint32_t qsl;
+ uint32_t ipf_en;
+ uint32_t ipf;
+ uint32_t slc_en;
+ uint32_t slc;
+ uint32_t pdb_en;
+ uint32_t pdb;
+ uint32_t msk_en;
+ uint32_t msk;
+ uint32_t hst_en;
+ uint32_t hst;
+ uint32_t epp_en;
+ uint32_t epp;
+ uint32_t tpe_en;
+ uint32_t tpe;
+ uint32_t rrb_en;
+ uint32_t rrb;
+ uint32_t sb0_type;
+ uint32_t sb0_data;
+ uint32_t sb1_type;
+ uint32_t sb1_data;
+ uint32_t sb2_type;
+ uint32_t sb2_data;
+};
+
+struct hw_mod_cat_v22_s {
+ struct cat_v21_cfn_s *cfn;
+ struct cat_v21_kce_s *kce; /* KCE 0/1 */
+ struct cat_v21_kcs_s *kcs; /* KCS 0/1 */
+ struct cat_v21_fte_s *fte; /* FTE 0/1 */
+ struct cat_v22_cte_s *cte;
+ struct cat_v18_cts_s *cts;
+ struct cat_v18_cot_s *cot;
+ struct cat_v18_cct_s *cct;
+ struct cat_v18_exo_s *exo;
+ struct cat_v18_rck_s *rck;
+ struct cat_v18_len_s *len;
+ struct cat_v18_kcc_s *kcc_cam;
+ struct cat_v22_cce_s *cce;
+ struct cat_v22_ccs_s *ccs;
+};
+
+#endif /* _HW_MOD_CAT_V22_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c
new file mode 100644
index 0000000000..404add5fe6
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c
@@ -0,0 +1,1099 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "FLM"
+#define _VER_ be->flm.ver
+
+bool hw_mod_flm_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_flm_present(be->be_dev);
+}
+
+int hw_mod_flm_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_flm_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "FLM MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_flm_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_categories", _MOD_, _VER_);
+ be->flm.nb_categories = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_size_mb(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_size_mb", _MOD_, _VER_);
+ be->flm.nb_size_mb = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_entry_size(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_entry_size", _MOD_, _VER_);
+ be->flm.nb_entry_size = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_variant(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_variant", _MOD_, _VER_);
+ be->flm.nb_variant = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_prios(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_prios", _MOD_, _VER_);
+ be->flm.nb_prios = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_pst_profiles(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_variant", _MOD_, _VER_);
+ be->flm.nb_pst_profiles = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 17:
+ if (!callocate_mod(CAST_COMMON(&be->flm), 26,
+ &be->flm.v17.control, 1,
+ sizeof(struct flm_v17_control_s),
+ &be->flm.v17.status, 1,
+ sizeof(struct flm_v17_status_s),
+ &be->flm.v17.timeout, 1,
+ sizeof(struct flm_v17_timeout_s),
+ &be->flm.v17.scrub, 1,
+ sizeof(struct flm_v17_scrub_s),
+ &be->flm.v17.load_bin, 1,
+ sizeof(struct flm_v17_load_bin_s),
+ &be->flm.v17.load_pps, 1,
+ sizeof(struct flm_v17_load_pps_s),
+ &be->flm.v17.load_lps, 1,
+ sizeof(struct flm_v17_load_lps_s),
+ &be->flm.v17.load_aps, 1,
+ sizeof(struct flm_v17_load_aps_s),
+ &be->flm.v17.prio, 1,
+ sizeof(struct flm_v17_prio_s),
+ &be->flm.v17.pst, be->flm.nb_pst_profiles,
+ sizeof(struct flm_v17_pst_s),
+ &be->flm.v17.rcp, be->flm.nb_categories,
+ sizeof(struct flm_v17_rcp_s),
+ &be->flm.v17.buf_ctrl, 1,
+ sizeof(struct flm_v17_buf_ctrl_s),
+ &be->flm.v17.lrn_done, 1,
+ sizeof(struct flm_v17_stat_lrn_done_s),
+ &be->flm.v17.lrn_ignore, 1,
+ sizeof(struct flm_v17_stat_lrn_ignore_s),
+ &be->flm.v17.lrn_fail, 1,
+ sizeof(struct flm_v17_stat_lrn_fail_s),
+ &be->flm.v17.unl_done, 1,
+ sizeof(struct flm_v17_stat_unl_done_s),
+ &be->flm.v17.unl_ignore, 1,
+ sizeof(struct flm_v17_stat_unl_ignore_s),
+ &be->flm.v17.rel_done, 1,
+ sizeof(struct flm_v17_stat_rel_done_s),
+ &be->flm.v17.rel_ignore, 1,
+ sizeof(struct flm_v17_stat_rel_ignore_s),
+ &be->flm.v17.aul_done, 1,
+ sizeof(struct flm_v17_stat_aul_done_s),
+ &be->flm.v17.aul_ignore, 1,
+ sizeof(struct flm_v17_stat_aul_ignore_s),
+ &be->flm.v17.aul_fail, 1,
+ sizeof(struct flm_v17_stat_aul_fail_s),
+ &be->flm.v17.tul_done, 1,
+ sizeof(struct flm_v17_stat_tul_done_s),
+ &be->flm.v17.flows, 1,
+ sizeof(struct flm_v17_stat_flows_s),
+ &be->flm.v17.prb_done, 1,
+ sizeof(struct flm_v17_stat_prb_done_s),
+ &be->flm.v17.prb_ignore, 1,
+ sizeof(struct flm_v17_stat_prb_ignore_s)))
+ return -1;
+ break;
+
+ case 20:
+ if (!callocate_mod(CAST_COMMON(&be->flm), 38,
+ &be->flm.v17.control, 1,
+ sizeof(struct flm_v17_control_s),
+ &be->flm.v17.status, 1,
+ sizeof(struct flm_v17_status_s),
+ &be->flm.v17.timeout, 1,
+ sizeof(struct flm_v17_timeout_s),
+ &be->flm.v17.scrub, 1,
+ sizeof(struct flm_v17_scrub_s),
+ &be->flm.v17.load_bin, 1,
+ sizeof(struct flm_v17_load_bin_s),
+ &be->flm.v17.load_pps, 1,
+ sizeof(struct flm_v17_load_pps_s),
+ &be->flm.v17.load_lps, 1,
+ sizeof(struct flm_v17_load_lps_s),
+ &be->flm.v17.load_aps, 1,
+ sizeof(struct flm_v17_load_aps_s),
+ &be->flm.v17.prio, 1,
+ sizeof(struct flm_v17_prio_s),
+ &be->flm.v17.pst, be->flm.nb_pst_profiles,
+ sizeof(struct flm_v17_pst_s),
+ &be->flm.v17.rcp, be->flm.nb_categories,
+ sizeof(struct flm_v17_rcp_s),
+ &be->flm.v17.buf_ctrl, 1,
+ sizeof(struct flm_v17_buf_ctrl_s),
+ &be->flm.v17.lrn_done, 1,
+ sizeof(struct flm_v17_stat_lrn_done_s),
+ &be->flm.v17.lrn_ignore, 1,
+ sizeof(struct flm_v17_stat_lrn_ignore_s),
+ &be->flm.v17.lrn_fail, 1,
+ sizeof(struct flm_v17_stat_lrn_fail_s),
+ &be->flm.v17.unl_done, 1,
+ sizeof(struct flm_v17_stat_unl_done_s),
+ &be->flm.v17.unl_ignore, 1,
+ sizeof(struct flm_v17_stat_unl_ignore_s),
+ &be->flm.v17.rel_done, 1,
+ sizeof(struct flm_v17_stat_rel_done_s),
+ &be->flm.v17.rel_ignore, 1,
+ sizeof(struct flm_v17_stat_rel_ignore_s),
+ &be->flm.v17.aul_done, 1,
+ sizeof(struct flm_v17_stat_aul_done_s),
+ &be->flm.v17.aul_ignore, 1,
+ sizeof(struct flm_v17_stat_aul_ignore_s),
+ &be->flm.v17.aul_fail, 1,
+ sizeof(struct flm_v17_stat_aul_fail_s),
+ &be->flm.v17.tul_done, 1,
+ sizeof(struct flm_v17_stat_tul_done_s),
+ &be->flm.v17.flows, 1,
+ sizeof(struct flm_v17_stat_flows_s),
+ &be->flm.v17.prb_done, 1,
+ sizeof(struct flm_v17_stat_prb_done_s),
+ &be->flm.v17.prb_ignore, 1,
+ sizeof(struct flm_v17_stat_prb_ignore_s),
+ &be->flm.v20.sta_done, 1,
+ sizeof(struct flm_v20_stat_sta_done_s),
+ &be->flm.v20.inf_done, 1,
+ sizeof(struct flm_v20_stat_inf_done_s),
+ &be->flm.v20.inf_skip, 1,
+ sizeof(struct flm_v20_stat_inf_skip_s),
+ &be->flm.v20.pck_hit, 1,
+ sizeof(struct flm_v20_stat_pck_hit_s),
+ &be->flm.v20.pck_miss, 1,
+ sizeof(struct flm_v20_stat_pck_miss_s),
+ &be->flm.v20.pck_unh, 1,
+ sizeof(struct flm_v20_stat_pck_unh_s),
+ &be->flm.v20.pck_dis, 1,
+ sizeof(struct flm_v20_stat_pck_dis_s),
+ &be->flm.v20.csh_hit, 1,
+ sizeof(struct flm_v20_stat_csh_hit_s),
+ &be->flm.v20.csh_miss, 1,
+ sizeof(struct flm_v20_stat_csh_miss_s),
+ &be->flm.v20.csh_unh, 1,
+ sizeof(struct flm_v20_stat_csh_unh_s),
+ &be->flm.v20.cuc_start, 1,
+ sizeof(struct flm_v20_stat_cuc_start_s),
+ &be->flm.v20.cuc_move, 1,
+ sizeof(struct flm_v20_stat_cuc_move_s)))
+ return -1;
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_flm_free(struct flow_api_backend_s *be)
+{
+ if (be->flm.base) {
+ free(be->flm.base);
+ be->flm.base = NULL;
+ }
+}
+
+int hw_mod_flm_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->flm);
+
+ NT_LOG(DBG, FILTER, "INIT FLM\n");
+ hw_mod_flm_control_set(be, HW_FLM_CONTROL_SPLIT_SDRAM_USAGE, 0x10);
+
+ hw_mod_flm_control_flush(be);
+ hw_mod_flm_timeout_flush(be);
+ hw_mod_flm_scrub_flush(be);
+ hw_mod_flm_rcp_flush(be, 0, ALL_ENTRIES);
+
+ return 0;
+}
+
+int hw_mod_flm_control_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_control_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_control_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_CONTROL_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(be->flm.v17.control, (uint8_t)*value,
+ sizeof(struct flm_v17_control_s));
+ break;
+ case HW_FLM_CONTROL_ENABLE:
+ get_set(&be->flm.v17.control->enable, value, get);
+ break;
+ case HW_FLM_CONTROL_INIT:
+ get_set(&be->flm.v17.control->init, value, get);
+ break;
+ case HW_FLM_CONTROL_LDS:
+ get_set(&be->flm.v17.control->lds, value, get);
+ break;
+ case HW_FLM_CONTROL_LFS:
+ get_set(&be->flm.v17.control->lfs, value, get);
+ break;
+ case HW_FLM_CONTROL_LIS:
+ get_set(&be->flm.v17.control->lis, value, get);
+ break;
+ case HW_FLM_CONTROL_UDS:
+ get_set(&be->flm.v17.control->uds, value, get);
+ break;
+ case HW_FLM_CONTROL_UIS:
+ get_set(&be->flm.v17.control->uis, value, get);
+ break;
+ case HW_FLM_CONTROL_RDS:
+ get_set(&be->flm.v17.control->rds, value, get);
+ break;
+ case HW_FLM_CONTROL_RIS:
+ get_set(&be->flm.v17.control->ris, value, get);
+ break;
+ case HW_FLM_CONTROL_PDS:
+ get_set(&be->flm.v17.control->pds, value, get);
+ break;
+ case HW_FLM_CONTROL_PIS:
+ get_set(&be->flm.v17.control->pis, value, get);
+ break;
+ case HW_FLM_CONTROL_CRCWR:
+ get_set(&be->flm.v17.control->crcwr, value, get);
+ break;
+ case HW_FLM_CONTROL_CRCRD:
+ get_set(&be->flm.v17.control->crcrd, value, get);
+ break;
+ case HW_FLM_CONTROL_RBL:
+ get_set(&be->flm.v17.control->rbl, value, get);
+ break;
+ case HW_FLM_CONTROL_EAB:
+ get_set(&be->flm.v17.control->eab, value, get);
+ break;
+ case HW_FLM_CONTROL_SPLIT_SDRAM_USAGE:
+ get_set(&be->flm.v17.control->split_sdram_usage, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_control_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_control_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_status_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_status_flush(be->be_dev, &be->flm);
+}
+
+int hw_mod_flm_status_update(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_status_update(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_status_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_STATUS_CALIBDONE:
+ get_set(&be->flm.v17.status->calibdone, value, get);
+ break;
+ case HW_FLM_STATUS_INITDONE:
+ get_set(&be->flm.v17.status->initdone, value, get);
+ break;
+ case HW_FLM_STATUS_IDLE:
+ get_set(&be->flm.v17.status->idle, value, get);
+ break;
+ case HW_FLM_STATUS_CRITICAL:
+ get_set(&be->flm.v17.status->critical, value, get);
+ break;
+ case HW_FLM_STATUS_PANIC:
+ get_set(&be->flm.v17.status->panic, value, get);
+ break;
+ case HW_FLM_STATUS_CRCERR:
+ get_set(&be->flm.v17.status->crcerr, value, get);
+ break;
+ case HW_FLM_STATUS_EFT_BP:
+ get_set(&be->flm.v17.status->eft_bp, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_status_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_status_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_timeout_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_timeout_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_TIMEOUT_T:
+ get_set(&be->flm.v17.timeout->t, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_timeout_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_timeout_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_scrub_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_scrub_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_SCRUB_I:
+ get_set(&be->flm.v17.scrub->i, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_scrub_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_scrub_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_bin_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_bin_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_BIN:
+ get_set(&be->flm.v17.load_bin->bin, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_bin_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_bin_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_pps_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_pps_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_PPS:
+ get_set(&be->flm.v17.load_pps->pps, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_pps_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_pps_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_lps_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_lps_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_LPS:
+ get_set(&be->flm.v17.load_lps->lps, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_lps_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_lps_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_aps_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_aps_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_APS:
+ get_set(&be->flm.v17.load_aps->aps, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_aps_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_aps_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_prio_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_prio_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_prio_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_PRIO_LIMIT0:
+ get_set(&be->flm.v17.prio->limit0, value, get);
+ break;
+ case HW_FLM_PRIO_FT0:
+ get_set(&be->flm.v17.prio->ft0, value, get);
+ break;
+ case HW_FLM_PRIO_LIMIT1:
+ get_set(&be->flm.v17.prio->limit1, value, get);
+ break;
+ case HW_FLM_PRIO_FT1:
+ get_set(&be->flm.v17.prio->ft1, value, get);
+ break;
+ case HW_FLM_PRIO_LIMIT2:
+ get_set(&be->flm.v17.prio->limit2, value, get);
+ break;
+ case HW_FLM_PRIO_FT2:
+ get_set(&be->flm.v17.prio->ft2, value, get);
+ break;
+ case HW_FLM_PRIO_LIMIT3:
+ get_set(&be->flm.v17.prio->limit3, value, get);
+ break;
+ case HW_FLM_PRIO_FT3:
+ get_set(&be->flm.v17.prio->ft3, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_prio_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_prio_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->flm.nb_pst_profiles;
+ if ((unsigned int)(start_idx + count) > be->flm.nb_pst_profiles)
+ return error_index_too_large(__func__);
+ return be->iface->flm_pst_flush(be->be_dev, &be->flm, start_idx, count);
+}
+
+static int hw_mod_flm_pst_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, int index, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_PST_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->flm.v17.pst[index], (uint8_t)*value,
+ sizeof(struct flm_v17_pst_s));
+ break;
+ case HW_FLM_PST_BP:
+ get_set(&be->flm.v17.pst[index].bp, value, get);
+ break;
+ case HW_FLM_PST_PP:
+ get_set(&be->flm.v17.pst[index].pp, value, get);
+ break;
+ case HW_FLM_PST_TP:
+ get_set(&be->flm.v17.pst[index].tp, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_flm_pst_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_flm_pst_mod(be, field, index, value, 1);
+}
+
+int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->flm.nb_categories;
+ if ((unsigned int)(start_idx + count) > be->flm.nb_categories)
+ return error_index_too_large(__func__);
+ return be->iface->flm_rcp_flush(be->be_dev, &be->flm, start_idx, count);
+}
+
+static int hw_mod_flm_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, int index, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->flm.v17.rcp[index], (uint8_t)*value,
+ sizeof(struct flm_v17_rcp_s));
+ break;
+ case HW_FLM_RCP_LOOKUP:
+ get_set(&be->flm.v17.rcp[index].lookup, value, get);
+ break;
+ case HW_FLM_RCP_QW0_DYN:
+ get_set(&be->flm.v17.rcp[index].qw0_dyn, value, get);
+ break;
+ case HW_FLM_RCP_QW0_OFS:
+ get_set(&be->flm.v17.rcp[index].qw0_ofs, value, get);
+ break;
+ case HW_FLM_RCP_QW0_SEL:
+ get_set(&be->flm.v17.rcp[index].qw0_sel, value, get);
+ break;
+ case HW_FLM_RCP_QW4_DYN:
+ get_set(&be->flm.v17.rcp[index].qw4_dyn, value, get);
+ break;
+ case HW_FLM_RCP_QW4_OFS:
+ get_set(&be->flm.v17.rcp[index].qw4_ofs, value, get);
+ break;
+ case HW_FLM_RCP_SW8_DYN:
+ get_set(&be->flm.v17.rcp[index].sw8_dyn, value, get);
+ break;
+ case HW_FLM_RCP_SW8_OFS:
+ get_set(&be->flm.v17.rcp[index].sw8_ofs, value, get);
+ break;
+ case HW_FLM_RCP_SW8_SEL:
+ get_set(&be->flm.v17.rcp[index].sw8_sel, value, get);
+ break;
+ case HW_FLM_RCP_SW9_DYN:
+ get_set(&be->flm.v17.rcp[index].sw9_dyn, value, get);
+ break;
+ case HW_FLM_RCP_SW9_OFS:
+ get_set(&be->flm.v17.rcp[index].sw9_ofs, value, get);
+ break;
+ case HW_FLM_RCP_MASK:
+ if (get) {
+ memcpy(value, be->flm.v17.rcp[index].mask,
+ sizeof(((struct flm_v17_rcp_s *)0)
+ ->mask));
+ } else {
+ memcpy(be->flm.v17.rcp[index].mask, value,
+ sizeof(((struct flm_v17_rcp_s *)0)
+ ->mask));
+ }
+ break;
+ case HW_FLM_RCP_KID:
+ get_set(&be->flm.v17.rcp[index].kid, value, get);
+ break;
+ case HW_FLM_RCP_OPN:
+ get_set(&be->flm.v17.rcp[index].opn, value, get);
+ break;
+ case HW_FLM_RCP_IPN:
+ get_set(&be->flm.v17.rcp[index].ipn, value, get);
+ break;
+ case HW_FLM_RCP_BYT_DYN:
+ get_set(&be->flm.v17.rcp[index].byt_dyn, value, get);
+ break;
+ case HW_FLM_RCP_BYT_OFS:
+ get_set(&be->flm.v17.rcp[index].byt_ofs, value, get);
+ break;
+ case HW_FLM_RCP_TXPLM:
+ get_set(&be->flm.v17.rcp[index].txplm, value, get);
+ break;
+ case HW_FLM_RCP_AUTO_IPV4_MASK:
+ get_set(&be->flm.v17.rcp[index].auto_ipv4_mask, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value)
+{
+ if (field != HW_FLM_RCP_MASK)
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ return hw_mod_flm_rcp_mod(be, field, index, value, 0);
+}
+
+int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value)
+{
+ if (field == HW_FLM_RCP_MASK)
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ return hw_mod_flm_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_flm_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_buf_ctrl_update(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_buf_ctrl_mod_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value)
+{
+ int get = 1; /* Only get supported */
+
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_BUF_CTRL_LRN_FREE:
+ get_set(&be->flm.v17.buf_ctrl->lrn_free, value, get);
+ break;
+ case HW_FLM_BUF_CTRL_INF_AVAIL:
+ get_set(&be->flm.v17.buf_ctrl->inf_avail, value, get);
+ break;
+ case HW_FLM_BUF_CTRL_STA_AVAIL:
+ get_set(&be->flm.v17.buf_ctrl->sta_avail, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_buf_ctrl_mod_get(be, field, value);
+}
+
+int hw_mod_flm_stat_update(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_stat_update(be->be_dev, &be->flm);
+}
+
+int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_STAT_LRN_DONE:
+ *value = be->flm.v17.lrn_done->cnt;
+ break;
+ case HW_FLM_STAT_LRN_IGNORE:
+ *value = be->flm.v17.lrn_ignore->cnt;
+ break;
+ case HW_FLM_STAT_LRN_FAIL:
+ *value = be->flm.v17.lrn_fail->cnt;
+ break;
+ case HW_FLM_STAT_UNL_DONE:
+ *value = be->flm.v17.unl_done->cnt;
+ break;
+ case HW_FLM_STAT_UNL_IGNORE:
+ *value = be->flm.v17.unl_ignore->cnt;
+ break;
+ case HW_FLM_STAT_REL_DONE:
+ *value = be->flm.v17.rel_done->cnt;
+ break;
+ case HW_FLM_STAT_REL_IGNORE:
+ *value = be->flm.v17.rel_ignore->cnt;
+ break;
+ case HW_FLM_STAT_PRB_DONE:
+ *value = be->flm.v17.prb_done->cnt;
+ break;
+ case HW_FLM_STAT_PRB_IGNORE:
+ *value = be->flm.v17.prb_ignore->cnt;
+ break;
+ case HW_FLM_STAT_AUL_DONE:
+ *value = be->flm.v17.aul_done->cnt;
+ break;
+ case HW_FLM_STAT_AUL_IGNORE:
+ *value = be->flm.v17.aul_ignore->cnt;
+ break;
+ case HW_FLM_STAT_AUL_FAIL:
+ *value = be->flm.v17.aul_fail->cnt;
+ break;
+ case HW_FLM_STAT_TUL_DONE:
+ *value = be->flm.v17.tul_done->cnt;
+ break;
+ case HW_FLM_STAT_FLOWS:
+ *value = be->flm.v17.flows->cnt;
+ break;
+
+ default: {
+ if (_VER_ < 18)
+ return error_unsup_field(__func__);
+
+ switch (field) {
+ case HW_FLM_STAT_STA_DONE:
+ *value = be->flm.v20.sta_done->cnt;
+ break;
+ case HW_FLM_STAT_INF_DONE:
+ *value = be->flm.v20.inf_done->cnt;
+ break;
+ case HW_FLM_STAT_INF_SKIP:
+ *value = be->flm.v20.inf_skip->cnt;
+ break;
+ case HW_FLM_STAT_PCK_HIT:
+ *value = be->flm.v20.pck_hit->cnt;
+ break;
+ case HW_FLM_STAT_PCK_MISS:
+ *value = be->flm.v20.pck_miss->cnt;
+ break;
+ case HW_FLM_STAT_PCK_UNH:
+ *value = be->flm.v20.pck_unh->cnt;
+ break;
+ case HW_FLM_STAT_PCK_DIS:
+ *value = be->flm.v20.pck_dis->cnt;
+ break;
+ case HW_FLM_STAT_CSH_HIT:
+ *value = be->flm.v20.csh_hit->cnt;
+ break;
+ case HW_FLM_STAT_CSH_MISS:
+ *value = be->flm.v20.csh_miss->cnt;
+ break;
+ case HW_FLM_STAT_CSH_UNH:
+ *value = be->flm.v20.csh_unh->cnt;
+ break;
+ case HW_FLM_STAT_CUC_START:
+ *value = be->flm.v20.cuc_start->cnt;
+ break;
+ case HW_FLM_STAT_CUC_MOVE:
+ *value = be->flm.v20.cuc_move->cnt;
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ }
+ break;
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be,
+ enum hw_flm_e field, const uint32_t *value)
+{
+ int ret = 0;
+
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_FLOW_LRN_DATA_V17:
+ ret = be->iface->flm_lrn_data_flush(be->be_dev,
+ &be->flm, value,
+ sizeof(struct flm_v17_lrn_data_s) /
+ sizeof(uint32_t));
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return ret;
+}
+
+int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ uint32_t word_cnt)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_FLOW_INF_DATA_V17:
+ be->iface->flm_inf_data_update(be->be_dev, &be->flm,
+ value, word_cnt);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_FLOW_STA_DATA_V17:
+ be->iface->flm_sta_data_update(be->be_dev,
+ &be->flm, value,
+ sizeof(struct flm_v17_sta_data_s) /
+ sizeof(uint32_t));
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h
new file mode 100644
index 0000000000..311e39ba36
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_FLM_V17_H_
+#define _HW_MOD_FLM_V17_H_
+
+struct flm_v17_mbr_idx_overlay {
+ uint64_t a : 28;
+ uint64_t b : 28;
+ uint64_t pad : 4;
+};
+
+#define FLM_V17_MBR_ID1(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)(mbr_id_ptr))->a)
+#define FLM_V17_MBR_ID2(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)(mbr_id_ptr))->b)
+#define FLM_V17_MBR_ID3(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)((mbr_id_ptr) + 7))->a)
+#define FLM_V17_MBR_ID4(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)((mbr_id_ptr) + 7))->b)
+
+struct flm_v17_control_s {
+ uint32_t enable;
+ uint32_t init;
+ uint32_t lds;
+ uint32_t lfs;
+ uint32_t lis;
+ uint32_t uds;
+ uint32_t uis;
+ uint32_t rds;
+ uint32_t ris;
+ uint32_t pds;
+ uint32_t pis;
+ uint32_t crcwr;
+ uint32_t crcrd;
+ uint32_t rbl;
+ uint32_t eab;
+ uint32_t split_sdram_usage;
+};
+
+struct flm_v17_status_s {
+ uint32_t calibdone;
+ uint32_t initdone;
+ uint32_t idle;
+ uint32_t critical;
+ uint32_t panic;
+ uint32_t crcerr;
+ uint32_t eft_bp;
+};
+
+struct flm_v17_timeout_s {
+ uint32_t t;
+};
+
+struct flm_v17_scrub_s {
+ uint32_t i;
+};
+
+struct flm_v17_load_bin_s {
+ uint32_t bin;
+};
+
+struct flm_v17_load_pps_s {
+ uint32_t pps;
+};
+
+struct flm_v17_load_lps_s {
+ uint32_t lps;
+};
+
+struct flm_v17_load_aps_s {
+ uint32_t aps;
+};
+
+struct flm_v17_prio_s {
+ uint32_t limit0;
+ uint32_t ft0;
+ uint32_t limit1;
+ uint32_t ft1;
+ uint32_t limit2;
+ uint32_t ft2;
+ uint32_t limit3;
+ uint32_t ft3;
+};
+
+struct flm_v17_pst_s {
+ uint32_t bp;
+ uint32_t pp;
+ uint32_t tp;
+};
+
+struct flm_v17_rcp_s {
+ uint32_t lookup;
+ uint32_t qw0_dyn;
+ uint32_t qw0_ofs;
+ uint32_t qw0_sel;
+ uint32_t qw4_dyn;
+ uint32_t qw4_ofs;
+ uint32_t sw8_dyn;
+ uint32_t sw8_ofs;
+ uint32_t sw8_sel;
+ uint32_t sw9_dyn;
+ uint32_t sw9_ofs;
+ uint32_t mask[10];
+ uint32_t kid;
+ uint32_t opn;
+ uint32_t ipn;
+ uint32_t byt_dyn;
+ uint32_t byt_ofs;
+ uint32_t txplm;
+ uint32_t auto_ipv4_mask;
+};
+
+struct flm_v17_buf_ctrl_s {
+ uint32_t lrn_free;
+ uint32_t inf_avail;
+ uint32_t sta_avail;
+};
+
+#pragma pack(1)
+struct flm_v17_lrn_data_s {
+ uint32_t sw9; /* 31:0 (32) */
+ uint32_t sw8; /* 63:32 (32) */
+ uint32_t qw4[4]; /* 191:64 (128) */
+ uint32_t qw0[4]; /* 319:192 (128) */
+ uint8_t prot; /* 327:320 (8) */
+ uint8_t kid; /* 335:328 (8) */
+ uint32_t nat_ip; /* 367:336 (32) */
+ uint32_t teid; /* 399:368 (32) */
+ uint16_t nat_port; /* 415:400 (16) */
+ uint16_t rate; /* 431:416 (16) */
+ uint16_t size; /* 447:432 (16) */
+ uint32_t color; /* 479:448 (32) */
+ uint32_t adj; /* 511:480 (32) */
+ uint8_t id[9]; /* 583:512 (72) */
+ uint16_t fill : 12; /* 595:584 (12) */
+ uint16_t ft : 4; /* 599:596 (4) */
+ uint8_t ft_mbr : 4; /* 603:600 (4) */
+ uint8_t ft_miss : 4; /* 607:604 (5) */
+
+ /* 635:608, 663:636, 691:664, 719:692 (4 x 28) Get/set with macros FLM_V17_MBR_IDx */
+ uint8_t mbr_idx[14];
+ uint32_t vol_idx : 3; /* 722:720 (3) */
+ uint32_t stat_prof : 4; /* 726:723 (4) */
+ uint32_t prio : 2; /* 728:727 (2) */
+ uint32_t ent : 1; /* 729:729 (1) */
+ uint32_t op : 4; /* 733:730 (4) */
+ uint32_t dscp : 6; /* 739:734 (6) */
+ uint32_t qfi : 6; /* 745:740 (6) */
+ uint32_t rqi : 1; /* 746:746 (1) */
+ uint32_t nat_en : 1; /* 747:747 (1) */
+ uint32_t pad0 : 4; /* 751:748 (4) */
+ uint16_t pad1 : 15; /* 752:766 (15) */
+ uint16_t eor : 1; /* 767:767 (1) */
+};
+
+struct flm_v17_inf_data_s {
+ uint64_t bytes;
+ uint64_t packets;
+ uint64_t ts;
+ uint64_t id0; /* id0 and id1 results in a 72-bit int */
+ uint32_t id1 : 8;
+ uint32_t cause : 3;
+ uint32_t pad : 20;
+ uint32_t eor : 1;
+};
+
+struct flm_v17_sta_data_s {
+ uint64_t id0; /* id0 and id1 results in a 72-bit int */
+ uint32_t id1 : 8;
+ uint32_t lds : 1;
+ uint32_t lfs : 1;
+ uint32_t lis : 1;
+ uint32_t uds : 1;
+ uint32_t uis : 1;
+ uint32_t rds : 1;
+ uint32_t ris : 1;
+ uint32_t pds : 1;
+ uint32_t pis : 1;
+ uint32_t pad : 14;
+ uint32_t eor : 1;
+};
+
+#pragma pack()
+struct flm_v17_stat_lrn_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_lrn_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_lrn_fail_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_unl_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_unl_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_rel_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_rel_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_aul_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_aul_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_aul_fail_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_tul_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_flows_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_prb_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_prb_ignore_s {
+ uint32_t cnt;
+};
+
+struct hw_mod_flm_v17_s {
+ struct flm_v17_control_s *control;
+ struct flm_v17_status_s *status;
+ struct flm_v17_timeout_s *timeout;
+ struct flm_v17_scrub_s *scrub;
+ struct flm_v17_load_bin_s *load_bin;
+ struct flm_v17_load_pps_s *load_pps;
+ struct flm_v17_load_lps_s *load_lps;
+ struct flm_v17_load_aps_s *load_aps;
+ struct flm_v17_prio_s *prio;
+ struct flm_v17_pst_s *pst;
+ struct flm_v17_rcp_s *rcp;
+ struct flm_v17_buf_ctrl_s *buf_ctrl;
+ /* lrn_data is not handled by struct */
+ /* inf_data is not handled by struct */
+ /* sta_data is not handled by struct */
+ struct flm_v17_stat_lrn_done_s *lrn_done;
+ struct flm_v17_stat_lrn_ignore_s *lrn_ignore;
+ struct flm_v17_stat_lrn_fail_s *lrn_fail;
+ struct flm_v17_stat_unl_done_s *unl_done;
+ struct flm_v17_stat_unl_ignore_s *unl_ignore;
+ struct flm_v17_stat_rel_done_s *rel_done;
+ struct flm_v17_stat_rel_ignore_s *rel_ignore;
+ struct flm_v17_stat_aul_done_s *aul_done;
+ struct flm_v17_stat_aul_ignore_s *aul_ignore;
+ struct flm_v17_stat_aul_fail_s *aul_fail;
+ struct flm_v17_stat_tul_done_s *tul_done;
+ struct flm_v17_stat_flows_s *flows;
+ struct flm_v17_stat_prb_done_s *prb_done;
+ struct flm_v17_stat_prb_ignore_s *prb_ignore;
+};
+
+#endif /* _HW_MOD_FLM_V17_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h
new file mode 100644
index 0000000000..e33d4353c3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_FLM_V20_H_
+#define _HW_MOD_FLM_V20_H_
+
+struct flm_v20_stat_sta_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_inf_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_inf_skip_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_hit_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_miss_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_unh_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_dis_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_csh_hit_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_csh_miss_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_csh_unh_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_cuc_start_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_cuc_move_s {
+ uint32_t cnt;
+};
+
+struct hw_mod_flm_v20_s {
+ struct flm_v17_control_s *control;
+ struct flm_v17_status_s *status;
+ struct flm_v17_timeout_s *timeout;
+ struct flm_v17_scrub_s *scrub;
+ struct flm_v17_load_bin_s *load_bin;
+ struct flm_v17_load_pps_s *load_pps;
+ struct flm_v17_load_lps_s *load_lps;
+ struct flm_v17_load_aps_s *load_aps;
+ struct flm_v17_prio_s *prio;
+ struct flm_v17_pst_s *pst;
+ struct flm_v17_rcp_s *rcp;
+ struct flm_v17_buf_ctrl_s *buf_ctrl;
+ /*
+ * lrn_data is not handled by struct
+ * inf_data is not handled by struct
+ * sta_data is not handled by struct
+ */
+ struct flm_v17_stat_lrn_done_s *lrn_done;
+ struct flm_v17_stat_lrn_ignore_s *lrn_ignore;
+ struct flm_v17_stat_lrn_fail_s *lrn_fail;
+ struct flm_v17_stat_unl_done_s *unl_done;
+ struct flm_v17_stat_unl_ignore_s *unl_ignore;
+ struct flm_v17_stat_rel_done_s *rel_done;
+ struct flm_v17_stat_rel_ignore_s *rel_ignore;
+ struct flm_v17_stat_aul_done_s *aul_done;
+ struct flm_v17_stat_aul_ignore_s *aul_ignore;
+ struct flm_v17_stat_aul_fail_s *aul_fail;
+ struct flm_v17_stat_tul_done_s *tul_done;
+ struct flm_v17_stat_flows_s *flows;
+ struct flm_v17_stat_prb_done_s *prb_done;
+ struct flm_v17_stat_prb_ignore_s *prb_ignore;
+ struct flm_v20_stat_sta_done_s *sta_done;
+ struct flm_v20_stat_inf_done_s *inf_done;
+ struct flm_v20_stat_inf_skip_s *inf_skip;
+ struct flm_v20_stat_pck_hit_s *pck_hit;
+ struct flm_v20_stat_pck_miss_s *pck_miss;
+ struct flm_v20_stat_pck_unh_s *pck_unh;
+ struct flm_v20_stat_pck_dis_s *pck_dis;
+ struct flm_v20_stat_csh_hit_s *csh_hit;
+ struct flm_v20_stat_csh_miss_s *csh_miss;
+ struct flm_v20_stat_csh_unh_s *csh_unh;
+ struct flm_v20_stat_cuc_start_s *cuc_start;
+ struct flm_v20_stat_cuc_move_s *cuc_move;
+};
+
+#endif /* _HW_MOD_FLM_V20_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c
new file mode 100644
index 0000000000..1b8896d5c2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "HSH"
+#define _VER_ be->hsh.ver
+
+#define HSH_RCP_ENTRIES_V4 16
+#define HSH_RCP_ENTRIES_V5 32
+#define HSH_RCP_MAC_PORT_MASK_SIZE 4
+#define HSH_RCP_WORD_MASK_SIZE 10
+
+bool hw_mod_hsh_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_hsh_present(be->be_dev);
+}
+
+int hw_mod_hsh_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_hsh_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "HSH MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 5:
+ be->hsh.nb_rcp = HSH_RCP_ENTRIES_V5;
+ if (!callocate_mod(CAST_COMMON(&be->hsh), 1,
+ &be->hsh.v5.rcp,
+ be->hsh.nb_rcp,
+ sizeof(struct hsh_v5_rcp_s)))
+ return -1;
+ break;
+ /* end case 5 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_hsh_free(struct flow_api_backend_s *be)
+{
+ if (be->hsh.base) {
+ free(be->hsh.base);
+ be->hsh.base = NULL;
+ }
+}
+
+int hw_mod_hsh_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->hsh);
+
+ NT_LOG(DBG, FILTER, "INIT HSH RCP\n");
+ return hw_mod_hsh_rcp_flush(be, 0, be->hsh.nb_rcp);
+}
+
+int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->hsh.nb_rcp;
+ if ((start_idx + count) > (int)be->hsh.nb_rcp)
+ return error_index_too_large(__func__);
+ return be->iface->hsh_rcp_flush(be->be_dev, &be->hsh, start_idx, count);
+}
+
+static int hw_mod_hsh_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_hsh_e field, uint32_t index,
+ uint32_t word_off, uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->hsh.nb_rcp)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 5:
+ switch (field) {
+ case HW_HSH_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->hsh.v5.rcp[index], (uint8_t)*value,
+ sizeof(struct hsh_v5_rcp_s));
+ break;
+ case HW_HSH_RCP_COMPARE:
+ rv = do_compare_indexes(be->hsh.v5.rcp,
+ sizeof(struct hsh_v5_rcp_s), index, word_off,
+ be->hsh.nb_rcp, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HSH_RCP_FIND:
+ rv = find_equal_index(be->hsh.v5.rcp,
+ sizeof(struct hsh_v5_rcp_s), index, word_off,
+ be->hsh.nb_rcp, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HSH_RCP_LOAD_DIST_TYPE:
+ get_set(&be->hsh.v5.rcp[index].load_dist_type, value, get);
+ break;
+ case HW_HSH_RCP_MAC_PORT_MASK:
+ if (word_off > HSH_RCP_MAC_PORT_MASK_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->hsh.v5.rcp[index].mac_port_mask[word_off],
+ value, get);
+ break;
+ case HW_HSH_RCP_SORT:
+ get_set(&be->hsh.v5.rcp[index].sort, value, get);
+ break;
+ case HW_HSH_RCP_QW0_PE:
+ get_set(&be->hsh.v5.rcp[index].qw0_pe, value, get);
+ break;
+ case HW_HSH_RCP_QW0_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].qw0_ofs, value, get);
+ break;
+ case HW_HSH_RCP_QW4_PE:
+ get_set(&be->hsh.v5.rcp[index].qw4_pe, value, get);
+ break;
+ case HW_HSH_RCP_QW4_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].qw4_ofs, value, get);
+ break;
+ case HW_HSH_RCP_W8_PE:
+ get_set(&be->hsh.v5.rcp[index].w8_pe, value, get);
+ break;
+ case HW_HSH_RCP_W8_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].w8_ofs, value, get);
+ break;
+ case HW_HSH_RCP_W8_SORT:
+ get_set(&be->hsh.v5.rcp[index].w8_sort, value, get);
+ break;
+ case HW_HSH_RCP_W9_PE:
+ get_set(&be->hsh.v5.rcp[index].w9_pe, value, get);
+ break;
+ case HW_HSH_RCP_W9_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].w9_ofs, value, get);
+ break;
+ case HW_HSH_RCP_W9_SORT:
+ get_set(&be->hsh.v5.rcp[index].w9_sort, value, get);
+ break;
+ case HW_HSH_RCP_W9_P:
+ get_set(&be->hsh.v5.rcp[index].w9_p, value, get);
+ break;
+ case HW_HSH_RCP_P_MASK:
+ get_set(&be->hsh.v5.rcp[index].p_mask, value, get);
+ break;
+ case HW_HSH_RCP_WORD_MASK:
+ if (word_off > HSH_RCP_WORD_MASK_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->hsh.v5.rcp[index].word_mask[word_off],
+ value, get);
+ break;
+ case HW_HSH_RCP_SEED:
+ get_set(&be->hsh.v5.rcp[index].seed, value, get);
+ break;
+ case HW_HSH_RCP_TNL_P:
+ get_set(&be->hsh.v5.rcp[index].tnl_p, value, get);
+ break;
+ case HW_HSH_RCP_HSH_VALID:
+ get_set(&be->hsh.v5.rcp[index].hsh_valid, value, get);
+ break;
+ case HW_HSH_RCP_HSH_TYPE:
+ get_set(&be->hsh.v5.rcp[index].hsh_type, value, get);
+ break;
+ case HW_HSH_RCP_AUTO_IPV4_MASK:
+ get_set(&be->hsh.v5.rcp[index].auto_ipv4_mask, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 5 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t value)
+{
+ return hw_mod_hsh_rcp_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value)
+{
+ return hw_mod_hsh_rcp_mod(be, field, index, word_off, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h
new file mode 100644
index 0000000000..8588750ff0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_HSH_V5_H_
+#define _HW_MOD_HSH_V5_H_
+
+struct hsh_v5_rcp_s {
+ uint32_t load_dist_type;
+ uint32_t mac_port_mask[4];
+ uint32_t sort;
+ uint32_t qw0_pe;
+ int32_t qw0_ofs;
+ uint32_t qw4_pe;
+ int32_t qw4_ofs;
+ uint32_t w8_pe;
+ int32_t w8_ofs;
+ uint32_t w8_sort;
+ uint32_t w9_pe;
+ int32_t w9_ofs;
+ uint32_t w9_sort;
+ uint32_t w9_p;
+ uint32_t p_mask;
+ uint32_t word_mask[10];
+ uint32_t seed;
+ uint32_t tnl_p;
+ uint32_t hsh_valid;
+ uint32_t hsh_type;
+ uint32_t auto_ipv4_mask;
+};
+
+struct hw_mod_hsh_v5_s {
+ struct hsh_v5_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_HSH_V5_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c
new file mode 100644
index 0000000000..751c7b3ffe
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "HST"
+#define _VER_ be->hst.ver
+
+bool hw_mod_hst_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_hst_present(be->be_dev);
+}
+
+int hw_mod_hst_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_hst_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "HST MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_hst_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "hst_categories", _MOD_, _VER_);
+ be->hst.nb_hst_rcp_categories = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 2:
+ if (!callocate_mod(CAST_COMMON(&be->hst), 1,
+ &be->hst.v2.rcp,
+ be->hst.nb_hst_rcp_categories,
+ sizeof(struct hst_v2_rcp_s)))
+ return -1;
+ break;
+ /* end case 2 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_hst_free(struct flow_api_backend_s *be)
+{
+ if (be->hst.base) {
+ free(be->hst.base);
+ be->hst.base = NULL;
+ }
+}
+
+int hw_mod_hst_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->hst);
+
+ NT_LOG(DBG, FILTER, "INIT HST RCP\n");
+ return hw_mod_hst_rcp_flush(be, 0, ALL_ENTRIES);
+}
+
+int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->hst.nb_hst_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->hst.nb_hst_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->hst_rcp_flush(be->be_dev, &be->hst, start_idx, count);
+}
+
+static int hw_mod_hst_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_hst_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->hst.nb_hst_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_HST_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->hst.v2.rcp[index], (uint8_t)*value,
+ sizeof(struct hst_v2_rcp_s));
+ break;
+ case HW_HST_RCP_FIND:
+ find_equal_index(be->hst.v2.rcp,
+ sizeof(struct hst_v2_rcp_s), index, *value,
+ be->hst.nb_hst_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HST_RCP_COMPARE:
+ rv = do_compare_indexes(be->hst.v2.rcp,
+ sizeof(struct hst_v2_rcp_s), index, *value,
+ be->hst.nb_hst_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HST_RCP_STRIP_MODE:
+ get_set(&be->hst.v2.rcp[index].strip_mode, value, get);
+ break;
+ case HW_HST_RCP_START_DYN:
+ get_set(&be->hst.v2.rcp[index].start_dyn, value, get);
+ break;
+ case HW_HST_RCP_START_OFS:
+ get_set(&be->hst.v2.rcp[index].start_ofs, value, get);
+ break;
+ case HW_HST_RCP_END_DYN:
+ get_set(&be->hst.v2.rcp[index].end_dyn, value, get);
+ break;
+ case HW_HST_RCP_END_OFS:
+ get_set(&be->hst.v2.rcp[index].end_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_CMD:
+ get_set(&be->hst.v2.rcp[index].modif0_cmd, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_DYN:
+ get_set(&be->hst.v2.rcp[index].modif0_dyn, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_OFS:
+ get_set(&be->hst.v2.rcp[index].modif0_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_VALUE:
+ get_set(&be->hst.v2.rcp[index].modif0_value, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_CMD:
+ get_set(&be->hst.v2.rcp[index].modif1_cmd, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_DYN:
+ get_set(&be->hst.v2.rcp[index].modif1_dyn, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_OFS:
+ get_set(&be->hst.v2.rcp[index].modif1_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_VALUE:
+ get_set(&be->hst.v2.rcp[index].modif1_value, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_CMD:
+ get_set(&be->hst.v2.rcp[index].modif2_cmd, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_DYN:
+ get_set(&be->hst.v2.rcp[index].modif2_dyn, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_OFS:
+ get_set(&be->hst.v2.rcp[index].modif2_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_VALUE:
+ get_set(&be->hst.v2.rcp[index].modif2_value, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 2 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_hst_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_hst_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h
new file mode 100644
index 0000000000..230c70b56d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_HST_V2_H_
+#define _HW_MOD_HST_V2_H_
+
+struct hst_v2_rcp_s {
+ uint32_t strip_mode;
+ uint32_t start_dyn;
+ uint32_t start_ofs;
+ uint32_t end_dyn;
+ uint32_t end_ofs;
+ uint32_t modif0_cmd;
+ uint32_t modif0_dyn;
+ uint32_t modif0_ofs;
+ uint32_t modif0_value;
+ uint32_t modif1_cmd;
+ uint32_t modif1_dyn;
+ uint32_t modif1_ofs;
+ uint32_t modif1_value;
+ uint32_t modif2_cmd;
+ uint32_t modif2_dyn;
+ uint32_t modif2_ofs;
+ uint32_t modif2_value;
+};
+
+struct hw_mod_hst_v2_s {
+ struct hst_v2_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_HST_V2_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c
new file mode 100644
index 0000000000..c8e3593637
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "IOA"
+#define _VER_ be->ioa.ver
+
+bool hw_mod_ioa_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_ioa_present(be->be_dev);
+}
+
+int hw_mod_ioa_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_ioa_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "IOA MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ int nb = be->iface->get_nb_ioa_categories(be->be_dev);
+
+ if (nb <= 0)
+ return error_resource_count(__func__, "ioa_categories", _MOD_, _VER_);
+ be->ioa.nb_rcp_categories = (uint32_t)nb;
+
+ /* NOTE: ROA number of categories are called here. FPGA uses a cross-indexing here - bad! */
+ nb = be->iface->get_nb_roa_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "roa_epp_entries", _MOD_, _VER_);
+ be->ioa.nb_roa_epp_entries = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 4:
+ if (!callocate_mod(CAST_COMMON(&be->ioa), 3,
+ &be->ioa.v4.rcp, be->ioa.nb_rcp_categories,
+ sizeof(struct ioa_v4_rcp_s),
+ &be->ioa.v4.tpid, 1,
+ sizeof(struct ioa_v4_special_tpid_s),
+ &be->ioa.v4.roa_epp, be->ioa.nb_roa_epp_entries,
+ sizeof(struct ioa_v4_roa_epp_s)))
+ return -1;
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_ioa_free(struct flow_api_backend_s *be)
+{
+ if (be->ioa.base) {
+ free(be->ioa.base);
+ be->ioa.base = NULL;
+ }
+}
+
+int hw_mod_ioa_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->ioa);
+
+ NT_LOG(DBG, FILTER, "INIT IOA RCP\n");
+ hw_mod_ioa_rcp_flush(be, 0, ALL_ENTRIES);
+ NT_LOG(DBG, FILTER, "INIT IOA SPECIAL TPID\n");
+ hw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_0, 0x8200);
+ hw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_1, 0x8300);
+ hw_mod_ioa_config_flush(be);
+ NT_LOG(DBG, FILTER, "INIT IOA ROA EPP\n");
+ hw_mod_ioa_roa_epp_flush(be, 0, ALL_ENTRIES);
+ return 0;
+}
+
+int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->ioa.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->ioa.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->ioa_rcp_flush(be->be_dev, &be->ioa, start_idx, count);
+}
+
+static int hw_mod_ioa_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_ioa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->ioa.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 4:
+ switch (field) {
+ case HW_IOA_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->ioa.v4.rcp[index], (uint8_t)*value,
+ sizeof(struct ioa_v4_rcp_s));
+ break;
+ case HW_IOA_RCP_FIND:
+ rv = find_equal_index(be->ioa.v4.rcp,
+ sizeof(struct ioa_v4_rcp_s), index, *value,
+ be->ioa.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_RCP_COMPARE:
+ rv = do_compare_indexes(be->ioa.v4.rcp,
+ sizeof(struct ioa_v4_rcp_s), index, *value,
+ be->ioa.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_RCP_TUNNEL_POP:
+ get_set(&be->ioa.v4.rcp[index].tunnel_pop, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_POP:
+ get_set(&be->ioa.v4.rcp[index].vlan_pop, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_PUSH:
+ get_set(&be->ioa.v4.rcp[index].vlan_push, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_VID:
+ get_set(&be->ioa.v4.rcp[index].vlan_vid, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_DEI:
+ get_set(&be->ioa.v4.rcp[index].vlan_dei, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_PCP:
+ get_set(&be->ioa.v4.rcp[index].vlan_pcp, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_TPID_SEL:
+ get_set(&be->ioa.v4.rcp[index].vlan_tpid_sel, value, get);
+ break;
+ case HW_IOA_RCP_QUEUE_OVERRIDE_EN:
+ get_set(&be->ioa.v4.rcp[index].queue_override_en, value, get);
+ break;
+ case HW_IOA_RCP_QUEUE_ID:
+ get_set(&be->ioa.v4.rcp[index].queue_id, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_ioa_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_ioa_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_ioa_config_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->ioa_special_tpid_flush(be->be_dev, &be->ioa);
+}
+
+int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t value)
+{
+ switch (_VER_) {
+ case 4:
+ switch (field) {
+ case HW_IOA_CONFIG_CUST_TPID_0:
+ be->ioa.v4.tpid->cust_tpid_0 = value;
+ break;
+ case HW_IOA_CONFIG_CUST_TPID_1:
+ be->ioa.v4.tpid->cust_tpid_1 = value;
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->ioa.nb_roa_epp_entries;
+ if ((unsigned int)(start_idx + count) > be->ioa.nb_roa_epp_entries)
+ return error_index_too_large(__func__);
+ return be->iface->ioa_roa_epp_flush(be->be_dev, &be->ioa, start_idx,
+ count);
+}
+
+static int hw_mod_ioa_roa_epp_mod(struct flow_api_backend_s *be,
+ enum hw_ioa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->ioa.nb_roa_epp_entries)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 4:
+ switch (field) {
+ case HW_IOA_ROA_EPP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->ioa.v4.roa_epp[index], (uint8_t)*value,
+ sizeof(struct ioa_v4_roa_epp_s));
+ break;
+ case HW_IOA_ROA_EPP_FIND:
+ rv = find_equal_index(be->ioa.v4.roa_epp,
+ sizeof(struct ioa_v4_roa_epp_s), index, *value,
+ be->ioa.nb_roa_epp_entries, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_ROA_EPP_COMPARE:
+ rv = do_compare_indexes(be->ioa.v4.roa_epp,
+ sizeof(struct ioa_v4_roa_epp_s), index, *value,
+ be->ioa.nb_roa_epp_entries, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_ROA_EPP_PUSH_TUNNEL:
+ get_set(&be->ioa.v4.roa_epp[index].push_tunnel, value, get);
+ break;
+ case HW_IOA_ROA_EPP_TX_PORT:
+ get_set(&be->ioa.v4.roa_epp[index].tx_port, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_ioa_roa_epp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_ioa_roa_epp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h
new file mode 100644
index 0000000000..309b53ff76
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_IOA_V4_H_
+#define _HW_MOD_IOA_V4_H_
+
+struct ioa_v4_rcp_s {
+ uint32_t tunnel_pop;
+ uint32_t vlan_pop;
+ uint32_t vlan_push;
+ uint32_t vlan_vid;
+ uint32_t vlan_dei;
+ uint32_t vlan_pcp;
+ uint32_t vlan_tpid_sel;
+ uint32_t queue_override_en;
+ uint32_t queue_id;
+};
+
+struct ioa_v4_special_tpid_s {
+ uint32_t cust_tpid_0;
+ uint32_t cust_tpid_1;
+};
+
+struct ioa_v4_roa_epp_s {
+ uint32_t push_tunnel;
+ uint32_t tx_port;
+};
+
+struct hw_mod_ioa_v4_s {
+ struct ioa_v4_rcp_s *rcp;
+ struct ioa_v4_special_tpid_s *tpid;
+ struct ioa_v4_roa_epp_s *roa_epp;
+};
+
+#endif /* _HW_MOD_IOA_V4_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c
new file mode 100644
index 0000000000..a91f0e0a7d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c
@@ -0,0 +1,629 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "KM"
+#define _VER_ be->km.ver
+
+#define KM_TCQ_ENTRIES 2048
+#define KM_RCP_MASK_A_SIZE 11
+#define KM_RCP_MASK_D_A_SIZE \
+ 12 /* Mask for double size word extractors for DW8/DW10 */
+#define KM_RCP_MASK_B_SIZE 6
+
+bool hw_mod_km_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_km_present(be->be_dev);
+}
+
+int hw_mod_km_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_km_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "KM MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_km_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "km_categories", _MOD_, _VER_);
+ be->km.nb_categories = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_cam_banks(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "cam_banks", _MOD_, _VER_);
+ be->km.nb_cam_banks = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_cam_records(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "cam_records", _MOD_, _VER_);
+ be->km.nb_cam_records = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_cam_record_words(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "cam_record_words", _MOD_, _VER_);
+ be->km.nb_cam_record_words = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_tcam_banks(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tcam_banks", _MOD_, _VER_);
+ be->km.nb_tcam_banks = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_tcam_bank_width(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tcam_bank_width", _MOD_, _VER_);
+ be->km.nb_tcam_bank_width = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 7:
+ be->km.nb_km_rcp_mask_a_word_size = 12;
+ be->km.nb_km_rcp_mask_b_word_size = 6;
+ if (!callocate_mod(CAST_COMMON(&be->km), 5,
+ &be->km.v7.rcp,
+ be->km.nb_categories,
+ sizeof(struct km_v7_rcp_s),
+ &be->km.v7.cam,
+ be->km.nb_cam_banks * be->km.nb_cam_records,
+ sizeof(struct km_v7_cam_s),
+ &be->km.v7.tcam,
+ be->km.nb_tcam_banks * 4 * 256,
+ sizeof(struct km_v7_tcam_s),
+ &be->km.v7.tci,
+ be->km.nb_tcam_banks * be->km.nb_tcam_bank_width,
+ sizeof(struct km_v7_tci_s),
+ &be->km.v7.tcq,
+ KM_TCQ_ENTRIES,
+ sizeof(struct km_v7_tcq_s)))
+ return -1;
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_km_free(struct flow_api_backend_s *be)
+{
+ if (be->km.base) {
+ free(be->km.base);
+ be->km.base = NULL;
+ }
+}
+
+int hw_mod_km_reset(struct flow_api_backend_s *be)
+{
+ uint32_t tcam_v_set[3] = { 0x00000000, 0x00000000, 0x00000000 };
+ /* int err = 0; */
+
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->km);
+
+ NT_LOG(DBG, FILTER, "INIT KM RCP\n");
+ hw_mod_km_rcp_flush(be, 0, ALL_ENTRIES);
+
+ /* init CAM - all zero */
+ NT_LOG(DBG, FILTER, "INIT KM CAM\n");
+ hw_mod_km_cam_flush(be, 0, 0, ALL_ENTRIES);
+
+ /* init TCAM - all zero */
+ NT_LOG(DBG, FILTER, "INIT KM TCAM\n");
+ for (unsigned int i = 0; i < be->km.nb_tcam_banks; i++) {
+ /*
+ * TCAM entries are cache controlled, thus need to hard reset initially to sync
+ * cache with HW
+ */
+ hw_mod_km_tcam_set(be, HW_KM_TCAM_BANK_RESET, i, 0, 0,
+ tcam_v_set);
+ }
+ hw_mod_km_tcam_flush(be, 0, ALL_ENTRIES);
+
+ /* init TCI - all zero */
+ NT_LOG(DBG, FILTER, "INIT KM TCI\n");
+ hw_mod_km_tci_flush(be, 0, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT KM TCQ\n");
+ for (unsigned int i = 0; i < be->km.nb_tcam_bank_width; i++)
+ hw_mod_km_tcq_flush(be, 0, i, be->km.nb_tcam_banks);
+
+ return 0;
+}
+
+int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_categories;
+ if ((unsigned int)(start_idx + count) > be->km.nb_categories)
+ return error_index_too_large(__func__);
+ return be->iface->km_rcp_flush(be->be_dev, &be->km, start_idx, count);
+}
+
+static int hw_mod_km_rcp_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t *value, int get)
+{
+ if ((unsigned int)index >= be->km.nb_categories)
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->km.v7.rcp[index], (uint8_t)*value,
+ sizeof(struct km_v7_rcp_s));
+ break;
+ case HW_KM_RCP_QW0_DYN:
+ get_set(&be->km.v7.rcp[index].qw0_dyn, value, get);
+ break;
+ case HW_KM_RCP_QW0_OFS:
+ get_set_signed(&be->km.v7.rcp[index].qw0_ofs, value, get);
+ break;
+ case HW_KM_RCP_QW0_SEL_A:
+ get_set(&be->km.v7.rcp[index].qw0_sel_a, value, get);
+ break;
+ case HW_KM_RCP_QW0_SEL_B:
+ get_set(&be->km.v7.rcp[index].qw0_sel_b, value, get);
+ break;
+ case HW_KM_RCP_QW4_DYN:
+ get_set(&be->km.v7.rcp[index].qw4_dyn, value, get);
+ break;
+ case HW_KM_RCP_QW4_OFS:
+ get_set_signed(&be->km.v7.rcp[index].qw4_ofs, value, get);
+ break;
+ case HW_KM_RCP_QW4_SEL_A:
+ get_set(&be->km.v7.rcp[index].qw4_sel_a, value, get);
+ break;
+ case HW_KM_RCP_QW4_SEL_B:
+ get_set(&be->km.v7.rcp[index].qw4_sel_b, value, get);
+ break;
+ case HW_KM_RCP_DW8_DYN:
+ get_set(&be->km.v7.rcp[index].dw8_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW8_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw8_ofs, value, get);
+ break;
+ case HW_KM_RCP_DW8_SEL_A:
+ get_set(&be->km.v7.rcp[index].dw8_sel_a, value, get);
+ break;
+ case HW_KM_RCP_DW8_SEL_B:
+ get_set(&be->km.v7.rcp[index].dw8_sel_b, value, get);
+ break;
+ case HW_KM_RCP_DW10_DYN:
+ get_set(&be->km.v7.rcp[index].dw10_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW10_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw10_ofs, value, get);
+ break;
+ case HW_KM_RCP_DW10_SEL_A:
+ get_set(&be->km.v7.rcp[index].dw10_sel_a, value, get);
+ break;
+ case HW_KM_RCP_DW10_SEL_B:
+ get_set(&be->km.v7.rcp[index].dw10_sel_b, value, get);
+ break;
+ case HW_KM_RCP_SWX_CCH:
+ get_set(&be->km.v7.rcp[index].swx_cch, value, get);
+ break;
+ case HW_KM_RCP_SWX_SEL_A:
+ get_set(&be->km.v7.rcp[index].swx_sel_a, value, get);
+ break;
+ case HW_KM_RCP_SWX_SEL_B:
+ get_set(&be->km.v7.rcp[index].swx_sel_b, value, get);
+ break;
+ case HW_KM_RCP_MASK_A:
+ if (word_off > KM_RCP_MASK_D_A_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->km.v7.rcp[index].mask_d_a[word_off], value, get);
+ break;
+ case HW_KM_RCP_MASK_B:
+ if (word_off > KM_RCP_MASK_B_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->km.v7.rcp[index].mask_b[word_off], value, get);
+ break;
+ case HW_KM_RCP_DUAL:
+ get_set(&be->km.v7.rcp[index].dual, value, get);
+ break;
+ case HW_KM_RCP_PAIRED:
+ get_set(&be->km.v7.rcp[index].paired, value, get);
+ break;
+ case HW_KM_RCP_EL_A:
+ get_set(&be->km.v7.rcp[index].el_a, value, get);
+ break;
+ case HW_KM_RCP_EL_B:
+ get_set(&be->km.v7.rcp[index].el_b, value, get);
+ break;
+ case HW_KM_RCP_INFO_A:
+ get_set(&be->km.v7.rcp[index].info_a, value, get);
+ break;
+ case HW_KM_RCP_INFO_B:
+ get_set(&be->km.v7.rcp[index].info_b, value, get);
+ break;
+ case HW_KM_RCP_FTM_A:
+ get_set(&be->km.v7.rcp[index].ftm_a, value, get);
+ break;
+ case HW_KM_RCP_FTM_B:
+ get_set(&be->km.v7.rcp[index].ftm_b, value, get);
+ break;
+ case HW_KM_RCP_BANK_A:
+ get_set(&be->km.v7.rcp[index].bank_a, value, get);
+ break;
+ case HW_KM_RCP_BANK_B:
+ get_set(&be->km.v7.rcp[index].bank_b, value, get);
+ break;
+ case HW_KM_RCP_KL_A:
+ get_set(&be->km.v7.rcp[index].kl_a, value, get);
+ break;
+ case HW_KM_RCP_KL_B:
+ get_set(&be->km.v7.rcp[index].kl_b, value, get);
+ break;
+ case HW_KM_RCP_KEYWAY_A:
+ get_set(&be->km.v7.rcp[index].keyway_a, value, get);
+ break;
+ case HW_KM_RCP_KEYWAY_B:
+ get_set(&be->km.v7.rcp[index].keyway_b, value, get);
+ break;
+ case HW_KM_RCP_SYNERGY_MODE:
+ get_set(&be->km.v7.rcp[index].synergy_mode, value, get);
+ break;
+ case HW_KM_RCP_DW0_B_DYN:
+ get_set(&be->km.v7.rcp[index].dw0_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW0_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw0_b_ofs, value, get);
+ break;
+ case HW_KM_RCP_DW2_B_DYN:
+ get_set(&be->km.v7.rcp[index].dw2_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW2_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw2_b_ofs, value, get);
+ break;
+ case HW_KM_RCP_SW4_B_DYN:
+ get_set(&be->km.v7.rcp[index].sw4_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_SW4_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].sw4_b_ofs, value, get);
+ break;
+ case HW_KM_RCP_SW5_B_DYN:
+ get_set(&be->km.v7.rcp[index].sw5_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_SW5_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].sw5_b_ofs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t value)
+{
+ return hw_mod_km_rcp_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t *value)
+{
+ return hw_mod_km_rcp_mod(be, field, index, word_off, value, 1);
+}
+
+int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_cam_records * be->km.nb_cam_banks;
+
+ unsigned int end =
+ start_bank * be->km.nb_cam_records + start_record + count;
+ if (end > (be->km.nb_cam_banks * be->km.nb_cam_records))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_cam_flush(be->be_dev, &be->km, start_bank,
+ start_record, count);
+}
+
+static int hw_mod_km_cam_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value, int get)
+{
+ if ((unsigned int)bank >= be->km.nb_cam_banks)
+ return error_index_too_large(__func__);
+ if ((unsigned int)record >= be->km.nb_cam_records)
+ return error_index_too_large(__func__);
+
+ unsigned int index = bank * be->km.nb_cam_records + record;
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_CAM_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->km.v7.cam[index], (uint8_t)*value,
+ sizeof(struct km_v7_cam_s));
+ break;
+ case HW_KM_CAM_W0:
+ get_set(&be->km.v7.cam[index].w0, value, get);
+ break;
+ case HW_KM_CAM_W1:
+ get_set(&be->km.v7.cam[index].w1, value, get);
+ break;
+ case HW_KM_CAM_W2:
+ get_set(&be->km.v7.cam[index].w2, value, get);
+ break;
+ case HW_KM_CAM_W3:
+ get_set(&be->km.v7.cam[index].w3, value, get);
+ break;
+ case HW_KM_CAM_W4:
+ get_set(&be->km.v7.cam[index].w4, value, get);
+ break;
+ case HW_KM_CAM_W5:
+ get_set(&be->km.v7.cam[index].w5, value, get);
+ break;
+ case HW_KM_CAM_FT0:
+ get_set(&be->km.v7.cam[index].ft0, value, get);
+ break;
+ case HW_KM_CAM_FT1:
+ get_set(&be->km.v7.cam[index].ft1, value, get);
+ break;
+ case HW_KM_CAM_FT2:
+ get_set(&be->km.v7.cam[index].ft2, value, get);
+ break;
+ case HW_KM_CAM_FT3:
+ get_set(&be->km.v7.cam[index].ft3, value, get);
+ break;
+ case HW_KM_CAM_FT4:
+ get_set(&be->km.v7.cam[index].ft4, value, get);
+ break;
+ case HW_KM_CAM_FT5:
+ get_set(&be->km.v7.cam[index].ft5, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value)
+{
+ return hw_mod_km_cam_mod(be, field, bank, record, &value, 0);
+}
+
+int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_cam_mod(be, field, bank, record, value, 1);
+}
+
+int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_tcam_banks * 4 * 256;
+ else if (count == ALL_BANK_ENTRIES)
+ count = 4 * 256;
+
+ unsigned int end = start_bank * 4 * 256 + count;
+
+ if (end > (be->km.nb_tcam_banks * 4 * 256))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_tcam_flush(be->be_dev, &be->km, start_bank, 0, 0,
+ count);
+}
+
+static int hw_mod_km_tcam_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val,
+ uint32_t *value_set, int get)
+{
+ unsigned int start_index = bank * 4 * 256 + (int)byte * 256 + byte_val;
+
+ if (start_index >= (be->km.nb_tcam_banks * 4 * 256))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_TCAM_BANK_RESET:
+ if (get)
+ return error_unsup_field(__func__);
+ {
+ int start_idx = bank * 4 * 256;
+
+ for (int i = 0; i < 4 * 256; i++) {
+ be->km.v7.tcam[start_idx + i].t[0] =
+ value_set[0];
+ be->km.v7.tcam[start_idx + i].t[1] =
+ value_set[1];
+ be->km.v7.tcam[start_idx + i].t[2] =
+ value_set[2];
+ be->km.v7.tcam[start_idx + i].dirty = 1;
+ }
+ }
+ break;
+ case HW_KM_TCAM_T: {
+ int index = bank * 4 * 256 + byte * 256 + byte_val;
+
+ if (get) {
+ value_set[0] = be->km.v7.tcam[index].t[0];
+ value_set[1] = be->km.v7.tcam[index].t[1];
+ value_set[2] = be->km.v7.tcam[index].t[2];
+ } else {
+ /* only change if any bits has to be changed */
+ if (be->km.v7.tcam[index].t[0] !=
+ value_set[0] ||
+ be->km.v7.tcam[index].t[1] !=
+ value_set[1] ||
+ be->km.v7.tcam[index].t[2] !=
+ value_set[2]) {
+ be->km.v7.tcam[index].t[0] =
+ value_set[0];
+ be->km.v7.tcam[index].t[1] =
+ value_set[1];
+ be->km.v7.tcam[index].t[2] =
+ value_set[2];
+ be->km.v7.tcam[index].dirty = 1;
+ }
+ }
+ }
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set)
+{
+ return hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set,
+ 0);
+}
+
+int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set)
+{
+ return hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set,
+ 1);
+}
+
+int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width;
+
+ unsigned int end = (int)start_bank * be->km.nb_tcam_bank_width +
+ start_record + count;
+
+ if (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_tci_flush(be->be_dev, &be->km, start_bank,
+ start_record, count);
+}
+
+static int hw_mod_km_tci_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value, int get)
+{
+ unsigned int index = bank * be->km.nb_tcam_bank_width + record;
+
+ if (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_TCI_COLOR:
+ get_set(&be->km.v7.tci[index].color, value, get);
+ break;
+ case HW_KM_TCI_FT:
+ get_set(&be->km.v7.tci[index].ft, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value)
+{
+ return hw_mod_km_tci_mod(be, field, bank, record, &value, 0);
+}
+
+int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_tci_mod(be, field, bank, record, value, 1);
+}
+
+int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width;
+
+ unsigned int end = (int)start_bank * be->km.nb_tcam_bank_width +
+ start_record + count;
+
+ if (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_tcq_flush(be->be_dev, &be->km, start_bank,
+ start_record, count);
+}
+
+static int hw_mod_km_tcq_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value, int get)
+{
+ unsigned int index = bank * be->km.nb_tcam_bank_width + record;
+
+ if (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_TCQ_BANK_MASK:
+ get_set(&be->km.v7.tcq[index].bank_mask, value, get);
+ break;
+ case HW_KM_TCQ_QUAL:
+ get_set(&be->km.v7.tcq[index].qual, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_tcq_mod(be, field, bank, record, value, 0);
+}
+
+int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_tcq_mod(be, field, bank, record, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h
new file mode 100644
index 0000000000..798a175609
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_KM_V7_H_
+#define _HW_MOD_KM_V7_H_
+
+struct km_v7_rcp_s {
+ uint32_t qw0_dyn;
+ int32_t qw0_ofs;
+ uint32_t qw0_sel_a;
+ uint32_t qw0_sel_b;
+ uint32_t qw4_dyn;
+ int32_t qw4_ofs;
+ uint32_t qw4_sel_a;
+ uint32_t qw4_sel_b;
+ uint32_t dw8_dyn;
+ int32_t dw8_ofs;
+ uint32_t dw8_sel_a;
+ uint32_t dw8_sel_b;
+ uint32_t dw10_dyn;
+ int32_t dw10_ofs;
+ uint32_t dw10_sel_a;
+ uint32_t dw10_sel_b;
+ uint32_t swx_cch;
+ uint32_t swx_sel_a;
+ uint32_t swx_sel_b;
+ uint32_t mask_d_a[12];
+ uint32_t mask_b[6];
+ uint32_t dual;
+ uint32_t paired;
+ uint32_t el_a;
+ uint32_t el_b;
+ uint32_t info_a;
+ uint32_t info_b;
+ uint32_t ftm_a;
+ uint32_t ftm_b;
+ uint32_t bank_a;
+ uint32_t bank_b;
+ uint32_t kl_a;
+ uint32_t kl_b;
+ uint32_t keyway_a;
+ uint32_t keyway_b;
+ uint32_t synergy_mode;
+ uint32_t dw0_b_dyn;
+ int32_t dw0_b_ofs;
+ uint32_t dw2_b_dyn;
+ int32_t dw2_b_ofs;
+ uint32_t sw4_b_dyn;
+ int32_t sw4_b_ofs;
+ uint32_t sw5_b_dyn;
+ int32_t sw5_b_ofs;
+};
+
+struct km_v7_cam_s {
+ uint32_t w0;
+ uint32_t w1;
+ uint32_t w2;
+ uint32_t w3;
+ uint32_t w4;
+ uint32_t w5;
+ uint32_t ft0;
+ uint32_t ft1;
+ uint32_t ft2;
+ uint32_t ft3;
+ uint32_t ft4;
+ uint32_t ft5;
+};
+
+struct km_v7_tcam_s {
+ uint32_t t[3];
+ uint32_t dirty;
+};
+
+struct km_v7_tci_s {
+ uint32_t color;
+ uint32_t ft;
+};
+
+struct km_v7_tcq_s {
+ uint32_t bank_mask;
+ uint32_t qual;
+};
+
+struct hw_mod_km_v7_s {
+ struct km_v7_rcp_s *rcp;
+ struct km_v7_cam_s *cam;
+ struct km_v7_tcam_s *tcam;
+ struct km_v7_tci_s *tci;
+ struct km_v7_tcq_s *tcq;
+};
+
+#endif /* _HW_MOD_KM_V7_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c
new file mode 100644
index 0000000000..8d0d70cae2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "PDB"
+#define _VER_ be->pdb.ver
+
+bool hw_mod_pdb_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_pdb_present(be->be_dev);
+}
+
+int hw_mod_pdb_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_pdb_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "PDB MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_pdb_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "pdb_categories", _MOD_, _VER_);
+ be->pdb.nb_pdb_rcp_categories = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 9:
+ if (!callocate_mod(CAST_COMMON(&be->pdb), 2,
+ &be->pdb.v9.rcp,
+ be->pdb.nb_pdb_rcp_categories,
+ sizeof(struct pdb_v9_rcp_s),
+ &be->pdb.v9.config,
+ 1,
+ sizeof(struct pdb_v9_config_s)))
+ return -1;
+ break;
+ /* end case 9 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_pdb_free(struct flow_api_backend_s *be)
+{
+ if (be->pdb.base) {
+ free(be->pdb.base);
+ be->pdb.base = NULL;
+ }
+}
+
+int hw_mod_pdb_reset(struct flow_api_backend_s *be)
+{
+ int err = 0;
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->pdb);
+
+ NT_LOG(DBG, FILTER, "INIT PDB RCP\n");
+ err |= hw_mod_pdb_rcp_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT PDB CONFIG\n");
+ err |= hw_mod_pdb_config_flush(be);
+ return err;
+}
+
+int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->pdb.nb_pdb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->pdb.nb_pdb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->pdb_rcp_flush(be->be_dev, &be->pdb, start_idx, count);
+}
+
+static int hw_mod_pdb_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_pdb_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->pdb.nb_pdb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 9:
+ switch (field) {
+ case HW_PDB_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->pdb.v9.rcp[index], (uint8_t)*value,
+ sizeof(struct pdb_v9_rcp_s));
+ break;
+ case HW_PDB_RCP_FIND:
+ rv = find_equal_index(be->pdb.v9.rcp,
+ sizeof(struct pdb_v9_rcp_s), index, *value,
+ be->pdb.nb_pdb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_PDB_RCP_COMPARE:
+ rv = do_compare_indexes(be->pdb.v9.rcp,
+ sizeof(struct pdb_v9_rcp_s), index, *value,
+ be->pdb.nb_pdb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_PDB_RCP_DESCRIPTOR:
+ get_set(&be->pdb.v9.rcp[index].descriptor, value, get);
+ break;
+ case HW_PDB_RCP_DESC_LEN:
+ get_set(&be->pdb.v9.rcp[index].desc_len, value, get);
+ break;
+ case HW_PDB_RCP_TX_PORT:
+ get_set(&be->pdb.v9.rcp[index].tx_port, value, get);
+ break;
+ case HW_PDB_RCP_TX_IGNORE:
+ get_set(&be->pdb.v9.rcp[index].tx_ignore, value, get);
+ break;
+ case HW_PDB_RCP_TX_NOW:
+ get_set(&be->pdb.v9.rcp[index].tx_now, value, get);
+ break;
+ case HW_PDB_RCP_CRC_OVERWRITE:
+ get_set(&be->pdb.v9.rcp[index].crc_overwrite, value, get);
+ break;
+ case HW_PDB_RCP_ALIGN:
+ get_set(&be->pdb.v9.rcp[index].align, value, get);
+ break;
+ case HW_PDB_RCP_OFS0_DYN:
+ get_set(&be->pdb.v9.rcp[index].ofs0_dyn, value, get);
+ break;
+ case HW_PDB_RCP_OFS0_REL:
+ get_set_signed(&be->pdb.v9.rcp[index].ofs0_rel, value, get);
+ break;
+ case HW_PDB_RCP_OFS1_DYN:
+ get_set(&be->pdb.v9.rcp[index].ofs1_dyn, value, get);
+ break;
+ case HW_PDB_RCP_OFS1_REL:
+ get_set_signed(&be->pdb.v9.rcp[index].ofs1_rel, value, get);
+ break;
+ case HW_PDB_RCP_OFS2_DYN:
+ get_set(&be->pdb.v9.rcp[index].ofs2_dyn, value, get);
+ break;
+ case HW_PDB_RCP_OFS2_REL:
+ get_set_signed(&be->pdb.v9.rcp[index].ofs2_rel, value, get);
+ break;
+ case HW_PDB_RCP_IP_PROT_TNL:
+ get_set(&be->pdb.v9.rcp[index].ip_prot_tnl, value, get);
+ break;
+ case HW_PDB_RCP_PPC_HSH:
+ get_set(&be->pdb.v9.rcp[index].ppc_hsh, value, get);
+ break;
+ case HW_PDB_RCP_DUPLICATE_EN:
+ get_set(&be->pdb.v9.rcp[index].duplicate_en, value, get);
+ break;
+ case HW_PDB_RCP_DUPLICATE_BIT:
+ get_set(&be->pdb.v9.rcp[index].duplicate_bit, value, get);
+ break;
+ case HW_PDB_RCP_PCAP_KEEP_FCS:
+ get_set(&be->pdb.v9.rcp[index].pcap_keep_fcs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 9 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_pdb_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_pdb_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_pdb_config_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->pdb_config_flush(be->be_dev, &be->pdb);
+}
+
+int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t value)
+{
+ switch (_VER_) {
+ case 9:
+ switch (field) {
+ case HW_PDB_CONFIG_TS_FORMAT:
+ be->pdb.v9.config->ts_format = value;
+ break;
+ case HW_PDB_CONFIG_PORT_OFS:
+ be->pdb.v9.config->port_ofs = value;
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 9 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h
new file mode 100644
index 0000000000..b14c10bc53
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_PDB_V9_H_
+#define _HW_MOD_PDB_V9_H_
+
+struct pdb_v9_rcp_s {
+ uint32_t descriptor;
+ uint32_t desc_len;
+ uint32_t tx_port;
+ uint32_t tx_ignore;
+ uint32_t tx_now;
+ uint32_t crc_overwrite;
+ uint32_t align;
+ uint32_t ofs0_dyn;
+ int32_t ofs0_rel;
+ uint32_t ofs1_dyn;
+ int32_t ofs1_rel;
+ uint32_t ofs2_dyn;
+ int32_t ofs2_rel;
+ uint32_t ip_prot_tnl;
+ uint32_t ppc_hsh;
+ uint32_t duplicate_en;
+ uint32_t duplicate_bit;
+ uint32_t pcap_keep_fcs; /* only field added to v9 cmp to v7/8 */
+};
+
+struct pdb_v9_config_s {
+ uint32_t ts_format;
+ uint32_t port_ofs;
+};
+
+struct hw_mod_pdb_v9_s {
+ struct pdb_v9_rcp_s *rcp;
+ struct pdb_v9_config_s *config;
+};
+
+#endif /* _HW_MOD_PDB_V9_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c
new file mode 100644
index 0000000000..86d23ea683
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c
@@ -0,0 +1,348 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "QSL"
+#define _VER_ be->qsl.ver
+
+#define QSL_QEN_ENTRIES 32
+#define QSL_QNMQ_ENTRIES 256
+
+bool hw_mod_qsl_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_qsl_present(be->be_dev);
+}
+
+int hw_mod_qsl_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_qsl_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "QSL MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_qsl_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "qsl_categories", _MOD_, _VER_);
+ be->qsl.nb_rcp_categories = (uint32_t)nb;
+
+ nb = be->iface->get_nb_qsl_qst_entries(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "qsl_qst_entries", _MOD_, _VER_);
+ be->qsl.nb_qst_entries = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 7:
+ if (!callocate_mod(CAST_COMMON(&be->qsl), 4,
+ &be->qsl.v7.rcp,
+ be->qsl.nb_rcp_categories,
+ sizeof(struct qsl_v7_rcp_s),
+ &be->qsl.v7.qst,
+ be->qsl.nb_qst_entries,
+ sizeof(struct qsl_v7_qst_s),
+ &be->qsl.v7.qen,
+ QSL_QEN_ENTRIES,
+ sizeof(struct qsl_v7_qen_s),
+ &be->qsl.v7.unmq,
+ QSL_QNMQ_ENTRIES,
+ sizeof(struct qsl_v7_unmq_s)))
+ return -1;
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_qsl_free(struct flow_api_backend_s *be)
+{
+ if (be->qsl.base) {
+ free(be->qsl.base);
+ be->qsl.base = NULL;
+ }
+}
+
+int hw_mod_qsl_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->qsl);
+
+ NT_LOG(DBG, FILTER, "INIT QSL RCP\n");
+ hw_mod_qsl_rcp_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT QSL QST\n");
+ hw_mod_qsl_qst_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT QSL QEN\n");
+ hw_mod_qsl_qen_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT QSL UNMQ\n");
+ be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, 0, 256);
+
+ return 0;
+}
+
+int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->qsl.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->qsl.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_rcp_flush(be->be_dev, &be->qsl, start_idx, count);
+}
+
+static int hw_mod_qsl_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->qsl.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->qsl.v7.rcp[index], (uint8_t)*value,
+ sizeof(struct qsl_v7_rcp_s));
+ break;
+ case HW_QSL_RCP_FIND:
+ rv = find_equal_index(be->qsl.v7.rcp,
+ sizeof(struct qsl_v7_rcp_s), index, *value,
+ be->qsl.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_QSL_RCP_COMPARE:
+ rv = do_compare_indexes(be->qsl.v7.rcp,
+ sizeof(struct qsl_v7_rcp_s), index, *value,
+ be->qsl.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_QSL_RCP_DISCARD:
+ get_set(&be->qsl.v7.rcp[index].discard, value, get);
+ break;
+ case HW_QSL_RCP_DROP:
+ get_set(&be->qsl.v7.rcp[index].drop, value, get);
+ break;
+ case HW_QSL_RCP_TBL_LO:
+ get_set(&be->qsl.v7.rcp[index].tbl_lo, value, get);
+ break;
+ case HW_QSL_RCP_TBL_HI:
+ get_set(&be->qsl.v7.rcp[index].tbl_hi, value, get);
+ break;
+ case HW_QSL_RCP_TBL_IDX:
+ get_set(&be->qsl.v7.rcp[index].tbl_idx, value, get);
+ break;
+ case HW_QSL_RCP_TBL_MSK:
+ get_set(&be->qsl.v7.rcp[index].tbl_msk, value, get);
+ break;
+ case HW_QSL_RCP_LR:
+ get_set(&be->qsl.v7.rcp[index].lr, value, get);
+ break;
+ case HW_QSL_RCP_TSA:
+ get_set(&be->qsl.v7.rcp[index].tsa, value, get);
+ break;
+ case HW_QSL_RCP_VLI:
+ get_set(&be->qsl.v7.rcp[index].vli, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->qsl.nb_qst_entries;
+ if ((unsigned int)(start_idx + count) > be->qsl.nb_qst_entries)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_qst_flush(be->be_dev, &be->qsl, start_idx, count);
+}
+
+static int hw_mod_qsl_qst_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->qsl.nb_qst_entries)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_QST_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->qsl.v7.qst[index], (uint8_t)*value,
+ sizeof(struct qsl_v7_qst_s));
+ break;
+ case HW_QSL_QST_QUEUE:
+ get_set(&be->qsl.v7.qst[index].queue, value, get);
+ break;
+ case HW_QSL_QST_EN:
+ get_set(&be->qsl.v7.qst[index].en, value, get);
+ break;
+ case HW_QSL_QST_TX_PORT:
+ get_set(&be->qsl.v7.qst[index].tx_port, value, get);
+ break;
+ case HW_QSL_QST_LRE:
+ get_set(&be->qsl.v7.qst[index].lre, value, get);
+ break;
+ case HW_QSL_QST_TCI:
+ get_set(&be->qsl.v7.qst[index].tci, value, get);
+ break;
+ case HW_QSL_QST_VEN:
+ get_set(&be->qsl.v7.qst[index].ven, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_qst_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_qst_mod(be, field, index, value, 1);
+}
+
+int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = QSL_QEN_ENTRIES;
+ if ((start_idx + count) > QSL_QEN_ENTRIES)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_qen_flush(be->be_dev, &be->qsl, start_idx, count);
+}
+
+static int hw_mod_qsl_qen_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= QSL_QEN_ENTRIES)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_QEN_EN:
+ get_set(&be->qsl.v7.qen[index].en, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_qen_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_qen_mod(be, field, index, value, 1);
+}
+
+int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = QSL_QNMQ_ENTRIES;
+ if ((start_idx + count) > QSL_QNMQ_ENTRIES)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, start_idx,
+ count);
+}
+
+static int hw_mod_qsl_unmq_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= QSL_QNMQ_ENTRIES)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_UNMQ_DEST_QUEUE:
+ get_set(&be->qsl.v7.unmq[index].dest_queue, value, get);
+ break;
+ case HW_QSL_UNMQ_EN:
+ get_set(&be->qsl.v7.unmq[index].en, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_unmq_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_unmq_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h
new file mode 100644
index 0000000000..747da4bc43
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_QSL_V7_H_
+#define _HW_MOD_QSL_V7_H_
+
+struct qsl_v7_rcp_s {
+ uint32_t discard;
+ uint32_t drop;
+ uint32_t tbl_lo;
+ uint32_t tbl_hi;
+ uint32_t tbl_idx;
+ uint32_t tbl_msk;
+ uint32_t lr;
+ uint32_t tsa;
+ uint32_t vli;
+};
+
+struct qsl_v7_qst_s {
+ uint32_t queue;
+ uint32_t en;
+ uint32_t tx_port;
+ uint32_t lre;
+ uint32_t tci;
+ uint32_t ven;
+};
+
+struct qsl_v7_qen_s {
+ uint32_t en;
+};
+
+struct qsl_v7_unmq_s {
+ uint32_t dest_queue;
+ uint32_t en;
+};
+
+struct hw_mod_qsl_v7_s {
+ struct qsl_v7_rcp_s *rcp;
+ struct qsl_v7_qst_s *qst;
+ struct qsl_v7_qen_s *qen;
+ struct qsl_v7_unmq_s *unmq;
+};
+
+#endif /* _HW_MOD_QSL_V7_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c
new file mode 100644
index 0000000000..7f1d695a90
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "RMC"
+#define _VER_ be->rmc.ver
+
+bool hw_mod_rmc_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_rmc_present(be->be_dev);
+}
+
+int hw_mod_rmc_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_rmc_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "RMC MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 0x10003:
+ if (!callocate_mod(CAST_COMMON(&be->rmc), 1,
+ &be->rmc.v1_3.ctrl, 1, sizeof(struct rmc_v1_3_ctrl_s)))
+ return -1;
+ break;
+ /* end case 1_3 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_rmc_free(struct flow_api_backend_s *be)
+{
+ if (be->rmc.base) {
+ free(be->rmc.base);
+ be->rmc.base = NULL;
+ }
+}
+
+int hw_mod_rmc_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->rmc);
+
+ NT_LOG(DBG, FILTER, "INIT RMC CTRL\n");
+ /* disable block stat, block keep alive */
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1);
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_KEEPA, 1);
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_MAC_PORT,
+ 0xff); /* initially block all ports */
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1);
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_RPP_SLICE, 0xf);
+ return hw_mod_rmc_ctrl_flush(be);
+}
+
+int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->rmc_ctrl_flush(be->be_dev, &be->rmc);
+}
+
+static int hw_mod_rmc_ctrl_mod(struct flow_api_backend_s *be,
+ enum hw_rmc_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 0x10003:
+ switch (field) {
+ case HW_RMC_BLOCK_STATT:
+ get_set(&be->rmc.v1_3.ctrl->block_statt, value, get);
+ break;
+ case HW_RMC_BLOCK_KEEPA:
+ get_set(&be->rmc.v1_3.ctrl->block_keepa, value, get);
+ break;
+ case HW_RMC_BLOCK_RPP_SLICE:
+ get_set(&be->rmc.v1_3.ctrl->block_rpp_slice, value, get);
+ break;
+ case HW_RMC_BLOCK_MAC_PORT:
+ get_set(&be->rmc.v1_3.ctrl->block_mac_port, value, get);
+ break;
+ case HW_RMC_LAG_PHY_ODD_EVEN:
+ get_set(&be->rmc.v1_3.ctrl->lag_phy_odd_even, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1.3 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t value)
+{
+ return hw_mod_rmc_ctrl_mod(be, field, &value, 0);
+}
+
+int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t *value)
+{
+ return hw_mod_rmc_ctrl_mod(be, field, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h
new file mode 100644
index 0000000000..8f90695821
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_RMC_V1_3_H_
+#define _HW_MOD_RMC_V1_3_H_
+
+struct rmc_v1_3_ctrl_s {
+ uint32_t block_statt;
+ uint32_t block_keepa;
+ uint32_t block_rpp_slice;
+ uint32_t block_mac_port;
+ uint32_t lag_phy_odd_even;
+};
+
+struct hw_mod_rmc_v1_3_s {
+ struct rmc_v1_3_ctrl_s *ctrl;
+};
+
+#endif /* _HW_MOD_RMC_V1_3_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c
new file mode 100644
index 0000000000..933caf9fd5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c
@@ -0,0 +1,358 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "ROA"
+#define _VER_ be->roa.ver
+
+#define ROA_LAGCFG_ENTRIES 512
+
+bool hw_mod_roa_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_roa_present(be->be_dev);
+}
+
+int hw_mod_roa_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_roa_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "ROA MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_roa_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "roa_categories", _MOD_, _VER_);
+ be->roa.nb_tun_categories = (uint32_t)nb;
+
+ be->roa.nb_tun_categories /= 4;
+
+ switch (_VER_) {
+ case 6:
+ be->roa.nb_lag_entries = ROA_LAGCFG_ENTRIES;
+ if (!callocate_mod(CAST_COMMON(&be->roa), 4,
+ &be->roa.v6.tunhdr,
+ be->roa.nb_tun_categories,
+ sizeof(struct roa_v6_tunhdr_s),
+ &be->roa.v6.tuncfg,
+ be->roa.nb_tun_categories,
+ sizeof(struct roa_v6_tuncfg_s),
+ &be->roa.v6.config,
+ 1,
+ sizeof(struct roa_v6_config_s),
+ &be->roa.v6.lagcfg,
+ be->roa.nb_lag_entries,
+ sizeof(struct roa_v6_lagcfg_s)))
+ return -1;
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_roa_free(struct flow_api_backend_s *be)
+{
+ if (be->roa.base) {
+ free(be->roa.base);
+ be->roa.base = NULL;
+ }
+}
+
+int hw_mod_roa_reset(struct flow_api_backend_s *be)
+{
+ int err = 0;
+
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->roa);
+
+ NT_LOG(DBG, FILTER, "INIT ROA TUNHDR\n");
+ err = hw_mod_roa_tunhdr_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT ROA TUNCFG\n");
+ hw_mod_roa_tuncfg_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT ROA CONFIG\n");
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_RECIRCULATE, 1);
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_NORMAL_PCKS, 1);
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT0, 1);
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT1, 1);
+ hw_mod_roa_config_flush(be);
+
+ NT_LOG(DBG, FILTER, "INIT ROA LAGCFG\n");
+ hw_mod_roa_lagcfg_flush(be, 0, ALL_ENTRIES);
+
+ return err;
+}
+
+int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->roa.nb_tun_categories;
+ if ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ return be->iface->roa_tunhdr_flush(be->be_dev, &be->roa, start_idx,
+ count);
+}
+
+static int hw_mod_roa_tunhdr_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t index,
+ uint32_t word_off, uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_TUNHDR_COMPARE:
+ rv = do_compare_indexes(be->roa.v6.tunhdr,
+ sizeof(struct roa_v6_tunhdr_s), index, word_off,
+ be->roa.nb_tun_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_ROA_TUNHDR:
+ get_set(&be->roa.v6.tunhdr[index].tunnel_hdr[word_off],
+ value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t value)
+{
+ return hw_mod_roa_tunhdr_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value)
+{
+ return hw_mod_roa_tunhdr_mod(be, field, index, word_off, value, 1);
+}
+
+int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->roa.nb_tun_categories;
+ if ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ return be->iface->roa_tuncfg_flush(be->be_dev, &be->roa, start_idx,
+ count);
+}
+
+static int hw_mod_roa_tuncfg_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_TUNCFG_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->roa.v6.tuncfg[index], (uint8_t)*value,
+ sizeof(struct roa_v6_tuncfg_s));
+ break;
+ case HW_ROA_TUNCFG_FIND:
+ rv = find_equal_index(be->roa.v6.tuncfg,
+ sizeof(struct roa_v6_tuncfg_s), index, *value,
+ be->roa.nb_tun_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_ROA_TUNCFG_COMPARE:
+ rv = do_compare_indexes(be->roa.v6.tuncfg,
+ sizeof(struct roa_v6_tuncfg_s), index, *value,
+ be->roa.nb_tun_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_ROA_TUNCFG_TUN_LEN:
+ get_set(&be->roa.v6.tuncfg[index].tun_len, value, get);
+ break;
+ case HW_ROA_TUNCFG_TUN_TYPE:
+ get_set(&be->roa.v6.tuncfg[index].tun_type, value, get);
+ break;
+ case HW_ROA_TUNCFG_TUN_VLAN:
+ get_set(&be->roa.v6.tuncfg[index].tun_vlan, value, get);
+ break;
+ case HW_ROA_TUNCFG_IP_TYPE:
+ get_set(&be->roa.v6.tuncfg[index].ip_type, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPCS_UPD:
+ get_set(&be->roa.v6.tuncfg[index].ipcs_upd, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPCS_PRECALC:
+ get_set(&be->roa.v6.tuncfg[index].ipcs_precalc, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPTL_UPD:
+ get_set(&be->roa.v6.tuncfg[index].iptl_upd, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPTL_PRECALC:
+ get_set(&be->roa.v6.tuncfg[index].iptl_precalc, value, get);
+ break;
+ case HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD:
+ get_set(&be->roa.v6.tuncfg[index].vxlan_udp_len_upd,
+ value, get);
+ break;
+ case HW_ROA_TUNCFG_TX_LAG_IX:
+ get_set(&be->roa.v6.tuncfg[index].tx_lag_ix, value, get);
+ break;
+ case HW_ROA_TUNCFG_RECIRCULATE:
+ get_set(&be->roa.v6.tuncfg[index].recirculate, value, get);
+ break;
+ case HW_ROA_TUNCFG_PUSH_TUNNEL:
+ get_set(&be->roa.v6.tuncfg[index].push_tunnel, value, get);
+ break;
+ case HW_ROA_TUNCFG_RECIRC_PORT:
+ get_set(&be->roa.v6.tuncfg[index].recirc_port, value, get);
+ break;
+ case HW_ROA_TUNCFG_RECIRC_BYPASS:
+ get_set(&be->roa.v6.tuncfg[index].recirc_bypass, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_roa_tuncfg_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_roa_tuncfg_mod(be, field, index, value, 1);
+}
+
+int hw_mod_roa_config_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->roa_config_flush(be->be_dev, &be->roa);
+}
+
+static int hw_mod_roa_config_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_CONFIG_FWD_RECIRCULATE:
+ get_set(&be->roa.v6.config->fwd_recirculate, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_NORMAL_PCKS:
+ get_set(&be->roa.v6.config->fwd_normal_pcks, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_TXPORT0:
+ get_set(&be->roa.v6.config->fwd_txport0, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_TXPORT1:
+ get_set(&be->roa.v6.config->fwd_txport1, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS:
+ get_set(&be->roa.v6.config->fwd_cellbuilder_pcks, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS:
+ get_set(&be->roa.v6.config->fwd_non_normal_pcks, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value)
+{
+ return hw_mod_roa_config_mod(be, field, &value, 0);
+}
+
+int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value)
+{
+ return hw_mod_roa_config_mod(be, field, value, 1);
+}
+
+int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->roa.nb_lag_entries;
+ if ((unsigned int)(start_idx + count) > be->roa.nb_lag_entries)
+ return error_index_too_large(__func__);
+ return be->iface->roa_lagcfg_flush(be->be_dev, &be->roa, start_idx,
+ count);
+}
+
+static int hw_mod_roa_lagcfg_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->roa.nb_lag_entries)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_LAGCFG_TXPHY_PORT:
+ get_set(&be->roa.v6.lagcfg[index].txphy_port, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_roa_lagcfg_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_roa_lagcfg_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h
new file mode 100644
index 0000000000..9930c52428
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_ROA_V6_H_
+#define _HW_MOD_ROA_V6_H_
+
+struct roa_v6_tunhdr_s {
+ uint32_t tunnel_hdr[4 * 4];
+};
+
+struct roa_v6_tuncfg_s {
+ uint32_t tun_len;
+ uint32_t tun_type;
+ uint32_t tun_vlan;
+ uint32_t ip_type;
+ uint32_t ipcs_upd;
+ uint32_t ipcs_precalc;
+ uint32_t iptl_upd;
+ uint32_t iptl_precalc;
+ uint32_t vxlan_udp_len_upd;
+ uint32_t tx_lag_ix;
+ uint32_t recirculate;
+ uint32_t push_tunnel;
+ uint32_t recirc_port;
+ uint32_t recirc_bypass;
+};
+
+struct roa_v6_config_s {
+ uint32_t fwd_recirculate;
+ uint32_t fwd_normal_pcks;
+ uint32_t fwd_txport0;
+ uint32_t fwd_txport1;
+ uint32_t fwd_cellbuilder_pcks;
+ uint32_t fwd_non_normal_pcks;
+};
+
+struct roa_v6_lagcfg_s {
+ uint32_t txphy_port;
+};
+
+struct hw_mod_roa_v6_s {
+ struct roa_v6_tunhdr_s *tunhdr;
+ struct roa_v6_tuncfg_s *tuncfg;
+ struct roa_v6_config_s *config;
+ struct roa_v6_lagcfg_s *lagcfg;
+};
+
+#endif /* _HW_MOD_ROA_V6_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c
new file mode 100644
index 0000000000..ca65db7232
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "SLC"
+#define _VER_ be->slc.ver
+
+bool hw_mod_slc_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_slc_present(be->be_dev);
+}
+
+int hw_mod_slc_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_slc_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "SLC MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 1:
+ if (!callocate_mod(CAST_COMMON(&be->slc), 1,
+ &be->slc.v1.rcp,
+ be->max_categories,
+ sizeof(struct slc_v1_rcp_s)))
+ return -1;
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_slc_free(struct flow_api_backend_s *be)
+{
+ if (be->slc.base) {
+ free(be->slc.base);
+ be->slc.base = NULL;
+ }
+}
+
+int hw_mod_slc_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->slc);
+
+ NT_LOG(DBG, FILTER, "INIT SLC RCP\n");
+ return hw_mod_slc_rcp_flush(be, 0, be->max_categories);
+}
+
+int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->max_categories;
+ if ((unsigned int)(start_idx + count) > be->max_categories)
+ return error_index_too_large(__func__);
+ return be->iface->slc_rcp_flush(be->be_dev, &be->slc, start_idx, count);
+}
+
+static int hw_mod_slc_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_slc_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->max_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ switch (field) {
+ case HW_SLC_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->slc.v1.rcp[index], (uint8_t)*value,
+ sizeof(struct hw_mod_slc_v1_s));
+ break;
+ case HW_SLC_RCP_FIND:
+ rv = find_equal_index(be->slc.v1.rcp,
+ sizeof(struct hw_mod_slc_v1_s), index, *value,
+ be->max_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_RCP_COMPARE:
+ rv = do_compare_indexes(be->slc.v1.rcp,
+ sizeof(struct hw_mod_slc_v1_s), index, *value,
+ be->max_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_RCP_SLC_EN:
+ get_set(&be->slc.v1.rcp[index].tail_slc_en, value, get);
+ break;
+ case HW_SLC_RCP_DYN:
+ get_set(&be->slc.v1.rcp[index].tail_dyn, value, get);
+ break;
+ case HW_SLC_RCP_OFS:
+ get_set_signed(&be->slc.v1.rcp[index].tail_ofs, value, get);
+ break;
+ case HW_SLC_RCP_PCAP:
+ get_set(&be->slc.v1.rcp[index].pcap, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_slc_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_slc_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
new file mode 100644
index 0000000000..9f40563e8a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "SLC_LR"
+#define _VER_ be->slc_lr.ver
+
+bool hw_mod_slc_lr_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_slc_lr_present(be->be_dev);
+}
+
+int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_slc_lr_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "SLC LR MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 2:
+ if (!callocate_mod(CAST_COMMON(&be->slc_lr), 1,
+ &be->slc_lr.v2.rcp,
+ be->max_categories,
+ sizeof(struct slc_lr_v2_rcp_s)))
+ return -1;
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_slc_lr_free(struct flow_api_backend_s *be)
+{
+ if (be->slc_lr.base) {
+ free(be->slc_lr.base);
+ be->slc_lr.base = NULL;
+ }
+}
+
+int hw_mod_slc_lr_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->slc_lr);
+
+ NT_LOG(DBG, FILTER, "INIT SLC LR RCP\n");
+ return hw_mod_slc_lr_rcp_flush(be, 0, be->max_categories);
+}
+
+int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->max_categories;
+ if ((unsigned int)(start_idx + count) > be->max_categories)
+ return error_index_too_large(__func__);
+ return be->iface->slc_lr_rcp_flush(be->be_dev, &be->slc_lr, start_idx,
+ count);
+}
+
+static int hw_mod_slc_lr_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_slc_lr_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->max_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_SLC_LR_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->slc_lr.v2.rcp[index], (uint8_t)*value,
+ sizeof(struct hw_mod_slc_lr_v2_s));
+ break;
+ case HW_SLC_LR_RCP_FIND:
+ rv = find_equal_index(be->slc_lr.v2.rcp,
+ sizeof(struct hw_mod_slc_lr_v2_s), index, *value,
+ be->max_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_LR_RCP_COMPARE:
+ rv = do_compare_indexes(be->slc_lr.v2.rcp,
+ sizeof(struct hw_mod_slc_lr_v2_s), index, *value,
+ be->max_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_LR_RCP_SLC_EN:
+ get_set(&be->slc_lr.v2.rcp[index].tail_slc_en, value, get);
+ break;
+ case HW_SLC_LR_RCP_DYN:
+ get_set(&be->slc_lr.v2.rcp[index].tail_dyn, value, get);
+ break;
+ case HW_SLC_LR_RCP_OFS:
+ get_set_signed(&be->slc_lr.v2.rcp[index].tail_ofs,
+ value, get);
+ break;
+ case HW_SLC_LR_RCP_PCAP:
+ get_set(&be->slc_lr.v2.rcp[index].pcap, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_slc_lr_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_slc_lr_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h
new file mode 100644
index 0000000000..d03b206e6d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_SLC_LR_V2_H_
+#define _HW_MOD_SLC_LR_V2_H_
+
+struct slc_lr_v2_rcp_s {
+ uint32_t tail_slc_en;
+ uint32_t tail_dyn;
+ int32_t tail_ofs;
+ uint32_t pcap;
+};
+
+struct hw_mod_slc_lr_v2_s {
+ struct slc_lr_v2_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_SLC_V2_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h
new file mode 100644
index 0000000000..01f60bfb18
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_SLC_V1_H_
+#define _HW_MOD_SLC_V1_H_
+
+struct slc_v1_rcp_s {
+ uint32_t tail_slc_en;
+ uint32_t tail_dyn;
+ int32_t tail_ofs;
+ uint32_t pcap;
+};
+
+struct hw_mod_slc_v1_s {
+ struct slc_v1_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_SLC_V1_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c
new file mode 100644
index 0000000000..dd6f06b2c4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c
@@ -0,0 +1,983 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "TPE"
+#define _VER_ be->tpe.ver
+
+bool hw_mod_tpe_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_tpe_present(be->be_dev);
+}
+
+int hw_mod_tpe_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_tpe_version(be->be_dev);
+ NT_LOG(DBG, FILTER, _MOD_ " MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_tpe_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tpe_categories", _MOD_, _VER_);
+ be->tpe.nb_rcp_categories = (uint32_t)nb;
+
+ be->tpe.nb_ifr_categories = 0;
+ if (_VER_ > 1) {
+ nb = be->iface->get_nb_tpe_ifr_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tpe_ifr_categories", _MOD_, _VER_);
+ be->tpe.nb_ifr_categories = (uint32_t)nb;
+ }
+
+ nb = be->iface->get_nb_tx_cpy_writers(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tx_cpy_writers", _MOD_, _VER_);
+ be->tpe.nb_cpy_writers = (uint32_t)nb;
+
+ nb = be->iface->get_nb_tx_rpl_depth(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tx_rpl_depth", _MOD_, _VER_);
+ be->tpe.nb_rpl_depth = (uint32_t)nb;
+
+ nb = be->iface->get_nb_tx_rpl_ext_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tx_rpl_ext_categories", _MOD_, _VER_);
+ be->tpe.nb_rpl_ext_categories = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 1:
+ if (!callocate_mod(CAST_COMMON(&be->tpe), 8,
+ &be->tpe.v1.rpp_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s),
+ &be->tpe.v1.ins_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_ins_v1_rcp_s),
+ &be->tpe.v1.rpl_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s),
+ &be->tpe.v1.rpl_ext, be->tpe.nb_rpl_ext_categories,
+ sizeof(struct tpe_v1_rpl_v2_ext_s),
+ &be->tpe.v1.rpl_rpl, be->tpe.nb_rpl_depth,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s),
+ &be->tpe.v1.cpy_rcp,
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s),
+ &be->tpe.v1.hfu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s),
+ &be->tpe.v1.csu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_csu_v0_rcp_s)))
+ return -1;
+ break;
+ case 2:
+ if (!callocate_mod(CAST_COMMON(&be->tpe), 10,
+ &be->tpe.v2.rpp_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s),
+ &be->tpe.v2.rpp_ifr_rcp, be->tpe.nb_ifr_categories,
+ sizeof(struct tpe_v2_rpp_v1_ifr_rcp_s),
+ &be->tpe.v2.ifr_rcp, be->tpe.nb_ifr_categories,
+ sizeof(struct tpe_v2_ifr_v1_rcp_s),
+ &be->tpe.v2.ins_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_ins_v1_rcp_s),
+ &be->tpe.v2.rpl_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s),
+ &be->tpe.v2.rpl_ext, be->tpe.nb_rpl_ext_categories,
+ sizeof(struct tpe_v1_rpl_v2_ext_s),
+ &be->tpe.v2.rpl_rpl, be->tpe.nb_rpl_depth,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s),
+ &be->tpe.v2.cpy_rcp,
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s),
+ &be->tpe.v2.hfu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s),
+ &be->tpe.v2.csu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_csu_v0_rcp_s)))
+ return -1;
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_tpe_free(struct flow_api_backend_s *be)
+{
+ if (be->tpe.base) {
+ free(be->tpe.base);
+ be->tpe.base = NULL;
+ }
+}
+
+int hw_mod_tpe_reset(struct flow_api_backend_s *be)
+{
+ int err = 0;
+
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->tpe);
+
+ NT_LOG(DBG, FILTER, "INIT TPE\n");
+ err |= hw_mod_tpe_rpp_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_ins_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_rpl_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_rpl_ext_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_rpl_rpl_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_cpy_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_hfu_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_csu_rcp_flush(be, 0, ALL_ENTRIES);
+
+ if (_VER_ == 2) {
+ err |= hw_mod_tpe_rpp_ifr_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_ifr_rcp_flush(be, 0, ALL_ENTRIES);
+ }
+
+ return err;
+}
+
+/*
+ * RPP_IFR_RCP
+ */
+
+int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_ifr_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpp_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpp_ifr_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_TPE_IFR_RCP_EN:
+ get_set(&be->tpe.v2.rpp_ifr_rcp[index].en, value, get);
+ break;
+
+ case HW_TPE_IFR_RCP_MTU:
+ get_set(&be->tpe.v2.rpp_ifr_rcp[index].mtu, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t value)
+{
+ return hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPP_RCP
+ */
+
+int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpp_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpp_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpp_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpp_rcp,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpp_rcp,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPP_RCP_EXP:
+ get_set(&be->tpe.v1.rpp_rcp[index].exp, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_rpp_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpp_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * IFR_RCP
+ */
+
+int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_ifr_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_ifr_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_TPE_IFR_RCP_EN:
+ get_set(&be->tpe.v2.ifr_rcp[index].en, value, get);
+ break;
+
+ case HW_TPE_IFR_RCP_MTU:
+ get_set(&be->tpe.v2.ifr_rcp[index].mtu, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_ifr_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_ifr_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * INS_RCP
+ */
+
+int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_ins_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_ins_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.ins_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_ins_v1_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.ins_rcp,
+ sizeof(struct tpe_v1_ins_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.ins_rcp,
+ sizeof(struct tpe_v1_ins_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_INS_RCP_DYN:
+ get_set(&be->tpe.v1.ins_rcp[index].dyn, value, get);
+ break;
+ case HW_TPE_INS_RCP_OFS:
+ get_set(&be->tpe.v1.ins_rcp[index].ofs, value, get);
+ break;
+ case HW_TPE_INS_RCP_LEN:
+ get_set(&be->tpe.v1.ins_rcp[index].len, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_ins_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_ins_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPL_RCP
+ */
+
+int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpl_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpl_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpl_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpl_rcp,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpl_rcp,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPL_RCP_DYN:
+ get_set(&be->tpe.v1.rpl_rcp[index].dyn, value, get);
+ break;
+ case HW_TPE_RPL_RCP_OFS:
+ get_set(&be->tpe.v1.rpl_rcp[index].ofs, value, get);
+ break;
+ case HW_TPE_RPL_RCP_LEN:
+ get_set(&be->tpe.v1.rpl_rcp[index].len, value, get);
+ break;
+ case HW_TPE_RPL_RCP_RPL_PTR:
+ get_set(&be->tpe.v1.rpl_rcp[index].rpl_ptr, value, get);
+ break;
+ case HW_TPE_RPL_RCP_EXT_PRIO:
+ get_set(&be->tpe.v1.rpl_rcp[index].ext_prio, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_rpl_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPL_EXT
+ */
+
+int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rpl_ext_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_ext_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpl_ext_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpl_ext_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rpl_ext_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpl_ext[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpl_v2_ext_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpl_ext,
+ sizeof(struct tpe_v1_rpl_v2_ext_s), index, *value,
+ be->tpe.nb_rpl_ext_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpl_ext,
+ sizeof(struct tpe_v1_rpl_v2_ext_s), index, *value,
+ be->tpe.nb_rpl_ext_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPL_EXT_RPL_PTR:
+ get_set(&be->tpe.v1.rpl_ext[index].rpl_ptr, value, get);
+ break;
+ case HW_TPE_RPL_EXT_META_RPL_LEN:
+ get_set(&be->tpe.v1.rpl_ext[index].meta_rpl_len, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_rpl_ext_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_ext_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPL_RPL
+ */
+
+int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rpl_depth;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_depth)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpl_rpl_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpl_rpl_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rpl_depth)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpl_rpl[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpl_rpl,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value,
+ be->tpe.nb_rpl_depth, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpl_rpl,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value,
+ be->tpe.nb_rpl_depth, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPL_RPL_VALUE:
+ if (get)
+ memcpy(value, be->tpe.v1.rpl_rpl[index].value,
+ sizeof(uint32_t) * 4);
+ else
+ memcpy(be->tpe.v1.rpl_rpl[index].value, value,
+ sizeof(uint32_t) * 4);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 0);
+}
+
+int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 1);
+}
+
+/*
+ * CPY_RCP
+ */
+
+int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ const uint32_t cpy_size =
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories;
+ if (count == ALL_ENTRIES)
+ count = cpy_size;
+ if ((unsigned int)(start_idx + count) > cpy_size)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_cpy_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_cpy_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ const uint32_t cpy_size =
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories;
+ int rv = 0;
+ if (index >= cpy_size)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.cpy_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.cpy_rcp,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value,
+ cpy_size, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.cpy_rcp,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value,
+ cpy_size, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_CPY_RCP_READER_SELECT:
+ get_set(&be->tpe.v1.cpy_rcp[index].reader_select, value, get);
+ break;
+ case HW_TPE_CPY_RCP_DYN:
+ get_set(&be->tpe.v1.cpy_rcp[index].dyn, value, get);
+ break;
+ case HW_TPE_CPY_RCP_OFS:
+ get_set(&be->tpe.v1.cpy_rcp[index].ofs, value, get);
+ break;
+ case HW_TPE_CPY_RCP_LEN:
+ get_set(&be->tpe.v1.cpy_rcp[index].len, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_cpy_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_cpy_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * HFU_RCP
+ */
+
+int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_hfu_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_hfu_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.hfu_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.hfu_rcp,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.hfu_rcp,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_outer_l4_len,
+ value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_ADD_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_add_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_ADD_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_add_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_SUB_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_sub_dyn, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_LEN_B_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_ADD_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_add_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_ADD_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_add_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_SUB_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_sub_dyn, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_LEN_C_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_ADD_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_add_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_ADD_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_add_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_SUB_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_sub_dyn, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_TTL_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].ttl_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_TTL_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_TTL_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_ofs, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_CS_INF:
+ get_set(&be->tpe.v1.hfu_rcp[index].cs_inf, value, get);
+ break;
+ case HW_TPE_HFU_RCP_L3_PRT:
+ get_set(&be->tpe.v1.hfu_rcp[index].l3_prt, value, get);
+ break;
+ case HW_TPE_HFU_RCP_L3_FRAG:
+ get_set(&be->tpe.v1.hfu_rcp[index].l3_frag, value, get);
+ break;
+ case HW_TPE_HFU_RCP_TUNNEL:
+ get_set(&be->tpe.v1.hfu_rcp[index].tunnel, value, get);
+ break;
+ case HW_TPE_HFU_RCP_L4_PRT:
+ get_set(&be->tpe.v1.hfu_rcp[index].l4_prt, value, get);
+ break;
+ case HW_TPE_HFU_RCP_OUTER_L3_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].outer_l3_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_OUTER_L4_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].outer_l4_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_INNER_L3_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].inner_l3_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_INNER_L4_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].inner_l4_ofs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_hfu_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_hfu_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * CSU_RCP
+ */
+
+int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_csu_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_csu_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.csu_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_csu_v0_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.csu_rcp,
+ sizeof(struct tpe_v1_csu_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.csu_rcp,
+ sizeof(struct tpe_v1_csu_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_CSU_RCP_OUTER_L3_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].ol3_cmd, value, get);
+ break;
+ case HW_TPE_CSU_RCP_OUTER_L4_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].ol4_cmd, value, get);
+ break;
+ case HW_TPE_CSU_RCP_INNER_L3_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].il3_cmd, value, get);
+ break;
+ case HW_TPE_CSU_RCP_INNER_L4_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].il4_cmd, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_csu_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_csu_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h
new file mode 100644
index 0000000000..dacd819659
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_TPE_V1_H_
+#define _HW_MOD_TPE_V1_H_
+
+struct tpe_v1_rpp_v0_rcp_s {
+ uint32_t exp;
+};
+
+struct tpe_v1_ins_v1_rcp_s {
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+};
+
+struct tpe_v1_rpl_v2_rcp_s {
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+ uint32_t rpl_ptr;
+ uint32_t ext_prio;
+};
+
+struct tpe_v1_rpl_v2_ext_s {
+ uint32_t rpl_ptr;
+ uint32_t meta_rpl_len; /* SW only */
+};
+
+struct tpe_v1_rpl_v2_rpl_s {
+ uint32_t value[4];
+};
+
+struct tpe_v1_cpy_v1_rcp_s {
+ uint32_t reader_select;
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+};
+
+struct tpe_v1_hfu_v1_rcp_s {
+ uint32_t len_a_wr;
+ uint32_t len_a_outer_l4_len;
+ uint32_t len_a_pos_dyn;
+ uint32_t len_a_pos_ofs;
+ uint32_t len_a_add_dyn;
+ uint32_t len_a_add_ofs;
+ uint32_t len_a_sub_dyn;
+
+ uint32_t len_b_wr;
+ uint32_t len_b_pos_dyn;
+ uint32_t len_b_pos_ofs;
+ uint32_t len_b_add_dyn;
+ uint32_t len_b_add_ofs;
+ uint32_t len_b_sub_dyn;
+
+ uint32_t len_c_wr;
+ uint32_t len_c_pos_dyn;
+ uint32_t len_c_pos_ofs;
+ uint32_t len_c_add_dyn;
+ uint32_t len_c_add_ofs;
+ uint32_t len_c_sub_dyn;
+
+ uint32_t ttl_wr;
+ uint32_t ttl_pos_dyn;
+ uint32_t ttl_pos_ofs;
+
+ uint32_t cs_inf;
+ uint32_t l3_prt;
+ uint32_t l3_frag;
+ uint32_t tunnel;
+ uint32_t l4_prt;
+ uint32_t outer_l3_ofs;
+ uint32_t outer_l4_ofs;
+ uint32_t inner_l3_ofs;
+ uint32_t inner_l4_ofs;
+};
+
+struct tpe_v1_csu_v0_rcp_s {
+ uint32_t ol3_cmd;
+ uint32_t ol4_cmd;
+ uint32_t il3_cmd;
+ uint32_t il4_cmd;
+};
+
+struct hw_mod_tpe_v1_s {
+ struct tpe_v1_rpp_v0_rcp_s *rpp_rcp;
+
+ struct tpe_v1_ins_v1_rcp_s *ins_rcp;
+
+ struct tpe_v1_rpl_v2_rcp_s *rpl_rcp;
+ struct tpe_v1_rpl_v2_ext_s *rpl_ext;
+ struct tpe_v1_rpl_v2_rpl_s *rpl_rpl;
+
+ struct tpe_v1_cpy_v1_rcp_s *cpy_rcp;
+
+ struct tpe_v1_hfu_v1_rcp_s *hfu_rcp;
+
+ struct tpe_v1_csu_v0_rcp_s *csu_rcp;
+};
+
+#endif /* _HW_MOD_TPE_V1_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h
new file mode 100644
index 0000000000..c56cad8d89
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_TPE_V2_H_
+#define _HW_MOD_TPE_V2_H_
+
+struct tpe_v2_rpp_v1_ifr_rcp_s {
+ uint32_t en;
+ uint32_t mtu;
+};
+
+struct tpe_v2_ifr_v1_rcp_s {
+ uint32_t en;
+ uint32_t mtu;
+};
+
+struct hw_mod_tpe_v2_s {
+ struct tpe_v1_rpp_v0_rcp_s *rpp_rcp;
+
+ struct tpe_v1_ins_v1_rcp_s *ins_rcp;
+
+ struct tpe_v1_rpl_v2_rcp_s *rpl_rcp;
+ struct tpe_v1_rpl_v2_ext_s *rpl_ext;
+ struct tpe_v1_rpl_v2_rpl_s *rpl_rpl;
+
+ struct tpe_v1_cpy_v1_rcp_s *cpy_rcp;
+
+ struct tpe_v1_hfu_v1_rcp_s *hfu_rcp;
+
+ struct tpe_v1_csu_v0_rcp_s *csu_rcp;
+
+ struct tpe_v2_rpp_v1_ifr_rcp_s *rpp_ifr_rcp;
+ struct tpe_v2_ifr_v1_rcp_s *ifr_rcp;
+};
+
+#endif /* _HW_MOD_TPE_V2_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h
new file mode 100644
index 0000000000..eae8f176a8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h
@@ -0,0 +1,697 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _STREAM_BINARY_FLOW_API_H_
+#define _STREAM_BINARY_FLOW_API_H_
+
+#include <stdint.h> /* uint16_t, uint32_t, uint64_t */
+#include <stdio.h> /* snprintf */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t be16_t; /* 16-bit big-endian */
+typedef uint32_t be32_t; /* 32-bit big-endian */
+typedef uint64_t be64_t; /* 64-bit big-endian */
+
+/*
+ * Flow frontend for binary programming interface
+ */
+
+#define FLOW_MAX_QUEUES 128
+
+#define RAW_ENCAP_DECAP_ELEMS_MAX 16
+
+/*
+ * Partial flow mark and special flow marks
+ */
+#define FLOW_MARK_LACP 0x7fffffff
+#define FLOW_MARK_MAX 0x7ffffffe
+/*
+ * Flow eth dev profile determines how the FPGA module resources are
+ * managed and what features are available
+ */
+enum flow_eth_dev_profile {
+ FLOW_ETH_DEV_PROFILE_VSWITCH = 0,
+ FLOW_ETH_DEV_PROFILE_INLINE = 1,
+};
+
+/*
+ * Flow rule attributes
+ */
+struct flow_attr {
+ uint32_t group; /* Priority group. */
+ uint32_t priority; /* Rule priority level within group. */
+ uint16_t forced_vlan_vid; /* Forced VLAN VID that filter must match. Ignored if 0. */
+ uint8_t caller_id; /* Unique ID of caller application. */
+};
+
+struct flow_queue_id_s {
+ int id;
+ int hw_id;
+};
+
+/* NT Private rte flow items. */
+
+/* NT Private rte flow actions. */
+
+enum flow_elem_type {
+ FLOW_ELEM_TYPE_END,
+ FLOW_ELEM_TYPE_ANY,
+ FLOW_ELEM_TYPE_ETH,
+ FLOW_ELEM_TYPE_VLAN,
+ FLOW_ELEM_TYPE_IPV4,
+ FLOW_ELEM_TYPE_IPV6,
+ FLOW_ELEM_TYPE_SCTP,
+ FLOW_ELEM_TYPE_TCP,
+ FLOW_ELEM_TYPE_UDP,
+ FLOW_ELEM_TYPE_ICMP,
+ FLOW_ELEM_TYPE_VXLAN,
+ FLOW_ELEM_TYPE_GTP,
+ FLOW_ELEM_TYPE_PORT_ID,
+ FLOW_ELEM_TYPE_TAG,
+ FLOW_ELEM_TYPE_VOID,
+
+ /*
+ * Not associated with a RTE_ITEM..., but rather an restoration API device specific
+ * extension
+ */
+ FLOW_ELEM_TYPE_TUNNEL
+};
+
+enum flow_action_type { /* conf structure */
+ FLOW_ACTION_TYPE_END, /* -none- : End tag for action list */
+ FLOW_ACTION_TYPE_POP_VLAN, /* -none- : Pops outer vlan tag */
+ FLOW_ACTION_TYPE_PUSH_VLAN, /* struct flow_action_push_vlan : Push VLAN TAG */
+ FLOW_ACTION_TYPE_SET_VLAN_VID, /* struct flow_action_set_vlan_vid : Set VLAN VID */
+ FLOW_ACTION_TYPE_SET_VLAN_PCP, /* struct flow_action_set_vlan_pcp : Set VLAN PCP */
+ /* -none- : Decapsulate outer most VXLAN tunnel from matched flow */
+ FLOW_ACTION_TYPE_VXLAN_DECAP,
+ FLOW_ACTION_TYPE_VXLAN_ENCAP, /* struct flow_action_vxlan_encap */
+ FLOW_ACTION_TYPE_DROP, /* -none- : Drop packets of this flow */
+ FLOW_ACTION_TYPE_COUNT, /* struct flow_action_count : Used for "query" flow function */
+ FLOW_ACTION_TYPE_MARK, /* struct flow_action_mark : Used to tag a flow in HW with a MARK */
+ FLOW_ACTION_TYPE_SET_TAG, /* struct flow_action_tag : Used to tag a flow in HW with a TAG */
+ /* struct flow_action_port_id : Destination port ID - HW port ID */
+ FLOW_ACTION_TYPE_PORT_ID,
+ FLOW_ACTION_TYPE_RSS, /* struct flow_action_rss : */
+ FLOW_ACTION_TYPE_QUEUE, /* struct flow_action_queue : */
+ FLOW_ACTION_TYPE_JUMP, /* struct flow_action_jump : */
+ /* struct flow_action_meter : Used to set MBR record ids in FLM learn records */
+ FLOW_ACTION_TYPE_METER,
+ FLOW_ACTION_TYPE_RAW_ENCAP, /* struct flow_action_raw_encap : */
+ FLOW_ACTION_TYPE_RAW_DECAP, /* struct flow_action_raw_decap : */
+ FLOW_ACTION_TYPE_MODIFY_FIELD, /* struct flow_action_modify_field : */
+
+ /*
+ * -none- : not associated with a RTE_ACTION..., but rather an restoration API device
+ * specific extension
+ */
+ FLOW_ACTION_TYPE_TUNNEL_SET
+};
+
+#pragma pack(1)
+struct ether_addr_s {
+ uint8_t addr_b[6];
+};
+
+#pragma pack()
+
+static inline void flow_ether_format_addr(char *buf, uint16_t size,
+ const struct ether_addr_s *eth_addr)
+{
+ snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X",
+ eth_addr->addr_b[0], eth_addr->addr_b[1], eth_addr->addr_b[2],
+ eth_addr->addr_b[3], eth_addr->addr_b[4], eth_addr->addr_b[5]);
+}
+
+/*
+ * IPv4 Header
+ */
+#pragma pack(1)
+struct ipv4_hdr_s {
+ uint8_t version_ihl;
+ uint8_t tos;
+ be16_t length;
+ be16_t id;
+ be16_t frag_offset;
+ uint8_t ttl;
+ uint8_t next_proto_id;
+ be16_t hdr_csum;
+ be32_t src_ip;
+ be32_t dst_ip;
+};
+
+#pragma pack()
+/*
+ * IPv6 Header
+ */
+#pragma pack(1)
+struct ipv6_hdr_s {
+ be32_t vtc_flow; /* IP version, traffic class & flow label */
+ be16_t payload_len; /* IP packet length - includes ip header */
+ uint8_t proto;
+ uint8_t hop_limits;
+ uint8_t src_addr[16];
+ uint8_t dst_addr[16];
+};
+
+#pragma pack()
+
+/*
+ * SCTP Header
+ */
+#pragma pack(1)
+struct sctp_hdr_s {
+ be16_t src_port;
+ be16_t dst_port;
+ be32_t tag; /* Validation tag */
+ be32_t cksum;
+};
+
+#pragma pack()
+
+/*
+ * TCP Header
+ */
+#pragma pack(1)
+struct tcp_hdr_s {
+ be16_t src_port;
+ be16_t dst_port;
+ be32_t sent_seq;
+ be32_t recv_ack;
+ uint8_t data_off;
+ uint8_t tcp_flags;
+ be16_t rx_win;
+ be16_t cksum;
+ be16_t tcp_urp;
+};
+
+#pragma pack()
+
+/*
+ * UDP Header
+ */
+#pragma pack(1)
+struct udp_hdr_s {
+ be16_t src_port;
+ be16_t dst_port;
+ be16_t len;
+ be16_t cksum;
+};
+
+#pragma pack()
+
+/*
+ * ICMP Header
+ */
+#pragma pack(1)
+struct icmp_hdr_s {
+ uint8_t type;
+ uint8_t code;
+ be16_t cksum;
+ be16_t ident;
+ be16_t seq_nb;
+};
+
+#pragma pack()
+/*
+ * FLOW_ELEM_TYPE_ETH specification
+ */
+#pragma pack(1)
+struct flow_elem_eth {
+ struct ether_addr_s d_addr; /* DMAC */
+ struct ether_addr_s s_addr; /* SMAC */
+ be16_t ether_type; /* Frame type */
+};
+
+#pragma pack()
+
+/*
+ * FLOW_ELEM_TYPE_VLAN specification
+ */
+#pragma pack(1)
+struct flow_elem_vlan {
+ be16_t tci; /* Tag control information */
+ be16_t inner_type; /* Inner EtherType or TPID */
+};
+
+#pragma pack()
+
+/*
+ * FLOW_ELEM_TYPE_IPV4 specification
+ */
+struct flow_elem_ipv4 {
+ struct ipv4_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_IPV6 specification
+ */
+struct flow_elem_ipv6 {
+ struct ipv6_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_SCTP specification
+ */
+struct flow_elem_sctp {
+ struct sctp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_TCP specification
+ */
+struct flow_elem_tcp {
+ struct tcp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_UDP specification
+ */
+struct flow_elem_udp {
+ struct udp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_ICMP specification
+ */
+struct flow_elem_icmp {
+ struct icmp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_GTP specification
+ */
+#pragma pack(1)
+struct flow_elem_gtp {
+ uint8_t v_pt_rsv_flags;
+ uint8_t msg_type;
+ be16_t msg_len;
+ be32_t teid;
+};
+
+#pragma pack()
+
+/*
+ * FLOW_ELEM_TYPE_VXLAN specification (RFC 7348)
+ */
+#pragma pack(1)
+struct flow_elem_vxlan {
+ uint8_t flags; /* Normally 0x08 (I flag) */
+ uint8_t rsvd0[3];
+ uint8_t vni[3];
+ uint8_t rsvd1;
+};
+
+#pragma pack()
+/*
+ * FLOW_ELEM_TYPE_PORT_ID specification
+ */
+struct flow_elem_port_id {
+ uint32_t id; /* HW port no */
+};
+
+/*
+ * FLOW_ELEM_TYPE_TAG specification
+ */
+struct flow_elem_tag {
+ uint32_t data;
+ uint8_t index;
+};
+
+/*
+ * FLOW_ELEM_TYPE_ANY specification
+ */
+struct flow_elem_any {
+ uint32_t num; /**< Number of layers covered. */
+};
+
+struct flow_elem {
+ enum flow_elem_type type; /* element type */
+ const void *spec; /* Pointer to element specification structure */
+ const void *mask; /* Bitmask applied to spec - same type */
+};
+
+/*
+ * FLOW_ACTION_TYPE_RSS
+ */
+enum flow_hash_function {
+ FLOW_HASH_FUNCTION_DEFAULT = 0,
+ FLOW_HASH_FUNCTION_TOEPLITZ, /* Unsupported in current supported FPGA */
+ FLOW_HASH_FUNCTION_SIMPLE_XOR /* Simple XOR - not supported */
+};
+
+struct flow_action_rss {
+ enum flow_hash_function func;
+ uint32_t level; /* only level 0 supported */
+ /* Specific RSS hash types (see like DPDK ETH_RSS_*) */
+ uint64_t types;
+ uint32_t key_len; /* Not supported yet - Hash key length in bytes */
+ uint32_t queue_num; /* Number of entries in queue */
+ const uint8_t *key; /* Not supported yet - Hash key */
+ const uint16_t *queue; /* Queue indices to use */
+};
+
+/*
+ * FLOW_ACTION_TYPE_PUSH_VLAN
+ * Push a new vlan TAG
+ */
+struct flow_action_push_vlan {
+ be16_t ethertype;
+};
+
+/*
+ * FLOW_ACTION_TYPE_SET_VLAN_VID
+ */
+struct flow_action_set_vlan_vid {
+ be16_t vlan_vid;
+};
+
+/*
+ * FLOW_ACTION_TYPE_SET_VLAN_PCP
+ */
+struct flow_action_set_vlan_pcp {
+ uint8_t vlan_pcp; /* < VLAN priority. */
+};
+
+/*
+ * FLOW_ACTION_TYPE_VXLAN_ENCAP specification
+ * Valid flow definition:
+ *
+ * - ETH / IPV4 / UDP / VXLAN / END
+ * - ETH / IPV6 / UDP / VXLAN / END
+ * - ETH / VLAN / IPV4 / UDP / VXLAN / END
+ *
+ */
+struct flow_action_vxlan_encap {
+ /* Encapsulating vxlan tunnel definition */
+ struct flow_elem *vxlan_tunnel;
+};
+
+/*
+ * FLOW_ACTION_TYPE_COUNT specification
+ */
+struct flow_action_count {
+ uint32_t id; /* HW port no */
+};
+
+/*
+ * FLOW_ACTION_TYPE_COUNT specification (query)
+ */
+struct flow_query_count {
+ uint32_t reset : 1;
+ uint32_t hits_set : 1;
+ uint32_t bytes_set : 1;
+
+ uint32_t tcp_flags : 9;
+
+ uint32_t reserved : 20;
+ uint64_t hits;
+ uint64_t bytes;
+};
+
+/*
+ * FLOW_ACTION_TYPE_MARK specification
+ */
+struct flow_action_mark {
+ uint32_t id; /* mark flow with this ID */
+};
+
+/*
+ * FLOW_ACTION_TYPE_TAG specification
+ */
+struct flow_action_tag {
+ uint32_t data; /* tag flow with this value */
+ uint32_t mask; /* bit-mask applied to "data" */
+ uint8_t index; /* index of tag to set */
+};
+
+/*
+ * FLOW_ACTION_TYPE_PORT_ID specification
+ */
+struct flow_action_port_id {
+ uint32_t rte_flags; /* not used but to be binary compatible with rte flow */
+ uint32_t id;
+};
+
+/*
+ * FLOW_ACTION_TYPE_QUEUE
+ */
+struct flow_action_queue {
+ uint16_t index;
+};
+
+/*
+ * FLOW_ACTION_TYPE_JUMP
+ */
+struct flow_action_jump {
+ uint32_t group;
+};
+
+/*
+ * FLOW_ACTION_TYPE_METER
+ */
+struct flow_action_meter {
+ uint32_t mtr_id;
+};
+
+/*
+ * FLOW_ACTION_TYPE_RAW_ENCAP
+ */
+struct flow_action_raw_encap {
+ uint8_t *data;
+ uint8_t *preserve;
+ size_t size;
+ struct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX];
+ int item_count;
+};
+
+/*
+ * FLOW_ACTION_TYPE_RAW_DECAP
+ */
+struct flow_action_raw_decap {
+ uint8_t *data;
+ size_t size;
+ struct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX];
+ int item_count;
+};
+
+/*
+ * Field IDs for MODIFY_FIELD action.
+ */
+enum flow_field_id {
+ FLOW_FIELD_START = 0, /* Start of a packet. */
+ FLOW_FIELD_MAC_DST, /* Destination MAC Address. */
+ FLOW_FIELD_MAC_SRC, /* Source MAC Address. */
+ FLOW_FIELD_VLAN_TYPE, /* 802.1Q Tag Identifier. */
+ FLOW_FIELD_VLAN_ID, /* 802.1Q VLAN Identifier. */
+ FLOW_FIELD_MAC_TYPE, /* EtherType. */
+ FLOW_FIELD_IPV4_DSCP, /* IPv4 DSCP. */
+ FLOW_FIELD_IPV4_TTL, /* IPv4 Time To Live. */
+ FLOW_FIELD_IPV4_SRC, /* IPv4 Source Address. */
+ FLOW_FIELD_IPV4_DST, /* IPv4 Destination Address. */
+ FLOW_FIELD_IPV6_DSCP, /* IPv6 DSCP. */
+ FLOW_FIELD_IPV6_HOPLIMIT, /* IPv6 Hop Limit. */
+ FLOW_FIELD_IPV6_SRC, /* IPv6 Source Address. */
+ FLOW_FIELD_IPV6_DST, /* IPv6 Destination Address. */
+ FLOW_FIELD_TCP_PORT_SRC, /* TCP Source Port Number. */
+ FLOW_FIELD_TCP_PORT_DST, /* TCP Destination Port Number. */
+ FLOW_FIELD_TCP_SEQ_NUM, /* TCP Sequence Number. */
+ FLOW_FIELD_TCP_ACK_NUM, /* TCP Acknowledgment Number. */
+ FLOW_FIELD_TCP_FLAGS, /* TCP Flags. */
+ FLOW_FIELD_UDP_PORT_SRC, /* UDP Source Port Number. */
+ FLOW_FIELD_UDP_PORT_DST, /* UDP Destination Port Number. */
+ FLOW_FIELD_VXLAN_VNI, /* VXLAN Network Identifier. */
+ FLOW_FIELD_GENEVE_VNI, /* GENEVE Network Identifier. */
+ FLOW_FIELD_GTP_TEID, /* GTP Tunnel Endpoint Identifier. */
+ FLOW_FIELD_TAG, /* Tag value. */
+ FLOW_FIELD_MARK, /* Mark value. */
+ FLOW_FIELD_META, /* Metadata value. */
+ FLOW_FIELD_POINTER, /* Memory pointer. */
+ FLOW_FIELD_VALUE, /* Immediate value. */
+ FLOW_FIELD_IPV4_ECN, /* IPv4 ECN. */
+ FLOW_FIELD_IPV6_ECN, /* IPv6 ECN. */
+ FLOW_FIELD_GTP_PSC_QFI, /* GTP QFI. */
+ FLOW_FIELD_METER_COLOR, /* Meter color marker. */
+};
+
+/*
+ * Field description for MODIFY_FIELD action.
+ */
+struct flow_action_modify_data {
+ enum flow_field_id field; /* Field or memory type ID. */
+ union {
+ struct {
+ /* Encapsulation level or tag index. */
+ uint32_t level;
+ /* Number of bits to skip from a field. */
+ uint32_t offset;
+ };
+ /*
+ * Immediate value for FLOW_FIELD_VALUE, presented in the
+ * same byte order and length as in relevant rte_flow_item_xxx.
+ */
+ uint8_t value[16];
+ /*
+ * Memory address for FLOW_FIELD_POINTER, memory layout
+ * should be the same as for relevant field in the
+ * rte_flow_item_xxx structure.
+ */
+ void *pvalue;
+ };
+};
+
+/*
+ * Operation types for MODIFY_FIELD action.
+ */
+enum flow_modify_op {
+ FLOW_MODIFY_SET = 0,
+ FLOW_MODIFY_ADD,
+ FLOW_MODIFY_SUB,
+};
+
+/*
+ * FLOW_ACTION_TYPE_MODIFY_FIELD
+ */
+struct flow_action_modify_field {
+ enum flow_modify_op operation;
+ struct flow_action_modify_data dst;
+ struct flow_action_modify_data src;
+ uint32_t width;
+};
+
+struct flow_action {
+ enum flow_action_type type;
+ const void *conf;
+};
+
+enum flow_error_e { FLOW_ERROR_NONE, FLOW_ERROR_SUCCESS, FLOW_ERROR_GENERAL };
+
+struct flow_error {
+ enum flow_error_e type;
+ const char *message;
+};
+
+enum flow_lag_cmd {
+ FLOW_LAG_SET_ENTRY,
+ FLOW_LAG_SET_ALL,
+ FLOW_LAG_SET_BALANCE,
+};
+
+/*
+ * Tunnel definition for DPDK RTE tunnel helper function support
+ */
+struct tunnel_cfg_s {
+ union {
+ struct {
+ uint32_t src_ip; /* BE */
+ uint32_t dst_ip; /* BE */
+ } v4;
+ struct {
+ uint8_t src_ip[16];
+ uint8_t dst_ip[16];
+ } v6;
+ struct {
+ uint64_t src_ip[2];
+ uint64_t dst_ip[2];
+ } v6_long;
+ };
+ int ipversion;
+ uint16_t s_port; /* BE */
+ uint16_t d_port; /* BE */
+ int tun_type;
+};
+
+struct flow_eth_dev; /* port device */
+struct flow_handle;
+
+/*
+ * Device Management API
+ */
+int flow_reset_nic_dev(uint8_t adapter_no);
+
+struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t hw_port_no,
+ uint32_t port_id, int alloc_queues,
+ struct flow_queue_id_s queue_ids[],
+ int *rss_target_id,
+ enum flow_eth_dev_profile flow_profile,
+ uint32_t exception_path);
+
+int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev,
+ struct flow_queue_id_s *queue_id);
+
+int flow_delete_eth_dev(struct flow_eth_dev *eth_dev);
+
+int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,
+ uint8_t vport);
+
+/*
+ * NT Flow API
+ */
+int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[],
+ const struct flow_action action[], struct flow_error *error);
+
+struct flow_handle *flow_create(struct flow_eth_dev *dev,
+ const struct flow_attr *attr,
+ const struct flow_elem item[],
+ const struct flow_action action[],
+ struct flow_error *error);
+
+int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow,
+ struct flow_error *error);
+
+int flow_flush(struct flow_eth_dev *dev, struct flow_error *error);
+
+int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow,
+ const struct flow_action *action, void **data, uint32_t *length,
+ struct flow_error *error);
+
+/*
+ * NT Flow FLM Meter API
+ */
+int flow_mtr_supported(struct flow_eth_dev *dev);
+
+uint64_t flow_mtr_meter_policy_n_max(void);
+
+int flow_mtr_set_profile(struct flow_eth_dev *dev, uint32_t profile_id,
+ uint64_t bucket_rate_a, uint64_t bucket_size_a,
+ uint64_t bucket_rate_b, uint64_t bucket_size_b);
+
+int flow_mtr_set_policy(struct flow_eth_dev *dev, uint32_t policy_id, int drop);
+
+int flow_mtr_create_meter(struct flow_eth_dev *dev, uint32_t mtr_id,
+ uint32_t profile_id, uint32_t policy_id,
+ uint64_t stats_mask);
+
+int flow_mtr_destroy_meter(struct flow_eth_dev *dev, uint32_t mtr_id);
+
+int flm_mtr_adjust_stats(struct flow_eth_dev *dev, uint32_t mtr_id,
+ uint32_t adjust_value);
+
+uint32_t flow_mtr_meters_supported(void);
+
+uint32_t flm_mtr_update_stats(struct flow_eth_dev *dev);
+void flm_mtr_read_stats(struct flow_eth_dev *dev, uint32_t id,
+ uint64_t *stats_mask, uint64_t *green_pkt,
+ uint64_t *green_bytes, int clear);
+
+/*
+ * Config API
+ */
+int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask);
+
+int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask);
+
+int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index,
+ uint32_t value);
+
+int flow_set_mtu_inline(struct flow_eth_dev *dev, uint32_t port, uint16_t mtu);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STREAM_BINARY_FLOW_API_H_ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 6/8] net/ntnic: adds flow logic
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (3 preceding siblings ...)
2023-08-16 13:25 ` [PATCH 5/8] net/ntnic: adds FPGA abstraction layer Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 13:25 ` [PATCH 7/8] net/ntnic: adds ethdev and makes PMD available Mykola Kostenok
` (15 subsequent siblings)
20 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
This logic layer takes rte_flow style patterns and actions as input,
and programs the FPGA accordingly.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/ntnic/adapter/nt4ga_adapter.c | 13 +
drivers/net/ntnic/adapter/nt4ga_stat.c | 20 +-
drivers/net/ntnic/meson.build | 4 +
drivers/net/ntnic/nthw/flow_api/flow_api.c | 1306 +++++
drivers/net/ntnic/nthw/flow_api/flow_api.h | 291 +
.../nthw/flow_api/flow_api_profile_inline.c | 5118 +++++++++++++++++
.../nthw/flow_api/flow_api_profile_inline.h | 56 +
.../net/ntnic/nthw/flow_filter/flow_backend.c | 3205 +++++++++++
.../net/ntnic/nthw/flow_filter/flow_backend.h | 15 +
.../net/ntnic/nthw/flow_filter/flow_filter.c | 39 +
.../net/ntnic/nthw/flow_filter/flow_filter.h | 16 +
11 files changed, 10078 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_backend.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_backend.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_filter.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_filter.h
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index 259aae2831..f9493202c3 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -10,6 +10,8 @@
#include "nt4ga_pci_ta_tg.h"
#include "nt4ga_link_100g.h"
+#include "flow_filter.h"
+
/* Sensors includes */
#include "board_sensors.h"
#include "avr_sensors.h"
@@ -306,6 +308,17 @@ int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info)
n_nim_ports = fpga_info->n_nims;
assert(n_nim_ports >= 1);
+ /* Nt4ga Init Filter */
+ nt4ga_filter_t *p_filter = &p_adapter_info->nt4ga_filter;
+
+ res = flow_filter_init(p_fpga, &p_filter->mp_flow_device,
+ p_adapter_info->adapter_no);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot initialize filter\n",
+ p_adapter_id_str);
+ return res;
+ }
+
/*
* HIF/PCI TA/TG
*/
diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.c b/drivers/net/ntnic/adapter/nt4ga_stat.c
index b61c73ea12..2c822c6b97 100644
--- a/drivers/net/ntnic/adapter/nt4ga_stat.c
+++ b/drivers/net/ntnic/adapter/nt4ga_stat.c
@@ -7,6 +7,7 @@
#include "nthw_drv.h"
#include "nthw_fpga.h"
#include "nt4ga_adapter.h"
+#include "flow_filter.h"
#define NO_FLAGS 0
@@ -16,12 +17,13 @@ static inline uint64_t timestamp2ns(uint64_t ts)
return ((ts >> 32) * 1000000000) + (ts & 0xffffffff);
}
-static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+static int nt4ga_stat_collect_cap_v1_stats(struct adapter_info_s *p_adapter_info,
+ nt4ga_stat_t *p_nt4ga_stat,
uint32_t *p_stat_dma_virtual);
static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
uint32_t *p_stat_dma_virtual);
-int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused,
+int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info,
nt4ga_stat_t *p_nt4ga_stat)
{
nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
@@ -39,7 +41,7 @@ int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused,
} else {
p_nt4ga_stat->last_timestamp =
timestamp2ns(*p_nthw_stat->mp_timestamp);
- nt4ga_stat_collect_cap_v1_stats(p_nt4ga_stat,
+ nt4ga_stat_collect_cap_v1_stats(p_adapter_info, p_nt4ga_stat,
p_nt4ga_stat->p_stat_dma_virtual);
}
return 0;
@@ -198,7 +200,9 @@ int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info)
return -1;
}
- p_nt4ga_stat->flm_stat_ver = 0;
+ struct flow_nic_dev *ndev =
+ p_adapter_info->nt4ga_filter.mp_flow_device;
+ p_nt4ga_stat->flm_stat_ver = ndev->be.flm.ver;
p_nt4ga_stat->mp_stat_structs_flm =
calloc(1, sizeof(struct flm_counters_v1));
@@ -394,10 +398,12 @@ static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
}
/* Called with stat mutex locked */
-static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+static int nt4ga_stat_collect_cap_v1_stats(struct adapter_info_s *p_adapter_info,
+ nt4ga_stat_t *p_nt4ga_stat,
uint32_t *p_stat_dma_virtual)
{
nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
const int n_rx_ports = p_nt4ga_stat->mn_rx_ports;
const int n_tx_ports = p_nt4ga_stat->mn_tx_ports;
@@ -701,5 +707,9 @@ static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
p_nt4ga_stat->a_port_tx_drops_total[p] += new_drop_events_sum;
}
+ /* _update and get FLM stats */
+ flow_get_flm_stats(ndev, (uint64_t *)p_nt4ga_stat->mp_stat_structs_flm,
+ sizeof(struct flm_counters_v1) / sizeof(uint64_t));
+
return 0;
}
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 387481bb4a..a9892615c9 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -60,8 +60,10 @@ sources = files(
'nthw/core/nthw_spim.c',
'nthw/core/nthw_spis.c',
'nthw/core/nthw_tsm.c',
+ 'nthw/flow_api/flow_api.c',
'nthw/flow_api/flow_api_actions.c',
'nthw/flow_api/flow_api_backend.c',
+ 'nthw/flow_api/flow_api_profile_inline.c',
'nthw/flow_api/flow_engine/flow_group.c',
'nthw/flow_api/flow_engine/flow_hasher.c',
'nthw/flow_api/flow_engine/flow_kcc.c',
@@ -80,6 +82,8 @@ sources = files(
'nthw/flow_api/hw_mod/hw_mod_slc.c',
'nthw/flow_api/hw_mod/hw_mod_slc_lr.c',
'nthw/flow_api/hw_mod/hw_mod_tpe.c',
+ 'nthw/flow_filter/flow_backend.c',
+ 'nthw/flow_filter/flow_filter.c',
'nthw/flow_filter/flow_nthw_cat.c',
'nthw/flow_filter/flow_nthw_csu.c',
'nthw/flow_filter/flow_nthw_flm.c',
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.c b/drivers/net/ntnic/nthw/flow_api/flow_api.c
new file mode 100644
index 0000000000..2598e1e27b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api.c
@@ -0,0 +1,1306 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+
+#include "ntlog.h"
+
+#include "flow_api.h"
+
+#include "flow_api_nic_setup.h"
+#include "stream_binary_flow_api.h"
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+#include "flow_api_profile_inline.h"
+
+#define SCATTER_GATHER
+
+const char *dbg_res_descr[] = {
+ /* RES_QUEUE */ "RES_QUEUE",
+ /* RES_CAT_CFN */ "RES_CAT_CFN",
+ /* RES_CAT_COT */ "RES_CAT_COT",
+ /* RES_CAT_EXO */ "RES_CAT_EXO",
+ /* RES_CAT_LEN */ "RES_CAT_LEN",
+ /* RES_KM_FLOW_TYPE */ "RES_KM_FLOW_TYPE",
+ /* RES_KM_CATEGORY */ "RES_KM_CATEGORY",
+ /* RES_HSH_RCP */ "RES_HSH_RCP",
+ /* RES_PDB_RCP */ "RES_PDB_RCP",
+ /* RES_QSL_RCP */ "RES_QSL_RCP",
+ /* RES_QSL_LTX */ "RES_QSL_LTX",
+ /* RES_QSL_QST */ "RES_QSL_QST",
+ /* RES_SLC_RCP */ "RES_SLC_RCP",
+ /* RES_IOA_RCP */ "RES_IOA_RCP",
+ /* RES_ROA_RCP */ "RES_ROA_RCP",
+ /* RES_FLM_FLOW_TYPE */ "RES_FLM_FLOW_TYPE",
+ /* RES_FLM_RCP */ "RES_FLM_RCP",
+ /* RES_HST_RCP */ "RES_HST_RCP",
+ /* RES_TPE_RCP */ "RES_TPE_RCP",
+ /* RES_TPE_EXT */ "RES_TPE_EXT",
+ /* RES_TPE_RPL */ "RES_TPE_RPL",
+ /* RES_COUNT */ "RES_COUNT",
+ /* RES_INVALID */ "RES_INVALID"
+};
+
+static struct flow_nic_dev *dev_base;
+static pthread_mutex_t base_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * *****************************************************************************
+ * Error handling
+ * *****************************************************************************
+ */
+
+static const struct {
+ const char *message;
+} err_msg[] = {
+ /* 00 */ { "Operation successfully completed" },
+ /* 01 */ { "Operation failed" },
+ /* 02 */ { "Memory allocation failed" },
+ /* 03 */ { "Too many output destinations" },
+ /* 04 */ { "Too many output queues for RSS" },
+ /* 05 */ { "The VLAN TPID specified is not supported" },
+ /* 06 */ { "The VxLan Push header specified is not accepted" },
+ /* 07 */
+ { "While interpreting VxLan Pop action, could not find a destination port" },
+ /* 08 */ { "Failed in creating a HW-internal VTEP port" },
+ /* 09 */ { "Too many VLAN tag matches" },
+ /* 10 */ { "IPv6 invalid header specified" },
+ /* 11 */ { "Too many tunnel ports. HW limit reached" },
+ /* 12 */ { "Unknown or unsupported flow match element received" },
+ /* 13 */ { "Match failed because of HW limitations" },
+ /* 14 */ { "Match failed because of HW resource limitations" },
+ /* 15 */ { "Match failed because of too complex element definitions" },
+ /* 16 */ { "Action failed. To too many output destinations" },
+ /* 17 */ { "Action Output failed, due to HW resource exhaustion" },
+ /* 18 */
+ { "Push Tunnel Header action cannot output to multiple destination queues" },
+ /* 19 */ { "Inline action HW resource exhaustion" },
+ /* 20 */ { "Action retransmit/recirculate HW resource exhaustion" },
+ /* 21 */ { "Flow counter HW resource exhaustion" },
+ /* 22 */ { "Internal HW resource exhaustion to handle Actions" },
+ /* 23 */ { "Internal HW QSL compare failed" },
+ /* 24 */ { "Internal CAT CFN reuse failed" },
+ /* 25 */ { "Match variations too complex" },
+ /* 26 */ { "Match failed because of CAM/TCAM full" },
+ /* 27 */ { "Internal creation of a tunnel end point port failed" },
+ /* 28 */ { "Unknown or unsupported flow action received" },
+ /* 29 */ { "Removing flow failed" },
+ /* 30 */
+ { "No output queue specified. Ignore this flow offload and uses default queue" },
+ /* 31 */ { "No output queue found" },
+ /* 32 */ { "Unsupported EtherType or rejected caused by offload policy" },
+ /* 33 */
+ { "Destination port specified is invalid or not reachable from this NIC" },
+ /* 34 */ { "Partial offload is not supported in this configuration" },
+ /* 35 */ { "Match failed because of CAT CAM exhausted" },
+ /* 36 */
+ { "Match failed because of CAT CAM Key clashed with an existing KCC Key" },
+ /* 37 */ { "Match failed because of CAT CAM write failed" },
+ /* 38 */ { "Partial flow mark too big for device" },
+};
+
+void flow_nic_set_error(enum flow_nic_err_msg_e msg, struct flow_error *error)
+{
+ assert(msg < ERR_MSG_NO_MSG);
+ if (error) {
+ error->message = err_msg[msg].message;
+ error->type = (msg == ERR_SUCCESS) ? FLOW_ERROR_SUCCESS :
+ FLOW_ERROR_GENERAL;
+ }
+}
+
+/*
+ * *****************************************************************************
+ * Resources
+ * *****************************************************************************
+ */
+
+int flow_nic_alloc_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ uint32_t alignment)
+{
+ for (unsigned int i = 0; i < ndev->res[res_type].resource_count;
+ i += alignment) {
+ if (!flow_nic_is_resource_used(ndev, res_type, i)) {
+ flow_nic_mark_resource_used(ndev, res_type, i);
+ ndev->res[res_type].ref[i] = 1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+int flow_nic_alloc_resource_index(struct flow_nic_dev *ndev, int idx,
+ enum res_type_e res_type)
+{
+ if (!flow_nic_is_resource_used(ndev, res_type, idx)) {
+ flow_nic_mark_resource_used(ndev, res_type, idx);
+ ndev->res[res_type].ref[idx] = 1;
+ return 0;
+ }
+ return -1;
+}
+
+int flow_nic_alloc_resource_contig(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, unsigned int num,
+ uint32_t alignment)
+{
+ unsigned int idx_offs;
+
+ for (unsigned int res_idx = 0;
+ res_idx < ndev->res[res_type].resource_count - (num - 1);
+ res_idx += alignment) {
+ if (!flow_nic_is_resource_used(ndev, res_type, res_idx)) {
+ for (idx_offs = 1; idx_offs < num; idx_offs++) {
+ if (flow_nic_is_resource_used(ndev, res_type,
+ res_idx + idx_offs))
+ break;
+ }
+ if (idx_offs < num)
+ continue;
+
+ /* found a contiguous number of "num" res_type elements - allocate them */
+ for (idx_offs = 0; idx_offs < num; idx_offs++) {
+ flow_nic_mark_resource_used(ndev, res_type,
+ res_idx + idx_offs);
+ ndev->res[res_type].ref[res_idx + idx_offs] = 1;
+ }
+ return res_idx;
+ }
+ }
+ return -1;
+}
+
+void flow_nic_free_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int idx)
+{
+ flow_nic_mark_resource_unused(ndev, res_type, idx);
+}
+
+int flow_nic_ref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int index)
+{
+ NT_LOG(DBG, FILTER,
+ "Reference resource %s idx %i (before ref cnt %i)\n",
+ dbg_res_descr[res_type], index, ndev->res[res_type].ref[index]);
+ assert(flow_nic_is_resource_used(ndev, res_type, index));
+ if (ndev->res[res_type].ref[index] == (uint32_t)-1)
+ return -1;
+ ndev->res[res_type].ref[index]++;
+ return 0;
+}
+
+int flow_nic_deref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int index)
+{
+ NT_LOG(DBG, FILTER,
+ "De-reference resource %s idx %i (before ref cnt %i)\n",
+ dbg_res_descr[res_type], index, ndev->res[res_type].ref[index]);
+ assert(flow_nic_is_resource_used(ndev, res_type, index));
+ assert(ndev->res[res_type].ref[index]);
+ /* deref */
+ ndev->res[res_type].ref[index]--;
+ if (!ndev->res[res_type].ref[index])
+ flow_nic_free_resource(ndev, res_type, index);
+ return !!ndev->res[res_type]
+ .ref[index]; /* if 0 resource has been freed */
+}
+
+int flow_nic_find_next_used_resource(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, int idx_start)
+{
+ for (unsigned int i = idx_start; i < ndev->res[res_type].resource_count;
+ i++) {
+ if (flow_nic_is_resource_used(ndev, res_type, i))
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Allocate a number flow resources.
+ *
+ * Arguments:
+ * ndev : device
+ * res_type : resource type
+ * fh : flow handle
+ * count : number of (contiguous) resources to be allocated
+ * alignment : start index alignment
+ * 1: the allocation can start at any index
+ * 2: the allocation must start at index modulus 2 (0, 2, 4, 6, ...)
+ * 3: the allocation must start at index modulus 3 (0, 3, 6, 9, ...)
+ * etc.
+ * Returns:
+ * 0 : success
+ * -1 : failure
+ */
+int flow_nic_allocate_fh_resource(struct flow_nic_dev *ndev,
+ enum res_type_e res_type,
+ struct flow_handle *fh, uint32_t count,
+ uint32_t alignment)
+{
+ if (count > 1) {
+ /* Contiguous */
+ fh->resource[res_type].index =
+ flow_nic_alloc_resource_contig(ndev, res_type, count, alignment);
+ } else {
+ fh->resource[res_type].index =
+ flow_nic_alloc_resource(ndev, res_type, alignment);
+ }
+
+ if (fh->resource[res_type].index < 0)
+ return -1;
+ fh->resource[res_type].count = count;
+ return 0;
+}
+
+int flow_nic_allocate_fh_resource_index(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, int idx,
+ struct flow_handle *fh)
+{
+ int err = flow_nic_alloc_resource_index(ndev, idx, res_type);
+
+ if (err)
+ return err;
+
+ fh->resource[res_type].index = idx;
+ if (fh->resource[res_type].index < 0)
+ return -1;
+ fh->resource[res_type].count = 1;
+ return 0;
+}
+
+/*
+ * *****************************************************************************
+ * Hash
+ * *****************************************************************************
+ */
+
+int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx,
+ enum flow_nic_hash_e algorithm)
+{
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
+ switch (algorithm) {
+ case HASH_ALGO_5TUPLE:
+ /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE,
+ hsh_idx, 0, 2);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0,
+ DYN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0,
+ -16);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0,
+ DYN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0,
+ 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx, 0,
+ DYN_L4);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_PE, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_OFS, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_P, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK, hsh_idx, 0, 1);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 8,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 9,
+ 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_SEED, hsh_idx, 0,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_VALID, hsh_idx, 0,
+ 1);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0,
+ HASH_5TUPLE);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+
+ NT_LOG(DBG, FILTER,
+ "Set IPv6 5-tuple hasher with adaptive IPv4 hashing\n");
+ break;
+ default:
+ case HASH_ALGO_ROUND_ROBIN:
+ /* zero is round-robin */
+ break;
+ }
+
+ return 0;
+}
+
+int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx,
+ struct nt_eth_rss f)
+{
+ uint64_t fields = f.fields;
+
+ int res = 0;
+
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0,
+ 0);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, hsh_idx,
+ 0, 2);
+ switch (fields) {
+ case NT_ETH_RSS_C_VLAN:
+ /*
+ * Here we are using 1st VLAN to point C-VLAN which is only try for the single VLAN
+ * provider
+ */
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx,
+ 0, DYN_FIRST_VLAN);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx,
+ 0, 0);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK,
+ hsh_idx, 8, 0xffffffff);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE,
+ hsh_idx, 0, HASH_LAST_VLAN_ID);
+ if (res) {
+ NT_LOG(ERR, FILTER,
+ "VLAN hasher is not set hardware communication problem has "
+ "occurred. The cardware could be in inconsistent state. Rerun.\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER, "Set VLAN hasher.\n");
+ return 0;
+ case NT_ETH_RSS_LEVEL_OUTERMOST | NT_ETH_RSS_L3_DST_ONLY | NT_ETH_RSS_IP:
+ /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0,
+ DYN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0,
+ 0);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7,
+ 0xffffffff);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0,
+ HASH_OUTER_DST_IP);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+ if (res) {
+ NT_LOG(ERR, FILTER,
+ "Outer dst IP hasher is not set hardware communication problem has "
+ "occurred. The cardware could be in inconsistent state. Rerun.\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER, "Set outer dst IP hasher.\n");
+ return 0;
+ case NT_ETH_RSS_LEVEL_INNERMOST | NT_ETH_RSS_L3_SRC_ONLY | NT_ETH_RSS_IP:
+ /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0,
+ DYN_TUN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0,
+ -16);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3,
+ 0xffffffff);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0,
+ HASH_INNER_SRC_IP);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+ if (res) {
+ NT_LOG(ERR, FILTER,
+ "Inner (depth = 1) src IP hasher is not set hardware communication "
+ "problem has occurred. The cardware could be in inconsistent state. "
+ "Rerun.\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER, "Set outer dst IP hasher.\n");
+ return 0;
+ default:
+ NT_LOG(ERR, FILTER,
+ "RSS bit flags can't be set up. "
+ "Flags combination is not supported.");
+ return -1;
+ }
+}
+
+/*
+ * *****************************************************************************
+ * Nic port/adapter lookup
+ * *****************************************************************************
+ */
+
+struct flow_eth_dev *nic_and_port_to_eth_dev(uint8_t adapter_no, uint8_t port)
+{
+ struct flow_nic_dev *nic_dev = dev_base;
+
+ while (nic_dev) {
+ if (nic_dev->adapter_no == adapter_no)
+ break;
+ nic_dev = nic_dev->next;
+ }
+
+ if (!nic_dev)
+ return NULL;
+
+ struct flow_eth_dev *dev = nic_dev->eth_base;
+
+ while (dev) {
+ if (port == dev->port)
+ return dev;
+ dev = dev->next;
+ }
+
+ return NULL;
+}
+
+struct flow_nic_dev *get_nic_dev_from_adapter_no(uint8_t adapter_no)
+{
+ struct flow_nic_dev *ndev = dev_base;
+
+ while (ndev) {
+ if (adapter_no == ndev->adapter_no)
+ break;
+ ndev = ndev->next;
+ }
+ return ndev;
+}
+
+/*
+ * *****************************************************************************
+ * LAG control implementation
+ * *****************************************************************************
+ */
+
+int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+ /*
+ * Sets each 2 ports for each bit N as Lag. Ports N*2+N*2+1 are merged together
+ * and reported as N*2 incoming port
+ */
+ hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_LAG_PHY_ODD_EVEN, port_mask);
+ hw_mod_rmc_ctrl_flush(&ndev->be);
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+}
+
+int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+ /* Blocks for traffic from port */
+ hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_MAC_PORT, port_mask);
+ hw_mod_rmc_ctrl_flush(&ndev->be);
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+}
+
+static void write_lag_entry(struct flow_api_backend_s *be, uint32_t index,
+ uint32_t value)
+{
+ hw_mod_roa_lagcfg_set(be, HW_ROA_LAGCFG_TXPHY_PORT, index, value);
+ hw_mod_roa_lagcfg_flush(be, index, 1);
+}
+
+int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index,
+ uint32_t value)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+
+ switch (cmd) {
+ case FLOW_LAG_SET_ENTRY:
+ write_lag_entry(&ndev->be, index, value);
+ break;
+
+ case FLOW_LAG_SET_ALL:
+ index &= 3;
+ for (unsigned int i = 0; i < ndev->be.roa.nb_lag_entries;
+ i += 4)
+ write_lag_entry(&ndev->be, i + index, value);
+ break;
+
+ case FLOW_LAG_SET_BALANCE:
+ /*
+ * This function will balance the output port
+ * value: The balance of the distribution:
+ * port P0 / P1
+ * 0: 0 / 100 port 0 is disabled
+ * 25: 25 / 75
+ * 50: 50 / 50
+ * 75: 75 / 25
+ * 100: 100/ 0 port 1 is disabled
+ */
+ {
+ /* Clamp the balance to 100% output on port 1 */
+ if (value > 100)
+ value = 100;
+ double balance = ((double)value / 100.0);
+ double block_count =
+ (double)ndev->be.roa.nb_lag_entries / 4.0;
+
+ int output_port = 1;
+ int port0_output_block_count =
+ (int)(block_count * balance);
+
+ for (int block = 0; block < block_count; block++) {
+ /* When the target port0 balance is reached. */
+ if (block >= port0_output_block_count)
+ output_port = 2;
+ /* Write an entire hash block to a given output port. */
+ for (int idx = 0; idx < 4; idx++) {
+ write_lag_entry(&ndev->be,
+ block * 4 + idx,
+ output_port);
+ } /* for each index in hash block */
+ } /* for each hash block */
+ }
+
+ break;
+ default:
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+}
+
+/*
+ * *****************************************************************************
+ * Flow API
+ * *****************************************************************************
+ */
+
+int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[],
+ const struct flow_action action[], struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_validate_profile_inline(dev, item, action, error);
+}
+
+struct flow_handle *flow_create(struct flow_eth_dev *dev,
+ const struct flow_attr *attr,
+ const struct flow_elem item[],
+ const struct flow_action action[],
+ struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return NULL;
+ }
+ return flow_create_profile_inline(dev, attr, item, action, error);
+}
+
+int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow,
+ struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_destroy_profile_inline(dev, flow, error);
+}
+
+int flow_flush(struct flow_eth_dev *dev, struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_flush_profile_inline(dev, error);
+}
+
+int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow,
+ const struct flow_action *action, void **data, uint32_t *length,
+ struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_query_profile_inline(dev, flow, action, data, length,
+ error);
+}
+
+/*
+ * *****************************************************************************
+ * Device Management API
+ * *****************************************************************************
+ */
+
+static void nic_insert_eth_port_dev(struct flow_nic_dev *ndev,
+ struct flow_eth_dev *dev)
+{
+ dev->next = ndev->eth_base;
+ ndev->eth_base = dev;
+}
+
+static int nic_remove_eth_port_dev(struct flow_nic_dev *ndev,
+ struct flow_eth_dev *eth_dev)
+{
+ struct flow_eth_dev *dev = ndev->eth_base, *prev = NULL;
+
+ while (dev) {
+ if (dev == eth_dev) {
+ if (prev)
+ prev->next = dev->next;
+
+ else
+ ndev->eth_base = dev->next;
+ return 0;
+ }
+ prev = dev;
+ dev = dev->next;
+ }
+ return -1;
+}
+
+static void flow_ndev_reset(struct flow_nic_dev *ndev)
+{
+ /* Delete all eth-port devices created on this NIC device */
+ while (ndev->eth_base)
+ flow_delete_eth_dev(ndev->eth_base);
+
+ /* Error check */
+ while (ndev->flow_base) {
+ NT_LOG(ERR, FILTER,
+ "ERROR : Flows still defined but all eth-ports deleted. Flow %p\n",
+ ndev->flow_base);
+
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return;
+ }
+ flow_destroy_profile_inline(ndev->flow_base->dev,
+ ndev->flow_base, NULL);
+ }
+
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return;
+ }
+ done_flow_management_of_ndev_profile_inline(ndev);
+
+ km_free_ndev_resource_management(&ndev->km_res_handle);
+ kcc_free_ndev_resource_management(&ndev->kcc_res_handle);
+
+#ifdef FLOW_DEBUG
+ /*
+ * free all resources default allocated, initially for this NIC DEV
+ * Is not really needed since the bitmap will be freed in a sec. Therefore
+ * only in debug mode
+ */
+
+ /* Check if all resources has been released */
+ NT_LOG(DBG, FILTER, "Delete NIC DEV Adaptor %i\n", ndev->adapter_no);
+ for (unsigned int i = 0; i < RES_COUNT; i++) {
+ int err = 0;
+#if defined(FLOW_DEBUG)
+ NT_LOG(DBG, FILTER, "RES state for: %s\n", dbg_res_descr[i]);
+#endif
+ for (unsigned int ii = 0; ii < ndev->res[i].resource_count;
+ ii++) {
+ int ref = ndev->res[i].ref[ii];
+ int used = flow_nic_is_resource_used(ndev, i, ii);
+
+ if (ref || used) {
+ NT_LOG(DBG, FILTER,
+ " [%i]: ref cnt %i, used %i\n", ii, ref,
+ used);
+ err = 1;
+ }
+ }
+ if (err)
+ NT_LOG(DBG, FILTER,
+ "ERROR - some resources not freed\n");
+ }
+#endif
+}
+
+int flow_reset_nic_dev(uint8_t adapter_no)
+{
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev)
+ return -1;
+ flow_ndev_reset(ndev);
+ flow_api_backend_reset(&ndev->be);
+ return 0;
+}
+
+/*
+ * adapter_no physical adapter no
+ * port_no local port no
+ * alloc_rx_queues number of rx-queues to allocate for this eth_dev
+ */
+struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t port_no,
+ uint32_t port_id, int alloc_rx_queues,
+ struct flow_queue_id_s queue_ids[],
+ int *rss_target_id,
+ enum flow_eth_dev_profile flow_profile,
+ uint32_t exception_path)
+{
+ int i;
+ struct flow_eth_dev *eth_dev = NULL;
+
+ NT_LOG(DBG, FILTER,
+ "Get eth-port adapter %i, port %i, port_id %u, rx queues %i, profile %i\n",
+ adapter_no, port_no, port_id, alloc_rx_queues, flow_profile);
+
+ if (MAX_OUTPUT_DEST < FLOW_MAX_QUEUES) {
+ assert(0);
+ NT_LOG(ERR, FILTER,
+ "ERROR: Internal array for multiple queues too small for API\n");
+ }
+
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error - no flow api found on specified adapter */
+ NT_LOG(ERR, FILTER,
+ "ERROR: no flow interface registered for adapter %d\n",
+ adapter_no);
+ pthread_mutex_unlock(&base_mtx);
+ return NULL;
+ }
+
+ if (ndev->ports < ((uint16_t)port_no + 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: port exceeds supported port range for adapter\n");
+ pthread_mutex_unlock(&base_mtx);
+ return NULL;
+ }
+
+ if ((alloc_rx_queues - 1) >
+ FLOW_MAX_QUEUES) { /* 0th is exception so +1 */
+ NT_LOG(ERR, FILTER,
+ "ERROR: Exceeds supported number of rx queues per eth device\n");
+ pthread_mutex_unlock(&base_mtx);
+ return NULL;
+ }
+
+ /* don't accept multiple eth_dev's on same NIC and same port */
+ eth_dev = nic_and_port_to_eth_dev(adapter_no, port_no);
+ if (eth_dev) {
+ NT_LOG(DBG, FILTER,
+ "Re-opening existing NIC port device: NIC DEV: %i Port %i\n",
+ adapter_no, port_no);
+ pthread_mutex_unlock(&base_mtx);
+ flow_delete_eth_dev(eth_dev);
+ eth_dev = NULL;
+ }
+
+ eth_dev = calloc(1, sizeof(struct flow_eth_dev));
+ if (!eth_dev) {
+ NT_LOG(ERR, FILTER, "ERROR: calloc failed\n");
+ goto err_exit1;
+ }
+
+ pthread_mutex_lock(&ndev->mtx);
+
+ eth_dev->ndev = ndev;
+ eth_dev->port = port_no;
+ eth_dev->port_id = port_id;
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ /* First time then NIC is initialized */
+ if (!ndev->flow_mgnt_prepared) {
+ ndev->flow_profile = flow_profile;
+ /* Initialize modules if needed - recipe 0 is used as no-match and must be setup */
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ goto err_exit0;
+ } else if (initialize_flow_management_of_ndev_profile_inline(ndev)
+ != 0) {
+ goto err_exit0;
+ }
+ } else {
+ /* check if same flow type is requested, otherwise fail */
+ if (ndev->flow_profile != flow_profile) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Different flow types requested on same NIC device. "
+ "Not supported.\n");
+ goto err_exit0;
+ }
+ }
+
+ /* Allocate the requested queues in HW for this dev */
+
+ for (i = 0; i < alloc_rx_queues; i++) {
+#ifdef SCATTER_GATHER
+ eth_dev->rx_queue[i] = queue_ids[i];
+#else
+ int queue_id = flow_nic_alloc_resource(ndev, RES_QUEUE, 1);
+
+ if (queue_id < 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: no more free queue IDs in NIC\n");
+ goto err_exit0;
+ }
+
+ eth_dev->rx_queue[eth_dev->num_queues].id = (uint8_t)queue_id;
+ eth_dev->rx_queue[eth_dev->num_queues].hw_id =
+ ndev->be.iface->alloc_rx_queue(ndev->be.be_dev,
+ eth_dev->rx_queue[eth_dev->num_queues].id);
+ if (eth_dev->rx_queue[eth_dev->num_queues].hw_id < 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: could not allocate a new queue\n");
+ goto err_exit0;
+ }
+
+ if (queue_ids) {
+ queue_ids[eth_dev->num_queues] =
+ eth_dev->rx_queue[eth_dev->num_queues];
+ }
+#endif
+ if (i == 0 && (flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH ||
+ (flow_profile == FLOW_ETH_DEV_PROFILE_INLINE &&
+ exception_path))) {
+ /*
+ * Init QSL UNM - unmatched - redirects otherwise discarded packets in QSL
+ */
+ if (hw_mod_qsl_unmq_set(&ndev->be,
+ HW_QSL_UNMQ_DEST_QUEUE,
+ eth_dev->port,
+ eth_dev->rx_queue[0].hw_id) < 0)
+ goto err_exit0;
+ if (hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_EN,
+ eth_dev->port, 1) < 0)
+ goto err_exit0;
+ if (hw_mod_qsl_unmq_flush(&ndev->be, eth_dev->port, 1) <
+ 0)
+ goto err_exit0;
+ }
+
+ eth_dev->num_queues++;
+ }
+
+ eth_dev->rss_target_id = -1;
+
+ if (flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) {
+ for (i = 0; i < eth_dev->num_queues; i++) {
+ uint32_t qen_value = 0;
+ uint32_t queue_id =
+ (uint32_t)eth_dev->rx_queue[i].hw_id;
+
+ hw_mod_qsl_qen_get(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4, &qen_value);
+ hw_mod_qsl_qen_set(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4,
+ qen_value | (1 << (queue_id % 4)));
+ hw_mod_qsl_qen_flush(&ndev->be, queue_id / 4, 1);
+ }
+ }
+
+ *rss_target_id = eth_dev->rss_target_id;
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ nic_insert_eth_port_dev(ndev, eth_dev);
+
+ pthread_mutex_unlock(&ndev->mtx);
+ pthread_mutex_unlock(&base_mtx);
+ return eth_dev;
+
+err_exit0:
+ pthread_mutex_unlock(&ndev->mtx);
+ pthread_mutex_unlock(&base_mtx);
+
+err_exit1:
+ if (eth_dev)
+ free(eth_dev);
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ NT_LOG(DBG, FILTER, "ERR in %s\n", __func__);
+ return NULL; /* Error exit */
+}
+
+int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev,
+ struct flow_queue_id_s *queue_id)
+{
+ uint32_t qen_value = 0;
+
+ eth_dev->rx_queue[eth_dev->num_queues].id = queue_id->id;
+ eth_dev->rx_queue[eth_dev->num_queues].hw_id = queue_id->hw_id;
+ eth_dev->num_queues += 1;
+
+ hw_mod_qsl_qen_get(ð_dev->ndev->be, HW_QSL_QEN_EN,
+ queue_id->hw_id / 4, &qen_value);
+ hw_mod_qsl_qen_set(ð_dev->ndev->be, HW_QSL_QEN_EN,
+ queue_id->hw_id / 4,
+ qen_value | (1 << (queue_id->hw_id % 4)));
+ hw_mod_qsl_qen_flush(ð_dev->ndev->be, queue_id->hw_id / 4, 1);
+
+ return 0;
+}
+
+int flow_delete_eth_dev(struct flow_eth_dev *eth_dev)
+{
+ struct flow_nic_dev *ndev = eth_dev->ndev;
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ return -1;
+ }
+
+ NT_LOG(DBG, FILTER, "Delete eth-port device %p, port %i\n", eth_dev,
+ eth_dev->port);
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ /* delete all created flows from this device */
+ pthread_mutex_lock(&ndev->mtx);
+
+ struct flow_handle *flow = ndev->flow_base;
+
+ while (flow) {
+ if (flow->dev == eth_dev) {
+ struct flow_handle *flow_next = flow->next;
+
+ if (ndev->flow_profile ==
+ FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ flow_destroy_locked_profile_inline(eth_dev,
+ flow, NULL);
+ flow = flow_next;
+ } else {
+ flow = flow->next;
+ }
+ }
+
+ /*
+ * remove unmatched queue if setup in QSL
+ * remove exception queue setting in QSL UNM
+ */
+ hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_DEST_QUEUE, eth_dev->port,
+ 0);
+ hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_EN, eth_dev->port, 0);
+ hw_mod_qsl_unmq_flush(&ndev->be, eth_dev->port, 1);
+
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) {
+ for (int i = 0; i < eth_dev->num_queues; ++i) {
+ uint32_t qen_value = 0;
+ uint32_t queue_id =
+ (uint32_t)eth_dev->rx_queue[i].hw_id;
+
+ hw_mod_qsl_qen_get(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4, &qen_value);
+ hw_mod_qsl_qen_set(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4,
+ qen_value & ~(1U << (queue_id % 4)));
+ hw_mod_qsl_qen_flush(&ndev->be, queue_id / 4, 1);
+ }
+ }
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+#ifndef SCATTER_GATHER
+ /* free rx queues */
+ for (int i = 0; i < eth_dev->num_queues; i++) {
+ ndev->be.iface->free_rx_queue(ndev->be.be_dev,
+ eth_dev->rx_queue[i].hw_id);
+ flow_nic_deref_resource(ndev, RES_QUEUE,
+ eth_dev->rx_queue[i].id);
+ }
+#endif
+
+ /* take eth_dev out of ndev list */
+ if (nic_remove_eth_port_dev(ndev, eth_dev) != 0)
+ NT_LOG(ERR, FILTER, "ERROR : eth_dev %p not found\n", eth_dev);
+
+ pthread_mutex_unlock(&ndev->mtx);
+
+ /* free eth_dev */
+ free(eth_dev);
+ return 0;
+}
+
+int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,
+ uint8_t vport)
+{
+ return tunnel_get_definition(tun, flow_stat_id, vport);
+}
+
+/*
+ * ***************************** Flow API NIC Setup ***************************************
+ * Flow backend creation function - register and initialize common backend API to FPA modules
+ * ******************************************************************************************
+ */
+
+static int init_resource_elements(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, uint32_t count)
+{
+ assert(ndev->res[res_type].alloc_bm == NULL);
+ /* allocate bitmap and ref counter */
+ ndev->res[res_type].alloc_bm =
+ calloc(1, BIT_CONTAINER_8_ALIGN(count) + count * sizeof(uint32_t));
+ if (ndev->res[res_type].alloc_bm) {
+ ndev->res[res_type].ref =
+ (uint32_t *)&ndev->res[res_type]
+ .alloc_bm[BIT_CONTAINER_8_ALIGN(count)];
+ ndev->res[res_type].resource_count = count;
+ return 0;
+ }
+ return -1;
+}
+
+static void done_resource_elements(struct flow_nic_dev *ndev,
+ enum res_type_e res_type)
+{
+ assert(ndev);
+ if (ndev->res[res_type].alloc_bm)
+ free(ndev->res[res_type].alloc_bm);
+}
+
+static void list_insert_flow_nic(struct flow_nic_dev *ndev)
+{
+ pthread_mutex_lock(&base_mtx);
+ ndev->next = dev_base;
+ dev_base = ndev;
+ pthread_mutex_unlock(&base_mtx);
+}
+
+static int list_remove_flow_nic(struct flow_nic_dev *ndev)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *nic_dev = dev_base, *prev = NULL;
+
+ while (nic_dev) {
+ if (nic_dev == ndev) {
+ if (prev)
+ prev->next = nic_dev->next;
+ else
+ dev_base = nic_dev->next;
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+ }
+ prev = nic_dev;
+ nic_dev = nic_dev->next;
+ }
+
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+}
+
+struct flow_nic_dev *flow_api_create(uint8_t adapter_no,
+ const struct flow_api_backend_ops *be_if,
+ void *be_dev)
+{
+ if (!be_if || be_if->version != 1) {
+ NT_LOG(DBG, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+ }
+
+ struct flow_nic_dev *ndev = calloc(1, sizeof(struct flow_nic_dev));
+
+ if (!ndev) {
+ NT_LOG(ERR, FILTER, "ERROR: calloc failed\n");
+ return NULL;
+ }
+
+ /*
+ * To dump module initialization writes use
+ * FLOW_BACKEND_DEBUG_MODE_WRITE
+ * then remember to set it ...NONE afterwards again
+ */
+ be_if->set_debug_mode(be_dev, FLOW_BACKEND_DEBUG_MODE_NONE);
+
+ if (flow_api_backend_init(&ndev->be, be_if, be_dev) != 0)
+ goto err_exit;
+ ndev->adapter_no = adapter_no;
+
+ ndev->ports = (uint16_t)((ndev->be.num_rx_ports > 256) ?
+ 256 :
+ ndev->be.num_rx_ports);
+
+ /*
+ * Free resources in NIC must be managed by this module
+ * Get resource sizes and create resource manager elements
+ */
+ if (init_resource_elements(ndev, RES_QUEUE, ndev->be.max_queues))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_CFN,
+ ndev->be.cat.nb_cat_funcs))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_COT, ndev->be.max_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_EXO, ndev->be.cat.nb_pm_ext))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_LEN, ndev->be.cat.nb_len))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_KM_FLOW_TYPE,
+ ndev->be.cat.nb_flow_types))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_KM_CATEGORY,
+ ndev->be.km.nb_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_HSH_RCP, ndev->be.hsh.nb_rcp))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_PDB_RCP,
+ ndev->be.pdb.nb_pdb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_QSL_RCP,
+ ndev->be.qsl.nb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_QSL_QST,
+ ndev->be.qsl.nb_qst_entries))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_SLC_RCP, ndev->be.max_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_IOA_RCP,
+ ndev->be.ioa.nb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_ROA_RCP,
+ ndev->be.roa.nb_tun_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_FLM_FLOW_TYPE,
+ ndev->be.cat.nb_flow_types))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_FLM_RCP,
+ ndev->be.flm.nb_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_HST_RCP,
+ ndev->be.hst.nb_hst_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_TPE_RCP,
+ ndev->be.tpe.nb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_TPE_EXT,
+ ndev->be.tpe.nb_rpl_ext_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_TPE_RPL,
+ ndev->be.tpe.nb_rpl_depth))
+ goto err_exit;
+
+ /* may need IPF, COR */
+
+ /* check all defined has been initialized */
+ for (int i = 0; i < RES_COUNT; i++)
+ assert(ndev->res[i].alloc_bm);
+
+ pthread_mutex_init(&ndev->mtx, NULL);
+ list_insert_flow_nic(ndev);
+
+ return ndev;
+
+err_exit:
+ if (ndev)
+ flow_api_done(ndev);
+ NT_LOG(DBG, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+}
+
+int flow_api_done(struct flow_nic_dev *ndev)
+{
+ NT_LOG(DBG, FILTER, "FLOW API DONE\n");
+ if (ndev) {
+ flow_ndev_reset(ndev);
+
+ /* delete resource management allocations for this ndev */
+ for (int i = 0; i < RES_COUNT; i++)
+ done_resource_elements(ndev, i);
+
+ flow_api_backend_done(&ndev->be);
+ list_remove_flow_nic(ndev);
+ free(ndev);
+ }
+ return 0;
+}
+
+void *flow_api_get_be_dev(struct flow_nic_dev *ndev)
+{
+ if (!ndev) {
+ NT_LOG(DBG, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+ }
+ return ndev->be.be_dev;
+}
+
+int flow_get_num_queues(uint8_t adapter_no, uint8_t port_no)
+{
+ struct flow_eth_dev *eth_dev =
+ nic_and_port_to_eth_dev(adapter_no, port_no);
+ return eth_dev->num_queues;
+}
+
+int flow_get_hw_id(uint8_t adapter_no, uint8_t port_no, uint8_t queue_no)
+{
+ struct flow_eth_dev *eth_dev =
+ nic_and_port_to_eth_dev(adapter_no, port_no);
+ return eth_dev->rx_queue[queue_no].hw_id;
+}
+
+int flow_get_flm_stats(struct flow_nic_dev *ndev, uint64_t *data, uint64_t size)
+{
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_INLINE)
+ return flow_get_flm_stats_profile_inline(ndev, data, size);
+ return -1;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.h b/drivers/net/ntnic/nthw/flow_api/flow_api.h
new file mode 100644
index 0000000000..f4b86899a8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api.h
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_API_H_
+#define _FLOW_API_H_
+
+#include <pthread.h>
+
+#include "ntlog.h"
+#include "stream_binary_flow_api.h"
+
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+/*
+ * ****************************************************
+ * Flow NIC and Eth port device management
+ * ****************************************************
+ */
+
+struct hw_mod_resource_s {
+ uint8_t *alloc_bm; /* allocation bitmap */
+ uint32_t *ref; /* reference counter for each resource element */
+ uint32_t resource_count; /* number of total available entries */
+};
+
+/*
+ * Set of definitions to be used to map desirable fields for RSS
+ * hash functions. Supposed to be used with dpdk, so the values
+ * correspond to dpdk definitions, but we avoid dependency to
+ * dpdk headers here.
+ */
+
+#define NT_ETH_RSS_IPV4 (UINT64_C(1) << 2)
+#define NT_ETH_RSS_FRAG_IPV4 (UINT64_C(1) << 3)
+#define NT_ETH_RSS_NONFRAG_IPV4_OTHER (UINT64_C(1) << 7)
+#define NT_ETH_RSS_IPV6 (UINT64_C(1) << 8)
+#define NT_ETH_RSS_FRAG_IPV6 (UINT64_C(1) << 9)
+#define NT_ETH_RSS_NONFRAG_IPV6_OTHER (UINT64_C(1) << 13)
+#define NT_ETH_RSS_IPV6_EX (UINT64_C(1) << 15)
+#define NT_ETH_RSS_C_VLAN (UINT64_C(1) << 26)
+#define NT_ETH_RSS_L3_DST_ONLY (UINT64_C(1) << 62)
+#define NT_ETH_RSS_L3_SRC_ONLY (UINT64_C(1) << 63)
+
+#define NT_ETH_RSS_IP \
+ (NT_ETH_RSS_IPV4 | NT_ETH_RSS_FRAG_IPV4 | \
+ NT_ETH_RSS_NONFRAG_IPV4_OTHER | NT_ETH_RSS_IPV6 | \
+ NT_ETH_RSS_FRAG_IPV6 | NT_ETH_RSS_NONFRAG_IPV6_OTHER | \
+ NT_ETH_RSS_IPV6_EX)
+
+/*
+ * level 1, requests RSS to be performed on the outermost packet
+ * encapsulation level.
+ */
+#define NT_ETH_RSS_LEVEL_OUTERMOST (UINT64_C(1) << 50)
+
+/*
+ * level 2, requests RSS to be performed on the specified inner packet
+ * encapsulation level, from outermost to innermost (lower to higher values).
+ */
+#define NT_ETH_RSS_LEVEL_INNERMOST (UINT64_C(2) << 50)
+
+/*
+ * Struct wrapping unsigned 64 bit integer carry RSS hash option bits
+ * to avoid occasional incorrect usage interfacing with higher level
+ * framework (e.g. DPDK)
+ */
+struct nt_eth_rss {
+ uint64_t fields;
+};
+
+struct flow_eth_dev {
+ struct flow_nic_dev *ndev; /* NIC that owns this port device */
+ uint8_t port; /* NIC port id */
+ uint32_t port_id; /* App assigned port_id - may be DPDK port_id */
+
+ struct flow_queue_id_s
+ rx_queue[FLOW_MAX_QUEUES + 1]; /* 0th for exception */
+ int num_queues; /* VSWITCH has exceptions sent on queue 0 per design */
+
+ int rss_target_id; /* QSL_HSH index if RSS needed QSL v6+ */
+ struct flow_eth_dev *next;
+};
+
+enum flow_nic_hash_e {
+ HASH_ALGO_ROUND_ROBIN = 0,
+ HASH_ALGO_5TUPLE,
+};
+
+/* registered NIC backends */
+struct flow_nic_dev {
+ uint8_t adapter_no; /* physical adapter no in the host system */
+ uint16_t ports; /* number of in-ports addressable on this NIC */
+ enum flow_eth_dev_profile
+ flow_profile; /* flow profile this NIC is initially prepared for */
+ int flow_mgnt_prepared;
+
+ struct hw_mod_resource_s
+ res[RES_COUNT]; /* raw NIC resource allocation table */
+ void *flm_res_handle;
+ void *km_res_handle;
+ void *kcc_res_handle;
+
+ void *flm_mtr_handle;
+ void *ft_res_handle;
+ void *mtr_stat_handle;
+ void *group_handle;
+
+ /* statistics */
+ uint32_t flow_stat_id_map[MAX_COLOR_FLOW_STATS];
+
+ struct flow_handle
+ *flow_base; /* linked list of all flows created on this NIC */
+ struct flow_handle *
+ flow_base_flm; /* linked list of all FLM flows created on this NIC */
+
+ struct flow_api_backend_s be; /* NIC backend API */
+ struct flow_eth_dev *
+ eth_base; /* linked list of created eth-port devices on this NIC */
+ pthread_mutex_t mtx;
+
+ int default_qsl_drop_index; /* pre allocated default QSL Drop */
+ int default_qsl_discard_index; /* pre allocated default QSL Discard */
+ /* RSS hash function settings bitfields correspond to data used for hashing */
+ struct nt_eth_rss
+ rss_hash_config;
+ struct flow_nic_dev *next; /* next NIC linked list */
+};
+
+/*
+ * ****************************************************
+ * Error
+ * ****************************************************
+ */
+
+enum flow_nic_err_msg_e {
+ ERR_SUCCESS = 0,
+ ERR_FAILED = 1,
+ ERR_MEMORY = 2,
+ ERR_OUTPUT_TOO_MANY = 3,
+ ERR_RSS_TOO_MANY_QUEUES = 4,
+ ERR_VLAN_TYPE_NOT_SUPPORTED = 5,
+ ERR_VXLAN_HEADER_NOT_ACCEPTED = 6,
+ ERR_VXLAN_POP_INVALID_RECIRC_PORT = 7,
+ ERR_VXLAN_POP_FAILED_CREATING_VTEP = 8,
+ ERR_MATCH_VLAN_TOO_MANY = 9,
+ ERR_MATCH_INVALID_IPV6_HDR = 10,
+ ERR_MATCH_TOO_MANY_TUNNEL_PORTS = 11,
+ ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM = 12,
+ ERR_MATCH_FAILED_BY_HW_LIMITS = 13,
+ ERR_MATCH_RESOURCE_EXHAUSTION = 14,
+ ERR_MATCH_FAILED_TOO_COMPLEX = 15,
+ ERR_ACTION_REPLICATION_FAILED = 16,
+ ERR_ACTION_OUTPUT_RESOURCE_EXHAUSTION = 17,
+ ERR_ACTION_TUNNEL_HEADER_PUSH_OUTPUT_LIMIT = 18,
+ ERR_ACTION_INLINE_MOD_RESOURCE_EXHAUSTION = 19,
+ ERR_ACTION_RETRANSMIT_RESOURCE_EXHAUSTION = 20,
+ ERR_ACTION_FLOW_COUNTER_EXHAUSTION = 21,
+ ERR_ACTION_INTERNAL_RESOURCE_EXHAUSTION = 22,
+ ERR_INTERNAL_QSL_COMPARE_FAILED = 23,
+ ERR_INTERNAL_CAT_FUNC_REUSE_FAILED = 24,
+ ERR_MATCH_ENTROPHY_FAILED = 25,
+ ERR_MATCH_CAM_EXHAUSTED = 26,
+ ERR_INTERNAL_VIRTUAL_PORT_CREATION_FAILED = 27,
+ ERR_ACTION_UNSUPPORTED = 28,
+ ERR_REMOVE_FLOW_FAILED = 29,
+ ERR_ACTION_NO_OUTPUT_DEFINED_USE_DEFAULT = 30,
+ ERR_ACTION_NO_OUTPUT_QUEUE_FOUND = 31,
+ ERR_MATCH_UNSUPPORTED_ETHER_TYPE = 32,
+ ERR_OUTPUT_INVALID = 33,
+ ERR_MATCH_PARTIAL_OFFLOAD_NOT_SUPPORTED = 34,
+ ERR_MATCH_CAT_CAM_EXHAUSTED = 35,
+ ERR_MATCH_KCC_KEY_CLASH = 36,
+ ERR_MATCH_CAT_CAM_FAILED = 37,
+ ERR_PARTIAL_FLOW_MARK_TOO_BIG = 38,
+ ERR_FLOW_PRIORITY_VALUE_INVALID = 39,
+ ERR_MSG_NO_MSG
+};
+
+void flow_nic_set_error(enum flow_nic_err_msg_e msg, struct flow_error *error);
+
+/*
+ * ****************************************************
+ * Resources
+ * ****************************************************
+ */
+
+extern const char *dbg_res_descr[];
+
+#define flow_nic_set_bit(arr, x) \
+ do { \
+ uint8_t *_temp_arr = (arr); \
+ size_t _temp_x = (x); \
+ _temp_arr[_temp_x / 8] = (uint8_t)(_temp_arr[_temp_x / 8] | \
+ (uint8_t)(1 << (_temp_x % 8))); \
+ } while (0)
+
+
+
+#define flow_nic_unset_bit(arr, x) \
+ do { \
+ size_t _temp_x = (x); \
+ arr[_temp_x / 8] &= (uint8_t)~(1 << (_temp_x % 8)); \
+ } while (0)
+
+#define flow_nic_is_bit_set(arr, x) \
+ ({ \
+ size_t _temp_x = (x); \
+ (arr[_temp_x / 8] & (uint8_t)(1 << (_temp_x % 8))); \
+ })
+
+#define flow_nic_mark_resource_used(_ndev, res_type, index) \
+ do { \
+ struct flow_nic_dev *_temp_ndev = (_ndev); \
+ __typeof__(res_type) _temp_res_type = (res_type); \
+ size_t _temp_index = (index); \
+ NT_LOG(DBG, FILTER, "mark resource used: %s idx %zu\n", \
+ dbg_res_descr[_temp_res_type], _temp_index); \
+ assert(flow_nic_is_bit_set(_temp_ndev->res[_temp_res_type].alloc_bm, _temp_index) \
+ == 0); \
+ flow_nic_set_bit(_temp_ndev->res[_temp_res_type].alloc_bm, _temp_index); \
+ } while (0)
+
+
+
+#define flow_nic_mark_resource_unused(_ndev, res_type, index) \
+ do { \
+ __typeof__(res_type) _temp_res_type = (res_type); \
+ size_t _temp_index = (index); \
+ NT_LOG(DBG, FILTER, "mark resource unused: %s idx %zu\n", \
+ dbg_res_descr[_temp_res_type], _temp_index); \
+ flow_nic_unset_bit((_ndev)->res[_temp_res_type].alloc_bm, _temp_index); \
+ } while (0)
+
+
+#define flow_nic_is_resource_used(_ndev, res_type, index) \
+ (!!flow_nic_is_bit_set((_ndev)->res[res_type].alloc_bm, index))
+
+int flow_nic_alloc_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ uint32_t alignment);
+int flow_nic_alloc_resource_index(struct flow_nic_dev *ndev, int idx,
+ enum res_type_e res_type);
+int flow_nic_alloc_resource_contig(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, unsigned int num,
+ uint32_t alignment);
+void flow_nic_free_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int idx);
+
+int flow_nic_ref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int index);
+int flow_nic_deref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int index);
+int flow_nic_find_next_used_resource(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, int idx_start);
+
+int flow_nic_allocate_fh_resource(struct flow_nic_dev *ndev,
+ enum res_type_e res_type,
+ struct flow_handle *fh, uint32_t count,
+ uint32_t alignment);
+int flow_nic_allocate_fh_resource_index(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, int idx,
+ struct flow_handle *fh);
+
+/*
+ * ****************************************************
+ * Other
+ * ****************************************************
+ */
+
+struct flow_eth_dev *nic_and_port_to_eth_dev(uint8_t adapter_no, uint8_t port);
+struct flow_nic_dev *get_nic_dev_from_adapter_no(uint8_t adapter_no);
+
+int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx,
+ enum flow_nic_hash_e algorithm);
+int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx,
+ struct nt_eth_rss fields);
+
+int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index,
+ uint32_t value);
+int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask);
+int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask);
+
+int flow_get_num_queues(uint8_t adapter_no, uint8_t port_no);
+int flow_get_hw_id(uint8_t adapter_no, uint8_t port_no, uint8_t queue_no);
+
+int flow_get_flm_stats(struct flow_nic_dev *ndev, uint64_t *data,
+ uint64_t size);
+
+#endif
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c
new file mode 100644
index 0000000000..782988554b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c
@@ -0,0 +1,5118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pthread.h>
+#include <unistd.h> /* sleep() */
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+#include <stdatomic.h>
+
+#include <inttypes.h>
+
+#include "ntlog.h"
+
+#include "flow_api_nic_setup.h"
+#include "stream_binary_flow_api.h"
+#include "flow_api.h"
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+#include "flow_api_profile_inline.h"
+
+#include <rte_spinlock.h>
+
+#define UNUSED __rte_unused
+
+/*
+ * lookup refers to key A/B/C/D, and can have values 0, 1, 2, and 3.
+ */
+static int set_flow_type_km(struct flow_nic_dev *ndev, int cfn_index,
+ int flow_type, int lookup, int enable)
+{
+ const int max_lookups = 4;
+ const int cat_funcs = (int)ndev->be.cat.nb_cat_funcs / 8;
+
+ int fte_index =
+ (8 * flow_type + cfn_index / cat_funcs) * max_lookups + lookup;
+ int fte_field = cfn_index % cat_funcs;
+
+ uint32_t current_bm = 0;
+ uint32_t fte_field_bm = 1 << fte_field;
+
+ hw_mod_cat_fte_km_get(&ndev->be, HW_CAT_FTE_ENABLE_BM, KM_FLM_IF_FIRST,
+ fte_index, ¤t_bm);
+
+ uint32_t final_bm = enable ? (fte_field_bm | current_bm) :
+ (~fte_field_bm & current_bm);
+
+ if (current_bm != final_bm) {
+ hw_mod_cat_fte_km_set(&ndev->be, HW_CAT_FTE_ENABLE_BM,
+ KM_FLM_IF_FIRST, fte_index, final_bm);
+ hw_mod_cat_fte_km_flush(&ndev->be, KM_FLM_IF_FIRST, fte_index,
+ 1);
+ }
+
+ return 0;
+}
+
+/*
+ * lookup refers to key A/B/C/D, and can have values 0, 1, 2, and 3.
+ */
+static int set_flow_type_flm(struct flow_nic_dev *ndev, int cfn_index,
+ int flow_type, int lookup, int enable)
+{
+ const int max_lookups = 4;
+ const int cat_funcs = (int)ndev->be.cat.nb_cat_funcs / 8;
+
+ int fte_index =
+ (8 * flow_type + cfn_index / cat_funcs) * max_lookups + lookup;
+ int fte_field = cfn_index % cat_funcs;
+
+ uint32_t current_bm = 0;
+ uint32_t fte_field_bm = 1 << fte_field;
+
+ hw_mod_cat_fte_flm_get(&ndev->be, HW_CAT_FTE_ENABLE_BM, KM_FLM_IF_FIRST,
+ fte_index, ¤t_bm);
+
+ uint32_t final_bm = enable ? (fte_field_bm | current_bm) :
+ (~fte_field_bm & current_bm);
+
+ if (current_bm != final_bm) {
+ hw_mod_cat_fte_flm_set(&ndev->be, HW_CAT_FTE_ENABLE_BM,
+ KM_FLM_IF_FIRST, fte_index, final_bm);
+ hw_mod_cat_fte_flm_flush(&ndev->be, KM_FLM_IF_FIRST, fte_index,
+ 1);
+ }
+
+ return 0;
+}
+
+static int rx_queue_idx_to_hw_id(struct flow_eth_dev *dev, int id)
+{
+ for (int i = 0; i < dev->num_queues; ++i) {
+ if (dev->rx_queue[i].id == id)
+ return dev->rx_queue[i].hw_id;
+ }
+ return -1;
+}
+
+/*
+ * Flow Matcher functionality
+ */
+
+static int flm_sdram_calibrate(struct flow_nic_dev *ndev)
+{
+ int success = 0;
+
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_PRESET_ALL, 0x0);
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_SPLIT_SDRAM_USAGE,
+ 0x10);
+ hw_mod_flm_control_flush(&ndev->be);
+
+ /* Wait for ddr4 calibration/init done */
+ for (uint32_t i = 0; i < 1000000; ++i) {
+ uint32_t value = 0;
+
+ hw_mod_flm_status_update(&ndev->be);
+ hw_mod_flm_status_get(&ndev->be, HW_FLM_STATUS_CALIBDONE,
+ &value);
+ if (value) {
+ success = 1;
+ break;
+ }
+ usleep(1);
+ }
+
+ if (!success) {
+ /* "Flow matcher initialization failed - SDRAM calibration failed"; */
+ return -1;
+ }
+
+ /* Set the flow scrubber and timeout settings */
+ hw_mod_flm_timeout_set(&ndev->be, HW_FLM_TIMEOUT_T, 0);
+ hw_mod_flm_timeout_flush(&ndev->be);
+
+ hw_mod_flm_scrub_set(&ndev->be, HW_FLM_SCRUB_I, 100);
+ hw_mod_flm_scrub_flush(&ndev->be);
+
+ return 0;
+}
+
+static int flm_sdram_reset(struct flow_nic_dev *ndev, int enable)
+{
+ int success = 0;
+
+ /*
+ * Make sure no lookup is performed during init, i.e.
+ * disable every category and disable FLM
+ */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_ENABLE, 0x0);
+ hw_mod_flm_control_flush(&ndev->be);
+
+ for (uint32_t i = 1; i < ndev->be.flm.nb_categories; ++i)
+ hw_mod_flm_rcp_set(&ndev->be, HW_FLM_RCP_PRESET_ALL, i, 0x0);
+ hw_mod_flm_rcp_flush(&ndev->be, 1, ndev->be.flm.nb_categories - 1);
+
+ /* Wait for FLM to enter Idle state */
+ for (uint32_t i = 0; i < 1000000; ++i) {
+ uint32_t value = 0;
+
+ hw_mod_flm_status_update(&ndev->be);
+ hw_mod_flm_status_get(&ndev->be, HW_FLM_STATUS_IDLE, &value);
+ if (value) {
+ success = 1;
+ break;
+ }
+ usleep(1);
+ }
+
+ if (!success) {
+ /* "Flow matcher initialization failed - never idle"; */
+ return -1;
+ }
+
+ success = 0;
+
+ /* Start SDRAM initialization */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_INIT, 0x1);
+ hw_mod_flm_control_flush(&ndev->be);
+
+ for (uint32_t i = 0; i < 1000000; ++i) {
+ uint32_t value = 0;
+
+ hw_mod_flm_status_update(&ndev->be);
+ hw_mod_flm_status_get(&ndev->be, HW_FLM_STATUS_INITDONE,
+ &value);
+ if (value) {
+ success = 1;
+ break;
+ }
+ usleep(1);
+ }
+
+ if (!success) {
+ /* "Flow matcher initialization failed - SDRAM initialization incomplete"; */
+ return -1;
+ }
+
+ /* Set the INIT value back to zero to clear the bit in the SW register cache */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_INIT, 0x0);
+ hw_mod_flm_control_flush(&ndev->be);
+
+ /* Enable FLM */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_ENABLE, enable);
+ hw_mod_flm_control_flush(&ndev->be);
+
+ return 0;
+}
+
+#define FLM_FLOW_RCP_MAX 32
+#define FLM_FLOW_FT_MAX 16
+
+struct flm_flow_ft_ident_s {
+ union {
+ struct {
+ uint64_t in_use : 1;
+ uint64_t drop : 1;
+ uint64_t ltx_en : 1;
+ uint64_t ltx_port : 1;
+ uint64_t queue_en : 1;
+ uint64_t queue : 8;
+ uint64_t encap_len : 8;
+ uint64_t encap_vlans : 2;
+ uint64_t encap_ip : 1;
+ uint64_t decap_end : 5;
+ uint64_t jump_to_group : 8;
+ uint64_t pad : 27;
+ };
+ uint64_t data;
+ };
+};
+
+struct flm_flow_key_def_s {
+ union {
+ struct {
+ uint64_t qw0_dyn : 7;
+ uint64_t qw0_ofs : 8;
+ uint64_t qw4_dyn : 7;
+ uint64_t qw4_ofs : 8;
+ uint64_t sw8_dyn : 7;
+ uint64_t sw8_ofs : 8;
+ uint64_t sw9_dyn : 7;
+ uint64_t sw9_ofs : 8;
+ uint64_t outer_proto : 1;
+ uint64_t inner_proto : 1;
+ uint64_t pad : 2;
+ };
+ uint64_t data;
+ };
+};
+
+static struct flm_flow_ft_ident_s flow_def_to_ft_ident(struct nic_flow_def *fd)
+{
+ struct flm_flow_ft_ident_s ft_ident;
+
+ assert(sizeof(struct flm_flow_ft_ident_s) == sizeof(uint64_t));
+
+ memset(&ft_ident, 0x0, sizeof(struct flm_flow_ft_ident_s));
+ ft_ident.in_use = 1;
+
+ if (fd->dst_num_avail == 0) {
+ ft_ident.drop = 1;
+ } else {
+ for (int i = 0; i < fd->dst_num_avail; ++i) {
+ if (fd->dst_id[i].type == PORT_PHY) {
+ ft_ident.ltx_en = 1;
+ ft_ident.ltx_port = fd->dst_id[i].id;
+ } else if (fd->dst_id[i].type == PORT_VIRT) {
+ ft_ident.queue_en = 1;
+ ft_ident.queue = fd->dst_id[i].id;
+ }
+ }
+ }
+
+ if (fd->tun_hdr.len > 0) {
+ ft_ident.encap_len = fd->tun_hdr.len;
+ ft_ident.encap_vlans = fd->tun_hdr.nb_vlans & 0x3;
+ ft_ident.encap_ip = fd->tun_hdr.ip_version == 4 ? 0 : 1;
+ }
+
+ ft_ident.decap_end = fd->header_strip_end_dyn & 0x1f;
+
+ if (fd->jump_to_group != UINT32_MAX)
+ ft_ident.jump_to_group = fd->jump_to_group & 0xff;
+
+ return ft_ident;
+}
+
+static inline void set_key_def_qw(struct flm_flow_key_def_s *key_def,
+ unsigned int qw, unsigned int dyn,
+ unsigned int ofs)
+{
+ assert(qw < 2);
+ if (qw == 0) {
+ key_def->qw0_dyn = dyn & 0x7f;
+ key_def->qw0_ofs = ofs & 0xff;
+ } else {
+ key_def->qw4_dyn = dyn & 0x7f;
+ key_def->qw4_ofs = ofs & 0xff;
+ }
+}
+
+static inline void set_key_def_sw(struct flm_flow_key_def_s *key_def,
+ unsigned int sw, unsigned int dyn,
+ unsigned int ofs)
+{
+ assert(sw < 2);
+ if (sw == 0) {
+ key_def->sw8_dyn = dyn & 0x7f;
+ key_def->sw8_ofs = ofs & 0xff;
+ } else {
+ key_def->sw9_dyn = dyn & 0x7f;
+ key_def->sw9_ofs = ofs & 0xff;
+ }
+}
+
+struct flm_flow_group_s {
+ int cfn_group0;
+ int km_ft_group0;
+ struct flow_handle *fh_group0;
+
+ struct flm_flow_key_def_s key_def;
+
+ int miss_enabled;
+
+ struct flm_flow_group_ft_s {
+ struct flm_flow_ft_ident_s ident;
+ struct flow_handle *fh;
+ } ft[FLM_FLOW_FT_MAX];
+
+ uint32_t cashed_ft_index;
+};
+
+struct flm_flow_handle_s {
+ struct flm_flow_group_s groups[FLM_FLOW_RCP_MAX];
+};
+
+static void flm_flow_handle_create(void **handle)
+{
+ struct flm_flow_handle_s *flm_handle;
+
+ if (!*handle)
+ *handle = calloc(1, sizeof(struct flm_flow_handle_s));
+
+ else
+ memset(*handle, 0x0, sizeof(struct flm_flow_handle_s));
+
+ flm_handle = (struct flm_flow_handle_s *)*handle;
+
+ for (int i = 0; i < FLM_FLOW_RCP_MAX; ++i) {
+ flm_handle->groups[i].cfn_group0 = -1;
+ flm_handle->groups[i].fh_group0 = NULL;
+ }
+}
+
+static void flm_flow_handle_remove(void **handle)
+{
+ free(*handle);
+ *handle = NULL;
+}
+
+static int flm_flow_setup_group(struct flow_eth_dev *dev, uint32_t group_index,
+ int cfn, int km_ft, struct flow_handle *fh)
+{
+ struct flm_flow_handle_s *flm_handle =
+ (struct flm_flow_handle_s *)dev->ndev->flm_res_handle;
+ struct flm_flow_group_s *flm_group;
+
+ if (group_index >= FLM_FLOW_RCP_MAX) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Invalid index for FLM programming: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ flm_group = &flm_handle->groups[group_index];
+
+ flm_group->cfn_group0 = cfn;
+ flm_group->km_ft_group0 = km_ft;
+ flm_group->fh_group0 = fh;
+ flm_group->miss_enabled = 0;
+
+ return 0;
+}
+
+static int flm_flow_destroy_group(struct flow_eth_dev *dev,
+ uint32_t group_index)
+{
+ struct flm_flow_handle_s *flm_handle =
+ (struct flm_flow_handle_s *)dev->ndev->flm_res_handle;
+ struct flm_flow_group_s *flm_group;
+
+ if (group_index >= FLM_FLOW_RCP_MAX) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Invalid index for FLM programming: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ flm_group = &flm_handle->groups[group_index];
+
+ memset(flm_group, 0x0, sizeof(struct flm_flow_group_s));
+ flm_group->cfn_group0 = -1;
+
+ return 0;
+}
+
+static int flm_flow_get_group_miss_fh(struct flow_eth_dev *dev,
+ uint32_t group_index,
+ struct flow_handle **fh_miss)
+{
+ struct flm_flow_handle_s *flm_handle =
+ (struct flm_flow_handle_s *)dev->ndev->flm_res_handle;
+
+ if (group_index >= FLM_FLOW_RCP_MAX) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Invalid index for FLM programming: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ *fh_miss = flm_handle->groups[group_index].fh_group0;
+
+ return 0;
+}
+
+static int flm_flow_setup_rcp(struct flow_eth_dev *dev,
+ struct flm_flow_key_def_s *key_def,
+ uint32_t *packet_mask, uint32_t group_index)
+{
+ if (group_index >= FLM_FLOW_RCP_MAX) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Invalid index for FLM programming: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ uint32_t flm_mask[10] = {
+ packet_mask[0], /* SW9 */
+ packet_mask[1], /* SW8 */
+ packet_mask[5], packet_mask[4],
+ packet_mask[3], packet_mask[2], /* QW4 */
+ packet_mask[9], packet_mask[8],
+ packet_mask[7], packet_mask[6], /* QW0 */
+ };
+
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_LOOKUP, group_index, 1);
+
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW0_DYN, group_index,
+ key_def->qw0_dyn);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW0_OFS, group_index,
+ key_def->qw0_ofs);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW0_SEL, group_index, 0);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW4_DYN, group_index,
+ key_def->qw4_dyn);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_QW4_OFS, group_index,
+ key_def->qw4_ofs);
+
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW8_DYN, group_index,
+ key_def->sw8_dyn);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW8_OFS, group_index,
+ key_def->sw8_ofs);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW8_SEL, group_index, 0);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW9_DYN, group_index,
+ key_def->sw9_dyn);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_SW9_OFS, group_index,
+ key_def->sw9_ofs);
+
+ hw_mod_flm_rcp_set_mask(&dev->ndev->be, HW_FLM_RCP_MASK, group_index,
+ flm_mask);
+
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_KID, group_index,
+ group_index + 2);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_OPN, group_index,
+ key_def->outer_proto);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_IPN, group_index,
+ key_def->inner_proto);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_BYT_DYN, group_index, 0);
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_BYT_OFS, group_index,
+ -20);
+
+ hw_mod_flm_rcp_flush(&dev->ndev->be, group_index, 1);
+
+ return 0;
+}
+
+static int flm_flow_destroy_rcp(struct flow_eth_dev *dev, uint32_t group_index)
+{
+ struct flm_flow_handle_s *flm_handle =
+ (struct flm_flow_handle_s *)dev->ndev->flm_res_handle;
+ struct flm_flow_group_s *flm_group;
+
+ if (group_index >= FLM_FLOW_RCP_MAX) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Invalid index for FLM programming: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ flm_group = &flm_handle->groups[group_index];
+
+ hw_mod_flm_rcp_set(&dev->ndev->be, HW_FLM_RCP_PRESET_ALL, group_index,
+ 0);
+ hw_mod_flm_rcp_flush(&dev->ndev->be, group_index, 1);
+
+ if (flm_group->miss_enabled) {
+ uint32_t bm = 0;
+
+ /* Change group 0 FLM RCP selection to point to 0 */
+ hw_mod_cat_kcs_flm_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST, flm_group->cfn_group0,
+ 0);
+ hw_mod_cat_kcs_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ flm_group->cfn_group0, 1);
+
+ /* Change group 0 FT MISS to FT UNHANDLED */
+ set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 0, 2, 0);
+ set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 1, 2, 1);
+
+ /* Finally, disable FLM for group 0 */
+ hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST,
+ flm_group->cfn_group0 / 8, &bm);
+ hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, flm_group->cfn_group0 / 8,
+ bm & ~(1 << (flm_group->cfn_group0 % 8)));
+ hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ flm_group->cfn_group0 / 8, 1);
+
+ memset(&flm_group->key_def, 0x0,
+ sizeof(struct flm_flow_key_def_s));
+ flm_group->miss_enabled = 0;
+ }
+
+ return 0;
+}
+
+static int flm_flow_learn_prepare(struct flow_eth_dev *dev,
+ struct flow_handle *fh, uint32_t group_index,
+ struct flm_flow_key_def_s *key_def,
+ uint32_t *packet_mask,
+ /* Return values */
+ uint32_t *kid, uint32_t *ft, int *cfn_to_copy,
+ int *cfn_to_copy_km_ft,
+ struct flow_handle **fh_excisting)
+{
+ struct flm_flow_handle_s *flm_handle =
+ (struct flm_flow_handle_s *)dev->ndev->flm_res_handle;
+ struct flm_flow_group_s *flm_group;
+ struct flm_flow_ft_ident_s temp_ft_ident;
+ struct nic_flow_def *fd = fh->fd;
+
+ if (group_index >= FLM_FLOW_RCP_MAX) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Invalid index for FLM programming: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ flm_group = &flm_handle->groups[group_index];
+
+ if (flm_group->cfn_group0 < 0) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Attempt to program to a unset CFN: Group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ if (!flm_group->miss_enabled) {
+ uint32_t bm = 0;
+
+ if (flow_nic_allocate_fh_resource_index(dev->ndev, RES_FLM_RCP,
+ (int)group_index, fh)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get FLM RCP resource\n");
+ return -1;
+ }
+
+ /* Change group 0 FLM RCP selection to point to "group_index" */
+ hw_mod_cat_kcs_flm_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST, flm_group->cfn_group0,
+ group_index);
+ hw_mod_cat_kcs_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ flm_group->cfn_group0, 1);
+
+ /* Setup FLM RCP "group_index" */
+ flm_flow_setup_rcp(dev, key_def, packet_mask, group_index);
+
+ /*
+ * Change group 0 FT UNHANDLED to FT MISS
+ * Note: Once this step is done, the filter is invalid until the KCE step is done
+ */
+ set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 1, 2, 0);
+ set_flow_type_flm(dev->ndev, flm_group->cfn_group0, 0, 2, 1);
+
+ /* Finally, enable FLM for group 0 */
+ hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST,
+ flm_group->cfn_group0 / 8, &bm);
+ hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST,
+ flm_group->cfn_group0 / 8,
+ bm | (1 << (flm_group->cfn_group0 % 8)));
+ hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ flm_group->cfn_group0 / 8, 1);
+
+ flm_group->key_def.data = key_def->data;
+ flm_group->miss_enabled = 1;
+ }
+
+ if (flm_group->key_def.data != key_def->data) {
+ NT_LOG(ERR, FILTER,
+ "FLM: Attempt to program 2 different types of flows into group=%d\n",
+ (int)group_index);
+ return -1;
+ }
+
+ /* Create action set */
+ memset(&temp_ft_ident, 0x0, sizeof(struct flm_flow_ft_ident_s));
+ temp_ft_ident.in_use = 1;
+
+ if (fd->dst_num_avail == 0) {
+ temp_ft_ident.drop = 1;
+ } else {
+ for (int i = 0; i < fd->dst_num_avail; ++i) {
+ if (fd->dst_id[i].type == PORT_PHY) {
+ temp_ft_ident.ltx_en = 1;
+ temp_ft_ident.ltx_port = fd->dst_id[i].id;
+ } else if (fd->dst_id[i].type == PORT_VIRT) {
+ temp_ft_ident.queue_en = 1;
+ temp_ft_ident.queue = fd->dst_id[i].id;
+ }
+ }
+ }
+
+ /* Set encap/decap data */
+ if (fd->tun_hdr.len > 0) {
+ temp_ft_ident.encap_len = fd->tun_hdr.len;
+ temp_ft_ident.encap_vlans = fd->tun_hdr.nb_vlans & 0x3;
+ temp_ft_ident.encap_ip = fd->tun_hdr.ip_version == 4 ? 0 : 1;
+ }
+
+ temp_ft_ident.decap_end = fd->header_strip_end_dyn & 0x1f;
+
+ /* Find ft ident or create a new one */
+ uint32_t ft_index = 0;
+
+ if (flm_group->cashed_ft_index > 0 &&
+ flm_group->ft[flm_group->cashed_ft_index].ident.data ==
+ temp_ft_ident.data) {
+ ft_index = flm_group->cashed_ft_index;
+ *fh_excisting = flm_group->ft[ft_index].fh;
+ } else {
+ for (ft_index = 2; ft_index < FLM_FLOW_FT_MAX; ++ft_index) {
+ struct flm_flow_ft_ident_s *ft_ident =
+ &flm_group->ft[ft_index].ident;
+ if (ft_ident->data == 0) {
+ ft_ident->data = temp_ft_ident.data;
+ *cfn_to_copy = flm_group->cfn_group0;
+ *cfn_to_copy_km_ft = flm_group->km_ft_group0;
+ flm_group->ft[ft_index].fh = fh;
+ fh->flm_group_index = (uint8_t)group_index;
+ fh->flm_ft_index = (uint8_t)ft_index;
+ break;
+ } else if (ft_ident->data == temp_ft_ident.data) {
+ *fh_excisting = flm_group->ft[ft_index].fh;
+ break;
+ }
+ }
+
+ if (ft_index >= FLM_FLOW_FT_MAX) {
+ NT_LOG(ERR, FILTER, "FLM: FT resource not available\n");
+ return -1;
+ }
+
+ flm_group->cashed_ft_index = ft_index;
+ }
+
+ /* Set return values */
+ *kid = group_index + 2;
+ *ft = ft_index;
+
+ return 0;
+}
+
+static int flow_flm_destroy_owner(struct flow_eth_dev *dev,
+ struct flow_handle *fh)
+{
+ int error = 0;
+
+ struct flm_flow_handle_s *flm_handle =
+ (struct flm_flow_handle_s *)dev->ndev->flm_res_handle;
+ struct flm_flow_group_s *flm_group =
+ &flm_handle->groups[fh->flm_group_index];
+
+ memset(&flm_group->ft[fh->flm_ft_index], 0x0,
+ sizeof(struct flm_flow_group_ft_s));
+
+ error |= set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ flm_group->km_ft_group0, 0, 0);
+ error |= set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ (int)fh->flm_ft_index, 2, 0);
+
+ return error;
+}
+
+#define FLM_MTR_PROFILE_SIZE 0x100000
+
+struct flm_flow_mtr_handle_s {
+ struct dual_buckets_s {
+ uint16_t rate_a;
+ uint16_t rate_b;
+ uint16_t size_a;
+ uint16_t size_b;
+ } dual_buckets[FLM_MTR_PROFILE_SIZE];
+};
+
+int flow_mtr_supported(struct flow_eth_dev *dev)
+{
+ return hw_mod_flm_present(&dev->ndev->be) &&
+ dev->ndev->be.flm.nb_variant == 2;
+}
+
+uint64_t flow_mtr_meter_policy_n_max(void)
+{
+ return FLM_MTR_PROFILE_SIZE;
+}
+
+static inline uint64_t convert_to_bucket_size_units(uint64_t value)
+{
+ /* Assumes a 40-bit int as input */
+ uint64_t lo_bits = (value & 0xfffff) * 1000000000;
+ uint64_t hi_bits = ((value >> 20) & 0xfffff) * 1000000000;
+ uint64_t round_up =
+ (hi_bits & 0xfffff) || (lo_bits & 0xffffffffff) ? 1 : 0;
+ return (hi_bits >> 20) + (lo_bits >> 40) + round_up;
+}
+
+int flow_mtr_set_profile(struct flow_eth_dev *dev, uint32_t profile_id,
+ uint64_t bucket_rate_a, uint64_t bucket_size_a,
+ uint64_t bucket_rate_b, uint64_t bucket_size_b)
+{
+ struct flow_nic_dev *ndev = dev->ndev;
+ struct flm_flow_mtr_handle_s *handle =
+ (struct flm_flow_mtr_handle_s *)ndev->flm_mtr_handle;
+ struct dual_buckets_s *buckets = &handle->dual_buckets[profile_id];
+
+ uint64_t bucket_rate_shift_a = 0;
+ uint64_t bucket_rate_shift_b = 0;
+
+ uint64_t bucket_size_shift_a = 0;
+ uint64_t bucket_size_shift_b = 0;
+
+ /* Round rates up to nearest 128 bytes/sec and shift to 128 bytes/sec units */
+ bucket_rate_a = (bucket_rate_a & 0x7f) ? (bucket_rate_a >> 7) + 1 :
+ (bucket_rate_a >> 7);
+ bucket_rate_b = (bucket_rate_b & 0x7f) ? (bucket_rate_b >> 7) + 1 :
+ (bucket_rate_b >> 7);
+
+ /* Round rate down to max rate supported */
+ if (bucket_rate_a > 0x7ff8000)
+ bucket_rate_a = 0x7ff8000;
+ if (bucket_rate_b > 0x7ff8000)
+ bucket_rate_b = 0x7ff8000;
+
+ /* Find shift to convert into 12-bit int */
+ while ((bucket_rate_a >> bucket_rate_shift_a) > 0xfff)
+ bucket_rate_shift_a += 1;
+ while ((bucket_rate_b >> bucket_rate_shift_b) > 0xfff)
+ bucket_rate_shift_b += 1;
+
+ /* Store in format [11:0] shift-left [15:12] */
+ buckets->rate_a = (bucket_rate_a >> bucket_rate_shift_a) |
+ (bucket_rate_shift_a << 12);
+ buckets->rate_b = (bucket_rate_b >> bucket_rate_shift_b) |
+ (bucket_rate_shift_b << 12);
+
+ /* Round size down to 38-bit int */
+ if (bucket_size_a > 0x3fffffffff)
+ bucket_size_a = 0x3fffffffff;
+ if (bucket_size_b > 0x3fffffffff)
+ bucket_size_b = 0x3fffffffff;
+
+ /* Convert size to units of 2^40 / 10^9. Output is a 28-bit int. */
+ bucket_size_a = convert_to_bucket_size_units(bucket_size_a);
+ bucket_size_b = convert_to_bucket_size_units(bucket_size_b);
+
+ /* Round rate down to max rate supported */
+ if (bucket_size_a > 0x7ff8000)
+ bucket_size_a = 0x7ff8000;
+ if (bucket_size_b > 0x7ff8000)
+ bucket_size_b = 0x7ff8000;
+
+ /* Find shift to convert into 12-bit int */
+ while ((bucket_size_a >> bucket_size_shift_a) > 0xfff)
+ bucket_size_shift_a += 1;
+ while ((bucket_size_b >> bucket_size_shift_b) > 0xfff)
+ bucket_size_shift_b += 1;
+
+ /* Store in format [11:0] shift-left [15:12] */
+ buckets->size_a = (bucket_size_a >> bucket_size_shift_a) |
+ (bucket_size_shift_a << 12);
+ buckets->size_b = (bucket_size_b >> bucket_size_shift_b) |
+ (bucket_size_shift_b << 12);
+
+ return 0;
+}
+
+int flow_mtr_set_policy(UNUSED struct flow_eth_dev *dev,
+ UNUSED uint32_t policy_id, UNUSED int drop)
+{
+ return 0;
+}
+
+#define FLM_MTR_STAT_SIZE 0x1000000
+#define WORDS_PER_INF_DATA \
+ (sizeof(struct flm_v17_inf_data_s) / sizeof(uint32_t))
+#define MAX_INF_DATA_RECORDS_PER_READ 20
+#define UINT64_MSB ((uint64_t)1 << 63)
+
+/* 2^23 bytes ~ 8MB */
+#define FLM_PERIODIC_STATS_BYTE_LIMIT 8
+/* 2^16 pkt ~ 64K pkt */
+#define FLM_PERIODIC_STATS_PKT_LIMIT 5
+/* 2^38 ns ~ 275 sec */
+#define FLM_PERIODIC_STATS_BYTE_TIMEOUT 23
+
+uint32_t flow_mtr_meters_supported(void)
+{
+ return FLM_MTR_STAT_SIZE;
+}
+
+struct mtr_stat_s {
+ struct dual_buckets_s *buckets;
+
+ volatile atomic_uint_fast64_t n_pkt;
+ volatile atomic_uint_fast64_t n_bytes;
+ uint64_t n_pkt_base;
+ uint64_t n_bytes_base;
+ volatile atomic_uint_fast64_t stats_mask;
+};
+
+#define WORDS_PER_LEARN_DATA sizeof(struct flm_v17_lrn_data_s)
+#define FLM_PROG_MAX_RETRY 100
+
+static uint32_t flm_read_inf_rec_locked(struct flow_eth_dev *dev,
+ uint32_t *data);
+
+static int flow_flm_apply(struct flow_eth_dev *dev,
+ struct flm_v17_lrn_data_s *learn_record)
+{
+ uint32_t lrn_ready;
+ uint32_t retry = 0;
+ uint32_t data[WORDS_PER_INF_DATA * MAX_INF_DATA_RECORDS_PER_READ];
+
+ hw_mod_flm_buf_ctrl_get(&dev->ndev->be, HW_FLM_BUF_CTRL_LRN_FREE,
+ &lrn_ready);
+ if (lrn_ready < WORDS_PER_LEARN_DATA) {
+ hw_mod_flm_buf_ctrl_update(&dev->ndev->be);
+ hw_mod_flm_buf_ctrl_get(&dev->ndev->be,
+ HW_FLM_BUF_CTRL_LRN_FREE, &lrn_ready);
+ while (lrn_ready < WORDS_PER_LEARN_DATA) {
+ ++retry;
+ if (retry > FLM_PROG_MAX_RETRY)
+ return 1;
+
+ flm_read_inf_rec_locked(dev, data);
+
+ hw_mod_flm_buf_ctrl_update(&dev->ndev->be);
+ hw_mod_flm_buf_ctrl_get(&dev->ndev->be,
+ HW_FLM_BUF_CTRL_LRN_FREE,
+ &lrn_ready);
+ }
+ }
+
+ int res = hw_mod_flm_lrn_data_set_flush(&dev->ndev->be,
+ HW_FLM_FLOW_LRN_DATA_V17,
+ (uint32_t *)learn_record);
+ return res;
+}
+
+int flow_mtr_create_meter(struct flow_eth_dev *dev, uint32_t mtr_id,
+ uint32_t profile_id, UNUSED uint32_t policy_id,
+ uint64_t stats_mask)
+{
+ pthread_mutex_lock(&dev->ndev->mtx);
+
+ struct flm_flow_mtr_handle_s *handle =
+ (struct flm_flow_mtr_handle_s *)dev->ndev->flm_mtr_handle;
+ struct dual_buckets_s *buckets = &handle->dual_buckets[profile_id];
+
+ struct flm_v17_lrn_data_s learn_record;
+
+ memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s));
+
+ learn_record.sw9 = mtr_id + 1;
+ learn_record.kid = 1;
+
+ learn_record.rate = buckets->rate_a;
+ learn_record.size = buckets->size_a;
+ learn_record.fill = buckets->size_a & 0x0fff;
+
+ learn_record.ft_mbr = 15; /* FT to assign if MBR has been exceeded */
+
+ learn_record.ent = 1;
+ learn_record.op = 1;
+ learn_record.eor = 1;
+
+ learn_record.id[0] = mtr_id & 0xff;
+ learn_record.id[1] = (mtr_id >> 8) & 0xff;
+ learn_record.id[2] = (mtr_id >> 16) & 0xff;
+ learn_record.id[3] = (mtr_id >> 24) & 0xff;
+ learn_record.id[8] = 1U << 7;
+
+ if (stats_mask)
+ learn_record.vol_idx = 1;
+
+ int res = flow_flm_apply(dev, &learn_record);
+
+ if (res == 0) {
+ struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle;
+
+ mtr_stat[mtr_id].buckets = buckets;
+ atomic_store(&mtr_stat[mtr_id].stats_mask, stats_mask);
+ }
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ return res;
+}
+
+int flow_mtr_destroy_meter(struct flow_eth_dev *dev, uint32_t mtr_id)
+{
+ pthread_mutex_lock(&dev->ndev->mtx);
+
+ struct flm_v17_lrn_data_s learn_record;
+
+ memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s));
+
+ learn_record.sw9 = mtr_id + 1;
+ learn_record.kid = 1;
+
+ learn_record.ent = 1;
+ learn_record.op = 0;
+ learn_record.eor = 1;
+
+ learn_record.id[0] = mtr_id & 0xff;
+ learn_record.id[1] = (mtr_id >> 8) & 0xff;
+ learn_record.id[2] = (mtr_id >> 16) & 0xff;
+ learn_record.id[3] = (mtr_id >> 24) & 0xff;
+ learn_record.id[8] = 1U << 7;
+
+ /* Clear statistics so stats_mask prevents updates of counters on deleted meters */
+ struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle;
+
+ atomic_store(&mtr_stat[mtr_id].stats_mask, 0);
+ atomic_store(&mtr_stat[mtr_id].n_bytes, 0);
+ atomic_store(&mtr_stat[mtr_id].n_pkt, 0);
+ mtr_stat[mtr_id].n_bytes_base = 0;
+ mtr_stat[mtr_id].n_pkt_base = 0;
+ mtr_stat[mtr_id].buckets = NULL;
+
+ int res = flow_flm_apply(dev, &learn_record);
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ return res;
+}
+
+int flm_mtr_adjust_stats(struct flow_eth_dev *dev, uint32_t mtr_id,
+ uint32_t adjust_value)
+{
+ pthread_mutex_lock(&dev->ndev->mtx);
+
+ struct mtr_stat_s *mtr_stat =
+ &((struct mtr_stat_s *)dev->ndev->mtr_stat_handle)[mtr_id];
+
+ struct flm_v17_lrn_data_s learn_record;
+
+ memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s));
+
+ learn_record.sw9 = mtr_id + 1;
+ learn_record.kid = 1;
+
+ learn_record.rate = mtr_stat->buckets->rate_a;
+ learn_record.size = mtr_stat->buckets->size_a;
+ learn_record.adj = adjust_value;
+
+ learn_record.ft_mbr = 15;
+
+ learn_record.ent = 1;
+ learn_record.op = 2;
+ learn_record.eor = 1;
+
+ if (atomic_load(&mtr_stat->stats_mask))
+ learn_record.vol_idx = 1;
+
+ int res = flow_flm_apply(dev, &learn_record);
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ return res;
+}
+
+static uint32_t flm_read_inf_rec_locked(struct flow_eth_dev *dev,
+ uint32_t *data)
+{
+ uint32_t inf_cnt = 0;
+
+ hw_mod_flm_buf_ctrl_get(&dev->ndev->be, HW_FLM_BUF_CTRL_INF_AVAIL,
+ &inf_cnt);
+ if (inf_cnt < WORDS_PER_INF_DATA) {
+ hw_mod_flm_buf_ctrl_update(&dev->ndev->be);
+ hw_mod_flm_buf_ctrl_get(&dev->ndev->be,
+ HW_FLM_BUF_CTRL_INF_AVAIL, &inf_cnt);
+ }
+
+ uint32_t records_to_read = inf_cnt / WORDS_PER_INF_DATA;
+
+ if (records_to_read == 0)
+ return 0;
+ if (records_to_read > MAX_INF_DATA_RECORDS_PER_READ)
+ records_to_read = MAX_INF_DATA_RECORDS_PER_READ;
+
+ hw_mod_flm_inf_data_update_get(&dev->ndev->be, HW_FLM_FLOW_INF_DATA_V17,
+ data,
+ records_to_read * WORDS_PER_INF_DATA);
+
+ return records_to_read;
+}
+
+uint32_t flm_mtr_update_stats(struct flow_eth_dev *dev)
+{
+ uint32_t data[WORDS_PER_INF_DATA * MAX_INF_DATA_RECORDS_PER_READ];
+
+ pthread_mutex_lock(&dev->ndev->mtx);
+ uint32_t records = flm_read_inf_rec_locked(dev, data);
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle;
+
+ for (uint32_t i = 0; i < records; ++i) {
+ uint32_t *p_record = &data[i * WORDS_PER_INF_DATA];
+
+ /* Check that received record hold valid meter statistics */
+ if ((p_record[6] < flow_mtr_meters_supported() &&
+ p_record[7] == 0 && (p_record[8] >> 31) == 1)) {
+ uint32_t id = p_record[6];
+
+ /* Don't update a deleted meter */
+ uint64_t stats_mask =
+ atomic_load(&mtr_stat[id].stats_mask);
+ if (stats_mask) {
+ uint64_t nb = ((uint64_t)p_record[1] << 32) |
+ p_record[0];
+ uint64_t np = ((uint64_t)p_record[3] << 32) |
+ p_record[2];
+
+ atomic_store(&mtr_stat[id].n_pkt,
+ np | UINT64_MSB);
+ atomic_store(&mtr_stat[id].n_bytes, nb);
+ atomic_store(&mtr_stat[id].n_pkt, np);
+ }
+ }
+ }
+
+ return records;
+}
+
+void flm_mtr_read_stats(struct flow_eth_dev *dev, uint32_t id,
+ uint64_t *stats_mask, uint64_t *green_pkt,
+ uint64_t *green_bytes, int clear)
+{
+ struct mtr_stat_s *mtr_stat = dev->ndev->mtr_stat_handle;
+ *stats_mask = atomic_load(&mtr_stat[id].stats_mask);
+ if (*stats_mask) {
+ uint64_t pkt_1;
+ uint64_t pkt_2;
+ uint64_t nb;
+
+ do {
+ do {
+ pkt_1 = atomic_load(&mtr_stat[id].n_pkt);
+ } while (pkt_1 & UINT64_MSB);
+ nb = atomic_load(&mtr_stat[id].n_bytes);
+ pkt_2 = atomic_load(&mtr_stat[id].n_pkt);
+ } while (pkt_1 != pkt_2);
+
+ *green_pkt = pkt_1 - mtr_stat[id].n_pkt_base;
+ *green_bytes = nb - mtr_stat[id].n_bytes_base;
+ if (clear) {
+ mtr_stat[id].n_pkt_base = pkt_1;
+ mtr_stat[id].n_bytes_base = nb;
+ }
+ }
+}
+
+static inline uint8_t convert_port_to_ifr_mtu_recipe(uint32_t port)
+{
+ return port + 1;
+}
+
+static uint8_t get_port_from_port_id(struct flow_nic_dev *ndev,
+ uint32_t port_id)
+{
+ struct flow_eth_dev *dev = ndev->eth_base;
+
+ while (dev) {
+ if (dev->port_id == port_id)
+ return dev->port;
+ dev = dev->next;
+ }
+
+ return UINT8_MAX;
+}
+
+static void nic_insert_flow(struct flow_nic_dev *ndev, struct flow_handle *fh)
+{
+ if (ndev->flow_base)
+ ndev->flow_base->prev = fh;
+ fh->next = ndev->flow_base;
+ fh->prev = NULL;
+ ndev->flow_base = fh;
+}
+
+static void nic_remove_flow(struct flow_nic_dev *ndev, struct flow_handle *fh)
+{
+ struct flow_handle *next = fh->next;
+ struct flow_handle *prev = fh->prev;
+
+ if (next && prev) {
+ prev->next = next;
+ next->prev = prev;
+ } else if (next) {
+ ndev->flow_base = next;
+ next->prev = NULL;
+ } else if (prev) {
+ prev->next = NULL;
+ } else if (ndev->flow_base == fh) {
+ ndev->flow_base = NULL;
+ }
+}
+
+static void nic_insert_flow_flm(struct flow_nic_dev *ndev,
+ struct flow_handle *fh)
+{
+ if (ndev->flow_base_flm)
+ ndev->flow_base_flm->prev = fh;
+ fh->next = ndev->flow_base_flm;
+ fh->prev = NULL;
+ ndev->flow_base_flm = fh;
+}
+
+static void nic_remove_flow_flm(struct flow_nic_dev *ndev,
+ struct flow_handle *fh_flm)
+{
+ struct flow_handle *next = fh_flm->next;
+ struct flow_handle *prev = fh_flm->prev;
+
+ if (next && prev) {
+ prev->next = next;
+ next->prev = prev;
+ } else if (next) {
+ ndev->flow_base_flm = next;
+ next->prev = NULL;
+ } else if (prev) {
+ prev->next = NULL;
+ } else if (ndev->flow_base_flm == fh_flm) {
+ ndev->flow_base_flm = NULL;
+ }
+}
+
+static int flow_elem_type_vlan(const struct flow_elem elem[], int eidx, uint16_t implicit_vlan_vid,
+ struct flow_error *error, struct nic_flow_def *fd, unsigned int sw_counter,
+ uint32_t *packet_data, uint32_t *packet_mask, struct flm_flow_key_def_s *key_def)
+{
+ const struct flow_elem_vlan *vlan_spec = (const struct flow_elem_vlan *)elem[eidx].spec;
+ const struct flow_elem_vlan *vlan_mask = (const struct flow_elem_vlan *)elem[eidx].mask;
+
+ if (vlan_spec != NULL && vlan_mask != NULL) {
+ if (vlan_mask->tci) {
+ if (implicit_vlan_vid > 0) {
+ NT_LOG(ERR, FILTER, "Multiple VLANs not supported "
+ "for implicit VLAN patterns.\n");
+ flow_nic_set_error(ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM, error);
+ free(fd);
+ return 1;
+ }
+
+ if (sw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = ntohs(vlan_mask->tci);
+ sw_data[0] = ntohs(vlan_spec->tci) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_FIRST_VLAN, 0);
+ set_key_def_sw(key_def, sw_counter, DYN_FIRST_VLAN, 0);
+ sw_counter += 1;
+ }
+ }
+
+ fd->vlans += 1;
+ return 0;
+}
+
+static int flow_elem_type_ipv4(const struct flow_elem elem[], int eidx, struct flow_error *error,
+ struct nic_flow_def *fd, unsigned int qw_counter, unsigned int sw_counter,
+ uint32_t *packet_data, uint32_t *packet_mask, struct flm_flow_key_def_s *key_def,
+ uint32_t any_count)
+{
+ const struct flow_elem_ipv4 *ipv4_spec = (const struct flow_elem_ipv4 *)elem[eidx].spec;
+ const struct flow_elem_ipv4 *ipv4_mask = (const struct flow_elem_ipv4 *)elem[eidx].mask;
+
+ if (ipv4_spec != NULL && ipv4_mask != NULL) {
+ if (ipv4_spec->hdr.frag_offset == 0xffff && ipv4_mask->hdr.frag_offset == 0xffff)
+ fd->fragmentation = 0xfe;
+
+ if (qw_counter < 2 && (ipv4_mask->hdr.src_ip || ipv4_mask->hdr.dst_ip)) {
+ uint32_t *qw_data = &packet_data[2 + 4 - qw_counter * 4];
+ uint32_t *qw_mask = &packet_mask[2 + 4 - qw_counter * 4];
+
+ qw_mask[0] = ntohl(ipv4_mask->hdr.src_ip);
+ qw_mask[1] = ntohl(ipv4_mask->hdr.dst_ip);
+
+ qw_data[0] = ntohl(ipv4_spec->hdr.src_ip) & qw_mask[0];
+ qw_data[1] = ntohl(ipv4_spec->hdr.dst_ip) & qw_mask[1];
+
+ km_add_match_elem(&fd->km, &qw_data[0], &qw_mask[0], 2, DYN_L3, 12);
+ set_key_def_qw(key_def, qw_counter, DYN_L3, 12);
+ qw_counter += 1;
+ } else {
+ if (2 - sw_counter < ((ipv4_mask->hdr.src_ip ? 1U : 0U) +
+ (ipv4_mask->hdr.dst_ip ? 1U : 0U))) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ if (ipv4_mask->hdr.src_ip) {
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = ntohl(ipv4_mask->hdr.src_ip);
+ sw_data[0] = ntohl(ipv4_spec->hdr.src_ip) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L3, 12);
+ set_key_def_sw(key_def, sw_counter, DYN_L3, 12);
+ sw_counter += 1;
+ }
+
+ if (ipv4_mask->hdr.dst_ip) {
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = ntohl(ipv4_mask->hdr.dst_ip);
+ sw_data[0] = ntohl(ipv4_spec->hdr.dst_ip) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L3, 16);
+ set_key_def_sw(key_def, sw_counter, DYN_L3, 16);
+ sw_counter += 1;
+ }
+ }
+ }
+
+ if (any_count > 0 || fd->l3_prot != -1)
+ fd->tunnel_l3_prot = PROT_TUN_L3_IPV4;
+ else
+ fd->l3_prot = PROT_L3_IPV4;
+ return 0;
+}
+
+static int flow_elem_type_ipv6(const struct flow_elem elem[], int eidx, struct flow_error *error,
+ struct nic_flow_def *fd, unsigned int qw_counter, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count)
+{
+ const struct flow_elem_ipv6 *ipv6_spec = (const struct flow_elem_ipv6 *)elem[eidx].spec;
+ const struct flow_elem_ipv6 *ipv6_mask = (const struct flow_elem_ipv6 *)elem[eidx].mask;
+
+ if (ipv6_spec != NULL && ipv6_mask != NULL) {
+ if (is_non_zero(ipv6_spec->hdr.src_addr, 16)) {
+ if (qw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of QW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *qw_data = &packet_data[2 + 4 - qw_counter * 4];
+ uint32_t *qw_mask = &packet_mask[2 + 4 - qw_counter * 4];
+
+ memcpy(&qw_data[0], ipv6_spec->hdr.src_addr, 16);
+ memcpy(&qw_mask[0], ipv6_mask->hdr.src_addr, 16);
+
+ qw_data[0] = ntohl(qw_data[0]);
+ qw_data[1] = ntohl(qw_data[1]);
+ qw_data[2] = ntohl(qw_data[2]);
+ qw_data[3] = ntohl(qw_data[3]);
+
+ qw_mask[0] = ntohl(qw_mask[0]);
+ qw_mask[1] = ntohl(qw_mask[1]);
+ qw_mask[2] = ntohl(qw_mask[2]);
+ qw_mask[3] = ntohl(qw_mask[3]);
+
+ qw_data[0] &= qw_mask[0];
+ qw_data[1] &= qw_mask[1];
+ qw_data[2] &= qw_mask[2];
+ qw_data[3] &= qw_mask[3];
+
+ km_add_match_elem(&fd->km, &qw_data[0], &qw_mask[0], 4, DYN_L3, 8);
+ set_key_def_qw(key_def, qw_counter, DYN_L3, 8);
+ qw_counter += 1;
+ }
+
+ if (is_non_zero(ipv6_spec->hdr.dst_addr, 16)) {
+ if (qw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of QW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *qw_data = &packet_data[2 + 4 - qw_counter * 4];
+ uint32_t *qw_mask = &packet_mask[2 + 4 - qw_counter * 4];
+
+ memcpy(&qw_data[0], ipv6_spec->hdr.dst_addr, 16);
+ memcpy(&qw_mask[0], ipv6_mask->hdr.dst_addr, 16);
+
+ qw_data[0] = ntohl(qw_data[0]);
+ qw_data[1] = ntohl(qw_data[1]);
+ qw_data[2] = ntohl(qw_data[2]);
+ qw_data[3] = ntohl(qw_data[3]);
+
+ qw_mask[0] = ntohl(qw_mask[0]);
+ qw_mask[1] = ntohl(qw_mask[1]);
+ qw_mask[2] = ntohl(qw_mask[2]);
+ qw_mask[3] = ntohl(qw_mask[3]);
+ qw_data[0] &= qw_mask[0];
+ qw_data[1] &= qw_mask[1];
+ qw_data[2] &= qw_mask[2];
+ qw_data[3] &= qw_mask[3];
+
+ km_add_match_elem(&fd->km, &qw_data[0], &qw_mask[0], 4, DYN_L3, 24);
+ set_key_def_qw(key_def, qw_counter, DYN_L3, 24);
+ qw_counter += 1;
+ }
+ }
+
+ if (any_count > 0 || fd->l3_prot != -1)
+ fd->tunnel_l3_prot = PROT_TUN_L3_IPV6;
+ else
+ fd->l3_prot = PROT_L3_IPV6;
+ return 0;
+}
+
+static int flow_elem_type_upd(const struct flow_elem elem[], int eidx, struct flow_error *error,
+ struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count)
+{
+ const struct flow_elem_udp *udp_spec = (const struct flow_elem_udp *)elem[eidx].spec;
+ const struct flow_elem_udp *udp_mask = (const struct flow_elem_udp *)elem[eidx].mask;
+
+ if (udp_spec != NULL && udp_mask != NULL) {
+ if (udp_mask->hdr.src_port || udp_mask->hdr.dst_port) {
+ if (sw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = (ntohs(udp_mask->hdr.src_port) << 16) |
+ ntohs(udp_mask->hdr.dst_port);
+ sw_data[0] = ((ntohs(udp_spec->hdr.src_port) << 16) |
+ ntohs(udp_spec->hdr.dst_port)) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4, 0);
+ set_key_def_sw(key_def, sw_counter, DYN_L4, 0);
+ sw_counter += 1;
+ }
+ }
+
+ if (any_count > 0 || fd->l4_prot != -1) {
+ fd->tunnel_l4_prot = PROT_TUN_L4_UDP;
+ key_def->inner_proto = 1;
+ } else {
+ fd->l4_prot = PROT_L4_UDP;
+ key_def->outer_proto = 1;
+ }
+ return 0;
+}
+
+static int flow_elem_type_sctp(const struct flow_elem elem[], int eidx, struct flow_error *error,
+ struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count)
+{
+ const struct flow_elem_sctp *sctp_spec = (const struct flow_elem_sctp *)elem[eidx].spec;
+ const struct flow_elem_sctp *sctp_mask = (const struct flow_elem_sctp *)elem[eidx].mask;
+
+ if (sctp_spec != NULL && sctp_mask != NULL) {
+ if (sctp_mask->hdr.src_port || sctp_mask->hdr.dst_port) {
+ if (sw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = (ntohs(sctp_mask->hdr.src_port) << 16) |
+ ntohs(sctp_mask->hdr.dst_port);
+ sw_data[0] = ((ntohs(sctp_spec->hdr.src_port) << 16) |
+ ntohs(sctp_spec->hdr.dst_port)) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4, 0);
+ set_key_def_sw(key_def, sw_counter, DYN_L4, 0);
+ sw_counter += 1;
+ }
+ }
+
+ if (any_count > 0 || fd->l4_prot != -1) {
+ fd->tunnel_l4_prot = PROT_TUN_L4_SCTP;
+ key_def->inner_proto = 1;
+ } else {
+ fd->l4_prot = PROT_L4_SCTP;
+ key_def->outer_proto = 1;
+ }
+ return 0;
+}
+
+static int flow_elem_type_tcp(const struct flow_elem elem[], int eidx, struct flow_error *error,
+ struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def, uint32_t any_count)
+{
+ const struct flow_elem_tcp *tcp_spec = (const struct flow_elem_tcp *)elem[eidx].spec;
+ const struct flow_elem_tcp *tcp_mask = (const struct flow_elem_tcp *)elem[eidx].mask;
+
+ if (tcp_spec != NULL && tcp_mask != NULL) {
+ if (tcp_mask->hdr.src_port || tcp_mask->hdr.dst_port) {
+ if (sw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = (ntohs(tcp_mask->hdr.src_port) << 16) |
+ ntohs(tcp_mask->hdr.dst_port);
+ sw_data[0] = ((ntohs(tcp_spec->hdr.src_port) << 16) |
+ ntohs(tcp_spec->hdr.dst_port)) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4, 0);
+ set_key_def_sw(key_def, sw_counter, DYN_L4, 0);
+ sw_counter += 1;
+ }
+ }
+
+ if (any_count > 0 || fd->l4_prot != -1) {
+ fd->tunnel_l4_prot = PROT_TUN_L4_TCP;
+ key_def->inner_proto = 1;
+ } else {
+ fd->l4_prot = PROT_L4_TCP;
+ key_def->outer_proto = 1;
+ }
+ return 0;
+}
+
+static int flow_elem_type_gtp(const struct flow_elem elem[], int eidx, struct flow_error *error,
+ struct nic_flow_def *fd, unsigned int sw_counter, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def)
+{
+ const struct flow_elem_gtp *gtp_spec = (const struct flow_elem_gtp *)elem[eidx].spec;
+ const struct flow_elem_gtp *gtp_mask = (const struct flow_elem_gtp *)elem[eidx].mask;
+
+ if (gtp_spec != NULL && gtp_mask != NULL) {
+ if (gtp_mask->teid) {
+ if (sw_counter >= 2) {
+ NT_LOG(ERR, FILTER, "Key size too big. Out of SW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return 1;
+ }
+
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = ntohl(gtp_mask->teid);
+ sw_data[0] = ntohl(gtp_spec->teid) & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1, DYN_L4_PAYLOAD, 4);
+ set_key_def_sw(key_def, sw_counter, DYN_L4_PAYLOAD, 4);
+ sw_counter += 1;
+ }
+ }
+
+ fd->tunnel_prot = PROT_TUN_GTPV1U;
+ return 0;
+}
+
+static struct nic_flow_def *interpret_flow_elements(struct flow_eth_dev *dev,
+ const struct flow_elem elem[], const struct flow_action action[],
+ struct flow_error *error, uint16_t implicit_vlan_vid,
+ uint32_t *in_port_id, uint32_t *num_dest_port,
+ uint32_t *num_queues, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def)
+{
+ uint32_t any_count = 0;
+ int mtr_count = 0;
+
+ unsigned int encap_decap_order = 0;
+
+ unsigned int qw_counter = 0;
+ unsigned int sw_counter = 0;
+
+ uint64_t modify_field_use_flags = 0x0;
+
+ *in_port_id = UINT32_MAX;
+ *num_dest_port = 0;
+ *num_queues = 0;
+
+ memset(packet_data, 0x0, sizeof(uint32_t) * 10);
+ memset(packet_mask, 0x0, sizeof(uint32_t) * 10);
+ key_def->data = 0;
+
+ if (action == NULL || elem == NULL) {
+ flow_nic_set_error(ERR_FAILED, error);
+ NT_LOG(ERR, FILTER, "Flow items / actions missing\n");
+ return NULL;
+ }
+
+ struct nic_flow_def *fd = calloc(1, sizeof(struct nic_flow_def));
+
+ if (!fd) {
+ flow_nic_set_error(ERR_MEMORY, error);
+ NT_LOG(ERR, FILTER, "ERR Memory\n");
+ return NULL;
+ }
+
+ /* Set default values for fd */
+ fd->full_offload = -1;
+ fd->in_port_override = -1;
+ fd->mark = UINT32_MAX;
+ fd->jump_to_group = UINT32_MAX;
+
+ fd->l2_prot = -1;
+ fd->l3_prot = -1;
+ fd->l4_prot = -1;
+ fd->vlans = 0;
+ fd->tunnel_prot = -1;
+ fd->tunnel_l3_prot = -1;
+ fd->tunnel_l4_prot = -1;
+ fd->fragmentation = -1;
+
+ NT_LOG(DBG, FILTER,
+ ">>>>> [Dev %p] Nic %i, Port %i: fd %p - FLOW Interpretation <<<<<\n",
+ dev, dev->ndev->adapter_no, dev->port, fd);
+
+ /*
+ * Gather flow match + actions and convert into internal flow definition structure
+ * (struct nic_flow_def_s)
+ * This is the 1st step in the flow creation - validate, convert and prepare
+ */
+ for (int aidx = 0; action[aidx].type != FLOW_ACTION_TYPE_END; ++aidx) {
+ switch (action[aidx].type) {
+ case FLOW_ACTION_TYPE_PORT_ID:
+ NT_LOG(DBG, FILTER,
+ "Dev:%p: FLOW_ACTION_TYPE_PORT_ID\n", dev);
+ if (action[aidx].conf) {
+ uint32_t port_id =
+ ((const struct flow_action_port_id *)
+ action[aidx]
+ .conf)
+ ->id;
+ uint8_t port = get_port_from_port_id(dev->ndev,
+ port_id);
+
+ if (fd->dst_num_avail == MAX_OUTPUT_DEST) {
+ /* ERROR too many output destinations */
+ NT_LOG(ERR, FILTER,
+ "Too many output destinations\n");
+ flow_nic_set_error(ERR_OUTPUT_TOO_MANY,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (port >= dev->ndev->be.num_phy_ports) {
+ /* ERROR phy port out of range */
+ NT_LOG(ERR, FILTER,
+ "Phy port out of range\n");
+ flow_nic_set_error(ERR_OUTPUT_INVALID,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ /* New destination port to add */
+ fd->dst_id[fd->dst_num_avail].owning_port_id =
+ port_id;
+ fd->dst_id[fd->dst_num_avail].type = PORT_PHY;
+ fd->dst_id[fd->dst_num_avail].id = (int)port;
+ fd->dst_id[fd->dst_num_avail].active = 1;
+ fd->dst_num_avail++;
+
+ if (fd->flm_mtu_fragmentation_recipe == 0) {
+ fd->flm_mtu_fragmentation_recipe =
+ convert_port_to_ifr_mtu_recipe(port);
+ }
+
+ if (fd->full_offload < 0)
+ fd->full_offload = 1;
+
+ *num_dest_port += 1;
+
+ NT_LOG(DBG, FILTER, "Phy port ID: %i\n",
+ (int)port);
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_QUEUE:
+ NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_QUEUE\n",
+ dev);
+ if (action[aidx].conf) {
+ const struct flow_action_queue *queue =
+ (const struct flow_action_queue *)
+ action[aidx]
+ .conf;
+
+ int hw_id = rx_queue_idx_to_hw_id(dev,
+ queue->index);
+
+ fd->dst_id[fd->dst_num_avail].owning_port_id =
+ dev->port;
+ fd->dst_id[fd->dst_num_avail].id = hw_id;
+ fd->dst_id[fd->dst_num_avail].type = PORT_VIRT;
+ fd->dst_id[fd->dst_num_avail].active = 1;
+ fd->dst_num_avail++;
+
+ NT_LOG(DBG, FILTER,
+ "Dev:%p: FLOW_ACTION_TYPE_QUEUE port %u, queue index: %u, hw id %u\n",
+ dev, dev->port, queue->index, hw_id);
+
+ fd->full_offload = 0;
+ *num_queues += 1;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_RSS:
+ NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_RSS\n",
+ dev);
+ if (action[aidx].conf) {
+ const struct flow_action_rss *rss =
+ (const struct flow_action_rss *)
+ action[aidx]
+ .conf;
+
+ for (uint32_t i = 0; i < rss->queue_num; ++i) {
+ int hw_id = rx_queue_idx_to_hw_id(dev, rss->queue[i]);
+
+ fd->dst_id[fd->dst_num_avail]
+ .owning_port_id = dev->port;
+ fd->dst_id[fd->dst_num_avail].id =
+ hw_id;
+ fd->dst_id[fd->dst_num_avail].type =
+ PORT_VIRT;
+ fd->dst_id[fd->dst_num_avail].active =
+ 1;
+ fd->dst_num_avail++;
+ }
+
+ fd->full_offload = 0;
+ *num_queues += rss->queue_num;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_MARK:
+ NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_MARK\n",
+ dev);
+ if (action[aidx].conf) {
+ fd->mark = ((const struct flow_action_mark *)
+ action[aidx]
+ .conf)
+ ->id;
+ NT_LOG(DBG, FILTER, "Mark: %i\n", fd->mark);
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_JUMP:
+ NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_JUMP\n",
+ dev);
+ if (action[aidx].conf) {
+ const struct flow_action_jump *jump =
+ (const struct flow_action_jump *)
+ action[aidx]
+ .conf;
+ fd->jump_to_group = jump->group;
+ NT_LOG(DBG, FILTER,
+ "Dev:%p: FLOW_ACTION_TYPE_JUMP: group %u\n",
+ dev, jump->group);
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_DROP:
+ NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_DROP\n",
+ dev);
+ if (action[aidx].conf) {
+ fd->dst_id[fd->dst_num_avail].owning_port_id =
+ 0;
+ fd->dst_id[fd->dst_num_avail].id = 0;
+ fd->dst_id[fd->dst_num_avail].type = PORT_NONE;
+ fd->dst_num_avail++;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_METER:
+ NT_LOG(DBG, FILTER, "Dev:%p: FLOW_ACTION_TYPE_METER\n",
+ dev);
+ if (action[aidx].conf) {
+ const struct flow_action_meter *meter =
+ (const struct flow_action_meter *)
+ action[aidx]
+ .conf;
+ if (mtr_count >= MAX_FLM_MTRS_SUPPORTED) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: - Number of METER actions exceeds %d.\n",
+ MAX_FLM_MTRS_SUPPORTED);
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+ fd->mtr_ids[mtr_count++] = meter->mtr_id + 1;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_RAW_ENCAP:
+ NT_LOG(DBG, FILTER,
+ "Dev:%p: FLOW_ACTION_TYPE_RAW_ENCAP\n", dev);
+ if (action[aidx].conf) {
+ const struct flow_action_raw_encap *encap =
+ (const struct flow_action_raw_encap *)
+ action[aidx]
+ .conf;
+ const struct flow_elem *items = encap->items;
+
+ if (encap_decap_order != 1) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: - RAW_ENCAP must follow RAW_DECAP.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (encap->size == 0 || encap->size > 255 ||
+ encap->item_count < 2) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: - RAW_ENCAP data/size invalid.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ encap_decap_order = 2;
+
+ fd->tun_hdr.len = (uint8_t)encap->size;
+ memcpy(fd->tun_hdr.d.hdr8, encap->data,
+ fd->tun_hdr.len);
+
+ while (items->type != FLOW_ELEM_TYPE_END) {
+ switch (items->type) {
+ case FLOW_ELEM_TYPE_ETH:
+ fd->tun_hdr.l2_len = 14;
+ break;
+ case FLOW_ELEM_TYPE_VLAN:
+ fd->tun_hdr.nb_vlans += 1;
+ fd->tun_hdr.l2_len += 4;
+ break;
+ case FLOW_ELEM_TYPE_IPV4:
+ fd->tun_hdr.ip_version = 4;
+ fd->tun_hdr.l3_len = sizeof(struct ipv4_hdr_s);
+ fd->tun_hdr.new_outer = 1;
+ break;
+ case FLOW_ELEM_TYPE_IPV6:
+ fd->tun_hdr.ip_version = 6;
+ fd->tun_hdr.l3_len = sizeof(struct ipv6_hdr_s);
+ fd->tun_hdr.new_outer = 1;
+ break;
+ case FLOW_ELEM_TYPE_SCTP:
+ fd->tun_hdr.l4_len = sizeof(struct sctp_hdr_s);
+ break;
+ case FLOW_ELEM_TYPE_TCP:
+ fd->tun_hdr.l4_len = sizeof(struct tcp_hdr_s);
+ break;
+ case FLOW_ELEM_TYPE_UDP:
+ fd->tun_hdr.l4_len = sizeof(struct udp_hdr_s);
+ break;
+ case FLOW_ELEM_TYPE_ICMP:
+ fd->tun_hdr.l4_len = sizeof(struct icmp_hdr_s);
+ break;
+ default:
+ break;
+ }
+ items++;
+ }
+
+ if (fd->tun_hdr.nb_vlans > 3) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: - Encapsulation with %d vlans not supported.\n",
+ (int)fd->tun_hdr.nb_vlans);
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ /* Convert encap data to 128-bit little endian */
+ for (size_t i = 0; i < (encap->size + 15) / 16;
+ ++i) {
+ uint8_t *data =
+ fd->tun_hdr.d.hdr8 + i * 16;
+ for (unsigned int j = 0; j < 8; ++j) {
+ uint8_t t = data[j];
+
+ data[j] = data[15 - j];
+ data[15 - j] = t;
+ }
+ }
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_RAW_DECAP:
+ NT_LOG(DBG, FILTER,
+ "Dev:%p: FLOW_ACTION_TYPE_RAW_DECAP\n", dev);
+ if (action[aidx].conf) {
+ const struct flow_action_raw_decap *decap =
+ (const struct flow_action_raw_decap *)
+ action[aidx]
+ .conf;
+
+ if (encap_decap_order != 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: - RAW_ENCAP must follow RAW_DECAP.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (decap->item_count < 2) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: - RAW_DECAP must decap something.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ encap_decap_order = 1;
+
+ fd->header_strip_start_dyn = 2;
+ fd->header_strip_start_ofs = 2;
+
+ switch (decap->items[decap->item_count - 2]
+ .type) {
+ case FLOW_ELEM_TYPE_ETH:
+ case FLOW_ELEM_TYPE_VLAN:
+ fd->header_strip_end_dyn = 4;
+ fd->header_strip_end_ofs = 0;
+ break;
+ case FLOW_ELEM_TYPE_IPV4:
+ case FLOW_ELEM_TYPE_IPV6:
+ fd->header_strip_end_dyn = 7;
+ fd->header_strip_end_ofs = 0;
+ fd->header_strip_removed_outer_ip = 1;
+ break;
+ case FLOW_ELEM_TYPE_SCTP:
+ case FLOW_ELEM_TYPE_TCP:
+ case FLOW_ELEM_TYPE_UDP:
+ case FLOW_ELEM_TYPE_ICMP:
+ fd->header_strip_end_dyn = 8;
+ fd->header_strip_end_ofs = 0;
+ fd->header_strip_removed_outer_ip = 1;
+ break;
+ case FLOW_ELEM_TYPE_GTP:
+ fd->header_strip_end_dyn = 13;
+ fd->header_strip_end_ofs = 0;
+ fd->header_strip_removed_outer_ip = 1;
+ break;
+ default:
+ fd->header_strip_end_dyn = 1;
+ fd->header_strip_end_ofs = 0;
+ fd->header_strip_removed_outer_ip = 1;
+ break;
+ }
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_MODIFY_FIELD:
+ NT_LOG(DBG, FILTER,
+ "Dev:%p: FLOW_ACTION_TYPE_MODIFY_FIELD\n", dev);
+ {
+ const struct flow_action_modify_field *modify_field =
+ (const struct flow_action_modify_field *)
+ action[aidx]
+ .conf;
+ uint64_t modify_field_use_flag = 0;
+
+ if (modify_field->src.field !=
+ FLOW_FIELD_VALUE) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD only src type VALUE is supported.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (modify_field->dst.level > 2) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD only dst level 0, 1, and 2 is supported.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (modify_field->dst.field ==
+ FLOW_FIELD_IPV4_TTL ||
+ modify_field->dst.field ==
+ FLOW_FIELD_IPV6_HOPLIMIT) {
+ if (modify_field->operation !=
+ FLOW_MODIFY_SUB) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD only operation SUB is supported for TTL/HOPLIMIT.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (fd->ttl_sub_enable) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD TTL/HOPLIMIT resource already in use.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ fd->ttl_sub_enable = 1;
+ fd->ttl_sub_ipv4 =
+ (modify_field->dst.field ==
+ FLOW_FIELD_IPV4_TTL) ?
+ 1 :
+ 0;
+ fd->ttl_sub_outer =
+ (modify_field->dst.level <= 1) ?
+ 1 :
+ 0;
+ } else {
+ if (modify_field->operation !=
+ FLOW_MODIFY_SET) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD only operation SET "
+ "is supported in general.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ if (fd->modify_field_count >=
+ dev->ndev->be.tpe.nb_cpy_writers) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD exceeded maximum of %u"
+ " MODIFY_FIELD actions.\n",
+ dev->ndev->be.tpe
+ .nb_cpy_writers);
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ switch (modify_field->dst.field) {
+ case FLOW_FIELD_IPV4_DSCP:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_DSCP_IPV4;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn = DYN_L3;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 1;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 1;
+ break;
+ case FLOW_FIELD_IPV6_DSCP:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_DSCP_IPV6;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn = DYN_L3;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 0;
+ fd->modify_field
+ /*
+ * len=2 is needed because IPv6 DSCP overlaps 2
+ * bytes.
+ */
+ [fd->modify_field_count]
+ .len = 2;
+ break;
+ case FLOW_FIELD_GTP_PSC_QFI:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_RQI_QFI;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn =
+ DYN_L4_PAYLOAD;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 14;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 1;
+ break;
+ case FLOW_FIELD_IPV4_SRC:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_IPV4;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn = DYN_L3;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 12;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 4;
+ break;
+ case FLOW_FIELD_IPV4_DST:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_IPV4;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn = DYN_L3;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 16;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 4;
+ break;
+ case FLOW_FIELD_TCP_PORT_SRC:
+ /* fallthrough */
+ case FLOW_FIELD_UDP_PORT_SRC:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_PORT;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn = DYN_L4;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 0;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 2;
+ break;
+ case FLOW_FIELD_TCP_PORT_DST:
+ /* fallthrough */
+ case FLOW_FIELD_UDP_PORT_DST:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_PORT;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn = DYN_L4;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 2;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 2;
+ break;
+ case FLOW_FIELD_GTP_TEID:
+ fd->modify_field
+ [fd->modify_field_count]
+ .select =
+ CPY_SELECT_TEID;
+ fd->modify_field
+ [fd->modify_field_count]
+ .dyn =
+ DYN_L4_PAYLOAD;
+ fd->modify_field
+ [fd->modify_field_count]
+ .ofs = 4;
+ fd->modify_field
+ [fd->modify_field_count]
+ .len = 4;
+ break;
+ default:
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD dst type is not supported.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ modify_field_use_flag =
+ 1
+ << fd->modify_field
+ [fd->modify_field_count]
+ .select;
+ if (modify_field_use_flag &
+ modify_field_use_flags) {
+ NT_LOG(ERR, FILTER,
+ "MODIFY_FIELD dst type hardware "
+ "resource already used.\n");
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED,
+ error);
+ free(fd);
+ return NULL;
+ }
+
+ memcpy(fd->modify_field
+ [fd->modify_field_count]
+ .value8,
+ modify_field->src.value, 16);
+
+ fd->modify_field[fd->modify_field_count]
+ .level =
+ modify_field->dst.level;
+
+ modify_field_use_flags |=
+ modify_field_use_flag;
+ fd->modify_field_count += 1;
+ }
+ }
+ break;
+
+ default:
+ NT_LOG(ERR, FILTER,
+ "Invalid or unsupported flow action received - %i\n",
+ action[aidx].type);
+ flow_nic_set_error(ERR_ACTION_UNSUPPORTED, error);
+ free(fd);
+ return NULL;
+ }
+ }
+
+ if (!(encap_decap_order == 0 || encap_decap_order == 2)) {
+ NT_LOG(ERR, FILTER, "Invalid encap/decap actions\n");
+ free(fd);
+ return NULL;
+ }
+
+ if (implicit_vlan_vid > 0) {
+ uint32_t *sw_data = &packet_data[1 - sw_counter];
+ uint32_t *sw_mask = &packet_mask[1 - sw_counter];
+
+ sw_mask[0] = 0x0fff;
+ sw_data[0] = implicit_vlan_vid & sw_mask[0];
+
+ km_add_match_elem(&fd->km, &sw_data[0], &sw_mask[0], 1,
+ DYN_FIRST_VLAN, 0);
+ set_key_def_sw(key_def, sw_counter, DYN_FIRST_VLAN, 0);
+ sw_counter += 1;
+
+ fd->vlans += 1;
+ }
+
+ /*
+ * All Actions interpreted
+ */
+ for (int eidx = 0; elem[eidx].type != FLOW_ELEM_TYPE_END; ++eidx) {
+ switch (elem[eidx].type) {
+ case FLOW_ELEM_TYPE_ANY:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_ANY\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ const struct flow_elem_any *any_spec =
+ (const struct flow_elem_any *)elem[eidx]
+ .spec;
+ const struct flow_elem_any *any_mask =
+ (const struct flow_elem_any *)elem[eidx]
+ .mask;
+
+ if (any_spec && any_mask) {
+ any_count += any_spec->num &
+ any_mask->num;
+ }
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_ETH:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_ETH\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ const struct flow_elem_eth *eth_spec =
+ (const struct flow_elem_eth *)elem[eidx]
+ .spec;
+ const struct flow_elem_eth *eth_mask =
+ (const struct flow_elem_eth *)elem[eidx]
+ .mask;
+
+ if (any_count > 0) {
+ NT_LOG(ERR, FILTER,
+ "Tunneled L2 ethernet not supported\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return NULL;
+ }
+
+ if (qw_counter >= 2) {
+ NT_LOG(ERR, FILTER,
+ "Key size too big. Out of QW resources.\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fd);
+ return NULL;
+ }
+
+ if (eth_spec != NULL && eth_mask != NULL) {
+ if (is_non_zero(eth_mask->d_addr.addr_b,
+ 6) ||
+ is_non_zero(eth_mask->s_addr.addr_b,
+ 6)) {
+ uint32_t *qw_data =
+ &packet_data[2 + 4 -
+ qw_counter *
+ 4];
+ uint32_t *qw_mask =
+ &packet_mask[2 + 4 -
+ qw_counter *
+ 4];
+
+ qw_data[0] =
+ ((eth_spec->d_addr
+ .addr_b[0] &
+ eth_mask->d_addr
+ .addr_b[0])
+ << 24) +
+ ((eth_spec->d_addr
+ .addr_b[1] &
+ eth_mask->d_addr
+ .addr_b[1])
+ << 16) +
+ ((eth_spec->d_addr
+ .addr_b[2] &
+ eth_mask->d_addr
+ .addr_b[2])
+ << 8) +
+ (eth_spec->d_addr
+ .addr_b[3] &
+ eth_mask->d_addr
+ .addr_b[3]);
+
+ qw_data[1] =
+ ((eth_spec->d_addr
+ .addr_b[4] &
+ eth_mask->d_addr
+ .addr_b[4])
+ << 24) +
+ ((eth_spec->d_addr
+ .addr_b[5] &
+ eth_mask->d_addr
+ .addr_b[5])
+ << 16) +
+ ((eth_spec->s_addr
+ .addr_b[0] &
+ eth_mask->s_addr
+ .addr_b[0])
+ << 8) +
+ (eth_spec->s_addr
+ .addr_b[1] &
+ eth_mask->s_addr
+ .addr_b[1]);
+
+ qw_data[2] =
+ ((eth_spec->s_addr
+ .addr_b[2] &
+ eth_mask->s_addr
+ .addr_b[2])
+ << 24) +
+ ((eth_spec->s_addr
+ .addr_b[3] &
+ eth_mask->s_addr
+ .addr_b[3])
+ << 16) +
+ ((eth_spec->s_addr
+ .addr_b[4] &
+ eth_mask->s_addr
+ .addr_b[4])
+ << 8) +
+ (eth_spec->s_addr
+ .addr_b[5] &
+ eth_mask->s_addr
+ .addr_b[5]);
+
+ qw_mask[0] = (eth_mask->d_addr
+ .addr_b[0]
+ << 24) +
+ (eth_mask->d_addr
+ .addr_b[1]
+ << 16) +
+ (eth_mask->d_addr
+ .addr_b[2]
+ << 8) +
+ eth_mask->d_addr
+ .addr_b[3];
+
+ qw_mask[1] = (eth_mask->d_addr
+ .addr_b[4]
+ << 24) +
+ (eth_mask->d_addr
+ .addr_b[5]
+ << 16) +
+ (eth_mask->s_addr
+ .addr_b[0]
+ << 8) +
+ eth_mask->s_addr
+ .addr_b[1];
+
+ qw_mask[2] = (eth_mask->s_addr
+ .addr_b[2]
+ << 24) +
+ (eth_mask->s_addr
+ .addr_b[3]
+ << 16) +
+ (eth_mask->s_addr
+ .addr_b[4]
+ << 8) +
+ eth_mask->s_addr
+ .addr_b[5];
+
+ km_add_match_elem(&fd->km,
+ &qw_data[(size_t)(qw_counter *
+ 4)],
+ &qw_mask[(size_t)(qw_counter *
+ 4)],
+ 3, DYN_L2, 0);
+ set_key_def_qw(key_def,
+ qw_counter,
+ DYN_L2, 0);
+ qw_counter += 1;
+ }
+ }
+
+ fd->l2_prot = PROT_L2_ETH2;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VLAN:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_VLAN\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_vlan(elem, eidx, implicit_vlan_vid, error, fd,
+ sw_counter, packet_data, packet_mask, key_def))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_IPV4:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_IPV4\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_ipv4(elem, eidx, error, fd, qw_counter,
+ sw_counter, packet_data, packet_mask, key_def, any_count))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_IPV6:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_IPV6\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_ipv6(elem, eidx, error, fd, qw_counter,
+ packet_data, packet_mask, key_def, any_count))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_UDP:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_UDP\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_upd(elem, eidx, error, fd, sw_counter,
+ packet_data, packet_mask, key_def, any_count))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_SCTP:
+ NT_LOG(DBG, FILTER,
+ "Adap %i,Port %i:FLOW_ELEM_TYPE_SCTP\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_sctp(elem, eidx, error, fd, sw_counter,
+ packet_data, packet_mask, key_def, any_count))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_TCP:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_TCP\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_tcp(elem, eidx, error, fd, sw_counter,
+ packet_data, packet_mask, key_def, any_count))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_GTP:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_GTP\n",
+ dev->ndev->adapter_no, dev->port);
+ {
+ if (flow_elem_type_gtp(elem, eidx, error, fd, sw_counter,
+ packet_data, packet_mask, key_def))
+ return NULL;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_PORT_ID:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_PORT_ID\n",
+ dev->ndev->adapter_no, dev->port);
+ if (elem[eidx].spec) {
+ *in_port_id =
+ ((const struct flow_elem_port_id *)
+ elem[eidx]
+ .spec)
+ ->id;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VOID:
+ NT_LOG(DBG, FILTER,
+ "Adap %i, Port %i: FLOW_ELEM_TYPE_VOID\n",
+ dev->ndev->adapter_no, dev->port);
+ break;
+
+ default:
+ NT_LOG(ERR, FILTER,
+ "Invalid or unsupported flow request: %d\n",
+ (int)elem[eidx].type);
+ flow_nic_set_error(ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM,
+ error);
+ free(fd);
+ return NULL;
+ }
+ }
+
+ return fd;
+}
+
+static int reset_cat_function_setup(struct flow_eth_dev *dev, int cfn)
+{
+ /* CFN */
+ {
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PRESET_ALL, cfn,
+ 0, 0);
+ hw_mod_cat_cfn_flush(&dev->ndev->be, cfn, 1);
+ }
+
+ /* KM */
+ {
+ uint32_t bm = 0;
+
+ hw_mod_cat_kce_km_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, cfn / 8, &bm);
+ hw_mod_cat_kce_km_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, cfn / 8,
+ bm & ~(1 << (cfn % 8)));
+ hw_mod_cat_kcs_km_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST, cfn, 0);
+
+ hw_mod_cat_kce_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ cfn / 8, 1);
+ hw_mod_cat_kcs_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST, cfn,
+ 1);
+
+ for (unsigned int ft = 0; ft < dev->ndev->be.cat.nb_flow_types;
+ ft++) {
+ set_flow_type_km(dev->ndev, cfn, ft, 0, 0);
+ set_flow_type_km(dev->ndev, cfn, ft, 1, 0);
+ set_flow_type_km(dev->ndev, cfn, ft, 2, 0);
+ set_flow_type_km(dev->ndev, cfn, ft, 3, 0);
+ }
+ }
+
+ /* FLM */
+ {
+ uint32_t bm = 0;
+
+ hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, cfn / 8, &bm);
+ hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, cfn / 8,
+ bm & ~(1 << (cfn % 8)));
+ hw_mod_cat_kcs_flm_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST, cfn, 0);
+
+ hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ cfn / 8, 1);
+ hw_mod_cat_kcs_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST, cfn,
+ 1);
+
+ for (unsigned int ft = 0; ft < dev->ndev->be.cat.nb_flow_types;
+ ft++) {
+ set_flow_type_flm(dev->ndev, cfn, ft, 0, 0);
+ set_flow_type_flm(dev->ndev, cfn, ft, 1, 0);
+ set_flow_type_flm(dev->ndev, cfn, ft, 2, 0);
+ set_flow_type_flm(dev->ndev, cfn, ft, 3, 0);
+ }
+ }
+
+ /* CTE / CTS */
+ {
+ uint32_t cte = 0;
+
+ hw_mod_cat_cte_get(&dev->ndev->be, HW_CAT_CTE_ENABLE_BM, cfn,
+ &cte);
+
+ if (cte) {
+ const int cts_offset =
+ ((int)dev->ndev->be.cat.cts_num + 1) / 2;
+
+ hw_mod_cat_cte_set(&dev->ndev->be, HW_CAT_CTE_ENABLE_BM,
+ cfn, 0);
+ hw_mod_cat_cte_flush(&dev->ndev->be, cfn, 1);
+
+ for (int cte_type = 0; cte_type < cts_offset;
+ ++cte_type) {
+ hw_mod_cat_cts_set(&dev->ndev->be,
+ HW_CAT_CTS_CAT_A,
+ cts_offset * cfn + cte_type,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be,
+ HW_CAT_CTS_CAT_B,
+ cts_offset * cfn + cte_type,
+ 0);
+ }
+
+ hw_mod_cat_cts_flush(&dev->ndev->be, cts_offset * cfn,
+ cts_offset);
+ }
+ }
+
+ return 0;
+}
+
+static int convert_fd_to_flm(struct flow_handle *fh, struct nic_flow_def *fd,
+ const uint32_t *packet_data, uint32_t flm_key_id,
+ uint16_t rpl_ext_ptr, uint32_t priority)
+{
+ if (fh->type != FLOW_HANDLE_TYPE_FLM)
+ return -1;
+
+ switch (fd->l4_prot) {
+ case PROT_L4_TCP:
+ fh->flm_prot = 6;
+ break;
+ case PROT_L4_UDP:
+ fh->flm_prot = 17;
+ break;
+ case PROT_L4_SCTP:
+ fh->flm_prot = 132;
+ break;
+ case PROT_L4_ICMP:
+ fh->flm_prot = 1;
+ break;
+ default:
+ switch (fd->tunnel_l4_prot) {
+ case PROT_TUN_L4_TCP:
+ fh->flm_prot = 6;
+ break;
+ case PROT_TUN_L4_UDP:
+ fh->flm_prot = 17;
+ break;
+ case PROT_TUN_L4_SCTP:
+ fh->flm_prot = 132;
+ break;
+ case PROT_TUN_L4_ICMP:
+ fh->flm_prot = 1;
+ break;
+ default:
+ fh->flm_prot = 0;
+ break;
+ }
+ break;
+ }
+
+ memcpy(fh->flm_data, packet_data, sizeof(uint32_t) * 10);
+
+ fh->flm_kid = flm_key_id;
+ fh->flm_rpl_ext_ptr = rpl_ext_ptr;
+ fh->flm_prio = (uint8_t)priority;
+
+ for (unsigned int i = 0; i < fd->modify_field_count; ++i) {
+ switch (fd->modify_field[i].select) {
+ case CPY_SELECT_DSCP_IPV4:
+ /* fallthrough */
+ case CPY_SELECT_DSCP_IPV6:
+ fh->flm_dscp = fd->modify_field[i].value8[0];
+ break;
+ case CPY_SELECT_RQI_QFI:
+ fh->flm_rqi = (fd->modify_field[i].value8[0] >> 6) &
+ 0x1;
+ fh->flm_qfi = fd->modify_field[i].value8[0] & 0x3f;
+ break;
+ case CPY_SELECT_IPV4:
+ fh->flm_nat_ipv4 =
+ ntohl(fd->modify_field[i].value32[0]);
+ break;
+ case CPY_SELECT_PORT:
+ fh->flm_nat_port =
+ ntohs(fd->modify_field[i].value16[0]);
+ break;
+ case CPY_SELECT_TEID:
+ fh->flm_teid = ntohl(fd->modify_field[i].value32[0]);
+ break;
+ }
+ }
+
+ fh->flm_mtu_fragmentation_recipe = fd->flm_mtu_fragmentation_recipe;
+
+ return 0;
+}
+
+static int flm_flow_programming(struct flow_eth_dev *dev,
+ struct flow_handle *fh, uint32_t *mtr_ids,
+ uint32_t flm_ft, uint32_t flm_op)
+{
+ struct flm_v17_lrn_data_s learn_record;
+
+ if (fh->type != FLOW_HANDLE_TYPE_FLM)
+ return -1;
+
+ memset(&learn_record, 0x0, sizeof(struct flm_v17_lrn_data_s));
+
+ learn_record.qw0[0] = fh->flm_data[9];
+ learn_record.qw0[1] = fh->flm_data[8];
+ learn_record.qw0[2] = fh->flm_data[7];
+ learn_record.qw0[3] = fh->flm_data[6];
+ learn_record.qw4[0] = fh->flm_data[5];
+ learn_record.qw4[1] = fh->flm_data[4];
+ learn_record.qw4[2] = fh->flm_data[3];
+ learn_record.qw4[3] = fh->flm_data[2];
+ learn_record.sw8 = fh->flm_data[1];
+ learn_record.sw9 = fh->flm_data[0];
+ learn_record.prot = fh->flm_prot;
+
+ if (mtr_ids) {
+ FLM_V17_MBR_ID1(learn_record.mbr_idx) = mtr_ids[0];
+ FLM_V17_MBR_ID2(learn_record.mbr_idx) = mtr_ids[1];
+ FLM_V17_MBR_ID3(learn_record.mbr_idx) = mtr_ids[2];
+ FLM_V17_MBR_ID4(learn_record.mbr_idx) = mtr_ids[3];
+
+ /* Last non-zero mtr is used for statistics */
+ uint8_t mbrs = 0;
+
+ while (mbrs < MAX_FLM_MTRS_SUPPORTED && mtr_ids[mbrs] != 0)
+ ++mbrs;
+ learn_record.vol_idx = mbrs;
+ }
+
+ learn_record.nat_ip = fh->flm_nat_ipv4;
+ learn_record.nat_port = fh->flm_nat_port;
+ learn_record.nat_en = fh->flm_nat_ipv4 || fh->flm_nat_port ? 1 : 0;
+
+ learn_record.dscp = fh->flm_dscp;
+ learn_record.teid = fh->flm_teid;
+ learn_record.qfi = fh->flm_qfi;
+ learn_record.rqi = fh->flm_rqi;
+ learn_record.color = fh->flm_rpl_ext_ptr &
+ 0x3ff; /* Lower 10 bits used for RPL EXT PTR */
+ learn_record.color |= (fh->flm_mtu_fragmentation_recipe & 0xf)
+ << 10; /* Bit [13:10] used for MTU recipe */
+
+ learn_record.ent = 0;
+ learn_record.op = flm_op & 0xf;
+ learn_record.prio = fh->flm_prio & 0x3;
+ learn_record.ft = flm_ft;
+ learn_record.kid = fh->flm_kid;
+ learn_record.eor = 1;
+
+ int res = flow_flm_apply(dev, &learn_record);
+ return res;
+}
+
+static int km_ft_handler(int *setup_km_ft, int *setup_km_rcp, int *setup_km,
+ struct flow_handle *found_flow, int identical_flow_found, struct flow_eth_dev *dev,
+ struct nic_flow_def *fd, struct flow_error *error, struct flow_handle *fh,
+ struct flow_handle *flow)
+{
+ if (!identical_flow_found) {
+ /* Find existing KM FT that can be reused */
+ {
+ int found_ft = 0, found_zero = 0;
+
+ struct flm_flow_ft_ident_s *ft_idents =
+ (struct flm_flow_ft_ident_s *)dev->ndev->ft_res_handle;
+ struct flm_flow_ft_ident_s ft_ident = flow_def_to_ft_ident(fd);
+
+ for (int i = 1; i < FLM_FLOW_FT_MAX; ++i) {
+ if (ft_ident.data == ft_idents[i].data) {
+ found_ft = i;
+ break;
+ } else if (found_zero == 0 && ft_idents[i].data == 0) {
+ found_zero = i;
+ }
+ }
+
+ if (found_ft) {
+ if (flow_nic_ref_resource(dev->ndev, RES_KM_FLOW_TYPE, found_ft)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not reference "
+ "KM FLOW TYPE resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+
+ fh->resource[RES_KM_FLOW_TYPE].count = 1;
+ fh->resource[RES_KM_FLOW_TYPE].index = found_ft;
+ fh->resource[RES_KM_FLOW_TYPE].referenced = 1;
+ } else if (found_zero) {
+ if (flow_nic_allocate_fh_resource_index(dev->ndev, RES_KM_FLOW_TYPE,
+ found_zero, fh)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not get "
+ "KM FLOW TYPE resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+
+ ft_idents[found_zero].data = ft_ident.data;
+ } else {
+ NT_LOG(ERR, FILTER, "ERROR: Could not get KM FLOW TYPE resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+ }
+ /* Attach resources to KM entry */
+ km_attach_ndev_resource_management(&fd->km, &dev->ndev->km_res_handle);
+ fd->km.flow_type = fh->resource[RES_KM_FLOW_TYPE].index;
+
+ /* _update existing KM RCP or allocate a new RCP */
+ if (found_flow != NULL) {
+ if (flow_nic_ref_resource(dev->ndev, RES_KM_CATEGORY, found_flow
+ ->resource[RES_KM_CATEGORY].index)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not reference "
+ "KM CATEGORY resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+
+ fh->resource[RES_KM_CATEGORY].count = 1;
+ fh->resource[RES_KM_CATEGORY].index =
+ found_flow->resource[RES_KM_CATEGORY].index;
+ fh->resource[RES_KM_CATEGORY].referenced = 1;
+
+ if (fd->km.target == KM_CAM) {
+ uint32_t ft_a_mask = 0;
+
+ hw_mod_km_rcp_get(&dev->ndev->be, HW_KM_RCP_FTM_A,
+ fh->resource[RES_KM_CATEGORY].index, 0, &ft_a_mask);
+ hw_mod_km_rcp_set(&dev->ndev->be, HW_KM_RCP_FTM_A,
+ fh->resource[RES_KM_CATEGORY].index, 0,
+ ft_a_mask | (1 << fd->km.flow_type));
+ }
+ } else {
+ if (flow_nic_allocate_fh_resource(dev->ndev, RES_KM_CATEGORY, fh, 1, 1)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not get KM CATEGORY resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+
+ /* Note: km_rcp_set clears existing RCPs */
+ km_rcp_set(&fd->km, fh->resource[RES_KM_CATEGORY].index);
+ }
+
+ /* Set filter setup variables */
+ *setup_km = 1;
+ *setup_km_ft = fh->resource[RES_KM_FLOW_TYPE].index;
+ *setup_km_rcp = fh->resource[RES_KM_CATEGORY].index;
+
+ /* _flush KM RCP and entry */
+ hw_mod_km_rcp_flush(&dev->ndev->be, fh->resource[RES_KM_CATEGORY].index, 1);
+
+ km_write_data_match_entry(&fd->km, 0);
+ } else {
+ if (flow_nic_ref_resource(dev->ndev, RES_KM_FLOW_TYPE,
+ found_flow->resource[RES_KM_FLOW_TYPE].index)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not reference KM FLOW TYPE resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+
+ fh->resource[RES_KM_FLOW_TYPE].count = 1;
+ fh->resource[RES_KM_FLOW_TYPE].index = found_flow->resource[RES_KM_FLOW_TYPE].index;
+ fh->resource[RES_KM_FLOW_TYPE].referenced = 1;
+
+ if (flow_nic_ref_resource(dev->ndev, RES_KM_CATEGORY,
+ found_flow->resource[RES_KM_CATEGORY].index)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not reference KM CATEGORY resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return 1;
+ }
+
+ fh->resource[RES_KM_CATEGORY].count = 1;
+ fh->resource[RES_KM_CATEGORY].index = found_flow->resource[RES_KM_CATEGORY].index;
+ fh->resource[RES_KM_CATEGORY].referenced = 1;
+
+ km_attach_ndev_resource_management(&fd->km, &dev->ndev->km_res_handle);
+ fd->km.flow_type = fh->resource[RES_KM_FLOW_TYPE].index;
+
+ km_refer_data_match_entry(&fd->km, &found_flow->fd->km);
+
+ *setup_km = 1;
+ *setup_km_ft = flow->resource[RES_KM_FLOW_TYPE].index;
+ *setup_km_rcp = flow->resource[RES_KM_CATEGORY].index;
+ }
+ return 0;
+}
+
+/*
+ * Tunneling invalidates dynamic offsets, so change them to static
+ * offsets starting at beginning of L2.
+ */
+static void align_tun_offset(struct nic_flow_def *fd, const uint32_t eth_length, int i,
+ uint32_t *ofs, uint32_t select, const uint32_t l2_length, const uint32_t l3_length,
+ const uint32_t l4_length, uint32_t *dyn)
+{
+ if (fd->tun_hdr.len > eth_length) {
+ if (!fd->tun_hdr.new_outer || fd->modify_field[i].level > 1) {
+ ofs += fd->tun_hdr.len - eth_length;
+ } else {
+ switch (select) {
+ case CPY_SELECT_IPV4:
+ case CPY_SELECT_DSCP_IPV4:
+ case CPY_SELECT_DSCP_IPV6:
+ *ofs += l2_length;
+ break;
+ case CPY_SELECT_PORT:
+ *ofs += l2_length + l3_length;
+ break;
+ case CPY_SELECT_TEID:
+ case CPY_SELECT_RQI_QFI:
+ *ofs += l2_length + l3_length + l4_length;
+ break;
+ }
+ *dyn = 1;
+ }
+ }
+}
+
+static struct flow_handle *
+create_flow_filter(struct flow_eth_dev *dev, struct nic_flow_def *fd,
+ const struct flow_attr *attr, struct flow_error *error,
+ uint32_t port_id, uint32_t num_dest_port,
+ uint32_t num_queues, uint32_t *packet_data,
+ uint32_t *packet_mask, struct flm_flow_key_def_s *key_def)
+{
+ uint32_t qsl_size = num_dest_port > num_queues ? num_dest_port :
+ num_queues;
+ uint32_t flm_key_id = 0;
+ uint32_t flm_ft = 0;
+ uint16_t flm_rpl_ext_ptr = 0;
+
+ struct flow_handle *fh_flm = NULL;
+ struct flow_handle *fh = calloc(1, sizeof(struct flow_handle));
+
+ if (!fh) {
+ NT_LOG(ERR, FILTER, "ERR memory\n");
+ flow_nic_set_error(ERR_MEMORY, error);
+ return NULL;
+ }
+
+ fh->type = FLOW_HANDLE_TYPE_FLOW;
+ fh->port_id = port_id;
+ fh->dev = dev;
+ fh->fd = fd;
+
+ int setup_cat_cfn = 0;
+ int setup_cat_cot = 0;
+ int setup_cat_cts = 0;
+ int setup_qsl_rcp = 0;
+
+ int setup_flm = 0;
+ int setup_flm_ft = 0;
+
+ int setup_km = 0;
+ int setup_km_ft = 0;
+ int setup_km_rcp = 0;
+
+ int setup_default_ft = 0;
+
+ int setup_hst = 0;
+ int setup_tpe = 0;
+ int setup_tpe_encap_data = 0;
+
+ int free_fd = 0;
+
+ const int empty_pattern =
+ fd->l2_prot < 0 && fd->l3_prot < 0 && fd->l4_prot < 0 &&
+ fd->vlans == 0 && fd->tunnel_prot < 0 &&
+ fd->tunnel_l3_prot < 0 && fd->tunnel_l4_prot < 0;
+
+ if (attr->group > 0 && empty_pattern) {
+ /*
+ * Group 0 default filter actions
+ */
+ struct flow_handle *fh_miss = NULL;
+
+ if (flm_flow_get_group_miss_fh(dev, attr->group, &fh_miss)) {
+ /* Error was printed to log by flm_flow_get_group_miss_fh */
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fh);
+ return NULL;
+ }
+
+ if (fh_miss == NULL) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not setup default action for uninitialized group\n");
+ flow_nic_set_error(ERR_FAILED, error);
+ free(fh);
+ return NULL;
+ }
+
+ if (qsl_size > 0 &&
+ flow_nic_allocate_fh_resource(dev->ndev, RES_QSL_QST, fh,
+ qsl_size, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get QSL QST resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ free(fh);
+ return NULL;
+ }
+
+ if (flow_nic_ref_resource(dev->ndev, RES_QSL_RCP,
+ fh_miss->resource[RES_QSL_RCP].index)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not reference QSL RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ free(fh);
+ return NULL;
+ }
+
+ fh->resource[RES_QSL_RCP].count = 1;
+ fh->resource[RES_QSL_RCP].index =
+ fh_miss->resource[RES_QSL_RCP].index;
+ fh->resource[RES_QSL_RCP].referenced = 1;
+
+ nic_insert_flow(dev->ndev, fh);
+
+ setup_qsl_rcp = 1;
+ } else if (attr->group > 0) {
+ /*
+ * FLM programming
+ */
+ struct flow_handle *fh_excisting = NULL;
+ int cfn_to_copy = -1;
+
+ if (attr->priority >= dev->ndev->be.flm.nb_prios) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Priority value of FLM flow exceeds %u"
+ "\n",
+ dev->ndev->be.flm.nb_prios);
+ flow_nic_set_error(ERR_FLOW_PRIORITY_VALUE_INVALID,
+ error);
+ free(fh);
+ return NULL;
+ }
+
+ if (flm_flow_learn_prepare(dev, fh, attr->group, key_def,
+ packet_mask, &flm_key_id, &flm_ft,
+ &cfn_to_copy, &setup_km_ft,
+ &fh_excisting)) {
+ /* Error was printed to log by flm_flow_learn_prepare */
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ free(fh);
+ return NULL;
+ }
+
+ setup_tpe_encap_data = (fd->tun_hdr.len > 0);
+ setup_tpe =
+ (fd->modify_field_count > 0 || fd->ttl_sub_enable > 0);
+
+ /* Create HIT filter for new FLM FT */
+ if (cfn_to_copy >= 0) {
+ uint32_t value = 0;
+
+ nic_insert_flow(dev->ndev, fh);
+
+ setup_qsl_rcp = 1;
+ setup_cat_cot = 1;
+ setup_cat_cts = 1;
+
+ setup_default_ft = 1;
+
+ setup_flm = 1;
+ setup_flm_ft = (int)flm_ft;
+
+ setup_tpe |= setup_tpe_encap_data;
+
+ if (fd->header_strip_start_dyn != fd->header_strip_end_dyn ||
+ fd->header_strip_start_ofs != fd->header_strip_end_ofs)
+ setup_hst = 1;
+
+ if (flow_nic_allocate_fh_resource(dev->ndev,
+ RES_CAT_CFN,
+ fh, 1, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get CAT CFN resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ if (flow_nic_allocate_fh_resource(dev->ndev,
+ RES_CAT_COT,
+ fh, 1, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get CAT COT resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ if (flow_nic_allocate_fh_resource(dev->ndev,
+ RES_QSL_RCP,
+ fh, 1, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get QSL RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ if (qsl_size > 0 &&
+ flow_nic_allocate_fh_resource(dev->ndev,
+ RES_QSL_QST,
+ fh, qsl_size, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get QSL QST resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ NT_LOG(DBG, FILTER,
+ "FLM: Creating new CFN %d as a copy of CFN %d with FT %d\n",
+ fh->resource[RES_CAT_CFN].index, cfn_to_copy,
+ setup_flm_ft);
+
+ /* Copy parts from base MISS filter */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_COPY_FROM,
+ fh->resource[RES_CAT_CFN].index, 0,
+ cfn_to_copy);
+ hw_mod_cat_cfn_flush(&dev->ndev->be,
+ fh->resource[RES_CAT_CFN].index,
+ 1);
+
+ hw_mod_cat_kcs_km_get(&dev->ndev->be,
+ HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST, cfn_to_copy,
+ &value);
+ if (value > 0) {
+ setup_km = 1;
+ setup_km_rcp = (int)value;
+ }
+
+ hw_mod_cat_kcs_flm_get(&dev->ndev->be,
+ HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST, cfn_to_copy,
+ &value);
+ hw_mod_cat_kcs_flm_set(&dev->ndev->be,
+ HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index,
+ value);
+ hw_mod_cat_kcs_flm_flush(&dev->ndev->be,
+ KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index,
+ 1);
+
+ fh_flm = calloc(1, sizeof(struct flow_handle));
+ if (!fh_flm) {
+ flow_nic_set_error(ERR_MEMORY, error);
+ return NULL;
+ }
+
+ nic_insert_flow_flm(dev->ndev, fh_flm);
+
+ fh_flm->type = FLOW_HANDLE_TYPE_FLM;
+ fh_flm->dev = dev;
+ fh_flm->flm_owner = fh;
+ } else {
+ /* Reuse allocated memory */
+ fh_flm = fh;
+ fh = fh_excisting;
+
+ nic_insert_flow_flm(dev->ndev, fh_flm);
+
+ fh_flm->type = FLOW_HANDLE_TYPE_FLM;
+ fh_flm->dev = dev;
+ fh_flm->flm_owner = fh_excisting;
+
+ free_fd = 1;
+ }
+
+ fh_flm->flm_owner->flm_ref_count += 1;
+ } else {
+ /*
+ * Filter creation
+ */
+ nic_insert_flow(dev->ndev, fh);
+
+ setup_cat_cfn = 1;
+ setup_cat_cts = 1;
+ setup_qsl_rcp = 1;
+
+ if (fd->km.num_ftype_elem) {
+ struct flow_handle *flow = dev->ndev->flow_base,
+ *found_flow = NULL;
+ int identical_flow_found = 0;
+
+ /* Compute new KM key */
+ if (km_key_create(&fd->km, fh->port_id)) {
+ NT_LOG(ERR, FILTER, "KM creation failed\n");
+ flow_nic_set_error(ERR_MATCH_FAILED_BY_HW_LIMITS,
+ error);
+ return NULL;
+ }
+
+ fd->km.be = &dev->ndev->be;
+
+ /* Find existing KM key that can be reused */
+ while (flow) {
+ if (flow->type == FLOW_HANDLE_TYPE_FLOW &&
+ flow->fd->km
+ .flow_type && /* This check also skips self */
+ flow->resource[RES_KM_CATEGORY].count) {
+ int res = km_key_compare(&fd->km,
+ &flow->fd->km);
+ if (res < 0) {
+ identical_flow_found = 1;
+ found_flow = flow;
+ break;
+ } else if (res > 0 &&
+ !flow->resource[RES_KM_CATEGORY]
+ .referenced &&
+ found_flow == NULL)
+ found_flow = flow;
+ }
+ flow = flow->next;
+ }
+ if (km_ft_handler(&setup_km_ft, &setup_km_rcp, &setup_km,
+ found_flow, identical_flow_found, dev, fd, error, fh, flow))
+ return NULL;
+ }
+
+ setup_default_ft = 1;
+
+ if (flow_nic_allocate_fh_resource(dev->ndev, RES_CAT_CFN,
+ fh, 1, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get CAT CFN resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ if (flow_nic_allocate_fh_resource(dev->ndev, RES_QSL_RCP, fh, 1,
+ 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get QSL RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ if (qsl_size > 0 &&
+ flow_nic_allocate_fh_resource(dev->ndev, RES_QSL_QST,
+ fh, qsl_size, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get QSL QST resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ /* Check if filter is set up for FLM */
+ if (fd->jump_to_group != UINT32_MAX) {
+ flm_flow_setup_group(dev, fd->jump_to_group,
+ fh->resource[RES_CAT_CFN].index,
+ fh->resource[RES_KM_FLOW_TYPE].index,
+ fh);
+ }
+ }
+
+ /*
+ * Setup QSL
+ */
+ if (setup_qsl_rcp) {
+ if (qsl_size == 0) {
+ /* Create drop filter */
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DISCARD,
+ fh->resource[RES_QSL_RCP].index,
+ 0x0);
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DROP,
+ fh->resource[RES_QSL_RCP].index,
+ 0x3);
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_LR,
+ fh->resource[RES_QSL_RCP].index,
+ 0x0);
+
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_LO,
+ fh->resource[RES_QSL_RCP].index, 0);
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_HI,
+ fh->resource[RES_QSL_RCP].index, 0);
+
+ hw_mod_qsl_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_QSL_RCP].index,
+ 1);
+ } else {
+ const int table_start = fh->resource[RES_QSL_QST].index;
+ const int table_end = table_start +
+ fh->resource[RES_QSL_QST].count -
+ 1;
+
+ /* Use 0x0 for pure retransmit */
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DISCARD,
+ fh->resource[RES_QSL_RCP].index,
+ 0x0);
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_DROP,
+ fh->resource[RES_QSL_RCP].index,
+ 0x0);
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_LR,
+ fh->resource[RES_QSL_RCP].index,
+ num_dest_port > 0 ? 0x3 : 0x0);
+
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_LO,
+ fh->resource[RES_QSL_RCP].index,
+ table_start);
+ hw_mod_qsl_rcp_set(&dev->ndev->be, HW_QSL_RCP_TBL_HI,
+ fh->resource[RES_QSL_RCP].index,
+ table_end);
+
+ hw_mod_qsl_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_QSL_RCP].index,
+ 1);
+
+ /* Setup QSL QST/QEN */
+ if (num_dest_port > 0 && num_queues > 0) {
+ int ports[num_dest_port];
+ int queues[num_queues];
+
+ int port_index = 0;
+ int queue_index = 0;
+
+ for (int i = 0; i < fd->dst_num_avail; ++i) {
+ if (fd->dst_id[i].type == PORT_PHY) {
+ ports[port_index++] =
+ fd->dst_id[i].id;
+ } else if (fd->dst_id[i].type ==
+ PORT_VIRT) {
+ queues[queue_index++] =
+ fd->dst_id[i].id;
+ }
+ }
+
+ for (int i = 0; i < fd->dst_num_avail; ++i) {
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_TX_PORT,
+ table_start + i,
+ ports[i % num_dest_port]);
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_LRE,
+ table_start + i, 1);
+
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_QUEUE,
+ table_start + i,
+ queues[i % num_queues]);
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_EN,
+ table_start + i, 1);
+ }
+ } else if (num_dest_port > 0) {
+ for (int i = 0; i < fd->dst_num_avail; ++i) {
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_TX_PORT,
+ table_start + i,
+ fd->dst_id[i].id);
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_LRE,
+ table_start + i, 1);
+ }
+ } else if (num_queues > 0) {
+ for (int i = 0; i < fd->dst_num_avail; ++i) {
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_QUEUE,
+ table_start + i,
+ fd->dst_id[i].id);
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_EN,
+ table_start + i, 1);
+ }
+ }
+
+ hw_mod_qsl_qst_flush(&dev->ndev->be, table_start,
+ fd->dst_num_avail);
+ }
+ }
+
+ /*
+ * Setup CAT KM functionality
+ */
+ if (setup_km) {
+ uint32_t bm = 0;
+
+ /* Enable KM match FS for key A */
+ set_flow_type_km(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ setup_km_ft, 0, 1);
+
+ /* KM function select */
+ hw_mod_cat_kcs_km_set(&dev->ndev->be, HW_CAT_KCS_CATEGORY,
+ KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index,
+ setup_km_rcp);
+ hw_mod_cat_kcs_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index, 1);
+
+ /* KM function enable */
+ hw_mod_cat_kce_km_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index / 8, &bm);
+ hw_mod_cat_kce_km_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, fh->resource[RES_CAT_CFN].index / 8,
+ bm | (1 << (fh->resource[RES_CAT_CFN].index % 8)));
+ hw_mod_cat_kce_km_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index / 8, 1);
+ } else if (setup_default_ft) {
+ /* Enable "no KM match" FT for key A */
+ set_flow_type_km(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ 0, 0, 1);
+ }
+
+ /*
+ * Setup CAT FLM functionality
+ */
+ if (setup_flm) {
+ uint32_t bm = 0;
+
+ /* Enable KM match FT for key A, and FLM match FT for key C */
+ set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ setup_km_ft, 0, 1); /* KM FT A */
+ set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ setup_flm_ft, 2, 1); /* FLM FT C */
+
+ /* FLM function enable */
+ hw_mod_cat_kce_flm_get(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index / 8,
+ &bm);
+ hw_mod_cat_kce_flm_set(&dev->ndev->be, HW_CAT_KCE_ENABLE_BM,
+ KM_FLM_IF_FIRST, fh->resource[RES_CAT_CFN].index / 8,
+ bm | (1 << (fh->resource[RES_CAT_CFN].index % 8)));
+ hw_mod_cat_kce_flm_flush(&dev->ndev->be, KM_FLM_IF_FIRST,
+ fh->resource[RES_CAT_CFN].index / 8,
+ 1);
+ } else if (setup_default_ft) {
+ /* Enable KM for key A and UNHANDLED for key C */
+ set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index,
+ setup_km_ft, 0, 1);
+ set_flow_type_flm(dev->ndev, fh->resource[RES_CAT_CFN].index, 1,
+ 2, 1);
+ }
+
+ /*
+ * Setup HST
+ */
+ if (setup_hst) {
+ int hst_index = -1;
+
+ for (int i = 1;
+ i < (int)dev->ndev->res[RES_HST_RCP].resource_count; ++i) {
+ uint32_t values[] = { 0, 0, 0, 0, 0 };
+
+ if (!flow_nic_is_resource_used(dev->ndev, RES_HST_RCP,
+ i))
+ continue;
+
+ hw_mod_hst_rcp_get(&dev->ndev->be,
+ HW_HST_RCP_STRIP_MODE, i,
+ &values[0]);
+ hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_START_DYN,
+ i, &values[1]);
+ hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_START_OFS,
+ i, &values[2]);
+ hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_END_DYN,
+ i, &values[3]);
+ hw_mod_hst_rcp_get(&dev->ndev->be, HW_HST_RCP_END_OFS,
+ i, &values[4]);
+
+ if ((int)values[0] == 1 &&
+ (int)values[1] == fd->header_strip_start_dyn &&
+ (int)values[2] == fd->header_strip_start_ofs &&
+ (int)values[3] == fd->header_strip_end_dyn &&
+ (int)values[4] == fd->header_strip_end_ofs) {
+ hst_index = i;
+ break;
+ }
+ }
+
+ if (hst_index >= 0) {
+ if (flow_nic_ref_resource(dev->ndev, RES_HST_RCP,
+ hst_index)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not reference HST RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ fh->resource[RES_HST_RCP].count = 1;
+ fh->resource[RES_HST_RCP].index = hst_index;
+ fh->resource[RES_HST_RCP].referenced = 1;
+ } else {
+ if (flow_nic_allocate_fh_resource(dev->ndev,
+ RES_HST_RCP,
+ fh, 1, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get HST RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ hw_mod_hst_rcp_set(&dev->ndev->be,
+ HW_HST_RCP_STRIP_MODE,
+ fh->resource[RES_HST_RCP].index, 1);
+ hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_START_DYN,
+ fh->resource[RES_HST_RCP].index,
+ fd->header_strip_start_dyn);
+ hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_START_OFS,
+ fh->resource[RES_HST_RCP].index,
+ fd->header_strip_start_ofs);
+ hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_END_DYN,
+ fh->resource[RES_HST_RCP].index,
+ fd->header_strip_end_dyn);
+ hw_mod_hst_rcp_set(&dev->ndev->be, HW_HST_RCP_END_OFS,
+ fh->resource[RES_HST_RCP].index,
+ fd->header_strip_end_ofs);
+
+ hw_mod_hst_rcp_set(&dev->ndev->be,
+ HW_HST_RCP_MODIF0_CMD,
+ fh->resource[RES_HST_RCP].index,
+ fd->header_strip_removed_outer_ip ? 7 : 6);
+ hw_mod_hst_rcp_set(&dev->ndev->be,
+ HW_HST_RCP_MODIF0_DYN,
+ fh->resource[RES_HST_RCP].index, 2);
+ hw_mod_hst_rcp_set(&dev->ndev->be,
+ HW_HST_RCP_MODIF0_OFS,
+ fh->resource[RES_HST_RCP].index, 0);
+
+ hw_mod_hst_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_HST_RCP].index, 1);
+ }
+ }
+
+ /*
+ * Setup TPE
+ */
+ if (setup_tpe_encap_data) {
+ int ext_rpl_index = -1;
+ int rpl_rpl_index = -1;
+ int rpl_rpl_length = -1;
+
+ /* Find existing RPL */
+ for (int i = 1;
+ i < (int)dev->ndev->res[RES_TPE_EXT].resource_count; ++i) {
+ int found = 1;
+ uint32_t len;
+ uint32_t ptr;
+
+ if (!flow_nic_is_resource_used(dev->ndev, RES_TPE_EXT,
+ i))
+ continue;
+
+ hw_mod_tpe_rpl_ext_get(&dev->ndev->be,
+ HW_TPE_RPL_EXT_META_RPL_LEN, i,
+ &len);
+ if (len != fd->tun_hdr.len)
+ continue;
+
+ hw_mod_tpe_rpl_ext_get(&dev->ndev->be,
+ HW_TPE_RPL_EXT_RPL_PTR, i, &ptr);
+
+ for (uint32_t ptr_it = 0; ptr_it < (len + 15) / 16;
+ ++ptr_it) {
+ uint32_t data[4];
+
+ hw_mod_tpe_rpl_rpl_get(&dev->ndev->be,
+ HW_TPE_RPL_RPL_VALUE,
+ ptr + ptr_it, data);
+
+ if (fd->tun_hdr.d.hdr32[ptr_it * 4 + 0] !=
+ data[0] ||
+ fd->tun_hdr.d.hdr32[ptr_it * 4 + 1] !=
+ data[1] ||
+ fd->tun_hdr.d.hdr32[ptr_it * 4 + 2] !=
+ data[2] ||
+ fd->tun_hdr.d.hdr32[ptr_it * 4 + 3] !=
+ data[3]) {
+ found = 0;
+ break;
+ }
+ }
+
+ if (found) {
+ ext_rpl_index = i;
+ rpl_rpl_index = (int)ptr;
+ rpl_rpl_length = (int)len;
+ break;
+ }
+ }
+
+ /* Set RPL data */
+ if (ext_rpl_index >= 0) {
+ if (flow_nic_ref_resource(dev->ndev, RES_TPE_EXT,
+ ext_rpl_index)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not reference TPE EXT resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ for (int i = 0; i < (rpl_rpl_length + 15) / 16; ++i) {
+ if (flow_nic_ref_resource(dev->ndev,
+ RES_TPE_RPL,
+ rpl_rpl_index + i)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not reference TPE RPL resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+ }
+ } else {
+ ext_rpl_index = flow_nic_alloc_resource(dev->ndev,
+ RES_TPE_EXT, 1);
+ if (ext_rpl_index < 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get TPE EXT resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ rpl_rpl_length = ((int)fd->tun_hdr.len + 15) / 16;
+ rpl_rpl_index = flow_nic_alloc_resource_contig(dev->ndev,
+ RES_TPE_RPL,
+ rpl_rpl_length,
+ 1);
+ if (rpl_rpl_index < 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get TPE RPL resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ /* Program new encap header data */
+ hw_mod_tpe_rpl_ext_set(&dev->ndev->be,
+ HW_TPE_RPL_EXT_RPL_PTR,
+ ext_rpl_index, rpl_rpl_index);
+ hw_mod_tpe_rpl_ext_set(&dev->ndev->be,
+ HW_TPE_RPL_EXT_META_RPL_LEN,
+ ext_rpl_index, fd->tun_hdr.len);
+ hw_mod_tpe_rpl_ext_flush(&dev->ndev->be, ext_rpl_index,
+ 1);
+
+ for (int i = 0; i < rpl_rpl_length; ++i) {
+ hw_mod_tpe_rpl_rpl_set(&dev->ndev->be,
+ HW_TPE_RPL_RPL_VALUE,
+ rpl_rpl_index + i,
+ fd->tun_hdr.d.hdr32 + i * 4);
+ }
+ hw_mod_tpe_rpl_rpl_flush(&dev->ndev->be, rpl_rpl_index,
+ rpl_rpl_length);
+ }
+
+ flm_rpl_ext_ptr = ext_rpl_index;
+ }
+
+ if (setup_tpe) {
+ const uint32_t eth_length = 14;
+ const uint32_t l2_length = fd->tun_hdr.l2_len;
+ const uint32_t l3_length = fd->tun_hdr.l3_len;
+ const uint32_t l4_length = fd->tun_hdr.l4_len;
+ const uint32_t fcs_length = 4;
+
+ int tpe_index = -1;
+
+ /* Find existing RCP */
+ for (int i = 1;
+ i < (int)dev->ndev->res[RES_TPE_RCP].resource_count; ++i) {
+ uint32_t value;
+
+ if (!flow_nic_is_resource_used(dev->ndev, RES_TPE_RCP,
+ i))
+ continue;
+
+ hw_mod_tpe_rpl_rcp_get(&dev->ndev->be,
+ HW_TPE_RPL_RCP_LEN, i, &value);
+ if (value != fd->tun_hdr.len)
+ continue;
+ hw_mod_tpe_rpl_rcp_get(&dev->ndev->be,
+ HW_TPE_RPL_RCP_DYN, i, &value);
+ if (value != 1)
+ continue;
+ hw_mod_tpe_rpl_rcp_get(&dev->ndev->be,
+ HW_TPE_RPL_RCP_OFS, i, &value);
+ if (value != 0)
+ continue;
+ hw_mod_tpe_hfu_rcp_get(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L3_PRT, i,
+ &value);
+ if (value != (fd->tun_hdr.ip_version == 4 ? 1 : 2))
+ continue;
+ hw_mod_tpe_hfu_rcp_get(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L3_OFS, i,
+ &value);
+ if (value != l2_length)
+ continue;
+
+ tpe_index = i;
+ break;
+ }
+
+ /* Set RCP data */
+ if (tpe_index >= 0) {
+ if (flow_nic_ref_resource(dev->ndev, RES_TPE_RCP,
+ tpe_index)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not reference TPE RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ fh->resource[RES_TPE_RCP].count = 1;
+ fh->resource[RES_TPE_RCP].index = tpe_index;
+ fh->resource[RES_TPE_RCP].referenced = 1;
+ } else {
+ if (flow_nic_allocate_fh_resource(dev->ndev,
+ RES_TPE_RCP,
+ fh, 1, 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Could not get TPE RCP resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION,
+ error);
+ return NULL;
+ }
+
+ /* Extend packet if needed. */
+ if (fd->tun_hdr.len > eth_length) {
+ /* Extend FPGA packet buffer */
+ hw_mod_tpe_rpp_rcp_set(&dev->ndev->be,
+ HW_TPE_RPP_RCP_EXP,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ hw_mod_tpe_rpp_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+
+ /*
+ * Insert 0's into packet
+ * After this step DYN offsets are shifted by encap length,
+ * so only DYN offset 1 and 18 should be used
+ */
+ hw_mod_tpe_ins_rcp_set(&dev->ndev->be,
+ HW_TPE_INS_RCP_DYN,
+ fh->resource[RES_TPE_RCP].index, 1);
+ hw_mod_tpe_ins_rcp_set(&dev->ndev->be,
+ HW_TPE_INS_RCP_OFS,
+ fh->resource[RES_TPE_RCP].index, 0);
+ hw_mod_tpe_ins_rcp_set(&dev->ndev->be,
+ HW_TPE_INS_RCP_LEN,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ hw_mod_tpe_ins_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ }
+
+ if (fd->tun_hdr.len > 0) {
+ /* Write header data to beginning of packet */
+ hw_mod_tpe_rpl_rcp_set(&dev->ndev->be,
+ HW_TPE_RPL_RCP_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_rpl_rcp_set(&dev->ndev->be,
+ HW_TPE_RPL_RCP_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_rpl_rcp_set(&dev->ndev->be,
+ HW_TPE_RPL_RCP_LEN,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len);
+ hw_mod_tpe_rpl_rcp_set(&dev->ndev->be,
+ HW_TPE_RPL_RCP_RPL_PTR,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_rpl_rcp_set(&dev->ndev->be,
+ HW_TPE_RPL_RCP_EXT_PRIO,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_rpl_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ }
+
+ for (unsigned int i = 0; i < fd->modify_field_count;
+ ++i) {
+ uint32_t select = fd->modify_field[i].select;
+ uint32_t dyn = fd->modify_field[i].dyn;
+ uint32_t ofs = fd->modify_field[i].ofs;
+ uint32_t len = fd->modify_field[i].len;
+
+ align_tun_offset(fd, eth_length, i, &ofs, select, l2_length,
+ l3_length, l4_length, &dyn);
+
+ hw_mod_tpe_cpy_rcp_set(&dev->ndev->be,
+ HW_TPE_CPY_RCP_READER_SELECT,
+ fh->resource[RES_TPE_RCP].index +
+ 16 * i,
+ select);
+ hw_mod_tpe_cpy_rcp_set(&dev->ndev->be,
+ HW_TPE_CPY_RCP_DYN,
+ fh->resource[RES_TPE_RCP].index +
+ 16 * i,
+ dyn);
+ hw_mod_tpe_cpy_rcp_set(&dev->ndev->be,
+ HW_TPE_CPY_RCP_OFS,
+ fh->resource[RES_TPE_RCP].index +
+ 16 * i,
+ ofs);
+ hw_mod_tpe_cpy_rcp_set(&dev->ndev->be,
+ HW_TPE_CPY_RCP_LEN,
+ fh->resource[RES_TPE_RCP].index +
+ 16 * i,
+ len);
+ hw_mod_tpe_cpy_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index +
+ 16 * i,
+ 1);
+ }
+
+ if (fd->tun_hdr.new_outer) {
+ /*
+ * UDP length
+ * dyn_ofs[ADD_DYN] - dyn_ofs[SUB_DYN] + ADD_OFS
+ */
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_WR,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_POS_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_POS_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ l2_length + l3_length + 4);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_ADD_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 18);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_ADD_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ -(l2_length + l3_length + fcs_length));
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_A_SUB_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+
+ /* IPv4/IPv6 length */
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_B_WR,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_B_POS_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_B_POS_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ l2_length +
+ (fd->tun_hdr.ip_version == 4 ? 2 : 4));
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_B_ADD_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 18);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_B_ADD_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ -(l2_length +
+ (fd->tun_hdr.ip_version == 4 ?
+ 0 : l3_length) + fcs_length));
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_B_SUB_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+
+ /* GTP length */
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_C_WR,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_C_POS_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_C_POS_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ l2_length + l3_length + l4_length + 2);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_C_ADD_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 18);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_C_ADD_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ -(l2_length + l3_length + l4_length +
+ 8 + fcs_length));
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_LEN_C_SUB_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+
+ /* _update TTL */
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_WR,
+ fh->resource[RES_TPE_RCP].index,
+ fd->ttl_sub_enable);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ fd->ttl_sub_outer ? 1 : DYN_L3);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ (fd->ttl_sub_outer ?
+ l2_length :
+ fd->tun_hdr.len - eth_length) +
+ (fd->ttl_sub_ipv4 ? 8 : 7));
+
+ /* _update FPGA DYN offsets */
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_CS_INF,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L3_PRT,
+ fh->resource[RES_TPE_RCP].index,
+ (fd->tun_hdr.ip_version == 4 ? 1 : 2));
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L3_FRAG,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TUNNEL,
+ fh->resource[RES_TPE_RCP].index,
+ 6);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L4_PRT,
+ fh->resource[RES_TPE_RCP].index,
+ 2);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L3_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ l2_length);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L4_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ l2_length + l3_length);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_INNER_L3_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_INNER_L4_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+
+ hw_mod_tpe_hfu_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ } else {
+ /* _update TTL */
+ if (fd->ttl_sub_enable) {
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_WR,
+ fh->resource[RES_TPE_RCP].index,
+ fd->ttl_sub_enable);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ fd->ttl_sub_outer ? DYN_L3 :
+ DYN_TUN_L3);
+ if (fd->tun_hdr.len == 0) {
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_OFS,
+ fh->resource[RES_TPE_RCP]
+ .index,
+ fd->ttl_sub_ipv4 ? 8 : 7);
+ } else {
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_OFS,
+ fh->resource[RES_TPE_RCP]
+ .index,
+ (fd->tun_hdr.len -
+ eth_length) +
+ (fd->ttl_sub_ipv4 ?
+ 8 : 7));
+ }
+ } else {
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_WR,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_DYN,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TTL_POS_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ }
+
+ /* _update FPGA DYN offsets */
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_CS_INF,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L3_PRT,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L3_FRAG,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_TUNNEL,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_L4_PRT,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ if (fd->tun_hdr.len == 0) {
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L3_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L4_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_INNER_L3_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_INNER_L4_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ 0);
+ } else {
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L3_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_OUTER_L4_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_INNER_L3_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_HFU_RCP_INNER_L4_OFS,
+ fh->resource[RES_TPE_RCP].index,
+ fd->tun_hdr.len - eth_length);
+ }
+
+ hw_mod_tpe_hfu_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ }
+
+ /* Calculate valid outer and inner checksums */
+ hw_mod_tpe_csu_rcp_set(&dev->ndev->be,
+ HW_TPE_CSU_RCP_OUTER_L3_CMD,
+ fh->resource[RES_TPE_RCP].index,
+ 3);
+ hw_mod_tpe_csu_rcp_set(&dev->ndev->be,
+ HW_TPE_CSU_RCP_OUTER_L4_CMD,
+ fh->resource[RES_TPE_RCP].index,
+ 3);
+ hw_mod_tpe_csu_rcp_set(&dev->ndev->be,
+ HW_TPE_CSU_RCP_INNER_L3_CMD,
+ fh->resource[RES_TPE_RCP].index,
+ 3);
+ hw_mod_tpe_csu_rcp_set(&dev->ndev->be,
+ HW_TPE_CSU_RCP_INNER_L4_CMD,
+ fh->resource[RES_TPE_RCP].index,
+ 3);
+ hw_mod_tpe_csu_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_TPE_RCP].index,
+ 1);
+ }
+ }
+
+ /*
+ * Setup CAT Color Table functionality
+ */
+ if (setup_cat_cot) {
+ hw_mod_cat_cot_set(&dev->ndev->be, HW_CAT_COT_COLOR,
+ fh->resource[RES_CAT_COT].index, 0);
+ hw_mod_cat_cot_set(&dev->ndev->be, HW_CAT_COT_KM,
+ fh->resource[RES_CAT_COT].index, 0x4);
+ hw_mod_cat_cot_flush(&dev->ndev->be,
+ fh->resource[RES_CAT_COT].index, 1);
+ }
+
+ /*
+ * Setup CAT action functionality
+ */
+ if (setup_cat_cts) {
+ /* Setup CAT CTS */
+ const int offset = ((int)dev->ndev->be.cat.cts_num + 1) / 2;
+
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A,
+ offset * fh->resource[RES_CAT_CFN].index + 0,
+ fh->resource[RES_CAT_COT].index);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B,
+ offset * fh->resource[RES_CAT_CFN].index + 0,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A,
+ offset * fh->resource[RES_CAT_CFN].index + 1,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B,
+ offset * fh->resource[RES_CAT_CFN].index + 1,
+ fh->resource[RES_QSL_RCP].index);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A,
+ offset * fh->resource[RES_CAT_CFN].index + 2,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B,
+ offset * fh->resource[RES_CAT_CFN].index + 2,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A,
+ offset * fh->resource[RES_CAT_CFN].index + 3,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B,
+ offset * fh->resource[RES_CAT_CFN].index + 3,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A,
+ offset * fh->resource[RES_CAT_CFN].index + 4,
+ fh->resource[RES_HST_RCP].index);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B,
+ offset * fh->resource[RES_CAT_CFN].index + 4,
+ 0);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_A,
+ offset * fh->resource[RES_CAT_CFN].index + 5,
+ fh->resource[RES_TPE_RCP].index);
+ hw_mod_cat_cts_set(&dev->ndev->be, HW_CAT_CTS_CAT_B,
+ offset * fh->resource[RES_CAT_CFN].index + 5,
+ 0);
+
+ hw_mod_cat_cts_flush(&dev->ndev->be,
+ offset * fh->resource[RES_CAT_CFN].index,
+ 6);
+ hw_mod_cat_cts_flush(&dev->ndev->be,
+ offset * fh->resource[RES_CAT_CFN].index,
+ 6);
+
+ /* Setup CAT CTE */
+ hw_mod_cat_cte_set(&dev->ndev->be,
+ HW_CAT_CTE_ENABLE_BM,
+ fh->resource[RES_CAT_CFN].index,
+ (fh->resource[RES_CAT_COT].index ? 0x001 : 0) | 0x004 |
+ (fh->resource[RES_QSL_RCP].index ? 0x008 : 0) |
+ 0x040 |
+ (fh->resource[RES_HST_RCP].index ? 0x100 : 0) |
+ (fh->resource[RES_TPE_RCP].index ? 0x400 : 0));
+ hw_mod_cat_cte_flush(&dev->ndev->be,
+ fh->resource[RES_CAT_CFN].index, 1);
+ }
+
+ /*
+ * Setup CAT CFN
+ *
+ * Once CAT CFN has been programmed traffic will start match the filter,
+ * so CAT CFN must be the last thing to be programmed.
+ */
+ if (setup_cat_cfn) {
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_SET_ALL_DEFAULTS,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ENABLE,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_INV,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+
+ /* Protocol checks */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_INV,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_ISL,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_CFP,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_MAC,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_L2,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->l2_prot != -1 ? (1 << fd->l2_prot) : -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_VNTAG,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_VLAN,
+ fh->resource[RES_CAT_CFN].index, 0,
+ (0xf << fd->vlans) & 0xf);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_MPLS,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_L3,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->l3_prot != -1 ? (1 << fd->l3_prot) : -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_FRAG,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->fragmentation);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_IP_PROT,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_L4,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->l4_prot != -1 ? (1 << fd->l4_prot) : -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be,
+ HW_CAT_CFN_PTC_TUNNEL,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->tunnel_prot != -1 ? (1 << fd->tunnel_prot) : -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_L2,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_VLAN,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_MPLS,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_L3,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->tunnel_l3_prot != -1 ?
+ (1 << fd->tunnel_l3_prot) : -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_FRAG,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_IP_PROT,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PTC_TNL_L4,
+ fh->resource[RES_CAT_CFN].index, 0,
+ fd->tunnel_l4_prot != -1 ?
+ (1 << fd->tunnel_l4_prot) : -1);
+
+ /* Error checks */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_INV,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_CV,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_FCS,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_TRUNC,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_L3_CS,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_L4_CS,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_TNL_L3_CS,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_ERR_TNL_L4_CS,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be,
+ HW_CAT_CFN_ERR_TTL_EXP,
+ fh->resource[RES_CAT_CFN].index, 0,
+ (fd->ttl_sub_enable && fd->ttl_sub_outer) ? -1 : 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be,
+ HW_CAT_CFN_ERR_TNL_TTL_EXP,
+ fh->resource[RES_CAT_CFN].index, 0,
+ (fd->ttl_sub_enable && !fd->ttl_sub_outer) ? -1 : 0x1);
+
+ /* MAC port check */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_MAC_PORT,
+ fh->resource[RES_CAT_CFN].index, 0,
+ 1 << fh->port_id);
+
+ /* Pattern match checks */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_CMP,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_DCT,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_EXT_INV,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_CMB,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_AND_INV,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_OR_INV,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_PM_INV,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+
+ /* Length checks */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_LC,
+ fh->resource[RES_CAT_CFN].index, 0, 0x0);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_LC_INV,
+ fh->resource[RES_CAT_CFN].index, 0, -1);
+
+ /* KM and FLM */
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_KM0_OR,
+ fh->resource[RES_CAT_CFN].index, 0, 0x1);
+ hw_mod_cat_cfn_set(&dev->ndev->be, HW_CAT_CFN_KM1_OR,
+ fh->resource[RES_CAT_CFN].index, 0, 0x3);
+
+ hw_mod_cat_cfn_flush(&dev->ndev->be,
+ fh->resource[RES_CAT_CFN].index, 1);
+ }
+
+ /* Program FLM flow */
+ if (fh_flm) {
+ convert_fd_to_flm(fh_flm, fd, packet_data, flm_key_id,
+ flm_rpl_ext_ptr, attr->priority);
+ flm_flow_programming(dev, fh_flm, fd->mtr_ids, flm_ft, 1);
+ }
+
+ if (free_fd)
+ free(fd);
+
+ return (fh_flm) ? fh_flm : fh;
+}
+
+/*
+ * Public functions
+ */
+
+int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
+{
+ if (!ndev->flow_mgnt_prepared) {
+ /* Check static arrays are big enough */
+ assert(ndev->be.tpe.nb_cpy_writers <=
+ MAX_CPY_WRITERS_SUPPORTED);
+
+ /* KM Flow Type 0 is reserved */
+ flow_nic_mark_resource_used(ndev, RES_KM_FLOW_TYPE, 0);
+ flow_nic_mark_resource_used(ndev, RES_KM_CATEGORY, 0);
+
+ /* FLM Flow Type 0 and 1 is reserved */
+ flow_nic_mark_resource_used(ndev, RES_FLM_FLOW_TYPE, 0);
+ flow_nic_mark_resource_used(ndev, RES_FLM_FLOW_TYPE, 1);
+ flow_nic_mark_resource_used(ndev, RES_FLM_RCP, 0);
+
+ /* CAT CFN 0 is reserved as a low priority catch all filter */
+ hw_mod_cat_cfn_set(&ndev->be, HW_CAT_CFN_SET_ALL_DEFAULTS,
+ 0, 0, 0);
+ hw_mod_cat_cfn_flush(&ndev->be, 0, 1);
+ flow_nic_mark_resource_used(ndev, RES_CAT_CFN, 0);
+
+ /* Initialize QSL with unmatched recipe index 0 - discard */
+ if (hw_mod_qsl_rcp_set(&ndev->be, HW_QSL_RCP_DISCARD, 0, 0x1) < 0)
+ goto err_exit0;
+ if (hw_mod_qsl_rcp_flush(&ndev->be, 0, 1) < 0)
+ goto err_exit0;
+
+ flow_nic_mark_resource_used(ndev, RES_QSL_RCP, 0);
+
+ /* Initialize QST with default index 0 */
+ if (hw_mod_qsl_qst_set(&ndev->be, HW_QSL_QST_PRESET_ALL, 0,
+ 0x0) < 0)
+ goto err_exit0;
+ if (hw_mod_qsl_qst_flush(&ndev->be, 0, 1) < 0)
+ goto err_exit0;
+
+ flow_nic_mark_resource_used(ndev, RES_QSL_QST, 0);
+
+ /* HST & TPE index 0 is reserved */
+ flow_nic_mark_resource_used(ndev, RES_HST_RCP, 0);
+ flow_nic_mark_resource_used(ndev, RES_TPE_RCP, 0);
+ flow_nic_mark_resource_used(ndev, RES_TPE_EXT, 0);
+ flow_nic_mark_resource_used(ndev, RES_TPE_RPL, 0);
+
+ /* PDB setup Direct Virtio Scatter-Gather descriptor of 12 bytes for its recipe 0 */
+ if (hw_mod_pdb_rcp_set(&ndev->be, HW_PDB_RCP_DESCRIPTOR, 0, 7) <
+ 0)
+ goto err_exit0;
+ if (hw_mod_pdb_rcp_set(&ndev->be, HW_PDB_RCP_DESC_LEN, 0, 6) <
+ 0)
+ goto err_exit0;
+
+ if (hw_mod_pdb_rcp_flush(&ndev->be, 0, 1) < 0)
+ goto err_exit0;
+
+ flow_nic_mark_resource_used(ndev, RES_PDB_RCP, 0);
+
+ /* Set default hasher recipe to 5-tuple */
+ flow_nic_set_hasher(ndev, 0, HASH_ALGO_5TUPLE);
+ hw_mod_hsh_rcp_flush(&ndev->be, 0, 1);
+
+ flow_nic_mark_resource_used(ndev, RES_HSH_RCP, 0);
+
+ /*
+ * COT - set color to 0 for unmatched - color encoding must not have CAO enabled for
+ * this entry
+ */
+ hw_mod_cat_cot_set(&ndev->be, HW_CAT_COT_PRESET_ALL, 0, 0);
+ if (hw_mod_cat_cot_flush(&ndev->be, 0, 1) < 0)
+ goto err_exit0;
+
+ flow_nic_mark_resource_used(ndev, RES_CAT_COT, 0);
+
+ /* Unblock MAC and MAC statistics on this NIC */
+ if (hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_STATT, 0) < 0)
+ goto err_exit0;
+ /* block keep alive - not needed */
+ if (hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_KEEPA, 1) < 0)
+ goto err_exit0;
+ /*
+ * Unblock all MAC ports
+ */
+ if (hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_MAC_PORT, 0) < 0)
+ goto err_exit0;
+
+ /*
+ * unblock RPP slices
+ */
+ hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_RPP_SLICE, 0);
+
+ if (hw_mod_rmc_ctrl_flush(&ndev->be) < 0)
+ goto err_exit0;
+
+ /* FLM */
+ if (flm_sdram_calibrate(ndev) < 0)
+ goto err_exit0;
+ if (flm_sdram_reset(ndev, 1) < 0)
+ goto err_exit0;
+ flm_flow_handle_create(&ndev->flm_res_handle);
+
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_LDS,
+ 0); /* Learn done status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_LFS,
+ 0); /* Learn fail status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_LIS,
+ 0); /* Learn ignore status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_UDS,
+ 0); /* Unlearn done status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_UIS,
+ 0); /* Unlearn ignore status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_RDS,
+ 0); /* Relearn done status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_RIS,
+ 0); /* Relearn ignore status */
+ hw_mod_flm_control_set(&ndev->be, HW_FLM_CONTROL_RBL, 4);
+ hw_mod_flm_control_flush(&ndev->be);
+
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT0,
+ 0); /* Drop at 100% FIFO fill level */
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT0, 1);
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT1,
+ 6); /* Drop at 37,5% FIFO fill level */
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT1, 1);
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT2,
+ 4); /* Drop at 25% FIFO fill level */
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT2, 1);
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_LIMIT3,
+ 2); /* Drop at 12,5% FIFO fill level */
+ hw_mod_flm_prio_set(&ndev->be, HW_FLM_PRIO_FT3, 1);
+ hw_mod_flm_prio_flush(&ndev->be);
+
+ for (uint32_t i = 0; i < ndev->be.flm.nb_pst_profiles; ++i) {
+ hw_mod_flm_pst_set(&ndev->be, HW_FLM_PST_BP, i,
+ FLM_PERIODIC_STATS_BYTE_LIMIT);
+ hw_mod_flm_pst_set(&ndev->be, HW_FLM_PST_PP, i,
+ FLM_PERIODIC_STATS_PKT_LIMIT);
+ hw_mod_flm_pst_set(&ndev->be, HW_FLM_PST_TP, i,
+ FLM_PERIODIC_STATS_BYTE_TIMEOUT);
+ }
+ hw_mod_flm_pst_flush(&ndev->be, 0, ALL_ENTRIES);
+
+ hw_mod_flm_stat_update(&ndev->be);
+
+ ndev->flm_mtr_handle =
+ calloc(1, sizeof(struct flm_flow_mtr_handle_s));
+ ndev->ft_res_handle =
+ calloc(FLM_FLOW_FT_MAX, sizeof(struct flm_flow_ft_ident_s));
+ ndev->mtr_stat_handle =
+ calloc(FLM_MTR_STAT_SIZE, sizeof(struct mtr_stat_s));
+
+ if (ndev->flm_mtr_handle == NULL ||
+ ndev->ft_res_handle == NULL ||
+ ndev->mtr_stat_handle == NULL)
+ goto err_exit0;
+
+ struct mtr_stat_s *mtr_stat = ndev->mtr_stat_handle;
+
+ for (uint32_t i = 0; i < FLM_MTR_STAT_SIZE; ++i) {
+ atomic_init(&mtr_stat[i].n_pkt, 0);
+ atomic_init(&mtr_stat[i].n_bytes, 0);
+ atomic_init(&mtr_stat[i].stats_mask, 0);
+ }
+
+ if (flow_group_handle_create(&ndev->group_handle,
+ FLM_FLOW_RCP_MAX))
+ goto err_exit0;
+
+ ndev->flow_mgnt_prepared = 1;
+ }
+ return 0;
+
+err_exit0:
+ done_flow_management_of_ndev_profile_inline(ndev);
+ return -1;
+}
+
+int done_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
+{
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ if (ndev->flow_mgnt_prepared) {
+ flm_sdram_reset(ndev, 0);
+ flm_flow_handle_remove(&ndev->flm_res_handle);
+
+ flow_nic_free_resource(ndev, RES_KM_FLOW_TYPE, 0);
+ flow_nic_free_resource(ndev, RES_KM_CATEGORY, 0);
+
+ hw_mod_flm_rcp_set(&ndev->be, HW_FLM_RCP_PRESET_ALL, 0, 0);
+ hw_mod_flm_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_FLM_FLOW_TYPE, 0);
+ flow_nic_free_resource(ndev, RES_FLM_FLOW_TYPE, 1);
+ flow_nic_free_resource(ndev, RES_FLM_RCP, 0);
+
+ free(ndev->flm_mtr_handle);
+ free(ndev->ft_res_handle);
+ free(ndev->mtr_stat_handle);
+ flow_group_handle_destroy(&ndev->group_handle);
+
+ hw_mod_cat_cfn_set(&ndev->be, HW_CAT_CFN_PRESET_ALL, 0, 0, 0);
+ hw_mod_cat_cfn_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_CAT_CFN, 0);
+
+ hw_mod_qsl_rcp_set(&ndev->be, HW_QSL_RCP_PRESET_ALL, 0, 0);
+ hw_mod_qsl_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_QSL_RCP, 0);
+
+ hw_mod_hst_rcp_set(&ndev->be, HW_HST_RCP_PRESET_ALL, 0, 0);
+ hw_mod_hst_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_HST_RCP, 0);
+
+ hw_mod_tpe_reset(&ndev->be);
+ flow_nic_free_resource(ndev, RES_TPE_RCP, 0);
+ flow_nic_free_resource(ndev, RES_TPE_EXT, 0);
+ flow_nic_free_resource(ndev, RES_TPE_RPL, 0);
+
+ hw_mod_pdb_rcp_set(&ndev->be, HW_PDB_RCP_PRESET_ALL, 0, 0);
+ hw_mod_pdb_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_PDB_RCP, 0);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, 0, 0, 0);
+ hw_mod_hsh_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_HSH_RCP, 0);
+
+ hw_mod_cat_cot_set(&ndev->be, HW_CAT_COT_PRESET_ALL, 0, 0);
+ hw_mod_cat_cot_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_CAT_COT, 0);
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ ndev->flow_mgnt_prepared = 0;
+ }
+
+ return 0;
+}
+
+int flow_validate_profile_inline(struct flow_eth_dev *dev,
+ const struct flow_elem elem[],
+ const struct flow_action action[],
+ struct flow_error *error)
+{
+ uint32_t port_id = 0;
+ uint32_t num_dest_port = 0;
+ uint32_t num_queues = 0;
+
+ uint32_t packet_data[10];
+ uint32_t packet_mask[10];
+ struct flm_flow_key_def_s key_def;
+
+ flow_nic_set_error(ERR_SUCCESS, error);
+
+ pthread_mutex_lock(&dev->ndev->mtx);
+ struct nic_flow_def *fd = interpret_flow_elements(dev, elem, action,
+ error, 0, &port_id,
+ &num_dest_port, &num_queues,
+ packet_data, packet_mask,
+ &key_def);
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ if (!fd)
+ return -1;
+
+ free(fd);
+ return 0;
+}
+
+struct flow_handle *flow_create_profile_inline(struct flow_eth_dev *dev,
+ const struct flow_attr *attr, const struct flow_elem elem[],
+ const struct flow_action action[], struct flow_error *error)
+{
+ struct flow_handle *fh = NULL;
+
+ uint32_t port_id = UINT32_MAX;
+ uint32_t num_dest_port;
+ uint32_t num_queues;
+
+ uint32_t packet_data[10];
+ uint32_t packet_mask[10];
+ struct flm_flow_key_def_s key_def;
+
+ struct flow_attr attr_local;
+
+ memcpy(&attr_local, attr, sizeof(struct flow_attr));
+ if (attr_local.group > 0)
+ attr_local.forced_vlan_vid = 0;
+
+ flow_nic_set_error(ERR_SUCCESS, error);
+
+ pthread_mutex_lock(&dev->ndev->mtx);
+
+ struct nic_flow_def *fd = interpret_flow_elements(dev, elem, action, error,
+ attr_local.forced_vlan_vid,
+ &port_id, &num_dest_port,
+ &num_queues, packet_data,
+ packet_mask, &key_def);
+ if (!fd)
+ goto err_exit;
+
+ /* Translate group IDs */
+ if (fd->jump_to_group != UINT32_MAX &&
+ flow_group_translate_get(dev->ndev->group_handle,
+ attr_local.caller_id, fd->jump_to_group,
+ &fd->jump_to_group)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not get group resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ goto err_exit;
+ }
+ if (attr_local.group > 0 &&
+ flow_group_translate_get(dev->ndev->group_handle,
+ attr_local.caller_id, attr_local.group,
+ &attr_local.group)) {
+ NT_LOG(ERR, FILTER, "ERROR: Could not get group resource\n");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ goto err_exit;
+ }
+
+ if (port_id == UINT32_MAX)
+ port_id = dev->port_id;
+
+ /* Create and flush filter to NIC */
+ fh = create_flow_filter(dev, fd, &attr_local, error, port_id,
+ num_dest_port, num_queues, packet_data,
+ packet_mask, &key_def);
+ if (!fh)
+ goto err_exit;
+
+ NT_LOG(DBG, FILTER,
+ "New FlOW: fh (flow handle) %p, fd (flow definition) %p\n", fh,
+ fd);
+ NT_LOG(DBG, FILTER,
+ ">>>>> [Dev %p] Nic %i, Port %i: fh %p fd %p - implementation <<<<<\n",
+ dev, dev->ndev->adapter_no, dev->port, fh, fd);
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ return fh;
+
+err_exit:
+ if (fh)
+ flow_destroy_locked_profile_inline(dev, fh, NULL);
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ NT_LOG(ERR, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+}
+
+int flow_destroy_locked_profile_inline(struct flow_eth_dev *dev,
+ struct flow_handle *fh,
+ struct flow_error *error)
+{
+ assert(dev);
+ assert(fh);
+
+ int err = 0;
+
+ flow_nic_set_error(ERR_SUCCESS, error);
+
+ /* take flow out of ndev list - may not have been put there yet */
+ if (fh->type == FLOW_HANDLE_TYPE_FLM)
+ nic_remove_flow_flm(dev->ndev, fh);
+
+ else
+ nic_remove_flow(dev->ndev, fh);
+
+#ifdef FLOW_DEBUG
+ dev->ndev->be.iface->set_debug_mode(dev->ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ if (fh->type == FLOW_HANDLE_TYPE_FLM) {
+ err |= flm_flow_programming(dev, fh, NULL, 0, 0);
+
+ if (fh->flm_rpl_ext_ptr > 0 &&
+ flow_nic_deref_resource(dev->ndev, RES_TPE_EXT,
+ (int)fh->flm_rpl_ext_ptr) == 0) {
+ uint32_t ptr = 0;
+ uint32_t len = 0;
+
+ hw_mod_tpe_rpl_ext_get(&dev->ndev->be,
+ HW_TPE_RPL_EXT_RPL_PTR,
+ (int)fh->flm_rpl_ext_ptr, &ptr);
+ hw_mod_tpe_rpl_ext_get(&dev->ndev->be,
+ HW_TPE_RPL_EXT_META_RPL_LEN,
+ (int)fh->flm_rpl_ext_ptr, &len);
+
+ hw_mod_tpe_rpl_ext_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ (int)fh->flm_rpl_ext_ptr, 0);
+ hw_mod_tpe_rpl_ext_flush(&dev->ndev->be,
+ (int)fh->flm_rpl_ext_ptr, 1);
+
+ for (uint32_t ii = 0; ii < (len + 15) / 16; ii++) {
+ if (flow_nic_deref_resource(dev->ndev,
+ RES_TPE_RPL,
+ (int)(ptr + ii)) == 0) {
+ uint32_t rpl_zero[] = { 0, 0, 0, 0 };
+
+ hw_mod_tpe_rpl_rpl_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ (int)(ptr + ii),
+ rpl_zero);
+ hw_mod_tpe_rpl_rpl_flush(&dev->ndev->be,
+ (int)(ptr + ii),
+ 1);
+ }
+ }
+ }
+
+ flow_group_translate_release(dev->ndev->group_handle,
+ fh->flm_owner->flm_group_index);
+
+ fh->flm_owner->flm_ref_count -= 1;
+ if (fh->flm_owner->flm_ref_count == 0) {
+ err |= flow_flm_destroy_owner(dev, fh->flm_owner);
+ err |= flow_destroy_locked_profile_inline(dev,
+ fh->flm_owner,
+ error);
+ }
+ } else {
+ NT_LOG(DBG, FILTER, "removing flow :%p\n", fh);
+
+ if (fh->fd) {
+ if (fh->fd->km.num_ftype_elem)
+ km_clear_data_match_entry(&fh->fd->km);
+
+ if (fh->fd->jump_to_group != UINT32_MAX) {
+ err |= flm_flow_destroy_group(dev,
+ fh->fd->jump_to_group);
+ flow_group_translate_release(dev->ndev->group_handle,
+ fh->fd->jump_to_group);
+ }
+ }
+
+ for (int res_type = 0; res_type < RES_COUNT; res_type++) {
+ if (fh->resource[res_type].count < 1)
+ continue;
+
+ for (int ii = 0; ii < fh->resource[res_type].count;
+ ii++) {
+ /* If last ref count of this resource, free it */
+ if (flow_nic_deref_resource(dev->ndev,
+ res_type,
+ fh->resource[res_type].index +
+ ii) == 0) {
+ /* Free resource up in NIC */
+ switch (res_type) {
+ case RES_CAT_CFN:
+ assert(ii == 0);
+ err |= reset_cat_function_setup(dev,
+ fh->resource[RES_CAT_CFN]
+ .index + ii);
+ break;
+
+ case RES_QSL_QST:
+ hw_mod_qsl_qst_set(&dev->ndev->be,
+ HW_QSL_QST_PRESET_ALL,
+ fh->resource[RES_QSL_QST]
+ .index + ii,
+ 0);
+ hw_mod_qsl_qst_flush(&dev->ndev->be,
+ fh->resource[RES_QSL_QST]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_QSL_RCP:
+ hw_mod_qsl_rcp_set(&dev->ndev->be,
+ HW_QSL_RCP_PRESET_ALL,
+ fh->resource[RES_QSL_RCP]
+ .index + ii,
+ 0);
+ hw_mod_qsl_rcp_flush(&dev->ndev->be,
+ fh->resource[RES_QSL_RCP]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_CAT_COT:
+ hw_mod_cat_cot_set(&dev->ndev->be,
+ HW_CAT_COT_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_cat_cot_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_KM_CATEGORY:
+ assert(ii == 0);
+ hw_mod_km_rcp_set(&dev->ndev->be,
+ HW_KM_RCP_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0, 0);
+ hw_mod_km_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_KM_FLOW_TYPE: {
+ struct flm_flow_ft_ident_s *ft_idents =
+ (struct flm_flow_ft_ident_s
+ *)dev->ndev
+ ->ft_res_handle;
+ ft_idents[fh->resource[res_type]
+ .index +
+ ii]
+ .data = 0;
+ }
+ break;
+
+ case RES_FLM_RCP:
+ assert(ii == 0);
+ err |= flm_flow_destroy_rcp(dev,
+ fh->resource[res_type]
+ .index + ii);
+ break;
+
+ case RES_FLM_FLOW_TYPE:
+ /* Nothing needed */
+ break;
+
+ case RES_HSH_RCP:
+ hw_mod_hsh_rcp_set(&dev->ndev->be,
+ HW_HSH_RCP_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0, 0);
+ hw_mod_hsh_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index +
+ ii,
+ 1);
+ break;
+
+ case RES_PDB_RCP:
+ hw_mod_pdb_rcp_set(&dev->ndev->be,
+ HW_PDB_RCP_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_pdb_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_HST_RCP:
+ hw_mod_hst_rcp_set(&dev->ndev->be,
+ HW_HST_RCP_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_hst_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_TPE_RCP:
+ hw_mod_tpe_rpp_rcp_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_rpp_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ hw_mod_tpe_ins_rcp_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_ins_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ hw_mod_tpe_rpl_rcp_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_rpl_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ hw_mod_tpe_rpl_ext_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_rpl_ext_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ hw_mod_tpe_cpy_rcp_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_cpy_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ hw_mod_tpe_hfu_rcp_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_hfu_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ hw_mod_tpe_csu_rcp_set(&dev->ndev->be,
+ HW_TPE_PRESET_ALL,
+ fh->resource[res_type]
+ .index + ii,
+ 0);
+ hw_mod_tpe_csu_rcp_flush(&dev->ndev->be,
+ fh->resource[res_type]
+ .index + ii,
+ 1);
+ break;
+
+ case RES_TPE_EXT:
+ /* Nothing needed */
+ break;
+
+ case RES_TPE_RPL:
+ /* Nothing needed */
+ break;
+
+ default:
+ err |= -1;
+ break;
+ }
+ }
+ }
+ }
+ free(fh->fd);
+ }
+
+ if (err) {
+ NT_LOG(ERR, FILTER, "FAILED removing flow: %p\n", fh);
+ flow_nic_set_error(ERR_REMOVE_FLOW_FAILED, error);
+ }
+
+ free(fh);
+
+#ifdef FLOW_DEBUG
+ dev->ndev->be.iface->set_debug_mode(dev->ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ return err;
+}
+
+int flow_destroy_profile_inline(struct flow_eth_dev *dev,
+ struct flow_handle *flow,
+ struct flow_error *error)
+{
+ int err = 0;
+
+ flow_nic_set_error(ERR_SUCCESS, error);
+
+ pthread_mutex_lock(&dev->ndev->mtx);
+ if (flow) {
+ /* Delete this flow */
+ err = flow_destroy_locked_profile_inline(dev, flow, error);
+ } else {
+ /* Delete all created flows from this eth device */
+ flow = dev->ndev->flow_base;
+
+ while (flow && !err) {
+ if (flow->dev == dev) {
+ struct flow_handle *flow_next = flow->next;
+
+ err = flow_destroy_locked_profile_inline(dev,
+ flow,
+ NULL);
+ flow = flow_next;
+ } else {
+ flow = flow->next;
+ }
+ }
+
+ /* Delete all created FLM flows from this eth device */
+ flow = dev->ndev->flow_base_flm;
+
+ while (flow && !err) {
+ if (flow->dev == dev) {
+ struct flow_handle *flow_next = flow->next;
+
+ err = flow_destroy_locked_profile_inline(dev,
+ flow,
+ NULL);
+ flow = flow_next;
+ } else {
+ flow = flow->next;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&dev->ndev->mtx);
+
+ return err;
+}
+
+int flow_flush_profile_inline(UNUSED struct flow_eth_dev *dev,
+ struct flow_error *error)
+{
+ NT_LOG(ERR, FILTER, "ERROR: Not implemented yet\n");
+ error->type = FLOW_ERROR_GENERAL;
+ error->message = "rte_flow_flush is not supported";
+ return -1;
+}
+
+int flow_query_profile_inline(UNUSED struct flow_eth_dev *dev,
+ UNUSED struct flow_handle *flow,
+ UNUSED const struct flow_action *action,
+ void **data, uint32_t *length,
+ struct flow_error *error)
+{
+ NT_LOG(ERR, FILTER, "ERROR: Not implemented yet\n");
+
+ *length = 0;
+ *data = NULL;
+ error->type = FLOW_ERROR_GENERAL;
+ error->message = "rte_flow_query is not supported";
+ return -1;
+}
+
+int flow_get_flm_stats_profile_inline(struct flow_nic_dev *ndev, uint64_t *data,
+ uint64_t size)
+{
+ const enum hw_flm_e fields[] = {
+ HW_FLM_STAT_FLOWS, HW_FLM_STAT_LRN_DONE,
+ HW_FLM_STAT_LRN_IGNORE, HW_FLM_STAT_LRN_FAIL,
+ HW_FLM_STAT_UNL_DONE, HW_FLM_STAT_UNL_IGNORE,
+ HW_FLM_STAT_AUL_DONE, HW_FLM_STAT_AUL_IGNORE,
+ HW_FLM_STAT_AUL_FAIL, HW_FLM_STAT_TUL_DONE,
+ HW_FLM_STAT_REL_DONE, HW_FLM_STAT_REL_IGNORE,
+ HW_FLM_STAT_PRB_DONE, HW_FLM_STAT_PRB_IGNORE,
+
+ HW_FLM_STAT_STA_DONE, HW_FLM_STAT_INF_DONE,
+ HW_FLM_STAT_INF_SKIP, HW_FLM_STAT_PCK_HIT,
+ HW_FLM_STAT_PCK_MISS, HW_FLM_STAT_PCK_UNH,
+ HW_FLM_STAT_PCK_DIS, HW_FLM_STAT_CSH_HIT,
+ HW_FLM_STAT_CSH_MISS, HW_FLM_STAT_CSH_UNH,
+ HW_FLM_STAT_CUC_START, HW_FLM_STAT_CUC_MOVE,
+ };
+
+ const uint64_t fields_cnt = sizeof(fields) / sizeof(enum hw_flm_e);
+
+ if (size < fields_cnt)
+ return -1;
+
+ hw_mod_flm_stat_update(&ndev->be);
+
+ for (uint64_t i = 0; i < fields_cnt; ++i) {
+ uint32_t value = 0;
+
+ hw_mod_flm_stat_get(&ndev->be, fields[i], &value);
+ data[i] = (fields[i] == HW_FLM_STAT_FLOWS) ? value :
+ data[i] + value;
+ if (ndev->be.flm.ver < 18 &&
+ fields[i] == HW_FLM_STAT_PRB_IGNORE)
+ break;
+ }
+
+ return 0;
+}
+
+int flow_set_mtu_inline(struct flow_eth_dev *dev, uint32_t port, uint16_t mtu)
+{
+ if (port >= 255)
+ return -1;
+
+ int err = 0;
+ uint8_t ifr_mtu_recipe = convert_port_to_ifr_mtu_recipe(port);
+ struct flow_nic_dev *ndev = dev->ndev;
+
+ err |= hw_mod_tpe_rpp_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_EN,
+ ifr_mtu_recipe, 1);
+ err |= hw_mod_tpe_rpp_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_MTU,
+ ifr_mtu_recipe, mtu);
+ err |= hw_mod_tpe_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_EN,
+ ifr_mtu_recipe, 1);
+ err |= hw_mod_tpe_ifr_rcp_set(&ndev->be, HW_TPE_IFR_RCP_MTU,
+ ifr_mtu_recipe, mtu);
+
+ if (err == 0) {
+ err |= hw_mod_tpe_rpp_ifr_rcp_flush(&ndev->be, ifr_mtu_recipe,
+ 1);
+ err |= hw_mod_tpe_ifr_rcp_flush(&ndev->be, ifr_mtu_recipe, 1);
+ }
+
+ return err;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h
new file mode 100644
index 0000000000..330cc39db6
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_API_PROFILE_INLINE_H_
+#define _FLOW_API_PROFILE_INLINE_H_
+
+#include "stream_binary_flow_api.h"
+#include "flow_api.h"
+
+/*
+ * Management
+ */
+
+int done_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev);
+
+int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev);
+
+/*
+ * Flow functionality
+ */
+
+int flow_destroy_locked_profile_inline(struct flow_eth_dev *dev,
+ struct flow_handle *flow,
+ struct flow_error *error);
+
+int flow_validate_profile_inline(struct flow_eth_dev *dev,
+ const struct flow_elem elem[],
+ const struct flow_action action[],
+ struct flow_error *error);
+
+struct flow_handle *flow_create_profile_inline(struct flow_eth_dev *dev,
+ const struct flow_attr *attr,
+ const struct flow_elem elem[], const struct flow_action action[],
+ struct flow_error *error);
+
+int flow_destroy_profile_inline(struct flow_eth_dev *dev,
+ struct flow_handle *flow,
+ struct flow_error *error);
+
+int flow_flush_profile_inline(struct flow_eth_dev *dev,
+ struct flow_error *error);
+
+int flow_query_profile_inline(struct flow_eth_dev *dev,
+ struct flow_handle *flow,
+ const struct flow_action *action, void **data,
+ uint32_t *length, struct flow_error *error);
+
+/*
+ * Stats
+ */
+
+int flow_get_flm_stats_profile_inline(struct flow_nic_dev *ndev, uint64_t *data,
+ uint64_t size);
+
+#endif /* _FLOW_API_PROFILE_INLINE_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_backend.c b/drivers/net/ntnic/nthw/flow_filter/flow_backend.c
new file mode 100644
index 0000000000..1214b32666
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_backend.c
@@ -0,0 +1,3205 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_drv.h"
+
+#include "flow_nthw_info.h"
+#include "flow_nthw_ifr.h"
+#include "flow_nthw_cat.h"
+#include "flow_nthw_csu.h"
+#include "flow_nthw_km.h"
+#include "flow_nthw_flm.h"
+#include "flow_nthw_hfu.h"
+#include "flow_nthw_hsh.h"
+#include "flow_nthw_hst.h"
+#include "flow_nthw_qsl.h"
+#include "flow_nthw_slc.h"
+#include "flow_nthw_slc_lr.h"
+#include "flow_nthw_pdb.h"
+#include "flow_nthw_ioa.h"
+#include "flow_nthw_rpp_lr.h"
+#include "flow_nthw_roa.h"
+#include "flow_nthw_rmc.h"
+#include "flow_nthw_tx_cpy.h"
+#include "flow_nthw_tx_ins.h"
+#include "flow_nthw_tx_rpl.h"
+#include "flow_backend.h"
+#include "flow_api_backend.h"
+
+#include <stdio.h> /* printf */
+
+#if !defined(MAX_PHYS_ADAPTERS)
+#define MAX_PHYS_ADAPTERS (8)
+#endif
+
+/*
+ * Binary Flow API backend implementation into ntservice driver
+ *
+ * General note on this backend implementation:
+ * Maybe use shadow class to combine multiple writes. However, this backend is only for dev/testing
+ */
+
+static struct backend_dev_s {
+ uint8_t adapter_no;
+ enum debug_mode_e dmode;
+ struct info_nthw *p_info_nthw;
+ struct cat_nthw *p_cat_nthw;
+ struct km_nthw *p_km_nthw;
+ struct flm_nthw *p_flm_nthw;
+ struct hsh_nthw *p_hsh_nthw;
+ struct hst_nthw *p_hst_nthw;
+ struct qsl_nthw *p_qsl_nthw;
+ struct slc_nthw *p_slc_nthw;
+ struct slc_lr_nthw *p_slc_lr_nthw;
+ struct pdb_nthw *p_pdb_nthw;
+ struct ioa_nthw *p_ioa_nthw;
+ struct roa_nthw *p_roa_nthw;
+ struct rmc_nthw *p_rmc_nthw;
+ struct hfu_nthw *p_hfu_nthw; /* TPE module */
+ struct rpp_lr_nthw *p_rpp_lr_nthw; /* TPE module */
+ struct tx_cpy_nthw *p_tx_cpy_nthw; /* TPE module */
+ struct tx_ins_nthw *p_tx_ins_nthw; /* TPE module */
+ struct tx_rpl_nthw *p_tx_rpl_nthw; /* TPE module */
+ struct csu_nthw *p_csu_nthw; /* TPE module */
+ struct ifr_nthw *p_ifr_nthw; /* TPE module */
+} be_devs[MAX_PHYS_ADAPTERS];
+
+#define _CHECK_DEBUG_ON(be, mod, inst) \
+ int __debug__ = 0; \
+ if (((be)->dmode & FLOW_BACKEND_DEBUG_MODE_WRITE) || (mod)->debug) \
+ do { \
+ mod##_nthw_set_debug_mode(inst, 0xFF); \
+ __debug__ = 1; \
+ } while (0)
+
+#define _CHECK_DEBUG_OFF(mod, inst) \
+ do { \
+ if (__debug__) \
+ mod##_nthw_set_debug_mode(inst, 0); \
+ } while (0)
+
+static int set_debug_mode(void *be_dev, enum debug_mode_e mode)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ be->dmode = mode;
+ return 0;
+}
+
+/*
+ * ***************** INFO *******************
+ */
+
+static int get_nb_phy_ports(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_phy_ports(be->p_info_nthw);
+}
+
+static int get_nb_rx_ports(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_rx_ports(be->p_info_nthw);
+}
+
+static int get_ltx_avail(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_ltx_avail(be->p_info_nthw);
+}
+
+static int get_nb_cat_funcs(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_cat_funcs(be->p_info_nthw);
+}
+
+static int get_nb_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_categories(be->p_info_nthw);
+}
+
+static int get_nb_cat_km_if_cnt(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_cat_km_if_cnt(be->p_info_nthw);
+}
+
+static int get_nb_cat_km_if_m0(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_cat_km_if_m0(be->p_info_nthw);
+}
+
+static int get_nb_cat_km_if_m1(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_cat_km_if_m1(be->p_info_nthw);
+}
+
+static int get_nb_queues(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_queues(be->p_info_nthw);
+}
+
+static int get_nb_km_flow_types(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_flow_types(be->p_info_nthw);
+}
+
+static int get_nb_pm_ext(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_pm_ext(be->p_info_nthw);
+}
+
+static int get_nb_len(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_len(be->p_info_nthw);
+}
+
+static int get_kcc_size(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_kcc_size(be->p_info_nthw);
+}
+
+static int get_kcc_banks(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_kcc_banks(be->p_info_nthw);
+}
+
+static int get_nb_km_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_categories(be->p_info_nthw);
+}
+
+static int get_nb_km_cam_banks(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_cam_banks(be->p_info_nthw);
+}
+
+static int get_nb_km_cam_record_words(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_cam_record_words(be->p_info_nthw);
+}
+
+static int get_nb_km_cam_records(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_cam_records(be->p_info_nthw);
+}
+
+static int get_nb_km_tcam_banks(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_tcam_banks(be->p_info_nthw);
+}
+
+static int get_nb_km_tcam_bank_width(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_km_tcam_bank_width(be->p_info_nthw);
+}
+
+static int get_nb_flm_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_flm_categories(be->p_info_nthw);
+}
+
+static int get_nb_flm_size_mb(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_flm_size_mb(be->p_info_nthw);
+}
+
+static int get_nb_flm_entry_size(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_flm_entry_size(be->p_info_nthw);
+}
+
+static int get_nb_flm_variant(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_flm_variant(be->p_info_nthw);
+}
+
+static int get_nb_flm_prios(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_flm_prios(be->p_info_nthw);
+}
+
+static int get_nb_flm_pst_profiles(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_flm_pst_profiles(be->p_info_nthw);
+}
+
+static int get_nb_hst_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_hst_categories(be->p_info_nthw);
+}
+
+static int get_nb_qsl_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_qsl_categories(be->p_info_nthw);
+}
+
+static int get_nb_qsl_qst_entries(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_qsl_qst_entries(be->p_info_nthw);
+}
+
+static int get_nb_pdb_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_pdb_categories(be->p_info_nthw);
+}
+
+static int get_nb_ioa_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_ioa_categories(be->p_info_nthw);
+}
+
+static int get_nb_roa_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_roa_categories(be->p_info_nthw);
+}
+
+static int get_nb_tpe_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_tpe_categories(be->p_info_nthw);
+}
+
+static int get_nb_tx_cpy_writers(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_tx_cpy_writers(be->p_info_nthw);
+}
+
+static int get_nb_tx_cpy_mask_mem(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_tx_cpy_mask_mem(be->p_info_nthw);
+}
+
+static int get_nb_tx_rpl_depth(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_tx_rpl_depth(be->p_info_nthw);
+}
+
+static int get_nb_tx_rpl_ext_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_tx_rpl_ext_categories(be->p_info_nthw);
+}
+
+static int get_nb_tpe_ifr_categories(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return info_nthw_get_nb_tpe_ifr_categories(be->p_info_nthw);
+}
+
+/*
+ * ***************** CAT *******************
+ */
+
+static bool cat_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_cat_nthw != NULL;
+}
+
+static uint32_t cat_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_cat_nthw->m_cat) << 16) |
+ (module_get_minor_version(be->p_cat_nthw->m_cat) &
+ 0xffff));
+}
+
+static int cat_cfn_flush(void *be_dev, const struct cat_func_s *cat,
+ int cat_func, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18) {
+ r(be->p_cat_nthw, 1U);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cfn_select(be->p_cat_nthw, cat_func);
+ cat_nthw_cfn_enable(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].enable);
+ cat_nthw_cfn_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].inv);
+ cat_nthw_cfn_ptc_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_inv);
+ cat_nthw_cfn_ptc_isl(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_isl);
+ cat_nthw_cfn_ptc_cfp(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_cfp);
+ cat_nthw_cfn_ptc_mac(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_mac);
+ cat_nthw_cfn_ptc_l2(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_l2);
+ cat_nthw_cfn_ptc_vn_tag(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_vntag);
+ cat_nthw_cfn_ptc_vlan(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_vlan);
+ cat_nthw_cfn_ptc_mpls(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_mpls);
+ cat_nthw_cfn_ptc_l3(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_l3);
+ cat_nthw_cfn_ptc_frag(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_frag);
+ cat_nthw_cfn_ptc_ip_prot(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_ip_prot);
+ cat_nthw_cfn_ptc_l4(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_l4);
+ cat_nthw_cfn_ptc_tunnel(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tunnel);
+ cat_nthw_cfn_ptc_tnl_l2(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_l2);
+ cat_nthw_cfn_ptc_tnl_vlan(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_vlan);
+ cat_nthw_cfn_ptc_tnl_mpls(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_mpls);
+ cat_nthw_cfn_ptc_tnl_l3(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_l3);
+ cat_nthw_cfn_ptc_tnl_frag(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_frag);
+ cat_nthw_cfn_ptc_tnl_ip_prot(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_ip_prot);
+ cat_nthw_cfn_ptc_tnl_l4(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].ptc_tnl_l4);
+
+ cat_nthw_cfn_err_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].err_inv);
+ cat_nthw_cfn_err_cv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].err_cv);
+ cat_nthw_cfn_err_fcs(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].err_fcs);
+ cat_nthw_cfn_err_trunc(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].err_trunc);
+ cat_nthw_cfn_err_l3_cs(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].err_l3_cs);
+ cat_nthw_cfn_err_l4_cs(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].err_l4_cs);
+
+ cat_nthw_cfn_mac_port(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].mac_port);
+
+ cat_nthw_cfn_pm_cmp(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_cmp);
+ cat_nthw_cfn_pm_dct(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_dct);
+ cat_nthw_cfn_pm_ext_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_ext_inv);
+ cat_nthw_cfn_pm_cmb(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_cmb);
+ cat_nthw_cfn_pm_and_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_and_inv);
+ cat_nthw_cfn_pm_or_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_or_inv);
+ cat_nthw_cfn_pm_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].pm_inv);
+
+ cat_nthw_cfn_lc(be->p_cat_nthw, cat->v18.cfn[cat_func].lc);
+ cat_nthw_cfn_lc_inv(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].lc_inv);
+ cat_nthw_cfn_km0_or(be->p_cat_nthw,
+ cat->v18.cfn[cat_func].km_or);
+ cat_nthw_cfn_flush(be->p_cat_nthw);
+ cat_func++;
+ }
+ } else if (cat->ver == 21 || cat->ver == 22) {
+ r(be->p_cat_nthw, 1U);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cfn_select(be->p_cat_nthw, cat_func);
+ cat_nthw_cfn_enable(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].enable);
+ cat_nthw_cfn_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].inv);
+ cat_nthw_cfn_ptc_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_inv);
+ cat_nthw_cfn_ptc_isl(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_isl);
+ cat_nthw_cfn_ptc_cfp(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_cfp);
+ cat_nthw_cfn_ptc_mac(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_mac);
+ cat_nthw_cfn_ptc_l2(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_l2);
+ cat_nthw_cfn_ptc_vn_tag(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_vntag);
+ cat_nthw_cfn_ptc_vlan(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_vlan);
+ cat_nthw_cfn_ptc_mpls(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_mpls);
+ cat_nthw_cfn_ptc_l3(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_l3);
+ cat_nthw_cfn_ptc_frag(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_frag);
+ cat_nthw_cfn_ptc_ip_prot(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_ip_prot);
+ cat_nthw_cfn_ptc_l4(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_l4);
+ cat_nthw_cfn_ptc_tunnel(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tunnel);
+ cat_nthw_cfn_ptc_tnl_l2(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_l2);
+ cat_nthw_cfn_ptc_tnl_vlan(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_vlan);
+ cat_nthw_cfn_ptc_tnl_mpls(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_mpls);
+ cat_nthw_cfn_ptc_tnl_l3(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_l3);
+ cat_nthw_cfn_ptc_tnl_frag(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_frag);
+ cat_nthw_cfn_ptc_tnl_ip_prot(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_ip_prot);
+ cat_nthw_cfn_ptc_tnl_l4(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].ptc_tnl_l4);
+
+ cat_nthw_cfn_err_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_inv);
+ cat_nthw_cfn_err_cv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_cv);
+ cat_nthw_cfn_err_fcs(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_fcs);
+ cat_nthw_cfn_err_trunc(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_trunc);
+ cat_nthw_cfn_err_l3_cs(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_l3_cs);
+ cat_nthw_cfn_err_l4_cs(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_l4_cs);
+ cat_nthw_cfn_err_tnl_l3_cs(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_tnl_l3_cs);
+ cat_nthw_cfn_err_tnl_l4_cs(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_tnl_l4_cs);
+ cat_nthw_cfn_err_ttl_exp(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_ttl_exp);
+ cat_nthw_cfn_err_tnl_ttl_exp(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].err_tnl_ttl_exp);
+
+ cat_nthw_cfn_mac_port(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].mac_port);
+
+ cat_nthw_cfn_pm_cmp(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_cmp);
+ cat_nthw_cfn_pm_dct(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_dct);
+ cat_nthw_cfn_pm_ext_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_ext_inv);
+ cat_nthw_cfn_pm_cmb(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_cmb);
+ cat_nthw_cfn_pm_and_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_and_inv);
+ cat_nthw_cfn_pm_or_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_or_inv);
+ cat_nthw_cfn_pm_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].pm_inv);
+
+ cat_nthw_cfn_lc(be->p_cat_nthw, cat->v21.cfn[cat_func].lc);
+ cat_nthw_cfn_lc_inv(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].lc_inv);
+ cat_nthw_cfn_km0_or(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].km0_or);
+ if (be->p_cat_nthw->m_km_if_cnt > 1) {
+ cat_nthw_cfn_km1_or(be->p_cat_nthw,
+ cat->v21.cfn[cat_func].km1_or);
+ }
+ cat_nthw_cfn_flush(be->p_cat_nthw);
+ cat_func++;
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_kce_flush(void *be_dev, const struct cat_func_s *cat,
+ int km_if_idx, int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18) {
+ cat_nthw_kce_cnt(be->p_cat_nthw, 0, 1U);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_kce_select(be->p_cat_nthw, 0, index + i);
+ cat_nthw_kce_enable(be->p_cat_nthw, 0,
+ cat->v18.kce[index + i].enable_bm);
+ cat_nthw_kce_flush(be->p_cat_nthw, 0);
+ }
+ } else if (cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_kce_cnt(be->p_cat_nthw, km_if_idx, 1U);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_kce_select(be->p_cat_nthw, km_if_idx, index + i);
+ cat_nthw_kce_enable(be->p_cat_nthw, km_if_idx,
+ cat->v21.kce[index + i].enable_bm[km_if_idx]);
+ cat_nthw_kce_flush(be->p_cat_nthw, km_if_idx);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_kcs_flush(void *be_dev, const struct cat_func_s *cat,
+ int km_if_idx, int cat_func, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18) {
+ cat_nthw_kcs_cnt(be->p_cat_nthw, 0, 1U);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_kcs_select(be->p_cat_nthw, 0, cat_func);
+ cat_nthw_kcs_category(be->p_cat_nthw, 0,
+ cat->v18.kcs[cat_func].category);
+ cat_nthw_kcs_flush(be->p_cat_nthw, 0);
+ cat_func++;
+ }
+ } else if (cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_kcs_cnt(be->p_cat_nthw, km_if_idx, 1U);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_kcs_select(be->p_cat_nthw, km_if_idx, cat_func);
+ cat_nthw_kcs_category(be->p_cat_nthw, km_if_idx,
+ cat->v21.kcs[cat_func].category[km_if_idx]);
+ cat_nthw_kcs_flush(be->p_cat_nthw, km_if_idx);
+ cat_func++;
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_fte_flush(void *be_dev, const struct cat_func_s *cat,
+ int km_if_idx, int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18) {
+ cat_nthw_fte_cnt(be->p_cat_nthw, 0, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_fte_select(be->p_cat_nthw, 0, index + i);
+ cat_nthw_fte_enable(be->p_cat_nthw, 0,
+ cat->v18.fte[index + i].enable_bm);
+ cat_nthw_fte_flush(be->p_cat_nthw, 0);
+ }
+ } else if (cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_fte_cnt(be->p_cat_nthw, km_if_idx, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_fte_select(be->p_cat_nthw, km_if_idx, index + i);
+ cat_nthw_fte_enable(be->p_cat_nthw, km_if_idx,
+ cat->v21.fte[index + i].enable_bm[km_if_idx]);
+ cat_nthw_fte_flush(be->p_cat_nthw, km_if_idx);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_cte_flush(void *be_dev, const struct cat_func_s *cat,
+ int cat_func, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21) {
+ cat_nthw_cte_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cte_select(be->p_cat_nthw, cat_func);
+ cat_nthw_cte_enable_col(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.col);
+ cat_nthw_cte_enable_cor(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.cor);
+ cat_nthw_cte_enable_hsh(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.hsh);
+ cat_nthw_cte_enable_qsl(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.qsl);
+ cat_nthw_cte_enable_ipf(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.ipf);
+ cat_nthw_cte_enable_slc(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.slc);
+ cat_nthw_cte_enable_pdb(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.pdb);
+ cat_nthw_cte_enable_msk(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.msk);
+ cat_nthw_cte_enable_hst(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.hst);
+ cat_nthw_cte_enable_epp(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.epp);
+ cat_nthw_cte_enable_tpe(be->p_cat_nthw,
+ cat->v18.cte[cat_func].b.tpe);
+
+ cat_nthw_cte_flush(be->p_cat_nthw);
+ cat_func++;
+ }
+ } else if (cat->ver == 22) {
+ cat_nthw_cte_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cte_select(be->p_cat_nthw, cat_func);
+ cat_nthw_cte_enable_col(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.col);
+ cat_nthw_cte_enable_cor(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.cor);
+ cat_nthw_cte_enable_hsh(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.hsh);
+ cat_nthw_cte_enable_qsl(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.qsl);
+ cat_nthw_cte_enable_ipf(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.ipf);
+ cat_nthw_cte_enable_slc(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.slc);
+ cat_nthw_cte_enable_pdb(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.pdb);
+ cat_nthw_cte_enable_msk(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.msk);
+ cat_nthw_cte_enable_hst(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.hst);
+ cat_nthw_cte_enable_epp(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.epp);
+ cat_nthw_cte_enable_tpe(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.tpe);
+ cat_nthw_cte_enable_tpe(be->p_cat_nthw,
+ cat->v22.cte[cat_func].b.rrb);
+
+ cat_nthw_cte_flush(be->p_cat_nthw);
+ cat_func++;
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_cts_flush(void *be_dev, const struct cat_func_s *cat, int index,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_cts_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cts_select(be->p_cat_nthw, index + i);
+ cat_nthw_cts_cat_a(be->p_cat_nthw,
+ cat->v18.cts[index + i].cat_a);
+ cat_nthw_cts_cat_b(be->p_cat_nthw,
+ cat->v18.cts[index + i].cat_b);
+ cat_nthw_cts_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_cot_flush(void *be_dev, const struct cat_func_s *cat,
+ int cat_func, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_cot_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cot_select(be->p_cat_nthw, cat_func + i);
+ cat_nthw_cot_color(be->p_cat_nthw,
+ cat->v18.cot[cat_func + i].color);
+ cat_nthw_cot_km(be->p_cat_nthw,
+ cat->v18.cot[cat_func + i].km);
+ cat_nthw_cot_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_cct_flush(void *be_dev, const struct cat_func_s *cat, int index,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_cct_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cct_select(be->p_cat_nthw, index + i);
+ cat_nthw_cct_color(be->p_cat_nthw,
+ cat->v18.cct[index + i].color);
+ cat_nthw_cct_km(be->p_cat_nthw, cat->v18.cct[index + i].km);
+ cat_nthw_cct_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_exo_flush(void *be_dev, const struct cat_func_s *cat,
+ int ext_index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_exo_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_exo_select(be->p_cat_nthw, ext_index + i);
+ cat_nthw_exo_dyn(be->p_cat_nthw,
+ cat->v18.exo[ext_index + i].dyn);
+ cat_nthw_exo_ofs(be->p_cat_nthw,
+ cat->v18.exo[ext_index + i].ofs);
+ cat_nthw_exo_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_rck_flush(void *be_dev, const struct cat_func_s *cat, int index,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_rck_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_rck_select(be->p_cat_nthw, index + i);
+ cat_nthw_rck_data(be->p_cat_nthw,
+ cat->v18.rck[index + i].rck_data);
+ cat_nthw_rck_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_len_flush(void *be_dev, const struct cat_func_s *cat,
+ int len_index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_len_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_len_select(be->p_cat_nthw, len_index + i);
+ cat_nthw_len_lower(be->p_cat_nthw,
+ cat->v18.len[len_index + i].lower);
+ cat_nthw_len_upper(be->p_cat_nthw,
+ cat->v18.len[len_index + i].upper);
+ cat_nthw_len_dyn1(be->p_cat_nthw,
+ cat->v18.len[len_index + i].dyn1);
+ cat_nthw_len_dyn2(be->p_cat_nthw,
+ cat->v18.len[len_index + i].dyn2);
+ cat_nthw_len_inv(be->p_cat_nthw,
+ cat->v18.len[len_index + i].inv);
+ cat_nthw_len_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_kcc_flush(void *be_dev, const struct cat_func_s *cat,
+ int len_index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 18 || cat->ver == 21 || cat->ver == 22) {
+ cat_nthw_kcc_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_kcc_select(be->p_cat_nthw, len_index + i);
+ cat_nthw_kcc_key(be->p_cat_nthw,
+ cat->v18.kcc_cam[len_index + i].key);
+ cat_nthw_kcc_category(be->p_cat_nthw,
+ cat->v18.kcc_cam[len_index + i].category);
+ cat_nthw_kcc_id(be->p_cat_nthw,
+ cat->v18.kcc_cam[len_index + i].id);
+ cat_nthw_kcc_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_cce_flush(void *be_dev, const struct cat_func_s *cat,
+ int len_index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 22) {
+ cat_nthw_cce_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_cce_select(be->p_cat_nthw, len_index + i);
+ cat_nthw_cce_data_imm(be->p_cat_nthw,
+ cat->v22.cce[len_index + i].imm);
+ cat_nthw_cce_data_ind(be->p_cat_nthw,
+ cat->v22.cce[len_index + i].ind);
+ cat_nthw_cce_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+static int cat_ccs_flush(void *be_dev, const struct cat_func_s *cat,
+ int len_index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, cat, be->p_cat_nthw);
+
+ if (cat->ver == 22) {
+ cat_nthw_ccs_cnt(be->p_cat_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ cat_nthw_ccs_select(be->p_cat_nthw, len_index + i);
+ cat_nthw_ccs_data_cor_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].cor_en);
+ cat_nthw_ccs_data_cor(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].cor);
+ cat_nthw_ccs_data_hsh_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].hsh_en);
+ cat_nthw_ccs_data_hsh(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].hsh);
+ cat_nthw_ccs_data_qsl_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].qsl_en);
+ cat_nthw_ccs_data_qsl(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].qsl);
+ cat_nthw_ccs_data_ipf_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].ipf_en);
+ cat_nthw_ccs_data_ipf(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].ipf);
+ cat_nthw_ccs_data_slc_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].slc_en);
+ cat_nthw_ccs_data_slc(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].slc);
+ cat_nthw_ccs_data_pdb_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].pdb_en);
+ cat_nthw_ccs_data_pdb(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].pdb);
+ cat_nthw_ccs_data_msk_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].msk_en);
+ cat_nthw_ccs_data_msk(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].msk);
+ cat_nthw_ccs_data_hst_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].hst_en);
+ cat_nthw_ccs_data_hst(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].hst);
+ cat_nthw_ccs_data_epp_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].epp_en);
+ cat_nthw_ccs_data_epp(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].epp);
+ cat_nthw_ccs_data_tpe_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].tpe_en);
+ cat_nthw_ccs_data_tpe(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].tpe);
+ cat_nthw_ccs_data_rrb_en(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].rrb_en);
+ cat_nthw_ccs_data_rrb(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].rrb);
+ cat_nthw_ccs_data_sb0_type(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].sb0_type);
+ cat_nthw_ccs_data_sb0_data(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].sb0_data);
+ cat_nthw_ccs_data_sb1_type(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].sb1_type);
+ cat_nthw_ccs_data_sb1_data(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].sb1_data);
+ cat_nthw_ccs_data_sb2_type(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].sb2_type);
+ cat_nthw_ccs_data_sb2_data(be->p_cat_nthw,
+ cat->v22.ccs[len_index + i].sb2_data);
+ cat_nthw_ccs_flush(be->p_cat_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(cat, be->p_cat_nthw);
+ return 0;
+}
+
+/*
+ * ***************** KM *******************
+ */
+
+static bool km_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_km_nthw != NULL;
+}
+
+static uint32_t km_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_km_nthw->m_km) << 16) |
+ (module_get_minor_version(be->p_km_nthw->m_km) & 0xffff));
+}
+
+static int km_rcp_flush(void *be_dev, const struct km_func_s *km, int category,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, km, be->p_km_nthw);
+
+ if (km->ver == 7) {
+ km_nthw_rcp_cnt(be->p_km_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ km_nthw_rcp_select(be->p_km_nthw, category + i);
+ km_nthw_rcp_qw0_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].qw0_dyn);
+ km_nthw_rcp_qw0_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].qw0_ofs);
+ km_nthw_rcp_qw0_sel_a(be->p_km_nthw,
+ km->v7.rcp[category + i].qw0_sel_a);
+ km_nthw_rcp_qw0_sel_b(be->p_km_nthw,
+ km->v7.rcp[category + i].qw0_sel_b);
+ km_nthw_rcp_qw4_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].qw4_dyn);
+ km_nthw_rcp_qw4_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].qw4_ofs);
+ km_nthw_rcp_qw4_sel_a(be->p_km_nthw,
+ km->v7.rcp[category + i].qw4_sel_a);
+ km_nthw_rcp_qw4_sel_b(be->p_km_nthw,
+ km->v7.rcp[category + i].qw4_sel_b);
+ km_nthw_rcp_dw8_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].dw8_dyn);
+ km_nthw_rcp_dw8_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].dw8_ofs);
+ km_nthw_rcp_dw8_sel_a(be->p_km_nthw,
+ km->v7.rcp[category + i].dw8_sel_a);
+ km_nthw_rcp_dw8_sel_b(be->p_km_nthw,
+ km->v7.rcp[category + i].dw8_sel_b);
+ km_nthw_rcp_dw10_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].dw10_dyn);
+ km_nthw_rcp_dw10_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].dw10_ofs);
+ km_nthw_rcp_dw10_sel_a(be->p_km_nthw,
+ km->v7.rcp[category + i].dw10_sel_a);
+ km_nthw_rcp_dw10_sel_b(be->p_km_nthw,
+ km->v7.rcp[category + i].dw10_sel_b);
+ km_nthw_rcp_swx_cch(be->p_km_nthw,
+ km->v7.rcp[category + i].swx_cch);
+ km_nthw_rcp_swx_sel_a(be->p_km_nthw,
+ km->v7.rcp[category + i].swx_sel_a);
+ km_nthw_rcp_swx_sel_b(be->p_km_nthw,
+ km->v7.rcp[category + i].swx_sel_b);
+ km_nthw_rcp_mask_d_a(be->p_km_nthw,
+ km->v7.rcp[category + i].mask_d_a);
+ km_nthw_rcp_mask_b(be->p_km_nthw,
+ km->v7.rcp[category + i].mask_b);
+ km_nthw_rcp_dual(be->p_km_nthw,
+ km->v7.rcp[category + i].dual);
+ km_nthw_rcp_paired(be->p_km_nthw,
+ km->v7.rcp[category + i].paired);
+ km_nthw_rcp_el_a(be->p_km_nthw,
+ km->v7.rcp[category + i].el_a);
+ km_nthw_rcp_el_b(be->p_km_nthw,
+ km->v7.rcp[category + i].el_b);
+ km_nthw_rcp_info_a(be->p_km_nthw,
+ km->v7.rcp[category + i].info_a);
+ km_nthw_rcp_info_b(be->p_km_nthw,
+ km->v7.rcp[category + i].info_b);
+ km_nthw_rcp_ftm_a(be->p_km_nthw,
+ km->v7.rcp[category + i].ftm_a);
+ km_nthw_rcp_ftm_b(be->p_km_nthw,
+ km->v7.rcp[category + i].ftm_b);
+ km_nthw_rcp_bank_a(be->p_km_nthw,
+ km->v7.rcp[category + i].bank_a);
+ km_nthw_rcp_bank_b(be->p_km_nthw,
+ km->v7.rcp[category + i].bank_b);
+ km_nthw_rcp_kl_a(be->p_km_nthw,
+ km->v7.rcp[category + i].kl_a);
+ km_nthw_rcp_kl_b(be->p_km_nthw,
+ km->v7.rcp[category + i].kl_b);
+ km_nthw_rcp_keyway_a(be->p_km_nthw,
+ km->v7.rcp[category + i].keyway_a);
+ km_nthw_rcp_keyway_b(be->p_km_nthw,
+ km->v7.rcp[category + i].keyway_b);
+ km_nthw_rcp_synergy_mode(be->p_km_nthw,
+ km->v7.rcp[category + i].synergy_mode);
+ km_nthw_rcp_dw0_b_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].dw0_b_dyn);
+ km_nthw_rcp_dw0_b_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].dw0_b_ofs);
+ km_nthw_rcp_dw2_b_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].dw2_b_dyn);
+ km_nthw_rcp_dw2_b_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].dw2_b_ofs);
+ km_nthw_rcp_sw4_b_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].sw4_b_dyn);
+ km_nthw_rcp_sw4_b_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].sw4_b_ofs);
+ km_nthw_rcp_sw5_b_dyn(be->p_km_nthw,
+ km->v7.rcp[category + i].sw5_b_dyn);
+ km_nthw_rcp_sw5_b_ofs(be->p_km_nthw,
+ km->v7.rcp[category + i].sw5_b_ofs);
+ km_nthw_rcp_flush(be->p_km_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(km, be->p_km_nthw);
+ return 0;
+}
+
+static int km_cam_flush(void *be_dev, const struct km_func_s *km, int bank,
+ int record, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, km, be->p_km_nthw);
+
+ if (km->ver == 7) {
+ km_nthw_cam_cnt(be->p_km_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ km_nthw_cam_select(be->p_km_nthw,
+ (bank << 11) + record + i);
+ km_nthw_cam_w0(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].w0);
+ km_nthw_cam_w1(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].w1);
+ km_nthw_cam_w2(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].w2);
+ km_nthw_cam_w3(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].w3);
+ km_nthw_cam_w4(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].w4);
+ km_nthw_cam_w5(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].w5);
+ km_nthw_cam_ft0(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].ft0);
+ km_nthw_cam_ft1(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].ft1);
+ km_nthw_cam_ft2(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].ft2);
+ km_nthw_cam_ft3(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].ft3);
+ km_nthw_cam_ft4(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].ft4);
+ km_nthw_cam_ft5(be->p_km_nthw,
+ km->v7.cam[(bank << 11) + record + i].ft5);
+ km_nthw_cam_flush(be->p_km_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(km, be->p_km_nthw);
+ return 0;
+}
+
+static int km_tcam_flush(void *be_dev, const struct km_func_s *km, int bank,
+ int byte, int value, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, km, be->p_km_nthw);
+
+ if (km->ver == 7) {
+ int start_idx = bank * 4 * 256 + byte * 256 + value;
+
+ km_nthw_tcam_cnt(be->p_km_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ if (km->v7.tcam[start_idx + i].dirty) {
+ km_nthw_tcam_select(be->p_km_nthw, start_idx + i);
+ km_nthw_tcam_t(be->p_km_nthw,
+ km->v7.tcam[start_idx + i].t);
+ km_nthw_tcam_flush(be->p_km_nthw);
+ km->v7.tcam[start_idx + i].dirty = 0;
+ }
+ }
+ }
+
+ _CHECK_DEBUG_OFF(km, be->p_km_nthw);
+ return 0;
+}
+
+/*
+ * bank is the TCAM bank, index is the index within the bank (0..71)
+ */
+static int km_tci_flush(void *be_dev, const struct km_func_s *km, int bank,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, km, be->p_km_nthw);
+
+ if (km->ver == 7) {
+ /* TCAM bank width in version 3 = 72 */
+ km_nthw_tci_cnt(be->p_km_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ km_nthw_tci_select(be->p_km_nthw, bank * 72 + index + i);
+ km_nthw_tci_color(be->p_km_nthw,
+ km->v7.tci[bank * 72 + index + i].color);
+ km_nthw_tci_ft(be->p_km_nthw,
+ km->v7.tci[bank * 72 + index + i].ft);
+ km_nthw_tci_flush(be->p_km_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(km, be->p_km_nthw);
+ return 0;
+}
+
+/*
+ * bank is the TCAM bank, index is the index within the bank (0..71)
+ */
+static int km_tcq_flush(void *be_dev, const struct km_func_s *km, int bank,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, km, be->p_km_nthw);
+
+ if (km->ver == 7) {
+ /* TCAM bank width in version 3 = 72 */
+ km_nthw_tcq_cnt(be->p_km_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ /* adr = lover 4 bits = bank, upper 7 bits = index */
+ km_nthw_tcq_select(be->p_km_nthw, bank + (index << 4) + i);
+ km_nthw_tcq_bank_mask(be->p_km_nthw,
+ km->v7.tcq[bank + (index << 4) + i].bank_mask);
+ km_nthw_tcq_qual(be->p_km_nthw,
+ km->v7.tcq[bank + (index << 4) + i].qual);
+ km_nthw_tcq_flush(be->p_km_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(km, be->p_km_nthw);
+ return 0;
+}
+
+/*
+ * ***************** FLM *******************
+ */
+
+static bool flm_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_flm_nthw != NULL;
+}
+
+static uint32_t flm_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_flm_nthw->m_flm) << 16) |
+ (module_get_minor_version(be->p_flm_nthw->m_flm) &
+ 0xffff));
+}
+
+static int flm_control_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_control_enable(be->p_flm_nthw, flm->v17.control->enable);
+ flm_nthw_control_init(be->p_flm_nthw, flm->v17.control->init);
+ flm_nthw_control_lds(be->p_flm_nthw, flm->v17.control->lds);
+ flm_nthw_control_lfs(be->p_flm_nthw, flm->v17.control->lfs);
+ flm_nthw_control_lis(be->p_flm_nthw, flm->v17.control->lis);
+ flm_nthw_control_uds(be->p_flm_nthw, flm->v17.control->uds);
+ flm_nthw_control_uis(be->p_flm_nthw, flm->v17.control->uis);
+ flm_nthw_control_rds(be->p_flm_nthw, flm->v17.control->rds);
+ flm_nthw_control_ris(be->p_flm_nthw, flm->v17.control->ris);
+ flm_nthw_control_pds(be->p_flm_nthw, flm->v17.control->pds);
+ flm_nthw_control_pis(be->p_flm_nthw, flm->v17.control->pis);
+ flm_nthw_control_crcwr(be->p_flm_nthw, flm->v17.control->crcwr);
+ flm_nthw_control_crcrd(be->p_flm_nthw, flm->v17.control->crcrd);
+ flm_nthw_control_rbl(be->p_flm_nthw, flm->v17.control->rbl);
+ flm_nthw_control_eab(be->p_flm_nthw, flm->v17.control->eab);
+ flm_nthw_control_split_sdram_usage(be->p_flm_nthw,
+ flm->v17.control->split_sdram_usage);
+ flm_nthw_control_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_status_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ /* CALIBDONE, INITDONE, IDLE, and EFT_BP is read only */
+ flm_nthw_status_critical(be->p_flm_nthw, &flm->v17.status->critical,
+ 0);
+ flm_nthw_status_panic(be->p_flm_nthw, &flm->v17.status->panic, 0);
+ flm_nthw_status_crcerr(be->p_flm_nthw, &flm->v17.status->crcerr, 0);
+ flm_nthw_status_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_status_update(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_status_update(be->p_flm_nthw);
+ flm_nthw_status_calibdone(be->p_flm_nthw,
+ &flm->v17.status->calibdone, 1);
+ flm_nthw_status_initdone(be->p_flm_nthw, &flm->v17.status->initdone,
+ 1);
+ flm_nthw_status_idle(be->p_flm_nthw, &flm->v17.status->idle, 1);
+ flm_nthw_status_critical(be->p_flm_nthw, &flm->v17.status->critical,
+ 1);
+ flm_nthw_status_panic(be->p_flm_nthw, &flm->v17.status->panic, 1);
+ flm_nthw_status_crcerr(be->p_flm_nthw, &flm->v17.status->crcerr, 1);
+ flm_nthw_status_eft_bp(be->p_flm_nthw, &flm->v17.status->eft_bp, 1);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_timeout_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_timeout_t(be->p_flm_nthw, flm->v17.timeout->t);
+ flm_nthw_timeout_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_scrub_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_scrub_i(be->p_flm_nthw, flm->v17.scrub->i);
+ flm_nthw_scrub_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_load_bin_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_load_bin(be->p_flm_nthw, flm->v17.load_bin->bin);
+ flm_nthw_load_bin_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_load_pps_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_load_pps(be->p_flm_nthw, flm->v17.load_pps->pps);
+ flm_nthw_load_pps_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_load_lps_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_load_lps(be->p_flm_nthw, flm->v17.load_lps->lps);
+ flm_nthw_load_lps_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_load_aps_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_load_aps(be->p_flm_nthw, flm->v17.load_aps->aps);
+ flm_nthw_load_aps_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_prio_flush(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_prio_limit0(be->p_flm_nthw, flm->v17.prio->limit0);
+ flm_nthw_prio_ft0(be->p_flm_nthw, flm->v17.prio->ft0);
+ flm_nthw_prio_limit1(be->p_flm_nthw, flm->v17.prio->limit1);
+ flm_nthw_prio_ft1(be->p_flm_nthw, flm->v17.prio->ft1);
+ flm_nthw_prio_limit2(be->p_flm_nthw, flm->v17.prio->limit2);
+ flm_nthw_prio_ft2(be->p_flm_nthw, flm->v17.prio->ft2);
+ flm_nthw_prio_limit3(be->p_flm_nthw, flm->v17.prio->limit3);
+ flm_nthw_prio_ft3(be->p_flm_nthw, flm->v17.prio->ft3);
+ flm_nthw_prio_flush(be->p_flm_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_pst_flush(void *be_dev, const struct flm_func_s *flm, int index,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_pst_cnt(be->p_flm_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ flm_nthw_pst_select(be->p_flm_nthw, index + i);
+ flm_nthw_pst_bp(be->p_flm_nthw, flm->v17.pst[index + i].bp);
+ flm_nthw_pst_pp(be->p_flm_nthw, flm->v17.pst[index + i].pp);
+ flm_nthw_pst_tp(be->p_flm_nthw, flm->v17.pst[index + i].tp);
+ flm_nthw_pst_flush(be->p_flm_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_rcp_flush(void *be_dev, const struct flm_func_s *flm, int index,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_rcp_cnt(be->p_flm_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ flm_nthw_rcp_select(be->p_flm_nthw, index + i);
+ flm_nthw_rcp_lookup(be->p_flm_nthw,
+ flm->v17.rcp[index + i].lookup);
+ flm_nthw_rcp_qw0_dyn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].qw0_dyn);
+ flm_nthw_rcp_qw0_ofs(be->p_flm_nthw,
+ flm->v17.rcp[index + i].qw0_ofs);
+ flm_nthw_rcp_qw0_sel(be->p_flm_nthw,
+ flm->v17.rcp[index + i].qw0_sel);
+ flm_nthw_rcp_qw4_dyn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].qw4_dyn);
+ flm_nthw_rcp_qw4_ofs(be->p_flm_nthw,
+ flm->v17.rcp[index + i].qw4_ofs);
+ flm_nthw_rcp_sw8_dyn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].sw8_dyn);
+ flm_nthw_rcp_sw8_ofs(be->p_flm_nthw,
+ flm->v17.rcp[index + i].sw8_ofs);
+ flm_nthw_rcp_sw8_sel(be->p_flm_nthw,
+ flm->v17.rcp[index + i].sw8_sel);
+ flm_nthw_rcp_sw9_dyn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].sw9_dyn);
+ flm_nthw_rcp_sw9_ofs(be->p_flm_nthw,
+ flm->v17.rcp[index + i].sw9_ofs);
+ flm_nthw_rcp_mask(be->p_flm_nthw,
+ flm->v17.rcp[index + i].mask);
+ flm_nthw_rcp_kid(be->p_flm_nthw,
+ flm->v17.rcp[index + i].kid);
+ flm_nthw_rcp_opn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].opn);
+ flm_nthw_rcp_ipn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].ipn);
+ flm_nthw_rcp_byt_dyn(be->p_flm_nthw,
+ flm->v17.rcp[index + i].byt_dyn);
+ flm_nthw_rcp_byt_ofs(be->p_flm_nthw,
+ flm->v17.rcp[index + i].byt_ofs);
+ flm_nthw_rcp_txplm(be->p_flm_nthw,
+ flm->v17.rcp[index + i].txplm);
+ flm_nthw_rcp_auto_ipv4_mask(be->p_flm_nthw,
+ flm->v17.rcp[index + i].auto_ipv4_mask);
+ flm_nthw_rcp_flush(be->p_flm_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_buf_ctrl_update(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_buf_ctrl_update(be->p_flm_nthw,
+ &flm->v17.buf_ctrl->lrn_free,
+ &flm->v17.buf_ctrl->inf_avail,
+ &flm->v17.buf_ctrl->sta_avail);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_stat_update(void *be_dev, const struct flm_func_s *flm)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ if (flm->ver >= 17) {
+ flm_nthw_stat_lrn_done_update(be->p_flm_nthw);
+ flm_nthw_stat_lrn_ignore_update(be->p_flm_nthw);
+ flm_nthw_stat_lrn_fail_update(be->p_flm_nthw);
+ flm_nthw_stat_unl_done_update(be->p_flm_nthw);
+ flm_nthw_stat_unl_ignore_update(be->p_flm_nthw);
+ flm_nthw_stat_rel_done_update(be->p_flm_nthw);
+ flm_nthw_stat_rel_ignore_update(be->p_flm_nthw);
+ flm_nthw_stat_aul_done_update(be->p_flm_nthw);
+ flm_nthw_stat_aul_ignore_update(be->p_flm_nthw);
+ flm_nthw_stat_aul_fail_update(be->p_flm_nthw);
+ flm_nthw_stat_tul_done_update(be->p_flm_nthw);
+ flm_nthw_stat_flows_update(be->p_flm_nthw);
+
+ flm_nthw_stat_lrn_done_cnt(be->p_flm_nthw, &flm->v17.lrn_done->cnt,
+ 1);
+ flm_nthw_stat_lrn_ignore_cnt(be->p_flm_nthw,
+ &flm->v17.lrn_ignore->cnt, 1);
+ flm_nthw_stat_lrn_fail_cnt(be->p_flm_nthw, &flm->v17.lrn_fail->cnt,
+ 1);
+ flm_nthw_stat_unl_done_cnt(be->p_flm_nthw, &flm->v17.unl_done->cnt,
+ 1);
+ flm_nthw_stat_unl_ignore_cnt(be->p_flm_nthw,
+ &flm->v17.unl_ignore->cnt, 1);
+ flm_nthw_stat_rel_done_cnt(be->p_flm_nthw, &flm->v17.rel_done->cnt,
+ 1);
+ flm_nthw_stat_rel_ignore_cnt(be->p_flm_nthw,
+ &flm->v17.rel_ignore->cnt, 1);
+ flm_nthw_stat_aul_done_cnt(be->p_flm_nthw, &flm->v17.aul_done->cnt,
+ 1);
+ flm_nthw_stat_aul_ignore_cnt(be->p_flm_nthw,
+ &flm->v17.aul_ignore->cnt, 1);
+ flm_nthw_stat_aul_fail_cnt(be->p_flm_nthw, &flm->v17.aul_fail->cnt,
+ 1);
+ flm_nthw_stat_tul_done_cnt(be->p_flm_nthw, &flm->v17.tul_done->cnt,
+ 1);
+ flm_nthw_stat_flows_cnt(be->p_flm_nthw, &flm->v17.flows->cnt, 1);
+
+ flm_nthw_stat_prb_done_update(be->p_flm_nthw);
+ flm_nthw_stat_prb_ignore_update(be->p_flm_nthw);
+ flm_nthw_stat_prb_done_cnt(be->p_flm_nthw, &flm->v17.prb_done->cnt,
+ 1);
+ flm_nthw_stat_prb_ignore_cnt(be->p_flm_nthw,
+ &flm->v17.prb_ignore->cnt, 1);
+ }
+ if (flm->ver >= 20) {
+ flm_nthw_stat_sta_done_update(be->p_flm_nthw);
+ flm_nthw_stat_inf_done_update(be->p_flm_nthw);
+ flm_nthw_stat_inf_skip_update(be->p_flm_nthw);
+ flm_nthw_stat_pck_hit_update(be->p_flm_nthw);
+ flm_nthw_stat_pck_miss_update(be->p_flm_nthw);
+ flm_nthw_stat_pck_unh_update(be->p_flm_nthw);
+ flm_nthw_stat_pck_dis_update(be->p_flm_nthw);
+ flm_nthw_stat_csh_hit_update(be->p_flm_nthw);
+ flm_nthw_stat_csh_miss_update(be->p_flm_nthw);
+ flm_nthw_stat_csh_unh_update(be->p_flm_nthw);
+ flm_nthw_stat_cuc_start_update(be->p_flm_nthw);
+ flm_nthw_stat_cuc_move_update(be->p_flm_nthw);
+
+ flm_nthw_stat_sta_done_cnt(be->p_flm_nthw, &flm->v20.sta_done->cnt,
+ 1);
+ flm_nthw_stat_inf_done_cnt(be->p_flm_nthw, &flm->v20.inf_done->cnt,
+ 1);
+ flm_nthw_stat_inf_skip_cnt(be->p_flm_nthw, &flm->v20.inf_skip->cnt,
+ 1);
+ flm_nthw_stat_pck_hit_cnt(be->p_flm_nthw, &flm->v20.pck_hit->cnt, 1);
+ flm_nthw_stat_pck_miss_cnt(be->p_flm_nthw, &flm->v20.pck_miss->cnt,
+ 1);
+ flm_nthw_stat_pck_unh_cnt(be->p_flm_nthw, &flm->v20.pck_unh->cnt, 1);
+ flm_nthw_stat_pck_dis_cnt(be->p_flm_nthw, &flm->v20.pck_dis->cnt, 1);
+ flm_nthw_stat_csh_hit_cnt(be->p_flm_nthw, &flm->v20.csh_hit->cnt, 1);
+ flm_nthw_stat_csh_miss_cnt(be->p_flm_nthw, &flm->v20.csh_miss->cnt,
+ 1);
+ flm_nthw_stat_csh_unh_cnt(be->p_flm_nthw, &flm->v20.csh_unh->cnt, 1);
+ flm_nthw_stat_cuc_start_cnt(be->p_flm_nthw, &flm->v20.cuc_start->cnt,
+ 1);
+ flm_nthw_stat_cuc_move_cnt(be->p_flm_nthw, &flm->v20.cuc_move->cnt,
+ 1);
+ }
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return 0;
+}
+
+static int flm_lrn_data_flush(void *be_dev, const struct flm_func_s *flm,
+ const uint32_t *lrn_data, uint32_t size)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ int ret = flm_nthw_lrn_data_flush(be->p_flm_nthw, lrn_data, size,
+ &flm->v17.buf_ctrl->lrn_free,
+ &flm->v17.buf_ctrl->inf_avail,
+ &flm->v17.buf_ctrl->sta_avail);
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return ret;
+}
+
+static int flm_inf_data_update(void *be_dev, const struct flm_func_s *flm,
+ uint32_t *inf_data, uint32_t size)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ int ret = flm_nthw_inf_data_update(be->p_flm_nthw, inf_data, size,
+ &flm->v17.buf_ctrl->lrn_free,
+ &flm->v17.buf_ctrl->inf_avail,
+ &flm->v17.buf_ctrl->sta_avail);
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return ret;
+}
+
+static int flm_sta_data_update(void *be_dev, const struct flm_func_s *flm,
+ uint32_t *sta_data, uint32_t size)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, flm, be->p_flm_nthw);
+
+ int ret = flm_nthw_sta_data_update(be->p_flm_nthw, sta_data, size,
+ &flm->v17.buf_ctrl->lrn_free,
+ &flm->v17.buf_ctrl->inf_avail,
+ &flm->v17.buf_ctrl->sta_avail);
+
+ _CHECK_DEBUG_OFF(flm, be->p_flm_nthw);
+ return ret;
+}
+
+/*
+ * ***************** HSH *******************
+ */
+
+static bool hsh_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_hsh_nthw != NULL;
+}
+
+static uint32_t hsh_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_hsh_nthw->m_hsh) << 16) |
+ (module_get_minor_version(be->p_hsh_nthw->m_hsh) &
+ 0xffff));
+}
+
+static int hsh_rcp_flush(void *be_dev, const struct hsh_func_s *hsh,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, hsh, be->p_hsh_nthw);
+
+ if (hsh->ver == 5) {
+ hsh_nthw_rcp_cnt(be->p_hsh_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ hsh_nthw_rcp_select(be->p_hsh_nthw, category + i);
+ hsh_nthw_rcp_load_dist_type(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].load_dist_type);
+ hsh_nthw_rcp_mac_port_mask(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].mac_port_mask);
+ hsh_nthw_rcp_sort(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].sort);
+ hsh_nthw_rcp_qw0_pe(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].qw0_pe);
+ hsh_nthw_rcp_qw0_ofs(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].qw0_ofs);
+ hsh_nthw_rcp_qw4_pe(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].qw4_pe);
+ hsh_nthw_rcp_qw4_ofs(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].qw4_ofs);
+ hsh_nthw_rcp_w8_pe(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w8_pe);
+ hsh_nthw_rcp_w8_ofs(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w8_ofs);
+ hsh_nthw_rcp_w8_sort(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w8_sort);
+ hsh_nthw_rcp_w9_pe(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w9_pe);
+ hsh_nthw_rcp_w9_ofs(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w9_ofs);
+ hsh_nthw_rcp_w9_sort(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w9_sort);
+ hsh_nthw_rcp_w9_p(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].w9_p);
+ hsh_nthw_rcp_p_mask(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].p_mask);
+ hsh_nthw_rcp_word_mask(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].word_mask);
+ hsh_nthw_rcp_seed(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].seed);
+ hsh_nthw_rcp_tnl_p(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].tnl_p);
+ hsh_nthw_rcp_hsh_valid(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].hsh_valid);
+ hsh_nthw_rcp_hsh_type(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].hsh_type);
+ hsh_nthw_rcp_auto_ipv4_mask(be->p_hsh_nthw,
+ hsh->v5.rcp[category + i].auto_ipv4_mask);
+ hsh_nthw_rcp_flush(be->p_hsh_nthw);
+ }
+ }
+ _CHECK_DEBUG_OFF(hsh, be->p_hsh_nthw);
+ return 0;
+}
+
+/*
+ * ***************** HST *******************
+ */
+
+static bool hst_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_hst_nthw != NULL;
+}
+
+static uint32_t hst_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_hst_nthw->m_hst) << 16) |
+ (module_get_minor_version(be->p_hst_nthw->m_hst) &
+ 0xffff));
+}
+
+static int hst_rcp_flush(void *be_dev, const struct hst_func_s *hst,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, hst, be->p_hst_nthw);
+
+ if (hst->ver == 2) {
+ hst_nthw_rcp_cnt(be->p_hst_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ hst_nthw_rcp_select(be->p_hst_nthw, category + i);
+ hst_nthw_rcp_strip_mode(be->p_hst_nthw,
+ hst->v2.rcp[category + i].strip_mode);
+ hst_nthw_rcp_start_dyn(be->p_hst_nthw,
+ hst->v2.rcp[category + i].start_dyn);
+ hst_nthw_rcp_start_ofs(be->p_hst_nthw,
+ hst->v2.rcp[category + i].start_ofs);
+ hst_nthw_rcp_end_dyn(be->p_hst_nthw,
+ hst->v2.rcp[category + i].end_dyn);
+ hst_nthw_rcp_end_ofs(be->p_hst_nthw,
+ hst->v2.rcp[category + i].end_ofs);
+ hst_nthw_rcp_modif0_cmd(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif0_cmd);
+ hst_nthw_rcp_modif0_dyn(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif0_dyn);
+ hst_nthw_rcp_modif0_ofs(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif0_ofs);
+ hst_nthw_rcp_modif0_value(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif0_value);
+ hst_nthw_rcp_modif1_cmd(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif1_cmd);
+ hst_nthw_rcp_modif1_dyn(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif1_dyn);
+ hst_nthw_rcp_modif1_ofs(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif1_ofs);
+ hst_nthw_rcp_modif1_value(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif1_value);
+ hst_nthw_rcp_modif2_cmd(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif2_cmd);
+ hst_nthw_rcp_modif2_dyn(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif2_dyn);
+ hst_nthw_rcp_modif2_ofs(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif2_ofs);
+ hst_nthw_rcp_modif2_value(be->p_hst_nthw,
+ hst->v2.rcp[category + i].modif2_value);
+ hst_nthw_rcp_flush(be->p_hst_nthw);
+ }
+ }
+ _CHECK_DEBUG_OFF(hst, be->p_hst_nthw);
+ return 0;
+}
+
+/*
+ * ***************** QSL *******************
+ */
+
+static bool qsl_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_qsl_nthw != NULL;
+}
+
+static uint32_t qsl_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_qsl_nthw->m_qsl) << 16) |
+ (module_get_minor_version(be->p_qsl_nthw->m_qsl) &
+ 0xffff));
+}
+
+static int qsl_rcp_flush(void *be_dev, const struct qsl_func_s *qsl,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw);
+
+ if (qsl->ver == 7) {
+ qsl_nthw_rcp_cnt(be->p_qsl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ qsl_nthw_rcp_select(be->p_qsl_nthw, category + i);
+ qsl_nthw_rcp_discard(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].discard);
+ qsl_nthw_rcp_drop(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].drop);
+ qsl_nthw_rcp_tbl_lo(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].tbl_lo);
+ qsl_nthw_rcp_tbl_hi(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].tbl_hi);
+ qsl_nthw_rcp_tbl_idx(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].tbl_idx);
+ qsl_nthw_rcp_tbl_msk(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].tbl_msk);
+ qsl_nthw_rcp_lr(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].lr);
+ qsl_nthw_rcp_tsa(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].tsa);
+ qsl_nthw_rcp_vli(be->p_qsl_nthw,
+ qsl->v7.rcp[category + i].vli);
+ qsl_nthw_rcp_flush(be->p_qsl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw);
+ return 0;
+}
+
+static int qsl_qst_flush(void *be_dev, const struct qsl_func_s *qsl, int entry,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw);
+
+ if (qsl->ver == 7) {
+ qsl_nthw_qst_cnt(be->p_qsl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ qsl_nthw_qst_select(be->p_qsl_nthw, entry + i);
+ qsl_nthw_qst_queue(be->p_qsl_nthw,
+ qsl->v7.qst[entry + i].queue);
+ qsl_nthw_qst_en(be->p_qsl_nthw, qsl->v7.qst[entry + i].en);
+
+ qsl_nthw_qst_tx_port(be->p_qsl_nthw,
+ qsl->v7.qst[entry + i].tx_port);
+ qsl_nthw_qst_lre(be->p_qsl_nthw,
+ qsl->v7.qst[entry + i].lre);
+ qsl_nthw_qst_tci(be->p_qsl_nthw,
+ qsl->v7.qst[entry + i].tci);
+ qsl_nthw_qst_ven(be->p_qsl_nthw,
+ qsl->v7.qst[entry + i].ven);
+ qsl_nthw_qst_flush(be->p_qsl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw);
+ return 0;
+}
+
+static int qsl_qen_flush(void *be_dev, const struct qsl_func_s *qsl, int entry,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw);
+
+ if (qsl->ver == 7) {
+ qsl_nthw_qen_cnt(be->p_qsl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ qsl_nthw_qen_select(be->p_qsl_nthw, entry + i);
+ qsl_nthw_qen_en(be->p_qsl_nthw, qsl->v7.qen[entry + i].en);
+ qsl_nthw_qen_flush(be->p_qsl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw);
+ return 0;
+}
+
+static int qsl_unmq_flush(void *be_dev, const struct qsl_func_s *qsl, int entry,
+ int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, qsl, be->p_qsl_nthw);
+
+ if (qsl->ver == 7) {
+ qsl_nthw_unmq_cnt(be->p_qsl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ qsl_nthw_unmq_select(be->p_qsl_nthw, entry + i);
+ qsl_nthw_unmq_dest_queue(be->p_qsl_nthw,
+ qsl->v7.unmq[entry + i].dest_queue);
+ qsl_nthw_unmq_en(be->p_qsl_nthw,
+ qsl->v7.unmq[entry + i].en);
+ qsl_nthw_unmq_flush(be->p_qsl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(qsl, be->p_qsl_nthw);
+ return 0;
+}
+
+/*
+ * ***************** SLC *******************
+ */
+
+static bool slc_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_slc_nthw != NULL;
+}
+
+static uint32_t slc_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_slc_nthw->m_slc) << 16) |
+ (module_get_minor_version(be->p_slc_nthw->m_slc) &
+ 0xffff));
+}
+
+static int slc_rcp_flush(void *be_dev, const struct slc_func_s *slc,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, slc, be->p_slc_nthw);
+
+ if (slc->ver == 1) {
+ slc_nthw_rcp_cnt(be->p_slc_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ slc_nthw_rcp_select(be->p_slc_nthw, category + i);
+ slc_nthw_rcp_tail_slc_en(be->p_slc_nthw,
+ slc->v1.rcp[category + i].tail_slc_en);
+ slc_nthw_rcp_tail_dyn(be->p_slc_nthw,
+ slc->v1.rcp[category + i].tail_dyn);
+ slc_nthw_rcp_tail_ofs(be->p_slc_nthw,
+ slc->v1.rcp[category + i].tail_ofs);
+ slc_nthw_rcp_pcap(be->p_slc_nthw,
+ slc->v1.rcp[category + i].pcap);
+ slc_nthw_rcp_flush(be->p_slc_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(slc, be->p_slc_nthw);
+ return 0;
+}
+
+/*
+ * ***************** SLC LR *******************
+ */
+
+static bool slc_lr_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_slc_lr_nthw != NULL;
+}
+
+static uint32_t slc_lr_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_slc_lr_nthw->m_slc_lr)
+ << 16) |
+ (module_get_minor_version(be->p_slc_lr_nthw->m_slc_lr) &
+ 0xffff));
+}
+
+static int slc_lr_rcp_flush(void *be_dev, const struct slc_lr_func_s *slc_lr,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, slc_lr, be->p_slc_lr_nthw);
+
+ if (slc_lr->ver == 2) {
+ slc_lr_nthw_rcp_cnt(be->p_slc_lr_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ slc_lr_nthw_rcp_select(be->p_slc_lr_nthw, category + i);
+ slc_lr_nthw_rcp_tail_slc_en(be->p_slc_lr_nthw,
+ slc_lr->v2.rcp[category + i].tail_slc_en);
+ slc_lr_nthw_rcp_tail_dyn(be->p_slc_lr_nthw,
+ slc_lr->v2.rcp[category + i].tail_dyn);
+ slc_lr_nthw_rcp_tail_ofs(be->p_slc_lr_nthw,
+ slc_lr->v2.rcp[category + i].tail_ofs);
+ slc_lr_nthw_rcp_pcap(be->p_slc_lr_nthw,
+ slc_lr->v2.rcp[category + i].pcap);
+ slc_lr_nthw_rcp_flush(be->p_slc_lr_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(slc_lr, be->p_slc_lr_nthw);
+ return 0;
+}
+
+/*
+ * ***************** PDB *******************
+ */
+
+static bool pdb_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_pdb_nthw != NULL;
+}
+
+static uint32_t pdb_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_pdb_nthw->m_pdb) << 16) |
+ (module_get_minor_version(be->p_pdb_nthw->m_pdb) &
+ 0xffff));
+}
+
+static int pdb_rcp_flush(void *be_dev, const struct pdb_func_s *pdb,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, pdb, be->p_pdb_nthw);
+
+ if (pdb->ver == 9) {
+ pdb_nthw_rcp_cnt(be->p_pdb_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ pdb_nthw_rcp_select(be->p_pdb_nthw, category + i);
+ pdb_nthw_rcp_descriptor(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].descriptor);
+ pdb_nthw_rcp_desc_len(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].desc_len);
+ pdb_nthw_rcp_tx_port(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].tx_port);
+ pdb_nthw_rcp_tx_ignore(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].tx_ignore);
+ pdb_nthw_rcp_tx_now(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].tx_now);
+ pdb_nthw_rcp_crc_overwrite(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].crc_overwrite);
+ pdb_nthw_rcp_align(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].align);
+ pdb_nthw_rcp_ofs0_dyn(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ofs0_dyn);
+ pdb_nthw_rcp_ofs0_rel(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ofs0_rel);
+ pdb_nthw_rcp_ofs1_dyn(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ofs1_dyn);
+ pdb_nthw_rcp_ofs1_rel(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ofs1_rel);
+ pdb_nthw_rcp_ofs2_dyn(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ofs2_dyn);
+ pdb_nthw_rcp_ofs2_rel(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ofs2_rel);
+ pdb_nthw_rcp_ip_prot_tnl(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ip_prot_tnl);
+ pdb_nthw_rcp_ppc_hsh(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].ppc_hsh);
+ pdb_nthw_rcp_duplicate_en(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].duplicate_en);
+ pdb_nthw_rcp_duplicate_bit(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].duplicate_bit);
+ pdb_nthw_rcp_duplicate_bit(be->p_pdb_nthw,
+ pdb->v9.rcp[category + i].pcap_keep_fcs);
+ pdb_nthw_rcp_flush(be->p_pdb_nthw);
+ }
+ }
+ _CHECK_DEBUG_OFF(pdb, be->p_pdb_nthw);
+ return 0;
+}
+
+static int pdb_config_flush(void *be_dev, const struct pdb_func_s *pdb)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, pdb, be->p_pdb_nthw);
+
+ if (pdb->ver == 9) {
+ pdb_nthw_config_ts_format(be->p_pdb_nthw, pdb->v9.config->ts_format);
+ pdb_nthw_config_port_ofs(be->p_pdb_nthw, pdb->v9.config->port_ofs);
+ pdb_nthw_config_flush(be->p_pdb_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(pdb, be->p_pdb_nthw);
+ return 0;
+}
+
+/*
+ * ***************** IOA *******************
+ */
+
+static bool ioa_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_ioa_nthw != NULL;
+}
+
+static uint32_t ioa_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_ioa_nthw->m_ioa) << 16) |
+ (module_get_minor_version(be->p_ioa_nthw->m_ioa) &
+ 0xffff));
+}
+
+static int ioa_rcp_flush(void *be_dev, const struct ioa_func_s *ioa,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, ioa, be->p_ioa_nthw);
+
+ if (ioa->ver == 4) {
+ ioa_nthw_rcp_cnt(be->p_ioa_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ ioa_nthw_rcp_select(be->p_ioa_nthw, category + i);
+ ioa_nthw_rcp_tunnel_pop(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].tunnel_pop);
+ ioa_nthw_rcp_vlan_pop(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].vlan_pop);
+ ioa_nthw_rcp_vlan_push(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].vlan_push);
+ ioa_nthw_rcp_vlan_vid(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].vlan_vid);
+ ioa_nthw_rcp_vlan_dei(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].vlan_dei);
+ ioa_nthw_rcp_vlan_pcp(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].vlan_pcp);
+ ioa_nthw_rcp_vlan_tpid_sel(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].vlan_tpid_sel);
+ ioa_nthw_rcp_queue_override_en(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].queue_override_en);
+ ioa_nthw_rcp_queue_id(be->p_ioa_nthw,
+ ioa->v4.rcp[category + i].queue_id);
+ ioa_nthw_rcp_flush(be->p_ioa_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(ioa, be->p_ioa_nthw);
+ return 0;
+}
+
+static int ioa_special_tpid_flush(void *be_dev, const struct ioa_func_s *ioa)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, ioa, be->p_ioa_nthw);
+
+ if (ioa->ver == 4) {
+ ioa_nthw_special_vlan_tpid_cust_tpid0(be->p_ioa_nthw,
+ ioa->v4.tpid->cust_tpid_0);
+ ioa_nthw_special_vlan_tpid_cust_tpid1(be->p_ioa_nthw,
+ ioa->v4.tpid->cust_tpid_1);
+ ioa_nthw_special_vlan_tpid_flush(be->p_ioa_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(ioa, be->p_ioa_nthw);
+ return 0;
+}
+
+static int ioa_roa_epp_flush(void *be_dev, const struct ioa_func_s *ioa,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, ioa, be->p_ioa_nthw);
+
+ if (ioa->ver == 4) {
+ ioa_nthw_roa_epp_cnt(be->p_ioa_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ ioa_nthw_roa_epp_select(be->p_ioa_nthw, index + i);
+ ioa_nthw_roa_epp_push_tunnel(be->p_ioa_nthw,
+ ioa->v4.roa_epp[index + i].push_tunnel);
+ ioa_nthw_roa_epp_tx_port(be->p_ioa_nthw,
+ ioa->v4.roa_epp[index + i].tx_port);
+ ioa_nthw_roa_epp_flush(be->p_ioa_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(ioa, be->p_ioa_nthw);
+ return 0;
+}
+
+/*
+ * ***************** ROA *******************
+ */
+
+static bool roa_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_roa_nthw != NULL;
+}
+
+static uint32_t roa_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_roa_nthw->m_roa) << 16) |
+ (module_get_minor_version(be->p_roa_nthw->m_roa) &
+ 0xffff));
+}
+
+static int roa_tunhdr_flush(void *be_dev, const struct roa_func_s *roa,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw);
+
+ if (roa->ver == 6) {
+ roa_nthw_tun_hdr_cnt(be->p_roa_nthw, 4);
+ for (int i = 0; i < cnt; i++) {
+ for (int ii = 0; ii < 4; ii++) {
+ roa_nthw_tun_hdr_select(be->p_roa_nthw,
+ index + (i * 4) + ii);
+ roa_nthw_tun_hdr_tunnel_hdr(be->p_roa_nthw,
+ &roa->v6.tunhdr[index / 4 + i]
+ .tunnel_hdr[ii * 4]);
+ roa_nthw_tun_hdr_flush(be->p_roa_nthw);
+ }
+ }
+ }
+
+ _CHECK_DEBUG_OFF(roa, be->p_roa_nthw);
+ return 0;
+}
+
+static int roa_tuncfg_flush(void *be_dev, const struct roa_func_s *roa,
+ int category, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw);
+
+ if (roa->ver == 6) {
+ roa_nthw_tun_cfg_cnt(be->p_roa_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ roa_nthw_tun_cfg_select(be->p_roa_nthw, category + i);
+ roa_nthw_tun_cfg_tun_len(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].tun_len);
+ roa_nthw_tun_cfg_tun_type(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].tun_type);
+ roa_nthw_tun_cfg_tun_vlan(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].tun_vlan);
+ roa_nthw_tun_cfg_ip_type(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].ip_type);
+ roa_nthw_tun_cfg_ipcs_upd(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].ipcs_upd);
+ roa_nthw_tun_cfg_ipcs_precalc(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].ipcs_precalc);
+ roa_nthw_tun_cfg_iptl_upd(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].iptl_upd);
+ roa_nthw_tun_cfg_iptl_precalc(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].iptl_precalc);
+ roa_nthw_tun_cfg_vxlan_udp_len_upd(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].vxlan_udp_len_upd);
+ roa_nthw_tun_cfg_tx_lag_ix(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].tx_lag_ix);
+ roa_nthw_tun_cfg_recirculate(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].recirculate);
+ roa_nthw_tun_cfg_push_tunnel(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].push_tunnel);
+ roa_nthw_tun_cfg_recirc_port(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].recirc_port);
+ roa_nthw_tun_cfg_recirc_bypass(be->p_roa_nthw,
+ roa->v6.tuncfg[category + i].recirc_bypass);
+ roa_nthw_tun_cfg_flush(be->p_roa_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(roa, be->p_roa_nthw);
+ return 0;
+}
+
+static int roa_config_flush(void *be_dev, const struct roa_func_s *roa)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw);
+
+ if (roa->ver == 6) {
+ roa_nthw_config_fwd_recirculate(be->p_roa_nthw,
+ roa->v6.config->fwd_recirculate);
+ roa_nthw_config_fwd_normal_pcks(be->p_roa_nthw,
+ roa->v6.config->fwd_normal_pcks);
+ roa_nthw_config_fwd_tx_port0(be->p_roa_nthw,
+ roa->v6.config->fwd_txport0);
+ roa_nthw_config_fwd_tx_port1(be->p_roa_nthw,
+ roa->v6.config->fwd_txport1);
+ roa_nthw_config_fwd_cell_builder_pcks(be->p_roa_nthw,
+ roa->v6.config->fwd_cellbuilder_pcks);
+ roa_nthw_config_fwd_non_normal_pcks(be->p_roa_nthw,
+ roa->v6.config->fwd_non_normal_pcks);
+ roa_nthw_config_flush(be->p_roa_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(roa, be->p_roa_nthw);
+ return 0;
+}
+
+static int roa_lagcfg_flush(void *be_dev, const struct roa_func_s *roa,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, roa, be->p_roa_nthw);
+
+ if (roa->ver == 6) {
+ roa_nthw_lag_cfg_cnt(be->p_roa_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ roa_nthw_lag_cfg_select(be->p_roa_nthw, index + i);
+ roa_nthw_lag_cfg_tx_phy_port(be->p_roa_nthw,
+ roa->v6.lagcfg[index + i].txphy_port);
+ roa_nthw_lag_cfg_flush(be->p_roa_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(roa, be->p_roa_nthw);
+ return 0;
+}
+
+/*
+ * ***************** RMC *******************
+ */
+
+static bool rmc_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_rmc_nthw != NULL;
+}
+
+static uint32_t rmc_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return (uint32_t)((module_get_major_version(be->p_rmc_nthw->m_rmc) << 16) |
+ (module_get_minor_version(be->p_rmc_nthw->m_rmc) &
+ 0xffff));
+}
+
+static int rmc_ctrl_flush(void *be_dev, const struct rmc_func_s *rmc)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, rmc, be->p_rmc_nthw);
+
+ if (rmc->ver == 0x10003) {
+ rmc_nthw_ctrl_block_statt(be->p_rmc_nthw,
+ rmc->v1_3.ctrl->block_statt);
+ rmc_nthw_ctrl_block_keep_a(be->p_rmc_nthw,
+ rmc->v1_3.ctrl->block_keepa);
+ rmc_nthw_ctrl_block_rpp_slice(be->p_rmc_nthw,
+ rmc->v1_3.ctrl->block_rpp_slice);
+ rmc_nthw_ctrl_block_mac_port(be->p_rmc_nthw,
+ rmc->v1_3.ctrl->block_mac_port);
+ rmc_nthw_ctrl_lag_phy_odd_even(be->p_rmc_nthw,
+ rmc->v1_3.ctrl->lag_phy_odd_even);
+ rmc_nthw_ctrl_flush(be->p_rmc_nthw);
+ }
+
+ _CHECK_DEBUG_OFF(rmc, be->p_rmc_nthw);
+ return 0;
+}
+
+/*
+ * ***************** TPE *******************
+ */
+
+static bool tpe_get_present(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ return be->p_csu_nthw != NULL && be->p_hfu_nthw != NULL &&
+ be->p_rpp_lr_nthw != NULL && be->p_tx_cpy_nthw != NULL &&
+ be->p_tx_ins_nthw != NULL && be->p_tx_rpl_nthw != NULL;
+}
+
+static uint32_t tpe_get_version(void *be_dev)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ const uint32_t csu_version =
+ (uint32_t)((module_get_major_version(be->p_csu_nthw->m_csu) << 16) |
+ (module_get_minor_version(be->p_csu_nthw->m_csu) &
+ 0xffff));
+
+ const uint32_t hfu_version =
+ (uint32_t)((module_get_major_version(be->p_hfu_nthw->m_hfu) << 16) |
+ (module_get_minor_version(be->p_hfu_nthw->m_hfu) &
+ 0xffff));
+
+ const uint32_t rpp_lr_version =
+ (uint32_t)((module_get_major_version(be->p_rpp_lr_nthw->m_rpp_lr)
+ << 16) |
+ (module_get_minor_version(be->p_rpp_lr_nthw->m_rpp_lr) &
+ 0xffff));
+
+ const uint32_t tx_cpy_version =
+ (uint32_t)((module_get_major_version(be->p_tx_cpy_nthw->m_tx_cpy)
+ << 16) |
+ (module_get_minor_version(be->p_tx_cpy_nthw->m_tx_cpy) &
+ 0xffff));
+
+ const uint32_t tx_ins_version =
+ (uint32_t)((module_get_major_version(be->p_tx_ins_nthw->m_tx_ins)
+ << 16) |
+ (module_get_minor_version(be->p_tx_ins_nthw->m_tx_ins) &
+ 0xffff));
+
+ const uint32_t tx_rpl_version =
+ (uint32_t)((module_get_major_version(be->p_tx_rpl_nthw->m_tx_rpl)
+ << 16) |
+ (module_get_minor_version(be->p_tx_rpl_nthw->m_tx_rpl) &
+ 0xffff));
+
+ if (csu_version == 0 && hfu_version == 1 && rpp_lr_version == 0 &&
+ tx_cpy_version == 1 && tx_ins_version == 1 && tx_rpl_version == 2)
+ return 1;
+
+ if (csu_version == 0 && hfu_version == 1 && rpp_lr_version == 1 &&
+ tx_cpy_version == 1 && tx_ins_version == 1 && tx_rpl_version == 2)
+ return 2;
+
+ assert(false);
+ return 0;
+}
+
+static int tpe_rpp_rcp_flush(void *be_dev, const struct tpe_func_s *rpp_lr,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, rpp_lr, be->p_rpp_lr_nthw);
+
+ if (rpp_lr->ver >= 1) {
+ rpp_lr_nthw_rcp_cnt(be->p_rpp_lr_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ rpp_lr_nthw_rcp_select(be->p_rpp_lr_nthw, index + i);
+ rpp_lr_nthw_rcp_exp(be->p_rpp_lr_nthw,
+ rpp_lr->v1.rpp_rcp[index + i].exp);
+ rpp_lr_nthw_rcp_flush(be->p_rpp_lr_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(rpp_lr, be->p_rpp_lr_nthw);
+ return 0;
+}
+
+static int tpe_rpp_ifr_rcp_flush(void *be_dev, const struct tpe_func_s *rpp_lr,
+ int index, int cnt)
+{
+ int res = 0;
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, rpp_lr, be->p_rpp_lr_nthw);
+
+ if (rpp_lr->ver >= 2) {
+ rpp_lr_nthw_ifr_rcp_cnt(be->p_rpp_lr_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ rpp_lr_nthw_ifr_rcp_select(be->p_rpp_lr_nthw, index + i);
+ rpp_lr_nthw_ifr_rcp_en(be->p_rpp_lr_nthw,
+ rpp_lr->v2.rpp_ifr_rcp[index + i].en);
+ rpp_lr_nthw_ifr_rcp_mtu(be->p_rpp_lr_nthw,
+ rpp_lr->v2.rpp_ifr_rcp[index + i].mtu);
+ rpp_lr_nthw_ifr_rcp_flush(be->p_rpp_lr_nthw);
+ }
+ } else {
+ res = -1;
+ }
+ _CHECK_DEBUG_OFF(rpp_lr, be->p_rpp_lr_nthw);
+ return res;
+}
+
+static int tpe_ifr_rcp_flush(void *be_dev, const struct tpe_func_s *ifr,
+ int index, int cnt)
+{
+ int res = 0;
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, ifr, be->p_ifr_nthw);
+
+ if (ifr->ver >= 2) {
+ ifr_nthw_rcp_cnt(be->p_ifr_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ ifr_nthw_rcp_select(be->p_ifr_nthw, index + i);
+ ifr_nthw_rcp_en(be->p_ifr_nthw,
+ ifr->v2.ifr_rcp[index + i].en);
+ ifr_nthw_rcp_mtu(be->p_ifr_nthw,
+ ifr->v2.ifr_rcp[index + i].mtu);
+ ifr_nthw_rcp_flush(be->p_ifr_nthw);
+ }
+ } else {
+ res = -1;
+ }
+ _CHECK_DEBUG_OFF(ifr, be->p_ifr_nthw);
+ return res;
+}
+
+static int tpe_ins_rcp_flush(void *be_dev, const struct tpe_func_s *tx_ins,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, tx_ins, be->p_tx_ins_nthw);
+
+ if (tx_ins->ver >= 1) {
+ tx_ins_nthw_rcp_cnt(be->p_tx_ins_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ tx_ins_nthw_rcp_select(be->p_tx_ins_nthw, index + i);
+ tx_ins_nthw_rcp_dyn(be->p_tx_ins_nthw,
+ tx_ins->v1.ins_rcp[index + i].dyn);
+ tx_ins_nthw_rcp_ofs(be->p_tx_ins_nthw,
+ tx_ins->v1.ins_rcp[index + i].ofs);
+ tx_ins_nthw_rcp_len(be->p_tx_ins_nthw,
+ tx_ins->v1.ins_rcp[index + i].len);
+ tx_ins_nthw_rcp_flush(be->p_tx_ins_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(tx_ins, be->p_tx_ins_nthw);
+ return 0;
+}
+
+static int tpe_rpl_rcp_flush(void *be_dev, const struct tpe_func_s *tx_rpl,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, tx_rpl, be->p_tx_rpl_nthw);
+
+ if (tx_rpl->ver >= 1) {
+ tx_rpl_nthw_rcp_cnt(be->p_tx_rpl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ tx_rpl_nthw_rcp_select(be->p_tx_rpl_nthw, index + i);
+ tx_rpl_nthw_rcp_dyn(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_rcp[index + i].dyn);
+ tx_rpl_nthw_rcp_ofs(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_rcp[index + i].ofs);
+ tx_rpl_nthw_rcp_len(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_rcp[index + i].len);
+ tx_rpl_nthw_rcp_rpl_ptr(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_rcp[index + i].rpl_ptr);
+ tx_rpl_nthw_rcp_ext_prio(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_rcp[index + i].ext_prio);
+ tx_rpl_nthw_rcp_flush(be->p_tx_rpl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(tx_rpl, be->p_tx_rpl_nthw);
+ return 0;
+}
+
+static int tpe_rpl_ext_flush(void *be_dev, const struct tpe_func_s *tx_rpl,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, tx_rpl, be->p_tx_rpl_nthw);
+
+ if (tx_rpl->ver >= 1) {
+ tx_rpl_nthw_ext_cnt(be->p_tx_rpl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ tx_rpl_nthw_ext_select(be->p_tx_rpl_nthw, index + i);
+ tx_rpl_nthw_ext_rpl_ptr(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_ext[index + i].rpl_ptr);
+ tx_rpl_nthw_ext_flush(be->p_tx_rpl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(tx_rpl, be->p_tx_rpl_nthw);
+ return 0;
+}
+
+static int tpe_rpl_rpl_flush(void *be_dev, const struct tpe_func_s *tx_rpl,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, tx_rpl, be->p_tx_rpl_nthw);
+
+ if (tx_rpl->ver >= 1) {
+ tx_rpl_nthw_rpl_cnt(be->p_tx_rpl_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ tx_rpl_nthw_rpl_select(be->p_tx_rpl_nthw, index + i);
+ tx_rpl_nthw_rpl_value(be->p_tx_rpl_nthw,
+ tx_rpl->v1.rpl_rpl[index + i].value);
+ tx_rpl_nthw_rpl_flush(be->p_tx_rpl_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(tx_rpl, be->p_tx_rpl_nthw);
+ return 0;
+}
+
+static int tpe_cpy_rcp_flush(void *be_dev, const struct tpe_func_s *tx_cpy,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+ unsigned int wr_index = -1;
+
+ _CHECK_DEBUG_ON(be, tx_cpy, be->p_tx_cpy_nthw);
+
+ if (tx_cpy->ver >= 1) {
+ for (int i = 0; i < cnt; i++) {
+ if (wr_index !=
+ (index + i) / tx_cpy->nb_rcp_categories) {
+ wr_index =
+ (index + i) / tx_cpy->nb_rcp_categories;
+ tx_cpy_nthw_writer_cnt(be->p_tx_cpy_nthw, wr_index,
+ 1);
+ }
+
+ tx_cpy_nthw_writer_select(be->p_tx_cpy_nthw, wr_index,
+ (index + i) % tx_cpy->nb_rcp_categories);
+ tx_cpy_nthw_writer_reader_select(be->p_tx_cpy_nthw, wr_index,
+ tx_cpy->v1.cpy_rcp[index + i].reader_select);
+ tx_cpy_nthw_writer_dyn(be->p_tx_cpy_nthw, wr_index,
+ tx_cpy->v1.cpy_rcp[index + i].dyn);
+ tx_cpy_nthw_writer_ofs(be->p_tx_cpy_nthw, wr_index,
+ tx_cpy->v1.cpy_rcp[index + i].ofs);
+ tx_cpy_nthw_writer_len(be->p_tx_cpy_nthw, wr_index,
+ tx_cpy->v1.cpy_rcp[index + i].len);
+ tx_cpy_nthw_writer_flush(be->p_tx_cpy_nthw, wr_index);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(tx_cpy, be->p_tx_cpy_nthw);
+ return 0;
+}
+
+static int tpe_hfu_rcp_flush(void *be_dev, const struct tpe_func_s *hfu,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, hfu, be->p_hfu_nthw);
+
+ if (hfu->ver >= 1) {
+ hfu_nthw_rcp_cnt(be->p_hfu_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ hfu_nthw_rcp_select(be->p_hfu_nthw, index + i);
+ hfu_nthw_rcp_len_a_wr(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_wr);
+ hfu_nthw_rcp_len_a_ol4len(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_outer_l4_len);
+ hfu_nthw_rcp_len_a_pos_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_pos_dyn);
+ hfu_nthw_rcp_len_a_pos_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_pos_ofs);
+ hfu_nthw_rcp_len_a_add_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_add_dyn);
+ hfu_nthw_rcp_len_a_add_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_add_ofs);
+ hfu_nthw_rcp_len_a_sub_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_a_sub_dyn);
+ hfu_nthw_rcp_len_b_wr(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_b_wr);
+ hfu_nthw_rcp_len_b_pos_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_b_pos_dyn);
+ hfu_nthw_rcp_len_b_pos_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_b_pos_ofs);
+ hfu_nthw_rcp_len_b_add_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_b_add_dyn);
+ hfu_nthw_rcp_len_b_add_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_b_add_ofs);
+ hfu_nthw_rcp_len_b_sub_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_b_sub_dyn);
+ hfu_nthw_rcp_len_c_wr(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_c_wr);
+ hfu_nthw_rcp_len_c_pos_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_c_pos_dyn);
+ hfu_nthw_rcp_len_c_pos_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_c_pos_ofs);
+ hfu_nthw_rcp_len_c_add_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_c_add_dyn);
+ hfu_nthw_rcp_len_c_add_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_c_add_ofs);
+ hfu_nthw_rcp_len_c_sub_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].len_c_sub_dyn);
+ hfu_nthw_rcp_ttl_wr(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].ttl_wr);
+ hfu_nthw_rcp_ttl_pos_dyn(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].ttl_pos_dyn);
+ hfu_nthw_rcp_ttl_pos_ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].ttl_pos_ofs);
+ hfu_nthw_rcp_csinf(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].cs_inf);
+ hfu_nthw_rcp_l3prt(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].l3_prt);
+ hfu_nthw_rcp_l3frag(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].l3_frag);
+ hfu_nthw_rcp_tunnel(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].tunnel);
+ hfu_nthw_rcp_l4prt(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].l4_prt);
+ hfu_nthw_rcp_ol3ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].outer_l3_ofs);
+ hfu_nthw_rcp_ol4ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].outer_l4_ofs);
+ hfu_nthw_rcp_il3ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].inner_l3_ofs);
+ hfu_nthw_rcp_il4ofs(be->p_hfu_nthw,
+ hfu->v1.hfu_rcp[index + i].inner_l4_ofs);
+ hfu_nthw_rcp_flush(be->p_hfu_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(hfu, be->p_hfu_nthw);
+ return 0;
+}
+
+static int tpe_csu_rcp_flush(void *be_dev, const struct tpe_func_s *csu,
+ int index, int cnt)
+{
+ struct backend_dev_s *be = (struct backend_dev_s *)be_dev;
+
+ _CHECK_DEBUG_ON(be, csu, be->p_csu_nthw);
+
+ if (csu->ver >= 1) {
+ csu_nthw_rcp_cnt(be->p_csu_nthw, 1);
+ for (int i = 0; i < cnt; i++) {
+ csu_nthw_rcp_select(be->p_csu_nthw, index + i);
+ csu_nthw_rcp_outer_l3_cmd(be->p_csu_nthw,
+ csu->v1.csu_rcp[index + i].ol3_cmd);
+ csu_nthw_rcp_outer_l4_cmd(be->p_csu_nthw,
+ csu->v1.csu_rcp[index + i].ol4_cmd);
+ csu_nthw_rcp_inner_l3_cmd(be->p_csu_nthw,
+ csu->v1.csu_rcp[index + i].il3_cmd);
+ csu_nthw_rcp_inner_l4_cmd(be->p_csu_nthw,
+ csu->v1.csu_rcp[index + i].il4_cmd);
+ csu_nthw_rcp_flush(be->p_csu_nthw);
+ }
+ }
+
+ _CHECK_DEBUG_OFF(csu, be->p_csu_nthw);
+ return 0;
+}
+
+/*
+ * ***************** DBS *******************
+ */
+
+static int alloc_rx_queue(void *be_dev, int queue_id)
+{
+ (void)be_dev;
+ (void)queue_id;
+ printf("ERROR alloc Rx queue\n");
+ return -1;
+}
+
+static int free_rx_queue(void *be_dev, int hw_queue)
+{
+ (void)be_dev;
+ (void)hw_queue;
+ printf("ERROR free Rx queue\n");
+ return 0;
+}
+
+const struct flow_api_backend_ops flow_be_iface = {
+ 1,
+
+ set_debug_mode,
+ get_nb_phy_ports,
+ get_nb_rx_ports,
+ get_ltx_avail,
+ get_nb_cat_funcs,
+ get_nb_categories,
+ get_nb_cat_km_if_cnt,
+ get_nb_cat_km_if_m0,
+ get_nb_cat_km_if_m1,
+ get_nb_queues,
+ get_nb_km_flow_types,
+ get_nb_pm_ext,
+ get_nb_len,
+ get_kcc_size,
+ get_kcc_banks,
+ get_nb_km_categories,
+ get_nb_km_cam_banks,
+ get_nb_km_cam_record_words,
+ get_nb_km_cam_records,
+ get_nb_km_tcam_banks,
+ get_nb_km_tcam_bank_width,
+ get_nb_flm_categories,
+ get_nb_flm_size_mb,
+ get_nb_flm_entry_size,
+ get_nb_flm_variant,
+ get_nb_flm_prios,
+ get_nb_flm_pst_profiles,
+ get_nb_hst_categories,
+ get_nb_qsl_categories,
+ get_nb_qsl_qst_entries,
+ get_nb_pdb_categories,
+ get_nb_ioa_categories,
+ get_nb_roa_categories,
+ get_nb_tpe_categories,
+ get_nb_tx_cpy_writers,
+ get_nb_tx_cpy_mask_mem,
+ get_nb_tx_rpl_depth,
+ get_nb_tx_rpl_ext_categories,
+ get_nb_tpe_ifr_categories,
+
+ alloc_rx_queue,
+ free_rx_queue,
+
+ cat_get_present,
+ cat_get_version,
+ cat_cfn_flush,
+
+ cat_kce_flush,
+ cat_kcs_flush,
+ cat_fte_flush,
+
+ cat_cte_flush,
+ cat_cts_flush,
+ cat_cot_flush,
+ cat_cct_flush,
+ cat_exo_flush,
+ cat_rck_flush,
+ cat_len_flush,
+ cat_kcc_flush,
+ cat_cce_flush,
+ cat_ccs_flush,
+
+ km_get_present,
+ km_get_version,
+ km_rcp_flush,
+ km_cam_flush,
+ km_tcam_flush,
+ km_tci_flush,
+ km_tcq_flush,
+
+ flm_get_present,
+ flm_get_version,
+ flm_control_flush,
+ flm_status_flush,
+ flm_status_update,
+ flm_timeout_flush,
+ flm_scrub_flush,
+ flm_load_bin_flush,
+ flm_load_pps_flush,
+ flm_load_lps_flush,
+ flm_load_aps_flush,
+ flm_prio_flush,
+ flm_pst_flush,
+ flm_rcp_flush,
+ flm_buf_ctrl_update,
+ flm_stat_update,
+ flm_lrn_data_flush,
+ flm_inf_data_update,
+ flm_sta_data_update,
+
+ hsh_get_present,
+ hsh_get_version,
+ hsh_rcp_flush,
+
+ hst_get_present,
+ hst_get_version,
+ hst_rcp_flush,
+
+ qsl_get_present,
+ qsl_get_version,
+ qsl_rcp_flush,
+ qsl_qst_flush,
+ qsl_qen_flush,
+ qsl_unmq_flush,
+
+ slc_get_present,
+ slc_get_version,
+ slc_rcp_flush,
+
+ slc_lr_get_present,
+ slc_lr_get_version,
+ slc_lr_rcp_flush,
+
+ pdb_get_present,
+ pdb_get_version,
+ pdb_rcp_flush,
+ pdb_config_flush,
+
+ ioa_get_present,
+ ioa_get_version,
+ ioa_rcp_flush,
+ ioa_special_tpid_flush,
+ ioa_roa_epp_flush,
+
+ roa_get_present,
+ roa_get_version,
+ roa_tunhdr_flush,
+ roa_tuncfg_flush,
+ roa_config_flush,
+ roa_lagcfg_flush,
+
+ rmc_get_present,
+ rmc_get_version,
+ rmc_ctrl_flush,
+
+ tpe_get_present,
+ tpe_get_version,
+ tpe_rpp_rcp_flush,
+ tpe_rpp_ifr_rcp_flush,
+ tpe_ifr_rcp_flush,
+ tpe_ins_rcp_flush,
+ tpe_rpl_rcp_flush,
+ tpe_rpl_ext_flush,
+ tpe_rpl_rpl_flush,
+ tpe_cpy_rcp_flush,
+ tpe_hfu_rcp_flush,
+ tpe_csu_rcp_flush,
+};
+
+const struct flow_api_backend_ops *bin_flow_backend_init(nt_fpga_t *p_fpga,
+ void **dev)
+{
+ uint8_t physical_adapter_no = (uint8_t)p_fpga->p_fpga_info->adapter_no;
+
+ struct info_nthw *pinfonthw = info_nthw_new();
+
+ info_nthw_init(pinfonthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_info_nthw = pinfonthw;
+
+ /* Init nthw CAT */
+ if (cat_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct cat_nthw *pcatnthw = cat_nthw_new();
+
+ cat_nthw_init(pcatnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_cat_nthw = pcatnthw;
+ } else {
+ be_devs[physical_adapter_no].p_cat_nthw = NULL;
+ }
+ /* Init nthw KM */
+ if (km_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct km_nthw *pkmnthw = km_nthw_new();
+
+ km_nthw_init(pkmnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_km_nthw = pkmnthw;
+ } else {
+ be_devs[physical_adapter_no].p_km_nthw = NULL;
+ }
+ /* Init nthw FLM */
+ if (flm_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct flm_nthw *pflmnthw = flm_nthw_new();
+
+ flm_nthw_init(pflmnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_flm_nthw = pflmnthw;
+ } else {
+ be_devs[physical_adapter_no].p_flm_nthw = NULL;
+ }
+ /* Init nthw IFR */
+ if (ifr_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct ifr_nthw *ifrnthw = ifr_nthw_new();
+
+ ifr_nthw_init(ifrnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_ifr_nthw = ifrnthw;
+ } else {
+ be_devs[physical_adapter_no].p_ifr_nthw = NULL;
+ }
+ /* Init nthw HSH */
+ if (hsh_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct hsh_nthw *phshnthw = hsh_nthw_new();
+
+ hsh_nthw_init(phshnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_hsh_nthw = phshnthw;
+ } else {
+ be_devs[physical_adapter_no].p_hsh_nthw = NULL;
+ }
+ /* Init nthw HST */
+ if (hst_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct hst_nthw *phstnthw = hst_nthw_new();
+
+ hst_nthw_init(phstnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_hst_nthw = phstnthw;
+ } else {
+ be_devs[physical_adapter_no].p_hst_nthw = NULL;
+ }
+ /* Init nthw QSL */
+ if (qsl_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct qsl_nthw *pqslnthw = qsl_nthw_new();
+
+ qsl_nthw_init(pqslnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_qsl_nthw = pqslnthw;
+ } else {
+ be_devs[physical_adapter_no].p_qsl_nthw = NULL;
+ }
+ /* Init nthw SLC */
+ if (slc_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct slc_nthw *pslcnthw = slc_nthw_new();
+
+ slc_nthw_init(pslcnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_slc_nthw = pslcnthw;
+ } else {
+ be_devs[physical_adapter_no].p_slc_nthw = NULL;
+ }
+ /* Init nthw SLC LR */
+ if (slc_lr_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct slc_lr_nthw *pslclrnthw = slc_lr_nthw_new();
+
+ slc_lr_nthw_init(pslclrnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_slc_lr_nthw = pslclrnthw;
+ } else {
+ be_devs[physical_adapter_no].p_slc_lr_nthw = NULL;
+ }
+ /* Init nthw PDB */
+ if (pdb_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct pdb_nthw *ppdbnthw = pdb_nthw_new();
+
+ pdb_nthw_init(ppdbnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_pdb_nthw = ppdbnthw;
+ } else {
+ be_devs[physical_adapter_no].p_pdb_nthw = NULL;
+ }
+ /* Init nthw IOA */
+ if (ioa_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct ioa_nthw *pioanthw = ioa_nthw_new();
+
+ ioa_nthw_init(pioanthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_ioa_nthw = pioanthw;
+ } else {
+ be_devs[physical_adapter_no].p_ioa_nthw = NULL;
+ }
+ /* Init nthw ROA */
+ if (roa_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct roa_nthw *proanthw = roa_nthw_new();
+
+ roa_nthw_init(proanthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_roa_nthw = proanthw;
+ } else {
+ be_devs[physical_adapter_no].p_roa_nthw = NULL;
+ }
+ /* Init nthw RMC */
+ if (rmc_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct rmc_nthw *prmcnthw = rmc_nthw_new();
+
+ rmc_nthw_init(prmcnthw, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_rmc_nthw = prmcnthw;
+ } else {
+ be_devs[physical_adapter_no].p_rmc_nthw = NULL;
+ }
+ /* Init nthw HFU */
+ if (hfu_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct hfu_nthw *ptr = hfu_nthw_new();
+
+ hfu_nthw_init(ptr, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_hfu_nthw = ptr;
+ } else {
+ be_devs[physical_adapter_no].p_hfu_nthw = NULL;
+ }
+ /* Init nthw RPP_LR */
+ if (rpp_lr_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct rpp_lr_nthw *ptr = rpp_lr_nthw_new();
+
+ rpp_lr_nthw_init(ptr, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_rpp_lr_nthw = ptr;
+ } else {
+ be_devs[physical_adapter_no].p_rpp_lr_nthw = NULL;
+ }
+ /* Init nthw TX_CPY */
+ if (tx_cpy_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct tx_cpy_nthw *ptr = tx_cpy_nthw_new();
+
+ tx_cpy_nthw_init(ptr, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_tx_cpy_nthw = ptr;
+ } else {
+ be_devs[physical_adapter_no].p_tx_cpy_nthw = NULL;
+ }
+ /* Init nthw CSU */
+ if (csu_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct csu_nthw *ptr = csu_nthw_new();
+
+ csu_nthw_init(ptr, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_csu_nthw = ptr;
+ } else {
+ be_devs[physical_adapter_no].p_csu_nthw = NULL;
+ }
+ /* Init nthw TX_INS */
+ if (tx_ins_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct tx_ins_nthw *ptr = tx_ins_nthw_new();
+
+ tx_ins_nthw_init(ptr, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_tx_ins_nthw = ptr;
+ } else {
+ be_devs[physical_adapter_no].p_tx_ins_nthw = NULL;
+ }
+ /* Init nthw TX_RPL */
+ if (tx_rpl_nthw_init(NULL, p_fpga, physical_adapter_no) == 0) {
+ struct tx_rpl_nthw *ptr = tx_rpl_nthw_new();
+
+ tx_rpl_nthw_init(ptr, p_fpga, physical_adapter_no);
+ be_devs[physical_adapter_no].p_tx_rpl_nthw = ptr;
+ } else {
+ be_devs[physical_adapter_no].p_tx_rpl_nthw = NULL;
+ }
+ be_devs[physical_adapter_no].adapter_no = physical_adapter_no;
+ *dev = (void *)&be_devs[physical_adapter_no];
+
+ return &flow_be_iface;
+}
+
+void bin_flow_backend_done(void *dev)
+{
+ struct backend_dev_s *be_dev = (struct backend_dev_s *)dev;
+
+ info_nthw_delete(be_dev->p_info_nthw);
+ cat_nthw_delete(be_dev->p_cat_nthw);
+ km_nthw_delete(be_dev->p_km_nthw);
+ flm_nthw_delete(be_dev->p_flm_nthw);
+ hsh_nthw_delete(be_dev->p_hsh_nthw);
+ hst_nthw_delete(be_dev->p_hst_nthw);
+ qsl_nthw_delete(be_dev->p_qsl_nthw);
+ slc_nthw_delete(be_dev->p_slc_nthw);
+ slc_lr_nthw_delete(be_dev->p_slc_lr_nthw);
+ pdb_nthw_delete(be_dev->p_pdb_nthw);
+ ioa_nthw_delete(be_dev->p_ioa_nthw);
+ roa_nthw_delete(be_dev->p_roa_nthw);
+ rmc_nthw_delete(be_dev->p_rmc_nthw);
+ csu_nthw_delete(be_dev->p_csu_nthw);
+ hfu_nthw_delete(be_dev->p_hfu_nthw);
+ rpp_lr_nthw_delete(be_dev->p_rpp_lr_nthw);
+ tx_cpy_nthw_delete(be_dev->p_tx_cpy_nthw);
+ tx_ins_nthw_delete(be_dev->p_tx_ins_nthw);
+ tx_rpl_nthw_delete(be_dev->p_tx_rpl_nthw);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_backend.h b/drivers/net/ntnic/nthw/flow_filter/flow_backend.h
new file mode 100644
index 0000000000..17fdcada3f
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_backend.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_BACKEND_H__
+#define __FLOW_BACKEND_H__
+
+#include <stdint.h> /* uint8_t */
+#include "nthw_fpga_model.h"
+
+const struct flow_api_backend_ops *bin_flow_backend_init(nt_fpga_t *p_fpga,
+ void **be_dev);
+void bin_flow_backend_done(void *be_dev);
+
+#endif /* __FLOW_BACKEND_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_filter.c b/drivers/net/ntnic/nthw/flow_filter/flow_filter.c
new file mode 100644
index 0000000000..90aeb71bd7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_filter.c
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_drv.h"
+#include "flow_filter.h"
+#include "flow_api_backend.h"
+#include "flow_backend.h"
+#include "flow_api_nic_setup.h"
+
+int flow_filter_init(nt_fpga_t *p_fpga, struct flow_nic_dev **p_flow_device,
+ int adapter_no)
+{
+ void *be_dev = NULL;
+ struct flow_nic_dev *flow_nic;
+
+ NT_LOG(DBG, FILTER, "Initializing flow filter api\n");
+ const struct flow_api_backend_ops *iface =
+ bin_flow_backend_init(p_fpga, &be_dev);
+
+ flow_nic = flow_api_create((uint8_t)adapter_no, iface, be_dev);
+ if (!flow_nic) {
+ *p_flow_device = NULL;
+ return -1;
+ }
+ *p_flow_device = flow_nic;
+ return 0;
+}
+
+int flow_filter_done(struct flow_nic_dev *dev)
+{
+ void *be_dev = flow_api_get_be_dev(dev);
+
+ int res = flow_api_done(dev);
+
+ if (be_dev)
+ bin_flow_backend_done(be_dev);
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_filter.h b/drivers/net/ntnic/nthw/flow_filter/flow_filter.h
new file mode 100644
index 0000000000..8ea21a614a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_filter.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_FILTER_HPP__
+#define __FLOW_FILTER_HPP__
+#undef USE_OPAE
+
+#include "nthw_fpga_model.h"
+#include "flow_api.h"
+
+int flow_filter_init(nt_fpga_t *p_fpga, struct flow_nic_dev **p_flow_device,
+ int adapter_no);
+int flow_filter_done(struct flow_nic_dev *dev);
+
+#endif /* __FLOW_FILTER_HPP__ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 7/8] net/ntnic: adds ethdev and makes PMD available
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (4 preceding siblings ...)
2023-08-16 13:25 ` [PATCH 6/8] net/ntnic: adds flow logic Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 13:25 ` [PATCH 8/8] net/ntnic: adds socket connection to PMD Mykola Kostenok
` (14 subsequent siblings)
20 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
Hooks into the DPDK API, and make the PMD available to use.
Also adds documentation as .rst and .ini files.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
.mailmap | 2 +
MAINTAINERS | 7 +
doc/guides/nics/features/ntnic.ini | 56 +
doc/guides/nics/ntnic.rst | 235 +
drivers/net/ntnic/include/ntdrv_4ga.h | 23 +
drivers/net/ntnic/include/ntos_system.h | 23 +
drivers/net/ntnic/meson.build | 13 +
drivers/net/ntnic/ntnic_dbsconfig.c | 1670 +++++++
drivers/net/ntnic/ntnic_dbsconfig.h | 251 +
drivers/net/ntnic/ntnic_ethdev.c | 4258 +++++++++++++++++
drivers/net/ntnic/ntnic_ethdev.h | 357 ++
.../net/ntnic/ntnic_filter/create_elements.h | 1194 +++++
drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 656 +++
drivers/net/ntnic/ntnic_filter/ntnic_filter.h | 14 +
drivers/net/ntnic/ntnic_hshconfig.c | 102 +
drivers/net/ntnic/ntnic_hshconfig.h | 9 +
drivers/net/ntnic/ntnic_meter.c | 811 ++++
drivers/net/ntnic/ntnic_meter.h | 10 +
drivers/net/ntnic/ntnic_vdpa.c | 365 ++
drivers/net/ntnic/ntnic_vdpa.h | 21 +
drivers/net/ntnic/ntnic_vf.c | 83 +
drivers/net/ntnic/ntnic_vf.h | 17 +
drivers/net/ntnic/ntnic_vf_vdpa.c | 1246 +++++
drivers/net/ntnic/ntnic_vf_vdpa.h | 25 +
drivers/net/ntnic/ntnic_vfio.c | 321 ++
drivers/net/ntnic/ntnic_vfio.h | 31 +
drivers/net/ntnic/ntnic_xstats.c | 703 +++
drivers/net/ntnic/ntnic_xstats.h | 22 +
28 files changed, 12525 insertions(+)
create mode 100644 doc/guides/nics/features/ntnic.ini
create mode 100644 doc/guides/nics/ntnic.rst
create mode 100644 drivers/net/ntnic/include/ntdrv_4ga.h
create mode 100644 drivers/net/ntnic/include/ntos_system.h
create mode 100644 drivers/net/ntnic/ntnic_dbsconfig.c
create mode 100644 drivers/net/ntnic/ntnic_dbsconfig.h
create mode 100644 drivers/net/ntnic/ntnic_ethdev.c
create mode 100644 drivers/net/ntnic/ntnic_ethdev.h
create mode 100644 drivers/net/ntnic/ntnic_filter/create_elements.h
create mode 100644 drivers/net/ntnic/ntnic_filter/ntnic_filter.c
create mode 100644 drivers/net/ntnic/ntnic_filter/ntnic_filter.h
create mode 100644 drivers/net/ntnic/ntnic_hshconfig.c
create mode 100644 drivers/net/ntnic/ntnic_hshconfig.h
create mode 100644 drivers/net/ntnic/ntnic_meter.c
create mode 100644 drivers/net/ntnic/ntnic_meter.h
create mode 100644 drivers/net/ntnic/ntnic_vdpa.c
create mode 100644 drivers/net/ntnic/ntnic_vdpa.h
create mode 100644 drivers/net/ntnic/ntnic_vf.c
create mode 100644 drivers/net/ntnic/ntnic_vf.h
create mode 100644 drivers/net/ntnic/ntnic_vf_vdpa.c
create mode 100644 drivers/net/ntnic/ntnic_vf_vdpa.h
create mode 100644 drivers/net/ntnic/ntnic_vfio.c
create mode 100644 drivers/net/ntnic/ntnic_vfio.h
create mode 100644 drivers/net/ntnic/ntnic_xstats.c
create mode 100644 drivers/net/ntnic/ntnic_xstats.h
diff --git a/.mailmap b/.mailmap
index 864d33ee46..be8880971d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -227,6 +227,7 @@ Chintu Hetam <rometoroam@gmail.com>
Choonho Son <choonho.son@gmail.com>
Chris Metcalf <cmetcalf@mellanox.com>
Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Christian Koue Muf <ckm@napatech.com>
Christian Maciocco <christian.maciocco@intel.com>
Christophe Fontaine <cfontain@redhat.com>
Christophe Grosse <christophe.grosse@6wind.com>
@@ -967,6 +968,7 @@ Mukesh Dua <mukesh.dua81@gmail.com>
Murphy Yang <murphyx.yang@intel.com>
Murthy NSSR <nidadavolu.murthy@caviumnetworks.com>
Muthurajan Jayakumar <muthurajan.jayakumar@intel.com>
+Mykola Kostenok <mko-plv@napatech.com>
Nachiketa Prachanda <nprachan@brocade.com> <nprachan@vyatta.att-mail.com>
Nagadheeraj Rottela <rnagadheeraj@marvell.com>
Naga Harish K S V <s.v.naga.harish.k@intel.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index 8c3f2c993f..02aca74173 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1053,6 +1053,13 @@ F: drivers/net/memif/
F: doc/guides/nics/memif.rst
F: doc/guides/nics/features/memif.ini
+NTNIC PMD
+M: Mykola Kostenok <mko-plv@napatech.com>
+M: Christiam Muf <ckm@napatech.com>
+F: drivers/net/ntnic/
+F: doc/guides/nics/ntnic.rst
+F: doc/guides/nics/features/ntnic.ini
+
Crypto Drivers
--------------
diff --git a/doc/guides/nics/features/ntnic.ini b/doc/guides/nics/features/ntnic.ini
new file mode 100644
index 0000000000..7cea4bb9d0
--- /dev/null
+++ b/doc/guides/nics/features/ntnic.ini
@@ -0,0 +1,56 @@
+;
+; Supported features of the 'ntnic' network poll mode driver.
+;
+; Refer to default.ini for the full list of available PMD features.
+;
+[Features]
+Speed capabilities = Y
+Link status = Y
+Queue start/stop = Y
+Shared Rx queue = Y
+MTU update = Y
+Promiscuous mode = Y
+Unicast MAC filter = Y
+Multicast MAC filter = Y
+RSS hash = Y
+RSS key update = Y
+Inner RSS = Y
+CRC offload = Y
+L3 checksum offload = Y
+L4 checksum offload = Y
+Inner L3 checksum = Y
+Inner L4 checksum = Y
+Basic stats = Y
+Extended stats = Y
+FW version = Y
+Linux = Y
+ARMv7 =
+ARMv8 =
+LoongArch64 =
+Power8 =
+rv64 =
+x86-32 =
+x86-64 =
+
+[rte_flow items]
+any = Y
+eth = Y
+gtp = Y
+ipv4 = Y
+ipv6 = Y
+port_id = Y
+sctp = Y
+tcp = Y
+udp = Y
+vlan = Y
+
+[rte_flow actions]
+drop = Y
+jump = Y
+meter = Y
+modify_field = Y
+port_id = Y
+queue = Y
+raw_decap = Y
+raw_encap = Y
+rss = Y
diff --git a/doc/guides/nics/ntnic.rst b/doc/guides/nics/ntnic.rst
new file mode 100644
index 0000000000..85c58543dd
--- /dev/null
+++ b/doc/guides/nics/ntnic.rst
@@ -0,0 +1,235 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright(c) 2023 Napatech A/S
+
+NTNIC Poll Mode Driver
+======================
+
+The NTNIC PMD provides poll mode driver support for Napatech smartNICs.
+
+
+Design
+------
+
+The NTNIC PMD is designed as a pure user-space driver, and requires no special
+Napatech kernel modules.
+
+The Napatech smartNIC presents one control PCI device (PF0). NTNIC PMD accesses
+smartNIC PF0 via vfio-pci kernel driver. Access to PF0 for all purposes is
+exclusive, so only one process should access it. The physical ports are located
+behind PF0 as DPDK port 0 and 1. These ports can be configured with one or more
+TX and RX queues each.
+
+Virtual ports can be added by creating VFs via SR-IOV. The vfio-pci kernel
+driver is bound to the VFs. The VFs implement virtio data plane only and the VF
+configuration is done by NTNIC PMD through PF0. Each VF can be configured with
+one or more TX and RX queue pairs. The VF’s are numbered starting from VF 4.
+The number of VFs is limited by the number of queues supported by the FPGA,
+and the number of queue pairs allocated for each VF. Current FPGA supports 128
+queues in each TX and RX direction. A maximum of 63 VFs is supported (VF4-VF66).
+
+As the Napatech smartNICs supports sensors and monitoring beyond what is
+available in the DPDK API, the PMD includes the ntconnect socket interface.
+ntconnect additionally allows Napatech to implement specific customer requests
+that are not supported by the DPDK API.
+
+
+Supported NICs
+--------------
+
+- NT200A02 2x100G SmartNIC
+
+ - FPGA ID 9563 (Inline Flow Management)
+
+
+Features
+--------
+
+- Multiple TX and RX queues.
+- Scattered and gather for TX and RX.
+- RSS based on VLAN or 5-tuple.
+- RSS using different combinations of fields: L3 only, L4 only or both, and
+ source only, destination only or both.
+- Several RSS hash keys, one for each flow type.
+- Default RSS operation with no hash key specification.
+- VLAN filtering.
+- RX VLAN stripping via raw decap.
+- TX VLAN insertion via raw encap.
+- Hairpin.
+- HW checksum offload of RX and hairpin.
+- Promiscuous mode on PF and VF.
+- Flow API.
+- Multiple process.
+- Tunnel types: GTP.
+- Tunnel HW offload: Packet type, inner/outer RSS, IP and UDP checksum
+ verification.
+- Support for multiple rte_flow groups.
+- Encapsulation and decapsulation of GTP data.
+- Packet modification: NAT, TTL decrement, DSCP tagging
+- Traffic mirroring.
+- Jumbo frame support.
+- Port and queue statistics.
+- RMON statistics in extended stats.
+- Flow metering, including meter policy API.
+- Link state information.
+- CAM and TCAM based matching.
+- Exact match of 140 million flows and policies.
+
+
+Limitations
+~~~~~~~~~~~
+
+Kernel versions before 5.7 are not supported. Kernel version 5.7 added vfio-pci
+support for creating VFs from the PF which is required for the PMD to use
+vfio-pci on the PF. This support has been back-ported to older Linux
+distributions and they are also supported. If vfio-pci is not required kernel
+version 4.18 is supported.
+
+Current NTNIC PMD implementation only supports one active adapter.
+
+
+Configuration
+-------------
+
+Command line arguments
+~~~~~~~~~~~~~~~~~~~~~~
+
+Following standard DPDK command line arguments are used by the PMD:
+
+ -a: Used to specifically define the NT adapter by PCI ID.
+ --iova-mode: Must be set to ‘pa’ for Physical Address mode.
+
+NTNIC specific arguments can be passed to the PMD in the PCI device parameter list::
+
+ <application> ... -a 0000:03:00.0[{,<NTNIC specific argument>}]
+
+The NTNIC specific argument format is::
+
+ <object>.<attribute>=[<object-ids>:]<value>
+
+Multiple arguments for the same device are separated by ‘,’ comma.
+<object-ids> can be a single value or a range.
+
+
+- ``rxqs`` parameter [int]
+
+ Specify number of RX queues to use.
+
+ To specify number of RX queues::
+
+ -a <domain>:<bus>:00.0,rxqs=4,txqs=4
+
+ By default, the value is set to 1.
+
+- ``txqs`` parameter [int]
+
+ Specify number of TX queues to use.
+
+ To specify number of TX queues::
+
+ -a <domain>:<bus>:00.0,rxqs=4,txqs=4
+
+ By default, the value is set to 1.
+
+- ``exception_path`` parameter [int]
+
+ Enable exception path for unmatched packets to go through queue 0.
+
+ To enable exception_path::
+
+ -a <domain>:<bus>:00.0,exception_path=1
+
+ By default, the value is set to 0.
+
+- ``port.link_speed`` parameter [list]
+
+ This parameter is used to set the link speed on physical ports in the format::
+
+ port.link_speed=<port>:<link speed in Mbps>
+
+ To set up link speeds::
+
+ -a <domain>:<bus>:00.0,port.link_speed=0:10000,port.link_speed=1:25000
+
+ By default, set to the maximum corresponding to the NIM bit rate.
+
+- ``supported-fpgas`` parameter [str]
+
+ List the supported FPGAs for a compiled NTNIC DPDK-driver.
+
+ This parameter has two options::
+
+ - list.
+ - verbose.
+
+ Example usages::
+
+ -a <domain>:<bus>:00.0,supported-fpgas=list
+ -a <domain>:<bus>:00.0,supported-fpgas=verbose
+
+- ``help`` parameter [none]
+
+ List all available NTNIC PMD parameters.
+
+
+Build options
+~~~~~~~~~~~~~
+
+- ``NT_TOOLS``
+
+ Define that enables the PMD ntconnect source code.
+
+ Default: Enabled.
+
+- ``NT_VF_VDPA``
+
+ Define that enables the PMD VF VDPA source code.
+
+ Default: Enabled.
+
+- ``NT_RELAY_CORE``
+
+ Define that enables the PMD replay core source code. The relay core is used
+ by Napatech's vSwitch PMD profile in an OVS environment.
+
+ Default: Disabled.
+
+
+Logging and Debugging
+---------------------
+
+NTNIC supports several groups of logging that can be enabled with ``log-level``
+parameter:
+
+- ETHDEV.
+
+ Logging info from the main PMD code. i.e. code that is related to DPDK::
+
+ --log-level=ntnic.ethdev,8
+
+- NTHW.
+
+ Logging info from NTHW. i.e. code that is related to the FPGA and the Adapter::
+
+ --log-level=ntnic.nthw,8
+
+- vDPA.
+
+ Logging info from vDPA. i.e. code that is related to VFIO and vDPA::
+
+ --log-level=ntnic.vdpa,8
+
+- FILTER.
+
+ Logging info from filter. i.e. code that is related to the binary filter::
+
+ --log-level=ntnic.filter,8
+
+- FPGA.
+
+ Logging related to FPGA::
+
+ --log-level=ntnic.fpga,8
+
+To enable logging on all levels use wildcard in the following way::
+
+ --log-level=ntnic.*,8
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
new file mode 100644
index 0000000000..e9c38fc330
--- /dev/null
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTDRV_4GA_H__
+#define __NTDRV_4GA_H__
+
+#include "nthw_drv.h"
+#include "nt4ga_adapter.h"
+#include "nthw_platform_drv.h"
+
+typedef struct ntdrv_4ga_s {
+ uint32_t pciident;
+ struct adapter_info_s adapter_info;
+ char *p_drv_name;
+
+ volatile bool b_shutdown;
+ pthread_mutex_t stat_lck;
+ pthread_t stat_thread;
+ pthread_t flm_thread;
+} ntdrv_4ga_t;
+
+#endif /* __NTDRV_4GA_H__ */
diff --git a/drivers/net/ntnic/include/ntos_system.h b/drivers/net/ntnic/include/ntos_system.h
new file mode 100644
index 0000000000..0adfe86cc3
--- /dev/null
+++ b/drivers/net/ntnic/include/ntos_system.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTOS_SYSTEM_H__
+#define __NTOS_SYSTEM_H__
+
+#include "include/ntdrv_4ga.h"
+
+/*
+ * struct drv_s for DPDK (clone of kernel struct)
+ * keep it as close as possible to original kernel struct
+ */
+struct drv_s {
+ int adapter_no;
+ struct rte_pci_device *p_dev;
+ struct ntdrv_4ga_s ntdrv;
+
+ int n_eth_dev_init_count;
+ int probe_finished;
+};
+
+#endif /* __NTOS_SYSTEM_H__ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index a9892615c9..faaba95af3 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -26,6 +26,9 @@ includes = [
include_directories('sensors/ntavr'),
]
+# deps
+deps += 'vhost'
+
# all sources
sources = files(
'adapter/nt4ga_adapter.c',
@@ -112,6 +115,16 @@ sources = files(
'nthw/nthw_stat.c',
'nthw/supported/nthw_fpga_9563_055_024_0000.c',
'ntlog/ntlog.c',
+ 'ntnic_dbsconfig.c',
+ 'ntnic_ethdev.c',
+ 'ntnic_filter/ntnic_filter.c',
+ 'ntnic_hshconfig.c',
+ 'ntnic_meter.c',
+ 'ntnic_vdpa.c',
+ 'ntnic_vf.c',
+ 'ntnic_vfio.c',
+ 'ntnic_vf_vdpa.c',
+ 'ntnic_xstats.c',
'ntutil/nt_util.c',
'sensors/avr_sensors/avr_sensors.c',
'sensors/board_sensors/board_sensors.c',
diff --git a/drivers/net/ntnic/ntnic_dbsconfig.c b/drivers/net/ntnic/ntnic_dbsconfig.c
new file mode 100644
index 0000000000..2217c163ad
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_dbsconfig.c
@@ -0,0 +1,1670 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h>
+#include <time.h>
+#include <rte_mbuf.h>
+#include <rte_pci.h>
+
+#include "ntdrv_4ga.h"
+#include "nt_util.h"
+#include "ntnic_dbsconfig.h"
+#include "ntnic_ethdev.h"
+#include "ntlog.h"
+
+#define STRUCT_ALIGNMENT (4 * 1024LU)
+#define MAX_VIRT_QUEUES 128
+
+#define LAST_QUEUE 127
+#define DISABLE 0
+#define ENABLE 1
+#define RX_AM_DISABLE DISABLE
+#define RX_AM_ENABLE ENABLE
+#define RX_UW_DISABLE DISABLE
+#define RX_UW_ENABLE ENABLE
+#define RX_Q_DISABLE DISABLE
+#define RX_Q_ENABLE ENABLE
+#define RX_AM_POLL_SPEED 5
+#define RX_UW_POLL_SPEED 9
+#define HOST_ID 0
+#define INIT_QUEUE 1
+
+#define TX_AM_DISABLE DISABLE
+#define TX_AM_ENABLE ENABLE
+#define TX_UW_DISABLE DISABLE
+#define TX_UW_ENABLE ENABLE
+#define TX_Q_DISABLE DISABLE
+#define TX_Q_ENABLE ENABLE
+#define TX_AM_POLL_SPEED 5
+#define TX_UW_POLL_SPEED 8
+
+/**************************************************************************/
+
+#define le64 uint64_t
+#define le32 uint32_t
+#define le16 uint16_t
+
+/**************************************************************************/
+
+#define VIRTQ_AVAIL_F_NO_INTERRUPT 1
+#pragma pack(1)
+struct virtq_avail {
+ le16 flags;
+ le16 idx;
+ le16 ring[]; /* Queue size */
+};
+
+#pragma pack()
+/**************************************************************************/
+
+/* le32 is used here for ids for padding reasons. */
+#pragma pack(1)
+struct virtq_used_elem {
+ /* Index of start of used descriptor chain. */
+ le32 id;
+ /* Total length of the descriptor chain which was used (written to) */
+ le32 len;
+};
+
+#pragma pack()
+
+#define VIRTQ_USED_F_NO_NOTIFY 1
+
+#pragma pack(1)
+struct virtq_used {
+ le16 flags;
+ le16 idx;
+ struct virtq_used_elem ring[]; /* Queue size */
+};
+
+#pragma pack()
+
+struct virtq_struct_layout_s {
+ size_t used_offset;
+ size_t desc_offset;
+};
+
+enum nthw_virt_queue_usage { UNUSED = 0, UNMANAGED, MANAGED };
+
+#define PACKED(vq_type) ((vq_type) == PACKED_RING ? 1 : 0)
+
+struct nthw_virt_queue {
+ /* Pointers to virt-queue structs */
+ union {
+ struct {
+ /* SPLIT virtqueue */
+ struct virtq_avail *p_avail;
+ struct virtq_used *p_used;
+ struct virtq_desc *p_desc;
+ /* Control variables for virt-queue structs */
+ le16 am_idx;
+ le16 used_idx;
+ le16 cached_idx;
+ le16 tx_descr_avail_idx;
+ };
+ struct {
+ /* PACKED virtqueue */
+ struct pvirtq_event_suppress *driver_event;
+ struct pvirtq_event_suppress *device_event;
+ struct pvirtq_desc *desc;
+ struct {
+ le16 next;
+ le16 num;
+ } outs;
+ /*
+ * when in-order release used Tx packets from FPGA it may collapse
+ * into a batch. When getting new Tx buffers we may only need
+ * partial
+ */
+ le16 next_avail;
+ le16 next_used;
+ le16 avail_wrap_count;
+ le16 used_wrap_count;
+ };
+ };
+
+ /* Array with packet buffers */
+ struct nthw_memory_descriptor *p_virtual_addr;
+
+ /* Queue configuration info */
+ enum nthw_virt_queue_usage usage;
+ uint16_t vq_type;
+ uint16_t in_order;
+ int irq_vector;
+
+ nthw_dbs_t *mp_nthw_dbs;
+ uint32_t index;
+ le16 queue_size;
+ uint32_t am_enable;
+ uint32_t host_id;
+ uint32_t port; /* Only used by TX queues */
+ uint32_t virtual_port; /* Only used by TX queues */
+ uint32_t header;
+ /*
+ * Only used by TX queues:
+ * 0: VirtIO-Net header (12 bytes).
+ * 1: Napatech DVIO0 descriptor (12 bytes).
+ */
+ void *avail_struct_phys_addr;
+ void *used_struct_phys_addr;
+ void *desc_struct_phys_addr;
+};
+
+struct pvirtq_struct_layout_s {
+ size_t driver_event_offset;
+ size_t device_event_offset;
+};
+
+static struct nthw_virt_queue rxvq[MAX_VIRT_QUEUES];
+static struct nthw_virt_queue txvq[MAX_VIRT_QUEUES];
+
+static void dbs_init_rx_queue(nthw_dbs_t *p_nthw_dbs, uint32_t queue,
+ uint32_t start_idx, uint32_t start_ptr)
+{
+ uint32_t busy;
+ uint32_t init;
+ uint32_t dummy;
+
+ do {
+ get_rx_init(p_nthw_dbs, &init, &dummy, &busy);
+ } while (busy != 0);
+
+ set_rx_init(p_nthw_dbs, start_idx, start_ptr, INIT_QUEUE, queue);
+
+ do {
+ get_rx_init(p_nthw_dbs, &init, &dummy, &busy);
+ } while (busy != 0);
+}
+
+static void dbs_init_tx_queue(nthw_dbs_t *p_nthw_dbs, uint32_t queue,
+ uint32_t start_idx, uint32_t start_ptr)
+{
+ uint32_t busy;
+ uint32_t init;
+ uint32_t dummy;
+
+ do {
+ get_tx_init(p_nthw_dbs, &init, &dummy, &busy);
+ } while (busy != 0);
+
+ set_tx_init(p_nthw_dbs, start_idx, start_ptr, INIT_QUEUE, queue);
+
+ do {
+ get_tx_init(p_nthw_dbs, &init, &dummy, &busy);
+ } while (busy != 0);
+}
+
+int nthw_virt_queue_init(struct fpga_info_s *p_fpga_info)
+{
+ assert(p_fpga_info);
+
+ nt_fpga_t *const p_fpga = p_fpga_info->mp_fpga;
+ nthw_dbs_t *p_nthw_dbs;
+ int res = 0;
+ uint32_t i;
+
+ p_fpga_info->mp_nthw_dbs = NULL;
+
+ p_nthw_dbs = nthw_dbs_new();
+ if (p_nthw_dbs == NULL)
+ return -1;
+
+ res = dbs_init(NULL, p_fpga, 0); /* Check that DBS exists in FPGA */
+ if (res) {
+ free(p_nthw_dbs);
+ return res;
+ }
+
+ res = dbs_init(p_nthw_dbs, p_fpga, 0); /* Create DBS module */
+ if (res) {
+ free(p_nthw_dbs);
+ return res;
+ }
+
+ p_fpga_info->mp_nthw_dbs = p_nthw_dbs;
+
+ for (i = 0; i < MAX_VIRT_QUEUES; ++i) {
+ rxvq[i].usage = UNUSED;
+ txvq[i].usage = UNUSED;
+ }
+
+ dbs_reset(p_nthw_dbs);
+
+ for (i = 0; i < NT_DBS_RX_QUEUES_MAX; ++i)
+ dbs_init_rx_queue(p_nthw_dbs, i, 0, 0);
+
+ for (i = 0; i < NT_DBS_TX_QUEUES_MAX; ++i)
+ dbs_init_tx_queue(p_nthw_dbs, i, 0, 0);
+
+ set_rx_control(p_nthw_dbs, LAST_QUEUE, RX_AM_DISABLE, RX_AM_POLL_SPEED,
+ RX_UW_DISABLE, RX_UW_POLL_SPEED, RX_Q_DISABLE);
+ set_rx_control(p_nthw_dbs, LAST_QUEUE, RX_AM_ENABLE, RX_AM_POLL_SPEED,
+ RX_UW_ENABLE, RX_UW_POLL_SPEED, RX_Q_DISABLE);
+ set_rx_control(p_nthw_dbs, LAST_QUEUE, RX_AM_ENABLE, RX_AM_POLL_SPEED,
+ RX_UW_ENABLE, RX_UW_POLL_SPEED, RX_Q_ENABLE);
+
+ set_tx_control(p_nthw_dbs, LAST_QUEUE, TX_AM_DISABLE, TX_AM_POLL_SPEED,
+ TX_UW_DISABLE, TX_UW_POLL_SPEED, TX_Q_DISABLE);
+ set_tx_control(p_nthw_dbs, LAST_QUEUE, TX_AM_ENABLE, TX_AM_POLL_SPEED,
+ TX_UW_ENABLE, TX_UW_POLL_SPEED, TX_Q_DISABLE);
+ set_tx_control(p_nthw_dbs, LAST_QUEUE, TX_AM_ENABLE, TX_AM_POLL_SPEED,
+ TX_UW_ENABLE, TX_UW_POLL_SPEED, TX_Q_ENABLE);
+
+ return 0;
+}
+
+static struct virtq_struct_layout_s dbs_calc_struct_layout(uint32_t queue_size)
+{
+ size_t avail_mem =
+ sizeof(struct virtq_avail) +
+ queue_size *
+ sizeof(le16); /* + sizeof(le16); ("avail->used_event" is not used) */
+ size_t avail_mem_aligned =
+ ((avail_mem % STRUCT_ALIGNMENT) == 0) ?
+ avail_mem :
+ STRUCT_ALIGNMENT * (avail_mem / STRUCT_ALIGNMENT + 1);
+
+ /* + sizeof(le16); ("used->avail_event" is not used) */
+ size_t used_mem =
+ sizeof(struct virtq_used) +
+ queue_size *
+ sizeof(struct virtq_used_elem);
+ size_t used_mem_aligned =
+ ((used_mem % STRUCT_ALIGNMENT) == 0) ?
+ used_mem :
+ STRUCT_ALIGNMENT * (used_mem / STRUCT_ALIGNMENT + 1);
+
+ struct virtq_struct_layout_s virtq_layout;
+
+ virtq_layout.used_offset = avail_mem_aligned;
+ virtq_layout.desc_offset = avail_mem_aligned + used_mem_aligned;
+
+ return virtq_layout;
+}
+
+static void dbs_initialize_avail_struct(void *addr, uint16_t queue_size,
+ uint16_t initial_avail_idx)
+{
+ uint16_t i;
+ struct virtq_avail *p_avail = (struct virtq_avail *)addr;
+
+ p_avail->flags = VIRTQ_AVAIL_F_NO_INTERRUPT;
+ p_avail->idx = initial_avail_idx;
+ for (i = 0; i < queue_size; ++i)
+ p_avail->ring[i] = i;
+}
+
+static void dbs_initialize_used_struct(void *addr, uint16_t queue_size)
+{
+ int i;
+ struct virtq_used *p_used = (struct virtq_used *)addr;
+
+ p_used->flags = 1;
+ p_used->idx = 0;
+ for (i = 0; i < queue_size; ++i) {
+ p_used->ring[i].id = 0;
+ p_used->ring[i].len = 0;
+ }
+}
+
+static void dbs_initialize_descriptor_struct(void *addr,
+ struct nthw_memory_descriptor *packet_buffer_descriptors,
+ uint16_t queue_size, ule16 flgs)
+{
+ if (packet_buffer_descriptors) {
+ int i;
+ struct virtq_desc *p_desc = (struct virtq_desc *)addr;
+
+ for (i = 0; i < queue_size; ++i) {
+ p_desc[i].addr =
+ (uint64_t)packet_buffer_descriptors[i].phys_addr;
+ p_desc[i].len = packet_buffer_descriptors[i].len;
+ p_desc[i].flags = flgs;
+ p_desc[i].next = 0;
+ }
+ }
+}
+
+static void dbs_initialize_virt_queue_structs(void *avail_struct_addr,
+ void *used_struct_addr, void *desc_struct_addr,
+ struct nthw_memory_descriptor *packet_buffer_descriptors,
+ uint16_t queue_size, uint16_t initial_avail_idx, ule16 flgs)
+{
+ dbs_initialize_avail_struct(avail_struct_addr, queue_size,
+ initial_avail_idx);
+ dbs_initialize_used_struct(used_struct_addr, queue_size);
+ dbs_initialize_descriptor_struct(desc_struct_addr,
+ packet_buffer_descriptors,
+ queue_size, flgs);
+}
+
+static le16 dbs_qsize_log2(le16 qsize)
+{
+ uint32_t qs = 0;
+
+ while (qsize) {
+ qsize = qsize >> 1;
+ ++qs;
+ }
+ --qs;
+ return qs;
+}
+
+struct nthw_virt_queue *nthw_setup_rx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint16_t start_idx,
+ uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr,
+ void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id,
+ uint32_t header, uint32_t vq_type, int irq_vector)
+{
+ uint32_t qs = dbs_qsize_log2(queue_size);
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+
+ /*
+ * Setup DBS module - DSF00094
+ * 3. Configure the DBS.RX_DR_DATA memory; good idea to initialize all
+ * DBS_RX_QUEUES entries.
+ */
+ if (set_rx_dr_data(p_nthw_dbs, index, (uint64_t)desc_struct_phys_addr,
+ host_id, qs, header, PACKED(vq_type)) != 0)
+ return NULL;
+
+ /*
+ * 4. Configure the DBS.RX_UW_DATA memory; good idea to initialize all
+ * DBS_RX_QUEUES entries.
+ * Notice: We always start out with interrupts disabled (by setting the
+ * "irq_vector" argument to -1). Queues that require interrupts will have
+ * it enabled at a later time (after we have enabled vfio interrupts in
+ * the kernel).
+ */
+ int_enable = 0;
+ vec = 0;
+ istk = 0;
+ NT_LOG(DBG, ETHDEV, "%s: set_rx_uw_data int=0 irq_vector=%u\n",
+ __func__, irq_vector);
+ if (set_rx_uw_data(p_nthw_dbs, index,
+ vq_type == PACKED_RING ? (uint64_t)desc_struct_phys_addr :
+ (uint64_t)used_struct_phys_addr,
+ host_id, qs, PACKED(vq_type), int_enable, vec, istk) != 0)
+ return NULL;
+
+ /*
+ * 2. Configure the DBS.RX_AM_DATA memory and enable the queues you plan to use;
+ * good idea to initialize all DBS_RX_QUEUES entries.
+ * Notice: We do this only for queues that don't require interrupts (i.e. if
+ * irq_vector < 0). Queues that require interrupts will have RX_AM_DATA enabled
+ * at a later time (after we have enabled vfio interrupts in the kernel).
+ */
+ if (irq_vector < 0) {
+ if (set_rx_am_data(p_nthw_dbs, index,
+ (uint64_t)avail_struct_phys_addr, RX_AM_DISABLE,
+ host_id, PACKED(vq_type),
+ irq_vector >= 0 ? 1 : 0) != 0)
+ return NULL;
+ }
+
+ /*
+ * 5. Initialize all RX queues (all DBS_RX_QUEUES of them) using the
+ * DBS.RX_INIT register.
+ */
+ dbs_init_rx_queue(p_nthw_dbs, index, start_idx, start_ptr);
+
+ /*
+ * 2. Configure the DBS.RX_AM_DATA memory and enable the queues you plan to use;
+ * good idea to initialize all DBS_RX_QUEUES entries.
+ */
+ if (set_rx_am_data(p_nthw_dbs, index, (uint64_t)avail_struct_phys_addr,
+ RX_AM_ENABLE, host_id, PACKED(vq_type),
+ irq_vector >= 0 ? 1 : 0) != 0)
+ return NULL;
+
+ /* Save queue state */
+ rxvq[index].usage = UNMANAGED;
+ rxvq[index].mp_nthw_dbs = p_nthw_dbs;
+ rxvq[index].index = index;
+ rxvq[index].queue_size = queue_size;
+ rxvq[index].am_enable = (irq_vector < 0) ? RX_AM_ENABLE : RX_AM_DISABLE;
+ rxvq[index].host_id = host_id;
+ rxvq[index].avail_struct_phys_addr = avail_struct_phys_addr;
+ rxvq[index].used_struct_phys_addr = used_struct_phys_addr;
+ rxvq[index].desc_struct_phys_addr = desc_struct_phys_addr;
+ rxvq[index].vq_type = vq_type;
+ rxvq[index].in_order = 0; /* not used */
+ rxvq[index].irq_vector = irq_vector;
+
+ /* Return queue handle */
+ return &rxvq[index];
+}
+
+static int dbs_wait_hw_queue_shutdown(struct nthw_virt_queue *vq, int rx);
+
+int nthw_disable_rx_virt_queue(struct nthw_virt_queue *rx_vq)
+{
+ if (!rx_vq) {
+ NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__);
+ return -1;
+ }
+
+ nthw_dbs_t *p_nthw_dbs = rx_vq->mp_nthw_dbs;
+
+ if (rx_vq->index >= MAX_VIRT_QUEUES)
+ return -1;
+
+ if (rx_vq->usage != UNMANAGED)
+ return -1;
+
+ uint32_t qs = dbs_qsize_log2(rx_vq->queue_size);
+
+ /* If ISTK is set, make sure to unset it */
+ if (set_rx_uw_data(p_nthw_dbs, rx_vq->index,
+ rx_vq->vq_type == PACKED_RING ?
+ (uint64_t)rx_vq->desc_struct_phys_addr :
+ (uint64_t)rx_vq->used_struct_phys_addr,
+ rx_vq->host_id, qs, PACKED(rx_vq->vq_type), 0, 0,
+ 0) != 0)
+ return -1;
+
+ /* Disable AM */
+ rx_vq->am_enable = RX_AM_DISABLE;
+ if (set_rx_am_data(p_nthw_dbs, rx_vq->index,
+ (uint64_t)rx_vq->avail_struct_phys_addr,
+ rx_vq->am_enable, rx_vq->host_id,
+ PACKED(rx_vq->vq_type), 0) != 0)
+ return -1;
+
+ /* let the FPGA finish packet processing */
+ if (dbs_wait_hw_queue_shutdown(rx_vq, 1) != 0)
+ return -1;
+
+ return 0;
+}
+
+int nthw_enable_rx_virt_queue(struct nthw_virt_queue *rx_vq)
+{
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+
+ if (!rx_vq) {
+ NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__);
+ return -1;
+ }
+
+ nthw_dbs_t *p_nthw_dbs = rx_vq->mp_nthw_dbs;
+
+ if (rx_vq->index >= MAX_VIRT_QUEUES)
+ return -1;
+
+ if (rx_vq->usage != UNMANAGED)
+ return -1;
+
+ uint32_t qs = dbs_qsize_log2(rx_vq->queue_size);
+
+ /* Set ISTK if */
+ if (rx_vq->irq_vector >= 0 &&
+ rx_vq->irq_vector < MAX_MSIX_VECTORS_PR_VF) {
+ int_enable = 1;
+ vec = rx_vq->irq_vector;
+ istk = 1;
+ } else {
+ int_enable = 0;
+ vec = 0;
+ istk = 0;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: set_rx_uw_data irq_vector=%u\n", __func__,
+ rx_vq->irq_vector);
+ if (set_rx_uw_data(p_nthw_dbs, rx_vq->index,
+ rx_vq->vq_type == PACKED_RING ?
+ (uint64_t)rx_vq->desc_struct_phys_addr :
+ (uint64_t)rx_vq->used_struct_phys_addr,
+ rx_vq->host_id, qs, PACKED(rx_vq->vq_type),
+ int_enable, vec, istk) != 0)
+ return -1;
+
+ /* Enable AM */
+ rx_vq->am_enable = RX_AM_ENABLE;
+ if (set_rx_am_data(p_nthw_dbs, rx_vq->index,
+ (uint64_t)rx_vq->avail_struct_phys_addr,
+ rx_vq->am_enable, rx_vq->host_id,
+ PACKED(rx_vq->vq_type),
+ rx_vq->irq_vector >= 0 ? 1 : 0) != 0)
+ return -1;
+
+ return 0;
+}
+
+int nthw_disable_tx_virt_queue(struct nthw_virt_queue *tx_vq)
+{
+ if (!tx_vq) {
+ NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__);
+ return -1;
+ }
+
+ nthw_dbs_t *p_nthw_dbs = tx_vq->mp_nthw_dbs;
+
+ if (tx_vq->index >= MAX_VIRT_QUEUES)
+ return -1;
+
+ if (tx_vq->usage != UNMANAGED)
+ return -1;
+
+ uint32_t qs = dbs_qsize_log2(tx_vq->queue_size);
+
+ /* If ISTK is set, make sure to unset it */
+ if (set_tx_uw_data(p_nthw_dbs, tx_vq->index,
+ tx_vq->vq_type == PACKED_RING ?
+ (uint64_t)tx_vq->desc_struct_phys_addr :
+ (uint64_t)tx_vq->used_struct_phys_addr,
+ tx_vq->host_id, qs, PACKED(tx_vq->vq_type), 0, 0, 0,
+ tx_vq->in_order) != 0)
+ return -1;
+
+ /* Disable AM */
+ tx_vq->am_enable = TX_AM_DISABLE;
+ if (set_tx_am_data(p_nthw_dbs, tx_vq->index,
+ (uint64_t)tx_vq->avail_struct_phys_addr,
+ tx_vq->am_enable, tx_vq->host_id,
+ PACKED(tx_vq->vq_type), 0) != 0)
+ return -1;
+
+ /* let the FPGA finish packet processing */
+ if (dbs_wait_hw_queue_shutdown(tx_vq, 0) != 0)
+ return -1;
+
+ return 0;
+}
+
+int nthw_enable_tx_virt_queue(struct nthw_virt_queue *tx_vq)
+{
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+
+ if (!tx_vq) {
+ NT_LOG(ERR, ETHDEV, "%s: Invalid queue\n", __func__);
+ return -1;
+ }
+
+ nthw_dbs_t *p_nthw_dbs = tx_vq->mp_nthw_dbs;
+
+ if (tx_vq->index >= MAX_VIRT_QUEUES)
+ return -1;
+
+ if (tx_vq->usage != UNMANAGED)
+ return -1;
+
+ uint32_t qs = dbs_qsize_log2(tx_vq->queue_size);
+
+ /* Set ISTK if irq_vector is used */
+ if (tx_vq->irq_vector >= 0 &&
+ tx_vq->irq_vector < MAX_MSIX_VECTORS_PR_VF) {
+ int_enable = 1;
+ vec = tx_vq->irq_vector;
+ istk = 1; /* Use sticky interrupt */
+ } else {
+ int_enable = 0;
+ vec = 0;
+ istk = 0;
+ }
+ if (set_tx_uw_data(p_nthw_dbs, tx_vq->index,
+ tx_vq->vq_type == PACKED_RING ?
+ (uint64_t)tx_vq->desc_struct_phys_addr :
+ (uint64_t)tx_vq->used_struct_phys_addr,
+ tx_vq->host_id, qs, PACKED(tx_vq->vq_type),
+ int_enable, vec, istk, tx_vq->in_order) != 0)
+ return -1;
+
+ /* Enable AM */
+ tx_vq->am_enable = TX_AM_ENABLE;
+ if (set_tx_am_data(p_nthw_dbs, tx_vq->index,
+ (uint64_t)tx_vq->avail_struct_phys_addr,
+ tx_vq->am_enable, tx_vq->host_id,
+ PACKED(tx_vq->vq_type),
+ tx_vq->irq_vector >= 0 ? 1 : 0) != 0)
+ return -1;
+
+ return 0;
+}
+
+int nthw_enable_and_change_port_tx_virt_queue(struct nthw_virt_queue *tx_vq,
+ uint32_t outport)
+{
+ nthw_dbs_t *p_nthw_dbs = tx_vq->mp_nthw_dbs;
+ uint32_t qs = dbs_qsize_log2(tx_vq->queue_size);
+
+ if (set_tx_dr_data(p_nthw_dbs, tx_vq->index,
+ (uint64_t)tx_vq->desc_struct_phys_addr, tx_vq->host_id,
+ qs, outport, 0, PACKED(tx_vq->vq_type)) != 0)
+ return -1;
+ return nthw_enable_tx_virt_queue(tx_vq);
+}
+
+int nthw_set_tx_qos_config(nthw_dbs_t *p_nthw_dbs, uint32_t port, uint32_t enable,
+ uint32_t ir, uint32_t bs)
+{
+ return set_tx_qos_data(p_nthw_dbs, port, enable, ir, bs);
+}
+
+int nthw_set_tx_qos_rate_global(nthw_dbs_t *p_nthw_dbs, uint32_t multiplier,
+ uint32_t divider)
+{
+ return set_tx_qos_rate(p_nthw_dbs, multiplier, divider);
+}
+
+#define INDEX_PTR_NOT_VALID 0x80000000
+static int dbs_get_rx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t *p_index)
+{
+ uint32_t ptr;
+ uint32_t queue;
+ uint32_t valid;
+
+ const int status = get_rx_ptr(p_nthw_dbs, &ptr, &queue, &valid);
+
+ if (status == 0) {
+ if (valid)
+ *p_index = ptr;
+ else
+ *p_index = INDEX_PTR_NOT_VALID;
+ }
+ return status;
+}
+
+static int dbs_get_tx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t *p_index)
+{
+ uint32_t ptr;
+ uint32_t queue;
+ uint32_t valid;
+
+ const int status = get_tx_ptr(p_nthw_dbs, &ptr, &queue, &valid);
+
+ if (status == 0) {
+ if (valid)
+ *p_index = ptr;
+ else
+ *p_index = INDEX_PTR_NOT_VALID;
+ }
+ return status;
+}
+
+static int dbs_initialize_get_rx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t queue)
+{
+ return set_rx_ptr_queue(p_nthw_dbs, queue);
+}
+
+static int dbs_initialize_get_tx_ptr(nthw_dbs_t *p_nthw_dbs, uint32_t queue)
+{
+ return set_tx_ptr_queue(p_nthw_dbs, queue);
+}
+
+static int dbs_wait_on_busy(struct nthw_virt_queue *vq, uint32_t *idle, int rx)
+{
+ uint32_t busy;
+ uint32_t queue;
+ int err = 0;
+ nthw_dbs_t *p_nthw_dbs = vq->mp_nthw_dbs;
+
+ do {
+ if (rx)
+ err = get_rx_idle(p_nthw_dbs, idle, &queue, &busy);
+ else
+ err = get_tx_idle(p_nthw_dbs, idle, &queue, &busy);
+ } while (!err && busy);
+
+ return err;
+}
+
+static int dbs_wait_hw_queue_shutdown(struct nthw_virt_queue *vq, int rx)
+{
+ int err = 0;
+ uint32_t idle = 0;
+ nthw_dbs_t *p_nthw_dbs = vq->mp_nthw_dbs;
+
+ err = dbs_wait_on_busy(vq, &idle, rx);
+ if (err) {
+ if (err == -ENOTSUP) {
+ NT_OS_WAIT_USEC(200000);
+ return 0;
+ }
+ return -1;
+ }
+
+ do {
+ if (rx)
+ err = set_rx_idle(p_nthw_dbs, 1, vq->index);
+ else
+ err = set_tx_idle(p_nthw_dbs, 1, vq->index);
+
+ if (err)
+ return -1;
+
+ if (dbs_wait_on_busy(vq, &idle, rx) != 0)
+ return -1;
+
+ } while (idle == 0);
+
+ return 0;
+}
+
+static int dbs_internal_release_rx_virt_queue(struct nthw_virt_queue *rxvq)
+{
+ nthw_dbs_t *p_nthw_dbs = rxvq->mp_nthw_dbs;
+
+ if (rxvq == NULL)
+ return -1;
+
+ /* Clear UW */
+ rxvq->used_struct_phys_addr = NULL;
+ if (set_rx_uw_data(p_nthw_dbs, rxvq->index,
+ (uint64_t)rxvq->used_struct_phys_addr, rxvq->host_id, 0,
+ PACKED(rxvq->vq_type), 0, 0, 0) != 0)
+ return -1;
+
+ /* Disable AM */
+ rxvq->am_enable = RX_AM_DISABLE;
+ if (set_rx_am_data(p_nthw_dbs, rxvq->index,
+ (uint64_t)rxvq->avail_struct_phys_addr, rxvq->am_enable,
+ rxvq->host_id, PACKED(rxvq->vq_type), 0) != 0)
+ return -1;
+
+ /* Let the FPGA finish packet processing */
+ if (dbs_wait_hw_queue_shutdown(rxvq, 1) != 0)
+ return -1;
+
+ /* Clear rest of AM */
+ rxvq->avail_struct_phys_addr = NULL;
+ rxvq->host_id = 0;
+ if (set_rx_am_data(p_nthw_dbs, rxvq->index,
+ (uint64_t)rxvq->avail_struct_phys_addr, rxvq->am_enable,
+ rxvq->host_id, PACKED(rxvq->vq_type), 0) != 0)
+ return -1;
+
+ /* Clear DR */
+ rxvq->desc_struct_phys_addr = NULL;
+ if (set_rx_dr_data(p_nthw_dbs, rxvq->index,
+ (uint64_t)rxvq->desc_struct_phys_addr, rxvq->host_id, 0,
+ rxvq->header, PACKED(rxvq->vq_type)) != 0)
+ return -1;
+
+ /* Initialize queue */
+ dbs_init_rx_queue(p_nthw_dbs, rxvq->index, 0, 0);
+
+ /* Reset queue state */
+ rxvq->usage = UNUSED;
+ rxvq->mp_nthw_dbs = p_nthw_dbs;
+ rxvq->index = 0;
+ rxvq->queue_size = 0;
+
+ return 0;
+}
+
+int nthw_release_rx_virt_queue(struct nthw_virt_queue *rxvq)
+{
+ if (rxvq == NULL || rxvq->usage != UNMANAGED)
+ return -1;
+
+ return dbs_internal_release_rx_virt_queue(rxvq);
+}
+
+int nthw_release_managed_rx_virt_queue(struct nthw_virt_queue *rxvq)
+{
+ if (rxvq == NULL || rxvq->usage != MANAGED)
+ return -1;
+
+ if (rxvq->p_virtual_addr) {
+ free(rxvq->p_virtual_addr);
+ rxvq->p_virtual_addr = NULL;
+ }
+
+ return dbs_internal_release_rx_virt_queue(rxvq);
+}
+
+static int dbs_internal_release_tx_virt_queue(struct nthw_virt_queue *txvq)
+{
+ nthw_dbs_t *p_nthw_dbs = txvq->mp_nthw_dbs;
+
+ if (txvq == NULL)
+ return -1;
+
+ /* Clear UW */
+ txvq->used_struct_phys_addr = NULL;
+ if (set_tx_uw_data(p_nthw_dbs, txvq->index,
+ (uint64_t)txvq->used_struct_phys_addr, txvq->host_id, 0,
+ PACKED(txvq->vq_type), 0, 0, 0,
+ txvq->in_order) != 0)
+ return -1;
+
+ /* Disable AM */
+ txvq->am_enable = TX_AM_DISABLE;
+ if (set_tx_am_data(p_nthw_dbs, txvq->index,
+ (uint64_t)txvq->avail_struct_phys_addr, txvq->am_enable,
+ txvq->host_id, PACKED(txvq->vq_type), 0) != 0)
+ return -1;
+
+ /* Let the FPGA finish packet processing */
+ if (dbs_wait_hw_queue_shutdown(txvq, 0) != 0)
+ return -1;
+
+ /* Clear rest of AM */
+ txvq->avail_struct_phys_addr = NULL;
+ txvq->host_id = 0;
+ if (set_tx_am_data(p_nthw_dbs, txvq->index,
+ (uint64_t)txvq->avail_struct_phys_addr, txvq->am_enable,
+ txvq->host_id, PACKED(txvq->vq_type), 0) != 0)
+ return -1;
+
+ /* Clear DR */
+ txvq->desc_struct_phys_addr = NULL;
+ txvq->port = 0;
+ txvq->header = 0;
+ if (set_tx_dr_data(p_nthw_dbs, txvq->index,
+ (uint64_t)txvq->desc_struct_phys_addr, txvq->host_id, 0,
+ txvq->port, txvq->header,
+ PACKED(txvq->vq_type)) != 0)
+ return -1;
+
+ /* Clear QP */
+ txvq->virtual_port = 0;
+ if (nthw_dbs_set_tx_qp_data(p_nthw_dbs, txvq->index, txvq->virtual_port) !=
+ 0)
+ return -1;
+
+ /* Initialize queue */
+ dbs_init_tx_queue(p_nthw_dbs, txvq->index, 0, 0);
+
+ /* Reset queue state */
+ txvq->usage = UNUSED;
+ txvq->mp_nthw_dbs = p_nthw_dbs;
+ txvq->index = 0;
+ txvq->queue_size = 0;
+
+ return 0;
+}
+
+int nthw_release_tx_virt_queue(struct nthw_virt_queue *txvq)
+{
+ if (txvq == NULL || txvq->usage != UNMANAGED)
+ return -1;
+
+ return dbs_internal_release_tx_virt_queue(txvq);
+}
+
+int nthw_release_managed_tx_virt_queue(struct nthw_virt_queue *txvq)
+{
+ if (txvq == NULL || txvq->usage != MANAGED)
+ return -1;
+
+ if (txvq->p_virtual_addr) {
+ free(txvq->p_virtual_addr);
+ txvq->p_virtual_addr = NULL;
+ }
+
+ return dbs_internal_release_tx_virt_queue(txvq);
+}
+
+struct nthw_virt_queue *nthw_setup_tx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint16_t start_idx,
+ uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr,
+ void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id,
+ uint32_t port, uint32_t virtual_port, uint32_t header, uint32_t vq_type,
+ int irq_vector, uint32_t in_order)
+{
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+ uint32_t qs = dbs_qsize_log2(queue_size);
+
+ /*
+ * Setup DBS module - DSF00094
+ * 3. Configure the DBS.TX_DR_DATA memory; good idea to initialize all
+ * DBS_TX_QUEUES entries.
+ */
+ if (set_tx_dr_data(p_nthw_dbs, index, (uint64_t)desc_struct_phys_addr,
+ host_id, qs, port, header, PACKED(vq_type)) != 0)
+ return NULL;
+
+ /*
+ * 4. Configure the DBS.TX_UW_DATA memory; good idea to initialize all
+ * DBS_TX_QUEUES entries.
+ * Notice: We always start out with interrupts disabled (by setting the
+ * "irq_vector" argument to -1). Queues that require interrupts will have
+ * it enabled at a later time (after we have enabled vfio interrupts in the
+ * kernel).
+ */
+ int_enable = 0;
+ vec = 0;
+ istk = 0;
+
+ if (set_tx_uw_data(p_nthw_dbs, index,
+ vq_type == PACKED_RING ?
+ (uint64_t)desc_struct_phys_addr :
+ (uint64_t)used_struct_phys_addr,
+ host_id, qs, PACKED(vq_type), int_enable, vec, istk,
+ in_order) != 0)
+ return NULL;
+
+ /*
+ * 2. Configure the DBS.TX_AM_DATA memory and enable the queues you plan to use;
+ * good idea to initialize all DBS_TX_QUEUES entries.
+ */
+ if (set_tx_am_data(p_nthw_dbs, index, (uint64_t)avail_struct_phys_addr,
+ TX_AM_DISABLE, host_id, PACKED(vq_type),
+ irq_vector >= 0 ? 1 : 0) != 0)
+ return NULL;
+
+ /*
+ * 5. Initialize all TX queues (all DBS_TX_QUEUES of them) using the
+ * DBS.TX_INIT register.
+ */
+ dbs_init_tx_queue(p_nthw_dbs, index, start_idx, start_ptr);
+
+ if (nthw_dbs_set_tx_qp_data(p_nthw_dbs, index, virtual_port) != 0)
+ return NULL;
+
+ /*
+ * 2. Configure the DBS.TX_AM_DATA memory and enable the queues you plan to use;
+ * good idea to initialize all DBS_TX_QUEUES entries.
+ * Notice: We do this only for queues that don't require interrupts (i.e. if
+ * irq_vector < 0). Queues that require interrupts will have TX_AM_DATA
+ * enabled at a later time (after we have enabled vfio interrupts in the
+ * kernel).
+ */
+ if (irq_vector < 0) {
+ if (set_tx_am_data(p_nthw_dbs, index,
+ (uint64_t)avail_struct_phys_addr, TX_AM_ENABLE,
+ host_id, PACKED(vq_type),
+ irq_vector >= 0 ? 1 : 0) != 0)
+ return NULL;
+ }
+
+ /* Save queue state */
+ txvq[index].usage = UNMANAGED;
+ txvq[index].mp_nthw_dbs = p_nthw_dbs;
+ txvq[index].index = index;
+ txvq[index].queue_size = queue_size;
+ txvq[index].am_enable = (irq_vector < 0) ? TX_AM_ENABLE : TX_AM_DISABLE;
+ txvq[index].host_id = host_id;
+ txvq[index].port = port;
+ txvq[index].virtual_port = virtual_port;
+ txvq[index].header = header;
+ txvq[index].avail_struct_phys_addr = avail_struct_phys_addr;
+ txvq[index].used_struct_phys_addr = used_struct_phys_addr;
+ txvq[index].desc_struct_phys_addr = desc_struct_phys_addr;
+ txvq[index].vq_type = vq_type;
+ txvq[index].in_order = in_order;
+ txvq[index].irq_vector = irq_vector;
+
+ /* Return queue handle */
+ return &txvq[index];
+}
+
+static struct nthw_virt_queue *nthw_setup_managed_rx_virt_queue_split(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t header,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers, int irq_vector)
+{
+ struct virtq_struct_layout_s virtq_struct_layout =
+ dbs_calc_struct_layout(queue_size);
+
+ dbs_initialize_virt_queue_structs(p_virt_struct_area->virt_addr,
+ (char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.used_offset,
+ (char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.desc_offset,
+ p_packet_buffers, (uint16_t)queue_size,
+ p_packet_buffers ? (uint16_t)queue_size : 0,
+ VIRTQ_DESC_F_WRITE /* Rx */);
+
+ rxvq[index].p_avail = p_virt_struct_area->virt_addr;
+ rxvq[index].p_used = (void *)((char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.used_offset);
+ rxvq[index].p_desc = (void *)((char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.desc_offset);
+
+ rxvq[index].am_idx = p_packet_buffers ? (uint16_t)queue_size : 0;
+ rxvq[index].used_idx = 0;
+ rxvq[index].cached_idx = 0;
+ rxvq[index].p_virtual_addr = NULL;
+
+ if (p_packet_buffers) {
+ rxvq[index].p_virtual_addr =
+ malloc(queue_size * sizeof(*p_packet_buffers));
+ memcpy(rxvq[index].p_virtual_addr, p_packet_buffers,
+ queue_size * sizeof(*p_packet_buffers));
+ }
+
+ nthw_setup_rx_virt_queue(p_nthw_dbs, index, 0, 0,
+ (void *)p_virt_struct_area->phys_addr,
+ (char *)p_virt_struct_area->phys_addr +
+ virtq_struct_layout.used_offset,
+ (char *)p_virt_struct_area->phys_addr +
+ virtq_struct_layout.desc_offset,
+ (uint16_t)queue_size, host_id, header,
+ SPLIT_RING, irq_vector);
+
+ rxvq[index].usage = MANAGED;
+
+ return &rxvq[index];
+}
+
+static struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue_split(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header,
+ int irq_vector, uint32_t in_order,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers)
+{
+ struct virtq_struct_layout_s virtq_struct_layout =
+ dbs_calc_struct_layout(queue_size);
+
+ dbs_initialize_virt_queue_structs(p_virt_struct_area->virt_addr,
+ (char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.used_offset,
+ (char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.desc_offset,
+ p_packet_buffers, (uint16_t)queue_size, 0, 0 /* Tx */);
+
+ txvq[index].p_avail = p_virt_struct_area->virt_addr;
+ txvq[index].p_used = (void *)((char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.used_offset);
+ txvq[index].p_desc = (void *)((char *)p_virt_struct_area->virt_addr +
+ virtq_struct_layout.desc_offset);
+ txvq[index].queue_size = (le16)queue_size;
+ txvq[index].am_idx = 0;
+ txvq[index].used_idx = 0;
+ txvq[index].cached_idx = 0;
+ txvq[index].p_virtual_addr = NULL;
+
+ txvq[index].tx_descr_avail_idx = 0;
+
+ if (p_packet_buffers) {
+ txvq[index].p_virtual_addr =
+ malloc(queue_size * sizeof(*p_packet_buffers));
+ memcpy(txvq[index].p_virtual_addr, p_packet_buffers,
+ queue_size * sizeof(*p_packet_buffers));
+ }
+
+ nthw_setup_tx_virt_queue(p_nthw_dbs, index, 0, 0,
+ (void *)p_virt_struct_area->phys_addr,
+ (char *)p_virt_struct_area->phys_addr +
+ virtq_struct_layout.used_offset,
+ (char *)p_virt_struct_area->phys_addr +
+ virtq_struct_layout.desc_offset,
+ (uint16_t)queue_size, host_id, port, virtual_port,
+ header, SPLIT_RING, irq_vector, in_order);
+
+ txvq[index].usage = MANAGED;
+
+ return &txvq[index];
+}
+
+/*
+ * Packed Ring
+ */
+static int nthw_setup_managed_virt_queue_packed(struct nthw_virt_queue *vq,
+ struct pvirtq_struct_layout_s *pvirtq_layout,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers, ule16 flags, int rx)
+{
+ /* page aligned */
+ assert(((uintptr_t)p_virt_struct_area->phys_addr & 0xfff) == 0);
+ assert(p_packet_buffers);
+
+ /* clean canvas */
+ memset(p_virt_struct_area->virt_addr, 0,
+ sizeof(struct pvirtq_desc) * vq->queue_size +
+ sizeof(struct pvirtq_event_suppress) * 2 +
+ sizeof(int) * vq->queue_size);
+
+ pvirtq_layout->device_event_offset =
+ sizeof(struct pvirtq_desc) * vq->queue_size;
+ pvirtq_layout->driver_event_offset =
+ pvirtq_layout->device_event_offset +
+ sizeof(struct pvirtq_event_suppress);
+
+ vq->desc = p_virt_struct_area->virt_addr;
+ vq->device_event = (void *)((uintptr_t)vq->desc +
+ pvirtq_layout->device_event_offset);
+ vq->driver_event = (void *)((uintptr_t)vq->desc +
+ pvirtq_layout->driver_event_offset);
+
+ vq->next_avail = 0;
+ vq->next_used = 0;
+ vq->avail_wrap_count = 1;
+ vq->used_wrap_count = 1;
+
+ /*
+ * Only possible if FPGA always delivers in-order
+ * Buffer ID used is the index in the pPacketBuffers array
+ */
+ unsigned int i;
+ struct pvirtq_desc *p_desc = vq->desc;
+
+ for (i = 0; i < vq->queue_size; i++) {
+ if (rx) {
+ p_desc[i].addr = (uint64_t)p_packet_buffers[i].phys_addr;
+ p_desc[i].len = p_packet_buffers[i].len;
+ }
+ p_desc[i].id = i;
+ p_desc[i].flags = flags;
+ }
+
+ if (rx)
+ vq->avail_wrap_count ^=
+ 1; /* filled up available buffers for Rx */
+ else
+ vq->used_wrap_count ^= 1; /* pre-fill free buffer IDs */
+
+ if (vq->queue_size == 0)
+ return -1; /* don't allocate memory with size of 0 bytes */
+ vq->p_virtual_addr = malloc(vq->queue_size * sizeof(*p_packet_buffers));
+ if (vq->p_virtual_addr == NULL)
+ return -1;
+
+ memcpy(vq->p_virtual_addr, p_packet_buffers,
+ vq->queue_size * sizeof(*p_packet_buffers));
+
+ /* Not used yet by FPGA - make sure we disable */
+ vq->device_event->flags = RING_EVENT_FLAGS_DISABLE;
+
+ return 0;
+}
+
+static struct nthw_virt_queue *nthw_setup_managed_rx_virt_queue_packed(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t header,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers, int irq_vector)
+{
+ struct pvirtq_struct_layout_s pvirtq_layout;
+ struct nthw_virt_queue *vq = &rxvq[index];
+ /* Set size and setup packed vq ring */
+ vq->queue_size = queue_size;
+ /* Use Avail flag bit == 1 because wrap bit is initially set to 1 - and Used is inverse */
+ if (nthw_setup_managed_virt_queue_packed(vq, &pvirtq_layout,
+ p_virt_struct_area, p_packet_buffers,
+ VIRTQ_DESC_F_WRITE | VIRTQ_DESC_F_AVAIL, 1) != 0)
+ return NULL;
+
+ nthw_setup_rx_virt_queue(p_nthw_dbs, index, 0x8000,
+ 0, /* start wrap ring counter as 1 */
+ (void *)((uintptr_t)p_virt_struct_area->phys_addr +
+ pvirtq_layout.driver_event_offset),
+ (void *)((uintptr_t)p_virt_struct_area->phys_addr +
+ pvirtq_layout.device_event_offset),
+ p_virt_struct_area->phys_addr, (uint16_t)queue_size,
+ host_id, header, PACKED_RING, irq_vector);
+
+ vq->usage = MANAGED;
+ return vq;
+}
+
+static struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue_packed(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header,
+ int irq_vector, uint32_t in_order,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers)
+{
+ struct pvirtq_struct_layout_s pvirtq_layout;
+ struct nthw_virt_queue *vq = &txvq[index];
+ /* Set size and setup packed vq ring */
+ vq->queue_size = queue_size;
+ if (nthw_setup_managed_virt_queue_packed(vq, &pvirtq_layout,
+ p_virt_struct_area,
+ p_packet_buffers, 0, 0) != 0)
+ return NULL;
+
+ nthw_setup_tx_virt_queue(p_nthw_dbs, index, 0x8000,
+ 0, /* start wrap ring counter as 1 */
+ (void *)((uintptr_t)p_virt_struct_area->phys_addr +
+ pvirtq_layout.driver_event_offset),
+ (void *)((uintptr_t)p_virt_struct_area->phys_addr +
+ pvirtq_layout.device_event_offset),
+ p_virt_struct_area->phys_addr, (uint16_t)queue_size,
+ host_id, port, virtual_port, header, PACKED_RING,
+ irq_vector, in_order);
+
+ vq->usage = MANAGED;
+ return vq;
+}
+
+/*
+ * Create a Managed Rx Virt Queue
+ *
+ * p_virt_struct_area - Memory that can be used for virtQueue structs
+ * p_packet_buffers - Memory that can be used for packet buffers. Array must have queue_size entries
+ *
+ * Notice: The queue will be created with interrupts disabled.
+ * If interrupts are required, make sure to call nthw_enable_rx_virt_queue()
+ * afterwards.
+ */
+struct nthw_virt_queue *
+nthw_setup_managed_rx_virt_queue(nthw_dbs_t *p_nthw_dbs, uint32_t index,
+ uint32_t queue_size, uint32_t host_id,
+ uint32_t header,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers,
+ uint32_t vq_type, int irq_vector)
+{
+ switch (vq_type) {
+ case SPLIT_RING:
+ return nthw_setup_managed_rx_virt_queue_split(p_nthw_dbs,
+ index, queue_size, host_id, header,
+ p_virt_struct_area, p_packet_buffers, irq_vector);
+ case PACKED_RING:
+ return nthw_setup_managed_rx_virt_queue_packed(p_nthw_dbs,
+ index, queue_size, host_id, header,
+ p_virt_struct_area, p_packet_buffers, irq_vector);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Create a Managed Tx Virt Queue
+ *
+ * p_virt_struct_area - Memory that can be used for virtQueue structs
+ * p_packet_buffers - Memory that can be used for packet buffers. Array must have queue_size entries
+ *
+ * Notice: The queue will be created with interrupts disabled.
+ * If interrupts are required, make sure to call nthw_enable_tx_virt_queue()
+ * afterwards.
+ */
+struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header,
+ struct nthw_memory_descriptor *p_virt_struct_area,
+ struct nthw_memory_descriptor *p_packet_buffers, uint32_t vq_type,
+ int irq_vector, uint32_t in_order)
+{
+ switch (vq_type) {
+ case SPLIT_RING:
+ return nthw_setup_managed_tx_virt_queue_split(p_nthw_dbs, index,
+ queue_size, host_id, port, virtual_port,
+ header, irq_vector, in_order, p_virt_struct_area,
+ p_packet_buffers);
+ case PACKED_RING:
+ return nthw_setup_managed_tx_virt_queue_packed(p_nthw_dbs, index,
+ queue_size, host_id, port, virtual_port,
+ header, irq_vector, in_order, p_virt_struct_area,
+ p_packet_buffers);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Packed Ring helper macros
+ */
+#define avail_flag(vq) ((vq)->avail_wrap_count ? VIRTQ_DESC_F_AVAIL : 0)
+#define used_flag_inv(vq) ((vq)->avail_wrap_count ? 0 : VIRTQ_DESC_F_USED)
+
+#define inc_avail(_vq, _num) \
+ do { \
+ __typeof__(_vq) (vq) = (_vq); \
+ __typeof__(_num) (num) = (_num); \
+ (vq)->next_avail += num; \
+ if ((vq)->next_avail >= (vq)->queue_size) { \
+ (vq)->next_avail -= (vq)->queue_size; \
+ (vq)->avail_wrap_count ^= 1; \
+ } \
+ } while (0)
+
+#define inc_used(_vq, _num) \
+ do { \
+ __typeof__(_vq) (vq) = (_vq); \
+ __typeof__(_num) (num) = (_num); \
+ (vq)->next_used += num; \
+ if ((vq)->next_used >= (vq)->queue_size) { \
+ (vq)->next_used -= (vq)->queue_size; \
+ (vq)->used_wrap_count ^= 1; \
+ } \
+ } while (0)
+
+uint16_t nthw_get_rx_packets(struct nthw_virt_queue *rxvq, uint16_t n,
+ struct nthw_received_packets *rp, uint16_t *nb_pkts)
+{
+ le16 segs = 0;
+ uint16_t pkts = 0;
+
+ if (rxvq->vq_type == SPLIT_RING) {
+ le16 i;
+ le16 entries_ready = (le16)(rxvq->cached_idx - rxvq->used_idx);
+
+ if (entries_ready < n) {
+ /* Look for more packets */
+ rxvq->cached_idx = rxvq->p_used->idx;
+ entries_ready = (le16)(rxvq->cached_idx - rxvq->used_idx);
+ if (entries_ready == 0) {
+ *nb_pkts = 0;
+ return 0;
+ }
+
+ if (n > entries_ready)
+ n = entries_ready;
+ }
+
+ /* Give packets - make sure all packets are whole packets.
+ * Valid because queue_size is always 2^n
+ */
+ const le16 queue_mask = (le16)(rxvq->queue_size - 1);
+ const ule32 buf_len = rxvq->p_desc[0].len;
+
+ le16 used = rxvq->used_idx;
+
+ for (i = 0; i < n; ++i) {
+ le32 id = rxvq->p_used->ring[used & queue_mask].id;
+
+ rp[i].addr = rxvq->p_virtual_addr[id].virt_addr;
+ rp[i].len = rxvq->p_used->ring[used & queue_mask].len;
+
+ uint32_t pkt_len =
+ ((struct _pkt_hdr_rx *)rp[i].addr)->cap_len;
+
+ if (pkt_len > buf_len) {
+ /* segmented */
+ int nbsegs = (pkt_len + buf_len - 1) / buf_len;
+
+ if (((int)i + nbsegs) > n) {
+ /* don't have enough segments - break out */
+ break;
+ }
+
+ int ii;
+
+ for (ii = 1; ii < nbsegs; ii++) {
+ ++i;
+ id = rxvq->p_used
+ ->ring[(used + ii) &
+ queue_mask]
+ .id;
+ rp[i].addr =
+ rxvq->p_virtual_addr[id].virt_addr;
+ rp[i].len = rxvq->p_used
+ ->ring[(used + ii) &
+ queue_mask]
+ .len;
+ }
+ used += nbsegs;
+ } else {
+ ++used;
+ }
+
+ pkts++;
+ segs = i + 1;
+ }
+
+ rxvq->used_idx = used;
+ } else if (rxvq->vq_type == PACKED_RING) {
+ /* This requires in-order behavior from FPGA */
+ int i;
+
+ for (i = 0; i < n; i++) {
+ struct pvirtq_desc *desc = &rxvq->desc[rxvq->next_used];
+
+ ule16 flags = desc->flags;
+ uint8_t avail = !!(flags & VIRTQ_DESC_F_AVAIL);
+ uint8_t used = !!(flags & VIRTQ_DESC_F_USED);
+
+ if (avail != rxvq->used_wrap_count ||
+ used != rxvq->used_wrap_count)
+ break;
+
+ rp[pkts].addr = rxvq->p_virtual_addr[desc->id].virt_addr;
+ rp[pkts].len = desc->len;
+ pkts++;
+
+ inc_used(rxvq, 1);
+ }
+
+ segs = pkts;
+ }
+
+ *nb_pkts = pkts;
+ return segs;
+}
+
+/*
+ * Put buffers back into Avail Ring
+ */
+void nthw_release_rx_packets(struct nthw_virt_queue *rxvq, le16 n)
+{
+ if (rxvq->vq_type == SPLIT_RING) {
+ rxvq->am_idx = (le16)(rxvq->am_idx + n);
+ rxvq->p_avail->idx = rxvq->am_idx;
+ } else if (rxvq->vq_type == PACKED_RING) {
+ int i;
+ /*
+ * Defer flags update on first segment - due to serialization towards HW and
+ * when jumbo segments are added
+ */
+
+ ule16 first_flags = VIRTQ_DESC_F_WRITE | avail_flag(rxvq) |
+ used_flag_inv(rxvq);
+ struct pvirtq_desc *first_desc = &rxvq->desc[rxvq->next_avail];
+
+ uint32_t len = rxvq->p_virtual_addr[0].len; /* all same size */
+
+ /* Optimization point: use in-order release */
+
+ for (i = 0; i < n; i++) {
+ struct pvirtq_desc *desc =
+ &rxvq->desc[rxvq->next_avail];
+
+ desc->id = rxvq->next_avail;
+ desc->addr =
+ (ule64)rxvq->p_virtual_addr[desc->id].phys_addr;
+ desc->len = len;
+ if (i)
+ desc->flags = VIRTQ_DESC_F_WRITE |
+ avail_flag(rxvq) |
+ used_flag_inv(rxvq);
+
+ inc_avail(rxvq, 1);
+ }
+ rte_rmb();
+ first_desc->flags = first_flags;
+ }
+}
+
+#define vq_log_arg(vq, format, ...)
+
+uint16_t nthw_get_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n,
+ uint16_t *first_idx, struct nthw_cvirtq_desc *cvq,
+ struct nthw_memory_descriptor **p_virt_addr)
+{
+ int m = 0;
+ le16 queue_mask = (le16)(txvq->queue_size -
+ 1); /* Valid because queue_size is always 2^n */
+ *p_virt_addr = txvq->p_virtual_addr;
+
+ if (txvq->vq_type == SPLIT_RING) {
+ cvq->s = txvq->p_desc;
+ cvq->vq_type = SPLIT_RING;
+
+ *first_idx = txvq->tx_descr_avail_idx;
+
+ le16 entries_used =
+ (le16)((txvq->tx_descr_avail_idx - txvq->cached_idx) &
+ queue_mask);
+ le16 entries_ready = (le16)(txvq->queue_size - 1 - entries_used);
+
+ vq_log_arg(txvq,
+ "ask %i: descrAvail %i, cachedidx %i, used: %i, ready %i used->idx %i\n",
+ n, txvq->tx_descr_avail_idx, txvq->cached_idx, entries_used,
+ entries_ready, txvq->p_used->idx);
+
+ if (entries_ready < n) {
+ /*
+ * Look for more packets.
+ * Using the used_idx in the avail ring since they are held synchronous
+ * because of in-order
+ */
+ txvq->cached_idx =
+ txvq->p_avail->ring[(txvq->p_used->idx - 1) &
+ queue_mask];
+
+ vq_log_arg(txvq,
+ "_update: get cachedidx %i (used_idx-1 %i)\n",
+ txvq->cached_idx,
+ (txvq->p_used->idx - 1) & queue_mask);
+ entries_used = (le16)((txvq->tx_descr_avail_idx -
+ txvq->cached_idx) &
+ queue_mask);
+ entries_ready =
+ (le16)(txvq->queue_size - 1 - entries_used);
+ vq_log_arg(txvq, "new used: %i, ready %i\n",
+ entries_used, entries_ready);
+ if (n > entries_ready)
+ n = entries_ready;
+ }
+ } else if (txvq->vq_type == PACKED_RING) {
+ int i;
+
+ cvq->p = txvq->desc;
+ cvq->vq_type = PACKED_RING;
+
+ if (txvq->outs.num) {
+ *first_idx = txvq->outs.next;
+ uint16_t num = RTE_MIN(n, txvq->outs.num);
+
+ txvq->outs.next = (txvq->outs.next + num) & queue_mask;
+ txvq->outs.num -= num;
+
+ if (n == num)
+ return n;
+
+ m = num;
+ n -= num;
+ } else {
+ *first_idx = txvq->next_used;
+ }
+ /* iterate the ring - this requires in-order behavior from FPGA */
+ for (i = 0; i < n; i++) {
+ struct pvirtq_desc *desc = &txvq->desc[txvq->next_used];
+
+ ule16 flags = desc->flags;
+ uint8_t avail = !!(flags & VIRTQ_DESC_F_AVAIL);
+ uint8_t used = !!(flags & VIRTQ_DESC_F_USED);
+
+ if (avail != txvq->used_wrap_count ||
+ used != txvq->used_wrap_count) {
+ n = i;
+ break;
+ }
+
+ le16 incr = (desc->id - txvq->next_used) & queue_mask;
+
+ i += incr;
+ inc_used(txvq, incr + 1);
+ }
+
+ if (i > n) {
+ int outs_num = i - n;
+
+ txvq->outs.next = (txvq->next_used - outs_num) &
+ queue_mask;
+ txvq->outs.num = outs_num;
+ }
+
+ } else {
+ return 0;
+ }
+ return m + n;
+}
+
+void nthw_release_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n,
+ uint16_t n_segs[])
+{
+ int i;
+
+ if (txvq->vq_type == SPLIT_RING) {
+ /* Valid because queue_size is always 2^n */
+ le16 queue_mask = (le16)(txvq->queue_size - 1);
+
+ vq_log_arg(txvq, "pkts %i, avail idx %i, start at %i\n", n,
+ txvq->am_idx, txvq->tx_descr_avail_idx);
+ for (i = 0; i < n; i++) {
+ int idx = txvq->am_idx & queue_mask;
+
+ txvq->p_avail->ring[idx] = txvq->tx_descr_avail_idx;
+ txvq->tx_descr_avail_idx =
+ (txvq->tx_descr_avail_idx + n_segs[i]) & queue_mask;
+ txvq->am_idx++;
+ }
+ /* Make sure the ring has been updated before HW reads index update */
+ rte_mb();
+ txvq->p_avail->idx = txvq->am_idx;
+ vq_log_arg(txvq, "new avail idx %i, descr_idx %i\n",
+ txvq->p_avail->idx, txvq->tx_descr_avail_idx);
+
+ } else if (txvq->vq_type == PACKED_RING) {
+ /*
+ * Defer flags update on first segment - due to serialization towards HW and
+ * when jumbo segments are added
+ */
+
+ ule16 first_flags = avail_flag(txvq) | used_flag_inv(txvq);
+ struct pvirtq_desc *first_desc = &txvq->desc[txvq->next_avail];
+
+ for (i = 0; i < n; i++) {
+ struct pvirtq_desc *desc =
+ &txvq->desc[txvq->next_avail];
+
+ desc->id = txvq->next_avail;
+ desc->addr =
+ (ule64)txvq->p_virtual_addr[desc->id].phys_addr;
+
+ if (i)
+ /* bitwise-or here because next flags may already have been setup */
+ desc->flags |= avail_flag(txvq) |
+ used_flag_inv(txvq);
+
+ inc_avail(txvq, 1);
+ }
+ /* Proper read barrier before FPGA may see first flags */
+ rte_rmb();
+ first_desc->flags = first_flags;
+ }
+}
+
+int nthw_get_rx_queue_ptr(struct nthw_virt_queue *rxvq, uint16_t *index)
+{
+ uint32_t rx_ptr;
+ uint32_t loops = 100000;
+
+ dbs_initialize_get_rx_ptr(rxvq->mp_nthw_dbs, rxvq->index);
+ do {
+ if (dbs_get_rx_ptr(rxvq->mp_nthw_dbs, &rx_ptr) != 0)
+ return -1;
+ if (--loops == 0)
+ return -1;
+ usleep(10);
+ } while (rx_ptr == INDEX_PTR_NOT_VALID);
+
+ *index = (uint16_t)(rx_ptr & 0xffff);
+ return 0;
+}
+
+int nthw_get_tx_queue_ptr(struct nthw_virt_queue *txvq, uint16_t *index)
+{
+ uint32_t tx_ptr;
+ uint32_t loops = 100000;
+
+ dbs_initialize_get_tx_ptr(txvq->mp_nthw_dbs, txvq->index);
+ do {
+ if (dbs_get_tx_ptr(txvq->mp_nthw_dbs, &tx_ptr) != 0)
+ return -1;
+ if (--loops == 0)
+ return -1;
+ usleep(10);
+ } while (tx_ptr == INDEX_PTR_NOT_VALID);
+
+ *index = (uint16_t)(tx_ptr & 0xffff);
+ return 0;
+}
diff --git a/drivers/net/ntnic/ntnic_dbsconfig.h b/drivers/net/ntnic/ntnic_dbsconfig.h
new file mode 100644
index 0000000000..ceae535741
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_dbsconfig.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTNIC_DBS_CONFIG_H
+#define NTNIC_DBS_CONFIG_H
+
+#include <stdint.h>
+#include "nthw_drv.h"
+
+struct nthw_virt_queue;
+
+struct nthw_memory_descriptor {
+ void *phys_addr;
+ void *virt_addr;
+ uint32_t len;
+};
+
+#define ule64 uint64_t
+#define ule32 uint32_t
+#define ule16 uint16_t
+
+#define MAX_MSIX_VECTORS_PR_VF 8
+
+#define SPLIT_RING 0
+#define PACKED_RING 1
+#define IN_ORDER 1
+#define NO_ORDER_REQUIRED 0
+
+/*
+ * SPLIT : This marks a buffer as continuing via the next field.
+ * PACKED: This marks a buffer as continuing. (packed does not have a next field, so must be
+ * contiguous) In Used descriptors it must be ignored
+ */
+#define VIRTQ_DESC_F_NEXT 1
+/*
+ * SPLIT : This marks a buffer as device write-only (otherwise device read-only).
+ * PACKED: This marks a descriptor as device write-only (otherwise device read-only).
+ * PACKED: In a used descriptor, this bit is used to specify whether any data has been written by
+ * the device into any parts of the buffer.
+ */
+#define VIRTQ_DESC_F_WRITE 2
+/*
+ * SPLIT : This means the buffer contains a list of buffer descriptors.
+ * PACKED: This means the element contains a table of descriptors.
+ */
+#define VIRTQ_DESC_F_INDIRECT 4
+
+/*
+ * Split Ring virtq Descriptor
+ */
+#pragma pack(1)
+struct virtq_desc {
+ /* Address (guest-physical). */
+ ule64 addr;
+ /* Length. */
+ ule32 len;
+ /* The flags as indicated above. */
+ ule16 flags;
+ /* Next field if flags & NEXT */
+ ule16 next;
+};
+
+#pragma pack()
+
+/*
+ * Packed Ring special structures and defines
+ *
+ */
+
+#define MAX_PACKED_RING_ELEMENTS (1 << 15) /* 32768 */
+
+/* additional packed ring flags */
+#define VIRTQ_DESC_F_AVAIL (1 << 7)
+#define VIRTQ_DESC_F_USED (1 << 15)
+
+/* descr phys address must be 16 byte aligned */
+#pragma pack(push, 16)
+struct pvirtq_desc {
+ /* Buffer Address. */
+ ule64 addr;
+ /* Buffer Length. */
+ ule32 len;
+ /* Buffer ID. */
+ ule16 id;
+ /* The flags depending on descriptor type. */
+ ule16 flags;
+};
+
+#pragma pack(pop)
+
+/* Enable events */
+#define RING_EVENT_FLAGS_ENABLE 0x0
+/* Disable events */
+#define RING_EVENT_FLAGS_DISABLE 0x1
+/*
+ * Enable events for a specific descriptor
+ * (as specified by Descriptor Ring Change Event offset/Wrap Counter).
+ * Only valid if VIRTIO_F_RING_EVENT_IDX has been negotiated.
+ */
+#define RING_EVENT_FLAGS_DESC 0x2
+/* The value 0x3 is reserved */
+
+struct pvirtq_event_suppress {
+ union {
+ struct {
+ ule16 desc_event_off : 15; /* Descriptor Ring Change Event offset */
+ ule16 desc_event_wrap : 1; /* Descriptor Ring Change Event Wrap Counter */
+ };
+ ule16 desc; /* If desc_event_flags set to RING_EVENT_FLAGS_DESC */
+ };
+
+ /* phys address must be 4 byte aligned */
+#pragma pack(push, 16)
+ union {
+ struct {
+ ule16 desc_event_flags : 2; /* Descriptor Ring Change Event Flags */
+ ule16 reserved : 14; /* Reserved, set to 0 */
+ };
+ ule16 flags;
+ };
+};
+
+#pragma pack(pop)
+
+/*
+ * Common virtq descr
+ */
+#define vq_set_next(_vq, index, nxt) \
+ do { \
+ __typeof__(_vq) (vq) = (_vq); \
+ if ((vq)->vq_type == SPLIT_RING) \
+ (vq)->s[index].next = nxt; \
+ } while (0)
+#define vq_add_flags(_vq, _index, _flgs) \
+ do { \
+ __typeof__(_vq) (vq) = (_vq); \
+ __typeof__(_index) (index) = (_index); \
+ __typeof__(_flgs) (flgs) = (_flgs); \
+ if ((vq)->vq_type == SPLIT_RING) \
+ (vq)->s[index].flags |= flgs; \
+ else if ((vq)->vq_type == PACKED_RING) \
+ (vq)->p[index].flags |= flgs; \
+ } while (0)
+#define vq_set_flags(_vq, _index, _flgs) \
+ do { \
+ __typeof__(_vq) (vq) = (_vq); \
+ __typeof__(_index) (index) = (_index); \
+ __typeof__(_flgs) (flgs) = (_flgs); \
+ if ((vq)->vq_type == SPLIT_RING) \
+ (vq)->s[index].flags = flgs; \
+ else if ((vq)->vq_type == PACKED_RING) \
+ (vq)->p[index].flags = flgs; \
+ } while (0)
+
+struct nthw_virtq_desc_buf {
+ /* Address (guest-physical). */
+ ule64 addr;
+ /* Length. */
+ ule32 len;
+} __rte_aligned(16);
+
+struct nthw_cvirtq_desc {
+ union {
+ struct nthw_virtq_desc_buf *b; /* buffer part as is common */
+ struct virtq_desc *s; /* SPLIT */
+ struct pvirtq_desc *p; /* PACKED */
+ };
+ uint16_t vq_type;
+};
+
+/* Setup a virt_queue for a VM */
+struct nthw_virt_queue *nthw_setup_rx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint16_t start_idx,
+ uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr,
+ void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id,
+ uint32_t header, uint32_t vq_type, int irq_vector);
+
+int nthw_enable_rx_virt_queue(struct nthw_virt_queue *rx_vq);
+int nthw_disable_rx_virt_queue(struct nthw_virt_queue *rx_vq);
+int nthw_release_rx_virt_queue(struct nthw_virt_queue *rxvq);
+
+struct nthw_virt_queue *nthw_setup_tx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint16_t start_idx,
+ uint16_t start_ptr, void *avail_struct_phys_addr, void *used_struct_phys_addr,
+ void *desc_struct_phys_addr, uint16_t queue_size, uint32_t host_id,
+ uint32_t port, uint32_t virtual_port, uint32_t header, uint32_t vq_type,
+ int irq_vector, uint32_t in_order);
+
+int nthw_enable_tx_virt_queue(struct nthw_virt_queue *tx_vq);
+int nthw_disable_tx_virt_queue(struct nthw_virt_queue *tx_vq);
+int nthw_release_tx_virt_queue(struct nthw_virt_queue *txvq);
+int nthw_enable_and_change_port_tx_virt_queue(struct nthw_virt_queue *tx_vq,
+ uint32_t outport);
+
+struct nthw_virt_queue *nthw_setup_managed_rx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t header,
+ struct nthw_memory_descriptor *
+ p_virt_struct_area,
+ struct nthw_memory_descriptor *
+ p_packet_buffers,
+ uint32_t vq_type, int irq_vector);
+
+int nthw_release_managed_rx_virt_queue(struct nthw_virt_queue *rxvq);
+
+struct nthw_virt_queue *nthw_setup_managed_tx_virt_queue(nthw_dbs_t *p_nthw_dbs,
+ uint32_t index, uint32_t queue_size,
+ uint32_t host_id, uint32_t port, uint32_t virtual_port, uint32_t header,
+ struct nthw_memory_descriptor *
+ p_virt_struct_area,
+ struct nthw_memory_descriptor *
+ p_packet_buffers,
+ uint32_t vq_type, int irq_vector, uint32_t in_order);
+
+int nthw_release_managed_tx_virt_queue(struct nthw_virt_queue *txvq);
+
+int nthw_set_tx_qos_config(nthw_dbs_t *p_nthw_dbs, uint32_t port, uint32_t enable,
+ uint32_t ir, uint32_t bs);
+
+int nthw_set_tx_qos_rate_global(nthw_dbs_t *p_nthw_dbs, uint32_t multiplier,
+ uint32_t divider);
+
+struct nthw_received_packets {
+ void *addr;
+ uint32_t len;
+};
+
+/*
+ * These functions handles both Split and Packed including merged buffers (jumbo)
+ */
+uint16_t nthw_get_rx_packets(struct nthw_virt_queue *rxvq, uint16_t n,
+ struct nthw_received_packets *rp,
+ uint16_t *nb_pkts);
+
+void nthw_release_rx_packets(struct nthw_virt_queue *rxvq, uint16_t n);
+
+uint16_t nthw_get_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n,
+ uint16_t *first_idx, struct nthw_cvirtq_desc *cvq,
+ struct nthw_memory_descriptor **p_virt_addr);
+
+void nthw_release_tx_buffers(struct nthw_virt_queue *txvq, uint16_t n,
+ uint16_t n_segs[]);
+
+int nthw_get_rx_queue_ptr(struct nthw_virt_queue *rxvq, uint16_t *index);
+
+int nthw_get_tx_queue_ptr(struct nthw_virt_queue *txvq, uint16_t *index);
+
+int nthw_virt_queue_init(struct fpga_info_s *p_fpga_info);
+
+#endif
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
new file mode 100644
index 0000000000..dd5d4ad918
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -0,0 +1,4258 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h> /* sleep() */
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdatomic.h>
+#include <sys/queue.h>
+
+#include "ntdrv_4ga.h"
+
+#include <rte_common.h>
+#include <rte_kvargs.h>
+#include <rte_interrupts.h>
+#include <rte_byteorder.h>
+#include <rte_debug.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_bus_vdev.h>
+#include <rte_ether.h>
+#include <ethdev_pci.h>
+#include <ethdev_driver.h>
+#include <rte_memory.h>
+#include <rte_eal.h>
+#include <rte_malloc.h>
+#include <rte_dev.h>
+#include <rte_vfio.h>
+#include <rte_flow_driver.h>
+#include <vdpa_driver.h>
+
+#include "ntlog.h"
+
+#include "stream_binary_flow_api.h"
+#include "nthw_fpga.h"
+#include "ntnic_xstats.h"
+#include "ntnic_hshconfig.h"
+#include "ntnic_ethdev.h"
+#include "ntnic_vdpa.h"
+#include "ntnic_vf.h"
+#include "ntnic_vfio.h"
+#include "ntnic_meter.h"
+
+#include "flow_api.h"
+
+#ifdef NT_TOOLS
+#include "ntconnect.h"
+#include "ntconnect_api.h"
+#include "ntconnect_modules/ntconn_modules.h"
+#endif
+
+/* Defines: */
+
+#define HW_MAX_PKT_LEN (10000)
+#define MAX_MTU (HW_MAX_PKT_LEN - RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN)
+#define MIN_MTU 46
+#define MIN_MTU_INLINE 512
+
+#include "ntnic_dbsconfig.h"
+
+#define EXCEPTION_PATH_HID 0
+
+#define MAX_TOTAL_QUEUES 128
+
+#define ONE_G_SIZE 0x40000000
+#define ONE_G_MASK (ONE_G_SIZE - 1)
+
+#define VIRTUAL_TUNNEL_PORT_OFFSET 72
+
+int lag_active;
+
+static struct {
+ struct nthw_virt_queue *vq;
+ int managed;
+ int rx;
+} rel_virt_queue[MAX_REL_VQS];
+
+#define MAX_RX_PACKETS 128
+#define MAX_TX_PACKETS 128
+
+#if defined(RX_SRC_DUMP_PKTS_DEBUG) || defined(RX_DST_DUMP_PKTS_DEBUG) || \
+ defined(TX_SRC_DUMP_PKTS_DEBUG) || defined(TX_DST_DUMP_PKTS_DEBUG)
+static void dump_packet_seg(const char *text, uint8_t *data, int len)
+{
+ int x;
+
+ if (text)
+ printf("%s (%p, len %i)", text, data, len);
+ for (x = 0; x < len; x++) {
+ if (!(x % 16))
+ printf("\n%04X:", x);
+ printf(" %02X", *(data + x));
+ }
+ printf("\n");
+}
+#endif
+
+/* Global statics: */
+extern const struct rte_flow_ops _dev_flow_ops;
+struct pmd_internals *pmd_intern_base;
+uint64_t rte_tsc_freq;
+
+/*------- Tables to store DPDK EAL log levels for nt log modules----------*/
+static int nt_log_module_logtype[NT_LOG_MODULE_COUNT] = { -1 };
+/*Register the custom module binding to EAL --log-level option here*/
+static const char *nt_log_module_eal_name[NT_LOG_MODULE_COUNT] = {
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_GENERAL)] = "pmd.net.ntnic.general",
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_NTHW)] = "pmd.net.ntnic.nthw",
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_FILTER)] = "pmd.net.ntnic.filter",
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_VDPA)] = "pmd.net.ntnic.vdpa",
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_FPGA)] = "pmd.net.ntnic.fpga",
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_NTCONNECT)] =
+ "pmd.net.ntnic.ntconnect",
+ [NT_LOG_MODULE_INDEX(NT_LOG_MODULE_ETHDEV)] = "pmd.net.ntnic.ethdev"
+};
+
+/*--------------------------------------------------------------------------*/
+
+rte_spinlock_t hwlock = RTE_SPINLOCK_INITIALIZER;
+
+static void *lag_management(void *arg);
+static void (*previous_handler)(int sig);
+static pthread_t shutdown_tid;
+int kill_pmd;
+
+#define ETH_DEV_NTNIC_HELP_ARG "help"
+#define ETH_DEV_NTHW_PORTMASK_ARG "portmask"
+#define ETH_DEV_NTHW_RXQUEUES_ARG "rxqs"
+#define ETH_DEV_NTHW_TXQUEUES_ARG "txqs"
+#define ETH_DEV_NTHW_PORTQUEUES_ARG "portqueues"
+#define ETH_DEV_NTHW_REPRESENTOR_ARG "representor"
+#define ETH_DEV_NTHW_EXCEPTION_PATH_ARG "exception_path"
+#define ETH_NTNIC_LAG_PRIMARY_ARG "primary"
+#define ETH_NTNIC_LAG_BACKUP_ARG "backup"
+#define ETH_NTNIC_LAG_MODE_ARG "mode"
+#define ETH_DEV_NTHW_LINK_SPEED_ARG "port.link_speed"
+#define ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG "supported-fpgas"
+
+#define DVIO_VHOST_DIR_NAME "/usr/local/var/run/"
+
+static const char *const valid_arguments[] = {
+ ETH_DEV_NTNIC_HELP_ARG,
+ ETH_DEV_NTHW_PORTMASK_ARG,
+ ETH_DEV_NTHW_RXQUEUES_ARG,
+ ETH_DEV_NTHW_TXQUEUES_ARG,
+ ETH_DEV_NTHW_PORTQUEUES_ARG,
+ ETH_DEV_NTHW_REPRESENTOR_ARG,
+ ETH_DEV_NTHW_EXCEPTION_PATH_ARG,
+ ETH_NTNIC_LAG_PRIMARY_ARG,
+ ETH_NTNIC_LAG_BACKUP_ARG,
+ ETH_NTNIC_LAG_MODE_ARG,
+ ETH_DEV_NTHW_LINK_SPEED_ARG,
+ ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG,
+ NULL,
+};
+
+static struct rte_ether_addr eth_addr_vp[MAX_FPGA_VIRTUAL_PORTS_SUPPORTED];
+
+/* Functions: */
+
+/*
+ * The set of PCI devices this driver supports
+ */
+static const struct rte_pci_id nthw_pci_id_map[] = {
+ { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT200A02) },
+ { RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT50B01) },
+ {
+ .vendor_id = 0,
+ }, /* sentinel */
+};
+
+/*
+ * Store and get adapter info
+ */
+
+static struct drv_s *g_p_drv[NUM_ADAPTER_MAX] = { NULL };
+
+static void store_pdrv(struct drv_s *p_drv)
+{
+ if (p_drv->adapter_no > NUM_ADAPTER_MAX) {
+ NT_LOG(ERR, ETHDEV,
+ "Internal error adapter number %u out of range. Max number of adapters: %u\n",
+ p_drv->adapter_no, NUM_ADAPTER_MAX);
+ return;
+ }
+ if (g_p_drv[p_drv->adapter_no] != 0) {
+ NT_LOG(WRN, ETHDEV,
+ "Overwriting adapter structure for PCI " PCIIDENT_PRINT_STR
+ " with adapter structure for PCI " PCIIDENT_PRINT_STR
+ "\n",
+ PCIIDENT_TO_DOMAIN(g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(g_p_drv[p_drv->adapter_no]->ntdrv.pciident),
+ PCIIDENT_TO_DOMAIN(p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(p_drv->ntdrv.pciident));
+ }
+ rte_spinlock_lock(&hwlock);
+ g_p_drv[p_drv->adapter_no] = p_drv;
+ rte_spinlock_unlock(&hwlock);
+}
+
+static struct drv_s *get_pdrv_from_pci(struct rte_pci_addr addr)
+{
+ int i;
+ struct drv_s *p_drv = NULL;
+
+ rte_spinlock_lock(&hwlock);
+ for (i = 0; i < NUM_ADAPTER_MAX; i++) {
+ if (g_p_drv[i]) {
+ if (PCIIDENT_TO_DOMAIN(g_p_drv[i]->ntdrv.pciident) ==
+ addr.domain &&
+ PCIIDENT_TO_BUSNR(g_p_drv[i]->ntdrv.pciident) ==
+ addr.bus) {
+ p_drv = g_p_drv[i];
+ break;
+ }
+ }
+ }
+ rte_spinlock_unlock(&hwlock);
+ return p_drv;
+}
+
+static struct drv_s *get_pdrv_from_pciident(uint32_t pciident)
+{
+ struct rte_pci_addr addr;
+
+ addr.domain = PCIIDENT_TO_DOMAIN(pciident);
+ addr.bus = PCIIDENT_TO_BUSNR(pciident);
+ addr.devid = PCIIDENT_TO_DEVNR(pciident);
+ addr.function = PCIIDENT_TO_FUNCNR(pciident);
+ return get_pdrv_from_pci(addr);
+}
+
+int debug_adapter_show_info(uint32_t pciident, FILE *pfh)
+{
+ struct drv_s *p_drv = get_pdrv_from_pciident(pciident);
+
+ return nt4ga_adapter_show_info(&p_drv->ntdrv.adapter_info, pfh);
+}
+
+nthw_dbs_t *get_pdbs_from_pci(struct rte_pci_addr pci_addr)
+{
+ nthw_dbs_t *p_nthw_dbs = NULL;
+ struct drv_s *p_drv;
+
+ p_drv = get_pdrv_from_pci(pci_addr);
+ if (p_drv) {
+ p_nthw_dbs = p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_dbs;
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "Adapter DBS %p (p_drv=%p) info for adapter with PCI " PCIIDENT_PRINT_STR
+ " is not found\n",
+ p_nthw_dbs, p_drv, pci_addr.domain, pci_addr.bus, pci_addr.devid,
+ pci_addr.function);
+ }
+ return p_nthw_dbs;
+}
+
+enum fpga_info_profile get_fpga_profile_from_pci(struct rte_pci_addr pci_addr)
+{
+ enum fpga_info_profile fpga_profile = FPGA_INFO_PROFILE_UNKNOWN;
+ struct drv_s *p_drv;
+
+ p_drv = get_pdrv_from_pci(pci_addr);
+ if (p_drv) {
+ fpga_profile = p_drv->ntdrv.adapter_info.fpga_info.profile;
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "FPGA profile (p_drv=%p) for adapter with PCI " PCIIDENT_PRINT_STR
+ " is not found\n",
+ p_drv, pci_addr.domain, pci_addr.bus, pci_addr.devid, pci_addr.function);
+ }
+ return fpga_profile;
+}
+
+static int string_to_u32(const char *key_str __rte_unused,
+ const char *value_str, void *extra_args)
+{
+ if (!value_str || !extra_args)
+ return -1;
+ const uint32_t value = strtol(value_str, NULL, 0);
+ *(uint32_t *)extra_args = value;
+ return 0;
+}
+
+struct port_link_speed {
+ int port_id;
+ int link_speed;
+};
+
+/* Parse <port>:<link speed Mbps>, e.g 1:10000 */
+static int string_to_port_link_speed(const char *key_str __rte_unused,
+ const char *value_str, void *extra_args)
+{
+ if (!value_str || !extra_args)
+ return -1;
+ char *semicol;
+ const uint32_t pid = strtol(value_str, &semicol, 10);
+
+ if (*semicol != ':')
+ return -1;
+ const uint32_t lspeed = strtol(++semicol, NULL, 10);
+ struct port_link_speed *pls = *(struct port_link_speed **)extra_args;
+
+ pls->port_id = pid;
+ pls->link_speed = lspeed;
+ ++(*((struct port_link_speed **)(extra_args)));
+ return 0;
+}
+
+static int dpdk_stats_collect(struct pmd_internals *internals,
+ struct rte_eth_stats *stats)
+{
+ unsigned int i;
+ struct drv_s *p_drv = internals->p_drv;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ const int if_index = internals->if_index;
+ uint64_t rx_total = 0;
+ uint64_t rx_total_b = 0;
+ uint64_t tx_total = 0;
+ uint64_t tx_total_b = 0;
+ uint64_t tx_err_total = 0;
+
+ if (!p_nthw_stat || !p_nt4ga_stat || !stats || if_index < 0 ||
+ if_index > NUM_ADAPTER_PORTS_MAX) {
+ NT_LOG(WRN, ETHDEV, "%s - error exit\n", __func__);
+ return -1;
+ }
+
+ /*
+ * Pull the latest port statistic numbers (Rx/Tx pkts and bytes)
+ * Return values are in the "internals->rxq_scg[]" and "internals->txq_scg[]" arrays
+ */
+ poll_statistics(internals);
+
+ memset(stats, 0, sizeof(*stats));
+ for (i = 0;
+ i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internals->nb_rx_queues;
+ i++) {
+ stats->q_ipackets[i] = internals->rxq_scg[i].rx_pkts;
+ stats->q_ibytes[i] = internals->rxq_scg[i].rx_bytes;
+ rx_total += stats->q_ipackets[i];
+ rx_total_b += stats->q_ibytes[i];
+ }
+
+ for (i = 0;
+ i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internals->nb_tx_queues;
+ i++) {
+ stats->q_opackets[i] = internals->txq_scg[i].tx_pkts;
+ stats->q_obytes[i] = internals->txq_scg[i].tx_bytes;
+ stats->q_errors[i] = internals->txq_scg[i].err_pkts;
+ tx_total += stats->q_opackets[i];
+ tx_total_b += stats->q_obytes[i];
+ tx_err_total += stats->q_errors[i];
+ }
+
+ stats->imissed = internals->rx_missed;
+ stats->ipackets = rx_total;
+ stats->ibytes = rx_total_b;
+ stats->opackets = tx_total;
+ stats->obytes = tx_total_b;
+ stats->oerrors = tx_err_total;
+
+ return 0;
+}
+
+static int dpdk_stats_reset(struct pmd_internals *internals,
+ struct ntdrv_4ga_s *p_nt_drv, int n_intf_no)
+{
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ unsigned int i;
+
+ if (!p_nthw_stat || !p_nt4ga_stat || n_intf_no < 0 ||
+ n_intf_no > NUM_ADAPTER_PORTS_MAX)
+ return -1;
+
+ pthread_mutex_lock(&p_nt_drv->stat_lck);
+
+ /* Rx */
+ for (i = 0; i < internals->nb_rx_queues; i++) {
+ internals->rxq_scg[i].rx_pkts = 0;
+ internals->rxq_scg[i].rx_bytes = 0;
+ internals->rxq_scg[i].err_pkts = 0;
+ }
+
+ internals->rx_missed = 0;
+
+ /* Tx */
+ for (i = 0; i < internals->nb_tx_queues; i++) {
+ internals->txq_scg[i].tx_pkts = 0;
+ internals->txq_scg[i].tx_bytes = 0;
+ internals->txq_scg[i].err_pkts = 0;
+ }
+
+ p_nt4ga_stat->n_totals_reset_timestamp = time(NULL);
+
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+
+ return 0;
+}
+
+/* NOTE: please note the difference between ETH_SPEED_NUM_xxx and ETH_LINK_SPEED_xxx */
+static int nt_link_speed_to_eth_speed_num(enum nt_link_speed_e nt_link_speed)
+{
+ int eth_speed_num = ETH_SPEED_NUM_NONE;
+
+ switch (nt_link_speed) {
+ case NT_LINK_SPEED_10M:
+ eth_speed_num = ETH_SPEED_NUM_10M;
+ break;
+ case NT_LINK_SPEED_100M:
+ eth_speed_num = ETH_SPEED_NUM_100M;
+ break;
+ case NT_LINK_SPEED_1G:
+ eth_speed_num = ETH_SPEED_NUM_1G;
+ break;
+ case NT_LINK_SPEED_10G:
+ eth_speed_num = ETH_SPEED_NUM_10G;
+ break;
+ case NT_LINK_SPEED_25G:
+ eth_speed_num = ETH_SPEED_NUM_25G;
+ break;
+ case NT_LINK_SPEED_40G:
+ eth_speed_num = ETH_SPEED_NUM_40G;
+ break;
+ case NT_LINK_SPEED_50G:
+ eth_speed_num = ETH_SPEED_NUM_50G;
+ break;
+ case NT_LINK_SPEED_100G:
+ eth_speed_num = ETH_SPEED_NUM_100G;
+ break;
+ default:
+ eth_speed_num = ETH_SPEED_NUM_NONE;
+ break;
+ }
+
+ return eth_speed_num;
+}
+
+static int nt_link_duplex_to_eth_duplex(enum nt_link_duplex_e nt_link_duplex)
+{
+ int eth_link_duplex = 0;
+
+ switch (nt_link_duplex) {
+ case NT_LINK_DUPLEX_FULL:
+ eth_link_duplex = ETH_LINK_FULL_DUPLEX;
+ break;
+ case NT_LINK_DUPLEX_HALF:
+ eth_link_duplex = ETH_LINK_HALF_DUPLEX;
+ break;
+ case NT_LINK_DUPLEX_UNKNOWN: /* fall-through */
+ default:
+ break;
+ }
+ return eth_link_duplex;
+}
+
+static int eth_link_update(struct rte_eth_dev *eth_dev,
+ int wait_to_complete __rte_unused)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ const int n_intf_no = internals->if_index;
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+
+ if (eth_dev->data->dev_started) {
+ if (internals->type == PORT_TYPE_VIRTUAL ||
+ internals->type == PORT_TYPE_OVERRIDE) {
+ eth_dev->data->dev_link.link_status =
+ ((internals->vport_comm ==
+ VIRT_PORT_NEGOTIATED_NONE) ?
+ ETH_LINK_DOWN :
+ ETH_LINK_UP);
+ eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+ eth_dev->data->dev_link.link_duplex =
+ ETH_LINK_FULL_DUPLEX;
+ return 0;
+ }
+
+ const bool port_link_status =
+ nt4ga_port_get_link_status(p_adapter_info, n_intf_no);
+ eth_dev->data->dev_link.link_status =
+ port_link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+ nt_link_speed_t port_link_speed =
+ nt4ga_port_get_link_speed(p_adapter_info, n_intf_no);
+ eth_dev->data->dev_link.link_speed =
+ nt_link_speed_to_eth_speed_num(port_link_speed);
+
+ nt_link_duplex_t nt_link_duplex =
+ nt4ga_port_get_link_duplex(p_adapter_info, n_intf_no);
+ eth_dev->data->dev_link.link_duplex =
+ nt_link_duplex_to_eth_duplex(nt_link_duplex);
+ } else {
+ eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+ eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ }
+ return 0;
+}
+
+static int eth_stats_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_stats *stats)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ dpdk_stats_collect(internals, stats);
+ return 0;
+}
+
+static int eth_stats_reset(struct rte_eth_dev *eth_dev)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ const int if_index = internals->if_index;
+
+ dpdk_stats_reset(internals, p_nt_drv, if_index);
+ return 0;
+}
+
+static uint32_t nt_link_speed_capa_to_eth_speed_capa(int nt_link_speed_capa)
+{
+ uint32_t eth_speed_capa = 0;
+
+ if (nt_link_speed_capa & NT_LINK_SPEED_10M)
+ eth_speed_capa |= ETH_LINK_SPEED_10M;
+ if (nt_link_speed_capa & NT_LINK_SPEED_100M)
+ eth_speed_capa |= ETH_LINK_SPEED_100M;
+ if (nt_link_speed_capa & NT_LINK_SPEED_1G)
+ eth_speed_capa |= ETH_LINK_SPEED_1G;
+ if (nt_link_speed_capa & NT_LINK_SPEED_10G)
+ eth_speed_capa |= ETH_LINK_SPEED_10G;
+ if (nt_link_speed_capa & NT_LINK_SPEED_25G)
+ eth_speed_capa |= ETH_LINK_SPEED_25G;
+ if (nt_link_speed_capa & NT_LINK_SPEED_40G)
+ eth_speed_capa |= ETH_LINK_SPEED_40G;
+ if (nt_link_speed_capa & NT_LINK_SPEED_50G)
+ eth_speed_capa |= ETH_LINK_SPEED_50G;
+ if (nt_link_speed_capa & NT_LINK_SPEED_100G)
+ eth_speed_capa |= ETH_LINK_SPEED_100G;
+
+ return eth_speed_capa;
+}
+
+#define RTE_RSS_5TUPLE (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP)
+
+static int eth_dev_infos_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_dev_info *dev_info)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ const int n_intf_no = internals->if_index;
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+
+ dev_info->if_index = internals->if_index;
+ dev_info->driver_name = internals->name;
+ dev_info->max_mac_addrs = NUM_MAC_ADDRS_PER_PORT;
+ dev_info->max_rx_pktlen = HW_MAX_PKT_LEN;
+ dev_info->max_mtu = MAX_MTU;
+ if (p_adapter_info->fpga_info.profile == FPGA_INFO_PROFILE_INLINE)
+ dev_info->min_mtu = MIN_MTU_INLINE;
+
+ else
+ dev_info->min_mtu = MIN_MTU;
+
+ if (internals->p_drv) {
+ dev_info->max_rx_queues = internals->nb_rx_queues;
+ dev_info->max_tx_queues = internals->nb_tx_queues;
+
+ dev_info->min_rx_bufsize = 64;
+
+ const uint32_t nt_port_speed_capa =
+ nt4ga_port_get_link_speed_capabilities(p_adapter_info,
+ n_intf_no);
+ dev_info->speed_capa = nt_link_speed_capa_to_eth_speed_capa(nt_port_speed_capa);
+ }
+
+ dev_info->flow_type_rss_offloads =
+ RTE_RSS_5TUPLE | RTE_ETH_RSS_C_VLAN |
+ RTE_ETH_RSS_LEVEL_INNERMOST | RTE_ETH_RSS_L3_SRC_ONLY |
+ RTE_ETH_RSS_LEVEL_OUTERMOST | RTE_ETH_RSS_L3_DST_ONLY;
+ /*
+ * NT hashing algorithm doesn't use key, so it is just a fake key length to
+ * feet testpmd requirements.
+ */
+ dev_info->hash_key_size = 1;
+
+ return 0;
+}
+
+static inline __rte_always_inline int
+copy_virtqueue_to_mbuf(struct rte_mbuf *mbuf, struct rte_mempool *mb_pool,
+ struct nthw_received_packets *hw_recv, int max_segs,
+ uint16_t data_len)
+{
+ int src_pkt = 0;
+ /*
+ * 1. virtqueue packets may be segmented
+ * 2. the mbuf size may be too small and may need to be segmented
+ */
+ char *data = (char *)hw_recv->addr + SG_HDR_SIZE;
+ char *dst = (char *)mbuf->buf_addr + RTE_PKTMBUF_HEADROOM;
+
+ /* set packet length */
+ mbuf->pkt_len = data_len - SG_HDR_SIZE;
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ void *dbg_src_start = hw_recv->addr;
+ void *dbg_dst_start = dst;
+#endif
+
+ int remain = mbuf->pkt_len;
+ /* First cpy_size is without header */
+ int cpy_size = (data_len > SG_HW_RX_PKT_BUFFER_SIZE) ?
+ SG_HW_RX_PKT_BUFFER_SIZE - SG_HDR_SIZE :
+ remain;
+
+ struct rte_mbuf *m = mbuf; /* if mbuf segmentation is needed */
+
+ while (++src_pkt <= max_segs) {
+ /* keep track of space in dst */
+ int cpto_size = rte_pktmbuf_tailroom(m);
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("src copy size %i\n", cpy_size);
+#endif
+
+ if (cpy_size > cpto_size) {
+ int new_cpy_size = cpto_size;
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("Seg %i: mbuf first cpy src off 0x%" PRIX64 ", dst off 0x%" PRIX64 ", size %i\n",
+ mbuf->nb_segs - 1,
+ (uint64_t)data - (uint64_t)dbg_src_start,
+ (uint64_t)dst - (uint64_t)dbg_dst_start,
+ new_cpy_size);
+#endif
+ rte_memcpy((void *)dst, (void *)data, new_cpy_size);
+ m->data_len += new_cpy_size;
+ remain -= new_cpy_size;
+ cpy_size -= new_cpy_size;
+
+ data += new_cpy_size;
+
+ /*
+ * Loop if remaining data from this virtqueue seg cannot fit in one extra
+ * mbuf
+ */
+ do {
+ m->next = rte_pktmbuf_alloc(mb_pool);
+ if (unlikely(!m->next))
+ return -1;
+ m = m->next;
+
+ /* Headroom is not needed in chained mbufs */
+ rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m));
+ dst = (char *)m->buf_addr;
+ m->data_len = 0;
+ m->pkt_len = 0;
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ dbg_dst_start = dst;
+#endif
+ cpto_size = rte_pktmbuf_tailroom(m);
+
+ int actual_cpy_size = (cpy_size > cpto_size) ?
+ cpto_size :
+ cpy_size;
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("new dst mbuf seg - size %i\n",
+ cpto_size);
+ printf("Seg %i: mbuf cpy src off 0x%" PRIX64 ", dst off 0x%" PRIX64 ", size %i\n",
+ mbuf->nb_segs,
+ (uint64_t)data - (uint64_t)dbg_src_start,
+ (uint64_t)dst - (uint64_t)dbg_dst_start,
+ actual_cpy_size);
+#endif
+
+ rte_memcpy((void *)dst, (void *)data,
+ actual_cpy_size);
+ m->pkt_len += actual_cpy_size;
+ m->data_len += actual_cpy_size;
+
+ remain -= actual_cpy_size;
+ cpy_size -= actual_cpy_size;
+
+ data += actual_cpy_size;
+
+ mbuf->nb_segs++;
+
+ } while (cpy_size && remain);
+
+ } else {
+ /* all data from this virtqueue segment can fit in current mbuf */
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("Copy all into Seg %i: %i bytes, src off 0x%" PRIX64
+ ", dst off 0x%" PRIX64 "\n",
+ mbuf->nb_segs - 1, cpy_size,
+ (uint64_t)data - (uint64_t)dbg_src_start,
+ (uint64_t)dst - (uint64_t)dbg_dst_start);
+#endif
+ rte_memcpy((void *)dst, (void *)data, cpy_size);
+ m->data_len += cpy_size;
+ if (mbuf->nb_segs > 1)
+ m->pkt_len += cpy_size;
+ remain -= cpy_size;
+ }
+
+ /* packet complete - all data from current virtqueue packet has been copied */
+ if (remain == 0)
+ break;
+ /* increment dst to data end */
+ dst = rte_pktmbuf_mtod_offset(m, char *, m->data_len);
+ /* prepare for next virtqueue segment */
+ data = (char *)hw_recv[src_pkt]
+ .addr; /* following packets are full data */
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ dbg_src_start = data;
+#endif
+ cpy_size = (remain > SG_HW_RX_PKT_BUFFER_SIZE) ?
+ SG_HW_RX_PKT_BUFFER_SIZE :
+ remain;
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("next src buf\n");
+#endif
+ };
+
+ if (src_pkt > max_segs) {
+ NT_LOG(ERR, ETHDEV,
+ "Did not receive correct number of segment for a whole packet");
+ return -1;
+ }
+
+ return src_pkt;
+}
+
+static uint16_t eth_dev_rx_scg(void *queue, struct rte_mbuf **bufs,
+ uint16_t nb_pkts)
+{
+ unsigned int i;
+ struct rte_mbuf *mbuf;
+ struct ntnic_rx_queue *rx_q = queue;
+ uint16_t num_rx = 0;
+
+ struct nthw_received_packets hw_recv[MAX_RX_PACKETS];
+
+ if (kill_pmd)
+ return 0;
+
+#ifdef DEBUG_PRINT_APPROX_CPU_LOAD
+ dbg_print_approx_cpu_load_rx_called(rx_q->port);
+#endif
+
+ if (unlikely(nb_pkts == 0))
+ return 0;
+
+ if (nb_pkts > MAX_RX_PACKETS)
+ nb_pkts = MAX_RX_PACKETS;
+
+ uint16_t whole_pkts;
+ uint16_t hw_recv_pkt_segs =
+ nthw_get_rx_packets(rx_q->vq, nb_pkts, hw_recv, &whole_pkts);
+
+ if (!hw_recv_pkt_segs) {
+#ifdef DEBUG_PRINT_APPROX_CPU_LOAD
+ dbg_print_approx_cpu_load_rx_done(rx_q->port, 0);
+#endif
+
+ return 0;
+ }
+
+#ifdef NT_DEBUG_STAT
+ dbg_rx_queue(rx_q,
+ hw_recv_pkt_segs); /* _update debug statistics with new rx packet count */
+#endif
+
+ nb_pkts = whole_pkts;
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("\n---------- DPDK Rx ------------\n");
+ printf("[Port %i] Pkts recv %i on hw queue index %i: tot segs %i, "
+ "vq buf %i, vq header size %i\n",
+ rx_q->port, nb_pkts, rx_q->queue.hw_id, hw_recv_pkt_segs,
+ SG_HW_RX_PKT_BUFFER_SIZE, SG_HDR_SIZE);
+#endif
+
+ int src_pkt = 0; /* from 0 to hw_recv_pkt_segs */
+
+ for (i = 0; i < nb_pkts; i++) {
+ bufs[i] = rte_pktmbuf_alloc(rx_q->mb_pool);
+ if (!bufs[i]) {
+ printf("ERROR - no more buffers mbuf in mempool\n");
+ goto err_exit;
+ }
+ mbuf = bufs[i];
+
+ struct _pkt_hdr_rx *phdr =
+ (struct _pkt_hdr_rx *)hw_recv[src_pkt].addr;
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("\nRx pkt #%i: vq pkt len %i, segs %i -> mbuf size %i, headroom size %i\n",
+ i, phdr->cap_len - SG_HDR_SIZE,
+ (phdr->cap_len + SG_HW_RX_PKT_BUFFER_SIZE - 1) /
+ SG_HW_RX_PKT_BUFFER_SIZE,
+ rte_pktmbuf_tailroom(mbuf), rte_pktmbuf_headroom(mbuf));
+#endif
+
+#ifdef RX_SRC_DUMP_PKTS_DEBUG
+ {
+ int d, _segs = (phdr->cap_len +
+ SG_HW_RX_PKT_BUFFER_SIZE - 1) /
+ SG_HW_RX_PKT_BUFFER_SIZE;
+ int _size = phdr->cap_len;
+
+ printf("Rx packet dump: pkt #%i hdr rx port %i, pkt len %i, segs %i\n",
+ i, phdr->port, phdr->cap_len - SG_HDR_SIZE,
+ _segs);
+ for (d = 0; d < _segs; d++) {
+ printf("Dump seg %i:\n", d);
+ dump_packet_seg("Vq seg:", hw_recv[src_pkt + d].addr,
+ _size > SG_HW_RX_PKT_BUFFER_SIZE ?
+ SG_HW_RX_PKT_BUFFER_SIZE :
+ _size);
+ _size -= SG_HW_RX_PKT_BUFFER_SIZE;
+ }
+ }
+#endif
+
+ if (phdr->cap_len < SG_HDR_SIZE) {
+ printf("Pkt len of zero received. No header!! - dropping packets\n");
+ rte_pktmbuf_free(mbuf);
+ goto err_exit;
+ }
+
+ {
+ if (phdr->cap_len <= SG_HW_RX_PKT_BUFFER_SIZE &&
+ (phdr->cap_len - SG_HDR_SIZE) <=
+ rte_pktmbuf_tailroom(mbuf)) {
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ printf("Simple copy vq -> mbuf %p size %i\n",
+ rte_pktmbuf_mtod(mbuf, void *),
+ phdr->cap_len);
+#endif
+ mbuf->data_len = phdr->cap_len - SG_HDR_SIZE;
+ rte_memcpy(rte_pktmbuf_mtod(mbuf, char *),
+ (char *)hw_recv[src_pkt].addr +
+ SG_HDR_SIZE,
+ mbuf->data_len);
+
+ mbuf->pkt_len = mbuf->data_len;
+ src_pkt++;
+ } else {
+ int cpy_segs = copy_virtqueue_to_mbuf(mbuf, rx_q->mb_pool,
+ &hw_recv[src_pkt],
+ hw_recv_pkt_segs - src_pkt,
+ phdr->cap_len);
+ if (cpy_segs < 0) {
+ /* Error */
+ rte_pktmbuf_free(mbuf);
+ goto err_exit;
+ }
+ src_pkt += cpy_segs;
+ }
+
+#ifdef RX_DST_DUMP_PKTS_DEBUG
+ {
+ struct rte_mbuf *m = mbuf;
+
+ printf("\nRx final mbuf:\n");
+ for (int ii = 0; m && ii < m->nb_segs; ii++) {
+ printf(" seg %i len %i\n", ii,
+ m->data_len);
+ printf(" seg dump:\n");
+ dump_packet_seg("mbuf seg:",
+ rte_pktmbuf_mtod(m, uint8_t *),
+ m->data_len);
+ m = m->next;
+ }
+ }
+#endif
+
+ num_rx++;
+
+ mbuf->ol_flags &=
+ ~(RTE_MBUF_F_RX_FDIR_ID | RTE_MBUF_F_RX_FDIR);
+ mbuf->port = (uint16_t)-1;
+
+ if (phdr->color_type == 0) {
+ if (phdr->port >= VIRTUAL_TUNNEL_PORT_OFFSET &&
+ ((phdr->color >> 24) == 0x02)) {
+ /* VNI in color of descriptor add port as well */
+ mbuf->hash.fdir.hi =
+ ((uint32_t)phdr->color &
+ 0xffffff) |
+ ((uint32_t)phdr->port
+ << 24);
+ mbuf->hash.fdir.lo =
+ (uint32_t)phdr->fid;
+ mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR_ID;
+
+ NT_LOG(DBG, ETHDEV,
+ "POP'ed packet received that missed on inner match. color = %08x, port %i, tunnel-match flow stat id %i",
+ phdr->color, phdr->port,
+ phdr->fid);
+ }
+
+ } else {
+ if (phdr->color) {
+ mbuf->hash.fdir.hi =
+ phdr->color &
+ (NT_MAX_COLOR_FLOW_STATS - 1);
+ mbuf->ol_flags |=
+ RTE_MBUF_F_RX_FDIR_ID |
+ RTE_MBUF_F_RX_FDIR;
+ }
+ }
+ }
+ }
+
+err_exit:
+ nthw_release_rx_packets(rx_q->vq, hw_recv_pkt_segs);
+
+#ifdef DEBUG_PRINT_APPROX_CPU_LOAD
+ dbg_print_approx_cpu_load_rx_done(rx_q->port, num_rx);
+#endif
+
+#ifdef RX_MERGE_SEGMENT_DEBUG
+ /*
+ * When the application double frees a mbuf, it will become a doublet in the memory pool
+ * This is obvious a bug in application, but can be verified here to some extend at least
+ */
+ uint64_t addr = (uint64_t)bufs[0]->buf_addr;
+
+ for (int i = 1; i < num_rx; i++) {
+ if (bufs[i]->buf_addr == addr) {
+ printf("Duplicate packet addresses! num_rx %i\n",
+ num_rx);
+ for (int ii = 0; ii < num_rx; ii++) {
+ printf("bufs[%i]->buf_addr %p\n", ii,
+ bufs[ii]->buf_addr);
+ }
+ }
+ }
+#endif
+
+ return num_rx;
+}
+
+int copy_mbuf_to_virtqueue(struct nthw_cvirtq_desc *cvq_desc,
+ uint16_t vq_descr_idx,
+ struct nthw_memory_descriptor *vq_bufs, int max_segs,
+ struct rte_mbuf *mbuf)
+{
+ /*
+ * 1. mbuf packet may be segmented
+ * 2. the virtqueue buffer size may be too small and may need to be segmented
+ */
+
+ char *data = rte_pktmbuf_mtod(mbuf, char *);
+ char *dst = (char *)vq_bufs[vq_descr_idx].virt_addr + SG_HDR_SIZE;
+
+ int remain = mbuf->pkt_len;
+ int cpy_size = mbuf->data_len;
+
+#ifdef CPY_MBUF_TO_VQUEUE_DEBUG
+ printf("src copy size %i\n", cpy_size);
+#endif
+
+ struct rte_mbuf *m = mbuf;
+ int cpto_size = SG_HW_TX_PKT_BUFFER_SIZE - SG_HDR_SIZE;
+
+ cvq_desc->b[vq_descr_idx].len = SG_HDR_SIZE;
+
+ int cur_seg_num = 0; /* start from 0 */
+
+ while (m) {
+ /* Can all data in current src segment be in current dest segment */
+ if (cpy_size > cpto_size) {
+ int new_cpy_size = cpto_size;
+
+#ifdef CPY_MBUF_TO_VQUEUE_DEBUG
+ printf("Seg %i: virtq buf first cpy src offs %u, dst offs 0x%" PRIX64 ", size %i\n",
+ cur_seg_num,
+ (uint64_t)data - rte_pktmbuf_mtod(m, uint64_t),
+ (uint64_t)dst -
+ (uint64_t)vq_bufs[vq_descr_idx].virt_addr,
+ new_cpy_size);
+#endif
+ rte_memcpy((void *)dst, (void *)data, new_cpy_size);
+
+ cvq_desc->b[vq_descr_idx].len += new_cpy_size;
+
+ remain -= new_cpy_size;
+ cpy_size -= new_cpy_size;
+
+ data += new_cpy_size;
+
+ /*
+ * Loop if remaining data from this virtqueue seg cannot fit in one extra
+ * mbuf
+ */
+ do {
+ vq_add_flags(cvq_desc, vq_descr_idx,
+ VIRTQ_DESC_F_NEXT);
+
+ int next_vq_descr_idx =
+ VIRTQ_DESCR_IDX_NEXT(vq_descr_idx);
+
+ vq_set_next(cvq_desc, vq_descr_idx,
+ next_vq_descr_idx);
+
+ vq_descr_idx = next_vq_descr_idx;
+
+ vq_set_flags(cvq_desc, vq_descr_idx, 0);
+ vq_set_next(cvq_desc, vq_descr_idx, 0);
+
+ if (++cur_seg_num > max_segs)
+ break;
+
+ dst = (char *)vq_bufs[vq_descr_idx].virt_addr;
+ cpto_size = SG_HW_TX_PKT_BUFFER_SIZE;
+
+ int actual_cpy_size = (cpy_size > cpto_size) ?
+ cpto_size :
+ cpy_size;
+#ifdef CPY_MBUF_TO_VQUEUE_DEBUG
+ printf("Tx vq buf seg %i: virtq cpy %i - offset 0x%" PRIX64 "\n",
+ cur_seg_num, actual_cpy_size,
+ (uint64_t)dst -
+ (uint64_t)vq_bufs[vq_descr_idx]
+ .virt_addr);
+#endif
+ rte_memcpy((void *)dst, (void *)data,
+ actual_cpy_size);
+
+ cvq_desc->b[vq_descr_idx].len = actual_cpy_size;
+
+ remain -= actual_cpy_size;
+ cpy_size -= actual_cpy_size;
+ cpto_size -= actual_cpy_size;
+
+ data += actual_cpy_size;
+
+ } while (cpy_size && remain);
+
+ } else {
+ /* All data from this segment can fit in current virtqueue buffer */
+#ifdef CPY_MBUF_TO_VQUEUE_DEBUG
+ printf("Tx vq buf seg %i: Copy %i bytes - offset %u\n",
+ cur_seg_num, cpy_size,
+ (uint64_t)dst -
+ (uint64_t)vq_bufs[vq_descr_idx].virt_addr);
+#endif
+
+ rte_memcpy((void *)dst, (void *)data, cpy_size);
+
+ cvq_desc->b[vq_descr_idx].len += cpy_size;
+
+ remain -= cpy_size;
+ cpto_size -= cpy_size;
+ }
+
+ /* Packet complete - all segments from current mbuf has been copied */
+ if (remain == 0)
+ break;
+ /* increment dst to data end */
+ dst = (char *)vq_bufs[vq_descr_idx].virt_addr +
+ cvq_desc->b[vq_descr_idx].len;
+
+ m = m->next;
+ if (!m) {
+ NT_LOG(ERR, ETHDEV, "ERROR: invalid packet size\n");
+ break;
+ }
+
+ /* Prepare for next mbuf segment */
+ data = rte_pktmbuf_mtod(m, char *);
+ cpy_size = m->data_len;
+ };
+
+ cur_seg_num++;
+ if (cur_seg_num > max_segs) {
+ NT_LOG(ERR, ETHDEV,
+ "Did not receive correct number of segment for a whole packet");
+ return -1;
+ }
+
+ return cur_seg_num;
+}
+
+static uint16_t eth_dev_tx_scg(void *queue, struct rte_mbuf **bufs,
+ uint16_t nb_pkts)
+{
+ uint16_t pkt;
+ uint16_t first_vq_descr_idx = 0;
+
+ struct nthw_cvirtq_desc cvq_desc;
+
+ struct nthw_memory_descriptor *vq_bufs;
+
+ struct ntnic_tx_queue *tx_q = queue;
+
+ int nb_segs = 0, i;
+ int pkts_sent = 0;
+ uint16_t nb_segs_arr[MAX_TX_PACKETS];
+
+ if (kill_pmd)
+ return 0;
+
+ if (nb_pkts > MAX_TX_PACKETS)
+ nb_pkts = MAX_TX_PACKETS;
+
+#ifdef TX_CHAINING_DEBUG
+ printf("\n---------- DPDK Tx ------------\n");
+#endif
+
+ /*
+ * count all segments needed to contain all packets in vq buffers
+ */
+ for (i = 0; i < nb_pkts; i++) {
+ if (bufs[i]->pkt_len < 60) {
+ bufs[i]->pkt_len = 60;
+ bufs[i]->data_len = 60;
+ }
+
+ /* build the num segments array for segmentation control and release function */
+ int vq_segs = NUM_VQ_SEGS(bufs[i]->pkt_len);
+
+ nb_segs_arr[i] = vq_segs;
+ nb_segs += vq_segs;
+ }
+ if (!nb_segs)
+ goto exit_out;
+
+#ifdef TX_CHAINING_DEBUG
+ printf("[Port %i] Mbufs for Tx: tot segs %i, packets %i, mbuf size %i, headroom size %i\n",
+ tx_q->port, nb_segs, nb_pkts,
+ bufs[0]->buf_len - rte_pktmbuf_headroom(bufs[0]),
+ rte_pktmbuf_headroom(bufs[0]));
+#endif
+
+ int got_nb_segs =
+ nthw_get_tx_buffers(tx_q->vq, nb_segs, &first_vq_descr_idx,
+ &cvq_desc /*&vq_descr,*/, &vq_bufs);
+ if (!got_nb_segs) {
+#ifdef TX_CHAINING_DEBUG
+ printf("Zero segments got - back pressure from HW\n");
+#endif
+ goto exit_out;
+ }
+
+ /*
+ * we may get less vq buffers than we have asked for
+ * calculate last whole packet that can fit into what
+ * we have got
+ */
+ while (got_nb_segs < nb_segs) {
+ if (!--nb_pkts)
+ goto exit_out;
+ nb_segs -= NUM_VQ_SEGS(bufs[nb_pkts]->pkt_len);
+ if (nb_segs <= 0)
+ goto exit_out;
+ }
+
+ /*
+ * nb_pkts & nb_segs, got it all, ready to copy
+ */
+ int seg_idx = 0;
+ int last_seg_idx = seg_idx;
+
+ for (pkt = 0; pkt < nb_pkts; ++pkt) {
+ uint16_t vq_descr_idx = VIRTQ_DESCR_IDX(seg_idx);
+
+ vq_set_flags(&cvq_desc, vq_descr_idx, 0);
+ vq_set_next(&cvq_desc, vq_descr_idx, 0);
+
+ struct _pkt_hdr_tx *hdr_tx =
+ (struct _pkt_hdr_tx *)vq_bufs[vq_descr_idx].virt_addr;
+ /* Set the header to all zeros */
+ memset(hdr_tx, 0, SG_HDR_SIZE);
+
+ /*
+ * Set the NT DVIO0 header fields
+ *
+ * Applicable for Vswitch only.
+ * For other product types the header values are "don't care" and we leave them as
+ * all zeros.
+ */
+ if (tx_q->profile == FPGA_INFO_PROFILE_VSWITCH) {
+ hdr_tx->bypass_port = tx_q->target_id;
+
+ /* set packet length */
+ hdr_tx->cap_len = bufs[pkt]->pkt_len + SG_HDR_SIZE;
+ }
+
+#ifdef TX_CHAINING_DEBUG
+ printf("\nTx pkt #%i: pkt segs %i, pkt len %i -> vq buf size %i, vq header size %i\n",
+ pkt, bufs[pkt]->nb_segs, bufs[pkt]->pkt_len,
+ SG_HW_TX_PKT_BUFFER_SIZE, SG_HDR_SIZE);
+
+#ifdef TX_SRC_DUMP_PKTS_DEBUG
+ {
+ struct rte_mbuf *m = bufs[pkt];
+ int ii;
+
+ printf("Dump src mbuf:\n");
+ for (ii = 0; ii < bufs[pkt]->nb_segs; ii++) {
+ printf(" seg %i len %i\n", ii, m->data_len);
+ printf(" seg dump:\n");
+ dump_packet_seg("mbuf seg:",
+ rte_pktmbuf_mtod(m, uint8_t *),
+ m->data_len);
+ m = m->next;
+ }
+ }
+#endif
+
+#endif
+
+ if (bufs[pkt]->nb_segs == 1 && nb_segs_arr[pkt] == 1) {
+#ifdef TX_CHAINING_DEBUG
+ printf("Simple copy %i bytes - mbuf -> vq\n",
+ bufs[pkt]->pkt_len);
+#endif
+ rte_memcpy((void *)((char *)vq_bufs[vq_descr_idx].virt_addr +
+ SG_HDR_SIZE),
+ rte_pktmbuf_mtod(bufs[pkt], void *),
+ bufs[pkt]->pkt_len);
+
+ cvq_desc.b[vq_descr_idx].len =
+ bufs[pkt]->pkt_len + SG_HDR_SIZE;
+
+ seg_idx++;
+ } else {
+ int cpy_segs = copy_mbuf_to_virtqueue(&cvq_desc,
+ vq_descr_idx, vq_bufs,
+ nb_segs - last_seg_idx, bufs[pkt]);
+ if (cpy_segs < 0)
+ break;
+ seg_idx += cpy_segs;
+ }
+
+#ifdef TX_DST_DUMP_PKTS_DEBUG
+ int d, tot_size = 0;
+
+ for (d = last_seg_idx; d < seg_idx; d++)
+ tot_size += cvq_desc.b[VIRTQ_DESCR_IDX(d)].len;
+ printf("\nDump final Tx vq pkt %i, size %i, tx port %i, bypass id %i, using hw queue index %i\n",
+ pkt, tot_size, tx_q->port, hdr_tx->bypass_port,
+ tx_q->queue.hw_id);
+ for (d = last_seg_idx; d < seg_idx; d++) {
+ char str[32];
+
+ sprintf(str, "Vq seg %i:", d - last_seg_idx);
+ dump_packet_seg(str,
+ vq_bufs[VIRTQ_DESCR_IDX(d)].virt_addr,
+ cvq_desc.b[VIRTQ_DESCR_IDX(d)].len);
+ }
+#endif
+
+ last_seg_idx = seg_idx;
+ rte_pktmbuf_free(bufs[pkt]);
+ pkts_sent++;
+ }
+
+#ifdef TX_CHAINING_DEBUG
+ printf("\nTx final vq setup:\n");
+ for (int i = 0; i < nb_segs; i++) {
+ int idx = VIRTQ_DESCR_IDX(i);
+
+ if (cvq_desc.vq_type == SPLIT_RING) {
+ printf("virtq descr %i, len %i, flags %04x, next %i\n",
+ idx, cvq_desc.b[idx].len, cvq_desc.s[idx].flags,
+ cvq_desc.s[idx].next);
+ }
+ }
+#endif
+
+exit_out:
+
+ if (pkts_sent) {
+#ifdef TX_CHAINING_DEBUG
+ printf("Release virtq segs %i\n", nb_segs);
+#endif
+ nthw_release_tx_buffers(tx_q->vq, pkts_sent, nb_segs_arr);
+ }
+ return pkts_sent;
+}
+
+static int allocate_hw_virtio_queues(struct rte_eth_dev *eth_dev, int vf_num,
+ struct hwq_s *hwq, int num_descr,
+ int buf_size)
+{
+ int i, res;
+ uint32_t size;
+ uint64_t iova_addr;
+
+ NT_LOG(DBG, ETHDEV,
+ "***** Configure IOMMU for HW queues on VF %i *****\n", vf_num);
+
+ /* Just allocate 1MB to hold all combined descr rings */
+ uint64_t tot_alloc_size = 0x100000 + buf_size * num_descr;
+
+ void *virt = rte_malloc_socket("VirtQDescr", tot_alloc_size,
+ ALIGN_SIZE(tot_alloc_size),
+ eth_dev->data->numa_node);
+ if (!virt)
+ return -1;
+
+ uint64_t gp_offset = (uint64_t)virt & ONE_G_MASK;
+ rte_iova_t hpa = rte_malloc_virt2iova(virt);
+
+ NT_LOG(DBG, ETHDEV,
+ "Allocated virtio descr rings : virt %p [0x%" PRIX64
+ "], hpa %p [0x%" PRIX64 "]\n",
+ virt, gp_offset, hpa, hpa & ONE_G_MASK);
+
+ /*
+ * Same offset on both HPA and IOVA
+ * Make sure 1G boundary is never crossed
+ */
+ if (((hpa & ONE_G_MASK) != gp_offset) ||
+ (((uint64_t)virt + tot_alloc_size) & ~ONE_G_MASK) !=
+ ((uint64_t)virt & ~ONE_G_MASK)) {
+ NT_LOG(ERR, ETHDEV,
+ "*********************************************************\n");
+ NT_LOG(ERR, ETHDEV,
+ "ERROR, no optimal IOMMU mapping available hpa : %016lx (%016lx), gp_offset : %016lx size %u\n",
+ hpa, hpa & ONE_G_MASK, gp_offset, tot_alloc_size);
+ NT_LOG(ERR, ETHDEV,
+ "*********************************************************\n");
+
+ rte_free(virt);
+
+ /* Just allocate 1MB to hold all combined descr rings */
+ size = 0x100000;
+ void *virt = rte_malloc_socket("VirtQDescr", size, 4096,
+ eth_dev->data->numa_node);
+ if (!virt)
+ return -1;
+
+ res = nt_vfio_dma_map(vf_num, virt, &iova_addr, size);
+
+ NT_LOG(DBG, ETHDEV, "VFIO MMAP res %i, vf_num %i\n", res,
+ vf_num);
+ if (res != 0)
+ return -1;
+
+ hwq->vf_num = vf_num;
+ hwq->virt_queues_ctrl.virt_addr = virt;
+ hwq->virt_queues_ctrl.phys_addr = (void *)iova_addr;
+ hwq->virt_queues_ctrl.len = size;
+
+ NT_LOG(DBG, ETHDEV,
+ "Allocated for virtio descr rings combined 1MB : %p, IOVA %016lx\n",
+ virt, iova_addr);
+
+ size = num_descr * sizeof(struct nthw_memory_descriptor);
+ hwq->pkt_buffers = rte_zmalloc_socket("rx_pkt_buffers", size,
+ 64, eth_dev->data->numa_node);
+ if (!hwq->pkt_buffers) {
+ NT_LOG(ERR, ETHDEV,
+ "Failed to allocated buffer array for hw-queue %p, "
+ "total size %i, elements %i\n",
+ hwq->pkt_buffers, size, num_descr);
+ rte_free(virt);
+ return -1;
+ }
+
+ size = buf_size * num_descr;
+ void *virt_addr = rte_malloc_socket("pkt_buffer_pkts", size,
+ 4096,
+ eth_dev->data->numa_node);
+ if (!virt_addr) {
+ NT_LOG(ERR, ETHDEV,
+ "Failed allocate packet buffers for hw-queue %p, "
+ "buf size %i, elements %i\n",
+ hwq->pkt_buffers, buf_size, num_descr);
+ rte_free(hwq->pkt_buffers);
+ rte_free(virt);
+ return -1;
+ }
+
+ res = nt_vfio_dma_map(vf_num, virt_addr, &iova_addr, size);
+
+ NT_LOG(DBG, ETHDEV,
+ "VFIO MMAP res %i, virt %p, iova %016lx, vf_num %i, num "
+ "pkt bufs %i, tot size %i\n",
+ res, virt_addr, iova_addr, vf_num, num_descr, size);
+
+ if (res != 0)
+ return -1;
+
+ for (i = 0; i < num_descr; i++) {
+ hwq->pkt_buffers[i].virt_addr =
+ (void *)((char *)virt_addr +
+ ((uint64_t)(i) * buf_size));
+ hwq->pkt_buffers[i].phys_addr =
+ (void *)(iova_addr + ((uint64_t)(i) * buf_size));
+ hwq->pkt_buffers[i].len = buf_size;
+ }
+
+ return 0;
+ } /* End of: no optimal IOMMU mapping available */
+
+ res = nt_vfio_dma_map(vf_num, virt, &iova_addr, ONE_G_SIZE);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "VFIO MMAP FAILED! res %i, vf_num %i\n",
+ res, vf_num);
+ return -1;
+ }
+
+ hwq->vf_num = vf_num;
+ hwq->virt_queues_ctrl.virt_addr = virt;
+ hwq->virt_queues_ctrl.phys_addr = (void *)(iova_addr);
+ hwq->virt_queues_ctrl.len = 0x100000;
+ iova_addr += 0x100000;
+
+ NT_LOG(DBG, ETHDEV,
+ "VFIO MMAP: virt_addr=%" PRIX64 " phys_addr=%" PRIX64
+ " size=%" PRIX64 " hpa=%" PRIX64 "\n",
+ hwq->virt_queues_ctrl.virt_addr, hwq->virt_queues_ctrl.phys_addr,
+ hwq->virt_queues_ctrl.len,
+ rte_malloc_virt2iova(hwq->virt_queues_ctrl.virt_addr));
+
+ size = num_descr * sizeof(struct nthw_memory_descriptor);
+ hwq->pkt_buffers = rte_zmalloc_socket("rx_pkt_buffers", size, 64,
+ eth_dev->data->numa_node);
+ if (!hwq->pkt_buffers) {
+ NT_LOG(ERR, ETHDEV,
+ "Failed to allocated buffer array for hw-queue %p, total size %i, elements %i\n",
+ hwq->pkt_buffers, size, num_descr);
+ rte_free(virt);
+ return -1;
+ }
+
+ void *virt_addr = (void *)((uint64_t)virt + 0x100000);
+
+ for (i = 0; i < num_descr; i++) {
+ hwq->pkt_buffers[i].virt_addr =
+ (void *)((char *)virt_addr + ((uint64_t)(i) * buf_size));
+ hwq->pkt_buffers[i].phys_addr =
+ (void *)(iova_addr + ((uint64_t)(i) * buf_size));
+ hwq->pkt_buffers[i].len = buf_size;
+ }
+ return 0;
+}
+
+static void release_hw_virtio_queues(struct hwq_s *hwq)
+{
+ if (!hwq || hwq->vf_num == 0)
+ return;
+ hwq->vf_num = 0;
+}
+
+static int deallocate_hw_virtio_queues(struct hwq_s *hwq)
+{
+ int vf_num = hwq->vf_num;
+
+ void *virt = hwq->virt_queues_ctrl.virt_addr;
+
+ int res = nt_vfio_dma_unmap(vf_num, hwq->virt_queues_ctrl.virt_addr,
+ (uint64_t)hwq->virt_queues_ctrl.phys_addr,
+ ONE_G_SIZE);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "VFIO UNMMAP FAILED! res %i, vf_num %i\n",
+ res, vf_num);
+ return -1;
+ }
+
+ release_hw_virtio_queues(hwq);
+ rte_free(hwq->pkt_buffers);
+ rte_free(virt);
+ return 0;
+}
+
+static void eth_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ struct ntnic_tx_queue *tx_q = &internals->txq_scg[queue_id];
+
+ deallocate_hw_virtio_queues(&tx_q->hwq);
+ NT_LOG(DBG, ETHDEV, "NTNIC: %s\n", __func__);
+}
+
+static void eth_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ struct ntnic_rx_queue *rx_q = &internals->rxq_scg[queue_id];
+
+ deallocate_hw_virtio_queues(&rx_q->hwq);
+ NT_LOG(DBG, ETHDEV, "NTNIC: %s\n", __func__);
+}
+
+static int num_queues_alloced;
+
+/* Returns num queue starting at returned queue num or -1 on fail */
+static int allocate_queue(int num)
+{
+ int next_free = num_queues_alloced;
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: num_queues_alloced=%u, New queues=%u, Max queues=%u\n",
+ __func__, num_queues_alloced, num, MAX_TOTAL_QUEUES);
+ if (num_queues_alloced + num > MAX_TOTAL_QUEUES)
+ return -1;
+ num_queues_alloced += num;
+ return next_free;
+}
+
+static int
+eth_rx_scg_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id,
+ uint16_t nb_rx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_rxconf *rx_conf __rte_unused,
+ struct rte_mempool *mb_pool)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+ struct rte_pktmbuf_pool_private *mbp_priv;
+ struct pmd_internals *internals = eth_dev->data->dev_private;
+ struct ntnic_rx_queue *rx_q = &internals->rxq_scg[rx_queue_id];
+ struct drv_s *p_drv = internals->p_drv;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+
+ if (internals->type == PORT_TYPE_OVERRIDE) {
+ rx_q->mb_pool = mb_pool;
+ eth_dev->data->rx_queues[rx_queue_id] = rx_q;
+ mbp_priv = rte_mempool_get_priv(rx_q->mb_pool);
+ rx_q->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size -
+ RTE_PKTMBUF_HEADROOM);
+ rx_q->enabled = 1;
+ return 0;
+ }
+
+ NT_LOG(DBG, ETHDEV,
+ "(%i) NTNIC RX OVS-SW queue setup: queue id %i, hw queue index %i\n",
+ internals->port, rx_queue_id, rx_q->queue.hw_id);
+
+ rx_q->mb_pool = mb_pool;
+
+ eth_dev->data->rx_queues[rx_queue_id] = rx_q;
+
+ mbp_priv = rte_mempool_get_priv(rx_q->mb_pool);
+ rx_q->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size -
+ RTE_PKTMBUF_HEADROOM);
+ rx_q->enabled = 1;
+
+ if (allocate_hw_virtio_queues(eth_dev, EXCEPTION_PATH_HID, &rx_q->hwq,
+ SG_NB_HW_RX_DESCRIPTORS,
+ SG_HW_RX_PKT_BUFFER_SIZE) < 0)
+ return -1;
+
+ rx_q->nb_hw_rx_descr = SG_NB_HW_RX_DESCRIPTORS;
+
+ rx_q->profile = p_drv->ntdrv.adapter_info.fpga_info.profile;
+
+ rx_q->vq = nthw_setup_managed_rx_virt_queue(p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs,
+ rx_q->queue.hw_id, /* index */
+ rx_q->nb_hw_rx_descr, EXCEPTION_PATH_HID, /* host_id */
+ 1, /* header NT DVIO header for exception path */
+ &rx_q->hwq.virt_queues_ctrl, rx_q->hwq.pkt_buffers, SPLIT_RING, -1);
+
+ NT_LOG(DBG, ETHDEV, "(%i) NTNIC RX OVS-SW queues successfully setup\n",
+ internals->port);
+
+ return 0;
+}
+
+static int
+eth_tx_scg_queue_setup(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id,
+ uint16_t nb_tx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+ struct pmd_internals *internals = eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ struct ntnic_tx_queue *tx_q = &internals->txq_scg[tx_queue_id];
+
+ if (internals->type == PORT_TYPE_OVERRIDE) {
+ eth_dev->data->tx_queues[tx_queue_id] = tx_q;
+ return 0;
+ }
+
+ NT_LOG(DBG, ETHDEV,
+ "(%i) NTNIC TX OVS-SW queue setup: queue id %i, hw queue index %i\n",
+ tx_q->port, tx_queue_id, tx_q->queue.hw_id);
+
+ if (tx_queue_id > internals->nb_tx_queues) {
+ printf("Error invalid tx queue id\n");
+ return -1;
+ }
+
+ eth_dev->data->tx_queues[tx_queue_id] = tx_q;
+
+ /* Calculate target ID for HW - to be used in NTDVIO0 header bypass_port */
+ if (tx_q->rss_target_id >= 0) {
+ /* bypass to a multiqueue port - qsl-hsh index */
+ tx_q->target_id = tx_q->rss_target_id + 0x90;
+ } else {
+ if (internals->vpq[tx_queue_id].hw_id > -1) {
+ /* virtual port - queue index */
+ tx_q->target_id = internals->vpq[tx_queue_id].hw_id;
+ } else {
+ /* Phy port - phy port identifier */
+ if (lag_active) {
+ /* If in LAG mode use bypass 0x90 mode */
+ tx_q->target_id = 0x90;
+ } else {
+ /* output/bypass to MAC */
+ tx_q->target_id = (int)(tx_q->port + 0x80);
+ }
+ }
+ }
+
+ if (allocate_hw_virtio_queues(eth_dev, EXCEPTION_PATH_HID, &tx_q->hwq,
+ SG_NB_HW_TX_DESCRIPTORS,
+ SG_HW_TX_PKT_BUFFER_SIZE) < 0)
+ return -1;
+
+ tx_q->nb_hw_tx_descr = SG_NB_HW_TX_DESCRIPTORS;
+
+ tx_q->profile = p_drv->ntdrv.adapter_info.fpga_info.profile;
+
+ uint32_t port, header;
+
+ if (tx_q->profile == FPGA_INFO_PROFILE_VSWITCH) {
+ /* transmit port - not used in vswitch enabled mode - using bypass */
+ port = 0;
+ header = 1; /* header type DVIO0 Always for exception path */
+ } else {
+ port = tx_q->port; /* transmit port */
+ header = 0; /* header type VirtIO-Net */
+ }
+ /*
+ * in_port - in vswitch mode has to move tx port from OVS excep. Away
+ * from VM tx port, because of QoS is matched by port id!
+ */
+ tx_q->vq = nthw_setup_managed_tx_virt_queue(p_nt_drv->adapter_info.fpga_info.mp_nthw_dbs,
+ tx_q->queue.hw_id, /* index */
+ tx_q->nb_hw_tx_descr, /* queue size */
+ EXCEPTION_PATH_HID, /* host_id always VF4 */
+ port,
+ tx_q->port +
+ 128,
+ header, &tx_q->hwq.virt_queues_ctrl, tx_q->hwq.pkt_buffers,
+ SPLIT_RING, -1, IN_ORDER);
+
+ tx_q->enabled = 1;
+ for (uint32_t i = 0; i < internals->vpq_nb_vq; i++) {
+ nthw_epp_set_queue_to_vport(p_nt_drv->adapter_info.fpga_info.mp_nthw_epp,
+ internals->vpq[i].hw_id, tx_q->port);
+ }
+
+ NT_LOG(DBG, ETHDEV, "(%i) NTNIC TX OVS-SW queues successfully setup\n",
+ internals->port);
+
+ if (internals->type == PORT_TYPE_PHYSICAL) {
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+ NT_LOG(DBG, ETHDEV, "Port %i is ready for data. Enable port\n",
+ internals->if_index);
+ nt4ga_port_set_adm_state(p_adapter_info, internals->if_index,
+ true);
+ if (lag_active && internals->if_index == 0) {
+ /*
+ * Special case for link aggregation where the second phy interface (port 1)
+ * is "hidden" from DPDK and therefore doesn't get enabled through normal
+ * interface probing
+ */
+ NT_LOG(DBG, ETHDEV, "LAG: Enable port %i\n",
+ internals->if_index + 1);
+ nt4ga_port_set_adm_state(p_adapter_info,
+ internals->if_index + 1, true);
+ }
+ }
+
+ return 0;
+}
+
+static int dev_set_mtu_inline(struct rte_eth_dev *dev, uint16_t mtu)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)dev->data->dev_private;
+ struct flow_eth_dev *flw_dev = internals->flw_dev;
+ int ret = -1;
+
+ if (internals->type == PORT_TYPE_PHYSICAL && mtu >= MIN_MTU_INLINE &&
+ mtu <= MAX_MTU)
+ ret = flow_set_mtu_inline(flw_dev, internals->port, mtu);
+ return ret ? -EINVAL : 0;
+}
+
+static int dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ /*struct ntnic_tx_queue *tx_q = internals->txq; */
+ struct drv_s *p_drv = internals->p_drv;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info;
+ int retval = EINVAL;
+
+ if (mtu < MIN_MTU || mtu > MAX_MTU)
+ return -EINVAL;
+
+ if (internals->type == PORT_TYPE_VIRTUAL) {
+ /* set MTU on exception to MAX_MTU */
+ retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp,
+ internals->rxq_scg[0]
+ .queue
+ .hw_id, /* exception tx queue hw_id to OVS */
+ MAX_MTU, /* max number of bytes allowed for a given port. */
+ internals->type); /* port type */
+
+ if (retval)
+ return retval;
+
+ uint i;
+
+ for (i = 0; i < internals->vpq_nb_vq; i++) {
+ retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp,
+ internals->vpq[i].hw_id, /* tx queue hw_id */
+ mtu, /* max number of bytes allowed for a given port. */
+ internals->type); /* port type */
+ if (retval)
+ return retval;
+
+ NT_LOG(DBG, ETHDEV, "SET MTU SIZE %d queue hw_id %d\n",
+ mtu, internals->vpq[i].hw_id);
+ }
+ } else if (internals->type == PORT_TYPE_PHYSICAL) {
+ /* set MTU on exception to MAX_MTU */
+ retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp,
+ internals->rxq_scg[0]
+ .queue
+ .hw_id, /* exception tx queue hw_id to OVS */
+ MAX_MTU, /* max number of bytes allowed for a given port. */
+ PORT_TYPE_VIRTUAL); /* port type */
+ if (retval)
+ return retval;
+
+ retval = nthw_epp_set_mtu(fpga_info->mp_nthw_epp,
+ internals->port, /* port number */
+ mtu, /* max number of bytes allowed for a given port. */
+ internals->type); /* port type */
+
+ NT_LOG(DBG, ETHDEV, "SET MTU SIZE %d port %d\n", mtu,
+ internals->port);
+ } else {
+ NT_LOG(DBG, ETHDEV,
+ "COULD NOT SET MTU SIZE %d port %d type %d\n", mtu,
+ internals->port, internals->type);
+ retval = -EINVAL;
+ }
+ return retval;
+}
+
+static int eth_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+ eth_dev->data->rx_queue_state[rx_queue_id] =
+ RTE_ETH_QUEUE_STATE_STARTED;
+ return 0;
+}
+
+static int eth_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+ eth_dev->data->rx_queue_state[rx_queue_id] =
+ RTE_ETH_QUEUE_STATE_STOPPED;
+ return 0;
+}
+
+static int eth_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+ eth_dev->data->tx_queue_state[rx_queue_id] =
+ RTE_ETH_QUEUE_STATE_STARTED;
+ return 0;
+}
+
+static int eth_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+ eth_dev->data->tx_queue_state[rx_queue_id] =
+ RTE_ETH_QUEUE_STATE_STOPPED;
+ return 0;
+}
+
+static void eth_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+ struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs;
+
+ assert(index < NUM_MAC_ADDRS_PER_PORT);
+
+ if (index >= NUM_MAC_ADDRS_PER_PORT) {
+ const struct pmd_internals *const internals =
+ dev->data->dev_private;
+ NT_LOG(ERR, ETHDEV,
+ "%s: [%s:%i]: Port %i: illegal index %u (>= %u)\n",
+ __FILE__, __func__, __LINE__, internals->if_index, index,
+ NUM_MAC_ADDRS_PER_PORT);
+ return;
+ }
+ (void)memset(ð_addrs[index], 0, sizeof(eth_addrs[index]));
+}
+
+static int eth_mac_addr_add(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr, uint32_t index,
+ uint32_t vmdq __rte_unused)
+{
+ struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs;
+
+ assert(index < NUM_MAC_ADDRS_PER_PORT);
+
+ if (index >= NUM_MAC_ADDRS_PER_PORT) {
+ const struct pmd_internals *const internals =
+ dev->data->dev_private;
+ NT_LOG(ERR, ETHDEV,
+ "%s: [%s:%i]: Port %i: illegal index %u (>= %u)\n",
+ __FILE__, __func__, __LINE__, internals->if_index, index,
+ NUM_MAC_ADDRS_PER_PORT);
+ return -1;
+ }
+
+ eth_addrs[index] = *mac_addr;
+
+ return 0;
+}
+
+static int eth_mac_addr_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr)
+{
+ struct rte_ether_addr *const eth_addrs = dev->data->mac_addrs;
+
+ eth_addrs[0U] = *mac_addr;
+
+ return 0;
+}
+
+static int eth_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addr_set,
+ uint32_t nb_mc_addr)
+{
+ struct pmd_internals *const internals = dev->data->dev_private;
+ struct rte_ether_addr *const mc_addrs = internals->mc_addrs;
+ size_t i;
+
+ if (nb_mc_addr >= NUM_MULTICAST_ADDRS_PER_PORT) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: [%s:%i]: Port %i: too many multicast addresses %u (>= %u)\n",
+ __FILE__, __func__, __LINE__, internals->if_index,
+ nb_mc_addr, NUM_MULTICAST_ADDRS_PER_PORT);
+ return -1;
+ }
+
+ for (i = 0U; i < NUM_MULTICAST_ADDRS_PER_PORT; i++) {
+ if (i < nb_mc_addr)
+ mc_addrs[i] = mc_addr_set[i];
+
+ else
+ (void)memset(&mc_addrs[i], 0, sizeof(mc_addrs[i]));
+ }
+
+ return 0;
+}
+
+static int eth_dev_configure(struct rte_eth_dev *eth_dev)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] Called for eth_dev %p\n", __func__,
+ __func__, __LINE__, eth_dev);
+
+ p_drv->probe_finished = 1;
+
+ /* The device is ALWAYS running promiscuous mode. */
+ eth_dev->data->promiscuous ^= ~eth_dev->data->promiscuous;
+ return 0;
+}
+
+static int eth_dev_start(struct rte_eth_dev *eth_dev)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ const int n_intf_no = internals->if_index;
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] - Port %u, %u\n", __func__, __func__,
+ __LINE__, internals->n_intf_no, internals->if_index);
+
+ if (internals->type == PORT_TYPE_VIRTUAL ||
+ internals->type == PORT_TYPE_OVERRIDE) {
+ eth_dev->data->dev_link.link_status = ETH_LINK_UP;
+ } else {
+ /*
+ * wait for link on port
+ * If application starts sending too soon before FPGA port is ready, garbage is
+ * produced
+ */
+ int loop = 0;
+
+ while (nt4ga_port_get_link_status(p_adapter_info, n_intf_no) ==
+ ETH_LINK_DOWN) {
+ /* break out after 5 sec */
+ if (++loop >= 50) {
+ NT_LOG(DBG, ETHDEV,
+ "%s: TIMEOUT No link on port %i (5sec timeout)\n",
+ __func__, internals->n_intf_no);
+ break;
+ }
+ usleep(100000);
+ }
+ assert(internals->n_intf_no ==
+ internals->if_index); /* Sanity check */
+ if (internals->lpbk_mode) {
+ if (internals->lpbk_mode & 1 << 0) {
+ nt4ga_port_set_loopback_mode(p_adapter_info,
+ n_intf_no,
+ NT_LINK_LOOPBACK_HOST);
+ }
+ if (internals->lpbk_mode & 1 << 1) {
+ nt4ga_port_set_loopback_mode(p_adapter_info,
+ n_intf_no,
+ NT_LINK_LOOPBACK_LINE);
+ }
+ }
+ }
+ return 0;
+}
+
+static int eth_dev_stop(struct rte_eth_dev *eth_dev)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ const int n_intf_no = internals->if_index;
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] - Port %u, %u, type %u\n", __func__,
+ __func__, __LINE__, internals->n_intf_no, internals->if_index,
+ internals->type);
+
+ if (internals->type != PORT_TYPE_VIRTUAL) {
+ struct ntnic_rx_queue *rx_q = internals->rxq_scg;
+ struct ntnic_tx_queue *tx_q = internals->txq_scg;
+
+ uint q;
+
+ for (q = 0; q < internals->nb_rx_queues; q++)
+ nthw_release_managed_rx_virt_queue(rx_q[q].vq);
+
+ for (q = 0; q < internals->nb_tx_queues; q++)
+ nthw_release_managed_tx_virt_queue(tx_q[q].vq);
+
+ nt4ga_port_set_adm_state(p_adapter_info, n_intf_no, 0);
+ nt4ga_port_set_link_status(p_adapter_info, n_intf_no, 0);
+ nt4ga_port_set_link_speed(p_adapter_info, n_intf_no,
+ NT_LINK_SPEED_UNKNOWN);
+ nt4ga_port_set_loopback_mode(p_adapter_info, n_intf_no,
+ NT_LINK_LOOPBACK_OFF);
+ }
+
+ eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ return 0;
+}
+
+static int eth_dev_set_link_up(struct rte_eth_dev *dev)
+{
+ struct pmd_internals *const internals = dev->data->dev_private;
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+ const int port = internals->if_index;
+
+ if (internals->type == PORT_TYPE_VIRTUAL ||
+ internals->type == PORT_TYPE_OVERRIDE)
+ return 0;
+
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ assert(port == internals->n_intf_no);
+
+ nt4ga_port_set_adm_state(p_adapter_info, port, true);
+
+ return 0;
+}
+
+static int eth_dev_set_link_down(struct rte_eth_dev *dev)
+{
+ struct pmd_internals *const internals = dev->data->dev_private;
+ struct adapter_info_s *p_adapter_info =
+ &internals->p_drv->ntdrv.adapter_info;
+ const int port = internals->if_index;
+
+ if (internals->type == PORT_TYPE_VIRTUAL ||
+ internals->type == PORT_TYPE_OVERRIDE)
+ return 0;
+
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ assert(port == internals->n_intf_no);
+
+ nt4ga_port_set_link_status(p_adapter_info, port, false);
+
+ return 0;
+}
+
+static int eth_dev_close(struct rte_eth_dev *eth_dev)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info;
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ (void)pci_dev; /* UNUSED */
+
+ NT_LOG(DBG, ETHDEV, "%s: enter [%s:%u]\n", __func__, __func__,
+ __LINE__);
+
+ internals->p_drv = NULL;
+
+ /* LAG cleanup */
+ if (internals->lag_config) {
+ if (internals->lag_config->lag_tid) {
+ internals->lag_config->lag_thread_active = 0;
+ pthread_join(internals->lag_config->lag_tid, NULL);
+ }
+ lag_active = 0;
+ rte_free(internals->lag_config);
+ }
+
+ /* free */
+ rte_free(internals);
+ internals = NULL;
+
+ eth_dev->data->dev_private = NULL;
+ eth_dev->data->mac_addrs = NULL;
+
+ /* release */
+ rte_eth_dev_release_port(eth_dev);
+
+ NT_LOG(DBG, ETHDEV, "%s: %d [%s:%u]\n", __func__,
+ p_drv->n_eth_dev_init_count, __func__, __LINE__);
+ p_drv->n_eth_dev_init_count--;
+
+ /*
+ * rte_pci_dev has no private member for p_drv
+ * wait until all rte_eth_dev's are closed - then close adapters via p_drv
+ */
+ if (!p_drv->n_eth_dev_init_count && p_drv) {
+ NT_LOG(DBG, ETHDEV, "%s: %d [%s:%u]\n", __func__,
+ p_drv->n_eth_dev_init_count, __func__, __LINE__);
+ p_drv->ntdrv.b_shutdown = true;
+ void *p_ret_val = NULL;
+
+ pthread_join(p_nt_drv->stat_thread, &p_ret_val);
+ if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
+ p_ret_val = NULL;
+ pthread_join(p_nt_drv->flm_thread, &p_ret_val);
+ }
+ nt4ga_adapter_deinit(&p_nt_drv->adapter_info);
+ rte_free(p_drv);
+ }
+ NT_LOG(DBG, ETHDEV, "%s: leave [%s:%u]\n", __func__, __func__,
+ __LINE__);
+ return 0;
+}
+
+static int eth_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
+ size_t fw_size)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+
+ if (internals->type == PORT_TYPE_VIRTUAL ||
+ internals->type == PORT_TYPE_OVERRIDE)
+ return 0;
+
+ fpga_info_t *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info;
+ const int length =
+ snprintf(fw_version, fw_size, "%03d-%04d-%02d-%02d",
+ fpga_info->n_fpga_type_id, fpga_info->n_fpga_prod_id,
+ fpga_info->n_fpga_ver_id, fpga_info->n_fpga_rev_id);
+ if ((size_t)length < fw_size) {
+ /* We have space for the version string */
+ return 0;
+ }
+ /* We do not have space for the version string -return the needed space */
+ return length + 1;
+}
+
+static int eth_xstats_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_xstat *stats, unsigned int n)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ int if_index = internals->if_index;
+ int nb_xstats;
+
+ pthread_mutex_lock(&p_nt_drv->stat_lck);
+ nb_xstats = nthw_xstats_get(p_nt4ga_stat, stats, n,
+ p_nthw_stat->mb_is_vswitch, if_index);
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+ return nb_xstats;
+}
+
+static int eth_xstats_get_by_id(struct rte_eth_dev *eth_dev,
+ const uint64_t *ids, uint64_t *values,
+ unsigned int n)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ int if_index = internals->if_index;
+ int nb_xstats;
+
+ pthread_mutex_lock(&p_nt_drv->stat_lck);
+ nb_xstats = nthw_xstats_get_by_id(p_nt4ga_stat, ids, values, n,
+ p_nthw_stat->mb_is_vswitch, if_index);
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+ return nb_xstats;
+}
+
+static int eth_xstats_reset(struct rte_eth_dev *eth_dev)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ int if_index = internals->if_index;
+
+ pthread_mutex_lock(&p_nt_drv->stat_lck);
+ nthw_xstats_reset(p_nt4ga_stat, p_nthw_stat->mb_is_vswitch, if_index);
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+ return dpdk_stats_reset(internals, p_nt_drv, if_index);
+}
+
+static int eth_xstats_get_names(struct rte_eth_dev *eth_dev __rte_unused,
+ struct rte_eth_xstat_name *xstats_names,
+ unsigned int size)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ return nthw_xstats_get_names(p_nt4ga_stat, xstats_names, size,
+ p_nthw_stat->mb_is_vswitch);
+}
+
+static int eth_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,
+ const uint64_t *ids,
+ struct rte_eth_xstat_name *xstats_names,
+ unsigned int size)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct drv_s *p_drv = internals->p_drv;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ return nthw_xstats_get_names_by_id(p_nt4ga_stat, xstats_names, ids, size,
+ p_nthw_stat->mb_is_vswitch);
+}
+
+static int _dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+ const struct rte_flow_ops **ops)
+{
+ *ops = &_dev_flow_ops;
+ return 0;
+}
+
+static int promiscuous_enable(struct rte_eth_dev __rte_unused * dev)
+{
+ NT_LOG(DBG, NTHW, "The device always run promiscuous mode.");
+ return 0;
+}
+
+static int eth_dev_rss_hash_update(struct rte_eth_dev *eth_dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct flow_eth_dev *fedev = internals->flw_dev;
+ struct flow_nic_dev *ndev = fedev->ndev;
+ const int hsh_idx =
+ 0; /* hsh index 0 means the default receipt in HSH module */
+ int res = flow_nic_set_hasher_fields(ndev, hsh_idx,
+ nt_rss_hash_field_from_dpdk(rss_conf->rss_hf));
+ res |= hw_mod_hsh_rcp_flush(&ndev->be, hsh_idx, 1);
+ return res;
+}
+
+static int rss_hash_conf_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct flow_eth_dev *fedev = internals->flw_dev;
+ struct flow_nic_dev *ndev = fedev->ndev;
+
+ rss_conf->rss_key = NULL;
+ rss_conf->rss_key_len = 0;
+ rss_conf->rss_hf |=
+ dpdk_rss_hash_define_from_nt_rss(ndev->rss_hash_config);
+ return 0;
+}
+
+static struct eth_dev_ops nthw_eth_dev_ops = {
+ .dev_configure = eth_dev_configure,
+ .dev_start = eth_dev_start,
+ .dev_stop = eth_dev_stop,
+ .dev_set_link_up = eth_dev_set_link_up,
+ .dev_set_link_down = eth_dev_set_link_down,
+ .dev_close = eth_dev_close,
+ .link_update = eth_link_update,
+ .stats_get = eth_stats_get,
+ .stats_reset = eth_stats_reset,
+ .dev_infos_get = eth_dev_infos_get,
+ .fw_version_get = eth_fw_version_get,
+ .rx_queue_setup = eth_rx_scg_queue_setup,
+ .rx_queue_start = eth_rx_queue_start,
+ .rx_queue_stop = eth_rx_queue_stop,
+ .rx_queue_release = eth_rx_queue_release,
+ .tx_queue_setup = eth_tx_scg_queue_setup,
+ .tx_queue_start = eth_tx_queue_start,
+ .tx_queue_stop = eth_tx_queue_stop,
+ .tx_queue_release = eth_tx_queue_release,
+ .mac_addr_remove = eth_mac_addr_remove,
+ .mac_addr_add = eth_mac_addr_add,
+ .mac_addr_set = eth_mac_addr_set,
+ .set_mc_addr_list = eth_set_mc_addr_list,
+ .xstats_get = eth_xstats_get,
+ .xstats_get_names = eth_xstats_get_names,
+ .xstats_reset = eth_xstats_reset,
+ .xstats_get_by_id = eth_xstats_get_by_id,
+ .xstats_get_names_by_id = eth_xstats_get_names_by_id,
+ .mtu_set = NULL,
+ .mtr_ops_get = eth_mtr_ops_get,
+ .flow_ops_get = _dev_flow_ops_get,
+ .promiscuous_disable = NULL,
+ .promiscuous_enable = promiscuous_enable,
+ .rss_hash_update = eth_dev_rss_hash_update,
+ .rss_hash_conf_get = rss_hash_conf_get,
+};
+
+/* Converts link speed provided in Mbps to NT specific definitions.*/
+static nt_link_speed_t convert_link_speed(int link_speed_mbps)
+{
+ switch (link_speed_mbps) {
+ case 10:
+ return NT_LINK_SPEED_10M;
+ case 100:
+ return NT_LINK_SPEED_100M;
+ case 1000:
+ return NT_LINK_SPEED_1G;
+ case 10000:
+ return NT_LINK_SPEED_10G;
+ case 40000:
+ return NT_LINK_SPEED_40G;
+ case 100000:
+ return NT_LINK_SPEED_100G;
+ case 50000:
+ return NT_LINK_SPEED_50G;
+ case 25000:
+ return NT_LINK_SPEED_25G;
+ default:
+ return NT_LINK_SPEED_UNKNOWN;
+ }
+}
+
+/*
+ * Adapter flm stat thread
+ */
+static void *adapter_flm_thread_fn(void *context)
+{
+ struct drv_s *p_drv = context;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
+ struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter;
+ struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device;
+
+ NT_LOG(DBG, ETHDEV, "%s: %s: waiting for port configuration\n",
+ p_adapter_info->mp_adapter_id_str, __func__);
+
+ while (p_flow_nic_dev->eth_base == NULL)
+ usleep(1000000);
+ struct flow_eth_dev *dev = p_flow_nic_dev->eth_base;
+
+ NT_LOG(DBG, ETHDEV, "%s: %s: begin\n", p_adapter_info->mp_adapter_id_str,
+ __func__);
+
+ while (!p_drv->ntdrv.b_shutdown) {
+ if (flm_mtr_update_stats(dev) == 0)
+ usleep(10);
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: %s: end\n", p_adapter_info->mp_adapter_id_str,
+ __func__);
+
+ return NULL;
+}
+
+/*
+ * Adapter stat thread
+ */
+static void *adapter_stat_thread_fn(void *context)
+{
+ struct drv_s *p_drv = context;
+ ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ const char *const p_adapter_id_str _unused =
+ p_nt_drv->adapter_info.mp_adapter_id_str;
+
+ NT_LOG(DBG, ETHDEV, "%s: %s: begin\n", p_adapter_id_str, __func__);
+
+ assert(p_nthw_stat);
+
+ uint64_t n_loop_iter_cnt = 0;
+
+ while (!p_drv->ntdrv.b_shutdown) {
+ usleep(100 * 100);
+
+ nthw_stat_trigger(p_nthw_stat);
+
+ uint32_t loop = 0;
+
+ while ((!p_drv->ntdrv.b_shutdown) &&
+ (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) {
+ usleep(1 * 100);
+
+ if (nt_log_is_debug(NT_LOG_MODULE_ETHDEV) &&
+ (++loop & 0x3fff) == 0) {
+ uint32_t sf_ram_of =
+ nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat->mp_nthw_rmc);
+ uint32_t descr_fifo_of =
+ nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat->mp_nthw_rmc);
+
+ uint32_t dbg_merge =
+ nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc);
+ uint32_t mac_if_err =
+ nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc);
+
+ NT_LOG(ERR, ETHDEV, "Statistics DMA frozen\n");
+ NT_LOG(ERR, ETHDEV,
+ "SF RAM Overflow : %08x\n",
+ sf_ram_of);
+ NT_LOG(ERR, ETHDEV,
+ "Descr Fifo Overflow : %08x\n",
+ descr_fifo_of);
+ NT_LOG(ERR, ETHDEV,
+ "DBG Merge : %08x\n",
+ dbg_merge);
+ NT_LOG(ERR, ETHDEV,
+ "MAC If Errors : %08x\n",
+ mac_if_err);
+ }
+ }
+
+ /* Check then collect */
+ {
+ pthread_mutex_lock(&p_nt_drv->stat_lck);
+ nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat);
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+ }
+ n_loop_iter_cnt++;
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: %s: end\n", p_adapter_id_str, __func__);
+
+ return NULL;
+}
+
+static struct {
+ struct rte_pci_device *vpf_dev;
+ struct rte_eth_devargs eth_da;
+ int portqueues[MAX_FPGA_VIRTUAL_PORTS_SUPPORTED];
+ uint16_t pf_backer_port_id;
+} rep;
+
+static int nthw_pci_dev_init(struct rte_pci_device *pci_dev)
+{
+ int res;
+ struct drv_s *p_drv;
+ ntdrv_4ga_t *p_nt_drv;
+ fpga_info_t *fpga_info;
+
+ hw_info_t *p_hw_info _unused;
+ uint32_t n_port_mask = -1; /* All ports enabled by default */
+ uint32_t nb_rx_queues = 1;
+ uint32_t nb_tx_queues = 1;
+ uint32_t exception_path = 0;
+ struct flow_queue_id_s queue_ids[FLOW_MAX_QUEUES];
+ lag_config_t *lag_config = NULL;
+ int n_phy_ports;
+ struct port_link_speed pls_mbps[NUM_ADAPTER_PORTS_MAX] = { 0 };
+ int num_port_speeds = 0;
+ enum flow_eth_dev_profile profile;
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__);
+ NT_LOG(DBG, ETHDEV, "Dev %s PF #%i Init : %02x:%02x:%i\n",
+ pci_dev->name, pci_dev->addr.function, pci_dev->addr.bus,
+ pci_dev->addr.devid, pci_dev->addr.function);
+
+ /*
+ * Process options/arguments
+ */
+ if (pci_dev->device.devargs && pci_dev->device.devargs->args) {
+ int kvargs_count;
+ struct rte_kvargs *kvlist = rte_kvargs_parse(pci_dev->device.devargs->args,
+ valid_arguments);
+ if (kvlist == NULL)
+ return -1;
+
+ /*
+ * Argument: help
+ * NOTE: this argument/option check should be the first as it will stop
+ * execution after producing its output
+ */
+ {
+ if (rte_kvargs_get(kvlist, ETH_DEV_NTNIC_HELP_ARG)) {
+ size_t i;
+
+ printf("NTNIC supported arguments:\n\n");
+ for (i = 0; i < RTE_DIM(valid_arguments); i++) {
+ if (valid_arguments[i] == NULL)
+ break;
+ printf(" %s\n", valid_arguments[i]);
+ }
+ printf("\n");
+ exit(0);
+ }
+ }
+
+ /*
+ * Argument: supported-fpgas=list|verbose
+ * NOTE: this argument/option check should be the first as it will stop
+ * execution after producing its output
+ */
+ {
+ const char *val_str;
+
+ val_str = rte_kvargs_get(kvlist,
+ ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG);
+ if (val_str) {
+ int detail_level = 0;
+ nt_fpga_mgr_t *p_fpga_mgr = NULL;
+
+ if (strcmp(val_str, "list") == 0) {
+ detail_level = 0;
+ } else if (strcmp(val_str, "verbose") == 0) {
+ detail_level = 1;
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "%s: argument '%s': '%s': unsupported value\n",
+ __func__,
+ ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG,
+ val_str);
+ exit(1);
+ }
+ /* Produce fpgamgr output and exit hard */
+ p_fpga_mgr = fpga_mgr_new();
+ if (p_fpga_mgr) {
+ fpga_mgr_init(p_fpga_mgr);
+ fpga_mgr_show(p_fpga_mgr, stdout,
+ detail_level);
+ fpga_mgr_delete(p_fpga_mgr);
+ p_fpga_mgr = NULL;
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "%s: %s cannot complete\n",
+ __func__,
+ ETH_DEV_NTNIC_SUPPORTED_FPGAS_ARG);
+ exit(1);
+ }
+ exit(0);
+ }
+ }
+
+ /* link_speed options/argument only applicable for physical ports. */
+ num_port_speeds =
+ rte_kvargs_count(kvlist, ETH_DEV_NTHW_LINK_SPEED_ARG);
+ if (num_port_speeds) {
+ assert(num_port_speeds <= NUM_ADAPTER_PORTS_MAX);
+ void *pls_mbps_ptr = &pls_mbps[0];
+
+ res = rte_kvargs_process(kvlist,
+ ETH_DEV_NTHW_LINK_SPEED_ARG,
+ &string_to_port_link_speed,
+ &pls_mbps_ptr);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with port link speed command "
+ "line arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ for (int i = 0; i < num_port_speeds; ++i) {
+ int pid = pls_mbps[i].port_id;
+
+ int lspeed _unused = pls_mbps[i].link_speed;
+
+ NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%d.%d\n",
+ __func__, ETH_DEV_NTHW_LINK_SPEED_ARG,
+ pid, lspeed);
+ if (pls_mbps[i].port_id >=
+ NUM_ADAPTER_PORTS_MAX) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with port link speed command line "
+ "arguments: port id should be 0 to %d, got %d\n",
+ __func__, NUM_ADAPTER_PORTS_MAX,
+ pid);
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * portmask option/argument
+ * It is intentional that portmask is only used to decide if DPDK eth_dev
+ * should be created for testing we would still keep the nthw subsystems
+ * running for all interfaces
+ */
+ kvargs_count =
+ rte_kvargs_count(kvlist, ETH_DEV_NTHW_PORTMASK_ARG);
+ if (kvargs_count) {
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist,
+ ETH_DEV_NTHW_PORTMASK_ARG,
+ &string_to_u32, &n_port_mask);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__,
+ ETH_DEV_NTHW_PORTMASK_ARG, n_port_mask);
+ }
+
+ /*
+ * rxq option/argument
+ * The number of rxq (hostbuffers) allocated in memory.
+ * Default is 32 RX Hostbuffers
+ */
+ kvargs_count =
+ rte_kvargs_count(kvlist, ETH_DEV_NTHW_RXQUEUES_ARG);
+ if (kvargs_count) {
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist,
+ ETH_DEV_NTHW_RXQUEUES_ARG,
+ &string_to_u32, &nb_rx_queues);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__,
+ ETH_DEV_NTHW_RXQUEUES_ARG, nb_rx_queues);
+ }
+
+ /*
+ * txq option/argument
+ * The number of txq (hostbuffers) allocated in memory.
+ * Default is 32 TX Hostbuffers
+ */
+ kvargs_count =
+ rte_kvargs_count(kvlist, ETH_DEV_NTHW_TXQUEUES_ARG);
+ if (kvargs_count) {
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist,
+ ETH_DEV_NTHW_TXQUEUES_ARG,
+ &string_to_u32, &nb_tx_queues);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__,
+ ETH_DEV_NTHW_TXQUEUES_ARG, nb_tx_queues);
+ }
+
+ kvargs_count = rte_kvargs_count(kvlist, ETH_NTNIC_LAG_MODE_ARG);
+ if (kvargs_count) {
+ lag_config = (lag_config_t *)rte_zmalloc(NULL, sizeof(lag_config_t), 0);
+ if (lag_config == NULL) {
+ NT_LOG(ERR, ETHDEV,
+ "Failed to alloc lag_config data\n");
+ return -1;
+ }
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist, ETH_NTNIC_LAG_MODE_ARG,
+ &string_to_u32,
+ &lag_config->mode);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__,
+ ETH_NTNIC_LAG_MODE_ARG, nb_tx_queues);
+ lag_active = 1;
+ }
+
+ kvargs_count = rte_kvargs_count(kvlist,
+ ETH_DEV_NTHW_EXCEPTION_PATH_ARG);
+ if (kvargs_count) {
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist,
+ ETH_DEV_NTHW_EXCEPTION_PATH_ARG,
+ &string_to_u32, &exception_path);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: devargs: %s=%u\n", __func__,
+ ETH_DEV_NTHW_EXCEPTION_PATH_ARG, exception_path);
+ }
+
+ if (lag_active && lag_config) {
+ switch (lag_config->mode) {
+ case BONDING_MODE_ACTIVE_BACKUP:
+ NT_LOG(DBG, ETHDEV,
+ "Active / Backup LAG mode\n");
+ kvargs_count = rte_kvargs_count(kvlist,
+ ETH_NTNIC_LAG_PRIMARY_ARG);
+ if (kvargs_count) {
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist,
+ ETH_NTNIC_LAG_PRIMARY_ARG,
+ &string_to_u32,
+ &lag_config->primary_port);
+ if (res < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line "
+ "arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV,
+ "%s: devargs: %s=%u\n", __func__,
+ ETH_NTNIC_LAG_MODE_ARG,
+ nb_tx_queues);
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "LAG must define a primary port\n");
+ return -1;
+ }
+
+ kvargs_count = rte_kvargs_count(kvlist,
+ ETH_NTNIC_LAG_BACKUP_ARG);
+ if (kvargs_count) {
+ assert(kvargs_count == 1);
+ res = rte_kvargs_process(kvlist,
+ ETH_NTNIC_LAG_BACKUP_ARG,
+ &string_to_u32,
+ &lag_config->backup_port);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: problem with command line "
+ "arguments: res=%d\n",
+ __func__, res);
+ return -1;
+ }
+ NT_LOG(DBG, ETHDEV,
+ "%s: devargs: %s=%u\n", __func__,
+ ETH_NTNIC_LAG_MODE_ARG,
+ nb_tx_queues);
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "LAG must define a backup port\n");
+ return -1;
+ }
+ break;
+
+ case BONDING_MODE_8023AD:
+ NT_LOG(DBG, ETHDEV,
+ "Active / Active LAG mode\n");
+ lag_config->primary_port = 0;
+ lag_config->backup_port = 0;
+ break;
+
+ default:
+ NT_LOG(ERR, ETHDEV, "Unsupported LAG mode\n");
+ return -1;
+ }
+ }
+
+ rte_kvargs_free(kvlist);
+ }
+
+ /* parse representor args */
+ if (setup_virtual_pf_representor_base(pci_dev) == -1) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: setup_virtual_pf_representor_base error %d (%s:%u)\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), -1, __func__,
+ __LINE__);
+ return -1;
+ }
+
+ /* alloc */
+ p_drv = rte_zmalloc_socket(pci_dev->name, sizeof(struct drv_s),
+ RTE_CACHE_LINE_SIZE,
+ pci_dev->device.numa_node);
+ if (!p_drv) {
+ NT_LOG(ERR, ETHDEV, "%s: error %d (%s:%u)\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), -1, __func__,
+ __LINE__);
+ return -1;
+ }
+
+ /* Setup VFIO context */
+ int vfio = nt_vfio_setup(pci_dev);
+
+ if (vfio < 0) {
+ NT_LOG(ERR, ETHDEV, "%s: vfio_setup error %d (%s:%u)\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), -1, __func__,
+ __LINE__);
+ rte_free(p_drv);
+ return -1;
+ }
+
+ p_drv->probe_finished = 0;
+ /* context */
+ p_nt_drv = &p_drv->ntdrv;
+ fpga_info = &p_nt_drv->adapter_info.fpga_info;
+ p_hw_info = &p_nt_drv->adapter_info.hw_info;
+
+ p_drv->p_dev = pci_dev;
+
+ /* Set context for NtDrv */
+ p_nt_drv->pciident =
+ BDF_TO_PCIIDENT(pci_dev->addr.domain, pci_dev->addr.bus,
+ pci_dev->addr.devid, pci_dev->addr.function);
+ p_nt_drv->adapter_info.n_rx_host_buffers = nb_rx_queues;
+ p_nt_drv->adapter_info.n_tx_host_buffers = nb_tx_queues;
+
+ fpga_info->bar0_addr = (void *)pci_dev->mem_resource[0].addr;
+ fpga_info->bar0_size = pci_dev->mem_resource[0].len;
+ NT_LOG(DBG, ETHDEV, "bar0=0x%" PRIX64 " len=%d\n", fpga_info->bar0_addr,
+ fpga_info->bar0_size);
+ fpga_info->numa_node = pci_dev->device.numa_node;
+ fpga_info->pciident = p_nt_drv->pciident;
+ fpga_info->adapter_no = p_drv->adapter_no;
+
+ p_nt_drv->adapter_info.hw_info.pci_class_id = pci_dev->id.class_id;
+ p_nt_drv->adapter_info.hw_info.pci_vendor_id = pci_dev->id.vendor_id;
+ p_nt_drv->adapter_info.hw_info.pci_device_id = pci_dev->id.device_id;
+ p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id =
+ pci_dev->id.subsystem_vendor_id;
+ p_nt_drv->adapter_info.hw_info.pci_sub_device_id =
+ pci_dev->id.subsystem_device_id;
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: " PCIIDENT_PRINT_STR " %04X:%04X: %04X:%04X:\n",
+ p_nt_drv->adapter_info.mp_adapter_id_str,
+ PCIIDENT_TO_DOMAIN(p_nt_drv->pciident),
+ PCIIDENT_TO_BUSNR(p_nt_drv->pciident),
+ PCIIDENT_TO_DEVNR(p_nt_drv->pciident),
+ PCIIDENT_TO_FUNCNR(p_nt_drv->pciident),
+ p_nt_drv->adapter_info.hw_info.pci_vendor_id,
+ p_nt_drv->adapter_info.hw_info.pci_device_id,
+ p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id,
+ p_nt_drv->adapter_info.hw_info.pci_sub_device_id);
+
+ p_nt_drv->b_shutdown = false;
+ p_nt_drv->adapter_info.pb_shutdown = &p_nt_drv->b_shutdown;
+
+ for (int i = 0; i < num_port_speeds; ++i) {
+ struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
+ nt_link_speed_t link_speed =
+ convert_link_speed(pls_mbps[i].link_speed);
+ nt4ga_port_set_link_speed(p_adapter_info, i, link_speed);
+ }
+
+ /* store context */
+ store_pdrv(p_drv);
+
+ /* initialize nt4ga nthw fpga module instance in drv */
+ int err = nt4ga_adapter_init(&p_nt_drv->adapter_info);
+
+ if (err != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot initialize the adapter instance\n",
+ p_nt_drv->adapter_info.mp_adapter_id_str);
+ return -1;
+ }
+
+ if (fpga_info->mp_nthw_epp != NULL)
+ nthw_eth_dev_ops.mtu_set = dev_set_mtu;
+
+ /* Initialize the queue system */
+ if (err == 0) {
+ err = nthw_virt_queue_init(fpga_info);
+ if (err != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot initialize scatter-gather queues\n",
+ p_nt_drv->adapter_info.mp_adapter_id_str);
+ } else {
+ NT_LOG(DBG, ETHDEV,
+ "%s: Initialized scatter-gather queues\n",
+ p_nt_drv->adapter_info.mp_adapter_id_str);
+ }
+ }
+
+ switch (fpga_info->profile) {
+ case FPGA_INFO_PROFILE_VSWITCH:
+ profile = FLOW_ETH_DEV_PROFILE_VSWITCH;
+ break;
+ case FPGA_INFO_PROFILE_INLINE:
+ profile = FLOW_ETH_DEV_PROFILE_INLINE;
+ break;
+ case FPGA_INFO_PROFILE_UNKNOWN:
+ /* fallthrough */
+ case FPGA_INFO_PROFILE_CAPTURE:
+ /* fallthrough */
+ default:
+ NT_LOG(ERR, ETHDEV, "%s: fpga profile not supported [%s:%u]\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), __func__,
+ __LINE__);
+ return -1;
+ }
+
+ if (err == 0) {
+ /* mp_adapter_id_str is initialized after nt4ga_adapter_init(p_nt_drv) */
+ const char *const p_adapter_id_str _unused =
+ p_nt_drv->adapter_info.mp_adapter_id_str;
+ NT_LOG(DBG, ETHDEV,
+ "%s: %s: AdapterPCI=" PCIIDENT_PRINT_STR
+ " Hw=0x%02X_rev%d PhyPorts=%d\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), p_adapter_id_str,
+ PCIIDENT_TO_DOMAIN(p_nt_drv->adapter_info.fpga_info.pciident),
+ PCIIDENT_TO_BUSNR(p_nt_drv->adapter_info.fpga_info.pciident),
+ PCIIDENT_TO_DEVNR(p_nt_drv->adapter_info.fpga_info.pciident),
+ PCIIDENT_TO_FUNCNR(p_nt_drv->adapter_info.fpga_info.pciident),
+ p_hw_info->hw_platform_id, fpga_info->nthw_hw_info.hw_id,
+ fpga_info->n_phy_ports);
+ } else {
+ NT_LOG(ERR, ETHDEV, "%s: error=%d [%s:%u]\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), err, __func__,
+ __LINE__);
+ return -1;
+ }
+
+ pthread_mutex_init(&p_nt_drv->stat_lck, NULL);
+ res = rte_ctrl_thread_create(&p_nt_drv->stat_thread, "nt4ga_stat_thr",
+ NULL, adapter_stat_thread_fn,
+ (void *)p_drv);
+ if (res) {
+ NT_LOG(ERR, ETHDEV, "%s: error=%d [%s:%u]\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), res, __func__,
+ __LINE__);
+ return -1;
+ }
+
+ if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
+ res = rte_ctrl_thread_create(&p_nt_drv->flm_thread,
+ "nt_flm_stat_thr", NULL,
+ adapter_flm_thread_fn,
+ (void *)p_drv);
+ if (res) {
+ NT_LOG(ERR, ETHDEV, "%s: error=%d [%s:%u]\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), res,
+ __func__, __LINE__);
+ return -1;
+ }
+ }
+
+ if (lag_config) {
+ /* LAG is activated, so only use port 0 */
+ n_phy_ports = 1;
+ } else {
+ n_phy_ports = fpga_info->n_phy_ports;
+ }
+ for (int n_intf_no = 0; n_intf_no < n_phy_ports; n_intf_no++) {
+ const char *const p_port_id_str _unused =
+ p_nt_drv->adapter_info.mp_port_id_str[n_intf_no];
+ struct pmd_internals *internals = NULL;
+ struct rte_eth_dev *eth_dev;
+ char name[32];
+ int i;
+
+ if ((1 << n_intf_no) & ~n_port_mask) {
+ NT_LOG(DBG, ETHDEV,
+ "%s: %s: interface #%d: skipping due to portmask 0x%02X\n",
+ __func__, p_port_id_str, n_intf_no, n_port_mask);
+ continue;
+ }
+
+ snprintf(name, sizeof(name), "ntnic%d", n_intf_no);
+ NT_LOG(DBG, ETHDEV, "%s: %s: interface #%d: %s: '%s'\n",
+ __func__, p_port_id_str, n_intf_no,
+ (pci_dev->name[0] ? pci_dev->name : "NA"), name);
+
+ internals = rte_zmalloc_socket(name,
+ sizeof(struct pmd_internals),
+ RTE_CACHE_LINE_SIZE,
+ pci_dev->device.numa_node);
+ if (!internals) {
+ NT_LOG(ERR, ETHDEV, "%s: %s: error=%d [%s:%u]\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), name,
+ -1, __func__, __LINE__);
+ return -1;
+ }
+
+ internals->pci_dev = pci_dev;
+ internals->n_intf_no = n_intf_no;
+ internals->if_index = n_intf_no;
+ internals->min_tx_pkt_size = 64;
+ internals->max_tx_pkt_size = 10000;
+ internals->type = PORT_TYPE_PHYSICAL;
+ internals->vhid = -1;
+ internals->port = n_intf_no;
+ internals->nb_rx_queues = nb_rx_queues;
+ internals->nb_tx_queues = nb_tx_queues;
+
+ /* Not used queue index as dest port in bypass - use 0x80 + port nr */
+ for (i = 0; i < MAX_QUEUES; i++)
+ internals->vpq[i].hw_id = -1;
+
+ /* Setup queue_ids */
+ if (nb_rx_queues > 1) {
+ NT_LOG(DBG, ETHDEV,
+ "(%i) NTNIC configured with Rx multi queues. %i queues\n",
+ 0 /*port*/, nb_rx_queues);
+ }
+
+ if (nb_tx_queues > 1) {
+ NT_LOG(DBG, ETHDEV,
+ "(%i) NTNIC configured with Tx multi queues. %i queues\n",
+ 0 /*port*/, nb_tx_queues);
+ }
+
+ int max_num_queues = (nb_rx_queues > nb_tx_queues) ?
+ nb_rx_queues :
+ nb_tx_queues;
+ int start_queue = allocate_queue(max_num_queues);
+
+ if (start_queue < 0)
+ return -1;
+
+ for (i = 0; i < (int)max_num_queues; i++) {
+ queue_ids[i].id = start_queue + i;
+ queue_ids[i].hw_id = queue_ids[i].id;
+
+ internals->rxq_scg[i].queue = queue_ids[i];
+ /* use same index in Rx and Tx rings */
+ internals->txq_scg[i].queue = queue_ids[i];
+ internals->rxq_scg[i].enabled = 0;
+ internals->txq_scg[i].type = internals->type;
+ internals->rxq_scg[i].type = internals->type;
+ internals->rxq_scg[i].port = internals->port;
+ }
+
+ /* no tx queues - tx data goes out on phy */
+ internals->vpq_nb_vq = 0;
+
+ for (i = 0; i < (int)nb_tx_queues; i++) {
+ internals->txq_scg[i].port = internals->port;
+ internals->txq_scg[i].enabled = 0;
+ }
+
+ /* Set MAC address (but only if the MAC address is permitted) */
+ if (n_intf_no < fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count) {
+ const uint64_t mac =
+ fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value +
+ n_intf_no;
+ internals->eth_addrs[0].addr_bytes[0] = (mac >> 40) &
+ 0xFFu;
+ internals->eth_addrs[0].addr_bytes[1] = (mac >> 32) &
+ 0xFFu;
+ internals->eth_addrs[0].addr_bytes[2] = (mac >> 24) &
+ 0xFFu;
+ internals->eth_addrs[0].addr_bytes[3] = (mac >> 16) &
+ 0xFFu;
+ internals->eth_addrs[0].addr_bytes[4] = (mac >> 8) &
+ 0xFFu;
+ internals->eth_addrs[0].addr_bytes[5] = (mac >> 0) &
+ 0xFFu;
+ }
+
+ eth_dev = rte_eth_dev_allocate(name);
+ if (!eth_dev) {
+ NT_LOG(ERR, ETHDEV, "%s: %s: error=%d [%s:%u]\n",
+ (pci_dev->name[0] ? pci_dev->name : "NA"), name,
+ -1, __func__, __LINE__);
+ return -1;
+ }
+
+ internals->flw_dev = flow_get_eth_dev(0, n_intf_no,
+ eth_dev->data->port_id,
+ nb_rx_queues,
+ queue_ids,
+ &internals->txq_scg[0].rss_target_id,
+ profile, exception_path);
+ if (!internals->flw_dev) {
+ NT_LOG(ERR, VDPA,
+ "Error creating port. Resource exhaustion in HW\n");
+ return -1;
+ }
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: [%s:%u] eth_dev %p, port_id %u, if_index %u\n",
+ __func__, __func__, __LINE__, eth_dev,
+ eth_dev->data->port_id, n_intf_no);
+
+ /* connect structs */
+ internals->p_drv = p_drv;
+ eth_dev->data->dev_private = internals;
+ eth_dev->data->mac_addrs = internals->eth_addrs;
+
+ internals->port_id = eth_dev->data->port_id;
+
+ /*
+ * if representor ports defined on this PF set the assigned port_id as the
+ * backer_port_id for the VFs
+ */
+ if (rep.vpf_dev == pci_dev)
+ rep.pf_backer_port_id = eth_dev->data->port_id;
+ NT_LOG(DBG, ETHDEV,
+ "%s: [%s:%u] Setting up RX functions for SCG\n",
+ __func__, __func__, __LINE__);
+ eth_dev->rx_pkt_burst = eth_dev_rx_scg;
+ eth_dev->tx_pkt_burst = eth_dev_tx_scg;
+ eth_dev->tx_pkt_prepare = NULL;
+
+ struct rte_eth_link pmd_link;
+
+ pmd_link.link_speed = ETH_SPEED_NUM_NONE;
+ pmd_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ pmd_link.link_status = ETH_LINK_DOWN;
+ pmd_link.link_autoneg = ETH_LINK_AUTONEG;
+
+ eth_dev->device = &pci_dev->device;
+ eth_dev->data->dev_link = pmd_link;
+ eth_dev->data->numa_node = pci_dev->device.numa_node;
+ eth_dev->dev_ops = &nthw_eth_dev_ops;
+ eth_dev->state = RTE_ETH_DEV_ATTACHED;
+
+ rte_eth_copy_pci_info(eth_dev, pci_dev);
+ eth_dev_pci_specific_init(eth_dev,
+ pci_dev); /* performs rte_eth_copy_pci_info() */
+
+ p_drv->n_eth_dev_init_count++;
+
+ if (lag_config) {
+ internals->lag_config = lag_config;
+ lag_config->internals = internals;
+
+ /* Always merge port 0 and port 1 on a LAG bond */
+ lag_set_port_group(0, (uint32_t)0x01);
+ lag_config->lag_thread_active = 1;
+ pthread_create(&lag_config->lag_tid, NULL,
+ lag_management, lag_config);
+ }
+
+ if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE &&
+ internals->flw_dev->ndev->be.tpe.ver >= 2) {
+ assert(nthw_eth_dev_ops.mtu_set ==
+ dev_set_mtu_inline ||
+ nthw_eth_dev_ops.mtu_set == NULL);
+ nthw_eth_dev_ops.mtu_set = dev_set_mtu_inline;
+ dev_set_mtu_inline(eth_dev, MTUINITVAL);
+ NT_LOG(DBG, ETHDEV,
+ "%s INLINE MTU supported, tpe version %d\n",
+ __func__, internals->flw_dev->ndev->be.tpe.ver);
+ } else {
+ NT_LOG(DBG, ETHDEV, "INLINE MTU not supported");
+ }
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] leave\n", __func__, __FILE__, __LINE__);
+
+#ifdef NT_TOOLS
+ /*
+ * If NtConnect interface must be started for external tools
+ */
+ ntconn_adap_register(p_drv);
+ ntconn_stat_register(p_drv);
+
+ /* Determine CPU used by the DPDK */
+ cpu_set_t cpuset;
+ unsigned int lcore_id;
+
+ CPU_ZERO(&cpuset);
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ if (rte_lcore_has_role(lcore_id, ROLE_OFF))
+ continue;
+ rte_cpuset_t lcore_cpuset = rte_lcore_cpuset(lcore_id);
+
+ RTE_CPU_OR(&cpuset, &cpuset, &lcore_cpuset);
+ }
+ /* Set available CPU for ntconnect */
+ RTE_CPU_NOT(&cpuset, &cpuset);
+
+ ntconn_flow_register(p_drv);
+ ntconn_meter_register(p_drv);
+#ifdef NTCONNECT_TEST
+ ntconn_test_register(p_drv);
+#endif
+ ntconnect_init(NTCONNECT_SOCKET, cpuset);
+#endif
+
+ return 0;
+}
+
+static int nthw_pci_dev_deinit(struct rte_eth_dev *eth_dev __rte_unused)
+{
+ int i;
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__);
+
+ struct pmd_internals *internals = pmd_intern_base;
+
+ sleep(1); /* let running threads end Rx and Tx activity */
+
+ while (internals) {
+ for (i = internals->nb_tx_queues - 1; i >= 0; i--) {
+ nthw_release_managed_tx_virt_queue(internals->txq_scg[i].vq);
+ release_hw_virtio_queues(&internals->txq_scg[i].hwq);
+ }
+
+ for (i = internals->nb_rx_queues - 1; i >= 0; i--) {
+ nthw_release_managed_rx_virt_queue(internals->rxq_scg[i].vq);
+ release_hw_virtio_queues(&internals->rxq_scg[i].hwq);
+ }
+ internals = internals->next;
+ }
+
+ for (i = 0; i < MAX_REL_VQS; i++) {
+ if (rel_virt_queue[i].vq != NULL) {
+ if (rel_virt_queue[i].rx) {
+ if (rel_virt_queue[i].managed)
+ nthw_release_managed_rx_virt_queue(rel_virt_queue[i].vq);
+ else
+ nthw_release_rx_virt_queue(rel_virt_queue[i].vq);
+ } else {
+ if (rel_virt_queue[i].managed)
+ nthw_release_managed_tx_virt_queue(rel_virt_queue[i].vq);
+ else
+ nthw_release_tx_virt_queue(rel_virt_queue[i].vq);
+ }
+ rel_virt_queue[i].vq = NULL;
+ }
+ }
+
+ nt_vfio_remove(EXCEPTION_PATH_HID);
+
+ return 0;
+}
+
+static void signal_handler_func_int(int sig)
+{
+ if (sig != SIGINT) {
+ signal(sig, previous_handler);
+ raise(sig);
+ return;
+ }
+ kill_pmd = 1;
+}
+
+static void *shutdown_thread(void *arg __rte_unused)
+{
+ struct rte_eth_dev dummy;
+
+ while (!kill_pmd)
+ usleep(100000);
+
+ NT_LOG(DBG, ETHDEV, "%s: Shutting down because of ctrl+C\n", __func__);
+ nthw_pci_dev_deinit(&dummy);
+
+ signal(SIGINT, previous_handler);
+ raise(SIGINT);
+
+ return NULL;
+}
+
+static int init_shutdown(void)
+{
+ NT_LOG(DBG, ETHDEV, "%s: Starting shutdown handler\n", __func__);
+ kill_pmd = 0;
+ previous_handler = signal(SIGINT, signal_handler_func_int);
+ pthread_create(&shutdown_tid, NULL, shutdown_thread, NULL);
+
+ /*
+ * 1 time calculation of 1 sec stat update rtc cycles to prevent stat poll
+ * flooding by OVS from multiple virtual port threads - no need to be precise
+ */
+ uint64_t now_rtc = rte_get_tsc_cycles();
+
+ usleep(10000);
+ rte_tsc_freq = 100 * (rte_get_tsc_cycles() - now_rtc);
+
+ return 0;
+}
+
+static int nthw_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ int res;
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__);
+
+#if defined(DEBUG)
+ NT_LOG(DBG, NTHW, "Testing NTHW %u [%s:%u]\n",
+ nt_log_module_logtype[NT_LOG_MODULE_INDEX(NT_LOG_MODULE_NTHW)],
+ __func__, __LINE__);
+#endif
+
+ NT_LOG(DBG, ETHDEV, "%s: pcidev: name: '%s'\n", __func__,
+ pci_dev->name);
+ NT_LOG(DBG, ETHDEV, "%s: devargs: name: '%s'\n", __func__,
+ pci_dev->device.name);
+ if (pci_dev->device.devargs) {
+ NT_LOG(DBG, ETHDEV, "%s: devargs: args: '%s'\n", __func__,
+ (pci_dev->device.devargs->args ?
+ pci_dev->device.devargs->args :
+ "NULL"));
+ NT_LOG(DBG, ETHDEV, "%s: devargs: data: '%s'\n", __func__,
+ (pci_dev->device.devargs->data ?
+ pci_dev->device.devargs->data :
+ "NULL"));
+ }
+
+ const int n_rte_has_pci = rte_eal_has_pci();
+
+ NT_LOG(DBG, ETHDEV, "has_pci=%d\n", n_rte_has_pci);
+ if (n_rte_has_pci == 0) {
+ NT_LOG(ERR, ETHDEV, "has_pci=%d: this PMD needs hugepages\n",
+ n_rte_has_pci);
+ return -1;
+ }
+
+ const int n_rte_vfio_no_io_mmu_enabled = rte_vfio_noiommu_is_enabled();
+
+ NT_LOG(DBG, ETHDEV, "vfio_no_iommu_enabled=%d\n",
+ n_rte_vfio_no_io_mmu_enabled);
+ if (n_rte_vfio_no_io_mmu_enabled) {
+ NT_LOG(ERR, ETHDEV,
+ "vfio_no_iommu_enabled=%d: this PMD needs VFIO IOMMU\n",
+ n_rte_vfio_no_io_mmu_enabled);
+ return -1;
+ }
+
+ const enum rte_iova_mode n_rte_io_va_mode = rte_eal_iova_mode();
+
+ NT_LOG(DBG, ETHDEV, "iova mode=%d\n", n_rte_io_va_mode);
+ if (n_rte_io_va_mode != RTE_IOVA_PA) {
+ NT_LOG(WRN, ETHDEV,
+ "iova mode (%d) should be PA for performance reasons\n",
+ n_rte_io_va_mode);
+ }
+
+ const int n_rte_has_huge_pages = rte_eal_has_hugepages();
+
+ NT_LOG(DBG, ETHDEV, "has_hugepages=%d\n", n_rte_has_huge_pages);
+ if (n_rte_has_huge_pages == 0) {
+ NT_LOG(ERR, ETHDEV,
+ "has_hugepages=%d: this PMD needs hugepages\n",
+ n_rte_has_huge_pages);
+ return -1;
+ }
+
+ NT_LOG(DBG, ETHDEV,
+ "busid=" PCI_PRI_FMT
+ " pciid=%04x:%04x_%04x:%04x locstr=%s @ numanode=%d: drv=%s drvalias=%s\n",
+ pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid,
+ pci_dev->addr.function, pci_dev->id.vendor_id,
+ pci_dev->id.device_id, pci_dev->id.subsystem_vendor_id,
+ pci_dev->id.subsystem_device_id,
+ pci_dev->name[0] ? pci_dev->name : "NA", /* locstr */
+ pci_dev->device.numa_node,
+ pci_dev->driver->driver.name ? pci_dev->driver->driver.name :
+ "NA",
+ pci_dev->driver->driver.alias ? pci_dev->driver->driver.alias :
+ "NA");
+
+ if (pci_dev->id.vendor_id == NT_HW_PCI_VENDOR_ID) {
+ if (pci_dev->id.device_id == NT_HW_PCI_DEVICE_ID_NT200A01 ||
+ pci_dev->id.device_id == NT_HW_PCI_DEVICE_ID_NT50B01) {
+ if (pci_dev->id.subsystem_device_id != 0x01) {
+ NT_LOG(DBG, ETHDEV,
+ "%s: PCIe bifurcation - secondary endpoint "
+ "found - leaving probe\n",
+ __func__);
+ return -1;
+ }
+ }
+ }
+
+ res = nthw_pci_dev_init(pci_dev);
+
+ init_shutdown();
+
+ NT_LOG(DBG, ETHDEV, "%s: leave: res=%d\n", __func__, res);
+ return res;
+}
+
+static int nthw_pci_remove(struct rte_pci_device *pci_dev)
+{
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+
+ return rte_eth_dev_pci_generic_remove(pci_dev, nthw_pci_dev_deinit);
+}
+
+static int nt_log_init_impl(void)
+{
+ rte_log_set_global_level(RTE_LOG_DEBUG);
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+
+ for (int i = NT_LOG_MODULE_GENERAL; i < NT_LOG_MODULE_END; ++i) {
+ int index = NT_LOG_MODULE_INDEX(i);
+
+ nt_log_module_logtype[index] =
+ rte_log_register_type_and_pick_level(nt_log_module_eal_name[index],
+ RTE_LOG_INFO);
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: [%s:%u]\n", __func__, __func__, __LINE__);
+
+ return 0;
+}
+
+static int nt_log_log_impl(enum nt_log_level level, uint32_t module,
+ const char *format, va_list args)
+{
+ uint32_t rte_level = 0;
+ uint32_t rte_module = 0;
+
+ switch (level) {
+ case NT_LOG_ERR:
+ rte_level = RTE_LOG_ERR;
+ break;
+ case NT_LOG_WRN:
+ rte_level = RTE_LOG_WARNING;
+ break;
+ case NT_LOG_INF:
+ rte_level = RTE_LOG_INFO;
+ break;
+ default:
+ rte_level = RTE_LOG_DEBUG;
+ }
+
+ rte_module =
+ (module >= NT_LOG_MODULE_GENERAL &&
+ module < NT_LOG_MODULE_END) ?
+ (uint32_t)nt_log_module_logtype[NT_LOG_MODULE_INDEX(module)] : module;
+
+ return (int)rte_vlog(rte_level, rte_module, format, args);
+}
+
+static int nt_log_is_debug_impl(uint32_t module)
+{
+ if (module < NT_LOG_MODULE_GENERAL || module >= NT_LOG_MODULE_END)
+ return -1;
+ int index = NT_LOG_MODULE_INDEX(module);
+
+ return rte_log_get_level(nt_log_module_logtype[index]) == RTE_LOG_DEBUG;
+}
+
+RTE_INIT(ntnic_rte_init); /* must go before function */
+
+static void ntnic_rte_init(void)
+{
+ static struct nt_log_impl impl = { .init = &nt_log_init_impl,
+ .log = &nt_log_log_impl,
+ .is_debug = &nt_log_is_debug_impl
+ };
+
+ nt_log_init(&impl);
+}
+
+static struct rte_pci_driver rte_nthw_pmd = {
+ .driver = {
+ .name = "net_ntnic",
+ },
+
+ .id_table = nthw_pci_id_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = nthw_pci_probe,
+ .remove = nthw_pci_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_ntnic, rte_nthw_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_ntnic, nthw_pci_id_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_ntnic, "* vfio-pci");
+
+/*
+ * VF and VDPA code
+ */
+int register_release_virtqueue_info(struct nthw_virt_queue *vq, int rx,
+ int managed)
+{
+ int i;
+
+ for (i = 0; i < MAX_REL_VQS; i++) {
+ if (rel_virt_queue[i].vq == NULL) {
+ rel_virt_queue[i].vq = vq;
+ rel_virt_queue[i].rx = rx;
+ rel_virt_queue[i].managed = managed;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int de_register_release_virtqueue_info(struct nthw_virt_queue *vq)
+{
+ int i;
+
+ for (i = 0; i < MAX_REL_VQS; i++) {
+ if (rel_virt_queue[i].vq == vq) {
+ rel_virt_queue[i].vq = NULL;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+struct pmd_internals *vp_vhid_instance_ready(int vhid)
+{
+ struct pmd_internals *intern = pmd_intern_base;
+
+ while (intern) {
+ if (intern->vhid == vhid)
+ return intern;
+ intern = intern->next;
+ }
+ return NULL;
+}
+
+struct pmd_internals *vp_path_instance_ready(const char *path)
+{
+ struct pmd_internals *intern = pmd_intern_base;
+
+ while (intern) {
+ printf("Searching for path: \"%s\" == \"%s\" (%d)\n",
+ intern->vhost_path, path,
+ strcmp(intern->vhost_path, path));
+ if (strcmp(intern->vhost_path, path) == 0)
+ return intern;
+ intern = intern->next;
+ }
+ return NULL;
+}
+
+static void read_port_queues_mapping(char *str, int *portq)
+{
+ int len;
+ char *tok;
+
+ while (*str != '[' && *str != '\0')
+ str++;
+
+ if (*str == '\0')
+ return;
+ str++;
+ len = strlen(str);
+ char *str_e = &str[len];
+
+ while (*str_e != ']' && str_e != str)
+ str_e--;
+ if (*str_e != ']')
+ return;
+ *str_e = '\0';
+
+ tok = strtok(str, ",;");
+ while (tok) {
+ char *ch = strchr(tok, ':');
+
+ if (ch) {
+ *ch = '\0';
+ int port = atoi(tok);
+ int nvq = atoi(ch + 1);
+
+ if (port >= 0 &&
+ port < MAX_FPGA_VIRTUAL_PORTS_SUPPORTED &&
+ nvq > 0 && nvq < MAX_QUEUES)
+ portq[port] = nvq;
+ }
+
+ tok = strtok(NULL, ",;");
+ }
+}
+
+int setup_virtual_pf_representor_base(struct rte_pci_device *dev)
+{
+ struct rte_eth_devargs eth_da;
+
+ eth_da.nb_representor_ports = 0U;
+ if (dev->device.devargs && dev->device.devargs->args) {
+ char *ch = strstr(dev->device.devargs->args, "portqueues");
+
+ if (ch) {
+ read_port_queues_mapping(ch, rep.portqueues);
+ /*
+ * Remove this extension. DPDK cannot read representor=[x] if added
+ * parameter to the end
+ */
+ *ch = '\0';
+ }
+
+ int err = rte_eth_devargs_parse(dev->device.devargs->args,
+ ð_da);
+ if (err) {
+ rte_errno = -err;
+ NT_LOG(ERR, VDPA,
+ "failed to process device arguments: %s",
+ strerror(rte_errno));
+ return -1;
+ }
+
+ if (eth_da.nb_representor_ports) {
+ rep.vpf_dev = dev;
+ rep.eth_da = eth_da;
+ }
+ }
+ /* Will be set later when assigned to this PF */
+ rep.pf_backer_port_id = RTE_MAX_ETHPORTS;
+ return eth_da.nb_representor_ports;
+}
+
+static inline struct rte_eth_dev *
+rte_eth_vdev_allocate(struct rte_pci_device *dev, const char *name,
+ size_t private_data_size, int *n_vq)
+{
+ static int next_rep_p;
+ struct rte_eth_dev *eth_dev = NULL;
+
+ eth_dev = rte_eth_dev_allocate(name);
+ if (!eth_dev)
+ return NULL;
+
+ NT_LOG(DBG, VDPA, "%s: [%s:%u] eth_dev %p, port_id %u\n", __func__,
+ __func__, __LINE__, eth_dev, eth_dev->data->port_id);
+
+ if (private_data_size) {
+ eth_dev->data->dev_private = rte_zmalloc_socket(name, private_data_size,
+ RTE_CACHE_LINE_SIZE,
+ dev->device.numa_node);
+ if (!eth_dev->data->dev_private) {
+ rte_eth_dev_release_port(eth_dev);
+ return NULL;
+ }
+ }
+
+ eth_dev->intr_handle = NULL;
+ eth_dev->data->numa_node = dev->device.numa_node;
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
+
+ if (rep.vpf_dev && rep.eth_da.nb_representor_ports > next_rep_p) {
+ eth_dev->data->representor_id =
+ rep.eth_da.representor_ports[next_rep_p++];
+ eth_dev->device = &rep.vpf_dev->device;
+ eth_dev->data->backer_port_id = rep.pf_backer_port_id;
+ } else {
+ eth_dev->data->representor_id = nt_vfio_vf_num(dev);
+ eth_dev->device = &dev->device;
+ }
+
+ if (rep.portqueues[eth_dev->data->representor_id])
+ *n_vq = rep.portqueues[eth_dev->data->representor_id];
+
+ else
+ *n_vq = 1;
+ return eth_dev;
+}
+
+static inline const char *
+rte_vdev_device_name(const struct rte_pci_device *dev)
+{
+ if (dev && dev->device.name)
+ return dev->device.name;
+ return NULL;
+}
+
+static const char *const valid_args[] = {
+#define VP_VLAN_ID "vlan"
+ VP_VLAN_ID,
+#define VP_SEPARATE_SOCKET "sep"
+ VP_SEPARATE_SOCKET, NULL
+};
+
+static int rte_pmd_vp_init_internals(struct rte_pci_device *vdev,
+ struct rte_eth_dev **eth_dev)
+{
+ struct pmd_internals *internals = NULL;
+ struct rte_eth_dev_data *data = NULL;
+ int i;
+ struct rte_eth_link pmd_link;
+ int numa_node = vdev->device.numa_node;
+ const char *name;
+ int n_vq;
+ int num_queues;
+ uint8_t port;
+ uint32_t vlan = 0;
+ uint32_t separate_socket = 0;
+
+ enum fpga_info_profile fpga_profile =
+ get_fpga_profile_from_pci(vdev->addr);
+
+ name = rte_vdev_device_name(vdev);
+
+ /*
+ * Now do all data allocation - for eth_dev structure
+ * and internal (private) data
+ */
+
+ if (vdev && vdev->device.devargs) {
+ struct rte_kvargs *kvlist = NULL;
+
+ kvlist = rte_kvargs_parse(vdev->device.devargs->args,
+ valid_args);
+ if (!kvlist) {
+ NT_LOG(ERR, VDPA, "error when parsing param");
+ goto error;
+ }
+
+ if (rte_kvargs_count(kvlist, VP_VLAN_ID) == 1) {
+ if (rte_kvargs_process(kvlist, VP_VLAN_ID,
+ &string_to_u32, &vlan) < 0) {
+ NT_LOG(ERR, VDPA, "error to parse %s",
+ VP_VLAN_ID);
+ goto error;
+ }
+ }
+
+ if (rte_kvargs_count(kvlist, VP_SEPARATE_SOCKET) == 1) {
+ if (rte_kvargs_process(kvlist, VP_SEPARATE_SOCKET,
+ &string_to_u32,
+ &separate_socket) < 0) {
+ NT_LOG(ERR, VDPA, "error to parse %s",
+ VP_SEPARATE_SOCKET);
+ goto error;
+ }
+ }
+ }
+
+ n_vq = 0;
+ *eth_dev =
+ rte_eth_vdev_allocate(vdev, name, sizeof(*internals), &n_vq);
+ if (*eth_dev == NULL)
+ goto error;
+
+ data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+ if (data == NULL)
+ goto error;
+
+ NT_LOG(DBG, VDPA, "%s: [%s:%u] eth_dev %p, port_id %u, if_index %u\n",
+ __func__, __func__, __LINE__, *eth_dev,
+ (*eth_dev)->data->port_id, (*eth_dev)->data->representor_id);
+
+ port = (*eth_dev)->data->representor_id;
+
+ if (port < MAX_NTNIC_PORTS || port >= VIRTUAL_TUNNEL_PORT_OFFSET) {
+ NT_LOG(ERR, VDPA,
+ "(%i) Creating ntvp-backend ethdev on numa socket %i has invalid representor port\n",
+ port, numa_node);
+ return -1;
+ }
+ NT_LOG(DBG, VDPA,
+ "(%i) Creating ntnic-backend ethdev on numa socket %i\n", port,
+ numa_node);
+
+ /* Build up private dev data */
+ internals = (*eth_dev)->data->dev_private;
+ internals->pci_dev = vdev;
+ if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) {
+ internals->type = PORT_TYPE_VIRTUAL;
+ internals->nb_rx_queues = 1;
+ internals->nb_tx_queues = 1;
+ } else {
+ internals->type = PORT_TYPE_OVERRIDE;
+ internals->nb_rx_queues = n_vq;
+ internals->nb_tx_queues = n_vq;
+ }
+ internals->p_drv = get_pdrv_from_pci(vdev->addr);
+
+ if (n_vq > MAX_QUEUES) {
+ NT_LOG(ERR, VDPA,
+ "Error creating virtual port. Too many rx or tx queues. Max is %i\n",
+ MAX_QUEUES);
+ goto error;
+ }
+
+ if (n_vq > FLOW_MAX_QUEUES) {
+ NT_LOG(ERR, VDPA,
+ "Error creating virtual port. Too many rx or tx queues for NIC. Max reported %i\n",
+ FLOW_MAX_QUEUES);
+ goto error;
+ }
+
+ /* Initialize HB output dest to none */
+ for (i = 0; i < MAX_QUEUES; i++)
+ internals->vpq[i].hw_id = -1;
+
+ internals->vhid = -1;
+ internals->port = port;
+ internals->if_index = port;
+ internals->port_id = (*eth_dev)->data->port_id;
+ internals->vlan = vlan;
+
+ /*
+ * Create first time all queues in HW
+ */
+ struct flow_queue_id_s queue_ids[FLOW_MAX_QUEUES + 1];
+
+ if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH)
+ num_queues = n_vq + 1; /* add 1: 0th for exception */
+ else
+ num_queues = n_vq;
+
+ int start_queue = allocate_queue(num_queues);
+
+ if (start_queue < 0) {
+ NT_LOG(ERR, VDPA,
+ "Error creating virtual port. Too many rx queues. Could not allocate %i\n",
+ num_queues);
+ goto error;
+ }
+
+ int vhid = -1;
+
+ for (i = 0; i < num_queues; i++) {
+ queue_ids[i].id = start_queue + i; /* 0th is exception queue */
+ queue_ids[i].hw_id = start_queue + i;
+ }
+
+ if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) {
+ internals->txq_scg[0].rss_target_id = -1;
+ internals->flw_dev = flow_get_eth_dev(0, internals->port,
+ internals->port_id, num_queues,
+ queue_ids,
+ &internals->txq_scg[0].rss_target_id,
+ FLOW_ETH_DEV_PROFILE_VSWITCH, 0);
+ } else {
+ uint16_t in_port = internals->port & 1;
+ char name[RTE_ETH_NAME_MAX_LEN];
+ struct pmd_internals *main_internals;
+ struct rte_eth_dev *eth_dev;
+ int i;
+ int status;
+
+ /* Get name of in_port */
+ status = rte_eth_dev_get_name_by_port(in_port, name);
+ if (status != 0) {
+ NT_LOG(ERR, VDPA, "Name of port not found");
+ goto error;
+ }
+ NT_LOG(DBG, VDPA, "Name of port %u = %s\n", in_port, name);
+
+ /* Get ether device for in_port */
+ eth_dev = rte_eth_dev_get_by_name(name);
+ if (eth_dev == NULL) {
+ NT_LOG(ERR, VDPA, "Failed to get eth device");
+ goto error;
+ }
+
+ /* Get internals for in_port */
+ main_internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ NT_LOG(DBG, VDPA, "internals port %u\n\n",
+ main_internals->port);
+ if (main_internals->port != in_port) {
+ NT_LOG(ERR, VDPA, "Port did not match");
+ goto error;
+ }
+
+ /* Get flow device for in_port */
+ internals->flw_dev = main_internals->flw_dev;
+
+ for (i = 0; i < num_queues && i < MAX_QUEUES; i++) {
+ NT_LOG(DBG, VDPA, "Queue: %u\n",
+ queue_ids[i].id);
+ NT_LOG(DBG, VDPA, "HW ID: %u\n",
+ queue_ids[i].hw_id);
+ if (flow_eth_dev_add_queue(main_internals->flw_dev,
+ &queue_ids[i])) {
+ NT_LOG(ERR, VDPA, "Could not add queue");
+ goto error;
+ }
+ }
+ }
+
+ if (!internals->flw_dev) {
+ NT_LOG(ERR, VDPA,
+ "Error creating virtual port. Resource exhaustion in HW\n");
+ goto error;
+ }
+
+ char path[128];
+
+ if (!separate_socket) {
+ sprintf(path, "%sstdvio%i", DVIO_VHOST_DIR_NAME, port);
+ } else {
+ sprintf(path, "%sstdvio%i/stdvio%i", DVIO_VHOST_DIR_NAME, port,
+ port);
+ }
+
+ internals->vpq_nb_vq = n_vq;
+ if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) {
+ if (nthw_vdpa_init(vdev, (*eth_dev)->device->name, path,
+ queue_ids[1].hw_id, n_vq, n_vq,
+ internals->port, &vhid)) {
+ NT_LOG(ERR, VDPA,
+ "*********** ERROR *********** vDPA RELAY INIT\n");
+ goto error;
+ }
+ for (i = 0; i < n_vq; i++) {
+ internals->vpq[i] =
+ queue_ids[i + 1]; /* queue 0 is for exception */
+ }
+ } else {
+ if (nthw_vdpa_init(vdev, (*eth_dev)->device->name, path,
+ queue_ids[0].hw_id, n_vq, n_vq,
+ internals->port, &vhid)) {
+ NT_LOG(ERR, VDPA,
+ "*********** ERROR *********** vDPA RELAY INIT\n");
+ goto error;
+ }
+ for (i = 0; i < n_vq; i++)
+ internals->vpq[i] = queue_ids[i];
+ }
+
+ /*
+ * Exception queue for OVS SW path
+ */
+ internals->rxq_scg[0].queue = queue_ids[0];
+ internals->txq_scg[0].queue =
+ queue_ids[0]; /* use same index in Rx and Tx rings */
+ internals->rxq_scg[0].enabled = 0;
+ internals->txq_scg[0].port = port;
+
+ internals->txq_scg[0].type = internals->type;
+ internals->rxq_scg[0].type = internals->type;
+ internals->rxq_scg[0].port = internals->port;
+
+ /* Setup pmd_link info */
+ pmd_link.link_speed = ETH_SPEED_NUM_NONE;
+ pmd_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ pmd_link.link_status = ETH_LINK_DOWN;
+
+ rte_memcpy(data, (*eth_dev)->data, sizeof(*data));
+ data->dev_private = internals;
+ data->port_id = (*eth_dev)->data->port_id;
+
+ data->nb_rx_queues = 1; /* this is exception */
+ data->nb_tx_queues = 1;
+
+ data->dev_link = pmd_link;
+ data->mac_addrs = ð_addr_vp[port - MAX_NTNIC_PORTS];
+ data->numa_node = numa_node;
+
+ (*eth_dev)->data = data;
+ (*eth_dev)->dev_ops = &nthw_eth_dev_ops;
+
+ if (pmd_intern_base) {
+ struct pmd_internals *intern = pmd_intern_base;
+
+ while (intern->next)
+ intern = intern->next;
+ intern->next = internals;
+ } else {
+ pmd_intern_base = internals;
+ }
+ internals->next = NULL;
+
+ atomic_store(&internals->vhid, vhid);
+
+ LIST_INIT(&internals->mtr_profiles);
+ LIST_INIT(&internals->mtrs);
+ return 0;
+
+error:
+ if (data)
+ rte_free(data);
+ if (internals)
+ rte_free(internals);
+ return -1;
+}
+
+/*
+ * PORT_TYPE_OVERRIDE cannot receive data through SCG as the queues
+ * are going to VF/vDPA
+ */
+static uint16_t eth_dev_rx_scg_dummy(void *queue __rte_unused,
+ struct rte_mbuf **bufs __rte_unused,
+ uint16_t nb_pkts __rte_unused)
+{
+ return 0;
+}
+
+/*
+ * PORT_TYPE_OVERRIDE cannot transmit data through SCG as the queues
+ * are coming from VF/vDPA
+ */
+static uint16_t eth_dev_tx_scg_dummy(void *queue __rte_unused,
+ struct rte_mbuf **bufs __rte_unused,
+ uint16_t nb_pkts __rte_unused)
+{
+ return 0;
+}
+
+int nthw_create_vf_interface_dpdk(struct rte_pci_device *pci_dev)
+{
+ struct pmd_internals *internals;
+ struct rte_eth_dev *eth_dev;
+
+ /* Create virtual function DPDK PCI devices.*/
+ if (rte_pmd_vp_init_internals(pci_dev, ð_dev) < 0)
+ return -1;
+
+ internals = (struct pmd_internals *)eth_dev->data->dev_private;
+
+ if (internals->type == PORT_TYPE_OVERRIDE) {
+ eth_dev->rx_pkt_burst = eth_dev_rx_scg_dummy;
+ eth_dev->tx_pkt_burst = eth_dev_tx_scg_dummy;
+ } else {
+ eth_dev->rx_pkt_burst = eth_dev_rx_scg;
+ eth_dev->tx_pkt_burst = eth_dev_tx_scg;
+ }
+
+ rte_eth_dev_probing_finish(eth_dev);
+
+ return 0;
+}
+
+int nthw_remove_vf_interface_dpdk(struct rte_pci_device *pci_dev)
+{
+ struct rte_eth_dev *eth_dev = NULL;
+
+ NT_LOG(DBG, VDPA, "Closing ntvp pmd on numa socket %u\n",
+ rte_socket_id());
+
+ if (!pci_dev)
+ return -1;
+
+ /* Clean up all vDPA devices */
+ nthw_vdpa_close();
+
+ /* reserve an ethdev entry */
+ eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(pci_dev));
+ if (eth_dev == NULL)
+ return -1;
+
+ rte_free(eth_dev->data->dev_private);
+ rte_free(eth_dev->data);
+
+ rte_eth_dev_release_port(eth_dev);
+
+ return 0;
+}
+
+/*
+ * LAG
+ */
+
+#define LAG_PORT0_ONLY (100)
+#define LAG_BALANCED_50_50 (50)
+#define LAG_PORT1_ONLY (0)
+
+#define LAG_NO_TX (0)
+#define LAG_PORT0_INDEX (1)
+#define LAG_PORT1_INDEX (2)
+#define LAG_HASH_INDEX (3)
+
+static int lag_nop(lag_config_t *config __rte_unused)
+{
+ return 0;
+}
+
+static int lag_balance(lag_config_t *config __rte_unused)
+{
+ NT_LOG(DBG, ETHDEV, "AA LAG: balanced output\n");
+ return lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, LAG_BALANCED_50_50);
+}
+
+static int lag_port0_active(lag_config_t *config __rte_unused)
+{
+ NT_LOG(DBG, ETHDEV, "AA LAG: port 0 output only\n");
+ return lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, LAG_PORT0_ONLY);
+}
+
+static int lag_port1_active(lag_config_t *config __rte_unused)
+{
+ NT_LOG(DBG, ETHDEV, "AA LAG: port 1 output only\n");
+ return lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, LAG_PORT1_ONLY);
+}
+
+static int lag_notx(lag_config_t *config __rte_unused)
+{
+ NT_LOG(DBG, ETHDEV, "AA LAG: no link\n");
+
+ int retval = 0;
+
+ retval +=
+ lag_set_config(0, FLOW_LAG_SET_ALL, LAG_PORT0_INDEX, LAG_NO_TX);
+ retval +=
+ lag_set_config(0, FLOW_LAG_SET_ALL, LAG_HASH_INDEX, LAG_NO_TX);
+ return retval;
+}
+
+static bool lag_get_link_status(lag_config_t *lag_config, uint8_t port)
+{
+ struct adapter_info_s *p_adapter_info =
+ &lag_config->internals->p_drv->ntdrv.adapter_info;
+ const bool link_up = nt4ga_port_get_link_status(p_adapter_info, port);
+
+ NT_LOG(DBG, ETHDEV, "port %d status: %d\n", port, link_up);
+ return link_up;
+}
+
+static int lag_get_status(lag_config_t *config)
+{
+ uint8_t port0 = lag_get_link_status(config, 0);
+
+ uint8_t port1 = lag_get_link_status(config, 1);
+
+ uint8_t status = (port1 << 1 | port0);
+ return status;
+}
+
+static int lag_activate_primary(lag_config_t *config)
+{
+ int retval;
+
+ uint8_t port_0_distribution;
+ uint8_t blocked_port;
+
+ if (config->primary_port == 0) {
+ /* If port 0 is the active primary, then it take 100% of the hash distribution. */
+ port_0_distribution = 100;
+ blocked_port = LAG_PORT1_INDEX;
+ } else {
+ /* If port 1 is the active primary, then port 0 take 0% of the hash distribution. */
+ port_0_distribution = 0;
+ blocked_port = LAG_PORT0_INDEX;
+ }
+
+ retval =
+ lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, port_0_distribution);
+
+ /* Block Rx on the backup port */
+ retval += lag_set_port_block(0, blocked_port);
+
+ return retval;
+}
+
+static int lag_activate_backup(lag_config_t *config)
+{
+ int retval;
+
+ uint8_t port_0_distribution;
+ uint8_t blocked_port;
+
+ if (config->backup_port == 0) {
+ /* If port 0 is the active backup, then it take 100% of the hash distribution. */
+ port_0_distribution = 100;
+ blocked_port = LAG_PORT1_INDEX;
+ } else {
+ /* If port 1 is the active backup, then port 0 take 0% of the hash distribution. */
+ port_0_distribution = 0;
+ blocked_port = LAG_PORT0_INDEX;
+ }
+
+ /* Tx only on the backup port */
+ retval =
+ lag_set_config(0, FLOW_LAG_SET_BALANCE, 0, port_0_distribution);
+
+ /* Block Rx on the primary port */
+ retval += lag_set_port_block(0, blocked_port);
+
+ return retval;
+}
+
+static int lag_active_backup(lag_config_t *config)
+{
+ uint8_t backup_port_active = 0;
+
+ /* Initialize with the primary port active */
+ lag_activate_primary(config);
+
+ while (config->lag_thread_active) {
+ usleep(500 *
+ 1000); /* 500 ms sleep between testing the link status. */
+
+ bool primary_port_status =
+ lag_get_link_status(config, config->primary_port);
+
+ if (!primary_port_status) {
+ bool backup_port_status =
+ lag_get_link_status(config, config->backup_port);
+ /* If the backup port has been activated, no need to do more. */
+ if (backup_port_active)
+ continue;
+
+ /* If the backup port is up, flip to it. */
+ if (backup_port_status) {
+ NT_LOG(DBG, ETHDEV,
+ "LAG: primary port down => swapping to backup port\n");
+ lag_activate_backup(config);
+ backup_port_active = 1;
+ }
+ } else {
+ /* If using the backup port and primary come back. */
+ if (backup_port_active) {
+ NT_LOG(DBG, ETHDEV,
+ "LAG: primary port restored => swapping to primary port\n");
+ lag_activate_primary(config);
+ backup_port_active = 0;
+ } /* Backup is active, while primary is restored. */
+ } /* Primary port status */
+ }
+
+ return 0;
+}
+
+typedef int (*lag_aa_action)(lag_config_t *config);
+
+/* port 0 is LSB and port 1 is MSB */
+enum lag_state_e {
+ P0DOWN_P1DOWN = 0b00,
+ P0UP_P1DOWN = 0b01,
+ P0DOWN_P1UP = 0b10,
+ P0UP_P1UP = 0b11
+};
+
+struct lag_action_s {
+ enum lag_state_e src_state;
+ enum lag_state_e dst_state;
+ lag_aa_action action;
+};
+
+struct lag_action_s actions[] = {
+ /* No action in same state */
+ { P0UP_P1UP, P0UP_P1UP, lag_nop },
+ { P0UP_P1DOWN, P0UP_P1DOWN, lag_nop },
+ { P0DOWN_P1UP, P0DOWN_P1UP, lag_nop },
+ { P0DOWN_P1DOWN, P0DOWN_P1DOWN, lag_nop },
+
+ /* UU start */
+ { P0UP_P1UP, P0UP_P1DOWN, lag_port0_active },
+ { P0UP_P1UP, P0DOWN_P1UP, lag_port1_active },
+ { P0UP_P1UP, P0DOWN_P1DOWN, lag_notx },
+
+ /* UD start */
+ { P0UP_P1DOWN, P0DOWN_P1DOWN, lag_notx },
+ { P0UP_P1DOWN, P0DOWN_P1UP, lag_port1_active },
+ { P0UP_P1DOWN, P0UP_P1UP, lag_balance },
+
+ /* DU start */
+ { P0DOWN_P1UP, P0DOWN_P1DOWN, lag_notx },
+ { P0DOWN_P1UP, P0UP_P1DOWN, lag_port0_active },
+ { P0DOWN_P1UP, P0UP_P1UP, lag_balance },
+
+ /* DD start */
+ { P0DOWN_P1DOWN, P0DOWN_P1UP, lag_port1_active },
+ { P0DOWN_P1DOWN, P0UP_P1DOWN, lag_port0_active },
+ { P0DOWN_P1DOWN, P0UP_P1UP, lag_balance },
+};
+
+static lag_aa_action lookup_action(enum lag_state_e current_state,
+ enum lag_state_e new_state)
+{
+ uint32_t i;
+
+ for (i = 0; i < sizeof(actions) / sizeof(struct lag_action_s); i++) {
+ if (actions[i].src_state == current_state &&
+ actions[i].dst_state == new_state)
+ return actions[i].action;
+ }
+ return NULL;
+}
+
+static int lag_active_active(lag_config_t *config)
+{
+ enum lag_state_e ports_status;
+
+ /* Set the initial state to 50/50% */
+ enum lag_state_e current_state = P0UP_P1UP;
+
+ lag_balance(config);
+ /* No ports are blocked in active/active */
+ lag_set_port_block(0, 0);
+
+ lag_aa_action action;
+
+ while (config->lag_thread_active) {
+ /* 500 ms sleep between testing the link status. */
+ usleep(500 * 1000);
+
+ ports_status = lag_get_status(config);
+
+ action = lookup_action(current_state, ports_status);
+ action(config);
+
+ current_state = ports_status;
+ }
+
+ return 0;
+}
+
+static void *lag_management(void *arg)
+{
+ lag_config_t *config = (lag_config_t *)arg;
+
+ switch (config->mode) {
+ case BONDING_MODE_ACTIVE_BACKUP:
+ lag_active_backup(config);
+ break;
+
+ case BONDING_MODE_8023AD:
+ lag_active_active(config);
+ break;
+
+ default:
+ fprintf(stderr, "Unsupported NTbond mode\n");
+ return NULL;
+ }
+
+ return NULL;
+}
diff --git a/drivers/net/ntnic/ntnic_ethdev.h b/drivers/net/ntnic/ntnic_ethdev.h
new file mode 100644
index 0000000000..a82027cbe7
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_ethdev.h
@@ -0,0 +1,357 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTNIC_ETHDEV_H__
+#define __NTNIC_ETHDEV_H__
+
+#include <stdatomic.h>
+
+#include <rte_ether.h>
+#include <rte_version.h> /* RTE_VERSION, RTE_VERSION_NUM */
+#include <rte_mtr_driver.h>
+#include <rte_mbuf.h>
+#include <rte_pci.h>
+#include <ethdev_pci.h>
+
+#include "ntos_system.h"
+#include "ntnic_dbsconfig.h"
+#include "stream_binary_flow_api.h"
+
+#if (RTE_VERSION_NUM(22, 07, 0, 0) <= RTE_VERSION)
+#undef ETH_LINK_HALF_DUPLEX
+#undef ETH_LINK_FULL_DUPLEX
+#undef ETH_LINK_DOWN
+#undef ETH_LINK_UP
+#undef ETH_LINK_FIXED
+#undef ETH_LINK_AUTONEG
+#undef ETH_SPEED_NUM_NONE
+#undef ETH_SPEED_NUM_10M
+#undef ETH_SPEED_NUM_100M
+#undef ETH_SPEED_NUM_1G
+#undef ETH_SPEED_NUM_2_5G
+#undef ETH_SPEED_NUM_5G
+#undef ETH_SPEED_NUM_10G
+#undef ETH_SPEED_NUM_20G
+#undef ETH_SPEED_NUM_25G
+#undef ETH_SPEED_NUM_40G
+#undef ETH_SPEED_NUM_50G
+#undef ETH_SPEED_NUM_56G
+#undef ETH_SPEED_NUM_100G
+#undef ETH_SPEED_NUM_200G
+#undef ETH_SPEED_NUM_UNKNOWN
+#undef ETH_LINK_SPEED_AUTONEG
+#undef ETH_LINK_SPEED_FIXED
+#undef ETH_LINK_SPEED_10M_HD
+#undef ETH_LINK_SPEED_10M
+#undef ETH_LINK_SPEED_100M_HD
+#undef ETH_LINK_SPEED_100M
+#undef ETH_LINK_SPEED_1G
+#undef ETH_LINK_SPEED_2_5G
+#undef ETH_LINK_SPEED_5G
+#undef ETH_LINK_SPEED_10G
+#undef ETH_LINK_SPEED_20G
+#undef ETH_LINK_SPEED_25G
+#undef ETH_LINK_SPEED_40G
+#undef ETH_LINK_SPEED_50G
+#undef ETH_LINK_SPEED_56G
+#undef ETH_LINK_SPEED_100G
+#undef ETH_LINK_SPEED_200G
+#undef ETH_RSS_IP
+#undef ETH_RSS_UDP
+#undef ETH_RSS_TCP
+#undef ETH_RSS_SCTP
+#define ETH_LINK_HALF_DUPLEX RTE_ETH_LINK_HALF_DUPLEX
+#define ETH_LINK_FULL_DUPLEX RTE_ETH_LINK_FULL_DUPLEX
+#define ETH_LINK_DOWN RTE_ETH_LINK_DOWN
+#define ETH_LINK_UP RTE_ETH_LINK_UP
+#define ETH_LINK_FIXED RTE_ETH_LINK_FIXED
+#define ETH_LINK_AUTONEG RTE_ETH_LINK_AUTONEG
+#define ETH_SPEED_NUM_NONE RTE_ETH_SPEED_NUM_NONE
+#define ETH_SPEED_NUM_10M RTE_ETH_SPEED_NUM_10M
+#define ETH_SPEED_NUM_100M RTE_ETH_SPEED_NUM_100M
+#define ETH_SPEED_NUM_1G RTE_ETH_SPEED_NUM_1G
+#define ETH_SPEED_NUM_2_5G RTE_ETH_SPEED_NUM_2_5G
+#define ETH_SPEED_NUM_5G RTE_ETH_SPEED_NUM_5G
+#define ETH_SPEED_NUM_10G RTE_ETH_SPEED_NUM_10G
+#define ETH_SPEED_NUM_20G RTE_ETH_SPEED_NUM_20G
+#define ETH_SPEED_NUM_25G RTE_ETH_SPEED_NUM_25G
+#define ETH_SPEED_NUM_40G RTE_ETH_SPEED_NUM_40G
+#define ETH_SPEED_NUM_50G RTE_ETH_SPEED_NUM_50G
+#define ETH_SPEED_NUM_56G RTE_ETH_SPEED_NUM_56G
+#define ETH_SPEED_NUM_100G RTE_ETH_SPEED_NUM_100G
+#define ETH_SPEED_NUM_200G RTE_ETH_SPEED_NUM_200G
+#define ETH_SPEED_NUM_UNKNOWN RTE_ETH_SPEED_NUM_UNKNOWN
+#define ETH_LINK_SPEED_AUTONEG RTE_ETH_LINK_SPEED_AUTONEG
+#define ETH_LINK_SPEED_FIXED RTE_ETH_LINK_SPEED_FIXED
+#define ETH_LINK_SPEED_10M_HD RTE_ETH_LINK_SPEED_10M_HD
+#define ETH_LINK_SPEED_10M RTE_ETH_LINK_SPEED_10M
+#define ETH_LINK_SPEED_100M_HD RTE_ETH_LINK_SPEED_100M_HD
+#define ETH_LINK_SPEED_100M RTE_ETH_LINK_SPEED_100M
+#define ETH_LINK_SPEED_1G RTE_ETH_LINK_SPEED_1G
+#define ETH_LINK_SPEED_2_5G RTE_ETH_LINK_SPEED_2_5G
+#define ETH_LINK_SPEED_5G RTE_ETH_LINK_SPEED_5G
+#define ETH_LINK_SPEED_10G RTE_ETH_LINK_SPEED_10G
+#define ETH_LINK_SPEED_20G RTE_ETH_LINK_SPEED_20G
+#define ETH_LINK_SPEED_25G RTE_ETH_LINK_SPEED_25G
+#define ETH_LINK_SPEED_40G RTE_ETH_LINK_SPEED_40G
+#define ETH_LINK_SPEED_50G RTE_ETH_LINK_SPEED_50G
+#define ETH_LINK_SPEED_56G RTE_ETH_LINK_SPEED_56G
+#define ETH_LINK_SPEED_100G RTE_ETH_LINK_SPEED_100G
+#define ETH_LINK_SPEED_200G RTE_ETH_LINK_SPEED_200G
+#define ETH_RSS_IP RTE_ETH_RSS_IP
+#define ETH_RSS_UDP RTE_ETH_RSS_UDP
+#define ETH_RSS_TCP RTE_ETH_RSS_TCP
+#define ETH_RSS_SCTP RTE_ETH_RSS_SCTP
+#define ETH_RSS_IPV4 RTE_ETH_RSS_IPV4
+#define ETH_RSS_FRAG_IPV4 RTE_ETH_RSS_FRAG_IPV4
+#define ETH_RSS_NONFRAG_IPV4_OTHER RTE_ETH_RSS_NONFRAG_IPV4_OTHER
+#define ETH_RSS_IPV6 RTE_ETH_RSS_IPV6
+#define ETH_RSS_FRAG_IPV6 RTE_ETH_RSS_FRAG_IPV6
+#define ETH_RSS_NONFRAG_IPV6_OTHER RTE_ETH_RSS_NONFRAG_IPV6_OTHER
+#define ETH_RSS_IPV6_EX RTE_ETH_RSS_IPV6_EX
+#define ETH_RSS_C_VLAN RTE_ETH_RSS_C_VLAN
+#define ETH_RSS_L3_DST_ONLY RTE_ETH_RSS_L3_DST_ONLY
+#define ETH_RSS_L3_SRC_ONLY RTE_ETH_RSS_L3_SRC_ONLY
+#endif
+
+#define NUM_MAC_ADDRS_PER_PORT (16U)
+#define NUM_MULTICAST_ADDRS_PER_PORT (16U)
+
+#define MAX_FPGA_VIRTUAL_PORTS_SUPPORTED 256
+
+/* Total max ports per NT NFV NIC */
+#define MAX_NTNIC_PORTS 2
+
+/* Max RSS queues */
+#define MAX_QUEUES 125
+
+#define SG_NB_HW_RX_DESCRIPTORS 1024
+#define SG_NB_HW_TX_DESCRIPTORS 1024
+#define SG_HW_RX_PKT_BUFFER_SIZE (1024 << 1)
+#define SG_HW_TX_PKT_BUFFER_SIZE (1024 << 1)
+
+#define SG_HDR_SIZE 12
+
+/* VQ buffers needed to fit all data in packet + header */
+#define NUM_VQ_SEGS(_data_size_) \
+ ({ \
+ size_t _size = (_data_size_); \
+ size_t _segment_count = ((_size + SG_HDR_SIZE) > SG_HW_TX_PKT_BUFFER_SIZE) ? \
+ (((_size + SG_HDR_SIZE) + SG_HW_TX_PKT_BUFFER_SIZE - 1) / \
+ SG_HW_TX_PKT_BUFFER_SIZE) : 1; \
+ _segment_count; \
+ })
+
+
+#define VIRTQ_DESCR_IDX(_tx_pkt_idx_) \
+ (((_tx_pkt_idx_) + first_vq_descr_idx) % SG_NB_HW_TX_DESCRIPTORS)
+
+#define VIRTQ_DESCR_IDX_NEXT(_vq_descr_idx_) \
+ (((_vq_descr_idx_) + 1) % SG_NB_HW_TX_DESCRIPTORS)
+
+#define MAX_REL_VQS 128
+
+/* Functions: */
+struct pmd_internals *vp_vhid_instance_ready(int vhid);
+struct pmd_internals *vp_path_instance_ready(const char *path);
+int setup_virtual_pf_representor_base(struct rte_pci_device *dev);
+int nthw_create_vf_interface_dpdk(struct rte_pci_device *pci_dev);
+int nthw_remove_vf_interface_dpdk(struct rte_pci_device *pci_dev);
+nthw_dbs_t *get_pdbs_from_pci(struct rte_pci_addr pci_addr);
+enum fpga_info_profile get_fpga_profile_from_pci(struct rte_pci_addr pci_addr);
+int register_release_virtqueue_info(struct nthw_virt_queue *vq, int rx,
+ int managed);
+int de_register_release_virtqueue_info(struct nthw_virt_queue *vq);
+int copy_mbuf_to_virtqueue(struct nthw_cvirtq_desc *cvq_desc,
+ uint16_t vq_descr_idx,
+ struct nthw_memory_descriptor *vq_bufs, int max_segs,
+ struct rte_mbuf *mbuf);
+
+extern int lag_active;
+extern uint64_t rte_tsc_freq;
+extern rte_spinlock_t hwlock;
+
+/* Structs: */
+
+#define SG_HDR_SIZE 12
+
+struct _pkt_hdr_rx {
+ uint32_t cap_len : 14;
+ uint32_t fid : 10;
+ uint32_t ofs1 : 8;
+ uint32_t ip_prot : 8;
+ uint32_t port : 13;
+ uint32_t descr : 8;
+ uint32_t descr_12b : 1;
+ uint32_t color_type : 2;
+ uint32_t color : 32;
+};
+
+struct _pkt_hdr_tx {
+ uint32_t cap_len : 14;
+ uint32_t lso_cso0 : 9;
+ uint32_t lso_cso1 : 9;
+ uint32_t lso_cso2 : 8;
+ /* all 1's : use implicit in-port. 0-127 queue index. 0x80 + phy-port to phy */
+ uint32_t bypass_port : 13;
+ uint32_t descr : 8;
+ uint32_t descr_12b : 1;
+ uint32_t color_type : 2;
+ uint32_t color : 32;
+};
+
+/* Compile time verification of scatter gather header size. */
+typedef char check_sg_pkt_rx_hdr_size
+[(sizeof(struct _pkt_hdr_rx) == SG_HDR_SIZE) ? 1 : -1];
+typedef char check_sg_pkt_tx_hdr_size
+[(sizeof(struct _pkt_hdr_tx) == SG_HDR_SIZE) ? 1 : -1];
+
+typedef void *handle_t;
+
+struct hwq_s {
+ int vf_num;
+ struct nthw_memory_descriptor virt_queues_ctrl;
+ struct nthw_memory_descriptor *pkt_buffers;
+};
+
+struct ntnic_rx_queue {
+ struct flow_queue_id_s
+ queue; /* queue info - user id and hw queue index */
+
+ struct rte_mempool *mb_pool; /* mbuf memory pool */
+ uint16_t buf_size; /* size of data area in mbuf */
+ unsigned long rx_pkts; /* Rx packet statistics */
+ unsigned long rx_bytes; /* Rx bytes statistics */
+ unsigned long err_pkts; /* Rx error packet statistics */
+ int enabled; /* Enabling/disabling of this queue */
+
+ struct hwq_s hwq;
+ struct nthw_virt_queue *vq;
+ int nb_hw_rx_descr;
+ nt_meta_port_type_t type;
+ uint32_t port; /* Rx port for this queue */
+ enum fpga_info_profile profile; /* Vswitch / Inline / Capture */
+
+} __rte_cache_aligned;
+
+struct ntnic_tx_queue {
+ struct flow_queue_id_s
+ queue; /* queue info - user id and hw queue index */
+ struct hwq_s hwq;
+ struct nthw_virt_queue *vq;
+ int nb_hw_tx_descr;
+ /* Used for bypass in NTDVIO0 header on Tx - pre calculated */
+ int target_id;
+ nt_meta_port_type_t type;
+ /* only used for exception tx queue from OVS SW switching */
+ int rss_target_id;
+
+ uint32_t port; /* Tx port for this queue */
+ unsigned long tx_pkts; /* Tx packet statistics */
+ unsigned long tx_bytes; /* Tx bytes statistics */
+ unsigned long err_pkts; /* Tx error packet stat */
+ int enabled; /* Enabling/disabling of this queue */
+ enum fpga_info_profile profile; /* Vswitch / Inline / Capture */
+} __rte_cache_aligned;
+
+#define MAX_ARRAY_ENTRIES MAX_QUEUES
+struct array_s {
+ uint32_t value[MAX_ARRAY_ENTRIES];
+ int count;
+};
+
+/* Configuerations related to LAG management */
+typedef struct {
+ uint8_t mode;
+
+ int8_t primary_port;
+ int8_t backup_port;
+
+ uint32_t ntpl_rx_id;
+
+ pthread_t lag_tid;
+ uint8_t lag_thread_active;
+
+ struct pmd_internals *internals;
+} lag_config_t;
+
+#define BONDING_MODE_ACTIVE_BACKUP (1)
+#define BONDING_MODE_8023AD (4)
+struct nt_mtr_profile {
+ LIST_ENTRY(nt_mtr_profile) next;
+ uint32_t profile_id;
+ struct rte_mtr_meter_profile profile;
+};
+
+struct nt_mtr {
+ LIST_ENTRY(nt_mtr) next;
+ uint32_t mtr_id;
+ int shared;
+ struct nt_mtr_profile *profile;
+};
+
+enum virt_port_comm {
+ VIRT_PORT_NEGOTIATED_NONE,
+ VIRT_PORT_NEGOTIATED_SPLIT,
+ VIRT_PORT_NEGOTIATED_PACKED,
+ VIRT_PORT_USE_RELAY
+};
+
+#define MAX_PATH_LEN 128
+
+struct pmd_internals {
+ const struct rte_pci_device *pci_dev;
+
+ struct flow_eth_dev *flw_dev;
+
+ char name[20];
+ char vhost_path[MAX_PATH_LEN];
+
+ int n_intf_no;
+ int if_index;
+
+ int lpbk_mode;
+
+ uint8_t nb_ports_on_adapter;
+ uint8_t ts_multiplier;
+ uint16_t min_tx_pkt_size;
+ uint16_t max_tx_pkt_size;
+
+ unsigned int nb_rx_queues; /* Number of Rx queues configured */
+ unsigned int nb_tx_queues; /* Number of Tx queues configured */
+ uint32_t port;
+ uint8_t port_id;
+
+ nt_meta_port_type_t type;
+ struct flow_queue_id_s vpq[MAX_QUEUES];
+ unsigned int vpq_nb_vq;
+ volatile atomic_int vhid; /* if a virtual port type - the vhid */
+ enum virt_port_comm vport_comm; /* link and how split,packed,relay */
+ uint32_t vlan;
+
+ lag_config_t *lag_config;
+
+ struct ntnic_rx_queue rxq_scg[MAX_QUEUES]; /* Array of Rx queues */
+ struct ntnic_tx_queue txq_scg[MAX_QUEUES]; /* Array of Tx queues */
+
+ struct drv_s *p_drv;
+ /* Ethernet (MAC) addresses. Element number zero denotes default address. */
+ struct rte_ether_addr eth_addrs[NUM_MAC_ADDRS_PER_PORT];
+ /* Multicast ethernet (MAC) addresses. */
+ struct rte_ether_addr mc_addrs[NUM_MULTICAST_ADDRS_PER_PORT];
+
+ LIST_HEAD(_profiles, nt_mtr_profile) mtr_profiles;
+ LIST_HEAD(_mtrs, nt_mtr) mtrs;
+
+ uint64_t last_stat_rtc;
+ uint64_t rx_missed;
+
+ struct pmd_internals *next;
+};
+
+void cleanup_flows(struct pmd_internals *internals);
+int poll_statistics(struct pmd_internals *internals);
+int debug_adapter_show_info(uint32_t pciident, FILE *pfh);
+
+#endif /* __NTNIC_ETHDEV_H__ */
diff --git a/drivers/net/ntnic/ntnic_filter/create_elements.h b/drivers/net/ntnic/ntnic_filter/create_elements.h
new file mode 100644
index 0000000000..77f01900f8
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_filter/create_elements.h
@@ -0,0 +1,1194 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __CREATE_ELEMENTS_H__
+#define __CREATE_ELEMENTS_H__
+
+#include "stream_binary_flow_api.h"
+
+#define MAX_ELEMENTS 64
+#define MAX_ACTIONS 32
+
+#define MAX_COLOR_FLOW_STATS 0x400
+
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+struct cnv_match_s {
+ struct flow_elem flow_elem[MAX_ELEMENTS];
+};
+
+struct tun_def_s {
+ struct flow_elem *tun_definition;
+ struct cnv_match_s match;
+};
+
+struct cnv_attr_s {
+ struct cnv_match_s match;
+ struct flow_attr attr;
+};
+
+struct cnv_action_s {
+ struct flow_action flow_actions[MAX_ACTIONS];
+ struct tun_def_s tun_def;
+ struct flow_action_rss flow_rss;
+ struct rte_flow_action_mark mark;
+ struct flow_action_raw_encap encap;
+ struct flow_action_raw_decap decap;
+ struct flow_action_queue queue;
+};
+
+/*
+ * Only needed because it eases the use of statistics through NTAPI
+ * for faster integration into NTAPI version of driver
+ * Therefore, this is only a good idea when running on a temporary NTAPI
+ * The query() functionality must go to flow engine, when moved to Open Source driver
+ */
+
+struct rte_flow {
+ void *flw_hdl;
+ int used;
+ uint32_t flow_stat_id;
+
+ uint64_t stat_pkts;
+ uint64_t stat_bytes;
+ uint8_t stat_tcp_flags;
+};
+
+enum nt_rte_flow_item_type {
+ NT_RTE_FLOW_ITEM_TYPE_END = INT_MIN,
+ NT_RTE_FLOW_ITEM_TYPE_TAG,
+ NT_RTE_FLOW_ITEM_TYPE_TUNNEL,
+};
+
+enum nt_rte_flow_action_type {
+ NT_RTE_FLOW_ACTION_TYPE_END = INT_MIN,
+ NT_RTE_FLOW_ACTION_TYPE_TAG,
+ NT_RTE_FLOW_ACTION_TYPE_TUNNEL_SET,
+ NT_RTE_FLOW_ACTION_TYPE_JUMP,
+};
+
+static int convert_tables_intialized;
+
+#define MAX_RTE_ENUM_INDEX 127
+
+static int elem_list[MAX_RTE_ENUM_INDEX + 1];
+static int action_list[MAX_RTE_ENUM_INDEX + 1];
+
+#ifdef RTE_FLOW_DEBUG
+static const char *elem_list_str[MAX_RTE_ENUM_INDEX + 1];
+static const char *action_list_str[MAX_RTE_ENUM_INDEX + 1];
+#endif
+
+#define CNV_TO_ELEM(item) \
+ ({ \
+ int _temp_item = (item); \
+ ((_temp_item >= 0 && _temp_item <= MAX_RTE_ENUM_INDEX) ? \
+ elem_list[_temp_item] : -1); \
+ })
+
+
+#define CNV_TO_ACTION(action) \
+ ({ \
+ int _temp_action = (action); \
+ (_temp_action >= 0 && _temp_action <= MAX_RTE_ENUM_INDEX) ? \
+ action_list[_temp_action] : -1; \
+ })
+
+
+static uint32_t flow_stat_id_map[MAX_COLOR_FLOW_STATS];
+static rte_spinlock_t flow_lock = RTE_SPINLOCK_INITIALIZER;
+
+static int convert_error(struct rte_flow_error *error,
+ struct flow_error *flow_error)
+{
+ if (error) {
+ error->cause = NULL;
+ error->message = flow_error->message;
+
+ if (flow_error->type == FLOW_ERROR_NONE ||
+ flow_error->type == FLOW_ERROR_SUCCESS)
+ error->type = RTE_FLOW_ERROR_TYPE_NONE;
+
+ else
+ error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ }
+ return 0;
+}
+
+/*
+ * Map Flow MARK to flow stat id
+ */
+static uint32_t create_flow_stat_id_locked(uint32_t mark)
+{
+ uint32_t flow_stat_id = mark & (MAX_COLOR_FLOW_STATS - 1);
+
+ while (flow_stat_id_map[flow_stat_id])
+ flow_stat_id = (flow_stat_id + 1) & (MAX_COLOR_FLOW_STATS - 1);
+
+ flow_stat_id_map[flow_stat_id] = mark + 1;
+ return flow_stat_id;
+}
+
+static uint32_t create_flow_stat_id(uint32_t mark)
+{
+ rte_spinlock_lock(&flow_lock);
+ uint32_t ret = create_flow_stat_id_locked(mark);
+
+ rte_spinlock_unlock(&flow_lock);
+ return ret;
+}
+
+static void delete_flow_stat_id_locked(uint32_t flow_stat_id)
+{
+ if (flow_stat_id < MAX_COLOR_FLOW_STATS)
+ flow_stat_id_map[flow_stat_id] = 0;
+}
+
+static void initialize_global_cnv_tables(void)
+{
+ if (convert_tables_intialized)
+ return;
+
+ memset(elem_list, -1, sizeof(elem_list));
+ elem_list[RTE_FLOW_ITEM_TYPE_END] = FLOW_ELEM_TYPE_END;
+ elem_list[RTE_FLOW_ITEM_TYPE_ANY] = FLOW_ELEM_TYPE_ANY;
+ elem_list[RTE_FLOW_ITEM_TYPE_ETH] = FLOW_ELEM_TYPE_ETH;
+ elem_list[RTE_FLOW_ITEM_TYPE_VLAN] = FLOW_ELEM_TYPE_VLAN;
+ elem_list[RTE_FLOW_ITEM_TYPE_IPV4] = FLOW_ELEM_TYPE_IPV4;
+ elem_list[RTE_FLOW_ITEM_TYPE_IPV6] = FLOW_ELEM_TYPE_IPV6;
+ elem_list[RTE_FLOW_ITEM_TYPE_UDP] = FLOW_ELEM_TYPE_UDP;
+ elem_list[RTE_FLOW_ITEM_TYPE_SCTP] = FLOW_ELEM_TYPE_SCTP;
+ elem_list[RTE_FLOW_ITEM_TYPE_TCP] = FLOW_ELEM_TYPE_TCP;
+ elem_list[RTE_FLOW_ITEM_TYPE_ICMP] = FLOW_ELEM_TYPE_ICMP;
+ elem_list[RTE_FLOW_ITEM_TYPE_VXLAN] = FLOW_ELEM_TYPE_VXLAN;
+ elem_list[RTE_FLOW_ITEM_TYPE_GTP] = FLOW_ELEM_TYPE_GTP;
+ elem_list[RTE_FLOW_ITEM_TYPE_PORT_ID] = FLOW_ELEM_TYPE_PORT_ID;
+ elem_list[RTE_FLOW_ITEM_TYPE_TAG] = FLOW_ELEM_TYPE_TAG;
+ elem_list[RTE_FLOW_ITEM_TYPE_VOID] = FLOW_ELEM_TYPE_VOID;
+
+#ifdef RTE_FLOW_DEBUG
+ elem_list_str[RTE_FLOW_ITEM_TYPE_END] = "FLOW_ELEM_TYPE_END";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_ANY] = "FLOW_ELEM_TYPE_ANY";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_ETH] = "FLOW_ELEM_TYPE_ETH";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_VLAN] = "FLOW_ELEM_TYPE_VLAN";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_IPV4] = "FLOW_ELEM_TYPE_IPV4";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_IPV6] = "FLOW_ELEM_TYPE_IPV6";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_UDP] = "FLOW_ELEM_TYPE_UDP";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_SCTP] = "FLOW_ELEM_TYPE_SCTP";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_TCP] = "FLOW_ELEM_TYPE_TCP";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_ICMP] = "FLOW_ELEM_TYPE_ICMP";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_VXLAN] = "FLOW_ELEM_TYPE_VXLAN";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_GTP] = "FLOW_ELEM_TYPE_GTP";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_PORT_ID] = "FLOW_ELEM_TYPE_PORT_ID";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_TAG] = "FLOW_ELEM_TYPE_TAG";
+ elem_list_str[RTE_FLOW_ITEM_TYPE_VOID] = "FLOW_ELEM_TYPE_VOID";
+#endif
+
+ memset(action_list, -1, sizeof(action_list));
+ action_list[RTE_FLOW_ACTION_TYPE_END] = FLOW_ACTION_TYPE_END;
+ action_list[RTE_FLOW_ACTION_TYPE_MARK] = FLOW_ACTION_TYPE_MARK;
+ action_list[RTE_FLOW_ACTION_TYPE_SET_TAG] = FLOW_ACTION_TYPE_SET_TAG;
+ action_list[RTE_FLOW_ACTION_TYPE_DROP] = FLOW_ACTION_TYPE_DROP;
+ action_list[RTE_FLOW_ACTION_TYPE_COUNT] = FLOW_ACTION_TYPE_COUNT;
+ action_list[RTE_FLOW_ACTION_TYPE_RSS] = FLOW_ACTION_TYPE_RSS;
+ action_list[RTE_FLOW_ACTION_TYPE_PORT_ID] = FLOW_ACTION_TYPE_PORT_ID;
+ action_list[RTE_FLOW_ACTION_TYPE_QUEUE] = FLOW_ACTION_TYPE_QUEUE;
+ action_list[RTE_FLOW_ACTION_TYPE_JUMP] = FLOW_ACTION_TYPE_JUMP;
+ action_list[RTE_FLOW_ACTION_TYPE_METER] = FLOW_ACTION_TYPE_METER;
+ action_list[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] =
+ FLOW_ACTION_TYPE_VXLAN_ENCAP;
+ action_list[RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] =
+ FLOW_ACTION_TYPE_VXLAN_DECAP;
+ action_list[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] =
+ FLOW_ACTION_TYPE_PUSH_VLAN;
+ action_list[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] =
+ FLOW_ACTION_TYPE_SET_VLAN_VID;
+ action_list[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] =
+ FLOW_ACTION_TYPE_SET_VLAN_PCP;
+ action_list[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] =
+ FLOW_ACTION_TYPE_POP_VLAN;
+ action_list[RTE_FLOW_ACTION_TYPE_RAW_ENCAP] =
+ FLOW_ACTION_TYPE_RAW_ENCAP;
+ action_list[RTE_FLOW_ACTION_TYPE_RAW_DECAP] =
+ FLOW_ACTION_TYPE_RAW_DECAP;
+ action_list[RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] =
+ FLOW_ACTION_TYPE_MODIFY_FIELD;
+
+#ifdef RTE_FLOW_DEBUG
+ action_list_str[RTE_FLOW_ACTION_TYPE_END] = "FLOW_ACTION_TYPE_END";
+ action_list_str[RTE_FLOW_ACTION_TYPE_MARK] = "FLOW_ACTION_TYPE_MARK";
+ action_list_str[RTE_FLOW_ACTION_TYPE_SET_TAG] =
+ "FLOW_ACTION_TYPE_SET_TAG";
+ action_list_str[RTE_FLOW_ACTION_TYPE_DROP] = "FLOW_ACTION_TYPE_DROP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_COUNT] = "FLOW_ACTION_TYPE_COUNT";
+ action_list_str[RTE_FLOW_ACTION_TYPE_RSS] = "FLOW_ACTION_TYPE_RSS";
+ action_list_str[RTE_FLOW_ACTION_TYPE_PORT_ID] =
+ "FLOW_ACTION_TYPE_PORT_ID";
+ action_list_str[RTE_FLOW_ACTION_TYPE_QUEUE] = "FLOW_ACTION_TYPE_QUEUE";
+ action_list_str[RTE_FLOW_ACTION_TYPE_JUMP] = "FLOW_ACTION_TYPE_JUMP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_METER] = "FLOW_ACTION_TYPE_METER";
+ action_list_str[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] =
+ "FLOW_ACTION_TYPE_VXLAN_ENCAP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] =
+ "FLOW_ACTION_TYPE_VXLAN_DECAP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] =
+ "FLOW_ACTION_TYPE_PUSH_VLAN";
+ action_list_str[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] =
+ "FLOW_ACTION_TYPE_SET_VLAN_VID";
+ action_list_str[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] =
+ "FLOW_ACTION_TYPE_SET_VLAN_PCP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] =
+ "FLOW_ACTION_TYPE_POP_VLAN";
+ action_list_str[RTE_FLOW_ACTION_TYPE_RAW_ENCAP] =
+ "FLOW_ACTION_TYPE_RAW_ENCAP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_RAW_DECAP] =
+ "FLOW_ACTION_TYPE_RAW_DECAP";
+ action_list_str[RTE_FLOW_ACTION_TYPE_MODIFY_FIELD] =
+ "FLOW_ACTION_TYPE_MODIFY_FIELD";
+#endif
+
+ convert_tables_intialized = 1;
+}
+
+static int interpret_raw_data(uint8_t *data, uint8_t *preserve, int size,
+ struct flow_elem *out)
+{
+ int hdri = 0;
+ int pkti = 0;
+
+ /* Ethernet */
+ if (size - pkti == 0)
+ goto interpret_end;
+ if (size - pkti < (int)sizeof(struct rte_ether_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_ETH;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ rte_be16_t ether_type =
+ ((struct rte_ether_hdr *)&data[pkti])->ether_type;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_ether_hdr);
+
+ if (size - pkti == 0)
+ goto interpret_end;
+
+ /* VLAN */
+ while (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ||
+ ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ) ||
+ ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ1)) {
+ if (size - pkti == 0)
+ goto interpret_end;
+ if (size - pkti < (int)sizeof(struct rte_vlan_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_VLAN;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ ether_type = ((struct rte_vlan_hdr *)&data[pkti])->eth_proto;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_vlan_hdr);
+ }
+
+ if (size - pkti == 0)
+ goto interpret_end;
+
+ /* Layer 3 */
+ uint8_t next_header = 0;
+
+ if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) &&
+ (data[pkti] & 0xF0) == 0x40) {
+ if (size - pkti < (int)sizeof(struct rte_ipv4_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_IPV4;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ next_header = data[pkti + 9];
+
+ hdri += 1;
+ pkti += sizeof(struct rte_ipv4_hdr);
+ } else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) &&
+ (data[pkti] & 0xF0) == 0x60) {
+ if (size - pkti < (int)sizeof(struct rte_ipv6_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_IPV6;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ next_header = data[pkti + 6];
+
+ hdri += 1;
+ pkti += sizeof(struct rte_ipv6_hdr);
+
+ } else {
+ return -1;
+ }
+
+ if (size - pkti == 0)
+ goto interpret_end;
+
+ /* Layer 4 */
+ int gtpu_encap = 0;
+
+ if (next_header == 1) { /* ICMP */
+ if (size - pkti < (int)sizeof(struct rte_icmp_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_ICMP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_icmp_hdr);
+ } else if (next_header == 6) { /* TCP */
+ if (size - pkti < (int)sizeof(struct rte_tcp_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_TCP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_tcp_hdr);
+ } else if (next_header == 17) { /* UDP */
+ if (size - pkti < (int)sizeof(struct rte_udp_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_UDP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ gtpu_encap = ((struct rte_udp_hdr *)&data[pkti])->dst_port ==
+ rte_cpu_to_be_16(RTE_GTPU_UDP_PORT);
+
+ hdri += 1;
+ pkti += sizeof(struct rte_udp_hdr);
+ } else if (next_header == 132) { /* SCTP */
+ if (size - pkti < (int)sizeof(struct rte_sctp_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_SCTP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_sctp_hdr);
+ } else {
+ return -1;
+ }
+
+ if (size - pkti == 0)
+ goto interpret_end;
+
+ /* GTPv1-U */
+ if (gtpu_encap) {
+ if (size - pkti < (int)sizeof(struct rte_gtp_hdr))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_GTP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] : NULL;
+
+ int extension_present_bit =
+ ((struct rte_gtp_hdr *)&data[pkti])->e;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_gtp_hdr);
+
+ if (extension_present_bit) {
+ if (size - pkti <
+ (int)sizeof(struct rte_gtp_hdr_ext_word))
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_GTP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ? &preserve[pkti] :
+ NULL;
+
+ uint8_t next_ext =
+ ((struct rte_gtp_hdr_ext_word *)&data[pkti])
+ ->next_ext;
+
+ hdri += 1;
+ pkti += sizeof(struct rte_gtp_hdr_ext_word);
+
+ while (next_ext) {
+ size_t ext_len = data[pkti] * 4;
+
+ if (size - pkti < (int)ext_len)
+ return -1;
+
+ out[hdri].type = FLOW_ELEM_TYPE_GTP;
+ out[hdri].spec = &data[pkti];
+ out[hdri].mask = (preserve != NULL) ?
+ &preserve[pkti] :
+ NULL;
+
+ next_ext = data[pkti + ext_len - 1];
+
+ hdri += 1;
+ pkti += ext_len;
+ }
+ }
+ }
+
+ if (size - pkti != 0)
+ return -1;
+
+interpret_end:
+ out[hdri].type = FLOW_ELEM_TYPE_END;
+ out[hdri].spec = NULL;
+ out[hdri].mask = NULL;
+
+ return hdri + 1;
+}
+
+static int create_attr(struct cnv_attr_s *attribute,
+ const struct rte_flow_attr *attr)
+{
+ memset(&attribute->attr, 0x0, sizeof(struct flow_attr));
+ if (attr) {
+ attribute->attr.group = attr->group;
+ attribute->attr.priority = attr->priority;
+ }
+ return 0;
+}
+
+static int create_match_elements(struct cnv_match_s *match,
+ const struct rte_flow_item items[],
+ int max_elem)
+{
+ int eidx = 0;
+ int iter_idx = 0;
+ int type = -1;
+
+ if (!items) {
+ NT_LOG(ERR, FILTER, "ERROR no items to iterate!\n");
+ return -1;
+ }
+
+ if (!convert_tables_intialized)
+ initialize_global_cnv_tables();
+
+ do {
+ type = CNV_TO_ELEM(items[iter_idx].type);
+ if (type < 0) {
+ if ((int)items[iter_idx].type ==
+ NT_RTE_FLOW_ITEM_TYPE_TUNNEL) {
+ type = FLOW_ELEM_TYPE_TUNNEL;
+ } else {
+ NT_LOG(ERR, FILTER,
+ "ERROR unknown item type received!\n");
+ return -1;
+ }
+ }
+
+ if (type >= 0) {
+ if (items[iter_idx].last) {
+ /* Ranges are not supported yet */
+ NT_LOG(ERR, FILTER,
+ "ERROR ITEM-RANGE SETUP - NOT SUPPORTED!\n");
+ return -1;
+ }
+
+ if (eidx == max_elem) {
+ NT_LOG(ERR, FILTER,
+ "ERROR TOO MANY ELEMENTS ENCOUNTERED!\n");
+ return -1;
+ }
+
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(INF, FILTER,
+ "RTE ITEM -> FILTER FLOW ELEM - %i -> %i - %s\n",
+ items[iter_idx].type, type,
+ ((int)items[iter_idx].type >= 0) ?
+ elem_list_str[items[iter_idx].type] :
+ "FLOW_ELEM_TYPE_TUNNEL");
+
+ switch (type) {
+ case FLOW_ELEM_TYPE_ETH:
+ if (items[iter_idx].spec) {
+ const struct flow_elem_eth *eth =
+ items[iter_idx].spec;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_ETH SPEC: dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eth->d_addr.addr_b[0] & 0xFF,
+ eth->d_addr.addr_b[1] & 0xFF,
+ eth->d_addr.addr_b[2] & 0xFF,
+ eth->d_addr.addr_b[3] & 0xFF,
+ eth->d_addr.addr_b[4] & 0xFF,
+ eth->d_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " src=%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eth->s_addr.addr_b[0] & 0xFF,
+ eth->s_addr.addr_b[1] & 0xFF,
+ eth->s_addr.addr_b[2] & 0xFF,
+ eth->s_addr.addr_b[3] & 0xFF,
+ eth->s_addr.addr_b[4] & 0xFF,
+ eth->s_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " type=%04x\n",
+ htons(eth->ether_type));
+ }
+ if (items[iter_idx].mask) {
+ const struct flow_elem_eth *eth =
+ items[iter_idx].mask;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_ETH MASK: dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eth->d_addr.addr_b[0] & 0xFF,
+ eth->d_addr.addr_b[1] & 0xFF,
+ eth->d_addr.addr_b[2] & 0xFF,
+ eth->d_addr.addr_b[3] & 0xFF,
+ eth->d_addr.addr_b[4] & 0xFF,
+ eth->d_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " src=%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eth->s_addr.addr_b[0] & 0xFF,
+ eth->s_addr.addr_b[1] & 0xFF,
+ eth->s_addr.addr_b[2] & 0xFF,
+ eth->s_addr.addr_b[3] & 0xFF,
+ eth->s_addr.addr_b[4] & 0xFF,
+ eth->s_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " type=%04x\n",
+ htons(eth->ether_type));
+ }
+ break;
+ case FLOW_ELEM_TYPE_VLAN:
+ if (items[iter_idx].spec) {
+ const struct flow_elem_vlan *vlan =
+ (const struct flow_elem_vlan *)
+ items[iter_idx]
+ .spec;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_VLAN SPEC: tci=%04x\n",
+ htons(vlan->tci));
+ NT_LOG(DBG, FILTER,
+ " inner type=%04x\n",
+ htons(vlan->inner_type));
+ }
+ if (items[iter_idx].mask) {
+ const struct flow_elem_vlan *vlan =
+ (const struct flow_elem_vlan *)
+ items[iter_idx]
+ .mask;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_VLAN MASK: tci=%04x\n",
+ htons(vlan->tci));
+ NT_LOG(DBG, FILTER,
+ " inner type=%04x\n",
+ htons(vlan->inner_type));
+ }
+ break;
+ case FLOW_ELEM_TYPE_IPV4:
+ if (items[iter_idx].spec) {
+ const struct flow_elem_ipv4 *ip =
+ items[iter_idx].spec;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_IPV4 SPEC: dst=%d.%d.%d.%d\n",
+ ((const char *)&ip->hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&ip->hdr.dst_ip)[1] & 0xFF,
+ ((const char *)&ip->hdr.dst_ip)[2] & 0xFF,
+ ((const char *)&ip->hdr.dst_ip)[3] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " src=%d.%d.%d.%d\n",
+ ((const char *)&ip->hdr.src_ip)[0] & 0xFF,
+ ((const char *)&ip->hdr.src_ip)[1] & 0xFF,
+ ((const char *)&ip->hdr.src_ip)[2] & 0xFF,
+ ((const char *)&ip->hdr.src_ip)[3] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " fragment_offset=%u\n",
+ ip->hdr.frag_offset);
+ NT_LOG(DBG, FILTER,
+ " next_proto_id=%u\n",
+ ip->hdr.next_proto_id);
+ NT_LOG(DBG, FILTER,
+ " packet_id=%u\n",
+ ip->hdr.id);
+ NT_LOG(DBG, FILTER,
+ " time_to_live=%u\n",
+ ip->hdr.ttl);
+ NT_LOG(DBG, FILTER,
+ " type_of_service=%u\n",
+ ip->hdr.tos);
+ NT_LOG(DBG, FILTER,
+ " version_ihl=%u\n",
+ ip->hdr.version_ihl);
+ NT_LOG(DBG, FILTER,
+ " total_length=%u\n",
+ ip->hdr.length);
+ }
+ if (items[iter_idx].mask) {
+ const struct flow_elem_ipv4 *ip =
+ items[iter_idx].mask;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_IPV4 MASK: dst=%d.%d.%d.%d\n",
+ ((const char *)&ip->hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&ip->hdr.dst_ip)[1] & 0xFF,
+ ((const char *)&ip->hdr.dst_ip)[2] & 0xFF,
+ ((const char *)&ip->hdr.dst_ip)[3] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " src=%d.%d.%d.%d\n",
+ ((const char *)&ip->hdr.src_ip)[0] & 0xFF,
+ ((const char *)&ip->hdr.src_ip)[1] & 0xFF,
+ ((const char *)&ip->hdr.src_ip)[2] & 0xFF,
+ ((const char *)&ip->hdr.src_ip)[3] & 0xFF);
+ NT_LOG(DBG, FILTER,
+ " fragment_offset=%x\n",
+ ip->hdr.frag_offset);
+ NT_LOG(DBG, FILTER,
+ " next_proto_id=%x\n",
+ ip->hdr.next_proto_id);
+ NT_LOG(DBG, FILTER,
+ " packet_id=%x\n",
+ ip->hdr.id);
+ NT_LOG(DBG, FILTER,
+ " time_to_live=%x\n",
+ ip->hdr.ttl);
+ NT_LOG(DBG, FILTER,
+ " type_of_service=%x\n",
+ ip->hdr.tos);
+ NT_LOG(DBG, FILTER,
+ " version_ihl=%x\n",
+ ip->hdr.version_ihl);
+ NT_LOG(DBG, FILTER,
+ " total_length=%x\n",
+ ip->hdr.length);
+ }
+ break;
+ case FLOW_ELEM_TYPE_UDP:
+ if (items[iter_idx].spec) {
+ const struct flow_elem_udp *udp =
+ (const struct flow_elem_udp *)
+ items[iter_idx]
+ .spec;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_UDP SPEC: src port=%04x\n",
+ htons(udp->hdr.src_port));
+ NT_LOG(DBG, FILTER,
+ " dst port=%04x\n",
+ htons(udp->hdr.dst_port));
+ }
+ if (items[iter_idx].mask) {
+ const struct flow_elem_udp *udp =
+ (const struct flow_elem_udp *)
+ items[iter_idx]
+ .mask;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_UDP MASK: src port=%04x\n",
+ htons(udp->hdr.src_port));
+ NT_LOG(DBG, FILTER,
+ " dst port=%04x\n",
+ htons(udp->hdr.dst_port));
+ }
+ break;
+ case FLOW_ELEM_TYPE_TAG:
+ if (items[iter_idx].spec) {
+ const struct flow_elem_tag *tag =
+ (const struct flow_elem_tag *)
+ items[iter_idx]
+ .spec;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_TAG SPEC: data=%u\n",
+ tag->data);
+ NT_LOG(DBG, FILTER,
+ " index=%u\n",
+ tag->index);
+ }
+ if (items[iter_idx].mask) {
+ const struct flow_elem_tag *tag =
+ (const struct flow_elem_tag *)
+ items[iter_idx]
+ .mask;
+ NT_LOG(DBG, FILTER,
+ "FLOW_ELEM_TYPE_TAG MASK: data=%u\n",
+ tag->data);
+ NT_LOG(DBG, FILTER,
+ " index=%u\n",
+ tag->index);
+ }
+ break;
+ case FLOW_ELEM_TYPE_VXLAN: {
+ const struct flow_elem_vxlan *vxlan =
+ (const struct flow_elem_vxlan *)
+ items[iter_idx]
+ .spec;
+ const struct flow_elem_vxlan *mask =
+ (const struct flow_elem_vxlan *)
+ items[iter_idx]
+ .mask;
+
+ uint32_t vni =
+ (uint32_t)(((uint32_t)vxlan->vni[0]
+ << 16) |
+ ((uint32_t)vxlan->vni[1]
+ << 8) |
+ ((uint32_t)vxlan->vni[2]));
+ uint32_t vni_mask =
+ (uint32_t)(((uint32_t)mask->vni[0]
+ << 16) |
+ ((uint32_t)mask->vni[1]
+ << 8) |
+ ((uint32_t)mask->vni[2]));
+
+ NT_LOG(INF, FILTER, "VNI: %08x / %08x\n", vni,
+ vni_mask);
+ }
+ break;
+ }
+#endif
+
+ match->flow_elem[eidx].type = type;
+ match->flow_elem[eidx].spec = items[iter_idx].spec;
+ match->flow_elem[eidx].mask = items[iter_idx].mask;
+
+ eidx++;
+ iter_idx++;
+ }
+
+ } while (type >= 0 && type != FLOW_ELEM_TYPE_END);
+
+ return (type >= 0) ? 0 : -1;
+}
+
+static int
+create_action_elements_vswitch(struct cnv_action_s *action,
+ const struct rte_flow_action actions[],
+ int max_elem, uint32_t *flow_stat_id)
+{
+ int aidx = 0;
+ int iter_idx = 0;
+ int type = -1;
+
+ if (!actions)
+ return -1;
+
+ if (!convert_tables_intialized)
+ initialize_global_cnv_tables();
+
+ *flow_stat_id = MAX_COLOR_FLOW_STATS;
+ do {
+ type = CNV_TO_ACTION(actions[iter_idx].type);
+ if (type < 0) {
+ if ((int)actions[iter_idx].type ==
+ NT_RTE_FLOW_ACTION_TYPE_TUNNEL_SET) {
+ type = FLOW_ACTION_TYPE_TUNNEL_SET;
+ } else {
+ NT_LOG(ERR, FILTER,
+ "ERROR unknown action type received!\n");
+ return -1;
+ }
+ }
+
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(INF, FILTER,
+ "RTE ACTION -> FILTER FLOW ACTION - %i -> %i - %s\n",
+ actions[iter_idx].type, type,
+ ((int)actions[iter_idx].type >= 0) ?
+ action_list_str[actions[iter_idx].type] :
+ "FLOW_ACTION_TYPE_TUNNEL_SET");
+#endif
+
+ if (type >= 0) {
+ action->flow_actions[aidx].type = type;
+
+ /*
+ * Non-compatible actions handled here
+ */
+ switch (type) {
+ case -1:
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(INF, FILTER,
+ "RTE ACTION UNSUPPORTED %i\n",
+ actions[iter_idx].type);
+#endif
+ return -1;
+
+ case FLOW_ACTION_TYPE_RSS: {
+ const struct rte_flow_action_rss *rss =
+ (const struct rte_flow_action_rss *)
+ actions[iter_idx]
+ .conf;
+ action->flow_rss.func =
+ FLOW_HASH_FUNCTION_DEFAULT;
+
+ if (rss->func !=
+ RTE_ETH_HASH_FUNCTION_DEFAULT)
+ return -1;
+ action->flow_rss.level = rss->level;
+ action->flow_rss.types = rss->types;
+ action->flow_rss.key_len = rss->key_len;
+ action->flow_rss.queue_num = rss->queue_num;
+ action->flow_rss.key = rss->key;
+ action->flow_rss.queue = rss->queue;
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RSS: rss->level = %u\n",
+ rss->level);
+ NT_LOG(DBG, FILTER,
+ " rss->types = 0x%" PRIX64 "\n",
+ (unsigned long long)rss->types);
+ NT_LOG(DBG, FILTER,
+ " rss->key_len = %u\n",
+ rss->key_len);
+ NT_LOG(DBG, FILTER,
+ " rss->queue_num = %u\n",
+ rss->queue_num);
+ NT_LOG(DBG, FILTER,
+ " rss->key = %p\n",
+ rss->key);
+ unsigned int i;
+
+ for (i = 0; i < rss->queue_num; i++) {
+ NT_LOG(DBG, FILTER,
+ " rss->queue[%u] = %u\n",
+ i, rss->queue[i]);
+ }
+#endif
+ action->flow_actions[aidx].conf =
+ &action->flow_rss;
+ break;
+ }
+
+ case FLOW_ACTION_TYPE_VXLAN_ENCAP: {
+ const struct rte_flow_action_vxlan_encap *tun =
+ (const struct rte_flow_action_vxlan_encap
+ *)actions[iter_idx]
+ .conf;
+ if (!tun || create_match_elements(&action->tun_def.match,
+ tun->definition,
+ MAX_ELEMENTS) != 0)
+ return -1;
+ action->tun_def.tun_definition =
+ action->tun_def.match.flow_elem;
+ action->flow_actions[aidx].conf =
+ &action->tun_def;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_MARK: {
+ const struct rte_flow_action_mark *mark_id =
+ (const struct rte_flow_action_mark *)
+ actions[iter_idx]
+ .conf;
+ if (mark_id) {
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER, "Mark ID=%u\n",
+ mark_id->id);
+#endif
+ *flow_stat_id = create_flow_stat_id(mark_id->id);
+ action->mark.id = *flow_stat_id;
+ action->flow_actions[aidx].conf =
+ &action->mark;
+
+ } else {
+ action->flow_actions[aidx].conf =
+ actions[iter_idx].conf;
+ }
+ }
+ break;
+
+ default:
+ /* Compatible */
+
+ /*
+ * OVS Full offload does not add mark in RTE Flow
+ * We need one in FPGA to control flow(color) statistics
+ */
+ if (type == FLOW_ACTION_TYPE_END &&
+ *flow_stat_id == MAX_COLOR_FLOW_STATS) {
+ /* We need to insert a mark for our FPGA */
+ *flow_stat_id = create_flow_stat_id(0);
+ action->mark.id = *flow_stat_id;
+
+ action->flow_actions[aidx].type =
+ FLOW_ACTION_TYPE_MARK;
+ action->flow_actions[aidx].conf =
+ &action->mark;
+ aidx++;
+
+ /* Move end type */
+ action->flow_actions[aidx].type =
+ FLOW_ACTION_TYPE_END;
+ }
+
+#ifdef RTE_FLOW_DEBUG
+ switch (type) {
+ case FLOW_ACTION_TYPE_PORT_ID:
+ NT_LOG(DBG, FILTER,
+ "Port ID=%u, Original=%u\n",
+ ((const struct rte_flow_action_port_id
+ *)actions[iter_idx]
+ .conf)
+ ->id,
+ ((const struct rte_flow_action_port_id
+ *)actions[iter_idx]
+ .conf)
+ ->original);
+ break;
+ case FLOW_ACTION_TYPE_COUNT:
+ NT_LOG(DBG, FILTER, "Count ID=%u\n",
+ ((const struct rte_flow_action_count
+ *)actions[iter_idx]
+ .conf)
+ ->id);
+ break;
+ case FLOW_ACTION_TYPE_SET_TAG:
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_SET_TAG: data=%u\n",
+ ((const struct flow_action_tag *)
+ actions[iter_idx]
+ .conf)
+ ->data);
+ NT_LOG(DBG, FILTER,
+ " mask=%u\n",
+ ((const struct flow_action_tag *)
+ actions[iter_idx]
+ .conf)
+ ->mask);
+ NT_LOG(DBG, FILTER,
+ " index=%u\n",
+ ((const struct flow_action_tag *)
+ actions[iter_idx]
+ .conf)
+ ->index);
+ break;
+ }
+#endif
+
+ action->flow_actions[aidx].conf =
+ actions[iter_idx].conf;
+ break;
+ }
+
+ aidx++;
+ if (aidx == max_elem)
+ return -1;
+ iter_idx++;
+ }
+
+ } while (type >= 0 && type != FLOW_ACTION_TYPE_END);
+
+ return (type >= 0) ? 0 : -1;
+}
+
+static int create_action_elements_inline(struct cnv_action_s *action,
+ const struct rte_flow_action actions[],
+ int max_elem, uint32_t queue_offset)
+{
+ int aidx = 0;
+ int type = -1;
+
+ do {
+ type = CNV_TO_ACTION(actions[aidx].type);
+
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(INF, FILTER,
+ "RTE ACTION -> FILTER FLOW ACTION - %i -> %i - %s\n",
+ actions[aidx].type, type,
+ ((int)actions[aidx].type >= 0) ?
+ action_list_str[actions[aidx].type] :
+ "FLOW_ACTION_TYPE_TUNNEL_SET");
+#endif
+
+ if (type >= 0) {
+ action->flow_actions[aidx].type = type;
+
+ /*
+ * Non-compatible actions handled here
+ */
+ switch (type) {
+ case FLOW_ACTION_TYPE_RSS: {
+ const struct rte_flow_action_rss *rss =
+ (const struct rte_flow_action_rss *)
+ actions[aidx]
+ .conf;
+ action->flow_rss.func =
+ FLOW_HASH_FUNCTION_DEFAULT;
+
+ if (rss->func !=
+ RTE_ETH_HASH_FUNCTION_DEFAULT)
+ return -1;
+ action->flow_rss.level = rss->level;
+ action->flow_rss.types = rss->types;
+ action->flow_rss.key_len = rss->key_len;
+ action->flow_rss.queue_num = rss->queue_num;
+ action->flow_rss.key = rss->key;
+ action->flow_rss.queue = rss->queue;
+ action->flow_actions[aidx].conf =
+ &action->flow_rss;
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RSS: rss->level = %u\n",
+ rss->level);
+ NT_LOG(DBG, FILTER,
+ " rss->types = 0x%" PRIX64 "\n",
+ (unsigned long long)rss->types);
+ NT_LOG(DBG, FILTER,
+ " rss->key_len = %u\n",
+ rss->key_len);
+ NT_LOG(DBG, FILTER,
+ " rss->queue_num = %u\n",
+ rss->queue_num);
+ NT_LOG(DBG, FILTER,
+ " rss->key = %p\n",
+ rss->key);
+ unsigned int i;
+
+ for (i = 0; i < rss->queue_num; i++) {
+ NT_LOG(DBG, FILTER,
+ " rss->queue[%u] = %u\n",
+ i, rss->queue[i]);
+ }
+#endif
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_RAW_DECAP: {
+ const struct rte_flow_action_raw_decap *decap =
+ (const struct rte_flow_action_raw_decap
+ *)actions[aidx]
+ .conf;
+ int item_count = interpret_raw_data(decap->data,
+ NULL, decap->size,
+ action->decap.items);
+ if (item_count < 0)
+ return item_count;
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RAW_DECAP: size = %u\n",
+ decap->size);
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RAW_DECAP: item_count = %u\n",
+ item_count);
+ for (int i = 0; i < item_count; i++) {
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RAW_DECAP: item = %u\n",
+ action->decap.items[i].type);
+ }
+#endif
+ action->decap.data = decap->data;
+ action->decap.size = decap->size;
+ action->decap.item_count = item_count;
+ action->flow_actions[aidx].conf =
+ &action->decap;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_RAW_ENCAP: {
+ const struct rte_flow_action_raw_encap *encap =
+ (const struct rte_flow_action_raw_encap
+ *)actions[aidx]
+ .conf;
+ int item_count = interpret_raw_data(encap->data,
+ encap->preserve,
+ encap->size,
+ action->encap.items);
+ if (item_count < 0)
+ return item_count;
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RAW_ENCAP: size = %u\n",
+ encap->size);
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_RAW_ENCAP: item_count = %u\n",
+ item_count);
+#endif
+ action->encap.data = encap->data;
+ action->encap.preserve = encap->preserve;
+ action->encap.size = encap->size;
+ action->encap.item_count = item_count;
+ action->flow_actions[aidx].conf =
+ &action->encap;
+ }
+ break;
+
+ case FLOW_ACTION_TYPE_QUEUE: {
+ const struct rte_flow_action_queue *queue =
+ (const struct rte_flow_action_queue *)
+ actions[aidx]
+ .conf;
+ action->queue.index =
+ queue->index + queue_offset;
+ action->flow_actions[aidx].conf =
+ &action->queue;
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_QUEUE: queue = %u\n",
+ action->queue.index);
+#endif
+ }
+ break;
+
+ default: {
+ action->flow_actions[aidx].conf =
+ actions[aidx].conf;
+
+#ifdef RTE_FLOW_DEBUG
+ switch (type) {
+ case FLOW_ACTION_TYPE_PORT_ID:
+ NT_LOG(DBG, FILTER,
+ "Port ID=%u, Original=%u\n",
+ ((const struct rte_flow_action_port_id
+ *)actions[aidx]
+ .conf)
+ ->id,
+ ((const struct rte_flow_action_port_id
+ *)actions[aidx]
+ .conf)
+ ->original);
+ break;
+ case FLOW_ACTION_TYPE_COUNT:
+ NT_LOG(DBG, FILTER, "Count ID=%u\n",
+ ((const struct rte_flow_action_count
+ *)actions[aidx]
+ .conf)
+ ->id);
+ break;
+ case FLOW_ACTION_TYPE_SET_TAG:
+ NT_LOG(DBG, FILTER,
+ "FLOW_ACTION_TYPE_SET_TAG: data=%u\n",
+ ((const struct flow_action_tag *)
+ actions[aidx]
+ .conf)
+ ->data);
+ NT_LOG(DBG, FILTER,
+ " mask=%u\n",
+ ((const struct flow_action_tag *)
+ actions[aidx]
+ .conf)
+ ->mask);
+ NT_LOG(DBG, FILTER,
+ " index=%u\n",
+ ((const struct flow_action_tag *)
+ actions[aidx]
+ .conf)
+ ->index);
+ break;
+ }
+#endif
+ }
+ break;
+ }
+
+ aidx++;
+ if (aidx == max_elem)
+ return -1;
+ }
+
+ } while (type >= 0 && type != FLOW_ACTION_TYPE_END);
+
+ return (type >= 0) ? 0 : -1;
+}
+
+#pragma GCC diagnostic pop
+
+#endif /* __CREATE_ELEMENTS_H__ */
diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
new file mode 100644
index 0000000000..b1cc4d2959
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
@@ -0,0 +1,656 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <malloc.h>
+
+#include "ntdrv_4ga.h"
+#include <rte_flow_driver.h>
+#include <rte_pci.h>
+#include "ntnic_ethdev.h"
+
+#include "ntlog.h"
+#include "nt_util.h"
+#include "create_elements.h"
+#include "ntnic_filter.h"
+
+#define MAX_RTE_FLOWS 8192
+#define MAX_PORTIDS 64
+
+#if (MAX_COLOR_FLOW_STATS != NT_MAX_COLOR_FLOW_STATS)
+#error Difference in COLOR_FLOW_STATS. Please synchronize the defines.
+#endif
+
+struct rte_flow nt_flows[MAX_RTE_FLOWS];
+
+static int is_flow_handle_typecast(struct rte_flow *flow)
+{
+ const void *first_element = &nt_flows[0];
+ const void *last_element = &nt_flows[MAX_RTE_FLOWS - 1];
+
+ return (void *)flow < first_element || (void *)flow > last_element;
+}
+
+static int convert_flow(struct rte_eth_dev *eth_dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item items[],
+ const struct rte_flow_action actions[],
+ struct cnv_attr_s *attribute, struct cnv_match_s *match,
+ struct cnv_action_s *action,
+ struct rte_flow_error *error, uint32_t *flow_stat_id)
+{
+ struct pmd_internals *dev = eth_dev->data->dev_private;
+ struct fpga_info_s *fpga_info = &dev->p_drv->ntdrv.adapter_info.fpga_info;
+
+ static struct flow_error flow_error = { .type = FLOW_ERROR_NONE,
+ .message = "none"
+ };
+ uint32_t queue_offset = 0;
+
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER, "ntnic_flow_create port_id %u - %s\n",
+ eth_dev->data->port_id, eth_dev->data->name);
+#endif
+
+ if (dev->type == PORT_TYPE_OVERRIDE && dev->vpq_nb_vq > 0) {
+ /*
+ * The queues coming from the main PMD will always start from 0
+ * When the port is a the VF/vDPA port the queues must be changed
+ * to match the queues allocated for VF/vDPA.
+ */
+ queue_offset = dev->vpq[0].id;
+ }
+
+ /* Set initial error */
+ convert_error(error, &flow_error);
+
+ if (!dev) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Missing eth_dev");
+ return -1;
+ }
+
+ if (create_attr(attribute, attr) != 0) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
+ NULL, "Error in attr");
+ return -1;
+ }
+ if (create_match_elements(match, items, MAX_ELEMENTS) != 0) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL, "Error in items");
+ return -1;
+ }
+ if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
+ if (create_action_elements_inline(action, actions, MAX_ACTIONS,
+ queue_offset) != 0) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Error in actions");
+ return -1;
+ }
+ if (attribute->attr.group > 0)
+ return 0;
+ } else if (fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH) {
+ if (create_action_elements_vswitch(action, actions, MAX_ACTIONS,
+ flow_stat_id) != 0) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Error in actions");
+ return -1;
+ }
+ } else {
+ rte_flow_error_set(error, EPERM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Unsupported adapter profile");
+ return -1;
+ }
+ return 0;
+}
+
+static int eth_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
+ struct rte_flow_error *error)
+{
+ struct pmd_internals *dev = eth_dev->data->dev_private;
+ static struct flow_error flow_error = { .type = FLOW_ERROR_NONE,
+ .message = "none"
+ };
+
+ int res = 0;
+
+ /* Set initial error */
+ convert_error(error, &flow_error);
+
+ if (!flow)
+ return 0;
+
+ if (is_flow_handle_typecast(flow)) {
+ res = flow_destroy(dev->flw_dev, (void *)flow, &flow_error);
+ convert_error(error, &flow_error);
+ } else {
+ res = flow_destroy(dev->flw_dev, flow->flw_hdl, &flow_error);
+ convert_error(error, &flow_error);
+
+ rte_spinlock_lock(&flow_lock);
+ delete_flow_stat_id_locked(flow->flow_stat_id);
+ flow->used = 0;
+ rte_spinlock_unlock(&flow_lock);
+ }
+
+ /* Clear the flow statistics if successfully destroyed */
+ if (res == 0) {
+ flow->stat_pkts = 0UL;
+ flow->stat_bytes = 0UL;
+ flow->stat_tcp_flags = 0;
+ }
+
+ return res;
+}
+
+static int eth_flow_validate(struct rte_eth_dev *eth_dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item items[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ static struct flow_error flow_error = { .type = FLOW_ERROR_NONE,
+ .message = "none"
+ };
+ struct pmd_internals *dev = eth_dev->data->dev_private;
+ struct cnv_attr_s attribute;
+ struct cnv_match_s match;
+ struct cnv_action_s action;
+ uint32_t flow_stat_id = 0;
+ int res;
+
+ if (convert_flow(eth_dev, attr, items, actions, &attribute, &match,
+ &action, error, &flow_stat_id) < 0)
+ return -EINVAL;
+
+ res = flow_validate(dev->flw_dev, match.flow_elem, action.flow_actions,
+ &flow_error);
+
+ if (res < 0)
+ convert_error(error, &flow_error);
+
+ return res;
+}
+
+static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item items[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ struct pmd_internals *dev = eth_dev->data->dev_private;
+ struct fpga_info_s *fpga_info = &dev->p_drv->ntdrv.adapter_info.fpga_info;
+
+ struct cnv_attr_s attribute;
+ struct cnv_match_s match;
+ struct cnv_action_s action;
+
+ static struct flow_error flow_error = { .type = FLOW_ERROR_NONE,
+ .message = "none"
+ };
+ uint32_t flow_stat_id = 0;
+
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(DBG, FILTER, "ntnic_flow_create port_id %u - %s\n",
+ eth_dev->data->port_id, eth_dev->data->name);
+#endif
+
+ if (convert_flow(eth_dev, attr, items, actions, &attribute, &match,
+ &action, error, &flow_stat_id) < 0)
+ return NULL;
+
+ if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE &&
+ attribute.attr.group > 0) {
+ void *flw_hdl = flow_create(dev->flw_dev, &attribute.attr,
+ match.flow_elem,
+ action.flow_actions, &flow_error);
+ convert_error(error, &flow_error);
+ return (struct rte_flow *)flw_hdl;
+ }
+
+ struct rte_flow *flow = NULL;
+
+ rte_spinlock_lock(&flow_lock);
+ int i;
+
+ for (i = 0; i < MAX_RTE_FLOWS; i++) {
+ if (!nt_flows[i].used) {
+ nt_flows[i].flow_stat_id = flow_stat_id;
+ if (nt_flows[i].flow_stat_id <
+ NT_MAX_COLOR_FLOW_STATS) {
+ nt_flows[i].used = 1;
+ flow = &nt_flows[i];
+ }
+ break;
+ }
+ }
+ rte_spinlock_unlock(&flow_lock);
+ if (flow) {
+ flow->flw_hdl = flow_create(dev->flw_dev, &attribute.attr,
+ match.flow_elem,
+ action.flow_actions, &flow_error);
+ convert_error(error, &flow_error);
+ if (!flow->flw_hdl) {
+ rte_spinlock_lock(&flow_lock);
+ delete_flow_stat_id_locked(flow->flow_stat_id);
+ flow->used = 0;
+ flow = NULL;
+ rte_spinlock_unlock(&flow_lock);
+ } else {
+#ifdef RTE_FLOW_DEBUG
+ NT_LOG(INF, FILTER, "Create Flow %p using stat_id %i\n",
+ flow, flow->flow_stat_id);
+#endif
+ }
+ }
+ return flow;
+}
+
+uint64_t last_stat_rtc;
+
+int poll_statistics(struct pmd_internals *internals)
+{
+ int flow;
+ struct drv_s *p_drv = internals->p_drv;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ const int if_index = internals->if_index;
+
+ if (!p_nt4ga_stat || if_index < 0 || if_index > NUM_ADAPTER_PORTS_MAX)
+ return -1;
+
+ assert(rte_tsc_freq > 0);
+
+ rte_spinlock_lock(&hwlock);
+
+ uint64_t now_rtc = rte_get_tsc_cycles();
+
+ /*
+ * Check per port max once a second
+ * if more than a second since last stat read, do a new one
+ */
+ if ((now_rtc - internals->last_stat_rtc) < rte_tsc_freq) {
+ rte_spinlock_unlock(&hwlock);
+ return 0;
+ }
+
+ internals->last_stat_rtc = now_rtc;
+
+ pthread_mutex_lock(&p_nt_drv->stat_lck);
+
+ /*
+ * Add the RX statistics increments since last time we polled.
+ * (No difference if physical or virtual port)
+ */
+ internals->rxq_scg[0].rx_pkts +=
+ p_nt4ga_stat->a_port_rx_packets_total[if_index] -
+ p_nt4ga_stat->a_port_rx_packets_base[if_index];
+ internals->rxq_scg[0].rx_bytes +=
+ p_nt4ga_stat->a_port_rx_octets_total[if_index] -
+ p_nt4ga_stat->a_port_rx_octets_base[if_index];
+ internals->rxq_scg[0].err_pkts += 0;
+ internals->rx_missed += p_nt4ga_stat->a_port_rx_drops_total[if_index] -
+ p_nt4ga_stat->a_port_rx_drops_base[if_index];
+
+ /* _update the increment bases */
+ p_nt4ga_stat->a_port_rx_packets_base[if_index] =
+ p_nt4ga_stat->a_port_rx_packets_total[if_index];
+ p_nt4ga_stat->a_port_rx_octets_base[if_index] =
+ p_nt4ga_stat->a_port_rx_octets_total[if_index];
+ p_nt4ga_stat->a_port_rx_drops_base[if_index] =
+ p_nt4ga_stat->a_port_rx_drops_total[if_index];
+
+ /* Tx (here we must distinguish between physical and virtual ports) */
+ if (internals->type == PORT_TYPE_PHYSICAL) {
+ /* LAG management of Tx stats. */
+ if (lag_active && if_index == 0) {
+ unsigned int i;
+ /*
+ * Collect all LAG ports Tx stat into this one. Simplified to only collect
+ * from port 0 and 1.
+ */
+ for (i = 0; i < 2; i++) {
+ /* Add the statistics increments since last time we polled */
+ internals->txq_scg[0].tx_pkts +=
+ p_nt4ga_stat->a_port_tx_packets_total[i] -
+ p_nt4ga_stat->a_port_tx_packets_base[i];
+ internals->txq_scg[0].tx_bytes +=
+ p_nt4ga_stat->a_port_tx_octets_total[i] -
+ p_nt4ga_stat->a_port_tx_octets_base[i];
+ internals->txq_scg[0].err_pkts += 0;
+
+ /* _update the increment bases */
+ p_nt4ga_stat->a_port_tx_packets_base[i] =
+ p_nt4ga_stat->a_port_tx_packets_total[i];
+ p_nt4ga_stat->a_port_tx_octets_base[i] =
+ p_nt4ga_stat->a_port_tx_octets_total[i];
+ }
+ } else {
+ /* Add the statistics increments since last time we polled */
+ internals->txq_scg[0].tx_pkts +=
+ p_nt4ga_stat->a_port_tx_packets_total[if_index] -
+ p_nt4ga_stat->a_port_tx_packets_base[if_index];
+ internals->txq_scg[0].tx_bytes +=
+ p_nt4ga_stat->a_port_tx_octets_total[if_index] -
+ p_nt4ga_stat->a_port_tx_octets_base[if_index];
+ internals->txq_scg[0].err_pkts += 0;
+
+ /* _update the increment bases */
+ p_nt4ga_stat->a_port_tx_packets_base[if_index] =
+ p_nt4ga_stat->a_port_tx_packets_total[if_index];
+ p_nt4ga_stat->a_port_tx_octets_base[if_index] =
+ p_nt4ga_stat->a_port_tx_octets_total[if_index];
+ }
+ }
+ if (internals->type == PORT_TYPE_VIRTUAL) {
+ /* _update TX counters from HB queue counter */
+ unsigned int i;
+ struct host_buffer_counters *const p_hb_counters =
+ p_nt4ga_stat->mp_stat_structs_hb;
+ uint64_t v_port_packets_total = 0, v_port_octets_total = 0;
+
+ /*
+ * This is a bit odd. But typically nb_tx_queues must be only 1 since it denotes
+ * the number of exception queues which must be 1 - for now. The code is kept if we
+ * want it in future, but it will not be likely.
+ * Therefore adding all vPorts queue tx counters into Tx[0] is ok for now.
+ *
+ * Only use the vPort Tx counter to update OVS, since these are the real ones.
+ * The rep port into OVS that represents this port will always replicate the traffic
+ * here, also when no offload occurs
+ */
+ for (i = 0; i < internals->vpq_nb_vq; ++i) {
+ v_port_packets_total +=
+ p_hb_counters[internals->vpq[i].id].fwd_packets;
+ v_port_octets_total +=
+ p_hb_counters[internals->vpq[i].id].fwd_bytes;
+ }
+ /* Add the statistics increments since last time we polled */
+ internals->txq_scg[0].tx_pkts +=
+ v_port_packets_total -
+ p_nt4ga_stat->a_port_tx_packets_base[if_index];
+ internals->txq_scg[0].tx_bytes +=
+ v_port_octets_total -
+ p_nt4ga_stat->a_port_tx_octets_base[if_index];
+ internals->txq_scg[0].err_pkts += 0; /* What to user here ?? */
+
+ /* _update the increment bases */
+ p_nt4ga_stat->a_port_tx_packets_base[if_index] = v_port_packets_total;
+ p_nt4ga_stat->a_port_tx_octets_base[if_index] = v_port_octets_total;
+ }
+
+ /* Globally only once a second */
+ if ((now_rtc - last_stat_rtc) < rte_tsc_freq) {
+ rte_spinlock_unlock(&hwlock);
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+ return 0;
+ }
+
+ last_stat_rtc = now_rtc;
+
+ /* All color counter are global, therefore only 1 pmd must update them */
+ const struct color_counters *p_color_counters =
+ p_nt4ga_stat->mp_stat_structs_color;
+ struct color_counters *p_color_counters_base =
+ p_nt4ga_stat->a_stat_structs_color_base;
+ uint64_t color_packets_accumulated, color_bytes_accumulated;
+
+ for (flow = 0; flow < MAX_RTE_FLOWS; flow++) {
+ if (nt_flows[flow].used) {
+ unsigned int color = nt_flows[flow].flow_stat_id;
+
+ if (color < NT_MAX_COLOR_FLOW_STATS) {
+ color_packets_accumulated =
+ p_color_counters[color].color_packets;
+ nt_flows[flow].stat_pkts +=
+ (color_packets_accumulated -
+ p_color_counters_base[color].color_packets);
+
+ nt_flows[flow].stat_tcp_flags |=
+ p_color_counters[color].tcp_flags;
+
+ color_bytes_accumulated =
+ p_color_counters[color].color_bytes;
+ nt_flows[flow].stat_bytes +=
+ (color_bytes_accumulated -
+ p_color_counters_base[color].color_bytes);
+
+ /* _update the counter bases */
+ p_color_counters_base[color].color_packets =
+ color_packets_accumulated;
+ p_color_counters_base[color].color_bytes =
+ color_bytes_accumulated;
+ }
+ }
+ }
+
+ rte_spinlock_unlock(&hwlock);
+ pthread_mutex_unlock(&p_nt_drv->stat_lck);
+
+ return 0;
+}
+
+static int eth_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
+ const struct rte_flow_action *action, void *data,
+ struct rte_flow_error *err)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+
+ err->cause = NULL;
+ err->message = NULL;
+
+ if (is_flow_handle_typecast(flow)) {
+ rte_flow_error_set(err, EFAULT, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "Error in flow handle");
+ return -1;
+ }
+
+ poll_statistics(internals);
+
+ if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+ struct rte_flow_query_count *qcnt =
+ (struct rte_flow_query_count *)data;
+ if (qcnt) {
+ if (flow) {
+ qcnt->hits = flow->stat_pkts;
+ qcnt->hits_set = 1;
+ qcnt->bytes = flow->stat_bytes;
+ qcnt->bytes_set = 1;
+
+ if (qcnt->reset) {
+ flow->stat_pkts = 0UL;
+ flow->stat_bytes = 0UL;
+ flow->stat_tcp_flags = 0;
+ }
+ } else {
+ qcnt->hits_set = 0;
+ qcnt->bytes_set = 0;
+ }
+ }
+ } else {
+ rte_flow_error_set(err, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "Unsupported query");
+ return -1;
+ }
+ rte_flow_error_set(err, 0, RTE_FLOW_ERROR_TYPE_NONE, NULL, "Success");
+ return 0;
+}
+
+#ifdef DEBUGGING
+
+static void _print_tunnel(struct rte_flow_tunnel *tunnel)
+{
+ struct in_addr addr;
+
+ NT_LOG(DBG, FILTER, " tun type: %i\n", tunnel->type);
+ NT_LOG(DBG, FILTER, " tun ID: %016lx\n", tunnel->tun_id);
+ addr.s_addr = tunnel->ipv4.src_addr;
+ NT_LOG(DBG, FILTER, " tun src IP: %s\n", inet_ntoa(addr));
+ addr.s_addr = tunnel->ipv4.dst_addr;
+ NT_LOG(DBG, FILTER, " tun dst IP: %s\n", inet_ntoa(addr));
+ NT_LOG(DBG, FILTER, " tun tp_src: %i\n", htons(tunnel->tp_src));
+ NT_LOG(DBG, FILTER, " tun tp_dst: %i\n", htons(tunnel->tp_dst));
+ NT_LOG(DBG, FILTER, " tun flags: %i\n", tunnel->tun_flags);
+ NT_LOG(DBG, FILTER, " tun ipv6: %i\n", tunnel->is_ipv6);
+
+ NT_LOG(DBG, FILTER, " tun tos: %i\n", tunnel->tos);
+ NT_LOG(DBG, FILTER, " tun ttl: %i\n", tunnel->ttl);
+}
+#endif
+
+static struct rte_flow_action _pmd_actions[] = {
+ { .type = (enum rte_flow_action_type)NT_RTE_FLOW_ACTION_TYPE_TUNNEL_SET,
+ .conf = NULL
+ },
+ { .type = 0, .conf = NULL }
+};
+
+static int ntnic_tunnel_decap_set(struct rte_eth_dev *dev _unused,
+ struct rte_flow_tunnel *tunnel,
+ struct rte_flow_action **pmd_actions,
+ uint32_t *num_of_actions,
+ struct rte_flow_error *err _unused)
+{
+#ifdef DEBUGGING
+ NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__);
+#endif
+
+ if (tunnel->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+ _pmd_actions[1].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
+ else
+ return -ENOTSUP;
+
+ *pmd_actions = _pmd_actions;
+ *num_of_actions = 2;
+
+ return 0;
+}
+
+static struct rte_flow_item _pmd_items = {
+ .type = (enum rte_flow_item_type)NT_RTE_FLOW_ITEM_TYPE_TUNNEL,
+ .spec = NULL,
+ .last = NULL,
+ .mask = NULL
+};
+
+static int ntnic_tunnel_match(struct rte_eth_dev *dev _unused,
+ struct rte_flow_tunnel *tunnel _unused,
+ struct rte_flow_item **pmd_items,
+ uint32_t *num_of_items,
+ struct rte_flow_error *err _unused)
+{
+#ifdef DEBUGGING
+ NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__);
+#endif
+
+ *pmd_items = &_pmd_items;
+ *num_of_items = 1;
+ return 0;
+}
+
+/*
+ * Restoration API support
+ */
+static int ntnic_get_restore_info(struct rte_eth_dev *dev _unused,
+ struct rte_mbuf *m,
+ struct rte_flow_restore_info *info,
+ struct rte_flow_error *err _unused)
+{
+#ifdef DEBUGGING
+ NT_LOG(DBG, FILTER, "%s: [%s:%u]\n", __func__, __FILE__, __LINE__);
+ NT_LOG(DBG, FILTER, "dev name: %s - port_id %i\n", dev->data->name, dev->data->port_id);
+ NT_LOG(DBG, FILTER, "dpdk tunnel mark %08x\n", m->hash.fdir.hi);
+#endif
+
+ if ((m->ol_flags & RTE_MBUF_F_RX_FDIR_ID) && m->hash.fdir.hi) {
+ uint8_t port_id = (m->hash.fdir.hi >> 24) & 0xff;
+ uint32_t stat_id = m->hash.fdir.lo & 0xffffff;
+
+ struct tunnel_cfg_s tuncfg;
+ int ret = flow_get_tunnel_definition(&tuncfg, stat_id, port_id);
+
+ if (ret)
+ return -EINVAL;
+
+ if (tuncfg.ipversion == 4) {
+ info->tunnel.ipv4.dst_addr = tuncfg.v4.dst_ip;
+ info->tunnel.ipv4.src_addr = tuncfg.v4.src_ip;
+ info->tunnel.is_ipv6 = 0;
+ } else {
+ /* IPv6 */
+ for (int i = 0; i < 16; i++) {
+ info->tunnel.ipv6.src_addr[i] =
+ tuncfg.v6.src_ip[i];
+ info->tunnel.ipv6.dst_addr[i] =
+ tuncfg.v6.dst_ip[i];
+ }
+ info->tunnel.is_ipv6 = 1;
+ }
+
+ info->tunnel.tp_dst = tuncfg.d_port;
+ info->tunnel.tp_src = tuncfg.s_port;
+
+ info->tunnel.ttl = 64;
+ info->tunnel.tos = 0;
+
+ /* FLOW_TNL_F_KEY | FLOW_TNL_F_DONT_FRAGMENT */
+ info->tunnel.tun_flags = (1 << 3) | (1 << 1);
+
+ info->tunnel.type = RTE_FLOW_ITEM_TYPE_VXLAN;
+ info->tunnel.tun_id = m->hash.fdir.hi & 0xffffff;
+
+ info->flags = RTE_FLOW_RESTORE_INFO_TUNNEL;
+ /* | RTE_FLOW_RESTORE_INFO_ENCAPSULATED; if restored packet is sent back */
+ info->group_id = 0;
+
+#ifdef DEBUGGING
+ _print_tunnel(&info->tunnel);
+#endif
+
+ return 0;
+ }
+ return -EINVAL; /* Supported, but no hit found */
+}
+
+static int
+ntnic_tunnel_action_decap_release(struct rte_eth_dev *dev _unused,
+ struct rte_flow_action *pmd_actions _unused,
+ uint32_t num_of_actions _unused,
+ struct rte_flow_error *err _unused)
+{
+#ifdef DEBUGGING
+ NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__);
+#endif
+ return 0;
+}
+
+static int ntnic_tunnel_item_release(struct rte_eth_dev *dev _unused,
+ struct rte_flow_item *pmd_items _unused,
+ uint32_t num_of_items _unused,
+ struct rte_flow_error *err _unused)
+{
+#ifdef DEBUGGING
+ NT_LOG(DBG, FILTER, "%s: [%s:%u] start\n", __func__, __FILE__, __LINE__);
+#endif
+ return 0;
+}
+
+const struct rte_flow_ops _dev_flow_ops = {
+ .validate = eth_flow_validate,
+ .create = eth_flow_create,
+ .destroy = eth_flow_destroy,
+ .flush = NULL,
+ .query = eth_flow_query,
+ .tunnel_decap_set = ntnic_tunnel_decap_set,
+ .tunnel_match = ntnic_tunnel_match,
+ .get_restore_info = ntnic_get_restore_info,
+ .tunnel_action_decap_release = ntnic_tunnel_action_decap_release,
+ .tunnel_item_release = ntnic_tunnel_item_release
+
+};
diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.h b/drivers/net/ntnic/ntnic_filter/ntnic_filter.h
new file mode 100644
index 0000000000..cf4207e5de
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTNIC_FILTER_H__
+#define __NTNIC_FILTER_H__
+
+struct rte_flow *
+client_flow_create(struct flow_eth_dev *flw_dev, enum fpga_info_profile profile,
+ struct cnv_attr_s *attribute, struct cnv_match_s *match,
+ struct cnv_action_s *action, uint32_t flow_stat_id,
+ struct rte_flow_error *error);
+
+#endif /* __NTNIC_FILTER_H__ */
diff --git a/drivers/net/ntnic/ntnic_hshconfig.c b/drivers/net/ntnic/ntnic_hshconfig.c
new file mode 100644
index 0000000000..a8eff76528
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_hshconfig.c
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <ntlog.h>
+#include <flow_api.h>
+
+#include "ntnic_hshconfig.h"
+
+#include <rte_ethdev.h>
+#include <nthw_helper.h>
+
+struct pair_uint64_t {
+ uint64_t first;
+ uint64_t second;
+};
+
+#define PAIR_NT(name) \
+ { \
+ RTE_##name, NT_##name \
+ }
+
+struct pair_uint64_t rte_eth_rss_to_nt[] = {
+ PAIR_NT(ETH_RSS_IPV4),
+ PAIR_NT(ETH_RSS_FRAG_IPV4),
+ PAIR_NT(ETH_RSS_NONFRAG_IPV4_OTHER),
+ PAIR_NT(ETH_RSS_IPV6),
+ PAIR_NT(ETH_RSS_FRAG_IPV6),
+ PAIR_NT(ETH_RSS_NONFRAG_IPV6_OTHER),
+ PAIR_NT(ETH_RSS_IPV6_EX),
+ PAIR_NT(ETH_RSS_C_VLAN),
+ PAIR_NT(ETH_RSS_L3_DST_ONLY),
+ PAIR_NT(ETH_RSS_L3_SRC_ONLY),
+ PAIR_NT(ETH_RSS_LEVEL_OUTERMOST),
+ PAIR_NT(ETH_RSS_LEVEL_INNERMOST),
+};
+
+static const uint64_t *rte_to_nt_rss_flag(const uint64_t rte_flag)
+{
+ const struct pair_uint64_t *start = rte_eth_rss_to_nt;
+
+ for (const struct pair_uint64_t *p = start;
+ p != start + ARRAY_SIZE(rte_eth_rss_to_nt); ++p) {
+ if (p->first == rte_flag)
+ return &p->second;
+ }
+ return NULL; /* NOT found */
+}
+
+static const uint64_t *nt_to_rte_rss_flag(const uint64_t nt_flag)
+{
+ const struct pair_uint64_t *start = rte_eth_rss_to_nt;
+
+ for (const struct pair_uint64_t *p = start;
+ p != start + ARRAY_SIZE(rte_eth_rss_to_nt); ++p) {
+ if (p->second == nt_flag)
+ return &p->first;
+ }
+ return NULL; /* NOT found */
+}
+
+struct nt_eth_rss nt_rss_hash_field_from_dpdk(uint64_t rte_hash_bits)
+{
+ struct nt_eth_rss res = { 0 };
+
+ for (uint i = 0; i < sizeof(rte_hash_bits) * CHAR_BIT; ++i) {
+ uint64_t rte_bit = (UINT64_C(1) << i);
+
+ if (rte_hash_bits & rte_bit) {
+ const uint64_t *nt_bit_p = rte_to_nt_rss_flag(rte_bit);
+
+ if (!nt_bit_p) {
+ NT_LOG(ERR, ETHDEV,
+ "RSS hash function field number %d is not supported. Only supported fields will be used in RSS hash function.",
+ i);
+ } else {
+ res.fields |= *nt_bit_p;
+ }
+ }
+ }
+
+ return res;
+}
+
+uint64_t dpdk_rss_hash_define_from_nt_rss(struct nt_eth_rss nt_hsh)
+{
+ uint64_t res = 0;
+
+ for (uint i = 0; i < sizeof(nt_hsh.fields) * CHAR_BIT; ++i) {
+ uint64_t nt_bit = (UINT64_C(1) << i);
+
+ if (nt_hsh.fields & nt_bit) {
+ const uint64_t *rte_bit_p = nt_to_rte_rss_flag(nt_bit);
+
+ assert(rte_bit_p &&
+ "All nt rss bit flags should be mapped to rte rss bit fields, as nt rss is a subset of rte options");
+ res |= *rte_bit_p;
+ }
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/ntnic_hshconfig.h b/drivers/net/ntnic/ntnic_hshconfig.h
new file mode 100644
index 0000000000..d4d7337d23
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_hshconfig.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <flow_api.h>
+
+/* Mapping from dpdk rss hash defines to nt hash defines */
+struct nt_eth_rss nt_rss_hash_field_from_dpdk(uint64_t rte_hash_bits);
+uint64_t dpdk_rss_hash_define_from_nt_rss(struct nt_eth_rss nt_hsh);
diff --git a/drivers/net/ntnic/ntnic_meter.c b/drivers/net/ntnic/ntnic_meter.c
new file mode 100644
index 0000000000..027ae073dd
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_meter.c
@@ -0,0 +1,811 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_meter.h>
+#include <ethdev_pci.h>
+#include <ethdev_driver.h>
+
+#include "ntdrv_4ga.h"
+#include "nthw_fpga.h"
+#include "ntnic_ethdev.h"
+#include "ntnic_meter.h"
+#include "ntlog.h"
+
+/*
+ *******************************************************************************
+ * Vswitch metering
+ *******************************************************************************
+ */
+
+static const uint32_t highest_bit_mask = (~(~0u >> 1));
+
+static struct nt_mtr_profile *
+nt_mtr_profile_find(struct pmd_internals *dev_priv, uint32_t meter_profile_id)
+{
+ struct nt_mtr_profile *profile = NULL;
+
+ LIST_FOREACH(profile, &dev_priv->mtr_profiles, next)
+ if (profile->profile_id == meter_profile_id)
+ break;
+
+ return profile;
+}
+
+static int eth_meter_profile_add(struct rte_eth_dev *dev,
+ uint32_t meter_profile_id,
+ struct rte_mtr_meter_profile *profile,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ const bool is_egress = meter_profile_id & highest_bit_mask;
+
+ if (dev_priv->type == PORT_TYPE_VIRTUAL || is_egress) {
+ struct nt_mtr_profile *prof;
+
+ prof = nt_mtr_profile_find(dev_priv, meter_profile_id);
+ if (prof)
+ return -rte_mtr_error_set(error, EEXIST,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL,
+ "Profile id already exists\n");
+
+ prof = rte_zmalloc(NULL, sizeof(*prof), 0);
+ if (!prof) {
+ return -rte_mtr_error_set(error,
+ ENOMEM, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+ NULL, NULL);
+ }
+
+ prof->profile_id = meter_profile_id;
+ memcpy(&prof->profile, profile,
+ sizeof(struct rte_mtr_meter_profile));
+
+ LIST_INSERT_HEAD(&dev_priv->mtr_profiles, prof, next);
+
+ return 0;
+ }
+ /* Ingress is not possible yet on phy ports */
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Traffic ingress metering/policing is not supported on physical ports\n");
+}
+
+static int eth_meter_profile_delete(struct rte_eth_dev *dev,
+ uint32_t meter_profile_id,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+ struct nt_mtr_profile *profile;
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ profile = nt_mtr_profile_find(dev_priv, meter_profile_id);
+ if (!profile)
+ return -rte_mtr_error_set(error, ENODEV,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL, "Profile id does not exist\n");
+
+ LIST_REMOVE(profile, next);
+ rte_free(profile);
+ return 0;
+}
+
+static struct nt_mtr *nt_mtr_find(struct pmd_internals *dev_priv,
+ uint32_t mtr_id)
+{
+ struct nt_mtr *mtr = NULL;
+
+ LIST_FOREACH(mtr, &dev_priv->mtrs, next)
+ if (mtr->mtr_id == mtr_id)
+ break;
+
+ return mtr;
+}
+
+struct qos_integer_fractional {
+ uint32_t integer;
+ uint32_t fractional; /* 1/1024 */
+};
+
+/*
+ * Converts byte/s to byte/period if form of integer + 1/1024*fractional
+ * the period depends on the clock friquency and other parameters which
+ * being combined give multiplier. The resulting formula is:
+ * f[bytes/period] = x[byte/s] * period_ps / 10^-12
+ */
+static struct qos_integer_fractional
+byte_per_second_to_qo_s_ri(uint64_t byte_per_second, uint64_t period_ps)
+{
+ struct qos_integer_fractional res;
+ const uint64_t dividend = byte_per_second * period_ps;
+ const uint64_t divisor = 1000000000000ull; /*10^12 pico second*/
+
+ res.integer = dividend / divisor;
+ const uint64_t reminder = dividend % divisor;
+
+ res.fractional = 1024ull * reminder / divisor;
+ return res;
+}
+
+static struct qos_integer_fractional
+byte_per_second_to_physical_qo_s_ri(uint64_t byte_per_second)
+{
+ return byte_per_second_to_qo_s_ri(byte_per_second, 8 * 3333ul);
+}
+
+static struct qos_integer_fractional
+byte_per_second_to_virtual_qo_s_ri(uint64_t byte_per_second)
+{
+ return byte_per_second_to_qo_s_ri(byte_per_second, 512 * 3333ul);
+}
+
+static int eth_meter_enable(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+ int res;
+ static int ingress_initial;
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ nthw_dbs_t *p_nthw_dbs =
+ dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_dbs;
+ nthw_epp_t *p_nthw_epp =
+ dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_epp;
+
+ /*
+ * FPGA is based on FRC 4115 so CIR,EIR and CBS/EBS are used
+ * rfc4115.cir = rfc2697.cir
+ * rfc4115.eir = rfc2697.cir
+ * rfc4115.cbs = rfc2697.cbs
+ * rfc4115.ebs = rfc2697.ebs
+ */
+ struct nt_mtr *mtr = nt_mtr_find(dev_priv, mtr_id);
+
+ if (!mtr) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
+ "Meter id not found\n");
+ }
+
+ if (!mtr->profile) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL, "Meter profile id not found\n");
+ }
+
+ const uint32_t profile_id = mtr->profile->profile_id;
+ const bool is_egress = profile_id & highest_bit_mask;
+ uint32_t burst = mtr->profile->profile.srtcm_rfc2697.cbs;
+
+ if (is_egress) {
+ const bool is_virtual = (dev_priv->type == PORT_TYPE_VIRTUAL);
+ struct qos_integer_fractional cir = { 0 };
+
+ if (is_virtual) {
+ cir =
+ byte_per_second_to_virtual_qo_s_ri(mtr->profile->profile.srtcm_rfc2697.cir);
+ if (cir.integer == 0 && cir.fractional == 0)
+ cir.fractional = 1;
+ res = nthw_epp_set_vport_qos(p_nthw_epp, dev_priv->port,
+ cir.integer, cir.fractional,
+ burst);
+ } else {
+ cir =
+ byte_per_second_to_physical_qo_s_ri(mtr->profile->profile
+ .srtcm_rfc2697.cir);
+ if (cir.integer == 0 && cir.fractional == 0)
+ cir.fractional = 1;
+ res = nthw_epp_set_txp_qos(p_nthw_epp, dev_priv->port,
+ cir.integer, cir.fractional,
+ burst);
+ }
+ if (res) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Applying meter profile for setting egress policy failed\n");
+ }
+ } else {
+ if (!ingress_initial) {
+ /*
+ * based on a 250Mhz FPGA
+ * _update refresh rate interval calculation:
+ * multiplier / (divider * 4ns)
+ * 1 / (2000 * 4ns) = 8,000*10-6 => refresh rate interval = 8000ns
+ *
+ * results in resolution of IR is 1Mbps
+ */
+ res = nthw_set_tx_qos_rate_global(p_nthw_dbs, 1, 2000);
+
+ if (res) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Applying meter profile for setting ingress "
+ "global QoS rate failed\n");
+ }
+ ingress_initial = 1;
+ }
+
+ if (mtr->profile->profile.srtcm_rfc2697.cbs >= (1 << 27)) {
+ /* max burst 1,074Mb (27 bits) */
+ mtr->profile->profile.srtcm_rfc2697.cbs = (1 << 27) - 1;
+ }
+ /* IR - fill x bytes each 8000ns -> 1B/8000ns => 1000Kbps => 125000Bps / x */
+ res = nthw_set_tx_qos_config(p_nthw_dbs, dev_priv->port, /* vport */
+ 1, /* enable */
+ mtr->profile->profile.srtcm_rfc2697.cir /
+ 125000,
+ mtr->profile->profile.srtcm_rfc2697
+ .cbs); /* BS - burst size in Bytes */
+ if (res) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+ NULL, "Applying meter profile failed\n");
+ }
+ }
+ return 0;
+}
+
+static void disable(struct pmd_internals *dev_priv)
+{
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ nthw_dbs_t *p_nthw_dbs =
+ dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_dbs;
+ nthw_set_tx_qos_config(p_nthw_dbs, dev_priv->port, /* vport */
+ 0, /* disable */
+ 0, /* IR */
+ 0); /* BS */
+}
+
+static int eth_meter_disable(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+ struct nt_mtr *mtr = nt_mtr_find(dev_priv, mtr_id);
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ nthw_epp_t *p_nthw_epp =
+ dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_epp;
+
+ if (!mtr) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
+ "Meter id not found\n");
+ }
+
+ const bool is_egress = mtr_id & highest_bit_mask;
+
+ if (is_egress) {
+ const bool is_virtual = (dev_priv->type == PORT_TYPE_VIRTUAL);
+
+ if (is_virtual)
+ nthw_epp_set_vport_qos(p_nthw_epp, dev_priv->port, 0, 0, 0);
+ else
+ nthw_epp_set_txp_qos(p_nthw_epp, dev_priv->port, 0, 0, 0);
+ } else {
+ disable(dev_priv);
+ }
+ return 0;
+}
+
+/* MTR object create */
+static int eth_mtr_create(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_params *params, int shared,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+ struct nt_mtr *mtr = NULL;
+ struct nt_mtr_profile *profile;
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ const bool is_egress = mtr_id & highest_bit_mask;
+
+ if (dev_priv->type == PORT_TYPE_PHYSICAL && !is_egress) {
+ NT_LOG(ERR, NTHW,
+ "ERROR try to create ingress meter object on a phy port. Not supported\n");
+
+ return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Traffic ingress metering/policing is not supported on physical ports\n");
+ }
+
+ mtr = nt_mtr_find(dev_priv, mtr_id);
+ if (mtr)
+ return -rte_mtr_error_set(error, EEXIST,
+ RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
+ "Meter id already exists\n");
+
+ profile = nt_mtr_profile_find(dev_priv, params->meter_profile_id);
+ if (!profile) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL, "Profile id does not exist\n");
+ }
+
+ mtr = rte_zmalloc(NULL, sizeof(struct nt_mtr), 0);
+ if (!mtr)
+ return -rte_mtr_error_set(error, ENOMEM,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ NULL);
+
+ mtr->shared = shared;
+ mtr->mtr_id = mtr_id;
+ mtr->profile = profile;
+ LIST_INSERT_HEAD(&dev_priv->mtrs, mtr, next);
+
+ if (params->meter_enable)
+ return eth_meter_enable(dev, mtr_id, error);
+
+ return 0;
+}
+
+/* MTR object destroy */
+static int eth_mtr_destroy(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+ struct nt_mtr *mtr;
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] adapter: " PCIIDENT_PRINT_STR "\n",
+ __func__, __func__, __LINE__,
+ PCIIDENT_TO_DOMAIN(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_BUSNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_DEVNR(dev_priv->p_drv->ntdrv.pciident),
+ PCIIDENT_TO_FUNCNR(dev_priv->p_drv->ntdrv.pciident));
+
+ nthw_epp_t *p_nthw_epp =
+ dev_priv->p_drv->ntdrv.adapter_info.fpga_info.mp_nthw_epp;
+
+ mtr = nt_mtr_find(dev_priv, mtr_id);
+ if (!mtr)
+ return -rte_mtr_error_set(error, EEXIST,
+ RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
+ "Meter id does not exist\n");
+
+ const bool is_egress = mtr_id & highest_bit_mask;
+
+ if (is_egress) {
+ const bool is_virtual = (dev_priv->type == PORT_TYPE_VIRTUAL);
+
+ if (is_virtual)
+ nthw_epp_set_vport_qos(p_nthw_epp, dev_priv->port, 0, 0, 0);
+ else
+ nthw_epp_set_txp_qos(p_nthw_epp, dev_priv->port, 0, 0, 0);
+ } else {
+ disable(dev_priv);
+ }
+ LIST_REMOVE(mtr, next);
+ rte_free(mtr);
+ return 0;
+}
+
+/*
+ *******************************************************************************
+ * Inline FLM metering
+ *******************************************************************************
+ */
+
+static int eth_mtr_capabilities_get_inline(struct rte_eth_dev *dev,
+ struct rte_mtr_capabilities *cap,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (!flow_mtr_supported(dev_priv->flw_dev)) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Ethernet device does not support metering\n");
+ }
+
+ memset(cap, 0x0, sizeof(struct rte_mtr_capabilities));
+
+ /* MBR records use 28-bit integers */
+ cap->n_max = flow_mtr_meters_supported();
+ cap->n_shared_max = cap->n_max;
+
+ cap->identical = 0;
+ cap->shared_identical = 0;
+
+ cap->shared_n_flows_per_mtr_max = UINT32_MAX;
+
+ /* Limited by number of MBR record ids per FLM learn record */
+ cap->chaining_n_mtrs_per_flow_max = 4;
+
+ cap->chaining_use_prev_mtr_color_supported = 0;
+ cap->chaining_use_prev_mtr_color_enforced = 0;
+
+ cap->meter_rate_max = (uint64_t)(0xfff << 0xf) * 1099;
+
+ cap->stats_mask = RTE_MTR_STATS_N_PKTS_GREEN |
+ RTE_MTR_STATS_N_BYTES_GREEN;
+
+ /* Only color-blind mode is supported */
+ cap->color_aware_srtcm_rfc2697_supported = 0;
+ cap->color_aware_trtcm_rfc2698_supported = 0;
+ cap->color_aware_trtcm_rfc4115_supported = 0;
+
+ /* Focused on RFC2698 for now */
+ cap->meter_srtcm_rfc2697_n_max = 0;
+ cap->meter_trtcm_rfc2698_n_max = cap->n_max;
+ cap->meter_trtcm_rfc4115_n_max = 0;
+
+ cap->meter_policy_n_max = flow_mtr_meter_policy_n_max();
+
+ /* Byte mode is supported */
+ cap->srtcm_rfc2697_byte_mode_supported = 0;
+ cap->trtcm_rfc2698_byte_mode_supported = 1;
+ cap->trtcm_rfc4115_byte_mode_supported = 0;
+
+ /* Packet mode not supported */
+ cap->srtcm_rfc2697_packet_mode_supported = 0;
+ cap->trtcm_rfc2698_packet_mode_supported = 0;
+ cap->trtcm_rfc4115_packet_mode_supported = 0;
+
+ return 0;
+}
+
+static int
+eth_mtr_meter_profile_add_inline(struct rte_eth_dev *dev,
+ uint32_t meter_profile_id,
+ struct rte_mtr_meter_profile *profile,
+ struct rte_mtr_error *error __rte_unused)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (meter_profile_id >= flow_mtr_meter_policy_n_max())
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL, "Profile id out of range\n");
+
+ if (profile->packet_mode != 0) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE, NULL,
+ "Profile packet mode not supported\n");
+ }
+
+ if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE,
+ NULL, "RFC 2697 not supported\n");
+ }
+
+ if (profile->alg == RTE_MTR_TRTCM_RFC4115) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE,
+ NULL, "RFC 4115 not supported\n");
+ }
+
+ if (profile->trtcm_rfc2698.cir != profile->trtcm_rfc2698.pir ||
+ profile->trtcm_rfc2698.cbs != profile->trtcm_rfc2698.pbs) {
+ return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
+ "Profile committed and peak rates must be equal\n");
+ }
+
+ int res = flow_mtr_set_profile(dev_priv->flw_dev, meter_profile_id,
+ profile->trtcm_rfc2698.cir,
+ profile->trtcm_rfc2698.cbs, 0, 0);
+
+ if (res) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE,
+ NULL,
+ "Profile could not be added.\n");
+ }
+
+ return 0;
+}
+
+static int
+eth_mtr_meter_profile_delete_inline(struct rte_eth_dev *dev __rte_unused,
+ uint32_t meter_profile_id __rte_unused,
+ struct rte_mtr_error *error __rte_unused)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (meter_profile_id >= flow_mtr_meter_policy_n_max())
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL, "Profile id out of range\n");
+
+ flow_mtr_set_profile(dev_priv->flw_dev, meter_profile_id, 0, 0, 0, 0);
+
+ return 0;
+}
+
+static int
+eth_mtr_meter_policy_add_inline(struct rte_eth_dev *dev, uint32_t policy_id,
+ struct rte_mtr_meter_policy_params *policy,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (policy_id >= flow_mtr_meter_policy_n_max())
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+ NULL, "Policy id out of range\n");
+
+ const struct rte_flow_action *actions =
+ policy->actions[RTE_COLOR_GREEN];
+ int green_action_supported =
+ (actions[0].type == RTE_FLOW_ACTION_TYPE_END) ||
+ (actions[0].type == RTE_FLOW_ACTION_TYPE_VOID &&
+ actions[1].type == RTE_FLOW_ACTION_TYPE_END) ||
+ (actions[0].type == RTE_FLOW_ACTION_TYPE_PASSTHRU &&
+ actions[1].type == RTE_FLOW_ACTION_TYPE_END);
+
+ actions = policy->actions[RTE_COLOR_YELLOW];
+ int yellow_action_supported =
+ actions[0].type == RTE_FLOW_ACTION_TYPE_DROP &&
+ actions[1].type == RTE_FLOW_ACTION_TYPE_END;
+
+ actions = policy->actions[RTE_COLOR_RED];
+ int red_action_supported = actions[0].type ==
+ RTE_FLOW_ACTION_TYPE_DROP &&
+ actions[1].type == RTE_FLOW_ACTION_TYPE_END;
+
+ if (green_action_supported == 0 || yellow_action_supported == 0 ||
+ red_action_supported == 0) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
+ "Unsupported meter policy actions\n");
+ }
+
+ if (flow_mtr_set_policy(dev_priv->flw_dev, policy_id, 1)) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
+ "Policy could not be added\n");
+ }
+
+ return 0;
+}
+
+static int
+eth_mtr_meter_policy_delete_inline(struct rte_eth_dev *dev __rte_unused,
+ uint32_t policy_id __rte_unused,
+ struct rte_mtr_error *error __rte_unused)
+{
+ if (policy_id >= flow_mtr_meter_policy_n_max())
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+ NULL, "Policy id out of range\n");
+
+ return 0;
+}
+
+static int eth_mtr_create_inline(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_params *params, int shared,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (params->use_prev_mtr_color != 0 || params->dscp_table != NULL) {
+ return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "Only color blind mode is supported\n");
+ }
+
+ uint64_t allowed_stats_mask = RTE_MTR_STATS_N_PKTS_GREEN |
+ RTE_MTR_STATS_N_BYTES_GREEN;
+ if ((params->stats_mask & ~allowed_stats_mask) != 0) {
+ return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "Requested color stats not supported\n");
+ }
+
+ if (params->meter_enable == 0) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "Disabled meters not supported\n");
+ }
+
+ if (shared == 0) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "Only shared mtrs are supported\n");
+ }
+
+ if (params->meter_profile_id >= flow_mtr_meter_policy_n_max())
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+ NULL, "Profile id out of range\n");
+
+ if (params->meter_policy_id >= flow_mtr_meter_policy_n_max())
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+ NULL, "Policy id out of range\n");
+
+ if (mtr_id >= flow_mtr_meters_supported()) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "MTR id is out of range\n");
+ }
+
+ int res = flow_mtr_create_meter(dev_priv->flw_dev, mtr_id,
+ params->meter_profile_id,
+ params->meter_policy_id,
+ params->stats_mask);
+
+ if (res) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to offload to hardware\n");
+ }
+
+ return 0;
+}
+
+static int eth_mtr_destroy_inline(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_error *error __rte_unused)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (mtr_id >= flow_mtr_meters_supported()) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "MTR id is out of range\n");
+ }
+
+ if (flow_mtr_destroy_meter(dev_priv->flw_dev, mtr_id)) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to offload to hardware\n");
+ }
+
+ return 0;
+}
+
+static int eth_mtr_stats_adjust_inline(struct rte_eth_dev *dev, uint32_t mtr_id,
+ uint64_t adjust_value,
+ struct rte_mtr_error *error)
+{
+ const uint64_t adjust_bit = 1ULL << 63;
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (mtr_id >= flow_mtr_meters_supported()) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "MTR id is out of range\n");
+ }
+
+ if ((adjust_value & adjust_bit) == 0) {
+ return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "To adjust a MTR bucket value, bit 63 of \"stats_mask\" must be 1\n");
+ }
+
+ adjust_value &= adjust_bit - 1;
+
+ if (adjust_value > (uint64_t)UINT32_MAX) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "Adjust value is out of range\n");
+ }
+
+ if (flm_mtr_adjust_stats(dev_priv->flw_dev, mtr_id,
+ (uint32_t)adjust_value)) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to adjust offloaded MTR\n");
+ }
+
+ return 0;
+}
+
+static int eth_mtr_stats_read_inline(struct rte_eth_dev *dev, uint32_t mtr_id,
+ struct rte_mtr_stats *stats,
+ uint64_t *stats_mask, int clear,
+ struct rte_mtr_error *error)
+{
+ struct pmd_internals *dev_priv = dev->data->dev_private;
+
+ if (mtr_id >= flow_mtr_meters_supported()) {
+ return -rte_mtr_error_set(error, EINVAL,
+ RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
+ "MTR id is out of range\n");
+ }
+
+ memset(stats, 0x0, sizeof(struct rte_mtr_stats));
+ flm_mtr_read_stats(dev_priv->flw_dev, mtr_id, stats_mask,
+ &stats->n_pkts[RTE_COLOR_GREEN],
+ &stats->n_bytes[RTE_COLOR_GREEN], clear);
+
+ return 0;
+}
+
+/*
+ *******************************************************************************
+ * Ops setup
+ *******************************************************************************
+ */
+
+static const struct rte_mtr_ops mtr_ops_vswitch = {
+ .meter_profile_add = eth_meter_profile_add,
+ .meter_profile_delete = eth_meter_profile_delete,
+ .create = eth_mtr_create,
+ .destroy = eth_mtr_destroy,
+ .meter_enable = eth_meter_enable,
+ .meter_disable = eth_meter_disable,
+};
+
+static const struct rte_mtr_ops mtr_ops_inline = {
+ .capabilities_get = eth_mtr_capabilities_get_inline,
+ .meter_profile_add = eth_mtr_meter_profile_add_inline,
+ .meter_profile_delete = eth_mtr_meter_profile_delete_inline,
+ .create = eth_mtr_create_inline,
+ .destroy = eth_mtr_destroy_inline,
+ .meter_policy_add = eth_mtr_meter_policy_add_inline,
+ .meter_policy_delete = eth_mtr_meter_policy_delete_inline,
+ .stats_update = eth_mtr_stats_adjust_inline,
+ .stats_read = eth_mtr_stats_read_inline,
+};
+
+int eth_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
+{
+ struct pmd_internals *internals =
+ (struct pmd_internals *)dev->data->dev_private;
+ ntdrv_4ga_t *p_nt_drv = &internals->p_drv->ntdrv;
+ enum fpga_info_profile profile = p_nt_drv->adapter_info.fpga_info.profile;
+
+ switch (profile) {
+ case FPGA_INFO_PROFILE_VSWITCH:
+ *(const struct rte_mtr_ops **)ops = &mtr_ops_vswitch;
+ break;
+ case FPGA_INFO_PROFILE_INLINE:
+ *(const struct rte_mtr_ops **)ops = &mtr_ops_inline;
+ break;
+ case FPGA_INFO_PROFILE_UNKNOWN:
+ /* fallthrough */
+ case FPGA_INFO_PROFILE_CAPTURE:
+ /* fallthrough */
+ default:
+ NT_LOG(ERR, NTHW,
+ "" PCIIDENT_PRINT_STR
+ ": fpga profile not supported [%s:%u]\n",
+ PCIIDENT_TO_DOMAIN(p_nt_drv->pciident),
+ PCIIDENT_TO_BUSNR(p_nt_drv->pciident),
+ PCIIDENT_TO_DEVNR(p_nt_drv->pciident),
+ PCIIDENT_TO_FUNCNR(p_nt_drv->pciident),
+ __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/ntnic_meter.h b/drivers/net/ntnic/ntnic_meter.h
new file mode 100644
index 0000000000..9484c9ee20
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_meter.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTNIC_METER_H__
+#define __NTNIC_METER_H__
+
+int eth_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *ops);
+
+#endif /* __NTNIC_METER_H__ */
diff --git a/drivers/net/ntnic/ntnic_vdpa.c b/drivers/net/ntnic/ntnic_vdpa.c
new file mode 100644
index 0000000000..6372514527
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vdpa.c
@@ -0,0 +1,365 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_vhost.h>
+#include <linux/virtio_net.h>
+#include <rte_vdpa.h>
+#include <rte_pci.h>
+#include <rte_string_fns.h>
+#include <rte_bus_pci.h>
+#include <vhost.h>
+#include "ntnic_vf_vdpa.h"
+#include "ntnic_vdpa.h"
+#include "ntnic_ethdev.h"
+#include "nt_util.h"
+#include "ntlog.h"
+#include "ntnic_vfio.h"
+
+#define MAX_PATH_LEN 128
+#define MAX_VDPA_PORTS 128UL
+
+struct vdpa_port {
+ char ifname[MAX_PATH_LEN];
+ struct rte_vdpa_device *vdev;
+ int vid;
+ uint32_t index;
+ uint32_t host_id;
+ uint32_t rep_port;
+ int rxqs;
+ int txqs;
+ uint64_t flags;
+ struct rte_pci_addr addr;
+};
+
+static struct vdpa_port vport[MAX_VDPA_PORTS];
+static uint32_t nb_vpda_devcnt;
+
+static int nthw_vdpa_start(struct vdpa_port *vport);
+
+int nthw_vdpa_get_queue_id_info(struct rte_vdpa_device *vdpa_dev, int rx,
+ int queue_id, uint32_t *hw_index,
+ uint32_t *host_id, uint32_t *rep_port)
+{
+ uint32_t i;
+
+ for (i = 0; i < nb_vpda_devcnt; i++) {
+ if (vport[i].vdev == vdpa_dev) {
+ if (rx) {
+ if (queue_id >= vport[i].rxqs) {
+ NT_LOG(ERR, VDPA,
+ "Failed: %s: Queue ID not configured. vDPA dev %p, rx queue_id %i, rxqs %i\n",
+ __func__, vdpa_dev, queue_id,
+ vport[i].rxqs);
+ return -1;
+ }
+ *hw_index = vport[i].index + queue_id;
+ } else {
+ if (queue_id >= vport[i].txqs) {
+ NT_LOG(ERR, VDPA,
+ "Failed: %s: Queue ID not configured. vDPA dev %p, tx queue_id %i, rxqs %i\n",
+ __func__, vdpa_dev, queue_id,
+ vport[i].rxqs);
+ return -1;
+ }
+ *hw_index = vport[i].index + queue_id;
+ }
+
+ *host_id = vport[i].host_id;
+ *rep_port = vport[i].rep_port;
+ return 0;
+ }
+ }
+
+ NT_LOG(ERR, VDPA,
+ "Failed: %s: Ask on vDPA dev %p, queue_id %i, nb_vpda_devcnt %i\n",
+ __func__, vdpa_dev, queue_id, nb_vpda_devcnt);
+ return -1;
+}
+
+int nthw_vdpa_init(const struct rte_pci_device *vdev,
+ const char *backing_devname _unused, const char *socket_path,
+ uint32_t index, int rxqs, int txqs, uint32_t rep_port,
+ int *vhid)
+{
+ int ret;
+ uint32_t host_id = nt_vfio_vf_num(vdev);
+
+ struct rte_vdpa_device *vdpa_dev =
+ rte_vdpa_find_device_by_name(vdev->name);
+ if (!vdpa_dev) {
+ NT_LOG(ERR, VDPA, "vDPA device with name %s - not found\n",
+ vdev->name);
+ return -1;
+ }
+
+ vport[nb_vpda_devcnt].vdev = vdpa_dev;
+ vport[nb_vpda_devcnt].host_id = host_id; /* VF # */
+ vport[nb_vpda_devcnt].index = index; /* HW ring index */
+ vport[nb_vpda_devcnt].rep_port = rep_port; /* in port override on Tx */
+ vport[nb_vpda_devcnt].rxqs = rxqs;
+ vport[nb_vpda_devcnt].txqs = txqs;
+ vport[nb_vpda_devcnt].addr = vdev->addr;
+
+ vport[nb_vpda_devcnt].flags = RTE_VHOST_USER_CLIENT;
+ strlcpy(vport[nb_vpda_devcnt].ifname, socket_path, MAX_PATH_LEN);
+
+ NT_LOG(INF, VDPA,
+ "vDPA%u: device %s (host_id %u), backing device %s, index %u, queues %i, rep port %u, ifname %s\n",
+ nb_vpda_devcnt, vdev->name, host_id, backing_devname, index,
+ rxqs, rep_port, vport[nb_vpda_devcnt].ifname);
+
+ ret = nthw_vdpa_start(&vport[nb_vpda_devcnt]);
+
+ *vhid = nb_vpda_devcnt;
+ nb_vpda_devcnt++;
+ return ret;
+}
+
+void nthw_vdpa_close(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < MAX_VDPA_PORTS; i++) {
+ if (vport[i].ifname[0] != '\0') {
+ int ret;
+ char *socket_path = vport[i].ifname;
+
+ ret = rte_vhost_driver_detach_vdpa_device(socket_path);
+ if (ret != 0) {
+ NT_LOG(ERR, VDPA,
+ "detach vdpa device failed: %s\n",
+ socket_path);
+ }
+
+ ret = rte_vhost_driver_unregister(socket_path);
+ if (ret != 0) {
+ NT_LOG(ERR, VDPA,
+ "Fail to unregister vhost driver for %s.\n",
+ socket_path);
+ }
+
+ vport[i].ifname[0] = '\0';
+ return;
+ }
+ }
+}
+
+#ifdef DUMP_VIRTIO_FEATURES
+#define VIRTIO_F_NOTIFICATION_DATA 38
+#define NUM_FEATURES 40
+struct {
+ uint64_t id;
+ const char *name;
+} virt_features[NUM_FEATURES] = {
+ { VIRTIO_NET_F_CSUM, "VIRTIO_NET_F_CSUM" },
+ { VIRTIO_NET_F_GUEST_CSUM, "VIRTIO_NET_F_GUEST_CSUM" },
+ { VIRTIO_NET_F_CTRL_GUEST_OFFLOADS,
+ " VIRTIO_NET_F_CTRL_GUEST_OFFLOADS"
+ },
+ { VIRTIO_NET_F_MTU, " VIRTIO_NET_F_MTU" },
+ { VIRTIO_NET_F_MAC, " VIRTIO_NET_F_MAC" },
+ { VIRTIO_NET_F_GSO, " VIRTIO_NET_F_GSO" },
+ { VIRTIO_NET_F_GUEST_TSO4, " VIRTIO_NET_F_GUEST_TSO4" },
+ { VIRTIO_NET_F_GUEST_TSO6, " VIRTIO_NET_F_GUEST_TSO6" },
+ { VIRTIO_NET_F_GUEST_ECN, " VIRTIO_NET_F_GUEST_ECN" },
+ { VIRTIO_NET_F_GUEST_UFO, " VIRTIO_NET_F_GUEST_UFO" },
+ { VIRTIO_NET_F_HOST_TSO4, " VIRTIO_NET_F_HOST_TSO4" },
+ { VIRTIO_NET_F_HOST_TSO6, " VIRTIO_NET_F_HOST_TSO6" },
+ { VIRTIO_NET_F_HOST_ECN, " VIRTIO_NET_F_HOST_ECN" },
+ { VIRTIO_NET_F_HOST_UFO, " VIRTIO_NET_F_HOST_UFO" },
+ { VIRTIO_NET_F_MRG_RXBUF, " VIRTIO_NET_F_MRG_RXBUF" },
+ { VIRTIO_NET_F_STATUS, " VIRTIO_NET_F_STATUS" },
+ { VIRTIO_NET_F_CTRL_VQ, " VIRTIO_NET_F_CTRL_VQ" },
+ { VIRTIO_NET_F_CTRL_RX, " VIRTIO_NET_F_CTRL_RX" },
+ { VIRTIO_NET_F_CTRL_VLAN, " VIRTIO_NET_F_CTRL_VLAN" },
+ { VIRTIO_NET_F_CTRL_RX_EXTRA, " VIRTIO_NET_F_CTRL_RX_EXTRA" },
+ { VIRTIO_NET_F_GUEST_ANNOUNCE, " VIRTIO_NET_F_GUEST_ANNOUNCE" },
+ { VIRTIO_NET_F_MQ, " VIRTIO_NET_F_MQ" },
+ { VIRTIO_NET_F_CTRL_MAC_ADDR, " VIRTIO_NET_F_CTRL_MAC_ADDR" },
+ { VIRTIO_NET_F_HASH_REPORT, " VIRTIO_NET_F_HASH_REPORT" },
+ { VIRTIO_NET_F_RSS, " VIRTIO_NET_F_RSS" },
+ { VIRTIO_NET_F_RSC_EXT, " VIRTIO_NET_F_RSC_EXT" },
+ { VIRTIO_NET_F_STANDBY, " VIRTIO_NET_F_STANDBY" },
+ { VIRTIO_NET_F_SPEED_DUPLEX, " VIRTIO_NET_F_SPEED_DUPLEX" },
+ { VIRTIO_F_NOTIFY_ON_EMPTY, " VIRTIO_F_NOTIFY_ON_EMPTY" },
+ { VIRTIO_F_ANY_LAYOUT, " VIRTIO_F_ANY_LAYOUT" },
+ { VIRTIO_RING_F_INDIRECT_DESC, " VIRTIO_RING_F_INDIRECT_DESC" },
+ { VIRTIO_F_VERSION_1, " VIRTIO_F_VERSION_1" },
+ { VIRTIO_F_IOMMU_PLATFORM, " VIRTIO_F_IOMMU_PLATFORM" },
+ { VIRTIO_F_RING_PACKED, " VIRTIO_F_RING_PACKED" },
+ { VIRTIO_TRANSPORT_F_START, " VIRTIO_TRANSPORT_F_START" },
+ { VIRTIO_TRANSPORT_F_END, " VIRTIO_TRANSPORT_F_END" },
+ { VIRTIO_F_IN_ORDER, " VIRTIO_F_IN_ORDER" },
+ { VIRTIO_F_ORDER_PLATFORM, " VIRTIO_F_ORDER_PLATFORM" },
+ { VIRTIO_F_NOTIFICATION_DATA, " VIRTIO_F_NOTIFICATION_DATA" },
+};
+
+static void dump_virtio_features(uint64_t features)
+{
+ int i;
+
+ for (i = 0; i < NUM_FEATURES; i++) {
+ if ((1ULL << virt_features[i].id) ==
+ (features & (1ULL << virt_features[i].id)))
+ printf("Virtio feature: %s\n", virt_features[i].name);
+ }
+}
+#endif
+
+static int nthw_vdpa_new_device(int vid)
+{
+ char ifname[MAX_PATH_LEN];
+ uint64_t negotiated_features = 0;
+ unsigned int vhid = -1;
+
+ rte_vhost_get_ifname(vid, ifname, sizeof(ifname));
+
+ for (vhid = 0; vhid < MAX_VDPA_PORTS; vhid++) {
+ if (strncmp(ifname, vport[vhid].ifname, MAX_PATH_LEN) == 0) {
+ vport[vhid].vid = vid;
+ break;
+ }
+ }
+
+ if (vhid >= MAX_VDPA_PORTS)
+ return -1;
+
+ int max_loops = 2000;
+ struct pmd_internals *intern;
+
+ while ((intern = vp_vhid_instance_ready(vhid)) == NULL) {
+ usleep(1000);
+ if (--max_loops == 0) {
+ NT_LOG(INF, VDPA,
+ "FAILED CREATING (vhost could not get ready) New port %s, vDPA dev: %s\n",
+ ifname, vport[vhid].vdev->device->name);
+ return -1;
+ }
+ }
+
+ /* set link up on virtual port */
+ intern->vport_comm = VIRT_PORT_NEGOTIATED_NONE;
+
+ /* Store ifname (vhost_path) */
+ strlcpy(intern->vhost_path, ifname, MAX_PATH_LEN);
+
+ NT_LOG(INF, VDPA, "New port %s, vDPA dev: %s\n", ifname,
+ vport[vhid].vdev->device->name);
+ rte_vhost_get_negotiated_features(vid, &negotiated_features);
+ NT_LOG(INF, VDPA, "Virtio Negotiated features %016lx\n",
+ negotiated_features);
+
+#ifdef DUMP_VIRTIO_FEATURES
+ dump_virtio_features(negotiated_features);
+#endif
+
+ if ((((negotiated_features & (1ULL << VIRTIO_F_IN_ORDER))) ||
+ ((negotiated_features & (1ULL << VIRTIO_F_RING_PACKED))))) {
+ /* IN_ORDER negotiated - we can run HW-virtio directly (vDPA) */
+ NT_LOG(INF, VDPA, "Running virtio in vDPA mode : %s %s\n",
+ (negotiated_features & (1ULL << VIRTIO_F_RING_PACKED)) ?
+ "\"Packed-Ring\"" :
+ "\"Split-Ring\"",
+ (negotiated_features & (1ULL << VIRTIO_F_IN_ORDER)) ?
+ "\"In-Order\"" :
+ "\"No In-Order Requested\"");
+
+ intern->vport_comm =
+ (negotiated_features & (1ULL << VIRTIO_F_RING_PACKED)) ?
+ VIRT_PORT_NEGOTIATED_PACKED :
+ VIRT_PORT_NEGOTIATED_SPLIT;
+ } else {
+ NT_LOG(ERR, VDPA, "Incompatible virtio negotiated features.\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void nthw_vdpa_destroy_device(int vid)
+{
+ char ifname[MAX_PATH_LEN];
+ uint32_t i;
+ unsigned int vhid;
+
+ rte_vhost_get_ifname(vid, ifname, sizeof(ifname));
+ for (i = 0; i < MAX_VDPA_PORTS; i++) {
+ if (strcmp(ifname, vport[i].ifname) == 0) {
+ NT_LOG(INF, VDPA, "\ndestroy port %s, vDPA dev: %s\n",
+ ifname, vport[i].vdev->device->name);
+ break;
+ }
+ }
+
+ struct pmd_internals *intern;
+
+ /* set link down on virtual port */
+ for (vhid = 0; vhid < MAX_VDPA_PORTS; vhid++) {
+ if (strncmp(ifname, vport[vhid].ifname, MAX_PATH_LEN) == 0) {
+ intern = vp_vhid_instance_ready(vhid);
+ if (intern)
+ intern->vport_comm = VIRT_PORT_NEGOTIATED_NONE;
+ break;
+ }
+ }
+}
+
+static const struct rte_vhost_device_ops vdpa_devops = {
+ .new_device = nthw_vdpa_new_device,
+ .destroy_device = nthw_vdpa_destroy_device,
+};
+
+static int nthw_vdpa_start(struct vdpa_port *vport)
+{
+ int ret;
+ char *socket_path = vport->ifname;
+
+ ret = rte_vhost_driver_register(socket_path, vport->flags);
+ if (ret != 0) {
+ NT_LOG(ERR, VDPA, "register driver failed: %s\n", socket_path);
+ return -1;
+ }
+
+ ret = rte_vhost_driver_callback_register(socket_path, &vdpa_devops);
+ if (ret != 0) {
+ NT_LOG(ERR, VDPA, "register driver ops failed: %s\n",
+ socket_path);
+ return -1;
+ }
+
+ ret = rte_vhost_driver_disable_features(socket_path, (1ULL << VIRTIO_NET_F_HOST_TSO4) |
+ (1ULL << VIRTIO_NET_F_HOST_TSO6) |
+ (1ULL << VIRTIO_NET_F_CSUM) |
+ (1ULL << VIRTIO_RING_F_EVENT_IDX) |
+ (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
+ (1ULL << VIRTIO_NET_F_HOST_UFO) |
+ (1ULL << VIRTIO_NET_F_HOST_ECN) |
+ (1ULL << VIRTIO_NET_F_GUEST_CSUM) |
+ (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
+ (1ULL << VIRTIO_NET_F_GUEST_TSO6) |
+ (1ULL << VIRTIO_NET_F_GUEST_UFO) |
+ (1ULL << VIRTIO_NET_F_GUEST_ECN) |
+ (1ULL << VIRTIO_NET_F_CTRL_VQ) |
+ (1ULL << VIRTIO_NET_F_CTRL_RX) |
+ (1ULL << VIRTIO_NET_F_GSO) |
+ (1ULL << VIRTIO_NET_F_MTU));
+
+ if (ret != 0) {
+ NT_LOG(INF, VDPA,
+ "rte_vhost_driver_disable_features failed for vhost user client port: %s\n",
+ socket_path);
+ return -1;
+ }
+
+ if (rte_vhost_driver_start(socket_path) < 0) {
+ NT_LOG(ERR, VDPA, "start vhost driver failed: %s\n",
+ socket_path);
+ return -1;
+ }
+ return 0;
+}
diff --git a/drivers/net/ntnic/ntnic_vdpa.h b/drivers/net/ntnic/ntnic_vdpa.h
new file mode 100644
index 0000000000..7acc2c8e4b
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vdpa.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTNIC_VDPA_H_
+#define _NTNIC_VDPA_H_
+
+#include <stdint.h>
+
+int nthw_vdpa_get_queue_id_info(struct rte_vdpa_device *vdpa_dev, int rx,
+ int queue_id, uint32_t *hw_index,
+ uint32_t *host_id, uint32_t *rep_port);
+
+int nthw_vdpa_init(const struct rte_pci_device *vdev,
+ const char *backing_devname, const char *socket_path,
+ uint32_t index, int rxqs, int txqs, uint32_t rep_port,
+ int *vhid);
+
+void nthw_vdpa_close(void);
+
+#endif /* _NTNIC_VDPA_H_ */
diff --git a/drivers/net/ntnic/ntnic_vf.c b/drivers/net/ntnic/ntnic_vf.c
new file mode 100644
index 0000000000..0724b040c3
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vf.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_interrupts.h>
+#include <eal_interrupts.h>
+#include <rte_bus_pci.h>
+#include <rte_vfio.h>
+#include <rte_spinlock.h>
+#include <rte_log.h>
+
+#include "ntnic_ethdev.h"
+#include "ntnic_vf.h"
+#include "ntnic_vf_vdpa.h"
+#include "nt_util.h"
+#include "ntlog.h"
+
+#define NT_HW_NAPATECH_PCI_VENDOR_ID (0x18F4)
+#define NT_HW_NAPATECH_PCI_DEVICE_ID_NT200A02_VF (0x051A)
+#define NT_HW_NAPATECH_PCI_DEVICE_ID_NT50B01_VF (0x051B)
+
+static const char *get_adapter_name(struct rte_pci_device *pci_dev)
+{
+ switch (pci_dev->id.vendor_id) {
+ case NT_HW_NAPATECH_PCI_VENDOR_ID:
+ switch (pci_dev->id.device_id) {
+ case NT_HW_NAPATECH_PCI_DEVICE_ID_NT200A02_VF:
+ return "NT200A02";
+ case NT_HW_NAPATECH_PCI_DEVICE_ID_NT50B01_VF:
+ return "NT50B01";
+ }
+ break;
+ }
+
+ return "Unknown";
+}
+
+int nt_vf_pci_probe(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
+{
+ const char *adapter_name _unused = get_adapter_name(pci_dev);
+
+ NT_LOG(INF, VDPA, "Probe %s VF : %02x:%02x:%i\n", adapter_name,
+ pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function);
+
+ /* Create vDPA device for the virtual function interface.*/
+
+ if (ntvf_vdpa_pci_probe(pci_drv, pci_dev) != 0)
+ return -1;
+
+ return nthw_create_vf_interface_dpdk(pci_dev);
+}
+
+int nt_vf_pci_remove(struct rte_pci_device *pci_dev)
+{
+ if (ntvf_vdpa_pci_remove(pci_dev) != 0)
+ return -1;
+
+ return nthw_remove_vf_interface_dpdk(pci_dev);
+}
+
+static const struct rte_pci_id pci_id_nt_vf_map[] = {
+ { RTE_PCI_DEVICE(NT_HW_NAPATECH_PCI_VENDOR_ID,
+ NT_HW_NAPATECH_PCI_DEVICE_ID_NT200A02_VF)
+ },
+ { RTE_PCI_DEVICE(NT_HW_NAPATECH_PCI_VENDOR_ID,
+ NT_HW_NAPATECH_PCI_DEVICE_ID_NT50B01_VF)
+ },
+ { .vendor_id = 0, /* sentinel */ },
+};
+
+static struct rte_pci_driver rte_nt_vf = {
+ .id_table = pci_id_nt_vf_map,
+ .drv_flags = 0,
+ .probe = nt_vf_pci_probe,
+ .remove = nt_vf_pci_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_nt_vf, rte_nt_vf);
+RTE_PMD_REGISTER_PCI_TABLE(net_nt_vf, pci_id_nt_vf_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_nt_vf, "* vfio-pci");
diff --git a/drivers/net/ntnic/ntnic_vf.h b/drivers/net/ntnic/ntnic_vf.h
new file mode 100644
index 0000000000..84be3bd71f
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vf.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTNIC_VF_H_
+#define _NTNIC_VF_H_
+
+#include "rte_bus_pci.h"
+
+int nt_vf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev);
+int nt_vf_pci_remove(struct rte_pci_device *pci_dev __rte_unused);
+
+int get_container_fd(int vf_num);
+int close_vf_mem_mapping(int vf_num);
+
+#endif /* _NTNIC_VF_H_ */
diff --git a/drivers/net/ntnic/ntnic_vf_vdpa.c b/drivers/net/ntnic/ntnic_vf_vdpa.c
new file mode 100644
index 0000000000..c520a43c44
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vf_vdpa.c
@@ -0,0 +1,1246 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdatomic.h>
+
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/epoll.h>
+
+#include <linux/virtio_net.h>
+#include <linux/pci_regs.h>
+
+#include <rte_interrupts.h>
+#include <eal_interrupts.h>
+
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_bus_pci.h>
+#include <rte_vhost.h>
+#include <rte_vdpa.h>
+#include <rte_vfio.h>
+#include <rte_spinlock.h>
+#include <rte_log.h>
+
+#include <vhost.h>
+
+#include "ntdrv_4ga.h"
+#include "ntnic_ethdev.h"
+#include "ntnic_vdpa.h"
+#include "ntnic_vf_vdpa.h"
+#include "ntnic_vf.h"
+#include "ntnic_vfio.h"
+#include "ntnic_dbsconfig.h"
+#include "ntlog.h"
+
+#define NTVF_VDPA_MAX_QUEUES (MAX_QUEUES)
+#define NTVF_VDPA_MAX_INTR_VECTORS 8
+
+#if RTE_VERSION_NUM(23, 3, 0, 99) > RTE_VERSION
+#define NTVF_VDPA_SUPPORTED_PROTOCOL_FEATURES \
+ ((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_MQ))
+#else
+#define NTVF_VDPA_SUPPORTED_PROTOCOL_FEATURES \
+ ((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_REQ) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_BACKEND_SEND_FD) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_MQ))
+#endif
+
+#define NTVF_VIRTIO_NET_SUPPORTED_FEATURES \
+ ((1ULL << VIRTIO_F_ANY_LAYOUT) | (1ULL << VIRTIO_F_VERSION_1) | \
+ (1ULL << VHOST_F_LOG_ALL) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+ (1ULL << VIRTIO_F_IOMMU_PLATFORM) | (1ULL << VIRTIO_F_IN_ORDER) | \
+ (1ULL << VIRTIO_F_RING_PACKED) | \
+ (1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
+ (1ULL << VHOST_USER_F_PROTOCOL_FEATURES))
+
+static int ntvf_vdpa_set_vring_state(int vid, int vring, int state);
+
+struct vring_info {
+ uint64_t desc;
+ uint64_t avail;
+ uint64_t used;
+ uint16_t size;
+
+ uint16_t last_avail_idx;
+ uint16_t last_used_idx;
+
+ int vq_type;
+ struct nthw_virt_queue *p_vq;
+
+ int enable;
+};
+
+struct ntvf_vdpa_hw {
+ uint64_t negotiated_features;
+
+ uint8_t nr_vring;
+
+ struct vring_info vring[NTVF_VDPA_MAX_QUEUES * 2];
+};
+
+struct ntvf_vdpa_internal {
+ struct rte_pci_device *pdev;
+ struct rte_vdpa_device *vdev;
+
+ int vfio_container_fd;
+ int vfio_group_fd;
+ int vfio_dev_fd;
+
+ int vid;
+
+ uint32_t outport;
+
+ uint16_t max_queues;
+
+ uint64_t features;
+
+ struct ntvf_vdpa_hw hw;
+
+ volatile atomic_int_fast32_t started;
+ volatile atomic_int_fast32_t dev_attached;
+ volatile atomic_int_fast32_t running;
+
+ rte_spinlock_t lock;
+
+ volatile atomic_int_fast32_t dma_mapped;
+ volatile atomic_int_fast32_t intr_enabled;
+};
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+#define NTVF_USED_RING_LEN(size) \
+ ((size) * sizeof(struct vring_used_elem) + sizeof(uint16_t) * 3)
+
+#define NTVF_MEDIATED_VRING 0x210000000000
+
+struct internal_list {
+ TAILQ_ENTRY(internal_list) next;
+ struct ntvf_vdpa_internal *internal;
+};
+
+TAILQ_HEAD(internal_list_head, internal_list);
+
+static struct internal_list_head internal_list =
+ TAILQ_HEAD_INITIALIZER(internal_list);
+
+static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
+
+int ntvf_vdpa_logtype;
+
+static struct internal_list *
+find_internal_resource_by_vdev(struct rte_vdpa_device *vdev)
+{
+ int found = 0;
+ struct internal_list *list;
+
+ NT_LOG(DBG, VDPA, "%s: vDPA dev=%p\n", __func__, vdev);
+
+ pthread_mutex_lock(&internal_list_lock);
+
+ TAILQ_FOREACH(list, &internal_list, next)
+ {
+ if (vdev == list->internal->vdev) {
+ found = 1;
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&internal_list_lock);
+
+ if (!found)
+ return NULL;
+
+ return list;
+}
+
+static struct internal_list *
+ntvf_vdpa_find_internal_resource_by_dev(const struct rte_pci_device *pdev)
+{
+ int found = 0;
+ struct internal_list *list;
+
+ NT_LOG(DBG, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, __LINE__);
+
+ pthread_mutex_lock(&internal_list_lock);
+
+ TAILQ_FOREACH(list, &internal_list, next)
+ {
+ if (pdev == list->internal->pdev) {
+ found = 1;
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&internal_list_lock);
+
+ if (!found)
+ return NULL;
+
+ return list;
+}
+
+static int ntvf_vdpa_vfio_setup(struct ntvf_vdpa_internal *internal)
+{
+ int vfio;
+
+ LOG_FUNC_ENTER();
+
+ internal->vfio_dev_fd = -1;
+ internal->vfio_group_fd = -1;
+ internal->vfio_container_fd = -1;
+
+ vfio = nt_vfio_setup(internal->pdev);
+ if (vfio == -1) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__, __LINE__);
+ return -1;
+ }
+ internal->vfio_container_fd = nt_vfio_get_container_fd(vfio);
+ internal->vfio_group_fd = nt_vfio_get_group_fd(vfio);
+ internal->vfio_dev_fd = nt_vfio_get_dev_fd(vfio);
+ return 0;
+}
+
+static int ntvf_vdpa_dma_map(struct ntvf_vdpa_internal *internal, int do_map)
+{
+ uint32_t i;
+ int ret = 0;
+ struct rte_vhost_memory *mem = NULL;
+ int vf_num = nt_vfio_vf_num(internal->pdev);
+
+ LOG_FUNC_ENTER();
+
+ NT_LOG(DBG, VDPA, "%s: vid=%d vDPA dev=%p\n", __func__, internal->vid,
+ internal->vdev);
+
+ if ((do_map && atomic_load(&internal->dma_mapped)) ||
+ (!do_map && !atomic_load(&internal->dma_mapped))) {
+ ret = -1;
+ goto exit;
+ }
+ ret = rte_vhost_get_mem_table(internal->vid, &mem);
+ if (ret < 0) {
+ NT_LOG(ERR, VDPA, "failed to get VM memory layout.\n");
+ goto exit;
+ }
+
+ for (i = 0; i < mem->nregions; i++) {
+ struct rte_vhost_mem_region *reg = &mem->regions[i];
+
+ NT_LOG(INF, VDPA,
+ "%s, region %u: HVA 0x%" PRIX64 ", GPA 0xllx, size 0x%" PRIX64 ".\n",
+ (do_map ? "DMA map" : "DMA unmap"), i,
+ reg->host_user_addr, reg->guest_phys_addr, reg->size);
+
+ if (do_map) {
+ ret = nt_vfio_dma_map_vdpa(vf_num, reg->host_user_addr,
+ reg->guest_phys_addr,
+ reg->size);
+ if (ret < 0) {
+ NT_LOG(ERR, VDPA, "%s: DMA map failed.\n",
+ __func__);
+ goto exit;
+ }
+ atomic_store(&internal->dma_mapped, 1);
+ } else {
+ ret = nt_vfio_dma_unmap_vdpa(vf_num,
+ reg->host_user_addr,
+ reg->guest_phys_addr,
+ reg->size);
+ if (ret < 0) {
+ NT_LOG(ERR, VDPA, "%s: DMA unmap failed.\n", __func__);
+ goto exit;
+ }
+ atomic_store(&internal->dma_mapped, 0);
+ }
+ }
+
+exit:
+ if (mem)
+ free(mem);
+
+ LOG_FUNC_LEAVE();
+ return ret;
+}
+
+static uint64_t _hva_to_gpa(int vid, uint64_t hva)
+{
+ struct rte_vhost_memory *mem = NULL;
+ struct rte_vhost_mem_region *reg;
+ uint64_t gpa = 0;
+ uint32_t i;
+
+ if (rte_vhost_get_mem_table(vid, &mem) < 0)
+ goto exit;
+
+ for (i = 0; i < mem->nregions; i++) {
+ reg = &mem->regions[i];
+ if (hva >= reg->host_user_addr &&
+ hva < reg->host_user_addr + reg->size) {
+ gpa = hva - reg->host_user_addr + reg->guest_phys_addr;
+ break;
+ }
+ }
+
+exit:
+ if (mem)
+ free(mem);
+
+ return gpa;
+}
+
+static int ntvf_vdpa_create_vring(struct ntvf_vdpa_internal *internal,
+ int vring)
+{
+ struct ntvf_vdpa_hw *hw = &internal->hw;
+ struct rte_vhost_vring vq;
+ int vid = internal->vid;
+ uint64_t gpa;
+
+ rte_vhost_get_vhost_vring(vid, vring, &vq);
+
+ NT_LOG(INF, VDPA, "%s: idx=%d: vq.desc %p\n", __func__, vring, vq.desc);
+
+ gpa = _hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.desc);
+ if (gpa == 0) {
+ NT_LOG(ERR, VDPA,
+ "%s: idx=%d: failed to get GPA for descriptor ring: vq.desc %p\n",
+ __func__, vring, vq.desc);
+ return -1;
+ }
+ hw->vring[vring].desc = gpa;
+
+ gpa = _hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.avail);
+ if (gpa == 0) {
+ NT_LOG(ERR, VDPA,
+ "%s: idx=%d: failed to get GPA for available ring\n",
+ __func__, vring);
+ return -1;
+ }
+ hw->vring[vring].avail = gpa;
+
+ gpa = _hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.used);
+ if (gpa == 0) {
+ NT_LOG(ERR, VDPA, "%s: idx=%d: fail to get GPA for used ring\n",
+ __func__, vring);
+ return -1;
+ }
+
+ hw->vring[vring].used = gpa;
+ hw->vring[vring].size = vq.size;
+
+ rte_vhost_get_vring_base(vid, vring, &hw->vring[vring].last_avail_idx,
+ &hw->vring[vring].last_used_idx);
+
+ /* Prevent multiple creations */
+ {
+ const int index = vring;
+ uint32_t hw_index = 0;
+ uint32_t host_id = 0;
+ const uint32_t header = 0; /* 0=VirtIO hdr, 1=NT virtio hdr */
+ uint32_t vport = 0;
+ uint32_t port = internal->outport;
+ struct vring_info *p_vr_inf = &hw->vring[vring];
+ nthw_dbs_t *p_nthw_dbs = get_pdbs_from_pci(internal->pdev->addr);
+
+ int res = nthw_vdpa_get_queue_id_info(internal->vdev,
+ !(vring & 1), vring >> 1,
+ &hw_index, &host_id,
+ &vport);
+ if (res) {
+ NT_LOG(ERR, VDPA, "HW info received failed\n");
+ p_vr_inf->p_vq = NULL; /* Failed to create the vring */
+ return res;
+ }
+
+ if (!(vring & 1)) {
+ NT_LOG(DBG, VDPA,
+ "Rx: idx %u, host_id %u, vport %u, queue %i\n",
+ hw_index, host_id, vport, vring >> 1);
+ } else {
+ NT_LOG(DBG, VDPA,
+ "Tx: idx %u, host_id %u, vport %u, queue %i\n",
+ hw_index, host_id, vport, vring >> 1);
+ }
+ NT_LOG(DBG, VDPA,
+ "%s: idx=%d: avail=%p used=%p desc=%p: %X: %d %d %d\n",
+ __func__, index, (void *)p_vr_inf->avail,
+ (void *)p_vr_inf->used, (void *)p_vr_inf->desc,
+ p_vr_inf->size, host_id, port, header);
+
+ if ((hw->negotiated_features & (1ULL << VIRTIO_F_IN_ORDER)) ||
+ (hw->negotiated_features &
+ (1ULL << VIRTIO_F_RING_PACKED))) {
+ int res;
+
+ NT_LOG(DBG, VDPA,
+ "%s: idx=%d: feature VIRTIO_F_IN_ORDER is set: 0x%016lX\n",
+ __func__, index, hw->negotiated_features);
+
+ if (!(vring & 1)) {
+ struct nthw_virt_queue *rx_vq;
+
+ uint16_t start_idx =
+ hw->vring[vring].last_avail_idx;
+ uint16_t next_ptr =
+ (start_idx & 0x7fff) % vq.size;
+
+ /* disable doorbell not needed by FPGA */
+ ((struct pvirtq_event_suppress *)vq.used)
+ ->flags = RING_EVENT_FLAGS_DISABLE;
+ rte_wmb();
+ if (hw->negotiated_features &
+ (1ULL << VIRTIO_F_RING_PACKED)) {
+ NT_LOG(DBG, VDPA,
+ "Rx: hw_index %u, host_id %u, start_idx %u, header %u, vring %u, vport %u\n",
+ hw_index, host_id, start_idx,
+ header, vring, vport);
+ /* irq_vector 1,3,5... for Rx we support max 8 pr VF */
+ rx_vq = nthw_setup_rx_virt_queue(p_nthw_dbs,
+ hw_index, start_idx,
+ next_ptr,
+ (void *)p_vr_inf
+ ->avail, /* -> driver_event */
+ (void *)p_vr_inf
+ ->used, /* -> device_event */
+ (void *)p_vr_inf->desc,
+ p_vr_inf->size, host_id, header,
+ PACKED_RING,
+ vring + 1);
+
+ } else {
+ rx_vq = nthw_setup_rx_virt_queue(p_nthw_dbs,
+ hw_index, start_idx,
+ next_ptr,
+ (void *)p_vr_inf->avail,
+ (void *)p_vr_inf->used,
+ (void *)p_vr_inf->desc,
+ p_vr_inf->size, host_id, header,
+ SPLIT_RING,
+ -1); /* no interrupt enabled */
+ }
+
+ p_vr_inf->p_vq = rx_vq;
+ p_vr_inf->vq_type = 0;
+ res = (rx_vq ? 0 : -1);
+ if (res == 0)
+ register_release_virtqueue_info(rx_vq,
+ 1, 0);
+
+ NT_LOG(DBG, VDPA, "[%i] Rx Queue size %i\n",
+ hw_index, p_vr_inf->size);
+ } else if (vring & 1) {
+ /*
+ * transmit virt queue
+ */
+ struct nthw_virt_queue *tx_vq;
+ uint16_t start_idx =
+ hw->vring[vring].last_avail_idx;
+ uint16_t next_ptr;
+
+ if (hw->negotiated_features &
+ (1ULL << VIRTIO_F_RING_PACKED)) {
+ next_ptr =
+ (start_idx & 0x7fff) % vq.size;
+
+ /* disable doorbell needs from FPGA */
+ ((struct pvirtq_event_suppress *)vq.used)
+ ->flags =
+ RING_EVENT_FLAGS_DISABLE;
+ rte_wmb();
+ tx_vq = nthw_setup_tx_virt_queue(p_nthw_dbs,
+ hw_index, start_idx,
+ next_ptr,
+ (void *)p_vr_inf->avail, /* driver_event */
+ (void *)p_vr_inf->used, /* device_event */
+ (void *)p_vr_inf->desc,
+ p_vr_inf->size, host_id, port,
+ vport, header, PACKED_RING,
+ vring + 1, /* interrupt 2,4,6... */
+ !!(hw->negotiated_features &
+ (1ULL << VIRTIO_F_IN_ORDER)));
+
+ } else {
+ /*
+ * In Live Migration restart scenario:
+ * This only works if no jumbo packets has been send from VM
+ * on the LM source sideÑ This pointer points to the next
+ * free descr and may be pushed ahead by next flag and if
+ * so, this pointer calculation is incorrect
+ *
+ * NOTE: THEREFORE, THIS DOES NOT WORK WITH JUMBO PACKETS
+ * SUPPORT IN VM
+ */
+ next_ptr =
+ (start_idx & 0x7fff) % vq.size;
+ tx_vq = nthw_setup_tx_virt_queue(p_nthw_dbs,
+ hw_index, start_idx,
+ next_ptr,
+ (void *)p_vr_inf->avail,
+ (void *)p_vr_inf->used,
+ (void *)p_vr_inf->desc,
+ p_vr_inf->size, host_id, port,
+ vport, header, SPLIT_RING,
+ -1, /* no interrupt enabled */
+ IN_ORDER);
+ }
+
+ p_vr_inf->p_vq = tx_vq;
+ p_vr_inf->vq_type = 1;
+ res = (tx_vq ? 0 : -1);
+ if (res == 0)
+ register_release_virtqueue_info(tx_vq,
+ 0, 0);
+
+ NT_LOG(DBG, VDPA, "[%i] Tx Queue size %i\n",
+ hw_index, p_vr_inf->size);
+ } else {
+ NT_LOG(ERR, VDPA,
+ "%s: idx=%d: unexpected index: %d\n",
+ __func__, index, vring);
+ res = -1;
+ }
+ if (res != 0) {
+ NT_LOG(ERR, VDPA,
+ "%s: idx=%d: vring error: res=%d\n",
+ __func__, index, res);
+ }
+
+ } else {
+ NT_LOG(WRN, VDPA,
+ "%s: idx=%d: for SPLIT RING: feature VIRTIO_F_IN_ORDER is *NOT* set: 0x%016lX\n",
+ __func__, index, hw->negotiated_features);
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int ntvf_vdpa_start(struct ntvf_vdpa_internal *internal)
+{
+ enum fpga_info_profile fpga_profile =
+ get_fpga_profile_from_pci(internal->pdev->addr);
+ struct ntvf_vdpa_hw *hw = &internal->hw;
+ int vid;
+
+ LOG_FUNC_ENTER();
+
+ vid = internal->vid;
+ hw->nr_vring = rte_vhost_get_vring_num(vid);
+ rte_vhost_get_negotiated_features(vid, &hw->negotiated_features);
+
+ if (fpga_profile == FPGA_INFO_PROFILE_INLINE) {
+ NT_LOG(INF, VDPA, "%s: Number of VRINGs=%u\n", __func__,
+ hw->nr_vring);
+
+ for (int i = 0; i < hw->nr_vring && i < 2; i++) {
+ if (!hw->vring[i].enable) {
+ ntvf_vdpa_dma_map(internal, 1);
+ ntvf_vdpa_create_vring(internal, i);
+ if (hw->vring[i].desc && hw->vring[i].p_vq) {
+ if (hw->vring[i].vq_type == 0)
+ nthw_enable_rx_virt_queue(hw->vring[i].p_vq);
+ else
+ nthw_enable_tx_virt_queue(hw->vring[i].p_vq);
+ hw->vring[i].enable = 1;
+ }
+ }
+ }
+ } else {
+ /*
+ * Initially vring 0 must be enabled/created here - it is not later
+ * enabled in vring state
+ */
+ if (!hw->vring[0].enable) {
+ ntvf_vdpa_dma_map(internal, 1);
+ ntvf_vdpa_create_vring(internal, 0);
+ hw->vring[0].enable = 1;
+ }
+ }
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_stop(struct ntvf_vdpa_internal *internal)
+{
+ struct ntvf_vdpa_hw *hw = &internal->hw;
+ uint64_t features;
+ uint32_t i;
+ int vid;
+ int res;
+
+ LOG_FUNC_ENTER();
+
+ vid = internal->vid;
+
+ for (i = 0; i < hw->nr_vring; i++) {
+ rte_vhost_set_vring_base(vid, i, hw->vring[i].last_avail_idx,
+ hw->vring[i].last_used_idx);
+ }
+
+ rte_vhost_get_negotiated_features(vid, &features);
+
+ for (i = 0; i < hw->nr_vring; i++) {
+ struct vring_info *p_vr_inf = &hw->vring[i];
+
+ if ((hw->negotiated_features & (1ULL << VIRTIO_F_IN_ORDER)) ||
+ (hw->negotiated_features &
+ (1ULL << VIRTIO_F_RING_PACKED))) {
+ NT_LOG(DBG, VDPA,
+ "%s: feature VIRTIO_F_IN_ORDER is set: 0x%016lX\n",
+ __func__, hw->negotiated_features);
+ if (p_vr_inf->vq_type == 0) {
+ de_register_release_virtqueue_info(p_vr_inf->p_vq);
+ res = nthw_release_rx_virt_queue(p_vr_inf->p_vq);
+ } else if (p_vr_inf->vq_type == 1) {
+ de_register_release_virtqueue_info(p_vr_inf->p_vq);
+ res = nthw_release_tx_virt_queue(p_vr_inf->p_vq);
+ } else {
+ NT_LOG(ERR, VDPA,
+ "%s: vring #%d: unknown type %d\n",
+ __func__, i, p_vr_inf->vq_type);
+ res = -1;
+ }
+ if (res != 0) {
+ NT_LOG(ERR, VDPA, "%s: vring #%d: res=%d\n",
+ __func__, i, res);
+ }
+ } else {
+ NT_LOG(WRN, VDPA,
+ "%s: feature VIRTIO_F_IN_ORDER is *NOT* set: 0x%016lX\n",
+ __func__, hw->negotiated_features);
+ }
+ p_vr_inf->desc = 0UL;
+ }
+
+ if (RTE_VHOST_NEED_LOG(features)) {
+ NT_LOG(WRN, VDPA,
+ "%s: vid %d: vhost logging feature needed - currently not supported\n",
+ __func__, vid);
+ }
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+#define MSIX_IRQ_SET_BUF_LEN \
+ (sizeof(struct vfio_irq_set) + \
+ sizeof(int) * NTVF_VDPA_MAX_QUEUES * 2 + 1)
+
+static int ntvf_vdpa_enable_vfio_intr(struct ntvf_vdpa_internal *internal)
+{
+ int ret;
+ uint32_t i, nr_vring;
+ char irq_set_buf[MSIX_IRQ_SET_BUF_LEN];
+ struct vfio_irq_set *irq_set;
+ int *fd_ptr;
+ struct rte_vhost_vring vring;
+
+ if (atomic_load(&internal->intr_enabled))
+ return 0;
+
+ LOG_FUNC_ENTER();
+ vring.callfd = -1;
+
+ nr_vring = rte_vhost_get_vring_num(internal->vid);
+
+ NT_LOG(INF, VDPA,
+ "Enable VFIO interrupt MSI-X num rings %i on VID %i (%02x:%02x.%x)\n",
+ nr_vring, internal->vid, internal->pdev->addr.bus,
+ internal->pdev->addr.devid, internal->pdev->addr.function);
+
+ if (nr_vring + 1 > NTVF_VDPA_MAX_INTR_VECTORS) {
+ NT_LOG(WRN, VDPA,
+ "Can't enable MSI interrupts. Too many vectors requested: "
+ "%i (max: %i) only poll mode drivers will work",
+ nr_vring + 1, NTVF_VDPA_MAX_INTR_VECTORS);
+ /*
+ * Return success, because polling drivers in VM still works without
+ * interrupts (i.e. DPDK PMDs)
+ */
+ return 0;
+ }
+
+ irq_set = (struct vfio_irq_set *)irq_set_buf;
+ irq_set->argsz = sizeof(irq_set_buf);
+ irq_set->count = nr_vring + 1;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+ VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+ irq_set->start = 0;
+ fd_ptr = (int *)&irq_set->data;
+
+ fd_ptr[RTE_INTR_VEC_ZERO_OFFSET] = internal->pdev->intr_handle->fd;
+
+ for (i = 0; i < nr_vring; i += 2) {
+ rte_vhost_get_vhost_vring(internal->vid, i, &vring);
+ fd_ptr[RTE_INTR_VEC_RXTX_OFFSET + i] = vring.callfd;
+
+ rte_vhost_get_vhost_vring(internal->vid, i + 1, &vring);
+ fd_ptr[RTE_INTR_VEC_RXTX_OFFSET + i + 1] = vring.callfd;
+ }
+
+ ret = ioctl(internal->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ if (ret) {
+ NT_LOG(ERR, VDPA, "Error enabling MSI-X interrupts: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ atomic_store(&internal->intr_enabled, 1);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_disable_vfio_intr(struct ntvf_vdpa_internal *internal)
+{
+ int ret;
+ char irq_set_buf[MSIX_IRQ_SET_BUF_LEN];
+ struct vfio_irq_set *irq_set;
+ int len;
+
+ if (!atomic_load(&internal->intr_enabled))
+ return 0;
+ LOG_FUNC_ENTER();
+
+ NT_LOG(INF, VDPA, "Disable VFIO interrupt on VID %i (%02x:%02x.%x)\n",
+ internal->vid, internal->pdev->addr.bus,
+ internal->pdev->addr.devid, internal->pdev->addr.function);
+
+ len = sizeof(struct vfio_irq_set);
+ irq_set = (struct vfio_irq_set *)irq_set_buf;
+ irq_set->argsz = len;
+ irq_set->count = 0;
+ irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+ irq_set->start = 0;
+
+ ret = ioctl(internal->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ if (ret) {
+ NT_LOG(ERR, VDPA, "Error disabling MSI-X interrupts: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ atomic_store(&internal->intr_enabled, 0);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_update_datapath(struct ntvf_vdpa_internal *internal)
+{
+ int ret;
+
+ LOG_FUNC_ENTER();
+
+ rte_spinlock_lock(&internal->lock);
+
+ if (!atomic_load(&internal->running) &&
+ (atomic_load(&internal->started) &&
+ atomic_load(&internal->dev_attached))) {
+ NT_LOG(DBG, VDPA, "%s: [%s:%u] start\n", __func__, __FILE__,
+ __LINE__);
+
+ ret = ntvf_vdpa_start(internal);
+ if (ret) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ goto err;
+ }
+
+ atomic_store(&internal->running, 1);
+ } else if (atomic_load(&internal->running) &&
+ (!atomic_load(&internal->started) ||
+ !atomic_load(&internal->dev_attached))) {
+ NT_LOG(DBG, VDPA, "%s: stop\n", __func__);
+
+ ret = ntvf_vdpa_stop(internal);
+ if (ret) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ goto err;
+ }
+
+ ret = ntvf_vdpa_disable_vfio_intr(internal);
+ if (ret) {
+ goto err;
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ }
+
+ ret = ntvf_vdpa_dma_map(internal, 0);
+ if (ret) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ goto err;
+ }
+
+ atomic_store(&internal->running, 0);
+ } else {
+ NT_LOG(INF, VDPA, "%s: unhandled state [%s:%u]\n", __func__,
+ __FILE__, __LINE__);
+ }
+
+ rte_spinlock_unlock(&internal->lock);
+ LOG_FUNC_LEAVE();
+ return 0;
+
+err:
+ rte_spinlock_unlock(&internal->lock);
+ NT_LOG(ERR, VDPA, "%s: leave [%s:%u]\n", __func__, __FILE__, __LINE__);
+ return ret;
+}
+
+static int ntvf_vdpa_dev_config(int vid)
+{
+ struct rte_vdpa_device *vdev;
+ struct internal_list *list;
+ struct ntvf_vdpa_internal *internal;
+
+ LOG_FUNC_ENTER();
+
+ vdev = rte_vhost_get_vdpa_device(vid);
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev);
+ return -1;
+ }
+
+ internal = list->internal;
+ internal->vid = vid;
+
+ atomic_store(&internal->dev_attached, 1);
+
+ ntvf_vdpa_update_datapath(internal);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_dev_close(int vid)
+{
+ struct rte_vdpa_device *vdev;
+ struct internal_list *list;
+ struct ntvf_vdpa_internal *internal;
+
+ LOG_FUNC_ENTER();
+
+ vdev = rte_vhost_get_vdpa_device(vid);
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev);
+ return -1;
+ }
+
+ internal = list->internal;
+
+ atomic_store(&internal->dev_attached, 0);
+ ntvf_vdpa_update_datapath(internal);
+
+ /* Invalidate the virt queue pointers */
+ uint32_t i;
+ struct ntvf_vdpa_hw *hw = &internal->hw;
+
+ for (i = 0; i < hw->nr_vring; i++)
+ hw->vring[i].p_vq = NULL;
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_set_features(int vid)
+{
+ uint64_t features;
+ struct rte_vdpa_device *vdev;
+ struct internal_list *list;
+
+ LOG_FUNC_ENTER();
+
+ vdev = rte_vhost_get_vdpa_device(vid);
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev);
+ return -1;
+ }
+
+ rte_vhost_get_negotiated_features(vid, &features);
+ NT_LOG(DBG, VDPA, "%s: vid %d: vDPA dev %p: features=0x%016lX\n",
+ __func__, vid, vdev, features);
+
+ if (!RTE_VHOST_NEED_LOG(features))
+ return 0;
+
+ NT_LOG(INF, VDPA,
+ "%s: Starting Live Migration for vid=%d vDPA dev=%p\n", __func__,
+ vid, vdev);
+
+ /* Relay core feature not present. We cannot do live migration then. */
+ NT_LOG(ERR, VDPA,
+ "%s: Live Migration not possible. Relay core feature required.\n",
+ __func__);
+ return -1;
+}
+
+static int ntvf_vdpa_get_vfio_group_fd(int vid)
+{
+ struct rte_vdpa_device *vdev;
+ struct internal_list *list;
+
+ LOG_FUNC_ENTER();
+
+ vdev = rte_vhost_get_vdpa_device(vid);
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev);
+ return -1;
+ }
+
+ LOG_FUNC_LEAVE();
+ return list->internal->vfio_group_fd;
+}
+
+static int ntvf_vdpa_get_vfio_device_fd(int vid)
+{
+ struct rte_vdpa_device *vdev;
+ struct internal_list *list;
+
+ LOG_FUNC_ENTER();
+
+ vdev = rte_vhost_get_vdpa_device(vid);
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev);
+ return -1;
+ }
+
+ LOG_FUNC_LEAVE();
+ return list->internal->vfio_dev_fd;
+}
+
+static int ntvf_vdpa_get_queue_num(struct rte_vdpa_device *vdev,
+ uint32_t *queue_num)
+{
+ struct internal_list *list;
+
+ LOG_FUNC_ENTER();
+
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "%s: Invalid device : %p\n", __func__, vdev);
+ return -1;
+ }
+ *queue_num = list->internal->max_queues;
+ NT_LOG(DBG, VDPA, "%s: vDPA dev=%p queue_num=%d\n", __func__, vdev,
+ *queue_num);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_get_vdpa_features(struct rte_vdpa_device *vdev,
+ uint64_t *features)
+{
+ struct internal_list *list;
+
+ LOG_FUNC_ENTER();
+
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "%s: Invalid device : %p\n", __func__, vdev);
+ return -1;
+ }
+
+ if (!features) {
+ NT_LOG(ERR, VDPA, "%s: vDPA dev=%p: no ptr to feature\n",
+ __func__, vdev);
+ return -1;
+ }
+
+ *features = list->internal->features;
+ NT_LOG(DBG, VDPA, "%s: vDPA dev=%p: features=0x%016lX\n", __func__,
+ vdev, *features);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int
+ntvf_vdpa_get_protocol_features(struct rte_vdpa_device *vdev __rte_unused,
+ uint64_t *features)
+{
+ LOG_FUNC_ENTER();
+
+ if (!features) {
+ NT_LOG(ERR, VDPA, "%s: vDPA dev=%p: no ptr to feature\n",
+ __func__, vdev);
+ return -1;
+ }
+
+ *features = NTVF_VDPA_SUPPORTED_PROTOCOL_FEATURES;
+ NT_LOG(DBG, VDPA, "%s: vDPA dev=%p: features=0x%016lX\n", __func__,
+ vdev, *features);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static int ntvf_vdpa_configure_queue(struct ntvf_vdpa_hw *hw,
+ struct ntvf_vdpa_internal *internal)
+{
+ int ret = 0;
+
+ ret = ntvf_vdpa_enable_vfio_intr(internal);
+ if (ret) {
+ printf("ERROR - ENABLE INTERRUPT via VFIO\n");
+ return ret;
+ }
+ /* Enable Rx and Tx for all vrings */
+ for (int i = 0; i < hw->nr_vring; i++) {
+ if (i & 1)
+ nthw_enable_tx_virt_queue(hw->vring[i].p_vq);
+ else
+ nthw_enable_rx_virt_queue(hw->vring[i].p_vq);
+ }
+ return ret;
+}
+static int ntvf_vdpa_set_vring_state(int vid, int vring, int state)
+{
+ struct rte_vdpa_device *vdev;
+ struct internal_list *list;
+
+ struct ntvf_vdpa_internal *internal;
+ struct ntvf_vdpa_hw *hw;
+ int ret = 0;
+
+ LOG_FUNC_ENTER();
+
+ vdev = rte_vhost_get_vdpa_device(vid);
+ list = find_internal_resource_by_vdev(vdev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "Invalid vDPA device: %p", vdev);
+ return -1;
+ }
+
+ internal = list->internal;
+ if (vring < 0 || vring >= internal->max_queues * 2) {
+ NT_LOG(ERR, VDPA, "Vring index %d not correct", vring);
+ return -1;
+ }
+
+ hw = &internal->hw;
+ enum fpga_info_profile fpga_profile =
+ get_fpga_profile_from_pci(internal->pdev->addr);
+
+ if (!state && hw->vring[vring].enable) {
+ /* Disable vring */
+ if (hw->vring[vring].desc && hw->vring[vring].p_vq) {
+ if (hw->vring[vring].vq_type == 0)
+ nthw_disable_rx_virt_queue(hw->vring[vring].p_vq);
+ else
+ nthw_disable_tx_virt_queue(hw->vring[vring].p_vq);
+ }
+ }
+
+ if (state && !hw->vring[vring].enable) {
+ /* Enable/Create vring */
+ if (hw->vring[vring].desc && hw->vring[vring].p_vq) {
+ if (hw->vring[vring].vq_type == 0)
+ nthw_enable_rx_virt_queue(hw->vring[vring].p_vq);
+ else
+ nthw_enable_tx_virt_queue(hw->vring[vring].p_vq);
+ } else {
+ ntvf_vdpa_dma_map(internal, 1);
+ ntvf_vdpa_create_vring(internal, vring);
+
+ if (fpga_profile != FPGA_INFO_PROFILE_INLINE) {
+ /*
+ * After last vq enable VFIO interrupt IOMMU re-mapping and enable
+ * FPGA Rx/Tx
+ */
+ if (vring == hw->nr_vring - 1) {
+ ret = ntvf_vdpa_configure_queue(hw, internal);
+ if (ret)
+ return ret;
+ }
+ }
+ }
+ }
+
+ if (fpga_profile == FPGA_INFO_PROFILE_INLINE) {
+ hw->vring[vring].enable = !!state;
+ /* after last vq enable VFIO interrupt IOMMU re-mapping */
+ if (hw->vring[vring].enable && vring == hw->nr_vring - 1) {
+ ret = ntvf_vdpa_configure_queue(hw, internal);
+ if (ret)
+ return ret;
+ }
+ } else {
+ hw->vring[vring].enable = !!state;
+ }
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static struct rte_vdpa_dev_ops ntvf_vdpa_vdpa_ops = {
+ .get_queue_num = ntvf_vdpa_get_queue_num,
+ .get_features = ntvf_vdpa_get_vdpa_features,
+ .get_protocol_features = ntvf_vdpa_get_protocol_features,
+ .dev_conf = ntvf_vdpa_dev_config,
+ .dev_close = ntvf_vdpa_dev_close,
+ .set_vring_state = ntvf_vdpa_set_vring_state,
+ .set_features = ntvf_vdpa_set_features,
+ .migration_done = NULL,
+ .get_vfio_group_fd = ntvf_vdpa_get_vfio_group_fd,
+ .get_vfio_device_fd = ntvf_vdpa_get_vfio_device_fd,
+ .get_notify_area = NULL,
+};
+
+int ntvf_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ struct ntvf_vdpa_internal *internal = NULL;
+ struct internal_list *list = NULL;
+ enum fpga_info_profile fpga_profile;
+
+ LOG_FUNC_ENTER();
+
+ NT_LOG(INF, VDPA, "%s: [%s:%u] %04x:%02x:%02x.%x\n", __func__, __FILE__,
+ __LINE__, pci_dev->addr.domain, pci_dev->addr.bus,
+ pci_dev->addr.devid, pci_dev->addr.function);
+ list = rte_zmalloc("ntvf_vdpa", sizeof(*list), 0);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ goto error;
+ }
+
+ internal = rte_zmalloc("ntvf_vdpa", sizeof(*internal), 0);
+ if (internal == NULL) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ goto error;
+ }
+
+ internal->pdev = pci_dev;
+ rte_spinlock_init(&internal->lock);
+
+ if (ntvf_vdpa_vfio_setup(internal) < 0) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u]\n", __func__, __FILE__,
+ __LINE__);
+ return -1;
+ }
+
+ internal->max_queues = NTVF_VDPA_MAX_QUEUES;
+
+ internal->features = NTVF_VIRTIO_NET_SUPPORTED_FEATURES;
+
+ NT_LOG(DBG, VDPA, "%s: masked features=0x%016lX [%s:%u]\n", __func__,
+ internal->features, __FILE__, __LINE__);
+
+ fpga_profile = get_fpga_profile_from_pci(internal->pdev->addr);
+ if (fpga_profile == FPGA_INFO_PROFILE_VSWITCH) {
+ internal->outport = 0;
+ } else {
+ /* VF4 output port 0, VF5 output port 1, VF6 output port 0, ....... */
+ internal->outport = internal->pdev->addr.function & 1;
+ }
+
+ list->internal = internal;
+
+ internal->vdev =
+ rte_vdpa_register_device(&pci_dev->device, &ntvf_vdpa_vdpa_ops);
+ NT_LOG(DBG, VDPA, "%s: vDPA dev=%p\n", __func__, internal->vdev);
+
+ if (!internal->vdev) {
+ NT_LOG(ERR, VDPA, "%s: [%s:%u] Register vDPA device failed\n",
+ __func__, __FILE__, __LINE__);
+ goto error;
+ }
+
+ pthread_mutex_lock(&internal_list_lock);
+ TAILQ_INSERT_TAIL(&internal_list, list, next);
+ pthread_mutex_unlock(&internal_list_lock);
+
+ atomic_store(&internal->started, 1);
+
+ ntvf_vdpa_update_datapath(internal);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+
+error:
+ rte_free(list);
+ rte_free(internal);
+ return -1;
+}
+
+int ntvf_vdpa_pci_remove(struct rte_pci_device *pci_dev)
+{
+ struct ntvf_vdpa_internal *internal;
+ struct internal_list *list;
+ int vf_num = nt_vfio_vf_num(pci_dev);
+
+ LOG_FUNC_ENTER();
+ list = ntvf_vdpa_find_internal_resource_by_dev(pci_dev);
+ if (list == NULL) {
+ NT_LOG(ERR, VDPA, "%s: Invalid device: %s", __func__,
+ pci_dev->name);
+ return -1;
+ }
+
+ internal = list->internal;
+ atomic_store(&internal->started, 0);
+
+ ntvf_vdpa_update_datapath(internal);
+
+ rte_pci_unmap_device(internal->pdev);
+ nt_vfio_remove(vf_num);
+ rte_vdpa_unregister_device(internal->vdev);
+
+ pthread_mutex_lock(&internal_list_lock);
+ TAILQ_REMOVE(&internal_list, list, next);
+ pthread_mutex_unlock(&internal_list_lock);
+
+ rte_free(list);
+ rte_free(internal);
+
+ LOG_FUNC_LEAVE();
+ return 0;
+}
+
+static const struct rte_pci_id pci_id_ntvf_vdpa_map[] = {
+ {
+ .vendor_id = 0,
+ },
+};
+
+static struct rte_pci_driver rte_ntvf_vdpa = {
+ .id_table = pci_id_ntvf_vdpa_map,
+ .drv_flags = 0,
+ .probe = ntvf_vdpa_pci_probe,
+ .remove = ntvf_vdpa_pci_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_ntvf_vdpa, rte_ntvf_vdpa);
+RTE_PMD_REGISTER_PCI_TABLE(net_ntvf_vdpa, pci_id_ntvf_vdpa_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_ntvf_vdpa, "* vfio-pci");
+
diff --git a/drivers/net/ntnic/ntnic_vf_vdpa.h b/drivers/net/ntnic/ntnic_vf_vdpa.h
new file mode 100644
index 0000000000..561e3bf7cf
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vf_vdpa.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTNIC_VF_VDPA_H__
+#define __NTNIC_VF_VDPA_H__
+
+extern int ntvf_vdpa_logtype;
+
+#define LOG_FUNC_TRACE
+#ifdef LOG_FUNC_TRACE
+#define LOG_FUNC_ENTER() NT_LOG(DBG, VDPA, "%s: enter\n", __func__)
+#define LOG_FUNC_LEAVE() NT_LOG(DBG, VDPA, "%s: leave\n", __func__)
+#else
+#define LOG_FUNC_ENTER()
+#define LOG_FUNC_LEAVE()
+#endif
+
+int ntvf_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev);
+int ntvf_vdpa_pci_remove(struct rte_pci_device *pci_dev);
+
+void ntvf_vdpa_reset_hw(int vid);
+
+#endif /* __NTNIC_VF_VDPA_H__ */
diff --git a/drivers/net/ntnic/ntnic_vfio.c b/drivers/net/ntnic/ntnic_vfio.c
new file mode 100644
index 0000000000..1390383c55
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vfio.c
@@ -0,0 +1,321 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <sys/ioctl.h>
+
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_vfio.h>
+#include <rte_dev.h>
+#include <rte_bus_pci.h>
+#include <rte_spinlock.h>
+
+#include <ntlog.h>
+#include <nt_util.h>
+#include "ntnic_vfio.h"
+
+#define ONE_G_SIZE 0x40000000
+#define ONE_G_MASK (ONE_G_SIZE - 1)
+#define START_VF_IOVA 0x220000000000
+
+int nt_vfio_vf_num(const struct rte_pci_device *pdev)
+{
+ return ((pdev->addr.devid & 0x1f) << 3) + ((pdev->addr.function) & 0x7);
+}
+
+/* Internal API */
+struct vfio_dev {
+ int container_fd;
+ int group_fd;
+ int dev_fd;
+ uint64_t iova_addr;
+};
+
+static struct vfio_dev vfio_list[256];
+
+static struct vfio_dev *vfio_get(int vf_num)
+{
+ if (vf_num < 0 || vf_num > 255)
+ return NULL;
+ return &vfio_list[vf_num];
+}
+
+/* External API */
+int nt_vfio_setup(struct rte_pci_device *dev)
+{
+ char devname[RTE_DEV_NAME_MAX_LEN] = { 0 };
+ int iommu_group_num;
+ int vf_num;
+ struct vfio_dev *vfio;
+
+ NT_LOG(INF, ETHDEV, "NT VFIO device setup %s\n", dev->name);
+
+ vf_num = nt_vfio_vf_num(dev);
+
+ vfio = vfio_get(vf_num);
+ if (vfio == NULL) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device setup failed. Illegal device id\n");
+ return -1;
+ }
+
+ vfio->dev_fd = -1;
+ vfio->group_fd = -1;
+ vfio->container_fd = -1;
+ vfio->iova_addr = START_VF_IOVA;
+
+ rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
+ rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
+ &iommu_group_num);
+
+ if (vf_num == 0) {
+ /* use default container for pf0 */
+ vfio->container_fd = RTE_VFIO_DEFAULT_CONTAINER_FD;
+ } else {
+ vfio->container_fd = rte_vfio_container_create();
+ if (vfio->container_fd < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device setup failed. VFIO container creation failed.\n");
+ return -1;
+ }
+ }
+
+ vfio->group_fd = rte_vfio_container_group_bind(vfio->container_fd,
+ iommu_group_num);
+ if (vfio->group_fd < 0) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device setup failed. VFIO container group bind failed.\n");
+ goto err;
+ }
+
+ if (vf_num > 0) {
+ if (rte_pci_map_device(dev)) {
+ NT_LOG(ERR, ETHDEV,
+ "Map VFIO device failed. is the vfio-pci driver loaded?\n");
+ goto err;
+ }
+ }
+
+ vfio->dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: VFIO id=%d, dev_fd=%d, container_fd=%d, group_fd=%d, iommu_group_num=%d\n",
+ dev->name, vf_num, vfio->dev_fd, vfio->container_fd,
+ vfio->group_fd, iommu_group_num);
+
+ return vf_num;
+
+err:
+ if (vfio->container_fd != RTE_VFIO_DEFAULT_CONTAINER_FD)
+ rte_vfio_container_destroy(vfio->container_fd);
+ return -1;
+}
+
+int nt_vfio_remove(int vf_num)
+{
+ struct vfio_dev *vfio;
+
+ NT_LOG(DBG, ETHDEV, "NT VFIO device remove VF=%d\n", vf_num);
+
+ vfio = vfio_get(vf_num);
+ if (!vfio) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device remove failed. Illegal device id\n");
+ return -1;
+ }
+
+ rte_vfio_container_destroy(vfio->container_fd);
+ return 0;
+}
+
+int nt_vfio_dma_map(int vf_num, void *virt_addr, uint64_t *iova_addr,
+ uint64_t size)
+{
+ uint64_t gp_virt_base;
+ uint64_t gp_offset;
+
+ if (size == ONE_G_SIZE) {
+ gp_virt_base = (uint64_t)virt_addr & ~ONE_G_MASK;
+ gp_offset = (uint64_t)virt_addr & ONE_G_MASK;
+ } else {
+ gp_virt_base = (uint64_t)virt_addr;
+ gp_offset = 0;
+ }
+
+ struct vfio_dev *vfio;
+
+ vfio = vfio_get(vf_num);
+ if (vfio == NULL) {
+ NT_LOG(ERR, ETHDEV, "VFIO MAP: VF number %d invalid\n", vf_num);
+ return -1;
+ }
+
+ NT_LOG(DBG, ETHDEV,
+ "VFIO MMAP VF=%d VirtAddr=%" PRIX64 " HPA=%" PRIX64
+ " VirtBase=%" PRIX64 " IOVA Addr=%" PRIX64 " size=%d\n",
+ vf_num, virt_addr, rte_malloc_virt2iova(virt_addr), gp_virt_base,
+ vfio->iova_addr, size);
+
+ int res = rte_vfio_container_dma_map(vfio->container_fd, gp_virt_base,
+ vfio->iova_addr, size);
+
+ NT_LOG(DBG, ETHDEV, "VFIO MMAP res %i, container_fd %i, vf_num %i\n",
+ res, vfio->container_fd, vf_num);
+ if (res) {
+ NT_LOG(ERR, ETHDEV,
+ "rte_vfio_container_dma_map failed: res %d\n", res);
+ return -1;
+ }
+
+ *iova_addr = vfio->iova_addr + gp_offset;
+
+ vfio->iova_addr += ONE_G_SIZE;
+
+ return 0;
+}
+
+int nt_vfio_dma_unmap(int vf_num, void *virt_addr, uint64_t iova_addr,
+ uint64_t size)
+{
+ uint64_t gp_virt_base;
+ struct vfio_dev *vfio;
+
+ if (size == ONE_G_SIZE) {
+ uint64_t gp_offset;
+
+ gp_virt_base = (uint64_t)virt_addr & ~ONE_G_MASK;
+ gp_offset = (uint64_t)virt_addr & ONE_G_MASK;
+ iova_addr -= gp_offset;
+ } else {
+ gp_virt_base = (uint64_t)virt_addr;
+ }
+
+ vfio = vfio_get(vf_num);
+
+ if (vfio == NULL) {
+ NT_LOG(ERR, ETHDEV, "VFIO UNMAP: VF number %d invalid\n",
+ vf_num);
+ return -1;
+ }
+
+ if (vfio->container_fd == -1)
+ return 0;
+
+ int res = rte_vfio_container_dma_unmap(vfio->container_fd, gp_virt_base,
+ iova_addr, size);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO UNMMAP FAILED! res %i, container_fd %i, vf_num %i, virt_base=%" PRIX64
+ ", IOVA=%" PRIX64 ", size=%i\n",
+ res, vfio->container_fd, vf_num, gp_virt_base, iova_addr,
+ (int)size);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* vDPA mapping with Guest Phy addresses as IOVA */
+int nt_vfio_dma_map_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr,
+ uint64_t size)
+{
+ struct vfio_dev *vfio = vfio_get(vf_num);
+
+ if (vfio == NULL) {
+ NT_LOG(ERR, ETHDEV, "VFIO MAP: VF number %d invalid\n", vf_num);
+ return -1;
+ }
+
+ NT_LOG(DBG, ETHDEV,
+ "VFIO vDPA MMAP VF=%d VirtAddr=%" PRIX64 " IOVA Addr=%" PRIX64
+ " size=%d\n",
+ vf_num, virt_addr, iova_addr, size);
+
+ int res = rte_vfio_container_dma_map(vfio->container_fd, virt_addr,
+ iova_addr, size);
+
+ NT_LOG(DBG, ETHDEV,
+ "VFIO vDPA MMAP res %i, container_fd %i, vf_num %i\n", res,
+ vfio->container_fd, vf_num);
+ if (res) {
+ NT_LOG(ERR, ETHDEV,
+ "rte_vfio_container_dma_map failed: res %d\n", res);
+ return -1;
+ }
+
+ return 0;
+}
+
+int nt_vfio_dma_unmap_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr,
+ uint64_t size)
+{
+ struct vfio_dev *vfio = vfio_get(vf_num);
+
+ if (vfio == NULL) {
+ NT_LOG(ERR, ETHDEV, "VFIO vDPA UNMAP: VF number %d invalid\n",
+ vf_num);
+ return -1;
+ }
+ int res = rte_vfio_container_dma_unmap(vfio->container_fd, virt_addr,
+ iova_addr, size);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO vDPA UNMMAP FAILED! res %i, container_fd %i, vf_num %i\n",
+ res, vfio->container_fd, vf_num);
+ return -1;
+ }
+
+ return 0;
+}
+
+int nt_vfio_get_container_fd(int vf_num)
+{
+ struct vfio_dev *vfio;
+
+ vfio = vfio_get(vf_num);
+ if (!vfio) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device remove failed. Illegal device id\n");
+ return -1;
+ }
+ return vfio->container_fd;
+}
+
+int nt_vfio_get_group_fd(int vf_num)
+{
+ struct vfio_dev *vfio;
+
+ vfio = vfio_get(vf_num);
+ if (!vfio) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device remove failed. Illegal device id\n");
+ return -1;
+ }
+ return vfio->group_fd;
+}
+
+int nt_vfio_get_dev_fd(int vf_num)
+{
+ struct vfio_dev *vfio;
+
+ vfio = vfio_get(vf_num);
+ if (!vfio) {
+ NT_LOG(ERR, ETHDEV,
+ "VFIO device remove failed. Illegal device id\n");
+ return -1;
+ }
+ return vfio->dev_fd;
+}
+
+/* Internal init */
+
+RTE_INIT(nt_vfio_init);
+
+static void nt_vfio_init(void)
+{
+ struct nt_util_vfio_impl s = { .vfio_dma_map = nt_vfio_dma_map,
+ .vfio_dma_unmap = nt_vfio_dma_unmap
+ };
+ nt_util_vfio_init(&s);
+}
diff --git a/drivers/net/ntnic/ntnic_vfio.h b/drivers/net/ntnic/ntnic_vfio.h
new file mode 100644
index 0000000000..5d8a63d364
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_vfio.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTNIC_VFIO_H_
+#define _NTNIC_VFIO_H_
+
+#include <rte_dev.h>
+#include <rte_bus_pci.h>
+#include <ethdev_pci.h>
+
+int nt_vfio_setup(struct rte_pci_device *dev);
+int nt_vfio_remove(int vf_num);
+
+int nt_vfio_get_container_fd(int vf_num);
+int nt_vfio_get_group_fd(int vf_num);
+int nt_vfio_get_dev_fd(int vf_num);
+
+int nt_vfio_dma_map(int vf_num, void *virt_addr, uint64_t *iova_addr,
+ uint64_t size);
+int nt_vfio_dma_unmap(int vf_num, void *virt_addr, uint64_t iova_addr,
+ uint64_t size);
+
+int nt_vfio_dma_map_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr,
+ uint64_t size);
+int nt_vfio_dma_unmap_vdpa(int vf_num, uint64_t virt_addr, uint64_t iova_addr,
+ uint64_t size);
+
+/* Find device (PF/VF) number from device address */
+int nt_vfio_vf_num(const struct rte_pci_device *dev);
+#endif /* _NTNIC_VFIO_H_ */
diff --git a/drivers/net/ntnic/ntnic_xstats.c b/drivers/net/ntnic/ntnic_xstats.c
new file mode 100644
index 0000000000..e034e33c89
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_xstats.c
@@ -0,0 +1,703 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <rte_ethdev.h>
+#include <rte_common.h>
+
+#include "ntdrv_4ga.h"
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+#include "ntnic_xstats.h"
+
+#define UNUSED __rte_unused
+
+struct rte_nthw_xstats_names_s {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ uint8_t source;
+ unsigned int offset;
+};
+
+/*
+ * Extended stat for VSwitch
+ */
+static struct rte_nthw_xstats_names_s nthw_virt_xstats_names[] = {
+ { "rx_octets", 1, offsetof(struct port_counters_vswitch_v1, octets) },
+ { "rx_packets", 1, offsetof(struct port_counters_vswitch_v1, pkts) },
+ { "rx_dropped_packets", 1,
+ offsetof(struct port_counters_vswitch_v1, drop_events)
+ },
+ { "rx_qos_dropped_bytes", 1,
+ offsetof(struct port_counters_vswitch_v1, qos_drop_octets)
+ },
+ { "rx_qos_dropped_packets", 1,
+ offsetof(struct port_counters_vswitch_v1, qos_drop_pkts)
+ },
+ { "tx_octets", 2, offsetof(struct port_counters_vswitch_v1, octets) },
+ { "tx_packets", 2, offsetof(struct port_counters_vswitch_v1, pkts) },
+ { "tx_dropped_packets", 2,
+ offsetof(struct port_counters_vswitch_v1, drop_events)
+ },
+ { "tx_qos_dropped_bytes", 2,
+ offsetof(struct port_counters_vswitch_v1, qos_drop_octets)
+ },
+ { "tx_qos_dropped_packets", 2,
+ offsetof(struct port_counters_vswitch_v1, qos_drop_pkts)
+ },
+};
+
+#define NTHW_VIRT_XSTATS_NAMES RTE_DIM(nthw_virt_xstats_names)
+
+/*
+ * Extended stat for Capture/Inline - implements RMON
+ * FLM 0.17
+ */
+static struct rte_nthw_xstats_names_s nthw_cap_xstats_names_v1[] = {
+ { "rx_drop_events", 1, offsetof(struct port_counters_v2, drop_events) },
+ { "rx_octets", 1, offsetof(struct port_counters_v2, octets) },
+ { "rx_packets", 1, offsetof(struct port_counters_v2, pkts) },
+ { "rx_broadcast_packets", 1,
+ offsetof(struct port_counters_v2, broadcast_pkts)
+ },
+ { "rx_multicast_packets", 1,
+ offsetof(struct port_counters_v2, multicast_pkts)
+ },
+ { "rx_unicast_packets", 1,
+ offsetof(struct port_counters_v2, unicast_pkts)
+ },
+ { "rx_align_errors", 1,
+ offsetof(struct port_counters_v2, pkts_alignment)
+ },
+ { "rx_code_violation_errors", 1,
+ offsetof(struct port_counters_v2, pkts_code_violation)
+ },
+ { "rx_crc_errors", 1, offsetof(struct port_counters_v2, pkts_crc) },
+ { "rx_undersize_packets", 1,
+ offsetof(struct port_counters_v2, undersize_pkts)
+ },
+ { "rx_oversize_packets", 1,
+ offsetof(struct port_counters_v2, oversize_pkts)
+ },
+ { "rx_fragments", 1, offsetof(struct port_counters_v2, fragments) },
+ { "rx_jabbers_not_truncated", 1,
+ offsetof(struct port_counters_v2, jabbers_not_truncated)
+ },
+ { "rx_jabbers_truncated", 1,
+ offsetof(struct port_counters_v2, jabbers_truncated)
+ },
+ { "rx_size_64_packets", 1,
+ offsetof(struct port_counters_v2, pkts_64_octets)
+ },
+ { "rx_size_65_to_127_packets", 1,
+ offsetof(struct port_counters_v2, pkts_65_to_127_octets)
+ },
+ { "rx_size_128_to_255_packets", 1,
+ offsetof(struct port_counters_v2, pkts_128_to_255_octets)
+ },
+ { "rx_size_256_to_511_packets", 1,
+ offsetof(struct port_counters_v2, pkts_256_to_511_octets)
+ },
+ { "rx_size_512_to_1023_packets", 1,
+ offsetof(struct port_counters_v2, pkts_512_to_1023_octets)
+ },
+ { "rx_size_1024_to_1518_packets", 1,
+ offsetof(struct port_counters_v2, pkts_1024_to_1518_octets)
+ },
+ { "rx_size_1519_to_2047_packets", 1,
+ offsetof(struct port_counters_v2, pkts_1519_to_2047_octets)
+ },
+ { "rx_size_2048_to_4095_packets", 1,
+ offsetof(struct port_counters_v2, pkts_2048_to_4095_octets)
+ },
+ { "rx_size_4096_to_8191_packets", 1,
+ offsetof(struct port_counters_v2, pkts_4096_to_8191_octets)
+ },
+ { "rx_size_8192_to_max_packets", 1,
+ offsetof(struct port_counters_v2, pkts_8192_to_max_octets)
+ },
+ { "rx_ip_checksum_error", 1,
+ offsetof(struct port_counters_v2, pkts_ip_chksum_error)
+ },
+ { "rx_udp_checksum_error", 1,
+ offsetof(struct port_counters_v2, pkts_udp_chksum_error)
+ },
+ { "rx_tcp_checksum_error", 1,
+ offsetof(struct port_counters_v2, pkts_tcp_chksum_error)
+ },
+
+ { "tx_drop_events", 2, offsetof(struct port_counters_v2, drop_events) },
+ { "tx_octets", 2, offsetof(struct port_counters_v2, octets) },
+ { "tx_packets", 2, offsetof(struct port_counters_v2, pkts) },
+ { "tx_broadcast_packets", 2,
+ offsetof(struct port_counters_v2, broadcast_pkts)
+ },
+ { "tx_multicast_packets", 2,
+ offsetof(struct port_counters_v2, multicast_pkts)
+ },
+ { "tx_unicast_packets", 2,
+ offsetof(struct port_counters_v2, unicast_pkts)
+ },
+ { "tx_align_errors", 2,
+ offsetof(struct port_counters_v2, pkts_alignment)
+ },
+ { "tx_code_violation_errors", 2,
+ offsetof(struct port_counters_v2, pkts_code_violation)
+ },
+ { "tx_crc_errors", 2, offsetof(struct port_counters_v2, pkts_crc) },
+ { "tx_undersize_packets", 2,
+ offsetof(struct port_counters_v2, undersize_pkts)
+ },
+ { "tx_oversize_packets", 2,
+ offsetof(struct port_counters_v2, oversize_pkts)
+ },
+ { "tx_fragments", 2, offsetof(struct port_counters_v2, fragments) },
+ { "tx_jabbers_not_truncated", 2,
+ offsetof(struct port_counters_v2, jabbers_not_truncated)
+ },
+ { "tx_jabbers_truncated", 2,
+ offsetof(struct port_counters_v2, jabbers_truncated)
+ },
+ { "tx_size_64_packets", 2,
+ offsetof(struct port_counters_v2, pkts_64_octets)
+ },
+ { "tx_size_65_to_127_packets", 2,
+ offsetof(struct port_counters_v2, pkts_65_to_127_octets)
+ },
+ { "tx_size_128_to_255_packets", 2,
+ offsetof(struct port_counters_v2, pkts_128_to_255_octets)
+ },
+ { "tx_size_256_to_511_packets", 2,
+ offsetof(struct port_counters_v2, pkts_256_to_511_octets)
+ },
+ { "tx_size_512_to_1023_packets", 2,
+ offsetof(struct port_counters_v2, pkts_512_to_1023_octets)
+ },
+ { "tx_size_1024_to_1518_packets", 2,
+ offsetof(struct port_counters_v2, pkts_1024_to_1518_octets)
+ },
+ { "tx_size_1519_to_2047_packets", 2,
+ offsetof(struct port_counters_v2, pkts_1519_to_2047_octets)
+ },
+ { "tx_size_2048_to_4095_packets", 2,
+ offsetof(struct port_counters_v2, pkts_2048_to_4095_octets)
+ },
+ { "tx_size_4096_to_8191_packets", 2,
+ offsetof(struct port_counters_v2, pkts_4096_to_8191_octets)
+ },
+ { "tx_size_8192_to_max_packets", 2,
+ offsetof(struct port_counters_v2, pkts_8192_to_max_octets)
+ },
+
+ /* FLM 0.17 */
+ { "flm_count_current", 3, offsetof(struct flm_counters_v1, current) },
+ { "flm_count_learn_done", 3,
+ offsetof(struct flm_counters_v1, learn_done)
+ },
+ { "flm_count_learn_ignore", 3,
+ offsetof(struct flm_counters_v1, learn_ignore)
+ },
+ { "flm_count_learn_fail", 3,
+ offsetof(struct flm_counters_v1, learn_fail)
+ },
+ { "flm_count_unlearn_done", 3,
+ offsetof(struct flm_counters_v1, unlearn_done)
+ },
+ { "flm_count_unlearn_ignore", 3,
+ offsetof(struct flm_counters_v1, unlearn_ignore)
+ },
+ { "flm_count_auto_unlearn_done", 3,
+ offsetof(struct flm_counters_v1, auto_unlearn_done)
+ },
+ { "flm_count_auto_unlearn_ignore", 3,
+ offsetof(struct flm_counters_v1, auto_unlearn_ignore)
+ },
+ { "flm_count_auto_unlearn_fail", 3,
+ offsetof(struct flm_counters_v1, auto_unlearn_fail)
+ },
+ { "flm_count_timeout_unlearn_done", 3,
+ offsetof(struct flm_counters_v1, timeout_unlearn_done)
+ },
+ { "flm_count_rel_done", 3, offsetof(struct flm_counters_v1, rel_done) },
+ { "flm_count_rel_ignore", 3,
+ offsetof(struct flm_counters_v1, rel_ignore)
+ },
+ { "flm_count_prb_done", 3, offsetof(struct flm_counters_v1, prb_done) },
+ { "flm_count_prb_ignore", 3,
+ offsetof(struct flm_counters_v1, prb_ignore)
+ },
+};
+
+/*
+ * Extended stat for Capture/Inline - implements RMON
+ * FLM 0.18
+ */
+static struct rte_nthw_xstats_names_s nthw_cap_xstats_names_v2[] = {
+ { "rx_drop_events", 1, offsetof(struct port_counters_v2, drop_events) },
+ { "rx_octets", 1, offsetof(struct port_counters_v2, octets) },
+ { "rx_packets", 1, offsetof(struct port_counters_v2, pkts) },
+ { "rx_broadcast_packets", 1,
+ offsetof(struct port_counters_v2, broadcast_pkts)
+ },
+ { "rx_multicast_packets", 1,
+ offsetof(struct port_counters_v2, multicast_pkts)
+ },
+ { "rx_unicast_packets", 1,
+ offsetof(struct port_counters_v2, unicast_pkts)
+ },
+ { "rx_align_errors", 1,
+ offsetof(struct port_counters_v2, pkts_alignment)
+ },
+ { "rx_code_violation_errors", 1,
+ offsetof(struct port_counters_v2, pkts_code_violation)
+ },
+ { "rx_crc_errors", 1, offsetof(struct port_counters_v2, pkts_crc) },
+ { "rx_undersize_packets", 1,
+ offsetof(struct port_counters_v2, undersize_pkts)
+ },
+ { "rx_oversize_packets", 1,
+ offsetof(struct port_counters_v2, oversize_pkts)
+ },
+ { "rx_fragments", 1, offsetof(struct port_counters_v2, fragments) },
+ { "rx_jabbers_not_truncated", 1,
+ offsetof(struct port_counters_v2, jabbers_not_truncated)
+ },
+ { "rx_jabbers_truncated", 1,
+ offsetof(struct port_counters_v2, jabbers_truncated)
+ },
+ { "rx_size_64_packets", 1,
+ offsetof(struct port_counters_v2, pkts_64_octets)
+ },
+ { "rx_size_65_to_127_packets", 1,
+ offsetof(struct port_counters_v2, pkts_65_to_127_octets)
+ },
+ { "rx_size_128_to_255_packets", 1,
+ offsetof(struct port_counters_v2, pkts_128_to_255_octets)
+ },
+ { "rx_size_256_to_511_packets", 1,
+ offsetof(struct port_counters_v2, pkts_256_to_511_octets)
+ },
+ { "rx_size_512_to_1023_packets", 1,
+ offsetof(struct port_counters_v2, pkts_512_to_1023_octets)
+ },
+ { "rx_size_1024_to_1518_packets", 1,
+ offsetof(struct port_counters_v2, pkts_1024_to_1518_octets)
+ },
+ { "rx_size_1519_to_2047_packets", 1,
+ offsetof(struct port_counters_v2, pkts_1519_to_2047_octets)
+ },
+ { "rx_size_2048_to_4095_packets", 1,
+ offsetof(struct port_counters_v2, pkts_2048_to_4095_octets)
+ },
+ { "rx_size_4096_to_8191_packets", 1,
+ offsetof(struct port_counters_v2, pkts_4096_to_8191_octets)
+ },
+ { "rx_size_8192_to_max_packets", 1,
+ offsetof(struct port_counters_v2, pkts_8192_to_max_octets)
+ },
+ { "rx_ip_checksum_error", 1,
+ offsetof(struct port_counters_v2, pkts_ip_chksum_error)
+ },
+ { "rx_udp_checksum_error", 1,
+ offsetof(struct port_counters_v2, pkts_udp_chksum_error)
+ },
+ { "rx_tcp_checksum_error", 1,
+ offsetof(struct port_counters_v2, pkts_tcp_chksum_error)
+ },
+
+ { "tx_drop_events", 2, offsetof(struct port_counters_v2, drop_events) },
+ { "tx_octets", 2, offsetof(struct port_counters_v2, octets) },
+ { "tx_packets", 2, offsetof(struct port_counters_v2, pkts) },
+ { "tx_broadcast_packets", 2,
+ offsetof(struct port_counters_v2, broadcast_pkts)
+ },
+ { "tx_multicast_packets", 2,
+ offsetof(struct port_counters_v2, multicast_pkts)
+ },
+ { "tx_unicast_packets", 2,
+ offsetof(struct port_counters_v2, unicast_pkts)
+ },
+ { "tx_align_errors", 2,
+ offsetof(struct port_counters_v2, pkts_alignment)
+ },
+ { "tx_code_violation_errors", 2,
+ offsetof(struct port_counters_v2, pkts_code_violation)
+ },
+ { "tx_crc_errors", 2, offsetof(struct port_counters_v2, pkts_crc) },
+ { "tx_undersize_packets", 2,
+ offsetof(struct port_counters_v2, undersize_pkts)
+ },
+ { "tx_oversize_packets", 2,
+ offsetof(struct port_counters_v2, oversize_pkts)
+ },
+ { "tx_fragments", 2, offsetof(struct port_counters_v2, fragments) },
+ { "tx_jabbers_not_truncated", 2,
+ offsetof(struct port_counters_v2, jabbers_not_truncated)
+ },
+ { "tx_jabbers_truncated", 2,
+ offsetof(struct port_counters_v2, jabbers_truncated)
+ },
+ { "tx_size_64_packets", 2,
+ offsetof(struct port_counters_v2, pkts_64_octets)
+ },
+ { "tx_size_65_to_127_packets", 2,
+ offsetof(struct port_counters_v2, pkts_65_to_127_octets)
+ },
+ { "tx_size_128_to_255_packets", 2,
+ offsetof(struct port_counters_v2, pkts_128_to_255_octets)
+ },
+ { "tx_size_256_to_511_packets", 2,
+ offsetof(struct port_counters_v2, pkts_256_to_511_octets)
+ },
+ { "tx_size_512_to_1023_packets", 2,
+ offsetof(struct port_counters_v2, pkts_512_to_1023_octets)
+ },
+ { "tx_size_1024_to_1518_packets", 2,
+ offsetof(struct port_counters_v2, pkts_1024_to_1518_octets)
+ },
+ { "tx_size_1519_to_2047_packets", 2,
+ offsetof(struct port_counters_v2, pkts_1519_to_2047_octets)
+ },
+ { "tx_size_2048_to_4095_packets", 2,
+ offsetof(struct port_counters_v2, pkts_2048_to_4095_octets)
+ },
+ { "tx_size_4096_to_8191_packets", 2,
+ offsetof(struct port_counters_v2, pkts_4096_to_8191_octets)
+ },
+ { "tx_size_8192_to_max_packets", 2,
+ offsetof(struct port_counters_v2, pkts_8192_to_max_octets)
+ },
+
+ /* FLM 0.17 */
+ { "flm_count_current", 3, offsetof(struct flm_counters_v1, current) },
+ { "flm_count_learn_done", 3,
+ offsetof(struct flm_counters_v1, learn_done)
+ },
+ { "flm_count_learn_ignore", 3,
+ offsetof(struct flm_counters_v1, learn_ignore)
+ },
+ { "flm_count_learn_fail", 3,
+ offsetof(struct flm_counters_v1, learn_fail)
+ },
+ { "flm_count_unlearn_done", 3,
+ offsetof(struct flm_counters_v1, unlearn_done)
+ },
+ { "flm_count_unlearn_ignore", 3,
+ offsetof(struct flm_counters_v1, unlearn_ignore)
+ },
+ { "flm_count_auto_unlearn_done", 3,
+ offsetof(struct flm_counters_v1, auto_unlearn_done)
+ },
+ { "flm_count_auto_unlearn_ignore", 3,
+ offsetof(struct flm_counters_v1, auto_unlearn_ignore)
+ },
+ { "flm_count_auto_unlearn_fail", 3,
+ offsetof(struct flm_counters_v1, auto_unlearn_fail)
+ },
+ { "flm_count_timeout_unlearn_done", 3,
+ offsetof(struct flm_counters_v1, timeout_unlearn_done)
+ },
+ { "flm_count_rel_done", 3, offsetof(struct flm_counters_v1, rel_done) },
+ { "flm_count_rel_ignore", 3,
+ offsetof(struct flm_counters_v1, rel_ignore)
+ },
+ { "flm_count_prb_done", 3, offsetof(struct flm_counters_v1, prb_done) },
+ { "flm_count_prb_ignore", 3,
+ offsetof(struct flm_counters_v1, prb_ignore)
+ },
+
+ /* FLM 0.20 */
+ { "flm_count_sta_done", 3, offsetof(struct flm_counters_v1, sta_done) },
+ { "flm_count_inf_done", 3, offsetof(struct flm_counters_v1, inf_done) },
+ { "flm_count_inf_skip", 3, offsetof(struct flm_counters_v1, inf_skip) },
+ { "flm_count_pck_hit", 3, offsetof(struct flm_counters_v1, pck_hit) },
+ { "flm_count_pck_miss", 3, offsetof(struct flm_counters_v1, pck_miss) },
+ { "flm_count_pck_unh", 3, offsetof(struct flm_counters_v1, pck_unh) },
+ { "flm_count_pck_dis", 3, offsetof(struct flm_counters_v1, pck_dis) },
+ { "flm_count_csh_hit", 3, offsetof(struct flm_counters_v1, csh_hit) },
+ { "flm_count_csh_miss", 3, offsetof(struct flm_counters_v1, csh_miss) },
+ { "flm_count_csh_unh", 3, offsetof(struct flm_counters_v1, csh_unh) },
+ { "flm_count_cuc_start", 3,
+ offsetof(struct flm_counters_v1, cuc_start)
+ },
+ { "flm_count_cuc_move", 3, offsetof(struct flm_counters_v1, cuc_move) },
+};
+
+#define NTHW_CAP_XSTATS_NAMES_V1 RTE_DIM(nthw_cap_xstats_names_v1)
+#define NTHW_CAP_XSTATS_NAMES_V2 RTE_DIM(nthw_cap_xstats_names_v2)
+
+/*
+ * Container for the reset values
+ */
+#define NTHW_XSTATS_SIZE ((NTHW_VIRT_XSTATS_NAMES < NTHW_CAP_XSTATS_NAMES_V2) ? \
+ NTHW_CAP_XSTATS_NAMES_V2 : NTHW_VIRT_XSTATS_NAMES)
+
+uint64_t nthw_xstats_reset_val[NUM_ADAPTER_PORTS_MAX][NTHW_XSTATS_SIZE] = { 0 };
+
+
+/*
+ * These functions must only be called with stat mutex locked
+ */
+int nthw_xstats_get(nt4ga_stat_t *p_nt4ga_stat, struct rte_eth_xstat *stats,
+ unsigned int n, bool is_vswitch, uint8_t port)
+{
+ unsigned int i;
+ uint8_t *flm_ptr;
+ uint8_t *rx_ptr;
+ uint8_t *tx_ptr;
+ uint32_t nb_names;
+ struct rte_nthw_xstats_names_s *names;
+
+ if (is_vswitch) {
+ flm_ptr = NULL;
+ rx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_rx[port];
+ tx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_tx[port];
+ names = nthw_virt_xstats_names;
+ nb_names = NTHW_VIRT_XSTATS_NAMES;
+ } else {
+ flm_ptr = (uint8_t *)p_nt4ga_stat->mp_stat_structs_flm;
+ rx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_rx[port];
+ tx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_tx[port];
+ if (p_nt4ga_stat->flm_stat_ver < 18) {
+ names = nthw_cap_xstats_names_v1;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V1;
+ } else {
+ names = nthw_cap_xstats_names_v2;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V2;
+ }
+ }
+
+ for (i = 0; i < n && i < nb_names; i++) {
+ stats[i].id = i;
+ switch (names[i].source) {
+ case 1:
+ /* RX stat */
+ stats[i].value =
+ *((uint64_t *)&rx_ptr[names[i].offset]) -
+ nthw_xstats_reset_val[port][i];
+ break;
+ case 2:
+ /* TX stat */
+ stats[i].value =
+ *((uint64_t *)&tx_ptr[names[i].offset]) -
+ nthw_xstats_reset_val[port][i];
+ break;
+ case 3:
+ /* FLM stat */
+ if (flm_ptr) {
+ stats[i].value =
+ *((uint64_t *)&flm_ptr[names[i].offset]) -
+ nthw_xstats_reset_val[0][i];
+ } else {
+ stats[i].value = 0;
+ }
+ break;
+ default:
+ stats[i].value = 0;
+ break;
+ }
+ }
+
+ return i;
+}
+
+int nthw_xstats_get_by_id(nt4ga_stat_t *p_nt4ga_stat, const uint64_t *ids,
+ uint64_t *values, unsigned int n, bool is_vswitch,
+ uint8_t port)
+{
+ unsigned int i;
+ uint8_t *flm_ptr;
+ uint8_t *rx_ptr;
+ uint8_t *tx_ptr;
+ uint32_t nb_names;
+ struct rte_nthw_xstats_names_s *names;
+ int count = 0;
+
+ if (is_vswitch) {
+ flm_ptr = NULL;
+ rx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_rx[port];
+ tx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_tx[port];
+ names = nthw_virt_xstats_names;
+ nb_names = NTHW_VIRT_XSTATS_NAMES;
+ } else {
+ flm_ptr = (uint8_t *)p_nt4ga_stat->mp_stat_structs_flm;
+ rx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_rx[port];
+ tx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_tx[port];
+ if (p_nt4ga_stat->flm_stat_ver < 18) {
+ names = nthw_cap_xstats_names_v1;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V1;
+ } else {
+ names = nthw_cap_xstats_names_v2;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V2;
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ if (ids[i] < nb_names) {
+ switch (names[ids[i]].source) {
+ case 1:
+ /* RX stat */
+ values[i] =
+ *((uint64_t *)&rx_ptr[names[ids[i]]
+ .offset]) -
+ nthw_xstats_reset_val[port][ids[i]];
+ break;
+ case 2:
+ /* TX stat */
+ values[i] =
+ *((uint64_t *)&tx_ptr[names[ids[i]]
+ .offset]) -
+ nthw_xstats_reset_val[port][ids[i]];
+ break;
+ case 3:
+ /* FLM stat */
+ if (flm_ptr) {
+ values[i] =
+ *((uint64_t *)&flm_ptr
+ [names[ids[i]].offset]) -
+ nthw_xstats_reset_val[0][ids[i]];
+ } else {
+ values[i] = 0;
+ }
+ break;
+ default:
+ values[i] = 0;
+ break;
+ }
+ count++;
+ }
+ }
+
+ return count;
+}
+
+void nthw_xstats_reset(nt4ga_stat_t *p_nt4ga_stat, bool is_vswitch, uint8_t port)
+{
+ unsigned int i;
+ uint8_t *flm_ptr;
+ uint8_t *rx_ptr;
+ uint8_t *tx_ptr;
+ uint32_t nb_names;
+ struct rte_nthw_xstats_names_s *names;
+
+ if (is_vswitch) {
+ flm_ptr = NULL;
+ rx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_rx[port];
+ tx_ptr = (uint8_t *)&p_nt4ga_stat->virt.mp_stat_structs_port_tx[port];
+ names = nthw_virt_xstats_names;
+ nb_names = NTHW_VIRT_XSTATS_NAMES;
+ } else {
+ flm_ptr = (uint8_t *)p_nt4ga_stat->mp_stat_structs_flm;
+ rx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_rx[port];
+ tx_ptr = (uint8_t *)&p_nt4ga_stat->cap.mp_stat_structs_port_tx[port];
+ if (p_nt4ga_stat->flm_stat_ver < 18) {
+ names = nthw_cap_xstats_names_v1;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V1;
+ } else {
+ names = nthw_cap_xstats_names_v2;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V2;
+ }
+ }
+
+ for (i = 0; i < nb_names; i++) {
+ switch (names[i].source) {
+ case 1:
+ /* RX stat */
+ nthw_xstats_reset_val[port][i] =
+ *((uint64_t *)&rx_ptr[names[i].offset]);
+ break;
+ case 2:
+ /* TX stat */
+ nthw_xstats_reset_val[port][i] =
+ *((uint64_t *)&tx_ptr[names[i].offset]);
+ break;
+ case 3:
+ /*
+ * FLM stat
+ * Reset makes no sense for flm_count_current
+ */
+ if (flm_ptr && strcmp(names[i].name, "flm_count_current") != 0) {
+ nthw_xstats_reset_val[0][i] =
+ *((uint64_t *)&flm_ptr[names[i].offset]);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * These functions does not require stat mutex locked
+ */
+int nthw_xstats_get_names(nt4ga_stat_t *p_nt4ga_stat,
+ struct rte_eth_xstat_name *xstats_names,
+ unsigned int size, bool is_vswitch)
+{
+ int count = 0;
+ unsigned int i;
+ uint32_t nb_names;
+ struct rte_nthw_xstats_names_s *names;
+
+ if (is_vswitch) {
+ names = nthw_virt_xstats_names;
+ nb_names = NTHW_VIRT_XSTATS_NAMES;
+ } else {
+ if (p_nt4ga_stat->flm_stat_ver < 18) {
+ names = nthw_cap_xstats_names_v1;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V1;
+ } else {
+ names = nthw_cap_xstats_names_v2;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V2;
+ }
+ }
+
+ if (!xstats_names)
+ return nb_names;
+
+ for (i = 0; i < size && i < nb_names; i++) {
+ strlcpy(xstats_names[i].name, names[i].name,
+ sizeof(xstats_names[i].name));
+ count++;
+ }
+
+ return count;
+}
+
+int nthw_xstats_get_names_by_id(nt4ga_stat_t *p_nt4ga_stat,
+ struct rte_eth_xstat_name *xstats_names,
+ const uint64_t *ids, unsigned int size,
+ bool is_vswitch)
+{
+ int count = 0;
+ unsigned int i;
+
+ uint32_t nb_names;
+ struct rte_nthw_xstats_names_s *names;
+
+ if (is_vswitch) {
+ names = nthw_virt_xstats_names;
+ nb_names = NTHW_VIRT_XSTATS_NAMES;
+ } else {
+ if (p_nt4ga_stat->flm_stat_ver < 18) {
+ names = nthw_cap_xstats_names_v1;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V1;
+ } else {
+ names = nthw_cap_xstats_names_v2;
+ nb_names = NTHW_CAP_XSTATS_NAMES_V2;
+ }
+ }
+
+ if (!xstats_names)
+ return nb_names;
+
+ for (i = 0; i < size; i++) {
+ if (ids[i] < nb_names) {
+ strlcpy(xstats_names[i].name, names[ids[i]].name,
+ RTE_ETH_XSTATS_NAME_SIZE);
+ }
+ count++;
+ }
+
+ return count;
+}
diff --git a/drivers/net/ntnic/ntnic_xstats.h b/drivers/net/ntnic/ntnic_xstats.h
new file mode 100644
index 0000000000..0a82a1a677
--- /dev/null
+++ b/drivers/net/ntnic/ntnic_xstats.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTNIC_XSTATS_H_
+#define NTNIC_XSTATS_H_
+
+int nthw_xstats_get_names(nt4ga_stat_t *p_nt4ga_stat,
+ struct rte_eth_xstat_name *xstats_names,
+ unsigned int size, bool is_vswitch);
+int nthw_xstats_get(nt4ga_stat_t *p_nt4ga_stat, struct rte_eth_xstat *stats,
+ unsigned int n, bool is_vswitch, uint8_t port);
+void nthw_xstats_reset(nt4ga_stat_t *p_nt4ga_stat, bool is_vswitch, uint8_t port);
+int nthw_xstats_get_names_by_id(nt4ga_stat_t *p_nt4ga_stat,
+ struct rte_eth_xstat_name *xstats_names,
+ const uint64_t *ids, unsigned int size,
+ bool is_vswitch);
+int nthw_xstats_get_by_id(nt4ga_stat_t *p_nt4ga_stat, const uint64_t *ids,
+ uint64_t *values, unsigned int n, bool is_vswitch,
+ uint8_t port);
+
+#endif /* NTNIC_XSTATS_H_ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH 8/8] net/ntnic: adds socket connection to PMD
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (5 preceding siblings ...)
2023-08-16 13:25 ` [PATCH 7/8] net/ntnic: adds ethdev and makes PMD available Mykola Kostenok
@ 2023-08-16 13:25 ` Mykola Kostenok
2023-08-16 14:46 ` Stephen Hemminger
2023-08-16 14:47 ` Stephen Hemminger
2023-08-17 14:43 ` [PATCH v2 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (13 subsequent siblings)
20 siblings, 2 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-16 13:25 UTC (permalink / raw)
To: dev; +Cc: Christian Koue Muf
From: Christian Koue Muf <ckm@napatech.com>
The socket connection is used by Napatech's tools for monitoring
and rte_flow programming from other processes.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/ntnic/meson.build | 24 +
.../ntconnect/include/ntconn_mod_helper.h | 97 ++
.../net/ntnic/ntconnect/include/ntconnect.h | 96 ++
.../ntnic/ntconnect/include/ntconnect_api.h | 87 ++
.../ntconnect/include/ntconnect_api_adapter.h | 221 +++
.../ntconnect/include/ntconnect_api_flow.h | 168 +++
.../ntconnect/include/ntconnect_api_meter.h | 89 ++
.../include/ntconnect_api_statistic.h | 173 +++
.../ntconnect/include/ntconnect_api_test.h | 18 +
drivers/net/ntnic/ntconnect/ntconn_server.c | 97 ++
drivers/net/ntnic/ntconnect/ntconnect.c | 641 ++++++++
.../ntnic/ntconnect_modules/ntconn_adapter.c | 775 ++++++++++
.../net/ntnic/ntconnect_modules/ntconn_flow.c | 1310 +++++++++++++++++
.../ntnic/ntconnect_modules/ntconn_meter.c | 517 +++++++
.../ntnic/ntconnect_modules/ntconn_modules.h | 19 +
.../net/ntnic/ntconnect_modules/ntconn_stat.c | 876 +++++++++++
.../net/ntnic/ntconnect_modules/ntconn_test.c | 146 ++
17 files changed, 5354 insertions(+)
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h
create mode 100644 drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h
create mode 100644 drivers/net/ntnic/ntconnect/ntconn_server.c
create mode 100644 drivers/net/ntnic/ntconnect/ntconnect.c
create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c
create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_flow.c
create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_meter.c
create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_modules.h
create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_stat.c
create mode 100644 drivers/net/ntnic/ntconnect_modules/ntconn_test.c
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index faaba95af3..262ce436b9 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -1,11 +1,27 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2020-2023 Napatech A/S
+# config object
+ntnic_conf = configuration_data()
+
+# transfer options into config object
+ntnic_conf.set('NT_TOOLS', true)
+
# cflags
cflags += [
'-std=c11',
]
+# check option 'debug' (boolean flag derived from meson buildtype)
+if get_option('debug')
+ cflags += '-DDEBUG'
+endif
+
+# check nt_tools build option
+if ntnic_conf.get('NT_TOOLS')
+ cflags += '-DNT_TOOLS'
+endif
+
# includes
includes = [
include_directories('.'),
@@ -19,6 +35,7 @@ includes = [
include_directories('nthw/supported'),
include_directories('nthw/flow_api'),
include_directories('nthw/flow_filter'),
+ include_directories('ntconnect/include'),
include_directories('sensors'),
include_directories('sensors/avr_sensors'),
include_directories('sensors/board_sensors'),
@@ -40,6 +57,13 @@ sources = files(
'nim/nt_link_speed.c',
'nim/qsfp_sensors.c',
'nim/sfp_sensors.c',
+ 'ntconnect/ntconn_server.c',
+ 'ntconnect/ntconnect.c',
+ 'ntconnect_modules/ntconn_adapter.c',
+ 'ntconnect_modules/ntconn_flow.c',
+ 'ntconnect_modules/ntconn_meter.c',
+ 'ntconnect_modules/ntconn_stat.c',
+ 'ntconnect_modules/ntconn_test.c',
'nthw/core/nthw_clock_profiles.c',
'nthw/core/nthw_fpga.c',
'nthw/core/nthw_fpga_nt200a0x.c',
diff --git a/drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h b/drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h
new file mode 100644
index 0000000000..f55c4141cc
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconn_mod_helper.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONN_MOD_HELPER_H_
+#define _NTCONN_MOD_HELPER_H_
+
+#include "ntconnect.h"
+
+/*
+ * Module parameter function call tree structures
+ */
+struct func_s {
+ const char *param;
+ struct func_s *sub_funcs;
+ int (*func)(void *hdl, int client_fd, struct ntconn_header_s *hdr,
+ char **data, int *len);
+};
+
+static inline int ntconn_error(char **data, int *len, const char *module,
+ enum ntconn_err_e err_code)
+{
+ *len = 0;
+ if (data) {
+ const ntconn_err_t *ntcerr = get_ntconn_error(err_code);
+ *data = malloc(4 + strlen(module) + 1 +
+ strlen(ntcerr->err_text) + 1);
+ if (*data) {
+ sprintf(*data, "----%s:%s", module, ntcerr->err_text);
+ *len = strlen(*data) + 1; /* add 0 - terminator */
+ *(uint32_t *)*data = (uint32_t)ntcerr->err_code;
+ }
+ }
+ return REQUEST_ERR;
+}
+
+static inline int ntconn_reply_status(char **data, int *len,
+ enum ntconn_reply_code_e code)
+{
+ *len = 0;
+ if (data) {
+ *data = malloc(sizeof(uint32_t));
+ if (*data) {
+ *len = sizeof(uint32_t);
+ *(uint32_t *)*data = (uint32_t)code;
+ }
+ }
+ return REQUEST_OK;
+}
+
+static inline int execute_function(const char *module, void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char *function,
+ struct func_s *func_list, char **data,
+ int *len, int recur_depth)
+{
+ char *tok = strtok(function, ",");
+
+ if (!tok) {
+ if (recur_depth == 0)
+ return ntconn_error(data, len, module,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ else
+ return ntconn_error(data, len, module,
+ NTCONN_ERR_CODE_FUNCTION_PARAM_INCOMPLETE);
+ }
+
+ hdr->len -= strlen(tok) + 1;
+ char *sub_funcs = function + strlen(tok) + 1;
+ int idx = 0;
+
+ while (func_list[idx].param) {
+ if (strcmp(func_list[idx].param, tok) == 0) {
+ /* hit */
+ if (func_list[idx].sub_funcs) {
+ return execute_function(module, hdl, client_id,
+ hdr, sub_funcs,
+ func_list[idx].sub_funcs,
+ data, len,
+ ++recur_depth);
+ } else if (func_list[idx].func) {
+ /* commands/parameters for function in text, zero-terminated */
+ *data = sub_funcs;
+ return func_list[idx].func(hdl, client_id, hdr,
+ data, len);
+ } else {
+ return ntconn_error(data, len, module,
+ NTCONN_ERR_CODE_INTERNAL_FUNC_ERROR);
+ }
+ }
+ idx++;
+ }
+ /* no hits */
+ return ntconn_error(data, len, module,
+ NTCONN_ERR_CODE_FUNC_PARAM_NOT_RECOGNIZED);
+}
+
+#endif /* _NTCONN_MOD_HELPER_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect.h b/drivers/net/ntnic/ntconnect/include/ntconnect.h
new file mode 100644
index 0000000000..9dcf2ec0a1
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_H_
+#define _NTCONNECT_H_
+
+#include <rte_pci.h>
+#include <sched.h>
+#include <stdint.h>
+
+#include "ntconnect_api.h"
+
+#define REQUEST_OK 0
+#define REQUEST_ERR -1
+
+typedef struct ntconn_api_s {
+ /*
+ * Name specifying this module. This name is used in the request string
+ */
+ const char *module;
+ /*
+ * The version of this module integration
+ */
+ uint32_t version_major;
+ uint32_t version_minor;
+ /*
+ * The request function:
+ * hdl : pointer to the context of this instance.
+ * client_id : identifying the client. To be able to manage client specific data/state.
+ * function : pointer to the remainder of the request command (Layer 3). May be modified.
+ * an example: <pci_id>;adapter;get,interface,port0,link_speed function will
+ * then be 'get,interface,port0,link_speed'.
+ * hdr : header for length of command string and length of binary blop.
+ * The command string will start at "*data" and will have the length hdr->len.
+ * The binary blob will start at "&(*data)[hdr->len]" and will have the length
+ * hdr->blob_len.
+ * data : pointer to the resulting data. Typically this will be allocated.
+ * len : length of the data in the reply.
+ *
+ * return : REQUEST_OK on success, REQUEST_ERR on failure. On failure, the data and len
+ * can contain an describing error text
+ */
+ int (*request)(void *hdl, int client_id, struct ntconn_header_s *hdr,
+ char *function, char **data, int *len);
+ /*
+ * After each request call, and when 'len' returns > 0, this function is called
+ * after sending reply to client.
+ * hdl : pointer to the context of this instance.
+ * data : the data pointer returned in the request function
+ */
+ void (*free_data)(void *hdl, char *data);
+ /*
+ * Clean up of client specific data allocations. Called when client disconnects from server
+ * hdl : pointer to the context of this instance.
+ * client_id : identifying the client.
+ */
+ void (*client_cleanup)(void *hdl, int client_id);
+} ntconnapi_t;
+
+/*
+ * ntconn error
+ */
+typedef struct ntconn_err_s {
+ uint32_t err_code;
+ const char *err_text;
+} ntconn_err_t;
+
+const ntconn_err_t *get_ntconn_error(enum ntconn_err_e err_code);
+
+typedef struct ntconn_mod_s {
+ void *hdl;
+ struct pci_id_s addr;
+ const ntconnapi_t *op;
+
+ pthread_mutex_t mutex;
+ struct ntconn_mod_s *next;
+} ntconn_mod_t;
+
+struct ntconn_server_s {
+ int serv_fd;
+ int running;
+ /*
+ * list of different pci_ids registered aka SmartNICs
+ */
+ struct pci_id_s pci_id_list[MAX_PCI_IDS]; /* 0 - terminates */
+ cpu_set_t cpuset;
+};
+
+int ntconn_server_register(void *server);
+
+int register_ntconn_mod(const struct rte_pci_addr *addr, void *hdl,
+ const ntconnapi_t *op);
+int ntconnect_init(const char *sockname, cpu_set_t cpuset);
+
+#endif /* _NTCONNECT_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api.h
new file mode 100644
index 0000000000..14668bf2ee
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_API_H_
+#define _NTCONNECT_API_H_
+
+#include "stdint.h"
+/*
+ * NtConnect API
+ */
+
+#define NTCONNECT_SOCKET "/var/run/ntconnect/ntconnect.sock"
+
+enum ntconn_err_e {
+ NTCONN_ERR_CODE_NONE = 0U,
+ NTCONN_ERR_CODE_INTERNAL_ERROR,
+ NTCONN_ERR_CODE_INVALID_REQUEST,
+ NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR,
+ NTCONN_ERR_CODE_NO_DATA,
+ NTCONN_ERR_CODE_NOT_YET_IMPLEMENTED,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM,
+ NTCONN_ERR_CODE_FUNCTION_PARAM_INCOMPLETE,
+ NTCONN_ERR_CODE_INTERNAL_FUNC_ERROR,
+ NTCONN_ERR_CODE_FUNC_PARAM_NOT_RECOGNIZED,
+};
+
+enum ntconn_reply_code_e {
+ NTCONN_ADAPTER_ERR_PORT_STATE_FAIL = 0U,
+ NTCONN_ADAPTER_ERR_WRONG_LINK_STATE,
+ NTCONN_ADAPTER_ERR_TX_POWER_FAIL,
+};
+
+enum {
+ NTCONN_TAG_NONE,
+ NTCONN_TAG_REQUEST,
+ NTCONN_TAG_REPLY,
+ NTCONN_TAG_ERROR
+};
+
+#define MESSAGE_BUFFER 256
+#define MAX_ERR_MESSAGE_LENGTH 256
+
+struct reply_err_s {
+ enum ntconn_err_e err_code;
+ char msg[MAX_ERR_MESSAGE_LENGTH];
+};
+
+#define NTCMOD_HDR_LEN sizeof(struct ntconn_header_s)
+struct ntconn_header_s {
+ uint16_t tag;
+ uint16_t len;
+ uint32_t blob_len;
+};
+
+struct pci_id_s {
+ union {
+ uint64_t pci_id;
+ struct {
+ uint32_t domain;
+ uint8_t bus;
+ uint8_t devid;
+ uint8_t function;
+ uint8_t pad;
+ };
+ };
+};
+
+#define VERSION_HI(version) ((unsigned int)((version) >> 32))
+#define VERSION_LO(version) ((unsigned int)((version) & 0xffffffff))
+
+/*
+ * Binary interface description for ntconnect module replies
+ */
+
+/*
+ * server get,nic_pci_ids
+ */
+#define MAX_PCI_IDS 16
+#define NICS_PCI_ID_LEN 12
+
+struct ntc_nic_pci_ids_s {
+ char nic_pci_id[MAX_PCI_IDS][NICS_PCI_ID_LEN + 1];
+ int num_nics;
+};
+
+#endif /* _NTCONNECT_API_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h
new file mode 100644
index 0000000000..2362d440b4
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_adapter.h
@@ -0,0 +1,221 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_API_ADAPTER_H_
+#define _NTCONNECT_API_ADAPTER_H_
+
+/*
+ * adapter get,interfaces
+ */
+enum port_speed {
+ PORT_LINK_SPEED_UNKNOWN,
+ PORT_LINK_SPEED_NONE_REPORTED,
+ PORT_LINK_SPEED_10M,
+ PORT_LINK_SPEED_100M,
+ PORT_LINK_SPEED_1G,
+ PORT_LINK_SPEED_10G,
+ PORT_LINK_SPEED_25G,
+ PORT_LINK_SPEED_40G,
+ PORT_LINK_SPEED_50G,
+ PORT_LINK_SPEED_100G,
+};
+
+enum port_states {
+ PORT_STATE_DISABLED,
+ PORT_STATE_NIM_PRESENT,
+ PORT_STATE_NIM_ABSENT,
+ PORT_STATE_VIRTUAL_UNATTACHED,
+ PORT_STATE_VIRTUAL_SPLIT,
+ PORT_STATE_VIRTUAL_PACKED,
+ PORT_STATE_VIRTUAL_RELAY,
+};
+
+enum port_link { PORT_LINK_UNKNOWN, PORT_LINK_UP, PORT_LINK_DOWN };
+
+enum port_type {
+ PORT_TYPE_PHY_NORMAL, /* Normal phy port (no LAG) */
+ /* Link aggregated phy port in active/active LAG configuration */
+ PORT_TYPE_PHY_LAG_ACTIVE_AVTIVE,
+ PORT_TYPE_PHY_LAG_PRIMARY, /* Primary phy port in active/backup LAG configuration */
+ PORT_TYPE_PHY_LAG_BACKUP, /* Backup phy port in active/backup LAG configuration */
+ PORT_TYPE_VIRT,
+ PORT_TYPE_LAST
+};
+
+enum nim_identifier_e {
+ NIM_UNKNOWN = 0x00, /* Nim type is unknown */
+ NIM_GBIC = 0x01, /* Nim type = GBIC */
+ NIM_FIXED = 0x02, /* Nim type = FIXED */
+ NIM_SFP_SFP_PLUS = 0x03, /* Nim type = SFP/SFP+ */
+ NIM_300_PIN_XBI = 0x04, /* Nim type = 300 pin XBI */
+ NIM_XEN_PAK = 0x05, /* Nim type = XEN-PAK */
+ NIM_XFP = 0x06, /* Nim type = XFP */
+ NIM_XFF = 0x07, /* Nim type = XFF */
+ NIM_XFP_E = 0x08, /* Nim type = XFP-E */
+ NIM_XPAK = 0x09, /* Nim type = XPAK */
+ NIM_X2 = 0x0A, /* Nim type = X2 */
+ NIM_DWDM = 0x0B, /* Nim type = DWDM */
+ NIM_QSFP = 0x0C, /* Nim type = QSFP */
+ NIM_QSFP_PLUS = 0x0D, /* Nim type = QSFP+ */
+ NIM_QSFP28 = 0x11, /* Nim type = QSFP28 */
+ NIM_CFP4 = 0x12, /* Nim type = CFP4 */
+};
+
+/*
+ * Port types
+ */
+enum port_type_e {
+ PORT_TYPE_NOT_AVAILABLE =
+ 0, /* The NIM/port type is not available (unknown) */
+ PORT_TYPE_NOT_RECOGNISED, /* The NIM/port type not recognized */
+ PORT_TYPE_RJ45, /* RJ45 type */
+ PORT_TYPE_SFP_NOT_PRESENT, /* SFP type but slot is empty */
+ PORT_TYPE_SFP_SX, /* SFP SX */
+ PORT_TYPE_SFP_SX_DD, /* SFP SX digital diagnostic */
+ PORT_TYPE_SFP_LX, /* SFP LX */
+ PORT_TYPE_SFP_LX_DD, /* SFP LX digital diagnostic */
+ PORT_TYPE_SFP_ZX, /* SFP ZX */
+ PORT_TYPE_SFP_ZX_DD, /* SFP ZX digital diagnostic */
+ PORT_TYPE_SFP_CU, /* SFP copper */
+ PORT_TYPE_SFP_CU_DD, /* SFP copper digital diagnostic */
+ PORT_TYPE_SFP_NOT_RECOGNISED, /* SFP unknown */
+ PORT_TYPE_XFP, /* XFP */
+ PORT_TYPE_XPAK, /* XPAK */
+ PORT_TYPE_SFP_CU_TRI_SPEED, /* SFP copper tri-speed */
+ PORT_TYPE_SFP_CU_TRI_SPEED_DD, /* SFP copper tri-speed digital diagnostic */
+ PORT_TYPE_SFP_PLUS, /* SFP+ type */
+ PORT_TYPE_SFP_PLUS_NOT_PRESENT, /* SFP+ type but slot is empty */
+ PORT_TYPE_XFP_NOT_PRESENT, /* XFP type but slot is empty */
+ PORT_TYPE_QSFP_PLUS_NOT_PRESENT, /* QSFP type but slot is empty */
+ PORT_TYPE_QSFP_PLUS, /* QSFP type */
+ PORT_TYPE_SFP_PLUS_PASSIVE_DAC, /* SFP+ Passive DAC */
+ PORT_TYPE_SFP_PLUS_ACTIVE_DAC, /* SFP+ Active DAC */
+ PORT_TYPE_CFP4, /* CFP4 type */
+ PORT_TYPE_CFP4_LR4 = PORT_TYPE_CFP4, /* CFP4 100G, LR4 type */
+ PORT_TYPE_CFP4_NOT_PRESENT, /* CFP4 type but slot is empty */
+ PORT_TYPE_INITIALIZE, /* The port type is not fully established yet */
+ PORT_TYPE_NIM_NOT_PRESENT, /* Generic "Not present" */
+ PORT_TYPE_HCB, /* Test mode: Host Compliance Board */
+ PORT_TYPE_NOT_SUPPORTED, /* The NIM type is not supported in this context */
+ PORT_TYPE_SFP_PLUS_DUAL_RATE, /* SFP+ supports 1G/10G */
+ PORT_TYPE_CFP4_SR4, /* CFP4 100G, SR4 type */
+ PORT_TYPE_QSFP28_NOT_PRESENT, /* QSFP28 type but slot is empty */
+ PORT_TYPE_QSFP28, /* QSFP28 type */
+ PORT_TYPE_QSFP28_SR4, /* QSFP28-SR4 type */
+ PORT_TYPE_QSFP28_LR4, /* QSFP28-LR4 type */
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ PORT_TYPE_QSFP_PLUS_4X10,
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ PORT_TYPE_QSFP_PASSIVE_DAC_4X10,
+ PORT_TYPE_QSFP_PASSIVE_DAC =
+ PORT_TYPE_QSFP_PASSIVE_DAC_4X10, /* QSFP passive DAC type */
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ PORT_TYPE_QSFP_ACTIVE_DAC_4X10,
+ PORT_TYPE_QSFP_ACTIVE_DAC =
+ PORT_TYPE_QSFP_ACTIVE_DAC_4X10, /* QSFP active DAC type */
+ PORT_TYPE_SFP_28, /* SFP28 type */
+ PORT_TYPE_SFP_28_SR, /* SFP28-SR type */
+ PORT_TYPE_SFP_28_LR, /* SFP28-LR type */
+ PORT_TYPE_SFP_28_CR_CA_L, /* SFP28-CR-CA-L type */
+ PORT_TYPE_SFP_28_CR_CA_S, /* SFP28-CR-CA-S type */
+ PORT_TYPE_SFP_28_CR_CA_N, /* SFP28-CR-CA-N type */
+ PORT_TYPE_QSFP28_CR_CA_L, /* QSFP28-CR-CA-L type */
+ PORT_TYPE_QSFP28_CR_CA_S, /* QSFP28-CR-CA-S type */
+ PORT_TYPE_QSFP28_CR_CA_N, /* QSFP28-CR-CA-N type */
+ PORT_TYPE_SFP_28_SR_DR, /* SFP28-SR-DR type */
+ PORT_TYPE_SFP_28_LR_DR, /* SFP28-LR-DR type */
+ PORT_TYPE_SFP_FX, /* SFP FX */
+ PORT_TYPE_SFP_PLUS_CU, /* SFP+ CU type */
+ PORT_TYPE_QSFP28_FR, /* QSFP28-FR type. Uses PAM4 modulation on one lane only */
+ PORT_TYPE_QSFP28_DR, /* QSFP28-DR type. Uses PAM4 modulation on one lane only */
+ PORT_TYPE_QSFP28_LR, /* QSFP28-LR type. Uses PAM4 modulation on one lane only */
+};
+
+struct mac_addr_s {
+ uint8_t addr_b[6];
+};
+
+struct nim_link_length_s {
+ /* NIM link length (in meters) supported SM (9um). A value of 0xFFFF indicates that the
+ * length is >= 65535 m
+ */
+ uint16_t sm;
+ uint16_t ebw; /* NIM link length (in meters) supported EBW (50um) */
+ uint16_t mm50; /* NIM link length (in meters) supported MM (50um) */
+ uint16_t mm62; /* NIM link length (in meters) supported MM (62.5um) */
+ uint16_t copper; /* NIM link length (in meters) supported copper */
+};
+
+struct nim_data_s {
+ uint8_t nim_id;
+ uint8_t port_type;
+ char vendor_name[17];
+ char prod_no[17];
+ char serial_no[17];
+ char date[9];
+ char rev[5];
+ uint8_t pwr_level_req;
+ uint8_t pwr_level_cur;
+ struct nim_link_length_s link_length;
+};
+
+struct sensor {
+ uint8_t sign;
+ uint8_t type;
+ uint32_t current_value;
+ uint32_t min_value;
+ uint32_t max_value;
+ char name[50];
+};
+
+struct ntc_sensors_s {
+ uint16_t adapter_sensors_cnt;
+ uint16_t ports_cnt;
+ uint16_t nim_sensors_cnt[8];
+ char adapter_name[24];
+};
+
+#define MAX_RSS_QUEUES 128
+
+enum queue_dir_e { QUEUE_INPUT, QUEUE_OUTPUT };
+
+struct queue_s {
+ enum queue_dir_e dir;
+ int idx;
+};
+
+struct ntc_interface_s {
+ uint8_t port_id;
+ enum port_type type;
+ enum port_link link;
+ enum port_states port_state;
+ enum port_speed port_speed;
+ struct pci_id_s pci_id;
+ struct mac_addr_s mac;
+ struct nim_data_s nim_data;
+ uint16_t mtu;
+ /* attached queues */
+ struct {
+ struct queue_s queue[MAX_RSS_QUEUES];
+ int num_queues;
+ };
+};
+
+/*
+ * adapter get,interfaces
+ */
+struct ntc_interfaces_s {
+ int final_list;
+ uint8_t nb_ports;
+ struct ntc_interface_s intf[];
+};
+
+/*
+ * adapter get,info
+ */
+struct ntc_adap_get_info_s {
+ char *fw_version[32];
+};
+
+#endif /* _NTCONNECT_API_ADAPTER_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h
new file mode 100644
index 0000000000..4091d61d7d
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_flow.h
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_API_FILTER_H_
+#define _NTCONNECT_API_FILTER_H_
+
+#include "stream_binary_flow_api.h"
+
+/*
+ * Create structures allocating the space to carry through ntconnect interface
+ */
+#define MAX_FLOW_STREAM_ELEM 16
+#define MAX_FLOW_STREAM_QUERY_DATA 1024
+#define MAX_FLOW_STREAM_ERROR_MSG 128
+#define MAX_FLOW_STREAM_VXLAN_TUN_ELEM 8
+#define MAX_FLOW_STREAM_COUNT_ACTIONS 4
+
+#define MAX_PATH_LEN 128
+
+enum ntconn_flow_err_e {
+ NTCONN_FLOW_ERR_NONE = 0,
+ NTCONN_FLOW_ERR_INTERNAL_ERROR = 0x100,
+ NTCONN_FLOW_ERR_PORT_IS_NOT_INITIALIZED,
+ NTCONN_FLOW_ERR_INVALID_PORT,
+ NTCONN_FLOW_ERR_UNEXPECTED_VIRTIO_PATH,
+ NTCONN_FLOW_ERR_UNSUPPORTED_ADAPTER,
+ NTCONN_FLOW_ERR_TO_MANY_FLOWS,
+ NTCONN_FLOW_ERR_NOT_YET_IMPLEMENTED,
+ NTCONN_FLOW_ERR_NO_VF_QUEUES,
+};
+
+struct flow_elem_types_s {
+ int valid;
+ union {
+ int start_addr;
+ struct flow_elem_eth eth;
+ struct flow_elem_vlan vlan[2];
+ struct flow_elem_ipv4 ipv4;
+ struct flow_elem_ipv6 ipv6;
+ struct flow_elem_sctp sctp;
+ struct flow_elem_tcp tcp;
+ struct flow_elem_udp udp;
+ struct flow_elem_icmp icmp;
+ struct flow_elem_vxlan vxlan;
+ struct flow_elem_port_id port_id;
+ struct flow_elem_tag tag;
+ } u;
+};
+
+struct flow_elem_cpy {
+ enum flow_elem_type type; /* element type */
+ struct flow_elem_types_s spec_cpy;
+ struct flow_elem_types_s mask_cpy;
+};
+
+struct flow_action_vxlan_encap_cpy {
+ /* Encapsulating vxlan tunnel definition */
+ struct flow_elem_cpy vxlan_tunnel[MAX_FLOW_STREAM_VXLAN_TUN_ELEM];
+};
+
+struct flow_action_rss_cpy {
+ struct flow_action_rss rss;
+ uint16_t cpy_queue[FLOW_MAX_QUEUES];
+};
+
+#define MAX_ACTION_ENCAP_DATA 512
+struct flow_action_decap_cpy {
+ uint8_t data[MAX_ACTION_ENCAP_DATA];
+ size_t size;
+ struct flow_elem_cpy item_cpy
+ [RAW_ENCAP_DECAP_ELEMS_MAX]; /* Need room for end command */
+ int item_count;
+};
+
+struct flow_action_encap_cpy {
+ uint8_t data[MAX_ACTION_ENCAP_DATA];
+ size_t size;
+ struct flow_elem_cpy item_cpy
+ [RAW_ENCAP_DECAP_ELEMS_MAX]; /* Need room for end command */
+ int item_count;
+};
+
+struct flow_action_types_s {
+ int valid;
+ union {
+ int start_addr;
+ struct flow_action_rss_cpy rss;
+ struct flow_action_push_vlan vlan;
+ struct flow_action_set_vlan_vid vlan_vid;
+ struct flow_action_vxlan_encap_cpy vxlan;
+ struct flow_action_count count;
+ struct flow_action_mark mark;
+ struct flow_action_port_id port_id;
+ struct flow_action_tag tag;
+ struct flow_action_queue queue;
+ struct flow_action_decap_cpy decap;
+ struct flow_action_encap_cpy encap;
+ struct flow_action_jump jump;
+ struct flow_action_meter meter;
+ } u;
+};
+
+struct flow_action_cpy {
+ enum flow_action_type type;
+ struct flow_action_types_s conf_cpy;
+};
+
+struct query_flow_ntconnect {
+ uint8_t port;
+ struct flow_action_cpy action;
+ uint64_t flow;
+};
+
+struct create_flow_ntconnect {
+ uint8_t port;
+ uint8_t vport;
+ struct flow_attr attr;
+ struct flow_elem_cpy elem[MAX_FLOW_STREAM_ELEM];
+ struct flow_action_cpy action[MAX_FLOW_STREAM_ELEM];
+};
+
+struct destroy_flow_ntconnect {
+ uint8_t port;
+ uint64_t flow;
+};
+
+#define ERR_MSG_LEN 128LLU
+
+struct flow_setport_return {
+ struct flow_queue_id_s queues[FLOW_MAX_QUEUES];
+ uint8_t num_queues;
+};
+
+struct flow_error_return_s {
+ enum flow_error_e type;
+ char err_msg[ERR_MSG_LEN];
+ int status;
+};
+
+struct create_flow_return_s {
+ uint64_t flow;
+};
+
+struct validate_flow_return_s {
+ int status;
+};
+
+struct query_flow_return_s {
+ enum flow_error_e type;
+ char err_msg[ERR_MSG_LEN];
+ int status;
+ uint32_t data_length;
+ uint8_t data[];
+};
+
+struct flow_return_s {
+ enum flow_error_e type;
+ char err_msg[ERR_MSG_LEN];
+ int status;
+};
+
+struct flow_error_ntconn {
+ enum flow_error_e type;
+ char message[ERR_MSG_LEN];
+};
+
+#endif /* _NTCONNECT_API_FILTER_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h
new file mode 100644
index 0000000000..901b0ccba1
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_meter.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_METER_FILTER_H_
+#define _NTCONNECT_METER_FILTER_H_
+
+#define FLOW_COOKIE 0x12344321
+
+/*
+ * Create structures allocating the space to carry through ntconnect interface
+ */
+
+#define MAX_PATH_LEN 128
+
+enum ntconn_meter_err_e {
+ NTCONN_METER_ERR_NONE = 0,
+ NTCONN_METER_ERR_INTERNAL_ERROR = 0x100,
+ NTCONN_METER_ERR_INVALID_PORT,
+ NTCONN_METER_ERR_UNEXPECTED_VIRTIO_PATH,
+ NTCONN_METER_ERR_PROFILE_ID,
+ NTCONN_METER_ERR_POLICY_ID,
+ NTCONN_METER_ERR_METER_ID,
+};
+
+enum ntconn_meter_command_e {
+ UNKNOWN_CMD,
+ ADD_PROFILE,
+ DEL_PROFILE,
+ ADD_POLICY,
+ DEL_POLICY,
+ CREATE_MTR,
+ DEL_MTR
+};
+
+#define ERR_MSG_LEN 128LLU
+
+struct meter_error_return_s {
+ enum rte_mtr_error_type type;
+ int status;
+ char err_msg[ERR_MSG_LEN];
+};
+
+struct meter_setup_s {
+ uint8_t vport;
+ uint32_t id;
+ int shared;
+ union {
+ struct rte_mtr_meter_profile profile;
+ struct {
+ struct rte_mtr_meter_policy_params policy;
+ struct rte_flow_action actions_green[2];
+ struct rte_flow_action actions_yellow[2];
+ struct rte_flow_action actions_red[2];
+ } p;
+ struct rte_mtr_params mtr_params;
+ };
+};
+
+struct meter_get_stat_s {
+ uint8_t vport;
+ uint32_t mtr_id;
+ int clear;
+};
+
+struct meter_return_stat_s {
+ struct rte_mtr_stats stats;
+ uint64_t stats_mask;
+};
+
+struct meter_setup_ptr_s {
+ uint32_t id;
+ int shared;
+ union {
+ struct rte_mtr_meter_profile *profile;
+ struct rte_mtr_meter_policy_params *policy;
+ struct rte_mtr_params *mtr_params;
+ };
+};
+
+struct meter_return_s {
+ int status;
+};
+
+struct meter_capabilities_return_s {
+ struct rte_mtr_capabilities cap;
+};
+
+#endif /* _NTCONNECT_METER_FILTER_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h
new file mode 100644
index 0000000000..1022bc2056
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_statistic.h
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_API_STATISTIC_H_
+#define _NTCONNECT_API_STATISTIC_H_
+
+/*
+ * Supported defined statistic records for Stat layout version 6 - defined in nthw_stat module
+ */
+#define NUM_STAT_RECORD_TYPE_COLOR \
+ (sizeof(struct color_type_fields_s) / sizeof(uint64_t))
+struct color_type_fields_s {
+ uint64_t pkts;
+ uint64_t octets;
+ uint64_t tcp_flgs;
+};
+
+#define NUM_STAT_RECORD_TYPE_FLOWMATCHER \
+ (sizeof(struct flowmatcher_type_fields_s) / sizeof(uint64_t))
+struct flowmatcher_type_fields_s {
+ /* FLM 0.17 */
+ uint64_t current;
+ uint64_t learn_done;
+ uint64_t learn_ignore;
+ uint64_t learn_fail;
+ uint64_t unlearn_done;
+ uint64_t unlearn_ignore;
+ uint64_t auto_unlearn_done;
+ uint64_t auto_unlearn_ignore;
+ uint64_t auto_unlearn_fail;
+ uint64_t timeout_unlearn_done;
+ uint64_t rel_done;
+ uint64_t rel_ignore;
+ uint64_t prb_done;
+ uint64_t prb_ignore;
+ /* FLM 0.20 */
+ uint64_t sta_done;
+ uint64_t inf_done;
+ uint64_t inf_skip;
+ uint64_t pck_hit;
+ uint64_t pck_miss;
+ uint64_t pck_unh;
+ uint64_t pck_dis;
+ uint64_t csh_hit;
+ uint64_t csh_miss;
+ uint64_t csh_unh;
+ uint64_t cuc_start;
+ uint64_t cuc_move;
+};
+
+#define NUM_STAT_RECORD_TYPE_QUEUE \
+ (sizeof(struct queue_type_fields_s) / sizeof(uint64_t))
+struct queue_type_fields_s {
+ uint64_t flush_pkts;
+ uint64_t drop_pkts;
+ uint64_t fwd_pkts;
+ uint64_t dbs_drop_pkts;
+ uint64_t flush_octets;
+ uint64_t drop_octets;
+ uint64_t fwd_octets;
+ uint64_t dbs_drop_octets;
+};
+
+/*
+ * Port stat counters for virtualization NICS with virtual ports support
+ */
+#define NUM_STAT_RECORD_TYPE_RX_PORT_VIRT \
+ (sizeof(struct rtx_type_fields_virt_s) / sizeof(uint64_t))
+/* same for Rx and Tx counters on Virt */
+#define NUM_STAT_RECORD_TYPE_TX_PORT_VIRT NUM_STAT_RECORD_TYPE_RX_PORT_VIRT
+struct rtx_type_fields_virt_s {
+ uint64_t octets;
+ uint64_t pkts;
+ uint64_t drop_events;
+ uint64_t qos_drop_octets;
+ uint64_t qos_drop_pkts;
+};
+
+/*
+ * Port RMON counters for Cap devices
+ */
+struct stat_rmon_s {
+ /* Sums that are calculated by software */
+ uint64_t drop_events;
+ uint64_t pkts;
+ /* Read from FPGA */
+ uint64_t octets;
+ uint64_t broadcast_pkts;
+ uint64_t multicast_pkts;
+ uint64_t unicast_pkts;
+ uint64_t pkts_alignment;
+ uint64_t pkts_code_violation;
+ uint64_t pkts_crc;
+ uint64_t undersize_pkts;
+ uint64_t oversize_pkts;
+ uint64_t fragments;
+ uint64_t jabbers_not_truncated;
+ uint64_t jabbers_truncated;
+ uint64_t pkts_64_octets;
+ uint64_t pkts_65_to_127_octets;
+ uint64_t pkts_128_to_255_octets;
+ uint64_t pkts_256_to_511_octets;
+ uint64_t pkts_512_to_1023_octets;
+ uint64_t pkts_1024_to_1518_octets;
+ uint64_t pkts_1519_to_2047_octets;
+ uint64_t pkts_2048_to_4095_octets;
+ uint64_t pkts_4096_to_8191_octets;
+ uint64_t pkts_8192_to_max_octets;
+};
+
+#define NUM_STAT_RECORD_TYPE_RX_PORT_CAP \
+ (sizeof(struct rx_type_fields_cap_s) / sizeof(uint64_t))
+struct rx_type_fields_cap_s {
+ struct stat_rmon_s rmon;
+ uint64_t mac_drop_events;
+ uint64_t pkts_lr;
+ /* Rx only port counters */
+ uint64_t duplicate;
+ uint64_t pkts_ip_chksum_error;
+ uint64_t pkts_udp_chksum_error;
+ uint64_t pkts_tcp_chksum_error;
+ uint64_t pkts_giant_undersize;
+ uint64_t pkts_baby_giant;
+ uint64_t pkts_not_isl_vlan_mpls;
+ uint64_t pkts_isl;
+ uint64_t pkts_vlan;
+ uint64_t pkts_isl_vlan;
+ uint64_t pkts_mpls;
+ uint64_t pkts_isl_mpls;
+ uint64_t pkts_vlan_mpls;
+ uint64_t pkts_isl_vlan_mpls;
+ uint64_t pkts_no_filter;
+ uint64_t pkts_dedup_drop;
+ uint64_t pkts_filter_drop;
+ uint64_t pkts_overflow;
+ uint64_t pkts_dbs_drop;
+ uint64_t octets_no_filter;
+ uint64_t octets_dedup_drop;
+ uint64_t octets_filter_drop;
+ uint64_t octets_overflow;
+ uint64_t octets_dbs_drop;
+ uint64_t ipft_first_hit;
+ uint64_t ipft_first_not_hit;
+ uint64_t ipft_mid_hit;
+ uint64_t ipft_mid_not_hit;
+ uint64_t ipft_last_hit;
+ uint64_t ipft_last_not_hit;
+};
+
+#define NUM_STAT_RECORD_TYPE_TX_PORT_CAP \
+ (sizeof(struct tx_type_fields_cap_s) / sizeof(uint64_t))
+struct tx_type_fields_cap_s {
+ struct stat_rmon_s rmon;
+};
+
+/*
+ * stat get,colors
+ * stat get,queues
+ * stat get,rx_counters
+ * stat get,tx_counters
+ */
+#define STAT_INFO_ELEMENTS \
+ (sizeof(struct ntc_stat_get_data_s) / sizeof(uint64_t))
+
+struct ntc_stat_get_data_s {
+ uint64_t nb_counters;
+ uint64_t timestamp;
+ uint64_t is_virt;
+ uint64_t data[];
+};
+
+#endif /* _NTCONNECT_API_STATISTIC_H_ */
diff --git a/drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h b/drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h
new file mode 100644
index 0000000000..44cacbd931
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/include/ntconnect_api_test.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONNECT_TEST_FILTER_H_
+#define _NTCONNECT_TEST_FILTER_H_
+
+/*
+ * Create structures allocating the space to carry through ntconnect interface
+ */
+
+struct test_s {
+ int number;
+ int status;
+ uint64_t test[];
+};
+
+#endif /* _NTCONNECT_TEST_FILTER_H_ */
diff --git a/drivers/net/ntnic/ntconnect/ntconn_server.c b/drivers/net/ntnic/ntconnect/ntconn_server.c
new file mode 100644
index 0000000000..34a3c19955
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/ntconn_server.c
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ntconnect.h"
+#include "ntconn_mod_helper.h"
+#include "nt_util.h"
+#include "ntlog.h"
+
+/*
+ * Server module always registered on 0000:00:00.0
+ */
+#define this_module_name "server"
+
+#define NTCONNECT_SERVER_VERSION_MAJOR 0U
+#define NTCONNECT_SERVER_VERSION_MINOR 1U
+
+static int func_get_nic_pci(void *hdl, int client_fd,
+ struct ntconn_header_s *hdr, char **data, int *len);
+static struct func_s funcs_get_level1[] = {
+ { "nic_pci_ids", NULL, func_get_nic_pci },
+ { NULL, NULL, NULL },
+};
+
+/*
+ * Entry level
+ */
+static struct func_s server_entry_funcs[] = {
+ { "get", funcs_get_level1, NULL },
+ { NULL, NULL, NULL },
+};
+
+static int func_get_nic_pci(void *hdl, int client_fd _unused,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ struct ntconn_server_s *serv = (struct ntconn_server_s *)hdl;
+ struct ntc_nic_pci_ids_s *npci =
+ calloc(1, sizeof(struct ntc_nic_pci_ids_s));
+ if (!npci) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+ int i = 0;
+
+ while (i < MAX_PCI_IDS && serv->pci_id_list[i].pci_id) {
+ sprintf(npci->nic_pci_id[i], "%04x:%02x:%02x.%x",
+ serv->pci_id_list[i].domain & 0xffff,
+ serv->pci_id_list[i].bus, serv->pci_id_list[i].devid,
+ serv->pci_id_list[i].function);
+ i++;
+ }
+ npci->num_nics = i;
+ *data = (char *)npci;
+ *len = sizeof(struct ntc_nic_pci_ids_s);
+
+ return REQUEST_OK;
+}
+
+static int ntconn_server_request(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char *function,
+ char **data, int *len)
+{
+ return execute_function(this_module_name, hdl, client_id, hdr, function,
+ server_entry_funcs, data, len, 0);
+}
+
+static void ntconn_server_free_data(void *hdl _unused, char *data)
+{
+ if (data) {
+#ifdef DEBUG
+ NT_LOG(DBG, NTCONNECT, "server free data\n");
+#endif
+ free(data);
+ }
+}
+
+static const ntconnapi_t ntconn_server_op = { this_module_name,
+ NTCONNECT_SERVER_VERSION_MAJOR,
+ NTCONNECT_SERVER_VERSION_MINOR,
+ ntconn_server_request,
+ ntconn_server_free_data,
+ NULL
+ };
+
+int ntconn_server_register(void *server)
+{
+ const struct rte_pci_addr addr = {
+ .domain = 0, .bus = 0, .devid = 0, .function = 0
+ };
+
+ return register_ntconn_mod(&addr, server, &ntconn_server_op);
+}
diff --git a/drivers/net/ntnic/ntconnect/ntconnect.c b/drivers/net/ntnic/ntconnect/ntconnect.c
new file mode 100644
index 0000000000..51f0577194
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect/ntconnect.c
@@ -0,0 +1,641 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "nt_util.h"
+#include "ntconnect.h"
+#include "ntconnect_api.h"
+#include "ntlog.h"
+
+/* clang-format off */
+ntconn_err_t ntconn_err[] = {
+ {NTCONN_ERR_CODE_NONE, "Success"},
+ {NTCONN_ERR_CODE_INTERNAL_ERROR, "Internal error"},
+ {NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR, "Internal error in reply from module"},
+ {NTCONN_ERR_CODE_NO_DATA, "No data found"},
+ {NTCONN_ERR_CODE_INVALID_REQUEST, "Invalid request"},
+ {NTCONN_ERR_CODE_NOT_YET_IMPLEMENTED, "Function not yet implemented"},
+ {NTCONN_ERR_CODE_INTERNAL_FUNC_ERROR, "Internal error in function call list"},
+ {NTCONN_ERR_CODE_MISSING_INVALID_PARAM, "Missing or invalid parameter"},
+ {NTCONN_ERR_CODE_FUNCTION_PARAM_INCOMPLETE, "Function parameter is incomplete"},
+ {NTCONN_ERR_CODE_FUNC_PARAM_NOT_RECOGNIZED,
+ "Function or parameter not recognized/supported"},
+ {-1, NULL}
+};
+
+/* clang-format on */
+
+static ntconn_mod_t *ntcmod_base;
+static pthread_t tid;
+static pthread_t ctid;
+static struct ntconn_server_s ntconn_serv;
+
+const ntconn_err_t *get_ntconn_error(enum ntconn_err_e err_code)
+{
+ int idx = 0;
+
+ while (ntconn_err[idx].err_code != (uint32_t)-1 &&
+ ntconn_err[idx].err_code != err_code)
+ idx++;
+ if (ntconn_err[idx].err_code == (uint32_t)-1)
+ idx = 1;
+
+ return &ntconn_err[idx];
+}
+
+int register_ntconn_mod(const struct rte_pci_addr *addr, void *hdl,
+ const ntconnapi_t *op)
+{
+ /* Verify and check module name is unique */
+#ifdef DEBUG
+ NT_LOG(DBG, NTCONNECT,
+ "Registering pci: %04x:%02x:%02x.%x, module %s\n", addr->domain,
+ addr->bus, addr->devid, addr->function, op->module);
+#endif
+
+ ntconn_mod_t *ntcmod = (ntconn_mod_t *)malloc(sizeof(ntconn_mod_t));
+
+ if (!ntcmod) {
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return -1;
+ }
+ ntcmod->addr.domain = addr->domain;
+ ntcmod->addr.bus = addr->bus;
+ ntcmod->addr.devid = addr->devid;
+ ntcmod->addr.function = addr->function;
+ ntcmod->addr.pad = 0;
+
+ ntcmod->hdl = hdl;
+ ntcmod->op = op;
+ pthread_mutex_init(&ntcmod->mutex, NULL);
+
+ ntcmod->next = ntcmod_base;
+ ntcmod_base = ntcmod;
+
+ if (ntcmod->addr.pci_id) { /* Avoid server fake pci_id */
+ int i;
+
+ for (i = 0; i < MAX_PCI_IDS; i++) {
+ if (ntconn_serv.pci_id_list[i].pci_id == 0) {
+ NT_LOG(DBG, NTCONNECT,
+ "insert at index %i PCI ID %" PRIX64 "\n", i,
+ ntcmod->addr.pci_id);
+ ntconn_serv.pci_id_list[i].pci_id =
+ ntcmod->addr.pci_id;
+ break;
+ } else if (ntconn_serv.pci_id_list[i].pci_id ==
+ ntcmod->addr.pci_id)
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int unix_build_address(const char *path, struct sockaddr_un *addr)
+{
+ if (addr == NULL || path == NULL)
+ return -1;
+ memset(addr, 0, sizeof(struct sockaddr_un));
+ addr->sun_family = AF_UNIX;
+ if (strlen(path) < sizeof(addr->sun_path)) {
+ rte_strscpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
+ return 0;
+ }
+ return -1;
+}
+
+#define STATUS_OK 0
+#define STATUS_INTERNAL_ERROR -1
+#define STATUS_TRYAGAIN -2
+#define STATUS_INVALID_PARAMETER -3
+#define STATUS_CONNECTION_CLOSED -4
+#define STATUS_CONNECTION_INVALID -5
+#define STATUS_TIMEOUT -6
+
+static int read_data(int fd, size_t len, uint8_t *data, size_t *recv_len,
+ int timeout)
+{
+ struct pollfd pfd;
+ ssize_t ret;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ ret = poll(&pfd, 1, timeout);
+ if (ret < 0) {
+ if (errno == EINTR)
+ return STATUS_TRYAGAIN; /* Caught signal before timeout */
+ if (errno == EINVAL)
+ return STATUS_INVALID_PARAMETER; /* Timeout is negative */
+ if (errno == EFAULT)
+ return STATUS_INVALID_PARAMETER; /* Fds argument is illegal */
+ /* else */
+ assert(0);
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ if (ret == 0)
+ return STATUS_TIMEOUT;
+
+ if (pfd.revents == 0) {
+ assert(ret == 1);
+ assert(0); /* Revents cannot be zero when NtSocket_Poll returns 1 */
+ return STATUS_TRYAGAIN;
+ }
+
+ if ((pfd.revents & POLLIN) &&
+ ((pfd.revents & (POLLERR | POLLNVAL)) == 0)) {
+ ret = recv(pfd.fd, data, len, 0);
+ if (ret < 0) {
+ int lerrno = errno;
+
+ if (lerrno == EWOULDBLOCK || lerrno == EAGAIN) {
+ /*
+ * We have data but if the very first read turns out to return
+ * EWOULDBLOCK or EAGAIN it means that the remote end has dropped
+ * the connection
+ */
+ NT_LOG(DBG, NTCONNECT,
+ "The socket with fd %d has been closed by remote end. %d [%s]\n",
+ pfd.fd, lerrno, strerror(lerrno));
+ return STATUS_CONNECTION_CLOSED;
+ }
+ if (lerrno != EINTR) {
+ NT_LOG(ERR, NTCONNECT,
+ "recv() from fd %d received errno %d [%s]\n",
+ pfd.fd, lerrno, strerror(lerrno));
+ return STATUS_CONNECTION_INVALID;
+ }
+ /* EINTR */
+ return STATUS_TRYAGAIN;
+ }
+ if (ret == 0) {
+ if (pfd.revents & POLLHUP) {
+ /* This means that we have read all data and the remote end has
+ * HUP
+ */
+#ifdef DEBUG
+ NT_LOG(DBG, NTCONNECT,
+ "The remote end has terminated the session\n");
+#endif
+ return STATUS_CONNECTION_CLOSED;
+ }
+ return STATUS_TRYAGAIN;
+ }
+
+ /* Ret can only be positive at this point */
+ *recv_len = (size_t)ret;
+ return STATUS_OK;
+ }
+
+ if ((pfd.revents & POLLHUP) == POLLHUP) {
+ /* this means that the remote end has HUP */
+ NT_LOG(DBG, NTCONNECT,
+ "The remote end has terminated the session\n");
+ return STATUS_CONNECTION_CLOSED;
+ }
+
+ NT_LOG(ERR, NTCONNECT,
+ "poll() returned 0x%x. Invalidating the connection\n",
+ pfd.revents);
+ return STATUS_CONNECTION_INVALID;
+}
+
+static int read_all(int clfd, uint8_t *data, size_t length)
+{
+ size_t recv_len = 0;
+ size_t left = length;
+ size_t pos = 0;
+
+ while (left > 0) {
+ int ret = read_data(clfd, left, &data[pos], &recv_len, -1);
+
+ if (ret == STATUS_OK) {
+ pos += recv_len;
+ left -= recv_len;
+ } else {
+ if (ret == STATUS_CONNECTION_CLOSED || ret == STATUS_TIMEOUT) {
+ /* Silently return status */
+ return ret;
+ }
+ if (ret != STATUS_TRYAGAIN) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed getting packet. Error code: 0x%X\n",
+ ret);
+ return ret;
+ }
+ }
+ /* Try again */
+ }
+ return STATUS_OK;
+}
+
+static int write_all(int fd, const uint8_t *data, size_t size)
+{
+ size_t len = 0;
+
+ while (len < size) {
+ ssize_t res = write(fd, (const void *)&data[len], size - len);
+
+ if (res < 0) {
+ NT_LOG(ERR, NTCONNECT, "write to socket failed!");
+ return STATUS_INTERNAL_ERROR;
+ }
+ len += res;
+ }
+ return 0;
+}
+
+static int read_request(int clfd, char **rdata)
+{
+ uint8_t *data = malloc(MESSAGE_BUFFER * sizeof(uint8_t));
+
+ if (!data) {
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ size_t recv_len = 0;
+ int ret = read_data(clfd, MESSAGE_BUFFER, data, &recv_len, -1);
+
+ if (ret) {
+ free(data);
+ return ret;
+ }
+
+ struct ntconn_header_s hdr;
+
+ memcpy(&hdr, data, NTCMOD_HDR_LEN);
+ size_t length = (hdr.len + hdr.blob_len) * sizeof(uint8_t);
+
+ if (length > MESSAGE_BUFFER) {
+ uint8_t *new_data = realloc(data, length);
+
+ if (!new_data) {
+ NT_LOG(ERR, NTCONNECT, "memory reallocation failed");
+ free(data);
+ return STATUS_INTERNAL_ERROR;
+ }
+ data = new_data;
+ ret = read_all(clfd, &data[recv_len], length - recv_len);
+ if (ret) {
+ free(data);
+ return ret;
+ }
+ }
+
+ *rdata = (char *)data;
+ return STATUS_OK;
+}
+
+static ntconn_mod_t *ntconnect_interpret_request(int clfd,
+ struct ntconn_header_s *hdr,
+ char **get_req _unused,
+ char **module_cmd, int *status)
+{
+ char pci_id[32];
+ char module[64];
+ ntconn_mod_t *result_ntcmod = NULL;
+ char *request = NULL;
+
+ int ret = read_request(clfd, &request);
+ *status = ret;
+ *get_req = request;
+
+ if (ret == STATUS_OK && request) {
+ *hdr = *(struct ntconn_header_s *)request;
+
+ if (!hdr) {
+ NT_LOG(ERR, NTCONNECT, "hdr returned NULL\n");
+ *status = STATUS_INTERNAL_ERROR;
+ return NULL;
+ }
+
+ switch (hdr->tag) {
+ case NTCONN_TAG_REQUEST: {
+ unsigned long idx = NTCMOD_HDR_LEN;
+ char *saveptr;
+ char *req = &request[idx];
+
+ uint32_t domain = 0xffffffff;
+ uint8_t bus = 0xff;
+ uint8_t devid = 0xff;
+ uint8_t function = 0xff;
+
+ char *tok = strtok_r(req, ";", &saveptr);
+
+ idx += strlen(tok) + 1;
+ if (!tok)
+ goto err_out;
+ rte_strscpy(pci_id, tok, 31);
+
+ tok = strtok_r(NULL, ";", &saveptr);
+ idx += strlen(tok) + 1;
+ if (!tok)
+ goto err_out;
+ rte_strscpy(module, tok, 63);
+
+ tok = strtok_r(NULL, "", &saveptr);
+ hdr->len -= idx;
+ if (tok)
+ *module_cmd = &request[idx];
+
+ tok = strtok_r(pci_id, ":.", &saveptr);
+ if (!tok)
+ goto err_out;
+ domain = (uint32_t)strtol(tok, NULL, 16);
+ tok = strtok_r(NULL, ":.", &saveptr);
+ if (!tok)
+ goto err_out;
+ bus = (uint8_t)strtol(tok, NULL, 16);
+
+ tok = strtok_r(NULL, ":.", &saveptr);
+ if (!tok)
+ goto err_out;
+ devid = (uint8_t)strtol(tok, NULL, 16);
+ tok = strtok_r(NULL, "", &saveptr);
+ if (!tok)
+ goto err_out;
+ function = (uint8_t)strtol(tok, NULL, 16);
+
+ /* Search for module registered as <pci_id:module> */
+ ntconn_mod_t *ntcmod = ntcmod_base;
+
+ while (ntcmod) {
+ if (domain == ntcmod->addr.domain &&
+ bus == ntcmod->addr.bus &&
+ devid == ntcmod->addr.devid &&
+ function == ntcmod->addr.function &&
+ strcmp(ntcmod->op->module, module) == 0) {
+ result_ntcmod = ntcmod;
+ break;
+ }
+ ntcmod = ntcmod->next;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+err_out:
+
+ return result_ntcmod;
+}
+
+static int send_reply(int clfd, uint16_t reply_tag, const void *data,
+ uint32_t size)
+{
+ struct ntconn_header_s hdr;
+
+ hdr.tag = reply_tag;
+ hdr.len = NTCMOD_HDR_LEN + size;
+ hdr.blob_len = 0;
+ uint8_t *message = malloc(hdr.len * sizeof(uint8_t));
+
+ if (!message) {
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return STATUS_INTERNAL_ERROR;
+ }
+ memcpy(message, (void *)&hdr, NTCMOD_HDR_LEN);
+ memcpy(&message[NTCMOD_HDR_LEN], data, size);
+ int res = write_all(clfd, message, hdr.len);
+
+ free(message);
+ if (res)
+ return res;
+
+ return 0;
+}
+
+static int send_reply_free_data(int clfd, ntconn_mod_t *cmod,
+ uint16_t reply_tag, void *data, uint32_t size)
+{
+ int res = send_reply(clfd, reply_tag, data, size);
+
+ if (size) {
+ pthread_mutex_lock(&cmod->mutex);
+ cmod->op->free_data(cmod->hdl, data);
+ pthread_mutex_unlock(&cmod->mutex);
+ }
+
+ return res;
+}
+
+static int ntconnect_send_error(int clfd, enum ntconn_err_e err_code)
+{
+ char err_buf[MAX_ERR_MESSAGE_LENGTH];
+ const ntconn_err_t *ntcerr = get_ntconn_error(err_code);
+
+ sprintf(err_buf, "----connect:%s", ntcerr->err_text);
+ unsigned int len = strlen(err_buf);
+ *(uint32_t *)err_buf = (uint32_t)ntcerr->err_code;
+
+ return send_reply(clfd, NTCONN_TAG_ERROR, err_buf, len);
+}
+
+static void *ntconnect_worker(void *arg)
+{
+ int status;
+ int clfd = (int)(uint64_t)arg;
+ char *module_cmd = NULL;
+ char *request = NULL;
+ struct ntconn_header_s hdr;
+
+ do {
+ ntconn_mod_t *cmod = ntconnect_interpret_request(clfd, &hdr,
+ &request,
+ &module_cmd,
+ &status);
+
+ if (cmod && module_cmd && status == 0) {
+ int len;
+ char *data;
+
+ /*
+ * Handle general module commands
+ */
+ if (strcmp(module_cmd, "version") == 0) {
+ uint64_t version =
+ ((uint64_t)cmod->op->version_major
+ << 32) +
+ (cmod->op->version_minor);
+
+ if (send_reply(clfd, NTCONN_TAG_REPLY,
+ (void *)&version,
+ sizeof(uint64_t)))
+ break;
+
+ } else {
+ /*
+ * Call module for execution of command
+ */
+ data = NULL;
+ pthread_mutex_lock(&cmod->mutex);
+ int repl = cmod->op->request(cmod->hdl, clfd,
+ &hdr, module_cmd,
+ &data, &len);
+ pthread_mutex_unlock(&cmod->mutex);
+
+ if (repl == REQUEST_OK && len >= 0) {
+ if (send_reply_free_data(clfd, cmod,
+ NTCONN_TAG_REPLY,
+ (void *)data,
+ (uint32_t)len))
+ break;
+
+ } else if (repl == REQUEST_ERR && len >= 0) {
+ if (send_reply_free_data(clfd, cmod,
+ NTCONN_TAG_ERROR,
+ (void *)data,
+ (uint32_t)len))
+ break;
+ } else {
+ NT_LOG(ERR, NTCONNECT,
+ "Invalid result from module request function: module %s, result %i\n",
+ cmod->op->module, repl);
+ if (ntconnect_send_error(clfd,
+ NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR))
+ break;
+ }
+ }
+
+ } else if (status == STATUS_TIMEOUT) {
+ /* Other end is dead */
+ NT_LOG(WRN, NTCONNECT,
+ "Client must be dead - timeout\n");
+ break;
+ } else if (status == STATUS_CONNECTION_CLOSED) {
+ break; /* silently break out */
+ }
+ /* Error - send error back */
+ if (ntconnect_send_error(clfd, NTCONN_ERR_CODE_INVALID_REQUEST))
+ break;
+ if (request)
+ free(request);
+ } while (1); /* while still connected */
+
+ close(clfd);
+
+ /* call module cleanup callback function for client_id */
+ ntconn_mod_t *ntcmod = ntcmod_base;
+
+ while (ntcmod) {
+ if (ntcmod->op->client_cleanup) {
+ pthread_mutex_lock(&ntcmod->mutex);
+ ntcmod->op->client_cleanup(ntcmod->hdl, clfd);
+ pthread_mutex_unlock(&ntcmod->mutex);
+ }
+
+ ntcmod = ntcmod->next;
+ }
+ pthread_exit(NULL);
+ return NULL;
+}
+
+static void *ntconnect_server(void *arg)
+{
+ struct ntconn_server_s *ntcserv = (struct ntconn_server_s *)arg;
+
+ ntcserv->running = 1;
+
+#ifdef DEBUG
+ NT_LOG(DBG, NTCONNECT, "Running NT Connection Server fd %i\n",
+ ntcserv->serv_fd);
+#endif
+
+ if (listen(ntcserv->serv_fd, 5) < 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Server failed on listen(), stopping thread. err: %s\n",
+ strerror(errno));
+ pthread_exit(NULL);
+ return NULL;
+ }
+
+ while (ntcserv->running) {
+ int clfd = accept(ntcserv->serv_fd, NULL, NULL);
+
+ if (clfd < 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "ERROR from accept(), stopping thread. err: %s\n",
+ strerror(errno));
+ break;
+ }
+ pthread_create(&ctid, NULL, ntconnect_worker,
+ (void *)(uint64_t)clfd);
+ pthread_setaffinity_np(ctid, sizeof(cpu_set_t),
+ &ntcserv->cpuset);
+ /* Detach immediately. We will never join this thread */
+ pthread_detach(ctid);
+ }
+
+ pthread_exit(NULL);
+ return NULL;
+}
+
+int ntconnect_init(const char *sockname, cpu_set_t cpuset)
+{
+ if (ntcmod_base) {
+ /* Make sure the socket directory exists */
+ char *sockname_copy = strdup(sockname);
+ char *sockname_dir = dirname(sockname_copy);
+
+ if (mkdir(sockname_dir, 0755) < 0 && errno != EEXIST) {
+ NT_LOG(ERR, NTCONNECT,
+ "Can't create socket directory: %s",
+ sockname_dir);
+ free(sockname_copy);
+ return -1;
+ }
+ free(sockname_copy);
+
+ /* Add server to module list - cannot work without */
+ ntconn_server_register(&ntconn_serv);
+
+ /* Start named socket server */
+ struct sockaddr_un addr;
+
+ unix_build_address(sockname, &addr);
+
+ ntconn_serv.serv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ ntconn_serv.cpuset = cpuset;
+ if (ntconn_serv.serv_fd == -1)
+ return -1;
+
+ /* Make sure the node in filesystem is deleted otherwise bind will fail */
+ unlink(sockname);
+
+ if (bind(ntconn_serv.serv_fd, (struct sockaddr *)&addr,
+ sizeof(struct sockaddr_un)) == -1) {
+ close(ntconn_serv.serv_fd);
+ return -1;
+ }
+
+ /* Run ntconnect service */
+ pthread_create(&tid, NULL, ntconnect_server, &ntconn_serv);
+ pthread_setaffinity_np(tid, sizeof(cpu_set_t),
+ &ntconn_serv.cpuset);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c b/drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c
new file mode 100644
index 0000000000..60753d6ef5
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect_modules/ntconn_adapter.c
@@ -0,0 +1,775 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntnic_ethdev.h"
+#include "ntconnect.h"
+#include "ntconnect_api_adapter.h"
+#include "ntos_system.h"
+#include "ntconn_modules.h"
+#include "ntconn_mod_helper.h"
+#include "nt_util.h"
+#include "ntlog.h"
+
+#define NTCONN_ADAP_VERSION_MAJOR 0U
+#define NTCONN_ADAP_VERSION_MINOR 1U
+
+#define this_module_name "adapter"
+
+#define MAX_ADAPTERS 2
+
+static struct adap_hdl_s {
+ struct drv_s *drv;
+} adap_hdl[MAX_ADAPTERS];
+
+static int func_adapter_get_interfaces(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_adapter_get_info(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_adapter_get_sensors(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len);
+static struct func_s funcs_get_level1[] = {
+ { "interfaces", NULL, func_adapter_get_interfaces },
+ { "info", NULL, func_adapter_get_info },
+ { "sensors", NULL, func_adapter_get_sensors },
+ { NULL, NULL, NULL },
+};
+
+static int func_adapter_set_interface(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_adapter_set_adapter(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static struct func_s funcs_set_level1[] = {
+ { "interface", NULL, func_adapter_set_interface },
+ { "adapter", NULL, func_adapter_set_adapter },
+ { NULL, NULL, NULL },
+};
+
+/*
+ * Entry level
+ */
+static struct func_s adapter_entry_funcs[] = {
+ { "get", funcs_get_level1, NULL },
+ { "set", funcs_set_level1, NULL },
+ { NULL, NULL, NULL },
+};
+
+static int read_link_speed(enum nt_link_speed_e link_speed)
+{
+ switch (link_speed) {
+ case NT_LINK_SPEED_10M:
+ return PORT_LINK_SPEED_10M;
+ case NT_LINK_SPEED_100M:
+ return PORT_LINK_SPEED_100M;
+ case NT_LINK_SPEED_1G:
+ return PORT_LINK_SPEED_1G;
+ case NT_LINK_SPEED_10G:
+ return PORT_LINK_SPEED_10G;
+ case NT_LINK_SPEED_25G:
+ return PORT_LINK_SPEED_25G;
+ case NT_LINK_SPEED_40G:
+ return PORT_LINK_SPEED_40G;
+ case NT_LINK_SPEED_50G:
+ return PORT_LINK_SPEED_50G;
+ case NT_LINK_SPEED_100G:
+ return PORT_LINK_SPEED_100G;
+ default:
+ break;
+ }
+ return PORT_LINK_SPEED_UNKNOWN;
+}
+
+static nt_link_speed_t convert_link_speed(char *speed_str)
+{
+ if (strcmp(speed_str, "10M") == 0)
+ return NT_LINK_SPEED_10M;
+ else if (strcmp(speed_str, "100M") == 0)
+ return NT_LINK_SPEED_100M;
+ else if (strcmp(speed_str, "1G") == 0)
+ return NT_LINK_SPEED_1G;
+ else if (strcmp(speed_str, "10G") == 0)
+ return NT_LINK_SPEED_10G;
+ else if (strcmp(speed_str, "25G") == 0)
+ return NT_LINK_SPEED_25G;
+ else if (strcmp(speed_str, "40G") == 0)
+ return NT_LINK_SPEED_40G;
+ else if (strcmp(speed_str, "50G") == 0)
+ return NT_LINK_SPEED_50G;
+ else if (strcmp(speed_str, "100G") == 0)
+ return NT_LINK_SPEED_100G;
+ else
+ return NT_LINK_SPEED_UNKNOWN;
+}
+
+static int func_adapter_get_interfaces(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct ntc_interfaces_s *ifs;
+ struct adap_hdl_s *adap = (struct adap_hdl_s *)hdl;
+ fpga_info_t *fpga_info = &adap->drv->ntdrv.adapter_info.fpga_info;
+ int lag_active;
+ int final_list = adap->drv->probe_finished;
+ /* keep final_list set before nb_ports are called */
+ rte_compiler_barrier();
+ int nb_ports = rte_eth_dev_count_avail();
+
+ /* Get the "internals" structure of phy port 0 to find out if we're running LAG */
+ char phy0_name[128];
+
+ rte_eth_dev_get_name_by_port(0, phy0_name);
+ struct rte_eth_dev *phy0_eth_dev = rte_eth_dev_get_by_name(phy0_name);
+
+ if (phy0_eth_dev == NULL || phy0_eth_dev->data == NULL ||
+ phy0_eth_dev->data->dev_private == NULL) {
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_INTERNAL_ERROR);
+ }
+ struct pmd_internals *phy0_internals =
+ (struct pmd_internals *)phy0_eth_dev->data->dev_private;
+ lag_active = (phy0_internals->lag_config == NULL) ? 0 : 1;
+ if (lag_active) {
+ /*
+ * Phy ports are link aggregated. I.e. number of ports is actually
+ * one bigger than what rte_eth_dev_count_avail() returned
+ */
+ nb_ports++;
+
+ /*
+ * Sanity check:
+ * For now we know about LAG with 2 ports only.
+ * If in the future we get HW with more ports, make assert to alert
+ * the developers that something needs to be looked at...
+ */
+ assert(fpga_info->n_phy_ports == 2);
+ }
+
+ *len = sizeof(struct ntc_interfaces_s) +
+ sizeof(struct ntc_interface_s) * nb_ports;
+ ifs = malloc(*len);
+ if (!ifs) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+ *data = (char *)ifs;
+
+ ifs->nb_ports = nb_ports;
+ ifs->final_list = final_list;
+
+ int i;
+
+ /* First set the "port type" of the physical ports */
+ if (lag_active) {
+ if (phy0_internals->lag_config->mode == BONDING_MODE_8023AD) {
+ /* Active/active LAG */
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ ifs->intf[i].type =
+ PORT_TYPE_PHY_LAG_ACTIVE_AVTIVE;
+ }
+ } else if (phy0_internals->lag_config->mode ==
+ BONDING_MODE_ACTIVE_BACKUP) {
+ /* Active/backup LAG */
+ ifs->intf[phy0_internals->lag_config->primary_port]
+ .type = PORT_TYPE_PHY_LAG_PRIMARY;
+ ifs->intf[phy0_internals->lag_config->backup_port].type =
+ PORT_TYPE_PHY_LAG_BACKUP;
+ } else {
+ /* Unknown LAG mode */
+ assert(0);
+ }
+ } else {
+ /* Normal phy ports (not link aggregated) */
+ for (i = 0; i < fpga_info->n_phy_ports; i++)
+ ifs->intf[i].type = PORT_TYPE_PHY_NORMAL;
+ }
+
+ /* Then set the remaining port values for the physical ports. */
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ char name[128];
+
+ if (i > 0 && lag_active) {
+ /*
+ * Secondary link aggregated port. Just display the "internals" values
+ * from port 0
+ */
+ rte_eth_dev_get_name_by_port(0, name);
+ } else {
+ rte_eth_dev_get_name_by_port(i, name);
+ }
+ struct rte_eth_dev *eth_dev = rte_eth_dev_get_by_name(name);
+
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+ struct adapter_info_s *p_adapter_info =
+ &adap->drv->ntdrv.adapter_info;
+
+ ifs->intf[i].port_id = i;
+ ifs->intf[i].pci_id.domain = internals->pci_dev->addr.domain;
+ ifs->intf[i].pci_id.bus = internals->pci_dev->addr.bus;
+ ifs->intf[i].pci_id.devid = internals->pci_dev->addr.devid;
+ ifs->intf[i].pci_id.function =
+ internals->pci_dev->addr.function;
+ ifs->intf[i].pci_id.pad = 0;
+
+ const bool port_link_status =
+ nt4ga_port_get_link_status(p_adapter_info, i);
+ ifs->intf[i].link = port_link_status ? PORT_LINK_UP :
+ PORT_LINK_DOWN;
+
+ const nt_link_speed_t port_link_speed =
+ nt4ga_port_get_link_speed(p_adapter_info, i);
+ ifs->intf[i].port_speed = read_link_speed(port_link_speed);
+
+ const bool port_adm_state =
+ nt4ga_port_get_adm_state(p_adapter_info, i);
+ if (!port_adm_state) {
+ ifs->intf[i].port_state = PORT_STATE_DISABLED;
+ } else {
+ const bool port_nim_present =
+ nt4ga_port_get_nim_present(p_adapter_info, i);
+ if (port_nim_present) {
+ ifs->intf[i].port_state =
+ PORT_STATE_NIM_PRESENT;
+ } else {
+ ifs->intf[i].port_state = PORT_STATE_NIM_ABSENT;
+ }
+ }
+
+ /* MTU */
+ if (i > 0 && lag_active) {
+ /* Secondary link aggregated port. Display same MTU value as port 0 */
+ rte_eth_dev_get_mtu(0, &ifs->intf[i].mtu);
+ } else {
+ rte_eth_dev_get_mtu(i, &ifs->intf[i].mtu);
+ }
+
+ /* MAC */
+ const uint64_t mac =
+ fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value + i;
+ ifs->intf[i].mac.addr_b[0] = (mac >> 40) & 0xFFu;
+ ifs->intf[i].mac.addr_b[1] = (mac >> 32) & 0xFFu;
+ ifs->intf[i].mac.addr_b[2] = (mac >> 24) & 0xFFu;
+ ifs->intf[i].mac.addr_b[3] = (mac >> 16) & 0xFFu;
+ ifs->intf[i].mac.addr_b[4] = (mac >> 8) & 0xFFu;
+ ifs->intf[i].mac.addr_b[5] = (mac >> 0) & 0xFFu;
+
+ if (i > 0 && lag_active) {
+ /* Secondary link aggregated port. Queues not applicable */
+ ifs->intf[i].num_queues = 0;
+ } else {
+ /* attached hw queues to this interface */
+ unsigned int input_num = internals->nb_rx_queues;
+ /*
+ * These are the "input" queues, meaning these go to host and is attached
+ * to receiving from a port
+ */
+ for (unsigned int ii = 0; ii < input_num; ii++) {
+ ifs->intf[i].queue[ii].idx =
+ internals->rxq_scg[ii].queue.hw_id;
+ ifs->intf[i].queue[ii].dir = QUEUE_INPUT;
+ }
+
+ /*
+ * These are the "output" queues, meaning these go to a virtual port queue
+ * which typically is used by vDPA
+ */
+ for (unsigned int ii = 0; ii < internals->vpq_nb_vq;
+ ii++) {
+ ifs->intf[i].queue[ii + input_num].idx =
+ internals->vpq[ii].hw_id;
+ ifs->intf[i].queue[ii + input_num].dir =
+ QUEUE_OUTPUT;
+ }
+
+ ifs->intf[i].num_queues =
+ input_num + internals->vpq_nb_vq;
+ }
+
+ /* NIM information */
+ nim_i2c_ctx_t nim_ctx =
+ nt4ga_port_get_nim_capabilities(p_adapter_info, i);
+
+ strlcpy((char *)&ifs->intf[i].nim_data.vendor_name,
+ nim_ctx.vendor_name,
+ sizeof(ifs->intf[i].nim_data.vendor_name));
+ strlcpy((char *)&ifs->intf[i].nim_data.prod_no, nim_ctx.prod_no,
+ sizeof(ifs->intf[i].nim_data.prod_no));
+ strlcpy((char *)&ifs->intf[i].nim_data.serial_no,
+ nim_ctx.serial_no,
+ sizeof(ifs->intf[i].nim_data.serial_no));
+ strlcpy((char *)&ifs->intf[i].nim_data.date, nim_ctx.date,
+ sizeof(ifs->intf[i].nim_data.date));
+ strlcpy((char *)&ifs->intf[i].nim_data.rev, nim_ctx.rev,
+ sizeof(ifs->intf[i].nim_data.rev));
+
+ if (nim_ctx.len_info[0] >= 0xFFFF)
+ ifs->intf[i].nim_data.link_length.sm = 0xFFFF;
+ else
+ ifs->intf[i].nim_data.link_length.sm =
+ nim_ctx.len_info[0];
+
+ ifs->intf[i].nim_data.link_length.ebw = nim_ctx.len_info[1];
+ ifs->intf[i].nim_data.link_length.mm50 = nim_ctx.len_info[2];
+ ifs->intf[i].nim_data.link_length.mm62 = nim_ctx.len_info[3];
+ ifs->intf[i].nim_data.link_length.copper = nim_ctx.len_info[4];
+
+ ifs->intf[i].nim_data.pwr_level_req = nim_ctx.pwr_level_req;
+ ifs->intf[i].nim_data.pwr_level_cur = nim_ctx.pwr_level_cur;
+ ifs->intf[i].nim_data.nim_id = nim_ctx.nim_id;
+ ifs->intf[i].nim_data.port_type = nim_ctx.port_type;
+ }
+
+ /* And finally handle the virtual ports. */
+ int rte_eth_dev_virt_port_offset = lag_active ? 1 :
+ fpga_info->n_phy_ports;
+ for (; i < nb_ports; i++, rte_eth_dev_virt_port_offset++) {
+ /* Continue counting from the "i" value reached in the previous for loop */
+ char name[128];
+
+ rte_eth_dev_get_name_by_port(rte_eth_dev_virt_port_offset,
+ name);
+ struct rte_eth_dev *eth_dev = rte_eth_dev_get_by_name(name);
+
+ struct pmd_internals *internals =
+ (struct pmd_internals *)eth_dev->data->dev_private;
+
+ ifs->intf[i].port_id = i;
+ ifs->intf[i].type = PORT_TYPE_VIRT;
+ ifs->intf[i].pci_id.domain = internals->pci_dev->addr.domain;
+ ifs->intf[i].pci_id.bus = internals->pci_dev->addr.bus;
+ ifs->intf[i].pci_id.devid = internals->pci_dev->addr.devid;
+ ifs->intf[i].pci_id.function =
+ internals->pci_dev->addr.function;
+ ifs->intf[i].pci_id.pad = 0;
+
+ ifs->intf[i].port_speed = PORT_LINK_SPEED_NONE_REPORTED;
+ switch (internals->vport_comm) {
+ case VIRT_PORT_NEGOTIATED_NONE:
+ ifs->intf[i].port_state = PORT_STATE_VIRTUAL_UNATTACHED;
+ ifs->intf[i].link = PORT_LINK_DOWN;
+ break;
+ case VIRT_PORT_NEGOTIATED_SPLIT:
+ ifs->intf[i].port_state = PORT_STATE_VIRTUAL_SPLIT;
+ ifs->intf[i].link = PORT_LINK_UP;
+ break;
+ case VIRT_PORT_NEGOTIATED_PACKED:
+ ifs->intf[i].port_state = PORT_STATE_VIRTUAL_PACKED;
+ ifs->intf[i].link = PORT_LINK_UP;
+ break;
+ case VIRT_PORT_USE_RELAY:
+ ifs->intf[i].port_state = PORT_STATE_VIRTUAL_RELAY;
+ ifs->intf[i].link = PORT_LINK_UP;
+ break;
+ }
+
+ /* MTU */
+ rte_eth_dev_get_mtu(rte_eth_dev_virt_port_offset,
+ &ifs->intf[i].mtu);
+
+ /* MAC */
+ for (int ii = 0; ii < 6; ii++) {
+ ifs->intf[i].mac.addr_b[ii] =
+ internals->eth_addrs[0].addr_bytes[ii];
+ }
+
+ /* attached hw queues to this interface */
+ unsigned int input_num = internals->nb_rx_queues;
+
+ /*
+ * These are the "input" queues, meaning these go to host and is attached to
+ * receiving from a port
+ */
+ for (unsigned int ii = 0; ii < input_num; ii++) {
+ ifs->intf[i].queue[ii].idx =
+ internals->rxq_scg[ii].queue.hw_id;
+ ifs->intf[i].queue[ii].dir = QUEUE_INPUT;
+ }
+
+ /*
+ * These are the "output" queues, meaning these go to a virtual port queue
+ * which typically is used by vDPA
+ */
+ unsigned int numq =
+ ((internals->vpq_nb_vq + input_num) > MAX_RSS_QUEUES) ?
+ MAX_RSS_QUEUES - input_num :
+ internals->vpq_nb_vq;
+ for (unsigned int ii = 0; ii < numq; ii++) {
+ ifs->intf[i].queue[ii + input_num].idx =
+ internals->vpq[ii].hw_id;
+ ifs->intf[i].queue[ii + input_num].dir = QUEUE_OUTPUT;
+ }
+ ifs->intf[i].num_queues = input_num + numq;
+ }
+ return REQUEST_OK;
+}
+
+static int func_adapter_get_info(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct adap_hdl_s *adap = (struct adap_hdl_s *)hdl;
+ fpga_info_t *fpga_info = &adap->drv->ntdrv.adapter_info.fpga_info;
+
+ *len = sizeof(struct ntc_adap_get_info_s);
+ *data = malloc(*len);
+ if (!*data) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+
+ snprintf(*data, 31, "%03d-%04d-%02d-%02d", fpga_info->n_fpga_type_id,
+ fpga_info->n_fpga_prod_id, fpga_info->n_fpga_ver_id,
+ fpga_info->n_fpga_rev_id);
+
+ return REQUEST_OK;
+}
+
+static int func_adapter_get_sensors(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct adapter_info_s *adapter =
+ &(((struct adap_hdl_s *)hdl)->drv->ntdrv.adapter_info);
+ struct sensor *sensor_ptr = NULL;
+ uint16_t sensors_num = 0;
+ uint8_t *sensors = NULL;
+ struct ntc_sensors_s sensors_info = {
+ .adapter_sensors_cnt = adapter->adapter_sensors_cnt,
+ .ports_cnt = adapter->fpga_info.n_phy_ports
+ };
+ memcpy(sensors_info.adapter_name, adapter->p_dev_name, 24);
+
+ /* Set a sum of sensor`s counters */
+ sensors_num = adapter->adapter_sensors_cnt;
+ for (int i = 0; i < adapter->fpga_info.n_phy_ports; i++) {
+ sensors_num += adapter->nim_sensors_cnt[i];
+ sensors_info.nim_sensors_cnt[i] = adapter->nim_sensors_cnt[i];
+ }
+
+ *len = sizeof(struct ntc_sensors_s) +
+ sensors_num * sizeof(struct sensor);
+
+ /* Allocate memory for sensors array */
+ sensors = malloc(*len);
+ if (!sensors) {
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ memcpy(sensors, &sensors_info, sizeof(struct ntc_sensors_s));
+ sensor_ptr = (struct sensor *)(sensors + sizeof(struct ntc_sensors_s));
+
+ /* Fetch adapter sensors */
+ for (struct nt_sensor_group *ptr = adapter->adapter_sensors;
+ ptr != NULL; ptr = ptr->next) {
+ sensor_ptr->current_value = ptr->sensor->info.value;
+ sensor_ptr->min_value = ptr->sensor->info.value_lowest;
+ sensor_ptr->max_value = ptr->sensor->info.value_highest;
+ sensor_ptr->sign = ptr->sensor->si;
+ sensor_ptr->type = ptr->sensor->info.type;
+ memcpy(sensor_ptr->name, ptr->sensor->info.name, 50);
+ sensor_ptr++;
+ }
+
+ /* Fetch NIM sensors */
+ for (int i = 0; i < adapter->fpga_info.n_phy_ports; i++) {
+ for (struct nim_sensor_group *ptr = adapter->nim_sensors[i];
+ ptr != NULL; ptr = ptr->next) {
+ sensor_ptr->current_value = ptr->sensor->info.value;
+ sensor_ptr->min_value = ptr->sensor->info.value_lowest;
+ sensor_ptr->max_value = ptr->sensor->info.value_highest;
+ sensor_ptr->sign = ptr->sensor->si;
+ sensor_ptr->type = ptr->sensor->info.type;
+
+ memcpy(sensor_ptr->name, ptr->sensor->info.name,
+ (strlen(ptr->sensor->info.name) >= 50) ?
+ 50 :
+ strlen(ptr->sensor->info.name));
+ sensor_ptr++;
+ }
+ }
+
+ /* Send response */
+ *data = (char *)sensors;
+
+ return REQUEST_OK;
+}
+
+static int set_port_enable(struct adap_hdl_s *adap, int port_nr)
+{
+ adapter_info_t *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ nt4ga_port_set_adm_state(p_adapter_info, port_nr, true);
+
+ return REQUEST_OK;
+}
+
+static int set_port_disable(struct adap_hdl_s *adap, int port_nr)
+{
+ adapter_info_t *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ nt4ga_port_set_adm_state(p_adapter_info, port_nr, false);
+
+ return REQUEST_OK;
+}
+
+static int set_link_up(struct adap_hdl_s *adap, int portid)
+{
+ struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ const bool link_status =
+ nt4ga_port_get_link_status(p_adapter_info, portid);
+
+ if (!link_status) {
+ nt4ga_port_set_link_status(p_adapter_info, portid, true);
+ NT_LOG(DBG, NTCONNECT, "Port %i: Link set to be up\n", portid);
+ } else {
+ NT_LOG(DBG, NTCONNECT,
+ "Port %i: Link is already set to be up\n", portid);
+ }
+
+ return REQUEST_OK;
+}
+
+static int set_link_down(struct adap_hdl_s *adap, int portid)
+{
+ struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ const bool link_status =
+ nt4ga_port_get_link_status(p_adapter_info, portid);
+
+ if (!link_status) {
+ NT_LOG(DBG, NTCONNECT,
+ "Port %i: Link is already set to be down\n", portid);
+ } else {
+ nt4ga_port_set_link_status(p_adapter_info, portid, false);
+ NT_LOG(DBG, NTCONNECT, "Port %i: Link set to be down\n",
+ portid);
+ }
+
+ return REQUEST_OK;
+}
+
+static int set_link_speed(struct adap_hdl_s *adap, int portid, char *speed_str,
+ char **data, int *len)
+{
+ struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ const bool port_adm_state =
+ nt4ga_port_get_adm_state(p_adapter_info, portid);
+ if (!port_adm_state) {
+ const nt_link_speed_t speed = convert_link_speed(speed_str);
+
+ if (speed != NT_LINK_SPEED_UNKNOWN) {
+ nt4ga_port_set_link_speed(p_adapter_info, portid, speed);
+ NT_LOG(DBG, NTCONNECT, "Port %i: set link speed - %s\n",
+ portid, speed_str);
+ } else {
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ }
+ } else {
+ NT_LOG(DBG, NTCONNECT,
+ "Port %i: fail to set link speed, port is enabled\n",
+ portid);
+ return ntconn_reply_status(data, len,
+ NTCONN_ADAPTER_ERR_WRONG_LINK_STATE);
+ }
+
+ return REQUEST_OK;
+}
+
+static int set_loopback_mode(struct adap_hdl_s *adap, int portid, int mode)
+{
+ struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ NT_LOG(DBG, NTCONNECT, "Port %i: set loopback mode %i\n", portid, mode);
+ nt4ga_port_set_loopback_mode(p_adapter_info, portid, mode);
+ return REQUEST_OK;
+}
+
+static int set_tx_power(struct adap_hdl_s *adap, int portid, bool disable,
+ char **data, int *len)
+{
+ struct adapter_info_s *p_adapter_info = &adap->drv->ntdrv.adapter_info;
+
+ NT_LOG(DBG, NTCONNECT, "Port %i: set tx_power %i\n", portid, disable);
+ if (nt4ga_port_tx_power(p_adapter_info, portid, disable)) {
+ NT_LOG(DBG, NTCONNECT,
+ "Port %i: ERROR while changing tx_power\n", portid);
+ return ntconn_reply_status(data, len,
+ NTCONN_ADAPTER_ERR_TX_POWER_FAIL);
+ }
+ return REQUEST_OK;
+}
+
+static int func_adapter_set_interface(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct adap_hdl_s *adap = (struct adap_hdl_s *)hdl;
+ char *saveptr;
+ int port_nr;
+ int length;
+ char *tok;
+
+ *len = 0;
+
+ /*
+ * This will receive the request strings starting with "adapter;set,interface,...."
+ * so in the situation of a request like: "adapter,set,interface,port0,link_speed=10G"
+ * the remainder of the command "port0,link_speed=10G" will be pointed to by *data,
+ * zero-terminated on entry
+ */
+
+ if (!(data && *data))
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_INVALID_REQUEST);
+
+ /* OK to modify *data */
+ tok = strtok_r(*data, ",", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+
+ length = strlen(tok);
+
+ if (!(length > 4 && memcmp(tok, "port", 4) == 0))
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+
+ port_nr = atoi(tok + 4);
+
+ /* Only set on phy ports */
+ if (port_nr < adap->drv->ntdrv.adapter_info.fpga_info.n_phy_ports)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+
+ tok = strtok_r(NULL, "=,", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ if (strcmp(tok, "link_speed") == 0) {
+ tok = strtok_r(NULL, ",", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ return set_link_speed(adap, port_nr, tok, data, len);
+ } else if (strcmp(tok, "enable") == 0) {
+ return set_port_enable(adap, port_nr);
+ } else if (strcmp(tok, "disable") == 0) {
+ return set_port_disable(adap, port_nr);
+ } else if (strcmp(tok, "link_state") == 0) {
+ tok = strtok_r(NULL, ",", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ if (strcmp(tok, "up") == 0)
+ return set_link_up(adap, port_nr);
+ else if (strcmp(tok, "down") == 0)
+ return set_link_down(adap, port_nr);
+ } else if (strcmp(tok, "host_loopback") == 0) {
+ tok = strtok_r(NULL, ",", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ if (strcmp(tok, "on") == 0)
+ return set_loopback_mode(adap, port_nr,
+ NT_LINK_LOOPBACK_HOST);
+ else if (strcmp(tok, "off") == 0)
+ return set_loopback_mode(adap, port_nr,
+ NT_LINK_LOOPBACK_OFF);
+ } else if (strcmp(tok, "line_loopback") == 0) {
+ tok = strtok_r(NULL, ",", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ if (strcmp(tok, "on") == 0)
+ return set_loopback_mode(adap, port_nr,
+ NT_LINK_LOOPBACK_LINE);
+ else if (strcmp(tok, "off") == 0)
+ return set_loopback_mode(adap, port_nr,
+ NT_LINK_LOOPBACK_OFF);
+ } else if (strcmp(tok, "tx_power") == 0) {
+ tok = strtok_r(NULL, ",", &saveptr);
+ if (!tok)
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+ if (strcmp(tok, "on") == 0)
+ return set_tx_power(adap, port_nr, false, data, len);
+ else if (strcmp(tok, "off") == 0)
+ return set_tx_power(adap, port_nr, true, data, len);
+ }
+
+ /* Should return 0 on success */
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_MISSING_INVALID_PARAM);
+}
+
+static int func_adapter_set_adapter(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ if (data && *data) {
+ NT_LOG(DBG, NTCONNECT,
+ "Set adapter: Command: %s\n", *data);
+ }
+
+ *len = 0;
+
+ /* Should return 0 on success */
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_NOT_YET_IMPLEMENTED);
+}
+
+static int adap_request(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr, char *function,
+ char **data, int *len)
+{
+ return execute_function(this_module_name, hdl, client_id, hdr, function,
+ adapter_entry_funcs, data, len, 0);
+}
+
+static void adap_free_data(void *hdl _unused, char *data)
+{
+ free(data);
+}
+
+static void adap_client_cleanup(void *hdl _unused, int client_id _unused)
+{
+ /* Nothing to do */
+}
+
+static const ntconnapi_t ntconn_adap_op = { this_module_name,
+ NTCONN_ADAP_VERSION_MAJOR,
+ NTCONN_ADAP_VERSION_MINOR,
+ adap_request,
+ adap_free_data,
+ adap_client_cleanup
+ };
+
+int ntconn_adap_register(struct drv_s *drv)
+{
+ int i;
+
+ for (i = 0; i < MAX_ADAPTERS; i++) {
+ if (adap_hdl[i].drv == NULL)
+ break;
+ }
+ if (i == MAX_ADAPTERS) {
+ NT_LOG(ERR, NTCONNECT,
+ "Cannot register more adapters into NtConnect framework");
+ return -1;
+ }
+
+ adap_hdl[i].drv = drv;
+ return register_ntconn_mod(&drv->p_dev->addr, (void *)&adap_hdl[i],
+ &ntconn_adap_op);
+}
diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_flow.c b/drivers/net/ntnic/ntconnect_modules/ntconn_flow.c
new file mode 100644
index 0000000000..31d5dc3edc
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect_modules/ntconn_flow.c
@@ -0,0 +1,1310 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <errno.h>
+#include "ntnic_ethdev.h"
+#include "ntconnect.h"
+#include "ntos_system.h"
+#include "ntconn_modules.h"
+#include "ntconn_mod_helper.h"
+#include "nt_util.h"
+#include "ntlog.h"
+#include "ntnic_vf_vdpa.h"
+
+#include "ntconnect_api_flow.h"
+#include "ntconnect_api_meter.h"
+#include "stream_binary_flow_api.h"
+
+#include <rte_errno.h>
+#include "flow_api.h"
+
+#define DEBUG_FLOW 1
+
+#define NTCONN_FLOW_VERSION_MAJOR 0U
+#define NTCONN_FLOW_VERSION_MINOR 1U
+
+#define this_module_name "filter"
+
+#define MAX_CLIENTS 32
+
+#define UNUSED __rte_unused
+
+static struct flow_hdl_s {
+ struct drv_s *drv;
+} flow_hdl[MAX_CLIENTS];
+
+#define MAX_PORTS 64
+static struct port_to_eth_s {
+ struct flow_eth_dev *flw_dev;
+ uint32_t forced_vlan_vid;
+ uint32_t caller_id;
+} port_eth[MAX_PORTS];
+
+static ntconn_err_t ntconn_err[] = {
+ { NTCONN_FLOW_ERR_NONE, "Success" },
+ { NTCONN_FLOW_ERR_INTERNAL_ERROR, "Internal error" },
+ { NTCONN_FLOW_ERR_PORT_IS_NOT_INITIALIZED, "Port is not initialized" },
+ { NTCONN_FLOW_ERR_UNEXPECTED_VIRTIO_PATH, "Unexpected virtio path" },
+ { NTCONN_FLOW_ERR_TO_MANY_FLOWS, "To many flows" },
+ { NTCONN_FLOW_ERR_INVALID_PORT, "Invalid port" },
+ { NTCONN_FLOW_ERR_NOT_YET_IMPLEMENTED, "Function not yet implemented" },
+ { NTCONN_FLOW_ERR_UNSUPPORTED_ADAPTER, "Adapter is not supported" },
+ { NTCONN_FLOW_ERR_NO_VF_QUEUES, "No queues for the VF is found" },
+ { -1, NULL }
+};
+
+static const char *get_error_msg(enum ntconn_flow_err_e err_code)
+{
+ int idx = 0;
+
+ while (ntconn_err[idx].err_code != (uint32_t)-1 &&
+ ntconn_err[idx].err_code != err_code)
+ idx++;
+ if (ntconn_err[idx].err_code == (uint32_t)-1)
+ idx = 1;
+
+ return ntconn_err[idx].err_text;
+}
+
+static inline int ntconn_flow_err_reply_status(char **data, int *len,
+ enum ntconn_flow_err_e code,
+ int err)
+{
+ *data = malloc(sizeof(struct flow_return_s));
+ if (*data) {
+ struct flow_return_s *return_value =
+ (struct flow_return_s *)*data;
+ *len = sizeof(struct flow_return_s);
+ return_value->status = err;
+ return_value->type = FLOW_ERROR_GENERAL;
+ const char *err_msg = get_error_msg(code);
+
+ memcpy(return_value->err_msg, err_msg,
+ RTE_MIN(strlen(err_msg), ERR_MSG_LEN));
+ return REQUEST_OK;
+ }
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory");
+ return REQUEST_ERR;
+}
+
+static inline int ntconn_flow_err_status(char **data, int *len, int err)
+{
+ *data = malloc(sizeof(struct flow_return_s));
+ if (*data) {
+ struct flow_return_s *return_value =
+ (struct flow_return_s *)*data;
+ *len = sizeof(struct flow_return_s);
+ return_value->status = err;
+ return_value->type = FLOW_ERROR_GENERAL;
+ const char *err_msg =
+ get_error_msg(NTCONN_FLOW_ERR_INTERNAL_ERROR);
+ strlcpy(return_value->err_msg, err_msg, ERR_MSG_LEN);
+ return REQUEST_OK;
+ }
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory");
+ return REQUEST_ERR;
+}
+
+/*
+ * Filter functions
+ */
+static int func_flow_create(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data, int *len);
+static int func_flow_validate(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_flow_destroy(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_flow_flush(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data, int *len);
+static int func_flow_query(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data, int *len);
+static int func_flow_setport(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static struct func_s adapter_entry_funcs[] = {
+ { "setport", NULL, func_flow_setport },
+ { "create", NULL, func_flow_create },
+ { "validate", NULL, func_flow_validate },
+ { "destroy", NULL, func_flow_destroy },
+ { "flush", NULL, func_flow_flush },
+ { "query", NULL, func_flow_query },
+ { NULL, NULL, NULL },
+};
+
+static int copy_return_status(char **data, int *len, int status,
+ struct flow_error *error)
+{
+ *data = malloc(sizeof(struct flow_return_s));
+ if (*data) {
+ struct flow_return_s *return_value =
+ (struct flow_return_s *)*data;
+ *len = sizeof(struct flow_return_s);
+
+ return_value->status = status;
+ return_value->type = error->type;
+ strlcpy(return_value->err_msg, error->message, ERR_MSG_LEN);
+ return REQUEST_OK;
+ }
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s",
+ __func__);
+ return REQUEST_ERR;
+}
+
+static void set_error(struct flow_error *error)
+{
+ error->type = FLOW_ERROR_SUCCESS;
+ error->message = "Operation successfully completed";
+}
+
+static int func_flow_setport(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ uint32_t i;
+ struct flow_error error;
+ uint32_t nb_port;
+ uint8_t in_port = MAX_PORTS;
+ char vpath[MAX_PATH_LEN];
+ char *saveptr;
+
+ set_error(&error);
+
+ nb_port = rte_eth_dev_count_avail();
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "%s: \"%s\"\n", __func__, *data);
+ NT_LOG(DBG, NTCONNECT, "Number of ports: %u\n", nb_port);
+#endif
+
+ char *tok = strtok_r(*data, ",", &saveptr);
+
+ if (tok) {
+ int length = strlen(tok);
+
+ if (length > 7 && memcmp(tok, "in_port=", 5) == 0)
+ in_port = atoi(tok + 7);
+ }
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "in_port: %u\n", in_port);
+#endif
+
+ tok = strtok_r(NULL, ",", &saveptr);
+ if (tok) {
+ int length = strlen(tok);
+
+ if (length > 6 && memcmp(tok, "vpath=", 6) == 0)
+ strlcpy(vpath, tok + 6, MAX_PATH_LEN);
+ }
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "vpath: %s\n", vpath);
+#endif
+
+ /* Check that the wanted ports are valid ports */
+ if (in_port >= nb_port) {
+ NT_LOG(ERR, NTCONNECT, "port out of range");
+ return ntconn_flow_err_status(data, len, ENODEV);
+ }
+
+ struct pmd_internals *vp_internals = vp_path_instance_ready(vpath);
+
+ if (!vp_internals) {
+ NT_LOG(ERR, NTCONNECT, "Failed to get VF device");
+ return ntconn_flow_err_status(data, len, ENODEV);
+ }
+
+ /* Get flow device */
+ port_eth[in_port].flw_dev = vp_internals->flw_dev;
+
+ if (port_eth[in_port].flw_dev == NULL) {
+ NT_LOG(ERR, NTCONNECT, "Failed to get eth device");
+ return ntconn_flow_err_status(data, len, ENODEV);
+ }
+
+ /* Only INLINE is supported */
+ if (vp_internals->flw_dev->ndev->flow_profile !=
+ FLOW_ETH_DEV_PROFILE_INLINE) {
+ /* Only inline profile is supported */
+ NT_LOG(ERR, NTCONNECT, "Adapter is not supported");
+ return ntconn_flow_err_status(data, len, ENODEV);
+ }
+
+ if (vp_internals->vpq_nb_vq == 0) {
+ NT_LOG(ERR, NTCONNECT, "No queues for the VF is found");
+ return ntconn_flow_err_status(data, len, ENODEV);
+ }
+
+ /* Server and client must agree of the virtual port number */
+ if (vp_internals->port != (in_port + 4U)) {
+ NT_LOG(ERR, NTCONNECT,
+ "Internal error: Virtual port out of sync");
+ return ntconn_flow_err_status(data, len, ENODEV);
+ }
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "vport: %u\n", vp_internals->port);
+ NT_LOG(DBG, NTCONNECT, "vlan (forced): %u\n", vp_internals->vlan);
+#endif
+
+ port_eth[in_port].caller_id = vp_internals->port;
+ port_eth[in_port].forced_vlan_vid = vp_internals->vlan;
+
+ *data = malloc(sizeof(struct flow_setport_return));
+ if (*data) {
+ struct flow_setport_return *return_value =
+ (struct flow_setport_return *)*data;
+ *len = sizeof(struct flow_setport_return);
+ return_value->num_queues = vp_internals->vpq_nb_vq;
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "Number of queues: %u\n",
+ vp_internals->vpq_nb_vq);
+#endif
+ for (i = 0; i < vp_internals->vpq_nb_vq && i < MAX_QUEUES;
+ i++) {
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "Queue: %u\n",
+ vp_internals->vpq[i].id);
+ NT_LOG(DBG, NTCONNECT, "HW ID: %u\n",
+ vp_internals->vpq[i].hw_id);
+#endif
+ return_value->queues[i].id = vp_internals->vpq[i].id;
+ return_value->queues[i].hw_id =
+ vp_internals->vpq[i].hw_id;
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT,
+ "Setup output port: %u, %04x:%02x:%02x.%x\n",
+ in_port, vp_internals->pci_dev->addr.domain,
+ vp_internals->pci_dev->addr.bus,
+ vp_internals->pci_dev->addr.devid,
+ vp_internals->pci_dev->addr.function);
+#endif
+ }
+ return REQUEST_OK;
+ }
+ *len = 0;
+ return REQUEST_ERR;
+}
+
+static int func_flow_flush(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ struct flow_error error;
+ int port = MAX_PORTS;
+ int status = -1;
+ char *saveptr;
+
+ set_error(&error);
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__);
+#endif
+
+ char *tok = strtok_r(*data, ",", &saveptr);
+
+ if (tok) {
+ int length = strlen(tok);
+
+ if (length > 5 && memcmp(tok, "port=", 5) == 0)
+ port = atoi(tok + 5);
+ }
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port);
+#endif
+
+ if (port >= MAX_PORTS) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "port id out of range");
+ return ntconn_flow_err_reply_status(data, len,
+ NTCONN_FLOW_ERR_INVALID_PORT,
+ ENODEV);
+ }
+
+ /* Call filter with data */
+ status = flow_flush(port_eth[port].flw_dev, &error);
+ return copy_return_status(data, len, status, &error);
+}
+
+static int func_flow_destroy(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data, int *len)
+{
+ struct flow_error error;
+ int port = MAX_PORTS;
+ uint64_t flow = 0;
+ int status = -1;
+
+ struct destroy_flow_ntconnect *flow_cpy =
+ (struct destroy_flow_ntconnect *)&(*data)[hdr->len];
+
+ if (hdr->blob_len != sizeof(struct destroy_flow_ntconnect)) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Error in filter data");
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_INVALID_REQUEST);
+ }
+
+#ifdef DEBUG_FLOW1
+ NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__);
+#endif
+
+ port = flow_cpy->port;
+
+#ifdef DEBUG_FLOW1
+ NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port);
+#endif
+
+ if (port >= MAX_PORTS) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "port id out of range");
+ return ntconn_flow_err_reply_status(data, len,
+ NTCONN_FLOW_ERR_INVALID_PORT,
+ ENODEV);
+ }
+
+ flow = flow_cpy->flow;
+
+#ifdef DEBUG_FLOW1
+ NT_LOG(DBG, NTCONNECT, "flow=0x%016llX\n",
+ (unsigned long long)flow);
+#endif
+
+ /* Call filter with data */
+ status = flow_destroy(port_eth[port].flw_dev,
+ (struct flow_handle *)flow, &error);
+
+ *data = malloc(sizeof(struct flow_return_s));
+ if (*data) {
+ struct flow_return_s *return_value =
+ (struct flow_return_s *)*data;
+ *len = sizeof(struct flow_return_s);
+
+ return_value->status = status;
+ return_value->type = error.type;
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+ return REQUEST_OK;
+ }
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s",
+ __func__);
+ return REQUEST_ERR;
+}
+
+enum {
+ FLOW_API_FUNC_CREATE,
+ FLOW_API_FUNC_VALIDATE,
+};
+
+static uint64_t make_flow_create(int func, int port,
+ struct create_flow_ntconnect *flow_cpy,
+ int *status, struct flow_error *error)
+{
+ struct flow_elem elem[MAX_FLOW_STREAM_ELEM];
+ struct flow_action action[MAX_FLOW_STREAM_ELEM];
+ struct flow_action_vxlan_encap vxlan_tun;
+ struct flow_action_raw_encap encap;
+ struct flow_action_raw_decap decap;
+ struct flow_elem elem_tun[MAX_FLOW_STREAM_VXLAN_TUN_ELEM];
+ int idx = -1;
+
+ struct flow_attr *attr = &flow_cpy->attr;
+ struct flow_elem_cpy *elem_cpy = flow_cpy->elem;
+ struct flow_action_cpy *action_cpy = flow_cpy->action;
+
+ error->type = FLOW_ERROR_GENERAL;
+ error->message = "To many flows";
+ *status = NTCONN_FLOW_ERR_TO_MANY_FLOWS;
+
+ attr->caller_id = port_eth[port].caller_id;
+ attr->forced_vlan_vid = port_eth[port].forced_vlan_vid;
+
+ do {
+ idx++;
+ if (idx > MAX_FLOW_STREAM_ELEM)
+ goto error;
+ elem[idx].type = elem_cpy[idx].type;
+ if (!elem_cpy[idx].spec_cpy.valid) {
+ elem[idx].spec = NULL;
+ } else {
+ elem[idx].spec =
+ (void *)&elem_cpy[idx].spec_cpy.u.start_addr;
+ }
+ if (!elem_cpy[idx].mask_cpy.valid) {
+ elem[idx].mask = NULL;
+ } else {
+ elem[idx].mask =
+ (void *)&elem_cpy[idx].mask_cpy.u.start_addr;
+ }
+ } while (elem_cpy[idx].type != FLOW_ELEM_TYPE_END);
+
+ idx = -1;
+ do {
+ idx++;
+ if (idx > MAX_FLOW_STREAM_ELEM)
+ goto error;
+ action[idx].type = action_cpy[idx].type;
+ if (!action_cpy[idx].conf_cpy.valid) {
+ action[idx].conf = NULL;
+ } else {
+ switch (action_cpy[idx].type) {
+ case FLOW_ACTION_TYPE_VXLAN_ENCAP: {
+ /*
+ * Special VXLAN ENCAP treatment create inner tunnel
+ * elements in action
+ */
+ struct flow_elem_cpy *tun_elem_cpy =
+ (struct flow_elem_cpy *)action_cpy[idx]
+ .conf_cpy.u.vxlan.vxlan_tunnel;
+ vxlan_tun.vxlan_tunnel = elem_tun;
+ int tun_idx = -1;
+
+ do {
+ tun_idx++;
+ if (tun_idx >
+ MAX_FLOW_STREAM_VXLAN_TUN_ELEM) {
+ error->message =
+ "To many VXLAN tunnels";
+ goto error;
+ }
+ elem_tun[tun_idx].type =
+ tun_elem_cpy[tun_idx].type;
+ if (!tun_elem_cpy[tun_idx]
+ .spec_cpy.valid) {
+ elem_tun[tun_idx].spec = NULL;
+ } else {
+ elem_tun[tun_idx].spec =
+ (void *)&tun_elem_cpy[tun_idx]
+ .spec_cpy.u
+ .start_addr;
+ }
+ if (!tun_elem_cpy[tun_idx]
+ .mask_cpy.valid) {
+ elem_tun[tun_idx].mask = NULL;
+ } else {
+ elem_tun[tun_idx].mask =
+ (void *)&tun_elem_cpy[tun_idx]
+ .mask_cpy.u
+ .start_addr;
+ }
+ } while (tun_elem_cpy[tun_idx].type !=
+ FLOW_ELEM_TYPE_END);
+ /* VXLAN ENCAP tunnel finished */
+ action[idx].conf = &vxlan_tun;
+ }
+ break;
+ case FLOW_ACTION_TYPE_RSS: {
+ /* Need to set queue pointer */
+ action_cpy[idx].conf_cpy.u.rss.rss.queue =
+ (const uint16_t *)&action_cpy[idx]
+ .conf_cpy.u.rss.cpy_queue;
+ action[idx].conf = (void *)&action_cpy[idx]
+ .conf_cpy.u.rss.rss;
+ }
+ break;
+ case FLOW_ACTION_TYPE_METER: {
+ /* Need to convert meter ID to uniq ID for the VF */
+ action_cpy[idx].conf_cpy.u.meter.mtr_id =
+ ((flow_mtr_meters_supported() /
+ (RTE_MAX_ETHPORTS - 2)) *
+ (flow_cpy->vport - 4)) +
+ action_cpy[idx].conf_cpy.u.meter.mtr_id;
+ action[idx].conf = (void *)&action_cpy[idx]
+ .conf_cpy.u.meter;
+ }
+ break;
+ case FLOW_ACTION_TYPE_RAW_ENCAP: {
+ encap.preserve = NULL;
+ encap.data =
+ action_cpy[idx].conf_cpy.u.encap.data;
+ encap.item_count =
+ action_cpy[idx]
+ .conf_cpy.u.encap.item_count;
+ encap.size =
+ action_cpy[idx].conf_cpy.u.encap.size;
+
+ for (int eidx = 0;
+ eidx <
+ action_cpy[idx].conf_cpy.u.encap.item_count;
+ eidx++) {
+ if (eidx > RAW_ENCAP_DECAP_ELEMS_MAX) {
+ error->message =
+ "To many encap items";
+ goto error;
+ }
+ encap.items[eidx].type =
+ action_cpy[idx]
+ .conf_cpy.u.encap
+ .item_cpy[eidx]
+ .type;
+ if (action_cpy[idx]
+ .conf_cpy.u.encap
+ .item_cpy[eidx]
+ .spec_cpy.valid) {
+ encap.items[eidx].spec =
+ (void *)&action_cpy[idx]
+ .conf_cpy.u
+ .encap
+ .item_cpy[eidx]
+ .spec_cpy.u
+ .start_addr;
+ } else {
+ encap.items[eidx].spec = NULL;
+ }
+ if (action_cpy[idx]
+ .conf_cpy.u.encap
+ .item_cpy[eidx]
+ .mask_cpy.valid) {
+ encap.items[eidx].mask =
+ (void *)&action_cpy[idx]
+ .conf_cpy.u
+ .encap
+ .item_cpy[eidx]
+ .mask_cpy.u
+ .start_addr;
+ } else {
+ encap.items[eidx].mask = NULL;
+ }
+ }
+ action[idx].conf = &encap;
+ }
+ break;
+ case FLOW_ACTION_TYPE_RAW_DECAP: {
+ decap.data =
+ action_cpy[idx].conf_cpy.u.decap.data;
+ decap.item_count =
+ action_cpy[idx]
+ .conf_cpy.u.decap.item_count;
+ decap.size =
+ action_cpy[idx].conf_cpy.u.decap.size;
+
+ for (int eidx = 0;
+ eidx <
+ action_cpy[idx].conf_cpy.u.decap.item_count;
+ eidx++) {
+ if (eidx > RAW_ENCAP_DECAP_ELEMS_MAX) {
+ error->message =
+ "To many decap items";
+ goto error;
+ }
+ decap.items[eidx].type =
+ action_cpy[idx]
+ .conf_cpy.u.decap
+ .item_cpy[eidx]
+ .type;
+ if (action_cpy[idx]
+ .conf_cpy.u.decap
+ .item_cpy[eidx]
+ .spec_cpy.valid) {
+ decap.items[eidx].spec =
+ (void *)&action_cpy[idx]
+ .conf_cpy.u
+ .decap
+ .item_cpy[eidx]
+ .spec_cpy.u
+ .start_addr;
+ } else {
+ decap.items[eidx].spec = NULL;
+ }
+ if (action_cpy[idx]
+ .conf_cpy.u.decap
+ .item_cpy[eidx]
+ .mask_cpy.valid) {
+ decap.items[eidx].mask =
+ (void *)&action_cpy[idx]
+ .conf_cpy.u
+ .decap
+ .item_cpy[eidx]
+ .mask_cpy.u
+ .start_addr;
+ } else {
+ decap.items[eidx].mask = NULL;
+ }
+ }
+ action[idx].conf = &decap;
+ }
+ break;
+ default: {
+ /* Move conf pointer into conf_cpy data field */
+ action[idx].conf =
+ (void *)&action_cpy[idx]
+ .conf_cpy.u.start_addr;
+ }
+ break;
+ }
+ }
+ } while (action_cpy[idx].type != FLOW_ACTION_TYPE_END);
+
+ *status = NTCONN_FLOW_ERR_NONE;
+ if (func == FLOW_API_FUNC_VALIDATE) {
+ *status = flow_validate(port_eth[port].flw_dev, elem, action,
+ error);
+ return 0ULL;
+ } else {
+ return (uint64_t)flow_create(port_eth[port].flw_dev, attr, elem,
+ action, error);
+ }
+
+error:
+ return 0;
+}
+
+static int func_flow_create(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data, int *len)
+{
+ int status;
+ struct flow_error error;
+ uint64_t flow = 0UL;
+ int port = MAX_PORTS;
+
+ struct create_flow_ntconnect *flow_cpy =
+ (struct create_flow_ntconnect *)&(*data)[hdr->len];
+
+ if (hdr->blob_len != sizeof(struct create_flow_ntconnect)) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Error in filter data");
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_INVALID_REQUEST);
+ }
+
+ port = flow_cpy->port;
+
+ if (port >= MAX_PORTS) {
+ NT_LOG(ERR, NTCONNECT, "port id out of range");
+ return ntconn_flow_err_reply_status(data, len,
+ NTCONN_FLOW_ERR_INVALID_PORT,
+ ENODEV);
+ }
+
+#ifdef DEBUG_PARSING
+ int i;
+
+ for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) {
+ if (flow_cpy[i].elem[i].type == FLOW_ELEM_TYPE_END) {
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_END\n");
+ break;
+ }
+ switch (flow_cpy->elem[i].type) {
+ case FLOW_ELEM_TYPE_IPV4:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV4 %i\n", i);
+ NT_LOG(DBG, NTCONNECT, " src_ip: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[1] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[2] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[3] & 0xFF);
+ NT_LOG(DBG, NTCONNECT, " dst_ip: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[1] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[2] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[3] & 0xFF);
+ NT_LOG(DBG, NTCONNECT, " src_mask: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[1] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[2] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[3] & 0xFF);
+ NT_LOG(DBG, NTCONNECT, " dst_mask: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[1] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[2] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[3] & 0xFF);
+ break;
+ case FLOW_ELEM_TYPE_ETH:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ETH %i\n", i);
+ NT_LOG(DBG, NTCONNECT,
+ " src mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, NTCONNECT,
+ " dst mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, NTCONNECT,
+ " src mask %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, NTCONNECT,
+ " dst mask %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[5] & 0xFF);
+ break;
+ case FLOW_ELEM_TYPE_VLAN:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VLAN %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_IPV6:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV6 %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_SCTP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_SCTP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_TCP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_TCP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_UDP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_UDP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_ICMP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ICMP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_VXLAN:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VXLAN %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_PORT_ID:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_PORT_ID %i\n",
+ i);
+ break;
+ default:
+ NT_LOG(DBG, NTCONNECT, "Unknown item %u\n",
+ flow_cpy->elem[i].type);
+ break;
+ }
+ }
+
+ for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) {
+ uint32_t j;
+
+ if (flow_cpy->action[i].type == FLOW_ACTION_TYPE_END) {
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_END\n");
+ break;
+ }
+ switch (flow_cpy->action[i].type) {
+ case FLOW_ACTION_TYPE_RSS:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_RSS %i\n", i);
+ NT_LOG(DBG, NTCONNECT, " queue nb: %u\n",
+ flow_cpy->action[i].conf_cpy.u.rss.rss.queue_num);
+ NT_LOG(DBG, NTCONNECT, " queue: ");
+ for (j = 0;
+ j < flow_cpy->action[i]
+ .conf_cpy.u.rss.rss.queue_num &&
+ j < FLOW_MAX_QUEUES;
+ j++) {
+ NT_LOG(DBG, NTCONNECT, "%u ",
+ flow_cpy->action[i]
+ .conf_cpy.u.rss.cpy_queue[j]);
+ }
+ NT_LOG(DBG, NTCONNECT, "\n");
+ break;
+
+ case FLOW_ACTION_TYPE_POP_VLAN:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_POP_VLAN %i\n",
+ i);
+ break;
+ case FLOW_ACTION_TYPE_PUSH_VLAN:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_PUSH_VLAN %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_SET_VLAN_VID:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_SET_VLAN_VID %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_SET_VLAN_PCP:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_SET_VLAN_PCP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_VXLAN_DECAP:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_VXLAN_DECAP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_VXLAN_ENCAP:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_VXLAN_ENCAP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_DROP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_DROP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_COUNT:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_COUNT %i\n",
+ i);
+ break;
+ case FLOW_ACTION_TYPE_MARK:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_MARK %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_PORT_ID:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_PORT_ID %i: ID=%u\n", i,
+ flow_cpy->action[i].conf_cpy.u.port_id.id);
+ break;
+ case FLOW_ACTION_TYPE_QUEUE:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_QUEUE %i: queue=%u\n", i,
+ flow_cpy->action[i].conf_cpy.u.queue.index);
+ break;
+ case FLOW_ACTION_TYPE_SET_TAG:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_SET_TAG %i: idx=%u, data=%u, mask=%X\n",
+ i, flow_cpy->action[i].conf_cpy.u.tag.index,
+ flow_cpy->action[i].conf_cpy.u.tag.data,
+ flow_cpy->action[i].conf_cpy.u.tag.mask);
+ break;
+ default:
+ NT_LOG(DBG, NTCONNECT, "Unknown action %u\n",
+ flow_cpy->action[i].type);
+ break;
+ }
+ }
+#endif
+
+ /* Call filter with data */
+ flow = make_flow_create(FLOW_API_FUNC_CREATE, port, flow_cpy, &status,
+ &error);
+ if (flow) {
+ *data = malloc(sizeof(struct create_flow_return_s));
+ if (!*data)
+ goto create_flow_error_malloc;
+ struct create_flow_return_s *return_value =
+ (struct create_flow_return_s *)*data;
+ *len = sizeof(struct create_flow_return_s);
+ return_value->flow = flow;
+ return REQUEST_OK;
+ }
+
+ *data = malloc(sizeof(struct flow_error_return_s));
+ if (!*data)
+ goto create_flow_error_malloc;
+ struct flow_error_return_s *return_value =
+ (struct flow_error_return_s *)*data;
+ *len = sizeof(struct flow_error_return_s);
+ return_value->type = error.type;
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+ return REQUEST_OK;
+
+create_flow_error_malloc:
+
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", __func__);
+ return REQUEST_ERR;
+}
+
+static int func_flow_validate(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data,
+ int *len)
+{
+ int status;
+ struct flow_error error;
+ int port = MAX_PORTS;
+
+ struct create_flow_ntconnect *flow_cpy =
+ (struct create_flow_ntconnect *)&(*data)[hdr->len];
+
+ if (hdr->blob_len != sizeof(struct create_flow_ntconnect)) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Error in filter data");
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_INVALID_REQUEST);
+ }
+
+ set_error(&error);
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "func_flow_create\n");
+#endif
+
+ port = flow_cpy->port;
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port);
+#endif
+
+ if (port >= MAX_PORTS) {
+ NT_LOG(ERR, NTCONNECT, "port id out of range");
+ return ntconn_flow_err_reply_status(data, len,
+ NTCONN_FLOW_ERR_INVALID_PORT, ENODEV);
+ }
+
+#ifdef DEBUG_PARSING
+ int i;
+
+ for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) {
+ if (flow_cpy[i].elem[i].type == FLOW_ELEM_TYPE_END) {
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_END\n");
+ break;
+ }
+ switch (flow_cpy->elem[i].type) {
+ case FLOW_ELEM_TYPE_IPV4:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV4 %i\n", i);
+ NT_LOG(DBG, NTCONNECT, " src_ip: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF);
+ NT_LOG(DBG, NTCONNECT, " dst_ip: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .spec_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF);
+ NT_LOG(DBG, NTCONNECT, " src_mask: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.src_ip)[0] & 0xFF);
+ NT_LOG(DBG, NTCONNECT, " dst_mask: %u.%u.%u.%u\n",
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF,
+ ((const char *)&flow_cpy->elem[i]
+ .mask_cpy.u.ipv4.hdr.dst_ip)[0] & 0xFF);
+ break;
+ case FLOW_ELEM_TYPE_ETH:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ETH %i\n", i);
+ NT_LOG(DBG, NTCONNECT,
+ " src mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.s_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, NTCONNECT,
+ " dst mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].spec_cpy.u.eth.d_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, NTCONNECT,
+ " src mask %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.s_addr.addr_b[5] & 0xFF);
+ NT_LOG(DBG, NTCONNECT,
+ " dst mask %02X:%02X:%02X:%02X:%02X:%02X\n",
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[0] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[1] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[2] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[3] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[4] & 0xFF,
+ flow_cpy->elem[i].mask_cpy.u.eth.d_addr.addr_b[5] & 0xFF);
+ break;
+ case FLOW_ELEM_TYPE_VLAN:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VLAN %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_IPV6:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_IPV6 %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_SCTP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_SCTP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_TCP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_TCP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_UDP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_UDP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_ICMP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_ICMP %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_VXLAN:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_VXLAN %i\n", i);
+ break;
+ case FLOW_ELEM_TYPE_PORT_ID:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ELEM_TYPE_PORT_ID %i\n",
+ i);
+ break;
+ default:
+ NT_LOG(DBG, NTCONNECT, "Unknown item %u\n",
+ flow_cpy->elem[i].type);
+ break;
+ }
+ }
+
+ for (i = 0; i < MAX_FLOW_STREAM_ELEM; i++) {
+ uint32_t j;
+
+ if (flow_cpy->action[i].type == FLOW_ACTION_TYPE_END) {
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_END\n");
+ break;
+ }
+ switch (flow_cpy->action[i].type) {
+ case FLOW_ACTION_TYPE_RSS:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_RSS %i\n", i);
+ NT_LOG(DBG, NTCONNECT, " queue nb: %u\n",
+ flow_cpy->action[i].conf_cpy.u.rss.rss.queue_num);
+ NT_LOG(DBG, NTCONNECT, " queue: ");
+ for (j = 0;
+ j < flow_cpy->action[i]
+ .conf_cpy.u.rss.rss.queue_num &&
+ j < FLOW_MAX_QUEUES;
+ j++) {
+ NT_LOG(DBG, NTCONNECT, "%u ",
+ flow_cpy->action[i]
+ .conf_cpy.u.rss.cpy_queue[j]);
+ }
+ NT_LOG(DBG, NTCONNECT, "\n");
+ break;
+
+ case FLOW_ACTION_TYPE_POP_VLAN:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_POP_VLAN %i\n",
+ i);
+ break;
+ case FLOW_ACTION_TYPE_PUSH_VLAN:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_PUSH_VLAN %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_SET_VLAN_VID:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_SET_VLAN_VID %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_SET_VLAN_PCP:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_SET_VLAN_PCP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_VXLAN_DECAP:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_VXLAN_DECAP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_VXLAN_ENCAP:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_VXLAN_ENCAP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_DROP:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_DROP %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_COUNT:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_COUNT %i\n",
+ i);
+ break;
+ case FLOW_ACTION_TYPE_MARK:
+ NT_LOG(DBG, NTCONNECT, "FLOW_ACTION_TYPE_MARK %i\n", i);
+ break;
+ case FLOW_ACTION_TYPE_PORT_ID:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_PORT_ID %i: ID=%u\n", i,
+ flow_cpy->action[i].conf_cpy.u.port_id.id);
+ break;
+ case FLOW_ACTION_TYPE_QUEUE:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_QUEUE %i: queue=%u\n", i,
+ flow_cpy->action[i].conf_cpy.u.queue.index);
+ break;
+ case FLOW_ACTION_TYPE_SET_TAG:
+ NT_LOG(DBG, NTCONNECT,
+ "FLOW_ACTION_TYPE_SET_TAG %i: idx=%u, data=%u, mask=%X\n",
+ i, flow_cpy->action[i].conf_cpy.u.tag.index,
+ flow_cpy->action[i].conf_cpy.u.tag.data,
+ flow_cpy->action[i].conf_cpy.u.tag.mask);
+ break;
+ default:
+ NT_LOG(DBG, NTCONNECT, "Unknown action %u\n",
+ flow_cpy->action[i].type);
+ break;
+ }
+ }
+#endif
+
+ /* Call filter with data */
+ make_flow_create(FLOW_API_FUNC_VALIDATE, port, flow_cpy, &status,
+ &error);
+ return copy_return_status(data, len, status, &error);
+
+ /* Call filter with data */
+ make_flow_create(FLOW_API_FUNC_VALIDATE, port, flow_cpy, &status,
+ &error);
+ if (!status) {
+ *data = malloc(sizeof(struct validate_flow_return_s));
+ if (!*data)
+ goto validate_flow_error_malloc;
+ struct validate_flow_return_s *return_value =
+ (struct validate_flow_return_s *)*data;
+ *len = sizeof(struct validate_flow_return_s);
+ return_value->status = 0;
+ return REQUEST_OK;
+ }
+
+ *data = malloc(sizeof(struct flow_error_return_s));
+ if (!*data)
+ goto validate_flow_error_malloc;
+ struct flow_error_return_s *return_value =
+ (struct flow_error_return_s *)*data;
+ *len = sizeof(struct flow_error_return_s);
+ return_value->type = error.type;
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+ return_value->status = status;
+ return REQUEST_OK;
+
+validate_flow_error_malloc:
+
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", __func__);
+ return REQUEST_ERR;
+}
+
+static int func_flow_query(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data, int *len)
+{
+ int status;
+ struct flow_error error;
+ int port = MAX_PORTS;
+ struct flow_handle *flow;
+
+ struct query_flow_ntconnect *flow_cpy =
+ (struct query_flow_ntconnect *)&(*data)[hdr->len];
+
+ if (hdr->blob_len != sizeof(struct query_flow_ntconnect)) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Error in filter data");
+ return ntconn_error(data, len, this_module_name,
+ NTCONN_ERR_CODE_INVALID_REQUEST);
+ }
+
+ set_error(&error);
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__);
+#endif
+
+ port = flow_cpy->port;
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "Port id=%u\n", port);
+#endif
+
+ if (port >= MAX_PORTS) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "port id out of range");
+ return ntconn_flow_err_reply_status(data, len,
+ NTCONN_FLOW_ERR_INVALID_PORT, ENODEV);
+ }
+
+#ifdef DEBUG_FLOW
+ NT_LOG(DBG, NTCONNECT, "flow=0x%016llX\n",
+ (unsigned long long)flow_cpy->flow);
+#endif
+
+ flow = (struct flow_handle *)flow_cpy->flow;
+
+ const struct flow_action action = {
+ flow_cpy->action.type,
+ (const void *)&flow_cpy->action.conf_cpy.u.count
+ };
+
+ /* Call filter with data */
+ void *data_out = NULL;
+ uint32_t length = 0;
+
+ status = flow_query(port_eth[port].flw_dev, flow, &action, &data_out,
+ &length, &error);
+
+ *data = malloc(sizeof(struct query_flow_return_s) + length);
+ if (*data) {
+ struct query_flow_return_s *return_value =
+ (struct query_flow_return_s *)*data;
+ *len = sizeof(struct query_flow_return_s) + length;
+
+ return_value->status = status;
+ return_value->type = error.type;
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+
+ if (data_out) {
+ memcpy(return_value->data, data_out, length);
+ return_value->data_length = length;
+ free(data_out);
+ } else {
+ return_value->data_length = 0;
+ }
+ return REQUEST_OK;
+ }
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s",
+ __func__);
+ return REQUEST_ERR;
+}
+
+static int flow_request(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr, char *function,
+ char **data, int *len)
+{
+ return execute_function(this_module_name, hdl, client_id, hdr, function,
+ adapter_entry_funcs, data, len, 0);
+}
+
+static void flow_free_data(void *hdl _unused, char *data)
+{
+ if (data)
+ free(data);
+}
+
+static void flow_client_cleanup(void *hdl _unused, int client_id _unused)
+{
+ /* Nothing to do */
+}
+
+static const ntconnapi_t ntconn_flow_op = { this_module_name,
+ NTCONN_FLOW_VERSION_MAJOR,
+ NTCONN_FLOW_VERSION_MINOR,
+ flow_request,
+ flow_free_data,
+ flow_client_cleanup
+ };
+
+int ntconn_flow_register(struct drv_s *drv)
+{
+ int i;
+
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ if (flow_hdl[i].drv == NULL)
+ break;
+ }
+ if (i == MAX_CLIENTS) {
+ NT_LOG(ERR, NTCONNECT,
+ "Cannot register more adapters into NtConnect framework");
+ return -1;
+ }
+
+ flow_hdl[i].drv = drv;
+ return register_ntconn_mod(&drv->p_dev->addr, (void *)&flow_hdl[i],
+ &ntconn_flow_op);
+}
diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_meter.c b/drivers/net/ntnic/ntconnect_modules/ntconn_meter.c
new file mode 100644
index 0000000000..7c21690f8b
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect_modules/ntconn_meter.c
@@ -0,0 +1,517 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <errno.h>
+#include "ntnic_ethdev.h"
+#include "ntconnect.h"
+#include "ntos_system.h"
+#include "ntconn_modules.h"
+#include "ntconn_mod_helper.h"
+#include "nt_util.h"
+#include "ntlog.h"
+#include "ntnic_vf_vdpa.h"
+
+#include "ntconnect_api_meter.h"
+#include "flow_api_profile_inline.h"
+
+#include <rte_errno.h>
+#include <rte_mtr.h>
+#include <rte_mtr_driver.h>
+
+#define NTCONN_METER_VERSION_MAJOR 0U
+#define NTCONN_METER_VERSION_MINOR 1U
+
+#define this_module_name "meter"
+
+#define MAX_CLIENTS 32
+
+#define UNUSED __rte_unused
+
+static struct meter_hdl_s {
+ struct drv_s *drv;
+} meter_hdl[MAX_CLIENTS];
+
+static ntconn_err_t ntconn_err[] = {
+ { NTCONN_METER_ERR_NONE, "Success" },
+ { NTCONN_METER_ERR_INTERNAL_ERROR, "Internal error" },
+ { NTCONN_METER_ERR_INVALID_PORT, "Invalid virtual port" },
+ { NTCONN_METER_ERR_PROFILE_ID, "Profile ID out of range" },
+ { NTCONN_METER_ERR_POLICY_ID, "Policy ID out of range" },
+ { NTCONN_METER_ERR_METER_ID, "Meter ID out of range" },
+ { -1, NULL }
+};
+
+/********************************************************************/
+/* Get error message corresponding to the error code */
+/********************************************************************/
+static const char *get_error_msg(uint32_t err_code)
+{
+ int idx = 0;
+
+ if (err_code < NTCONN_METER_ERR_INTERNAL_ERROR) {
+ const ntconn_err_t *err_msg = get_ntconn_error(err_code);
+
+ return err_msg->err_text;
+ }
+ while (ntconn_err[idx].err_code != (uint32_t)-1 &&
+ ntconn_err[idx].err_code != err_code)
+ idx++;
+ if (ntconn_err[idx].err_code == (uint32_t)-1)
+ idx = 1;
+ return ntconn_err[idx].err_text;
+}
+
+/*
+ * Filter functions
+ */
+static int func_meter_get_capabilities(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_meter_setup(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data, int *len);
+static int func_meter_read(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data, int *len);
+static struct func_s adapter_entry_funcs[] = {
+ { "capabilities", NULL, func_meter_get_capabilities },
+ { "setup", NULL, func_meter_setup },
+ { "read", NULL, func_meter_read },
+ { NULL, NULL, NULL },
+};
+
+/**********************************************************************/
+/* copy error message corresponding to the error code to error struct */
+/**********************************************************************/
+static void copy_mtr_error(struct rte_mtr_error *error, uint32_t err)
+{
+ error->type = RTE_MTR_ERROR_TYPE_UNSPECIFIED;
+ error->message = get_error_msg(err);
+ error->cause = NULL;
+}
+
+static int func_meter_get_capabilities(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ char *saveptr;
+ uint8_t vport = 0;
+ uint8_t port = 0;
+ int status;
+ struct rte_mtr_capabilities cap;
+ struct rte_mtr_error error;
+
+#ifdef DEBUG_METER
+ NT_LOG(DBG, NTCONNECT, "%s: \"%s\"\n", __func__, *data);
+#endif
+
+ char *tok = strtok_r(*data, ",", &saveptr);
+
+ if (tok) {
+ int length = strlen(tok);
+
+ if (length > 6 && memcmp(tok, "vport=", 6) == 0)
+ vport = atoi(tok + 6);
+ }
+#ifdef DEBUG_METER
+ NT_LOG(DBG, NTCONNECT, "vport=%u\n", vport);
+#endif
+
+ if (vport == 0 || vport > 64) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Virtual port is invalid");
+ copy_mtr_error(&error, NTCONN_METER_ERR_INVALID_PORT);
+ status = -ENODEV;
+ goto error_get_capa;
+ }
+
+ port = vport & 1;
+ status = rte_mtr_capabilities_get(port, &cap, &error);
+ if (status == 0) {
+ /* Handle success by copying the return values to the return struct */
+ *data = malloc(sizeof(struct meter_capabilities_return_s));
+ if (!*data)
+ goto error_get_capa_malloc;
+ struct meter_capabilities_return_s *return_value =
+ (struct meter_capabilities_return_s *)*data;
+ *len = sizeof(struct meter_capabilities_return_s);
+ memcpy(&return_value->cap, &cap,
+ sizeof(struct rte_mtr_capabilities));
+ return REQUEST_OK;
+ }
+
+error_get_capa:
+
+ /* Handle errors by copy errors to the error struct */
+ NT_LOG(ERR, NTCONNECT, "Failed to get capabilities for port %u (%u)",
+ port, vport);
+ *data = malloc(sizeof(struct meter_error_return_s));
+ if (!*data)
+ goto error_get_capa_malloc;
+ struct meter_error_return_s *return_value =
+ (struct meter_error_return_s *)*data;
+ *len = sizeof(struct meter_error_return_s);
+ return_value->status = status;
+ return_value->type = error.type;
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+ return REQUEST_OK;
+
+error_get_capa_malloc:
+
+ *len = 0;
+ return REQUEST_ERR;
+}
+
+static int func_meter_setup(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data, int *len)
+{
+ char *saveptr;
+ uint8_t port;
+ uint32_t max_id;
+ int status;
+ struct rte_mtr_error error;
+ int command = UNKNOWN_CMD;
+
+#ifdef DEBUG_METER
+ NT_LOG(DBG, NTCONNECT, "%s: \"%s\"\n", __func__, *data);
+#endif
+
+ if (hdr->blob_len != sizeof(struct meter_setup_s)) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Error: Profile data size is illegal");
+ copy_mtr_error(&error, NTCONN_ERR_CODE_INVALID_REQUEST);
+ status = -EINTR;
+ goto error_meter_setup;
+ }
+
+ /* Get the data blob containing the data for the meter function */
+ struct meter_setup_s *cpy_data =
+ (struct meter_setup_s *)&(*data)[hdr->len];
+
+ if (cpy_data->vport < 4 || cpy_data->vport > 128) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Virtual port is invalid");
+ copy_mtr_error(&error, NTCONN_METER_ERR_INVALID_PORT);
+ status = -ENODEV;
+ goto error_meter_setup;
+ }
+
+ char *tok = strtok_r(*data, ",", &saveptr);
+
+ if (tok) {
+ int length = strlen(tok);
+
+ if (length == 6) {
+ if (memcmp(tok, "addpro", 6) == 0)
+ command = ADD_PROFILE;
+
+ else if (memcmp(tok, "delpro", 6) == 0)
+ command = DEL_PROFILE;
+
+ else if (memcmp(tok, "addpol", 6) == 0)
+ command = ADD_POLICY;
+
+ else if (memcmp(tok, "delpol", 6) == 0)
+ command = DEL_POLICY;
+
+ else if (memcmp(tok, "crtmtr", 6) == 0)
+ command = CREATE_MTR;
+
+ else if (memcmp(tok, "delmtr", 6) == 0)
+ command = DEL_MTR;
+ }
+ }
+
+ if (command == UNKNOWN_CMD) {
+ NT_LOG(ERR, NTCONNECT, "Error: Invalid command");
+ copy_mtr_error(&error, NTCONN_ERR_CODE_INVALID_REQUEST);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+
+ /* Port will be either 0 or 1 depending on the VF. */
+ port = cpy_data->vport & 1;
+
+ switch (command) {
+ case ADD_PROFILE:
+ max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2);
+ if (cpy_data->id > max_id) {
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Profile ID %u out of range. Max value is %u",
+ cpy_data->id, max_id);
+ copy_mtr_error(&error, NTCONN_METER_ERR_PROFILE_ID);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+ cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id;
+ status = rte_mtr_meter_profile_add(port, cpy_data->id,
+ &cpy_data->profile, &error);
+ if (status != 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed to add profile for port %u (%u)", port,
+ cpy_data->vport);
+ }
+ break;
+ case DEL_PROFILE:
+ max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2);
+ if (cpy_data->id > max_id) {
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Profile ID %u out of range. Max value is %u",
+ cpy_data->id, max_id);
+ copy_mtr_error(&error, NTCONN_METER_ERR_PROFILE_ID);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+ cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id;
+ status = rte_mtr_meter_profile_delete(port, cpy_data->id,
+ &error);
+ if (status != 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed to delete profile for port %u (%u)",
+ port, cpy_data->vport);
+ }
+ break;
+ case ADD_POLICY:
+ max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2);
+ if (cpy_data->id > max_id) {
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Policy ID %u out of range. Max value is %u",
+ cpy_data->id, max_id);
+ copy_mtr_error(&error, NTCONN_METER_ERR_POLICY_ID);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+ cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id;
+ cpy_data->p.policy.actions[RTE_COLOR_GREEN] =
+ cpy_data->p.actions_green;
+ cpy_data->p.policy.actions[RTE_COLOR_YELLOW] =
+ cpy_data->p.actions_yellow;
+ cpy_data->p.policy.actions[RTE_COLOR_RED] =
+ cpy_data->p.actions_red;
+ status = rte_mtr_meter_policy_add(port, cpy_data->id,
+ &cpy_data->p.policy, &error);
+ if (status != 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed to add policy for port %u (%u)", port,
+ cpy_data->vport);
+ }
+ break;
+ case DEL_POLICY:
+ max_id = flow_mtr_meter_policy_n_max() / (RTE_MAX_ETHPORTS - 2);
+ if (cpy_data->id > max_id) {
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Policy ID %u out of range. Max value is %u",
+ cpy_data->id, max_id);
+ copy_mtr_error(&error, NTCONN_METER_ERR_POLICY_ID);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+ cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id;
+ status =
+ rte_mtr_meter_policy_delete(port, cpy_data->id, &error);
+ if (status != 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed to delete policy for port %u (%u)", port,
+ cpy_data->vport);
+ }
+ break;
+ case CREATE_MTR:
+ max_id = flow_mtr_meters_supported() / (RTE_MAX_ETHPORTS - 2);
+ if (cpy_data->id > max_id) {
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Meter ID %u out of range. Max value is %u",
+ cpy_data->id, max_id);
+ copy_mtr_error(&error, NTCONN_METER_ERR_METER_ID);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+ cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id;
+ cpy_data->mtr_params.meter_profile_id =
+ ((cpy_data->vport - 4) *
+ (flow_mtr_meter_policy_n_max() /
+ (RTE_MAX_ETHPORTS - 2))) +
+ cpy_data->mtr_params.meter_profile_id;
+ cpy_data->mtr_params.meter_policy_id =
+ ((cpy_data->vport - 4) *
+ (flow_mtr_meter_policy_n_max() /
+ (RTE_MAX_ETHPORTS - 2))) +
+ cpy_data->mtr_params.meter_policy_id;
+ status = rte_mtr_create(port, cpy_data->id,
+ &cpy_data->mtr_params, cpy_data->shared,
+ &error);
+ if (status != 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed to create meter for port %u (%u)", port,
+ cpy_data->vport);
+ }
+ break;
+ case DEL_MTR:
+ max_id = flow_mtr_meters_supported() / (RTE_MAX_ETHPORTS - 2);
+ if (cpy_data->id > max_id) {
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Meter ID %u out of range. Max value is %u",
+ cpy_data->id, max_id);
+ copy_mtr_error(&error, NTCONN_METER_ERR_METER_ID);
+ status = -EINVAL;
+ goto error_meter_setup;
+ }
+ cpy_data->id = ((cpy_data->vport - 4) * max_id) + cpy_data->id;
+ status = rte_mtr_destroy(port, cpy_data->id, &error);
+ if (status != 0) {
+ NT_LOG(ERR, NTCONNECT,
+ "Failed to destroy meter for port %u (%u)", port,
+ cpy_data->vport);
+ }
+ break;
+ }
+
+ if (status == 0) {
+ /* Handle success by copying the return values to the return struct */
+ *data = malloc(sizeof(struct meter_return_s));
+ if (!*data)
+ goto error_meter_setup_malloc;
+ struct meter_return_s *return_value =
+ (struct meter_return_s *)*data;
+ *len = sizeof(struct meter_return_s);
+ return_value->status = 0;
+ return REQUEST_OK;
+ }
+
+error_meter_setup:
+
+ /* Handle errors by copy errors to the error struct */
+ *data = malloc(sizeof(struct meter_error_return_s));
+ if (!*data)
+ goto error_meter_setup_malloc;
+ struct meter_error_return_s *return_value =
+ (struct meter_error_return_s *)*data;
+ *len = sizeof(struct meter_error_return_s);
+ return_value->status = status;
+ return_value->type = error.type;
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+ return REQUEST_OK;
+
+error_meter_setup_malloc:
+
+ *len = 0;
+ return REQUEST_ERR;
+}
+
+static int func_meter_read(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data, int *len)
+{
+ uint8_t port = 0;
+ int status;
+ struct rte_mtr_error error;
+ struct rte_mtr_stats stats;
+ uint64_t stats_mask;
+
+#ifdef DEBUG_METER
+ NT_LOG(DBG, NTCONNECT, "%s: [%s:%u] enter\n", __func__, __FILE__, __LINE__);
+#endif
+
+ if (hdr->blob_len != sizeof(struct meter_get_stat_s)) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT,
+ "Error: Read meter stats data size is illegal");
+ copy_mtr_error(&error, NTCONN_ERR_CODE_INVALID_REQUEST);
+ status = -EINTR;
+ goto error_meter_read;
+ }
+
+ /* Get the data blob containing the data for the meter function */
+ struct meter_get_stat_s *cpy_data =
+ (struct meter_get_stat_s *)&(*data)[hdr->len];
+
+ if (cpy_data->vport < 4 || cpy_data->vport > 128) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Virtual port is invalid");
+ copy_mtr_error(&error, NTCONN_METER_ERR_INVALID_PORT);
+ status = -ENODEV;
+ goto error_meter_read;
+ }
+
+ port = cpy_data->vport & 1;
+ cpy_data->mtr_id =
+ ((cpy_data->vport - 4) *
+ (flow_mtr_meters_supported() / (RTE_MAX_ETHPORTS - 2))) +
+ cpy_data->mtr_id;
+ status = rte_mtr_stats_read(port, cpy_data->mtr_id, &stats, &stats_mask,
+ cpy_data->clear, &error);
+ if (status == 0) {
+ /* Handle success by copying the return values to the return struct */
+ *data = malloc(sizeof(struct meter_return_stat_s));
+ if (!*data)
+ goto error_meter_read_malloc;
+ struct meter_return_stat_s *return_value =
+ (struct meter_return_stat_s *)*data;
+ *len = sizeof(struct meter_return_stat_s);
+ return_value->stats_mask = stats_mask;
+ memcpy(&return_value->stats, &stats,
+ sizeof(struct rte_mtr_stats));
+ return REQUEST_OK;
+ }
+
+error_meter_read:
+ /* Handle errors by copy errors to the error struct */
+ NT_LOG(ERR, NTCONNECT, "Failed to read meter stats");
+ *data = malloc(sizeof(struct meter_error_return_s));
+ if (!*data)
+ goto error_meter_read_malloc;
+ struct meter_error_return_s *return_value =
+ (struct meter_error_return_s *)*data;
+ *len = sizeof(struct meter_error_return_s);
+ strlcpy(return_value->err_msg, error.message, ERR_MSG_LEN);
+ return_value->status = status;
+ return_value->type = error.type;
+ return REQUEST_OK;
+
+error_meter_read_malloc:
+ *len = 0;
+ return REQUEST_ERR;
+}
+
+static int meter_request(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr, char *function,
+ char **data, int *len)
+{
+ return execute_function(this_module_name, hdl, client_id, hdr, function,
+ adapter_entry_funcs, data, len, 0);
+}
+
+static void meter_free_data(void *hdl _unused, char *data)
+{
+ if (data)
+ free(data);
+}
+
+static void meter_client_cleanup(void *hdl _unused, int client_id _unused)
+{
+ /* Nothing to do */
+}
+
+static const ntconnapi_t ntconn_meter_op = { this_module_name,
+ NTCONN_METER_VERSION_MAJOR,
+ NTCONN_METER_VERSION_MINOR,
+ meter_request,
+ meter_free_data,
+ meter_client_cleanup
+ };
+
+int ntconn_meter_register(struct drv_s *drv)
+{
+ int i;
+
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ if (meter_hdl[i].drv == NULL)
+ break;
+ }
+ if (i == MAX_CLIENTS) {
+ NT_LOG(ERR, NTCONNECT,
+ "Cannot register more adapters into NtConnect framework");
+ return -1;
+ }
+
+ meter_hdl[i].drv = drv;
+ return register_ntconn_mod(&drv->p_dev->addr, (void *)&meter_hdl[i],
+ &ntconn_meter_op);
+}
diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_modules.h b/drivers/net/ntnic/ntconnect_modules/ntconn_modules.h
new file mode 100644
index 0000000000..ea379015fe
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect_modules/ntconn_modules.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTCONN_MODULES_H_
+#define _NTCONN_MODULES_H_
+
+#include "ntos_system.h"
+
+/*
+ * All defined NT connection modules
+ */
+int ntconn_adap_register(struct drv_s *drv);
+int ntconn_stat_register(struct drv_s *drv);
+int ntconn_flow_register(struct drv_s *drv);
+int ntconn_meter_register(struct drv_s *drv);
+int ntconn_test_register(struct drv_s *drv);
+
+#endif /* _NTCONN_MODULES_H_ */
diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_stat.c b/drivers/net/ntnic/ntconnect_modules/ntconn_stat.c
new file mode 100644
index 0000000000..1b3e59fcc1
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect_modules/ntconn_stat.c
@@ -0,0 +1,876 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <rte_dev.h>
+#include <rte_bus_pci.h>
+#include <ethdev_pci.h>
+#include <rte_ethdev.h>
+
+#include "ntconnect.h"
+#include "ntconnect_api_statistic.h"
+#include "ntos_system.h"
+#include "ntconn_modules.h"
+#include "ntconn_mod_helper.h"
+#include "nt_util.h"
+#include "ntlog.h"
+#include "ntnic_xstats.h"
+
+#define STAT_VERSION_MAJOR 0U
+#define STAT_VERSION_MINOR 2U
+
+#define this_module_name "stat"
+
+/*
+ * Supported Stat Layout Versions
+ */
+#define NUM_LAYOUT_VERSIONS_SUPPORTED (RTE_DIM(layout_versions_supported))
+static int layout_versions_supported[] = {
+ 6,
+ /*
+ * Add here other layout versions to support
+ * When more versions are added, add new version dependent binary reply structures
+ * in ntconnect_api.h file for client to select on reading layout_version
+ */
+};
+
+enum snap_addr_select_e {
+ SNAP_COLORS,
+ SNAP_QUEUES,
+ SNAP_RX_PORT,
+ SNAP_TX_PORT,
+ SNAP_ADDR_COUNT
+};
+
+struct snap_addr_s {
+ const uint64_t *ptr;
+ unsigned int size;
+};
+
+struct snaps_s {
+ int client_id;
+ /* Pointers into buffer */
+ struct snap_addr_s snap_addr[SNAP_ADDR_COUNT];
+ uint64_t *buffer;
+ struct snaps_s *next;
+};
+
+static struct stat_hdl {
+ struct drv_s *drv;
+ nt4ga_stat_t *p_nt4ga_stat;
+ struct snaps_s *snaps_base;
+} stat_hdl;
+
+enum stat_type_e {
+ STAT_TYPE_COLOR,
+ STAT_TYPE_QUEUE,
+ STAT_TYPE_RX,
+ STAT_TYPE_TX,
+ STAT_TYPE_FLOWMATCHER
+};
+
+static int func_get_snap_colors(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_get_snap_queues(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_get_snap_rx_port(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_get_snap_tx_port(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static struct func_s func_snap_level2[] = {
+ { "colors", NULL, func_get_snap_colors },
+ { "queues", NULL, func_get_snap_queues },
+ { "rx_counters", NULL, func_get_snap_rx_port },
+ { "tx_counters", NULL, func_get_snap_tx_port },
+ { NULL, NULL, NULL },
+};
+
+static int func_get_layout_version(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_get_flm(void *hdl, int client_id, struct ntconn_header_s *hdr,
+ char **data, int *len);
+static int func_get_color(void *hdl, int client_id, struct ntconn_header_s *hdr,
+ char **data, int *len);
+static int func_get_queue(void *hdl, int client_id, struct ntconn_header_s *hdr,
+ char **data, int *len);
+static int func_get_rx_counters(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_get_tx_counters(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+static int func_get_flm_layout_version(void *hdl, int client_id,
+ struct ntconn_header_s *hdr, char **data,
+ int *len);
+
+static struct func_s funcs_get_level1[] = {
+ { "snapshot", func_snap_level2, NULL },
+ { "layout_version", NULL, func_get_layout_version },
+ { "flm", NULL, func_get_flm },
+ { "colors", NULL, func_get_color },
+ { "queues", NULL, func_get_queue },
+ { "rx_counters", NULL, func_get_rx_counters },
+ { "tx_counters", NULL, func_get_tx_counters },
+ { "flm_layout_version", NULL, func_get_flm_layout_version },
+ { NULL, NULL, NULL },
+};
+
+/*
+ * Entry level
+ */
+static int func_snapshot(void *hdl, int client_id, struct ntconn_header_s *hdr,
+ char **data, int *len);
+static struct func_s stat_entry_funcs[] = {
+ { "get", funcs_get_level1, NULL },
+ { "snapshot", NULL, func_snapshot },
+ { NULL, NULL, NULL },
+};
+
+static int read_flm(nt4ga_stat_t *hwstat, uint64_t *val, int nbc)
+{
+ struct ntc_stat_get_data_s *cdata = (struct ntc_stat_get_data_s *)val;
+
+ cdata->nb_counters = (uint64_t)nbc;
+ cdata->timestamp = hwstat->last_timestamp;
+ cdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch;
+
+ struct rte_eth_xstat stats[100];
+ struct rte_eth_xstat_name names[100];
+ int cnt_names = nthw_xstats_get_names(hwstat, names, 100,
+ hwstat->mp_nthw_stat->mb_is_vswitch);
+ int cnt_values = nthw_xstats_get(hwstat, stats, 100,
+ hwstat->mp_nthw_stat->mb_is_vswitch, 0);
+ assert(cnt_names == cnt_values);
+
+ /* virt/cap same */
+ struct flowmatcher_type_fields_s *flm =
+ (struct flowmatcher_type_fields_s *)cdata->data;
+ if (hwstat->mp_stat_structs_flm) {
+ int c;
+
+ for (c = 0; c < nbc; c++) {
+ flm->current = hwstat->mp_stat_structs_flm->current;
+ flm->learn_done = hwstat->mp_stat_structs_flm->learn_done;
+ flm->learn_ignore =
+ hwstat->mp_stat_structs_flm->learn_ignore;
+ flm->learn_fail = hwstat->mp_stat_structs_flm->learn_fail;
+ flm->unlearn_done =
+ hwstat->mp_stat_structs_flm->unlearn_done;
+ flm->unlearn_ignore =
+ hwstat->mp_stat_structs_flm->unlearn_ignore;
+ flm->auto_unlearn_done =
+ hwstat->mp_stat_structs_flm->auto_unlearn_done;
+ flm->auto_unlearn_ignore =
+ hwstat->mp_stat_structs_flm->auto_unlearn_ignore;
+ flm->auto_unlearn_fail =
+ hwstat->mp_stat_structs_flm->auto_unlearn_fail;
+ flm->timeout_unlearn_done =
+ hwstat->mp_stat_structs_flm->timeout_unlearn_done;
+ flm->rel_done = hwstat->mp_stat_structs_flm->rel_done;
+ flm->rel_ignore = hwstat->mp_stat_structs_flm->rel_ignore;
+ flm->prb_done = hwstat->mp_stat_structs_flm->prb_done;
+ flm->prb_ignore = hwstat->mp_stat_structs_flm->prb_ignore;
+
+ flm->sta_done = hwstat->mp_stat_structs_flm->sta_done;
+ flm->inf_done = hwstat->mp_stat_structs_flm->inf_done;
+ flm->inf_skip = hwstat->mp_stat_structs_flm->inf_skip;
+ flm->pck_hit = hwstat->mp_stat_structs_flm->pck_hit;
+ flm->pck_miss = hwstat->mp_stat_structs_flm->pck_miss;
+ flm->pck_unh = hwstat->mp_stat_structs_flm->pck_unh;
+ flm->pck_dis = hwstat->mp_stat_structs_flm->pck_dis;
+ flm->csh_hit = hwstat->mp_stat_structs_flm->csh_hit;
+ flm->csh_miss = hwstat->mp_stat_structs_flm->csh_miss;
+ flm->csh_unh = hwstat->mp_stat_structs_flm->csh_unh;
+ flm->cuc_start = hwstat->mp_stat_structs_flm->cuc_start;
+ flm->cuc_move = hwstat->mp_stat_structs_flm->cuc_move;
+ }
+ } else {
+ memset(flm, 0, sizeof(*hwstat->mp_stat_structs_flm));
+ }
+ return nbc * NUM_STAT_RECORD_TYPE_FLOWMATCHER + STAT_INFO_ELEMENTS;
+}
+
+static int read_colors(nt4ga_stat_t *hwstat, uint64_t *val, int nbc)
+{
+ struct ntc_stat_get_data_s *cdata = (struct ntc_stat_get_data_s *)val;
+
+ cdata->nb_counters = (uint64_t)nbc;
+ cdata->timestamp = hwstat->last_timestamp;
+ cdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch;
+
+ /* virt/cap same */
+ struct color_type_fields_s *clr =
+ (struct color_type_fields_s *)cdata->data;
+ int c;
+
+ for (c = 0; c < nbc; c++) {
+ clr->pkts = hwstat->mp_stat_structs_color[c].color_packets;
+ clr->octets = hwstat->mp_stat_structs_color[c].color_bytes;
+ clr->tcp_flgs =
+ (uint64_t)hwstat->mp_stat_structs_color[c].tcp_flags;
+ clr++;
+ }
+ return nbc * NUM_STAT_RECORD_TYPE_COLOR + STAT_INFO_ELEMENTS;
+}
+
+static int read_queues(nt4ga_stat_t *hwstat, uint64_t *val, int nbq)
+{
+ struct ntc_stat_get_data_s *qdata = (struct ntc_stat_get_data_s *)val;
+
+ qdata->nb_counters = (uint64_t)nbq;
+ qdata->timestamp = hwstat->last_timestamp;
+ qdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch;
+
+ /* virt/cap same */
+ struct queue_type_fields_s *que =
+ (struct queue_type_fields_s *)qdata->data;
+ int q;
+
+ for (q = 0; q < nbq; q++) {
+ que->flush_pkts = hwstat->mp_stat_structs_hb[q].flush_packets;
+ que->drop_pkts = hwstat->mp_stat_structs_hb[q].drop_packets;
+ que->fwd_pkts = hwstat->mp_stat_structs_hb[q].fwd_packets;
+ que->dbs_drop_pkts = hwstat->mp_stat_structs_hb[q].dbs_drop_packets;
+ que->flush_octets = hwstat->mp_stat_structs_hb[q].flush_bytes;
+ que->drop_octets = hwstat->mp_stat_structs_hb[q].drop_bytes;
+ que->fwd_octets = hwstat->mp_stat_structs_hb[q].fwd_bytes;
+ que->dbs_drop_octets = hwstat->mp_stat_structs_hb[q].dbs_drop_bytes;
+ que++;
+ }
+ return nbq * NUM_STAT_RECORD_TYPE_QUEUE + STAT_INFO_ELEMENTS;
+}
+
+static void copy_rmon_stat(struct port_counters_v2 *cptr,
+ struct stat_rmon_s *rmon)
+{
+ rmon->drop_events = cptr->drop_events;
+ rmon->pkts = cptr->pkts;
+ rmon->octets = cptr->octets;
+ rmon->broadcast_pkts = cptr->broadcast_pkts;
+ rmon->multicast_pkts = cptr->multicast_pkts;
+ rmon->unicast_pkts = cptr->unicast_pkts;
+ rmon->pkts_alignment = cptr->pkts_alignment;
+ rmon->pkts_code_violation = cptr->pkts_code_violation;
+ rmon->pkts_crc = cptr->pkts_crc;
+ rmon->undersize_pkts = cptr->undersize_pkts;
+ rmon->oversize_pkts = cptr->oversize_pkts;
+ rmon->fragments = cptr->fragments;
+ rmon->jabbers_not_truncated = cptr->jabbers_not_truncated;
+ rmon->jabbers_truncated = cptr->jabbers_truncated;
+ rmon->pkts_64_octets = cptr->pkts_64_octets;
+ rmon->pkts_65_to_127_octets = cptr->pkts_65_to_127_octets;
+ rmon->pkts_128_to_255_octets = cptr->pkts_128_to_255_octets;
+ rmon->pkts_256_to_511_octets = cptr->pkts_256_to_511_octets;
+ rmon->pkts_512_to_1023_octets = cptr->pkts_512_to_1023_octets;
+ rmon->pkts_1024_to_1518_octets = cptr->pkts_1024_to_1518_octets;
+ rmon->pkts_1519_to_2047_octets = cptr->pkts_1519_to_2047_octets;
+ rmon->pkts_2048_to_4095_octets = cptr->pkts_2048_to_4095_octets;
+ rmon->pkts_4096_to_8191_octets = cptr->pkts_4096_to_8191_octets;
+ rmon->pkts_8192_to_max_octets = cptr->pkts_8192_to_max_octets;
+}
+
+static int read_rx_counters(nt4ga_stat_t *hwstat, uint64_t *val, int nbp)
+{
+ struct ntc_stat_get_data_s *rxdata = (struct ntc_stat_get_data_s *)val;
+
+ rxdata->nb_counters = (uint64_t)nbp;
+ rxdata->timestamp = hwstat->last_timestamp;
+ rxdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch;
+
+ if (rxdata->is_virt) {
+ struct rtx_type_fields_virt_s *rxc =
+ (struct rtx_type_fields_virt_s *)rxdata->data;
+ int p;
+
+ for (p = 0; p < nbp; p++) {
+ rxc->octets =
+ hwstat->virt.mp_stat_structs_port_rx[p].octets;
+ rxc->pkts = hwstat->virt.mp_stat_structs_port_rx[p].pkts;
+ rxc->drop_events =
+ hwstat->virt.mp_stat_structs_port_rx[p].drop_events;
+ rxc->qos_drop_octets =
+ hwstat->virt.mp_stat_structs_port_rx[p]
+ .qos_drop_octets;
+ rxc->qos_drop_pkts = hwstat->virt.mp_stat_structs_port_rx[p]
+ .qos_drop_pkts;
+ rxc++;
+ }
+ return nbp * NUM_STAT_RECORD_TYPE_RX_PORT_VIRT +
+ STAT_INFO_ELEMENTS;
+ } else {
+ struct rx_type_fields_cap_s *rxc =
+ (struct rx_type_fields_cap_s *)rxdata->data;
+ int p;
+
+ for (p = 0; p < nbp; p++) {
+ copy_rmon_stat(&hwstat->cap.mp_stat_structs_port_rx[p],
+ &rxc->rmon);
+
+ /* Rx only port counters */
+ rxc->mac_drop_events =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .mac_drop_events;
+ rxc->pkts_lr =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_lr;
+ rxc->duplicate =
+ hwstat->cap.mp_stat_structs_port_rx[p].duplicate;
+ rxc->pkts_ip_chksum_error =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_ip_chksum_error;
+ rxc->pkts_udp_chksum_error =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_udp_chksum_error;
+ rxc->pkts_tcp_chksum_error =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_tcp_chksum_error;
+ rxc->pkts_giant_undersize =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_giant_undersize;
+ rxc->pkts_baby_giant =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_baby_giant;
+ rxc->pkts_not_isl_vlan_mpls =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_not_isl_vlan_mpls;
+ rxc->pkts_isl =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_isl;
+ rxc->pkts_vlan =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_vlan;
+ rxc->pkts_isl_vlan =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan;
+ rxc->pkts_mpls =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_mpls;
+ rxc->pkts_isl_mpls =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_isl_mpls;
+ rxc->pkts_vlan_mpls = hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_vlan_mpls;
+ rxc->pkts_isl_vlan_mpls =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_isl_vlan_mpls;
+ rxc->pkts_no_filter = hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_no_filter;
+ rxc->pkts_dedup_drop =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_dedup_drop;
+ rxc->pkts_filter_drop =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .pkts_filter_drop;
+ rxc->pkts_overflow =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_overflow;
+ rxc->pkts_dbs_drop =
+ hwstat->cap.mp_stat_structs_port_rx[p].pkts_dbs_drop;
+ rxc->octets_no_filter =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .octets_no_filter;
+ rxc->octets_dedup_drop =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .octets_dedup_drop;
+ rxc->octets_filter_drop =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .octets_filter_drop;
+ rxc->octets_overflow =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .octets_overflow;
+ rxc->octets_dbs_drop =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .octets_dbs_drop;
+ rxc->ipft_first_hit = hwstat->cap.mp_stat_structs_port_rx[p]
+ .ipft_first_hit;
+ rxc->ipft_first_not_hit =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .ipft_first_not_hit;
+ rxc->ipft_mid_hit =
+ hwstat->cap.mp_stat_structs_port_rx[p].ipft_mid_hit;
+ rxc->ipft_mid_not_hit =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .ipft_mid_not_hit;
+ rxc->ipft_last_hit =
+ hwstat->cap.mp_stat_structs_port_rx[p].ipft_last_hit;
+ rxc->ipft_last_not_hit =
+ hwstat->cap.mp_stat_structs_port_rx[p]
+ .ipft_last_not_hit;
+ rxc++;
+ }
+ return nbp * NUM_STAT_RECORD_TYPE_RX_PORT_CAP +
+ STAT_INFO_ELEMENTS;
+ }
+}
+
+static int read_tx_counters(nt4ga_stat_t *hwstat, uint64_t *val, int nbp)
+{
+ struct ntc_stat_get_data_s *txdata = (struct ntc_stat_get_data_s *)val;
+
+ txdata->nb_counters = (uint64_t)nbp;
+ txdata->timestamp = hwstat->last_timestamp;
+ txdata->is_virt = hwstat->mp_nthw_stat->mb_is_vswitch;
+
+ if (txdata->is_virt) {
+ struct rtx_type_fields_virt_s *txc =
+ (struct rtx_type_fields_virt_s *)txdata->data;
+ int p;
+
+ for (p = 0; p < nbp; p++) {
+ txc->octets =
+ hwstat->virt.mp_stat_structs_port_tx[p].octets;
+ txc->pkts = hwstat->virt.mp_stat_structs_port_tx[p].pkts;
+ txc->drop_events =
+ hwstat->virt.mp_stat_structs_port_tx[p].drop_events;
+ txc->qos_drop_octets =
+ hwstat->virt.mp_stat_structs_port_tx[p]
+ .qos_drop_octets;
+ txc->qos_drop_pkts = hwstat->virt.mp_stat_structs_port_tx[p]
+ .qos_drop_pkts;
+ txc++;
+ }
+ return nbp * NUM_STAT_RECORD_TYPE_TX_PORT_VIRT +
+ STAT_INFO_ELEMENTS;
+ } else {
+ struct tx_type_fields_cap_s *txc =
+ (struct tx_type_fields_cap_s *)txdata->data;
+ int p;
+
+ for (p = 0; p < nbp; p++) {
+ copy_rmon_stat(&hwstat->cap.mp_stat_structs_port_tx[p],
+ &txc->rmon);
+ txc->rmon.pkts = hwstat->a_port_tx_packets_total[p];
+ txc++;
+ }
+ return nbp * NUM_STAT_RECORD_TYPE_TX_PORT_CAP +
+ STAT_INFO_ELEMENTS;
+ }
+}
+
+static int func_get_layout_version(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ *data = malloc(sizeof(int));
+ if (!*data) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+
+ *(int *)*data = stat->p_nt4ga_stat->mp_nthw_stat->mn_stat_layout_version;
+ *len = sizeof(int);
+ return REQUEST_OK;
+}
+
+static int func_get_flm_layout_version(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ *data = malloc(sizeof(int));
+ if (!*data) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+
+ *(int *)*data = (stat->p_nt4ga_stat->flm_stat_ver < 18) ? 1 : 2;
+ *len = sizeof(int);
+ return REQUEST_OK;
+}
+
+/*
+ * Return total number of 64bit counters occupied by this stat type
+ * additionally, returns total number of records for this type (ie number of queues, ports, etc)
+ */
+static int get_size(struct stat_hdl *stat, enum stat_type_e type,
+ int *num_records)
+{
+ int nrec, size;
+
+ switch (type) {
+ case STAT_TYPE_COLOR:
+ nrec = stat->p_nt4ga_stat->mp_nthw_stat->m_nb_color_counters / 2;
+ size = nrec * NUM_STAT_RECORD_TYPE_COLOR;
+ break;
+ case STAT_TYPE_QUEUE:
+ nrec = stat->p_nt4ga_stat->mp_nthw_stat->m_nb_rx_host_buffers;
+ size = nrec * NUM_STAT_RECORD_TYPE_QUEUE;
+ break;
+ case STAT_TYPE_RX:
+ nrec = stat->p_nt4ga_stat->mn_rx_ports;
+ size = nrec * ((stat->p_nt4ga_stat->mp_nthw_stat->mb_is_vswitch) ?
+ NUM_STAT_RECORD_TYPE_RX_PORT_VIRT :
+ NUM_STAT_RECORD_TYPE_RX_PORT_CAP);
+ break;
+ case STAT_TYPE_TX:
+ nrec = stat->p_nt4ga_stat->mn_tx_ports;
+ size = nrec * ((stat->p_nt4ga_stat->mp_nthw_stat->mb_is_vswitch) ?
+ NUM_STAT_RECORD_TYPE_TX_PORT_VIRT :
+ NUM_STAT_RECORD_TYPE_TX_PORT_CAP);
+ break;
+ case STAT_TYPE_FLOWMATCHER:
+ nrec = 1;
+ size = nrec * NUM_STAT_RECORD_TYPE_FLOWMATCHER;
+ break;
+ }
+
+ *num_records = nrec;
+ return size + STAT_INFO_ELEMENTS;
+}
+
+static int do_get_stats(struct stat_hdl *stat, char **data, int *len,
+ enum stat_type_e stype,
+ int (*read_counters)(nt4ga_stat_t *, uint64_t *, int))
+{
+ int nbg;
+ int size = get_size(stat, stype, &nbg);
+
+ size *= sizeof(uint64_t);
+ uint64_t *val = (uint64_t *)malloc(size);
+
+ if (!val) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+
+ pthread_mutex_lock(&stat->drv->ntdrv.stat_lck);
+ read_counters(stat->p_nt4ga_stat, val, nbg);
+ pthread_mutex_unlock(&stat->drv->ntdrv.stat_lck);
+
+ *data = (char *)val;
+ *len = size;
+ return REQUEST_OK;
+}
+
+/*
+ * Stat Request functions
+ */
+static int func_get_flm(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ return do_get_stats(stat, data, len, STAT_TYPE_FLOWMATCHER, read_flm);
+}
+
+static int func_get_color(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ return do_get_stats(stat, data, len, STAT_TYPE_COLOR, read_colors);
+}
+
+static int func_get_queue(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ return do_get_stats(stat, data, len, STAT_TYPE_QUEUE, read_queues);
+}
+
+static int func_get_rx_counters(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ return do_get_stats(stat, data, len, STAT_TYPE_RX, read_rx_counters);
+}
+
+static int func_get_tx_counters(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ return do_get_stats(stat, data, len, STAT_TYPE_TX, read_tx_counters);
+}
+
+/*
+ * Snapshot handling. This is to ensure atomic reading of all statistics in one collection
+ */
+
+static struct snaps_s *find_client_snap_data(struct stat_hdl *stat,
+ int client_id,
+ struct snaps_s **parent)
+{
+ struct snaps_s *snaps = stat->snaps_base;
+
+ if (parent)
+ *parent = NULL;
+ while (snaps && snaps->client_id != client_id) {
+ if (parent)
+ *parent = snaps;
+ snaps = snaps->next;
+ }
+
+ return snaps;
+}
+
+static struct snaps_s *get_client_snap_data(struct stat_hdl *stat,
+ int client_id)
+{
+ struct snaps_s *snaps = find_client_snap_data(stat, client_id, NULL);
+
+ if (!snaps) {
+ snaps = malloc(sizeof(struct snaps_s)); /* return NULL on malloc failure */
+ if (snaps) {
+ snaps->client_id = client_id;
+ snaps->next = stat->snaps_base;
+ stat->snaps_base = snaps;
+ snaps->buffer = NULL;
+ }
+ }
+ return snaps;
+}
+
+static int func_snapshot(void *hdl, int client_id,
+ struct ntconn_header_s *hdr _unused, char **data,
+ int *len)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+ int nbc, nbq, nbpr, nbpt;
+ struct snaps_s *snaps;
+
+ if (!stat->p_nt4ga_stat || !stat->p_nt4ga_stat->mp_nthw_stat) {
+ *data = NULL;
+ *len = 0;
+ return REQUEST_ERR;
+ }
+ snaps = get_client_snap_data(stat, client_id);
+ if (!snaps)
+ goto err_out;
+
+ if (snaps->buffer)
+ free(snaps->buffer);
+
+ snaps->snap_addr[SNAP_COLORS].size =
+ (unsigned int)get_size(stat, STAT_TYPE_COLOR, &nbc);
+ snaps->snap_addr[SNAP_QUEUES].size =
+ (unsigned int)get_size(stat, STAT_TYPE_QUEUE, &nbq);
+ snaps->snap_addr[SNAP_RX_PORT].size =
+ (unsigned int)get_size(stat, STAT_TYPE_RX, &nbpr);
+ snaps->snap_addr[SNAP_TX_PORT].size =
+ (unsigned int)get_size(stat, STAT_TYPE_TX, &nbpt);
+
+ unsigned int tot_size = snaps->snap_addr[SNAP_COLORS].size +
+ snaps->snap_addr[SNAP_QUEUES].size +
+ snaps->snap_addr[SNAP_RX_PORT].size +
+ snaps->snap_addr[SNAP_TX_PORT].size;
+
+ snaps->buffer = malloc(tot_size * sizeof(uint64_t));
+ if (!snaps->buffer) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+ uint64_t *val = snaps->buffer;
+
+ snaps->snap_addr[SNAP_COLORS].ptr = val;
+ pthread_mutex_lock(&stat->drv->ntdrv.stat_lck);
+ unsigned int size = read_colors(stat->p_nt4ga_stat, val, nbc);
+
+ if (size != snaps->snap_addr[SNAP_COLORS].size) {
+ NT_LOG(ERR, NTCONNECT, "stat.snapshot: color size mismatch");
+ goto err_out;
+ }
+
+ val += size;
+ snaps->snap_addr[SNAP_QUEUES].ptr = val;
+ size = read_queues(stat->p_nt4ga_stat, val, nbq);
+ if (size != snaps->snap_addr[SNAP_QUEUES].size) {
+ NT_LOG(ERR, NTCONNECT,
+ "stat.snapshot: queue statistic size mismatch");
+ goto err_out;
+ }
+
+ val += size;
+ snaps->snap_addr[SNAP_RX_PORT].ptr = val;
+ size = read_rx_counters(stat->p_nt4ga_stat, val, nbpr);
+ if (size != snaps->snap_addr[SNAP_RX_PORT].size) {
+ NT_LOG(ERR, NTCONNECT,
+ "stat.snapshot: Rx port statistic size mismatch %i, %i",
+ size, snaps->snap_addr[SNAP_RX_PORT].size);
+ goto err_out;
+ }
+
+ val += size;
+ snaps->snap_addr[SNAP_TX_PORT].ptr = val;
+ size = read_tx_counters(stat->p_nt4ga_stat, val, nbpt);
+ if (size != snaps->snap_addr[SNAP_TX_PORT].size) {
+ NT_LOG(ERR, NTCONNECT,
+ "stat.snapshot: Tx port statistic size mismatch");
+ goto err_out;
+ }
+
+ pthread_mutex_unlock(&stat->drv->ntdrv.stat_lck);
+
+ *data = NULL;
+ *len = 0;
+ return REQUEST_OK;
+
+err_out:
+ pthread_mutex_unlock(&stat->drv->ntdrv.stat_lck);
+ return ntconn_error(data, len, "stat",
+ NTCONN_ERR_CODE_INTERNAL_REPLY_ERROR);
+}
+
+static int get_snap_data(void *hdl, int client_id, char **data, int *len,
+ enum snap_addr_select_e snap_addr_idx)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+ struct snaps_s *snaps = find_client_snap_data(stat, client_id, NULL);
+
+ if (!snaps || !snaps->buffer)
+ return ntconn_error(data, len, "stat", NTCONN_ERR_CODE_NO_DATA);
+
+ int ln = snaps->snap_addr[snap_addr_idx].size * sizeof(uint64_t);
+
+ *data = malloc(ln);
+ if (!data) {
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "memory allocation failed");
+ return REQUEST_ERR;
+ }
+ memcpy(*data, snaps->snap_addr[snap_addr_idx].ptr, ln);
+ *len = ln;
+
+ return REQUEST_OK;
+}
+
+static int func_get_snap_colors(void *hdl, int client_id,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ return get_snap_data(hdl, client_id, data, len, SNAP_COLORS);
+}
+
+static int func_get_snap_queues(void *hdl, int client_id,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ return get_snap_data(hdl, client_id, data, len, SNAP_QUEUES);
+}
+
+static int func_get_snap_rx_port(void *hdl, int client_id,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ return get_snap_data(hdl, client_id, data, len, SNAP_RX_PORT);
+}
+
+static int func_get_snap_tx_port(void *hdl, int client_id,
+ struct ntconn_header_s *hdr _unused,
+ char **data, int *len)
+{
+ return get_snap_data(hdl, client_id, data, len, SNAP_TX_PORT);
+}
+
+/*
+ * Stat main request function
+ */
+static int stat_request(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr, char *function,
+ char **data, int *len)
+{
+ return execute_function(this_module_name, hdl, client_id, hdr, function,
+ stat_entry_funcs, data, len, 0);
+}
+
+static void stat_free_data(void *hdl _unused, char *data)
+{
+ free(data);
+}
+
+static void stat_client_cleanup(void *hdl, int client_id)
+{
+ struct stat_hdl *stat = (struct stat_hdl *)hdl;
+ struct snaps_s *snaps_parent;
+ struct snaps_s *snaps =
+ find_client_snap_data(stat, client_id, &snaps_parent);
+
+ if (!snaps)
+ return;
+
+ if (snaps_parent)
+ snaps_parent->next = snaps->next;
+ else
+ stat->snaps_base = snaps->next;
+
+ if (snaps->buffer)
+ free(snaps->buffer);
+ free(snaps);
+}
+
+static const ntconnapi_t ntconn_stat_op = {
+ this_module_name, STAT_VERSION_MAJOR, STAT_VERSION_MINOR,
+ stat_request, stat_free_data, stat_client_cleanup
+};
+
+int ntconn_stat_register(struct drv_s *drv)
+{
+ stat_hdl.drv = drv;
+ stat_hdl.p_nt4ga_stat = &drv->ntdrv.adapter_info.nt4ga_stat;
+
+ /* Check supported Layout_versions by this module */
+ size_t i;
+
+ for (i = 0; i < NUM_LAYOUT_VERSIONS_SUPPORTED; i++) {
+ if (stat_hdl.p_nt4ga_stat->mp_nthw_stat->mn_stat_layout_version ==
+ layout_versions_supported[i])
+ break;
+ }
+
+ if (i == NUM_LAYOUT_VERSIONS_SUPPORTED) {
+ NT_LOG(ERR, NTCONNECT,
+ "stat: layout version %i is not supported. Module will not be activated",
+ stat_hdl.p_nt4ga_stat->mp_nthw_stat->mn_stat_layout_version);
+ return -1;
+ }
+
+ return register_ntconn_mod(&drv->p_dev->addr, (void *)&stat_hdl,
+ &ntconn_stat_op);
+}
diff --git a/drivers/net/ntnic/ntconnect_modules/ntconn_test.c b/drivers/net/ntnic/ntconnect_modules/ntconn_test.c
new file mode 100644
index 0000000000..907ea4ff5f
--- /dev/null
+++ b/drivers/net/ntnic/ntconnect_modules/ntconn_test.c
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <errno.h>
+#include "ntnic_ethdev.h"
+#include "ntconnect.h"
+#include "ntos_system.h"
+#include "ntconn_modules.h"
+#include "ntconn_mod_helper.h"
+#include "nt_util.h"
+#include "ntlog.h"
+#include "ntnic_vf_vdpa.h"
+
+#include "ntconnect_api_test.h"
+
+#define NTCONN_TEST_VERSION_MAJOR 0U
+#define NTCONN_TEST_VERSION_MINOR 1U
+
+#define this_module_name "ntconnect_test"
+
+#define MAX_CLIENTS 32
+
+#define UNUSED __rte_unused
+
+static struct test_hdl_s {
+ struct drv_s *drv;
+} test_hdl[MAX_CLIENTS];
+
+/*
+ * Test functions
+ */
+static int func_test(void *hdl, int client_id, struct ntconn_header_s *hdr,
+ char **data, int *len);
+static struct func_s adapter_entry_funcs[] = {
+ { "test", NULL, func_test },
+ { NULL, NULL, NULL },
+};
+
+static int func_test(void *hdl _unused, int client_id _unused,
+ struct ntconn_header_s *hdr, char **data, int *len)
+{
+ int status = 0;
+ int number = 0;
+ uint32_t size;
+ struct test_s *test_cpy = (struct test_s *)&(*data)[hdr->len];
+
+ if (hdr->blob_len < sizeof(struct test_s)) {
+ NT_LOG(ERR, NTCONNECT, "Error in test data: to small");
+ status = -1;
+ goto TEST_ERROR;
+ }
+
+ number = test_cpy->number;
+ size = sizeof(struct test_s) + sizeof(uint64_t) * number;
+
+ if (hdr->blob_len != size) {
+ NT_LOG(ERR, NTCONNECT, "Error in test data: wrong size");
+ status = -1;
+ goto TEST_ERROR;
+ }
+
+ {
+ *data = malloc(sizeof(struct test_s) +
+ number * sizeof(uint64_t));
+ if (!*data)
+ goto TEST_ERROR_MALLOC;
+ struct test_s *return_value = (struct test_s *)*data;
+ *len = sizeof(struct test_s) + number * sizeof(uint64_t);
+ for (int i = 0; i < number; i++)
+ return_value->test[i] = test_cpy->test[i];
+ return_value->status = 0;
+ return_value->number = number;
+ return REQUEST_OK;
+ }
+
+TEST_ERROR:
+
+ {
+ *data = malloc(sizeof(struct test_s));
+ if (!*data)
+ goto TEST_ERROR_MALLOC;
+ struct test_s *return_value = (struct test_s *)*data;
+ *len = sizeof(struct test_s);
+ return_value->status = status;
+ return_value->number = 0;
+ return REQUEST_OK;
+ }
+
+TEST_ERROR_MALLOC:
+
+ *len = 0;
+ NT_LOG(ERR, NTCONNECT, "Not able to allocate memory %s", __func__);
+ return REQUEST_ERR;
+}
+
+enum {
+ FLOW_API_FUNC_CREATE,
+ FLOW_API_FUNC_VALIDATE,
+};
+
+static int test_request(void *hdl, int client_id _unused,
+ struct ntconn_header_s *hdr, char *function,
+ char **data, int *len)
+{
+ return execute_function(this_module_name, hdl, client_id, hdr, function,
+ adapter_entry_funcs, data, len, 0);
+}
+
+static void test_free_data(void *hdl _unused, char *data)
+{
+ if (data)
+ free(data);
+}
+
+static void test_client_cleanup(void *hdl _unused, int client_id _unused)
+{
+ /* Nothing to do */
+}
+
+static const ntconnapi_t ntconn_test_op = { this_module_name,
+ NTCONN_TEST_VERSION_MAJOR,
+ NTCONN_TEST_VERSION_MINOR,
+ test_request,
+ test_free_data,
+ test_client_cleanup
+ };
+
+int ntconn_test_register(struct drv_s *drv)
+{
+ int i;
+
+ for (i = 0; i < MAX_CLIENTS; i++) {
+ if (test_hdl[i].drv == NULL)
+ break;
+ }
+ if (i == MAX_CLIENTS) {
+ NT_LOG(ERR, NTCONNECT,
+ "Cannot register more adapters into NtConnect framework");
+ return -1;
+ }
+
+ test_hdl[i].drv = drv;
+ return register_ntconn_mod(&drv->p_dev->addr, (void *)&test_hdl[i],
+ &ntconn_test_op);
+}
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* Re: [PATCH 8/8] net/ntnic: adds socket connection to PMD
2023-08-16 13:25 ` [PATCH 8/8] net/ntnic: adds socket connection to PMD Mykola Kostenok
@ 2023-08-16 14:46 ` Stephen Hemminger
2023-08-25 13:52 ` Christian Koue Muf
2023-08-16 14:47 ` Stephen Hemminger
1 sibling, 1 reply; 142+ messages in thread
From: Stephen Hemminger @ 2023-08-16 14:46 UTC (permalink / raw)
To: Mykola Kostenok; +Cc: dev, Christian Koue Muf
On Wed, 16 Aug 2023 15:25:52 +0200
Mykola Kostenok <mko-plv@napatech.com> wrote:
> From: Christian Koue Muf <ckm@napatech.com>
>
> The socket connection is used by Napatech's tools for monitoring
> and rte_flow programming from other processes.
>
> Signed-off-by: Christian Koue Muf <ckm@napatech.com>
> Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
I would prefer that this be general and work with other PMD's.
Why is existing telemetry model not good enough?
^ permalink raw reply [flat|nested] 142+ messages in thread
* Re: [PATCH 8/8] net/ntnic: adds socket connection to PMD
2023-08-16 13:25 ` [PATCH 8/8] net/ntnic: adds socket connection to PMD Mykola Kostenok
2023-08-16 14:46 ` Stephen Hemminger
@ 2023-08-16 14:47 ` Stephen Hemminger
1 sibling, 0 replies; 142+ messages in thread
From: Stephen Hemminger @ 2023-08-16 14:47 UTC (permalink / raw)
To: Mykola Kostenok; +Cc: dev, Christian Koue Muf
On Wed, 16 Aug 2023 15:25:52 +0200
Mykola Kostenok <mko-plv@napatech.com> wrote:
> From: Christian Koue Muf <ckm@napatech.com>
>
> The socket connection is used by Napatech's tools for monitoring
> and rte_flow programming from other processes.
>
> Signed-off-by: Christian Koue Muf <ckm@napatech.com>
> Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
Also, a proprietary socket API introduces a whole new security attack surface.
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH v2 1/8] net/ntnic: initial commit which adds register defines
2023-08-16 13:25 [PATCH 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (6 preceding siblings ...)
2023-08-16 13:25 ` [PATCH 8/8] net/ntnic: adds socket connection to PMD Mykola Kostenok
@ 2023-08-17 14:43 ` Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 2/8] net/ntnic: adds core registers and fpga functionality Mykola Kostenok
` (7 more replies)
2023-08-18 18:41 ` [PATCH v4 " Mykola Kostenok
` (12 subsequent siblings)
20 siblings, 8 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-17 14:43 UTC (permalink / raw)
To: dev, mko-plv; +Cc: ckm
From: Christian Koue Muf <ckm@napatech.com>
The NTNIC PMD does not rely on a kernel space Napatech driver,
thus all defines related to the register layout is part of the PMD
code, which will be added in later commits.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
drivers/net/meson.build | 1 +
drivers/net/ntnic/include/fpga_model.h | 99 +
drivers/net/ntnic/meson.build | 29 +
drivers/net/ntnic/nthw/nthw_register.h | 19 +
.../supported/nthw_fpga_9563_055_024_0000.c | 4190 ++++++++++
.../nthw/supported/nthw_fpga_instances.h | 14 +
.../nthw/supported/nthw_fpga_modules_defs.h | 166 +
.../supported/nthw_fpga_parameters_defs.h | 209 +
.../nthw/supported/nthw_fpga_registers_defs.h | 7277 +++++++++++++++++
9 files changed, 12004 insertions(+)
create mode 100644 drivers/net/ntnic/include/fpga_model.h
create mode 100644 drivers/net/ntnic/meson.build
create mode 100644 drivers/net/ntnic/nthw/nthw_register.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h
create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h
diff --git a/drivers/net/meson.build b/drivers/net/meson.build
index bd38b533c5..fb6d34b782 100644
--- a/drivers/net/meson.build
+++ b/drivers/net/meson.build
@@ -45,6 +45,7 @@ drivers = [
'nfb',
'nfp',
'ngbe',
+ 'ntnic',
'null',
'octeontx',
'octeon_ep',
diff --git a/drivers/net/ntnic/include/fpga_model.h b/drivers/net/ntnic/include/fpga_model.h
new file mode 100644
index 0000000000..89f1ae9736
--- /dev/null
+++ b/drivers/net/ntnic/include/fpga_model.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef FPGA_MODEL_H_
+#define FPGA_MODEL_H_
+
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+enum nt_fpga_bus_type {
+ BUS_TYPE_UNKNOWN =
+ 0, /* Unknown/uninitialized - keep this as the first enum element */
+ BUS_TYPE_BAR,
+ BUS_TYPE_PCI,
+ BUS_TYPE_CCIP,
+ BUS_TYPE_RAB0,
+ BUS_TYPE_RAB1,
+ BUS_TYPE_RAB2,
+ BUS_TYPE_NMB,
+ BUS_TYPE_NDM,
+ BUS_TYPE_SPI0,
+ BUS_TYPE_SPI = BUS_TYPE_SPI0,
+};
+
+typedef enum nt_fpga_bus_type nt_fpga_bus_type_t;
+
+enum nt_fpga_register_type {
+ REGISTER_TYPE_UNKNOWN =
+ 0, /* Unknown/uninitialized - keep this as the first enum element */
+ REGISTER_TYPE_RW,
+ REGISTER_TYPE_RO,
+ REGISTER_TYPE_WO,
+ REGISTER_TYPE_RC1,
+ REGISTER_TYPE_MIXED,
+};
+
+typedef enum nt_fpga_register_type nt_fpga_register_type_t;
+
+struct nt_fpga_field_init {
+ int id;
+ uint16_t bw;
+ uint16_t low;
+ uint64_t reset_val;
+};
+
+typedef struct nt_fpga_field_init nt_fpga_field_init_t;
+
+struct nt_fpga_register_init {
+ int id;
+ uint32_t addr_rel;
+ uint16_t bw;
+ nt_fpga_register_type_t type;
+ uint64_t reset_val;
+ int nb_fields;
+ struct nt_fpga_field_init *fields;
+};
+
+typedef struct nt_fpga_register_init nt_fpga_register_init_t;
+
+struct nt_fpga_module_init {
+ int id;
+ int instance;
+ int def_id;
+ int major_version;
+ int minor_version;
+ nt_fpga_bus_type_t bus_id;
+ uint32_t addr_base;
+ int nb_registers;
+ struct nt_fpga_register_init *registers;
+};
+
+typedef struct nt_fpga_module_init nt_fpga_module_init_t;
+
+struct nt_fpga_prod_param {
+ const int param_id;
+ const int param_value;
+};
+
+typedef struct nt_fpga_prod_param nt_fpga_prod_param_t;
+
+struct nt_fpga_prod_init {
+ int fpga_item_id;
+ int fpga_product_id;
+ int fpga_version;
+ int fpga_revision;
+ int fpga_patch_no;
+ int fpga_build_no;
+ uint32_t fpga_build_time;
+ int nb_prod_params;
+ struct nt_fpga_prod_param *product_params;
+ int nb_modules;
+ struct nt_fpga_module_init *modules;
+};
+
+typedef struct nt_fpga_prod_init nt_fpga_prod_init_t;
+
+#endif /* FPGA_MODEL_H_ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
new file mode 100644
index 0000000000..99569c2843
--- /dev/null
+++ b/drivers/net/ntnic/meson.build
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020-2023 Napatech A/S
+
+# cflags
+cflags += [
+ '-std=c11',
+]
+
+# includes
+includes = [
+ include_directories('.'),
+ include_directories('include'),
+ include_directories('nthw'),
+ include_directories('nthw/supported'),
+]
+
+# all sources
+sources = files(
+ 'nthw/supported/nthw_fpga_9563_055_024_0000.c',
+)
+
+if is_variable('default_cflags')
+ cflags += default_cflags
+else
+ cflags += machine_args
+ cflags += ['-DALLOW_INTERNAL_API']
+endif
+
+# END
diff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h
new file mode 100644
index 0000000000..5cdbd9fc5d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_register.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_REGISTER_H_
+#define NTHW_REGISTER_H_
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "fpga_model.h"
+
+#include "nthw_fpga_modules_defs.h"
+#include "nthw_fpga_parameters_defs.h"
+#include "nthw_fpga_registers_defs.h"
+
+#endif /* NTHW_REGISTER_H_ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c b/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c
new file mode 100644
index 0000000000..b8113b40da
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_9563_055_024_0000.c
@@ -0,0 +1,4190 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_register.h"
+
+static nt_fpga_field_init_t cat_cct_ctrl_fields[] = {
+ { CAT_CCT_CTRL_ADR, 8, 0, 0x0000 },
+ { CAT_CCT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cct_data_fields[] = {
+ { CAT_CCT_DATA_COLOR, 32, 0, 0x0000 },
+ { CAT_CCT_DATA_KM, 4, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cfn_ctrl_fields[] = {
+ { CAT_CFN_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_CFN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cfn_data_fields[] = {
+ { CAT_CFN_DATA_ENABLE, 1, 0, 0x0000 },
+ { CAT_CFN_DATA_ERR_CV, 2, 99, 0x0000 },
+ { CAT_CFN_DATA_ERR_FCS, 2, 101, 0x0000 },
+ { CAT_CFN_DATA_ERR_INV, 1, 98, 0x0000 },
+ { CAT_CFN_DATA_ERR_L3_CS, 2, 105, 0x0000 },
+ { CAT_CFN_DATA_ERR_L4_CS, 2, 107, 0x0000 },
+ { CAT_CFN_DATA_ERR_TNL_L3_CS, 2, 109, 0x0000 },
+ { CAT_CFN_DATA_ERR_TNL_L4_CS, 2, 111, 0x0000 },
+ { CAT_CFN_DATA_ERR_TNL_TTL_EXP, 2, 115, 0x0000 },
+ { CAT_CFN_DATA_ERR_TRUNC, 2, 103, 0x0000 },
+ { CAT_CFN_DATA_ERR_TTL_EXP, 2, 113, 0x0000 },
+ { CAT_CFN_DATA_INV, 1, 1, 0x0000 },
+ { CAT_CFN_DATA_KM0_OR, 3, 173, 0x0000 },
+ { CAT_CFN_DATA_KM1_OR, 3, 176, 0x0000 },
+ { CAT_CFN_DATA_LC, 8, 164, 0x0000 },
+ { CAT_CFN_DATA_LC_INV, 1, 172, 0x0000 },
+ { CAT_CFN_DATA_MAC_PORT, 2, 117, 0x0000 },
+ { CAT_CFN_DATA_PM_AND_INV, 1, 161, 0x0000 },
+ { CAT_CFN_DATA_PM_CMB, 4, 157, 0x0000 },
+ { CAT_CFN_DATA_PM_CMP, 32, 119, 0x0000 },
+ { CAT_CFN_DATA_PM_DCT, 2, 151, 0x0000 },
+ { CAT_CFN_DATA_PM_EXT_INV, 4, 153, 0x0000 },
+ { CAT_CFN_DATA_PM_INV, 1, 163, 0x0000 },
+ { CAT_CFN_DATA_PM_OR_INV, 1, 162, 0x0000 },
+ { CAT_CFN_DATA_PTC_CFP, 2, 5, 0x0000 },
+ { CAT_CFN_DATA_PTC_FRAG, 4, 36, 0x0000 },
+ { CAT_CFN_DATA_PTC_INV, 1, 2, 0x0000 },
+ { CAT_CFN_DATA_PTC_IP_PROT, 8, 40, 0x0000 },
+ { CAT_CFN_DATA_PTC_ISL, 2, 3, 0x0000 },
+ { CAT_CFN_DATA_PTC_L2, 7, 12, 0x0000 },
+ { CAT_CFN_DATA_PTC_L3, 3, 33, 0x0000 },
+ { CAT_CFN_DATA_PTC_L4, 5, 48, 0x0000 },
+ { CAT_CFN_DATA_PTC_MAC, 5, 7, 0x0000 },
+ { CAT_CFN_DATA_PTC_MPLS, 8, 25, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_FRAG, 4, 81, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_IP_PROT, 8, 85, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_L2, 2, 64, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_L3, 3, 78, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_L4, 5, 93, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_MPLS, 8, 70, 0x0000 },
+ { CAT_CFN_DATA_PTC_TNL_VLAN, 4, 66, 0x0000 },
+ { CAT_CFN_DATA_PTC_TUNNEL, 11, 53, 0x0000 },
+ { CAT_CFN_DATA_PTC_VLAN, 4, 21, 0x0000 },
+ { CAT_CFN_DATA_PTC_VNTAG, 2, 19, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cot_ctrl_fields[] = {
+ { CAT_COT_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_COT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cot_data_fields[] = {
+ { CAT_COT_DATA_COLOR, 32, 0, 0x0000 },
+ { CAT_COT_DATA_KM, 4, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cte_ctrl_fields[] = {
+ { CAT_CTE_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_CTE_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cte_data_fields[] = {
+ { CAT_CTE_DATA_COL_ENABLE, 1, 0, 0x0000 },
+ { CAT_CTE_DATA_COR_ENABLE, 1, 1, 0x0000 },
+ { CAT_CTE_DATA_EPP_ENABLE, 1, 9, 0x0000 },
+ { CAT_CTE_DATA_HSH_ENABLE, 1, 2, 0x0000 },
+ { CAT_CTE_DATA_HST_ENABLE, 1, 8, 0x0000 },
+ { CAT_CTE_DATA_IPF_ENABLE, 1, 4, 0x0000 },
+ { CAT_CTE_DATA_MSK_ENABLE, 1, 7, 0x0000 },
+ { CAT_CTE_DATA_PDB_ENABLE, 1, 6, 0x0000 },
+ { CAT_CTE_DATA_QSL_ENABLE, 1, 3, 0x0000 },
+ { CAT_CTE_DATA_SLC_ENABLE, 1, 5, 0x0000 },
+ { CAT_CTE_DATA_TPE_ENABLE, 1, 10, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cts_ctrl_fields[] = {
+ { CAT_CTS_CTRL_ADR, 9, 0, 0x0000 },
+ { CAT_CTS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_cts_data_fields[] = {
+ { CAT_CTS_DATA_CAT_A, 6, 0, 0x0000 },
+ { CAT_CTS_DATA_CAT_B, 6, 6, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_dct_ctrl_fields[] = {
+ { CAT_DCT_CTRL_ADR, 13, 0, 0x0000 },
+ { CAT_DCT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_dct_data_fields[] = {
+ { CAT_DCT_DATA_RES, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_dct_sel_fields[] = {
+ { CAT_DCT_SEL_LU, 2, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_exo_ctrl_fields[] = {
+ { CAT_EXO_CTRL_ADR, 2, 0, 0x0000 },
+ { CAT_EXO_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_exo_data_fields[] = {
+ { CAT_EXO_DATA_DYN, 5, 0, 0x0000 },
+ { CAT_EXO_DATA_OFS, 11, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte0_ctrl_fields[] = {
+ { CAT_FTE0_CTRL_ADR, 9, 0, 0x0000 },
+ { CAT_FTE0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte0_data_fields[] = {
+ { CAT_FTE0_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte1_ctrl_fields[] = {
+ { CAT_FTE1_CTRL_ADR, 9, 0, 0x0000 },
+ { CAT_FTE1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_fte1_data_fields[] = {
+ { CAT_FTE1_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_join_fields[] = {
+ { CAT_JOIN_J1, 2, 0, 0x0000 },
+ { CAT_JOIN_J2, 1, 8, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcc_ctrl_fields[] = {
+ { CAT_KCC_CTRL_ADR, 11, 0, 0x0000 },
+ { CAT_KCC_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcc_data_fields[] = {
+ { CAT_KCC_DATA_CATEGORY, 8, 64, 0x0000 },
+ { CAT_KCC_DATA_ID, 12, 72, 0x0000 },
+ { CAT_KCC_DATA_KEY, 64, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce0_ctrl_fields[] = {
+ { CAT_KCE0_CTRL_ADR, 3, 0, 0x0000 },
+ { CAT_KCE0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce0_data_fields[] = {
+ { CAT_KCE0_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce1_ctrl_fields[] = {
+ { CAT_KCE1_CTRL_ADR, 3, 0, 0x0000 },
+ { CAT_KCE1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kce1_data_fields[] = {
+ { CAT_KCE1_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs0_ctrl_fields[] = {
+ { CAT_KCS0_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_KCS0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs0_data_fields[] = {
+ { CAT_KCS0_DATA_CATEGORY, 6, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs1_ctrl_fields[] = {
+ { CAT_KCS1_CTRL_ADR, 6, 0, 0x0000 },
+ { CAT_KCS1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_kcs1_data_fields[] = {
+ { CAT_KCS1_DATA_CATEGORY, 6, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_len_ctrl_fields[] = {
+ { CAT_LEN_CTRL_ADR, 3, 0, 0x0000 },
+ { CAT_LEN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_len_data_fields[] = {
+ { CAT_LEN_DATA_DYN1, 5, 28, 0x0000 },
+ { CAT_LEN_DATA_DYN2, 5, 33, 0x0000 },
+ { CAT_LEN_DATA_INV, 1, 38, 0x0000 },
+ { CAT_LEN_DATA_LOWER, 14, 0, 0x0000 },
+ { CAT_LEN_DATA_UPPER, 14, 14, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_rck_ctrl_fields[] = {
+ { CAT_RCK_CTRL_ADR, 8, 0, 0x0000 },
+ { CAT_RCK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cat_rck_data_fields[] = {
+ { CAT_RCK_DATA_CM0U, 1, 1, 0x0000 },
+ { CAT_RCK_DATA_CM1U, 1, 5, 0x0000 },
+ { CAT_RCK_DATA_CM2U, 1, 9, 0x0000 },
+ { CAT_RCK_DATA_CM3U, 1, 13, 0x0000 },
+ { CAT_RCK_DATA_CM4U, 1, 17, 0x0000 },
+ { CAT_RCK_DATA_CM5U, 1, 21, 0x0000 },
+ { CAT_RCK_DATA_CM6U, 1, 25, 0x0000 },
+ { CAT_RCK_DATA_CM7U, 1, 29, 0x0000 },
+ { CAT_RCK_DATA_CML0, 1, 0, 0x0000 },
+ { CAT_RCK_DATA_CML1, 1, 4, 0x0000 },
+ { CAT_RCK_DATA_CML2, 1, 8, 0x0000 },
+ { CAT_RCK_DATA_CML3, 1, 12, 0x0000 },
+ { CAT_RCK_DATA_CML4, 1, 16, 0x0000 },
+ { CAT_RCK_DATA_CML5, 1, 20, 0x0000 },
+ { CAT_RCK_DATA_CML6, 1, 24, 0x0000 },
+ { CAT_RCK_DATA_CML7, 1, 28, 0x0000 },
+ { CAT_RCK_DATA_SEL0, 1, 2, 0x0000 },
+ { CAT_RCK_DATA_SEL1, 1, 6, 0x0000 },
+ { CAT_RCK_DATA_SEL2, 1, 10, 0x0000 },
+ { CAT_RCK_DATA_SEL3, 1, 14, 0x0000 },
+ { CAT_RCK_DATA_SEL4, 1, 18, 0x0000 },
+ { CAT_RCK_DATA_SEL5, 1, 22, 0x0000 },
+ { CAT_RCK_DATA_SEL6, 1, 26, 0x0000 },
+ { CAT_RCK_DATA_SEL7, 1, 30, 0x0000 },
+ { CAT_RCK_DATA_SEU0, 1, 3, 0x0000 },
+ { CAT_RCK_DATA_SEU1, 1, 7, 0x0000 },
+ { CAT_RCK_DATA_SEU2, 1, 11, 0x0000 },
+ { CAT_RCK_DATA_SEU3, 1, 15, 0x0000 },
+ { CAT_RCK_DATA_SEU4, 1, 19, 0x0000 },
+ { CAT_RCK_DATA_SEU5, 1, 23, 0x0000 },
+ { CAT_RCK_DATA_SEU6, 1, 27, 0x0000 },
+ { CAT_RCK_DATA_SEU7, 1, 31, 0x0000 },
+};
+
+static nt_fpga_register_init_t cat_registers[] = {
+ { CAT_CCT_CTRL, 30, 32, REGISTER_TYPE_WO, 0, 2, cat_cct_ctrl_fields },
+ { CAT_CCT_DATA, 31, 36, REGISTER_TYPE_WO, 0, 2, cat_cct_data_fields },
+ { CAT_CFN_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, cat_cfn_ctrl_fields },
+ { CAT_CFN_DATA, 11, 179, REGISTER_TYPE_WO, 0, 44, cat_cfn_data_fields },
+ { CAT_COT_CTRL, 28, 32, REGISTER_TYPE_WO, 0, 2, cat_cot_ctrl_fields },
+ { CAT_COT_DATA, 29, 36, REGISTER_TYPE_WO, 0, 2, cat_cot_data_fields },
+ { CAT_CTE_CTRL, 24, 32, REGISTER_TYPE_WO, 0, 2, cat_cte_ctrl_fields },
+ { CAT_CTE_DATA, 25, 11, REGISTER_TYPE_WO, 0, 11, cat_cte_data_fields },
+ { CAT_CTS_CTRL, 26, 32, REGISTER_TYPE_WO, 0, 2, cat_cts_ctrl_fields },
+ { CAT_CTS_DATA, 27, 12, REGISTER_TYPE_WO, 0, 2, cat_cts_data_fields },
+ { CAT_DCT_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, cat_dct_ctrl_fields },
+ { CAT_DCT_DATA, 7, 16, REGISTER_TYPE_WO, 0, 1, cat_dct_data_fields },
+ { CAT_DCT_SEL, 4, 2, REGISTER_TYPE_WO, 0, 1, cat_dct_sel_fields },
+ { CAT_EXO_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, cat_exo_ctrl_fields },
+ { CAT_EXO_DATA, 1, 27, REGISTER_TYPE_WO, 0, 2, cat_exo_data_fields },
+ { CAT_FTE0_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2, cat_fte0_ctrl_fields },
+ { CAT_FTE0_DATA, 17, 8, REGISTER_TYPE_WO, 0, 1, cat_fte0_data_fields },
+ { CAT_FTE1_CTRL, 22, 32, REGISTER_TYPE_WO, 0, 2, cat_fte1_ctrl_fields },
+ { CAT_FTE1_DATA, 23, 8, REGISTER_TYPE_WO, 0, 1, cat_fte1_data_fields },
+ { CAT_JOIN, 5, 9, REGISTER_TYPE_WO, 0, 2, cat_join_fields },
+ { CAT_KCC_CTRL, 32, 32, REGISTER_TYPE_WO, 0, 2, cat_kcc_ctrl_fields },
+ { CAT_KCC_DATA, 33, 84, REGISTER_TYPE_WO, 0, 3, cat_kcc_data_fields },
+ { CAT_KCE0_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, cat_kce0_ctrl_fields },
+ { CAT_KCE0_DATA, 13, 8, REGISTER_TYPE_WO, 0, 1, cat_kce0_data_fields },
+ { CAT_KCE1_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2, cat_kce1_ctrl_fields },
+ { CAT_KCE1_DATA, 19, 8, REGISTER_TYPE_WO, 0, 1, cat_kce1_data_fields },
+ { CAT_KCS0_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2, cat_kcs0_ctrl_fields },
+ { CAT_KCS0_DATA, 15, 6, REGISTER_TYPE_WO, 0, 1, cat_kcs0_data_fields },
+ { CAT_KCS1_CTRL, 20, 32, REGISTER_TYPE_WO, 0, 2, cat_kcs1_ctrl_fields },
+ { CAT_KCS1_DATA, 21, 6, REGISTER_TYPE_WO, 0, 1, cat_kcs1_data_fields },
+ { CAT_LEN_CTRL, 8, 32, REGISTER_TYPE_WO, 0, 2, cat_len_ctrl_fields },
+ { CAT_LEN_DATA, 9, 39, REGISTER_TYPE_WO, 0, 5, cat_len_data_fields },
+ { CAT_RCK_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, cat_rck_ctrl_fields },
+ { CAT_RCK_DATA, 3, 32, REGISTER_TYPE_WO, 0, 32, cat_rck_data_fields },
+};
+
+static nt_fpga_field_init_t cpy_writer0_ctrl_fields[] = {
+ { CPY_WRITER0_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer0_data_fields[] = {
+ { CPY_WRITER0_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER0_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER0_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER0_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER0_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer0_mask_ctrl_fields[] = {
+ { CPY_WRITER0_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER0_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer0_mask_data_fields[] = {
+ { CPY_WRITER0_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_ctrl_fields[] = {
+ { CPY_WRITER1_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_data_fields[] = {
+ { CPY_WRITER1_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER1_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER1_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER1_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER1_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_mask_ctrl_fields[] = {
+ { CPY_WRITER1_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER1_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer1_mask_data_fields[] = {
+ { CPY_WRITER1_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_ctrl_fields[] = {
+ { CPY_WRITER2_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER2_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_data_fields[] = {
+ { CPY_WRITER2_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER2_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER2_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER2_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER2_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_mask_ctrl_fields[] = {
+ { CPY_WRITER2_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER2_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer2_mask_data_fields[] = {
+ { CPY_WRITER2_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_ctrl_fields[] = {
+ { CPY_WRITER3_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER3_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_data_fields[] = {
+ { CPY_WRITER3_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER3_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER3_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER3_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER3_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_mask_ctrl_fields[] = {
+ { CPY_WRITER3_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER3_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer3_mask_data_fields[] = {
+ { CPY_WRITER3_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_ctrl_fields[] = {
+ { CPY_WRITER4_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER4_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_data_fields[] = {
+ { CPY_WRITER4_DATA_DYN, 5, 17, 0x0000 },
+ { CPY_WRITER4_DATA_LEN, 4, 22, 0x0000 },
+ { CPY_WRITER4_DATA_MASK_POINTER, 4, 26, 0x0000 },
+ { CPY_WRITER4_DATA_OFS, 14, 3, 0x0000 },
+ { CPY_WRITER4_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_mask_ctrl_fields[] = {
+ { CPY_WRITER4_MASK_CTRL_ADR, 4, 0, 0x0000 },
+ { CPY_WRITER4_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t cpy_writer4_mask_data_fields[] = {
+ { CPY_WRITER4_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t cpy_registers[] = {
+ { CPY_WRITER0_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer0_ctrl_fields
+ },
+ { CPY_WRITER0_DATA, 1, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer0_data_fields
+ },
+ { CPY_WRITER0_MASK_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer0_mask_ctrl_fields
+ },
+ { CPY_WRITER0_MASK_DATA, 3, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer0_mask_data_fields
+ },
+ { CPY_WRITER1_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer1_ctrl_fields
+ },
+ { CPY_WRITER1_DATA, 5, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer1_data_fields
+ },
+ { CPY_WRITER1_MASK_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer1_mask_ctrl_fields
+ },
+ { CPY_WRITER1_MASK_DATA, 7, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer1_mask_data_fields
+ },
+ { CPY_WRITER2_CTRL, 8, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer2_ctrl_fields
+ },
+ { CPY_WRITER2_DATA, 9, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer2_data_fields
+ },
+ { CPY_WRITER2_MASK_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer2_mask_ctrl_fields
+ },
+ { CPY_WRITER2_MASK_DATA, 11, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer2_mask_data_fields
+ },
+ { CPY_WRITER3_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer3_ctrl_fields
+ },
+ { CPY_WRITER3_DATA, 13, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer3_data_fields
+ },
+ { CPY_WRITER3_MASK_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer3_mask_ctrl_fields
+ },
+ { CPY_WRITER3_MASK_DATA, 15, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer3_mask_data_fields
+ },
+ { CPY_WRITER4_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer4_ctrl_fields
+ },
+ { CPY_WRITER4_DATA, 17, 30, REGISTER_TYPE_WO, 0, 5,
+ cpy_writer4_data_fields
+ },
+ { CPY_WRITER4_MASK_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2,
+ cpy_writer4_mask_ctrl_fields
+ },
+ { CPY_WRITER4_MASK_DATA, 19, 16, REGISTER_TYPE_WO, 0, 1,
+ cpy_writer4_mask_data_fields
+ },
+};
+
+static nt_fpga_field_init_t csu_rcp_ctrl_fields[] = {
+ { CSU_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { CSU_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t csu_rcp_data_fields[] = {
+ { CSU_RCP_DATA_IL3_CMD, 2, 5, 0x0000 },
+ { CSU_RCP_DATA_IL4_CMD, 3, 7, 0x0000 },
+ { CSU_RCP_DATA_OL3_CMD, 2, 0, 0x0000 },
+ { CSU_RCP_DATA_OL4_CMD, 3, 2, 0x0000 },
+};
+
+static nt_fpga_register_init_t csu_registers[] = {
+ { CSU_RCP_CTRL, 1, 32, REGISTER_TYPE_WO, 0, 2, csu_rcp_ctrl_fields },
+ { CSU_RCP_DATA, 2, 10, REGISTER_TYPE_WO, 0, 4, csu_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t dbs_rx_am_ctrl_fields[] = {
+ { DBS_RX_AM_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_RX_AM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_am_data_fields[] = {
+ { DBS_RX_AM_DATA_ENABLE, 1, 72, 0x0000 },
+ { DBS_RX_AM_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_RX_AM_DATA_HID, 8, 64, 0x0000 },
+ { DBS_RX_AM_DATA_INT, 1, 74, 0x0000 },
+ { DBS_RX_AM_DATA_PCKED, 1, 73, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_control_fields[] = {
+ { DBS_RX_CONTROL_AME, 1, 7, 0 }, { DBS_RX_CONTROL_AMS, 4, 8, 8 },
+ { DBS_RX_CONTROL_LQ, 7, 0, 0 }, { DBS_RX_CONTROL_QE, 1, 17, 0 },
+ { DBS_RX_CONTROL_UWE, 1, 12, 0 }, { DBS_RX_CONTROL_UWS, 4, 13, 5 },
+};
+
+static nt_fpga_field_init_t dbs_rx_dr_ctrl_fields[] = {
+ { DBS_RX_DR_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_RX_DR_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_dr_data_fields[] = {
+ { DBS_RX_DR_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_RX_DR_DATA_HDR, 1, 88, 0x0000 },
+ { DBS_RX_DR_DATA_HID, 8, 64, 0x0000 },
+ { DBS_RX_DR_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_RX_DR_DATA_QS, 15, 72, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_idle_fields[] = {
+ { DBS_RX_IDLE_BUSY, 1, 8, 0 },
+ { DBS_RX_IDLE_IDLE, 1, 0, 0x0000 },
+ { DBS_RX_IDLE_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_init_fields[] = {
+ { DBS_RX_INIT_BUSY, 1, 8, 0 },
+ { DBS_RX_INIT_INIT, 1, 0, 0x0000 },
+ { DBS_RX_INIT_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_init_val_fields[] = {
+ { DBS_RX_INIT_VAL_IDX, 16, 0, 0x0000 },
+ { DBS_RX_INIT_VAL_PTR, 15, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_ptr_fields[] = {
+ { DBS_RX_PTR_PTR, 16, 0, 0x0000 },
+ { DBS_RX_PTR_QUEUE, 7, 16, 0x0000 },
+ { DBS_RX_PTR_VALID, 1, 23, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_uw_ctrl_fields[] = {
+ { DBS_RX_UW_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_RX_UW_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_rx_uw_data_fields[] = {
+ { DBS_RX_UW_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_RX_UW_DATA_HID, 8, 64, 0x0000 },
+ { DBS_RX_UW_DATA_INT, 1, 88, 0x0000 },
+ { DBS_RX_UW_DATA_ISTK, 1, 92, 0x0000 },
+ { DBS_RX_UW_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_RX_UW_DATA_QS, 15, 72, 0x0000 },
+ { DBS_RX_UW_DATA_VEC, 3, 89, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_am_ctrl_fields[] = {
+ { DBS_TX_AM_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_AM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_am_data_fields[] = {
+ { DBS_TX_AM_DATA_ENABLE, 1, 72, 0x0000 },
+ { DBS_TX_AM_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_TX_AM_DATA_HID, 8, 64, 0x0000 },
+ { DBS_TX_AM_DATA_INT, 1, 74, 0x0000 },
+ { DBS_TX_AM_DATA_PCKED, 1, 73, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_control_fields[] = {
+ { DBS_TX_CONTROL_AME, 1, 7, 0 }, { DBS_TX_CONTROL_AMS, 4, 8, 5 },
+ { DBS_TX_CONTROL_LQ, 7, 0, 0 }, { DBS_TX_CONTROL_QE, 1, 17, 0 },
+ { DBS_TX_CONTROL_UWE, 1, 12, 0 }, { DBS_TX_CONTROL_UWS, 4, 13, 8 },
+};
+
+static nt_fpga_field_init_t dbs_tx_dr_ctrl_fields[] = {
+ { DBS_TX_DR_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_DR_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_dr_data_fields[] = {
+ { DBS_TX_DR_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_TX_DR_DATA_HDR, 1, 88, 0x0000 },
+ { DBS_TX_DR_DATA_HID, 8, 64, 0x0000 },
+ { DBS_TX_DR_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_TX_DR_DATA_PORT, 1, 89, 0x0000 },
+ { DBS_TX_DR_DATA_QS, 15, 72, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_idle_fields[] = {
+ { DBS_TX_IDLE_BUSY, 1, 8, 0 },
+ { DBS_TX_IDLE_IDLE, 1, 0, 0x0000 },
+ { DBS_TX_IDLE_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_init_fields[] = {
+ { DBS_TX_INIT_BUSY, 1, 8, 0 },
+ { DBS_TX_INIT_INIT, 1, 0, 0x0000 },
+ { DBS_TX_INIT_QUEUE, 7, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_init_val_fields[] = {
+ { DBS_TX_INIT_VAL_IDX, 16, 0, 0x0000 },
+ { DBS_TX_INIT_VAL_PTR, 15, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_ptr_fields[] = {
+ { DBS_TX_PTR_PTR, 16, 0, 0x0000 },
+ { DBS_TX_PTR_QUEUE, 7, 16, 0x0000 },
+ { DBS_TX_PTR_VALID, 1, 23, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qos_ctrl_fields[] = {
+ { DBS_TX_QOS_CTRL_ADR, 1, 0, 0x0000 },
+ { DBS_TX_QOS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qos_data_fields[] = {
+ { DBS_TX_QOS_DATA_BS, 27, 17, 0x0000 },
+ { DBS_TX_QOS_DATA_EN, 1, 0, 0x0000 },
+ { DBS_TX_QOS_DATA_IR, 16, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qos_rate_fields[] = {
+ { DBS_TX_QOS_RATE_DIV, 19, 16, 2 },
+ { DBS_TX_QOS_RATE_MUL, 16, 0, 1 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qp_ctrl_fields[] = {
+ { DBS_TX_QP_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_QP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_qp_data_fields[] = {
+ { DBS_TX_QP_DATA_VPORT, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_uw_ctrl_fields[] = {
+ { DBS_TX_UW_CTRL_ADR, 7, 0, 0x0000 },
+ { DBS_TX_UW_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t dbs_tx_uw_data_fields[] = {
+ { DBS_TX_UW_DATA_GPA, 64, 0, 0x0000 },
+ { DBS_TX_UW_DATA_HID, 8, 64, 0x0000 },
+ { DBS_TX_UW_DATA_INO, 1, 93, 0x0000 },
+ { DBS_TX_UW_DATA_INT, 1, 88, 0x0000 },
+ { DBS_TX_UW_DATA_ISTK, 1, 92, 0x0000 },
+ { DBS_TX_UW_DATA_PCKED, 1, 87, 0x0000 },
+ { DBS_TX_UW_DATA_QS, 15, 72, 0x0000 },
+ { DBS_TX_UW_DATA_VEC, 3, 89, 0x0000 },
+};
+
+static nt_fpga_register_init_t dbs_registers[] = {
+ { DBS_RX_AM_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_am_ctrl_fields
+ },
+ { DBS_RX_AM_DATA, 11, 75, REGISTER_TYPE_WO, 0, 5,
+ dbs_rx_am_data_fields
+ },
+ { DBS_RX_CONTROL, 0, 18, REGISTER_TYPE_RW, 43008, 6,
+ dbs_rx_control_fields
+ },
+ { DBS_RX_DR_CTRL, 18, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_dr_ctrl_fields
+ },
+ { DBS_RX_DR_DATA, 19, 89, REGISTER_TYPE_WO, 0, 5,
+ dbs_rx_dr_data_fields
+ },
+ { DBS_RX_IDLE, 8, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_idle_fields },
+ { DBS_RX_INIT, 2, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_init_fields },
+ { DBS_RX_INIT_VAL, 3, 31, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_init_val_fields
+ },
+ { DBS_RX_PTR, 4, 24, REGISTER_TYPE_MIXED, 0, 3, dbs_rx_ptr_fields },
+ { DBS_RX_UW_CTRL, 14, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_rx_uw_ctrl_fields
+ },
+ { DBS_RX_UW_DATA, 15, 93, REGISTER_TYPE_WO, 0, 7,
+ dbs_rx_uw_data_fields
+ },
+ { DBS_TX_AM_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_am_ctrl_fields
+ },
+ { DBS_TX_AM_DATA, 13, 75, REGISTER_TYPE_WO, 0, 5,
+ dbs_tx_am_data_fields
+ },
+ { DBS_TX_CONTROL, 1, 18, REGISTER_TYPE_RW, 66816, 6,
+ dbs_tx_control_fields
+ },
+ { DBS_TX_DR_CTRL, 20, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_dr_ctrl_fields
+ },
+ { DBS_TX_DR_DATA, 21, 90, REGISTER_TYPE_WO, 0, 6,
+ dbs_tx_dr_data_fields
+ },
+ { DBS_TX_IDLE, 9, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_idle_fields },
+ { DBS_TX_INIT, 5, 9, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_init_fields },
+ { DBS_TX_INIT_VAL, 6, 31, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_init_val_fields
+ },
+ { DBS_TX_PTR, 7, 24, REGISTER_TYPE_MIXED, 0, 3, dbs_tx_ptr_fields },
+ { DBS_TX_QOS_CTRL, 24, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_qos_ctrl_fields
+ },
+ { DBS_TX_QOS_DATA, 25, 44, REGISTER_TYPE_WO, 0, 3,
+ dbs_tx_qos_data_fields
+ },
+ { DBS_TX_QOS_RATE, 26, 35, REGISTER_TYPE_RW, 131073, 2,
+ dbs_tx_qos_rate_fields
+ },
+ { DBS_TX_QP_CTRL, 22, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_qp_ctrl_fields
+ },
+ { DBS_TX_QP_DATA, 23, 1, REGISTER_TYPE_WO, 0, 1,
+ dbs_tx_qp_data_fields
+ },
+ { DBS_TX_UW_CTRL, 16, 32, REGISTER_TYPE_WO, 0, 2,
+ dbs_tx_uw_ctrl_fields
+ },
+ { DBS_TX_UW_DATA, 17, 94, REGISTER_TYPE_WO, 0, 8,
+ dbs_tx_uw_data_fields
+ },
+};
+
+static nt_fpga_field_init_t flm_buf_ctrl_fields[] = {
+ { FLM_BUF_CTRL_INF_AVAIL, 16, 16, 0x0000 },
+ { FLM_BUF_CTRL_LRN_FREE, 16, 0, 0x0000 },
+ { FLM_BUF_CTRL_STA_AVAIL, 16, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_control_fields[] = {
+ { FLM_CONTROL_CRCRD, 1, 12, 0x0000 },
+ { FLM_CONTROL_CRCWR, 1, 11, 0x0000 },
+ { FLM_CONTROL_EAB, 5, 18, 0 },
+ { FLM_CONTROL_ENABLE, 1, 0, 0 },
+ { FLM_CONTROL_INIT, 1, 1, 0x0000 },
+ { FLM_CONTROL_LDS, 1, 2, 0x0000 },
+ { FLM_CONTROL_LFS, 1, 3, 0x0000 },
+ { FLM_CONTROL_LIS, 1, 4, 0x0000 },
+ { FLM_CONTROL_PDS, 1, 9, 0x0000 },
+ { FLM_CONTROL_PIS, 1, 10, 0x0000 },
+ { FLM_CONTROL_RBL, 4, 13, 0 },
+ { FLM_CONTROL_RDS, 1, 7, 0x0000 },
+ { FLM_CONTROL_RIS, 1, 8, 0x0000 },
+ { FLM_CONTROL_SPLIT_SDRAM_USAGE, 5, 23, 16 },
+ { FLM_CONTROL_UDS, 1, 5, 0x0000 },
+ { FLM_CONTROL_UIS, 1, 6, 0x0000 },
+ { FLM_CONTROL_WPD, 1, 17, 0 },
+};
+
+static nt_fpga_field_init_t flm_inf_data_fields[] = {
+ { FLM_INF_DATA_BYTES, 64, 0, 0x0000 },
+ { FLM_INF_DATA_CAUSE, 3, 264, 0x0000 },
+ { FLM_INF_DATA_EOR, 1, 287, 0x0000 },
+ { FLM_INF_DATA_ID, 72, 192, 0x0000 },
+ { FLM_INF_DATA_PACKETS, 64, 64, 0x0000 },
+ { FLM_INF_DATA_TS, 64, 128, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_load_aps_fields[] = {
+ { FLM_LOAD_APS_APS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_load_bin_fields[] = {
+ { FLM_LOAD_BIN_BIN, 30, 0, 8388607 },
+};
+
+static nt_fpga_field_init_t flm_load_lps_fields[] = {
+ { FLM_LOAD_LPS_LPS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_load_pps_fields[] = {
+ { FLM_LOAD_PPS_PPS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_lrn_data_fields[] = {
+ { FLM_LRN_DATA_ADJ, 32, 480, 0x0000 },
+ { FLM_LRN_DATA_COLOR, 32, 448, 0x0000 },
+ { FLM_LRN_DATA_DSCP, 6, 734, 0x0000 },
+ { FLM_LRN_DATA_ENT, 1, 729, 0x0000 },
+ { FLM_LRN_DATA_EOR, 1, 767, 0x0000 },
+ { FLM_LRN_DATA_FILL, 12, 584, 0x0000 },
+ { FLM_LRN_DATA_FT, 4, 596, 0x0000 },
+ { FLM_LRN_DATA_FT_MBR, 4, 600, 0x0000 },
+ { FLM_LRN_DATA_FT_MISS, 4, 604, 0x0000 },
+ { FLM_LRN_DATA_ID, 72, 512, 0x0000 },
+ { FLM_LRN_DATA_KID, 8, 328, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID1, 28, 608, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID2, 28, 636, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID3, 28, 664, 0x0000 },
+ { FLM_LRN_DATA_MBR_ID4, 28, 692, 0x0000 },
+ { FLM_LRN_DATA_NAT_EN, 1, 747, 0x0000 },
+ { FLM_LRN_DATA_NAT_IP, 32, 336, 0x0000 },
+ { FLM_LRN_DATA_NAT_PORT, 16, 400, 0x0000 },
+ { FLM_LRN_DATA_OP, 4, 730, 0x0000 },
+ { FLM_LRN_DATA_PRIO, 2, 727, 0x0000 },
+ { FLM_LRN_DATA_PROT, 8, 320, 0x0000 },
+ { FLM_LRN_DATA_QFI, 6, 740, 0x0000 },
+ { FLM_LRN_DATA_QW0, 128, 192, 0x0000 },
+ { FLM_LRN_DATA_QW4, 128, 64, 0x0000 },
+ { FLM_LRN_DATA_RATE, 16, 416, 0x0000 },
+ { FLM_LRN_DATA_RQI, 1, 746, 0x0000 },
+ { FLM_LRN_DATA_SIZE, 16, 432, 0x0000 },
+ { FLM_LRN_DATA_STAT_PROF, 4, 723, 0x0000 },
+ { FLM_LRN_DATA_SW8, 32, 32, 0x0000 },
+ { FLM_LRN_DATA_SW9, 32, 0, 0x0000 },
+ { FLM_LRN_DATA_TEID, 32, 368, 0x0000 },
+ { FLM_LRN_DATA_VOL_IDX, 3, 720, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_prio_fields[] = {
+ { FLM_PRIO_FT0, 4, 4, 1 }, { FLM_PRIO_FT1, 4, 12, 1 },
+ { FLM_PRIO_FT2, 4, 20, 1 }, { FLM_PRIO_FT3, 4, 28, 1 },
+ { FLM_PRIO_LIMIT0, 4, 0, 0 }, { FLM_PRIO_LIMIT1, 4, 8, 0 },
+ { FLM_PRIO_LIMIT2, 4, 16, 0 }, { FLM_PRIO_LIMIT3, 4, 24, 0 },
+};
+
+static nt_fpga_field_init_t flm_pst_ctrl_fields[] = {
+ { FLM_PST_CTRL_ADR, 4, 0, 0x0000 },
+ { FLM_PST_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_pst_data_fields[] = {
+ { FLM_PST_DATA_BP, 5, 0, 0x0000 },
+ { FLM_PST_DATA_PP, 5, 5, 0x0000 },
+ { FLM_PST_DATA_TP, 5, 10, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_rcp_ctrl_fields[] = {
+ { FLM_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { FLM_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_rcp_data_fields[] = {
+ { FLM_RCP_DATA_AUTO_IPV4_MASK, 1, 402, 0x0000 },
+ { FLM_RCP_DATA_BYT_DYN, 5, 387, 0x0000 },
+ { FLM_RCP_DATA_BYT_OFS, 8, 392, 0x0000 },
+ { FLM_RCP_DATA_IPN, 1, 386, 0x0000 },
+ { FLM_RCP_DATA_KID, 8, 377, 0x0000 },
+ { FLM_RCP_DATA_LOOKUP, 1, 0, 0x0000 },
+ { FLM_RCP_DATA_MASK, 320, 57, 0x0000 },
+ { FLM_RCP_DATA_OPN, 1, 385, 0x0000 },
+ { FLM_RCP_DATA_QW0_DYN, 5, 1, 0x0000 },
+ { FLM_RCP_DATA_QW0_OFS, 8, 6, 0x0000 },
+ { FLM_RCP_DATA_QW0_SEL, 2, 14, 0x0000 },
+ { FLM_RCP_DATA_QW4_DYN, 5, 16, 0x0000 },
+ { FLM_RCP_DATA_QW4_OFS, 8, 21, 0x0000 },
+ { FLM_RCP_DATA_SW8_DYN, 5, 29, 0x0000 },
+ { FLM_RCP_DATA_SW8_OFS, 8, 34, 0x0000 },
+ { FLM_RCP_DATA_SW8_SEL, 2, 42, 0x0000 },
+ { FLM_RCP_DATA_SW9_DYN, 5, 44, 0x0000 },
+ { FLM_RCP_DATA_SW9_OFS, 8, 49, 0x0000 },
+ { FLM_RCP_DATA_TXPLM, 2, 400, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_scrub_fields[] = {
+ { FLM_SCRUB_I, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t flm_status_fields[] = {
+ { FLM_STATUS_CALIBDONE, 1, 0, 0x0000 },
+ { FLM_STATUS_CRCERR, 1, 5, 0x0000 },
+ { FLM_STATUS_CRITICAL, 1, 3, 0x0000 },
+ { FLM_STATUS_EFT_BP, 1, 6, 0x0000 },
+ { FLM_STATUS_IDLE, 1, 2, 0x0000 },
+ { FLM_STATUS_INITDONE, 1, 1, 0x0000 },
+ { FLM_STATUS_PANIC, 1, 4, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_aul_done_fields[] = {
+ { FLM_STAT_AUL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_aul_fail_fields[] = {
+ { FLM_STAT_AUL_FAIL_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_aul_ignore_fields[] = {
+ { FLM_STAT_AUL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_csh_hit_fields[] = {
+ { FLM_STAT_CSH_HIT_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_csh_miss_fields[] = {
+ { FLM_STAT_CSH_MISS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_csh_unh_fields[] = {
+ { FLM_STAT_CSH_UNH_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_cuc_move_fields[] = {
+ { FLM_STAT_CUC_MOVE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_cuc_start_fields[] = {
+ { FLM_STAT_CUC_START_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_flows_fields[] = {
+ { FLM_STAT_FLOWS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_inf_done_fields[] = {
+ { FLM_STAT_INF_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_inf_skip_fields[] = {
+ { FLM_STAT_INF_SKIP_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_lrn_done_fields[] = {
+ { FLM_STAT_LRN_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_lrn_fail_fields[] = {
+ { FLM_STAT_LRN_FAIL_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_lrn_ignore_fields[] = {
+ { FLM_STAT_LRN_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_dis_fields[] = {
+ { FLM_STAT_PCK_DIS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_hit_fields[] = {
+ { FLM_STAT_PCK_HIT_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_miss_fields[] = {
+ { FLM_STAT_PCK_MISS_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_pck_unh_fields[] = {
+ { FLM_STAT_PCK_UNH_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_prb_done_fields[] = {
+ { FLM_STAT_PRB_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_prb_ignore_fields[] = {
+ { FLM_STAT_PRB_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_rel_done_fields[] = {
+ { FLM_STAT_REL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_rel_ignore_fields[] = {
+ { FLM_STAT_REL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_sta_done_fields[] = {
+ { FLM_STAT_STA_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_tul_done_fields[] = {
+ { FLM_STAT_TUL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_unl_done_fields[] = {
+ { FLM_STAT_UNL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_stat_unl_ignore_fields[] = {
+ { FLM_STAT_UNL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_sta_data_fields[] = {
+ { FLM_STA_DATA_EOR, 1, 95, 0x0000 },
+ { FLM_STA_DATA_ID, 72, 0, 0x0000 },
+ { FLM_STA_DATA_LDS, 1, 72, 0x0000 },
+ { FLM_STA_DATA_LFS, 1, 73, 0x0000 },
+ { FLM_STA_DATA_LIS, 1, 74, 0x0000 },
+ { FLM_STA_DATA_PDS, 1, 79, 0x0000 },
+ { FLM_STA_DATA_PIS, 1, 80, 0x0000 },
+ { FLM_STA_DATA_RDS, 1, 77, 0x0000 },
+ { FLM_STA_DATA_RIS, 1, 78, 0x0000 },
+ { FLM_STA_DATA_UDS, 1, 75, 0x0000 },
+ { FLM_STA_DATA_UIS, 1, 76, 0x0000 },
+};
+
+static nt_fpga_field_init_t flm_timeout_fields[] = {
+ { FLM_TIMEOUT_T, 32, 0, 0 },
+};
+
+static nt_fpga_register_init_t flm_registers[] = {
+ { FLM_BUF_CTRL, 14, 48, REGISTER_TYPE_RW, 0, 3, flm_buf_ctrl_fields },
+ { FLM_CONTROL, 0, 28, REGISTER_TYPE_MIXED, 134217728, 17,
+ flm_control_fields
+ },
+ { FLM_INF_DATA, 16, 288, REGISTER_TYPE_RO, 0, 6, flm_inf_data_fields },
+ { FLM_LOAD_APS, 7, 32, REGISTER_TYPE_RO, 0, 1, flm_load_aps_fields },
+ { FLM_LOAD_BIN, 4, 30, REGISTER_TYPE_WO, 8388607, 1,
+ flm_load_bin_fields
+ },
+ { FLM_LOAD_LPS, 6, 32, REGISTER_TYPE_RO, 0, 1, flm_load_lps_fields },
+ { FLM_LOAD_PPS, 5, 32, REGISTER_TYPE_RO, 0, 1, flm_load_pps_fields },
+ { FLM_LRN_DATA, 15, 768, REGISTER_TYPE_WO, 0, 32, flm_lrn_data_fields },
+ { FLM_PRIO, 8, 32, REGISTER_TYPE_WO, 269488144, 8, flm_prio_fields },
+ { FLM_PST_CTRL, 10, 32, REGISTER_TYPE_WO, 0, 2, flm_pst_ctrl_fields },
+ { FLM_PST_DATA, 11, 15, REGISTER_TYPE_WO, 0, 3, flm_pst_data_fields },
+ { FLM_RCP_CTRL, 12, 32, REGISTER_TYPE_WO, 0, 2, flm_rcp_ctrl_fields },
+ { FLM_RCP_DATA, 13, 403, REGISTER_TYPE_WO, 0, 19, flm_rcp_data_fields },
+ { FLM_SCRUB, 3, 16, REGISTER_TYPE_WO, 0, 1, flm_scrub_fields },
+ { FLM_STATUS, 1, 12, REGISTER_TYPE_MIXED, 0, 7, flm_status_fields },
+ { FLM_STAT_AUL_DONE, 41, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_aul_done_fields
+ },
+ { FLM_STAT_AUL_FAIL, 43, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_aul_fail_fields
+ },
+ { FLM_STAT_AUL_IGNORE, 42, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_aul_ignore_fields
+ },
+ { FLM_STAT_CSH_HIT, 52, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_csh_hit_fields
+ },
+ { FLM_STAT_CSH_MISS, 53, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_csh_miss_fields
+ },
+ { FLM_STAT_CSH_UNH, 54, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_csh_unh_fields
+ },
+ { FLM_STAT_CUC_MOVE, 57, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_cuc_move_fields
+ },
+ { FLM_STAT_CUC_START, 56, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_cuc_start_fields
+ },
+ { FLM_STAT_FLOWS, 18, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_flows_fields
+ },
+ { FLM_STAT_INF_DONE, 46, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_inf_done_fields
+ },
+ { FLM_STAT_INF_SKIP, 47, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_inf_skip_fields
+ },
+ { FLM_STAT_LRN_DONE, 32, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_lrn_done_fields
+ },
+ { FLM_STAT_LRN_FAIL, 34, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_lrn_fail_fields
+ },
+ { FLM_STAT_LRN_IGNORE, 33, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_lrn_ignore_fields
+ },
+ { FLM_STAT_PCK_DIS, 51, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_dis_fields
+ },
+ { FLM_STAT_PCK_HIT, 48, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_hit_fields
+ },
+ { FLM_STAT_PCK_MISS, 49, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_miss_fields
+ },
+ { FLM_STAT_PCK_UNH, 50, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_pck_unh_fields
+ },
+ { FLM_STAT_PRB_DONE, 39, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_prb_done_fields
+ },
+ { FLM_STAT_PRB_IGNORE, 40, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_prb_ignore_fields
+ },
+ { FLM_STAT_REL_DONE, 37, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_rel_done_fields
+ },
+ { FLM_STAT_REL_IGNORE, 38, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_rel_ignore_fields
+ },
+ { FLM_STAT_STA_DONE, 45, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_sta_done_fields
+ },
+ { FLM_STAT_TUL_DONE, 44, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_tul_done_fields
+ },
+ { FLM_STAT_UNL_DONE, 35, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_unl_done_fields
+ },
+ { FLM_STAT_UNL_IGNORE, 36, 32, REGISTER_TYPE_RO, 0, 1,
+ flm_stat_unl_ignore_fields
+ },
+ { FLM_STA_DATA, 17, 96, REGISTER_TYPE_RO, 0, 11, flm_sta_data_fields },
+ { FLM_TIMEOUT, 2, 32, REGISTER_TYPE_WO, 0, 1, flm_timeout_fields },
+};
+
+static nt_fpga_field_init_t gfg_burstsize0_fields[] = {
+ { GFG_BURSTSIZE0_VAL, 24, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_burstsize1_fields[] = {
+ { GFG_BURSTSIZE1_VAL, 24, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_ctrl0_fields[] = {
+ { GFG_CTRL0_ENABLE, 1, 0, 0 },
+ { GFG_CTRL0_MODE, 3, 1, 0 },
+ { GFG_CTRL0_PRBS_EN, 1, 4, 0 },
+ { GFG_CTRL0_SIZE, 14, 16, 64 },
+};
+
+static nt_fpga_field_init_t gfg_ctrl1_fields[] = {
+ { GFG_CTRL1_ENABLE, 1, 0, 0 },
+ { GFG_CTRL1_MODE, 3, 1, 0 },
+ { GFG_CTRL1_PRBS_EN, 1, 4, 0 },
+ { GFG_CTRL1_SIZE, 14, 16, 64 },
+};
+
+static nt_fpga_field_init_t gfg_run0_fields[] = {
+ { GFG_RUN0_RUN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_run1_fields[] = {
+ { GFG_RUN1_RUN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_sizemask0_fields[] = {
+ { GFG_SIZEMASK0_VAL, 14, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_sizemask1_fields[] = {
+ { GFG_SIZEMASK1_VAL, 14, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_streamid0_fields[] = {
+ { GFG_STREAMID0_VAL, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t gfg_streamid1_fields[] = {
+ { GFG_STREAMID1_VAL, 8, 0, 1 },
+};
+
+static nt_fpga_register_init_t gfg_registers[] = {
+ { GFG_BURSTSIZE0, 3, 24, REGISTER_TYPE_WO, 0, 1,
+ gfg_burstsize0_fields
+ },
+ { GFG_BURSTSIZE1, 8, 24, REGISTER_TYPE_WO, 0, 1,
+ gfg_burstsize1_fields
+ },
+ { GFG_CTRL0, 0, 30, REGISTER_TYPE_WO, 4194304, 4, gfg_ctrl0_fields },
+ { GFG_CTRL1, 5, 30, REGISTER_TYPE_WO, 4194304, 4, gfg_ctrl1_fields },
+ { GFG_RUN0, 1, 1, REGISTER_TYPE_WO, 0, 1, gfg_run0_fields },
+ { GFG_RUN1, 6, 1, REGISTER_TYPE_WO, 0, 1, gfg_run1_fields },
+ { GFG_SIZEMASK0, 4, 14, REGISTER_TYPE_WO, 0, 1, gfg_sizemask0_fields },
+ { GFG_SIZEMASK1, 9, 14, REGISTER_TYPE_WO, 0, 1, gfg_sizemask1_fields },
+ { GFG_STREAMID0, 2, 8, REGISTER_TYPE_WO, 0, 1, gfg_streamid0_fields },
+ { GFG_STREAMID1, 7, 8, REGISTER_TYPE_WO, 1, 1, gfg_streamid1_fields },
+};
+
+static nt_fpga_field_init_t gmf_ctrl_fields[] = {
+ { GMF_CTRL_ENABLE, 1, 0, 0 },
+ { GMF_CTRL_FCS_ALWAYS, 1, 1, 0 },
+ { GMF_CTRL_IFG_AUTO_ADJUST_ENABLE, 1, 7, 0 },
+ { GMF_CTRL_IFG_ENABLE, 1, 2, 0 },
+ { GMF_CTRL_IFG_TX_NOW_ALWAYS, 1, 3, 0 },
+ { GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE, 1, 5, 0 },
+ { GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK, 1, 6, 0 },
+ { GMF_CTRL_IFG_TX_ON_TS_ALWAYS, 1, 4, 0 },
+ { GMF_CTRL_TS_INJECT_ALWAYS, 1, 8, 0 },
+ { GMF_CTRL_TS_INJECT_DUAL_STEP, 1, 9, 0 },
+};
+
+static nt_fpga_field_init_t gmf_debug_lane_marker_fields[] = {
+ { GMF_DEBUG_LANE_MARKER_COMPENSATION, 16, 0, 16384 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_max_adjust_slack_fields[] = {
+ { GMF_IFG_MAX_ADJUST_SLACK_SLACK, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_set_clock_delta_fields[] = {
+ { GMF_IFG_SET_CLOCK_DELTA_DELTA, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_set_clock_delta_adjust_fields[] = {
+ { GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ifg_tx_now_on_ts_fields[] = {
+ { GMF_IFG_TX_NOW_ON_TS_TS, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_speed_fields[] = {
+ { GMF_SPEED_IFG_SPEED, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_stat_data_buffer_fields[] = {
+ { GMF_STAT_DATA_BUFFER_USED, 15, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t gmf_stat_max_delayed_pkt_fields[] = {
+ { GMF_STAT_MAX_DELAYED_PKT_NS, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_stat_next_pkt_fields[] = {
+ { GMF_STAT_NEXT_PKT_NS, 64, 0, 0 },
+};
+
+static nt_fpga_field_init_t gmf_stat_sticky_fields[] = {
+ { GMF_STAT_STICKY_DATA_UNDERFLOWED, 1, 0, 0 },
+ { GMF_STAT_STICKY_IFG_ADJUSTED, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t gmf_ts_inject_fields[] = {
+ { GMF_TS_INJECT_OFFSET, 14, 0, 0 },
+ { GMF_TS_INJECT_POS, 2, 14, 0 },
+};
+
+static nt_fpga_register_init_t gmf_registers[] = {
+ { GMF_CTRL, 0, 10, REGISTER_TYPE_WO, 0, 10, gmf_ctrl_fields },
+ { GMF_DEBUG_LANE_MARKER, 7, 16, REGISTER_TYPE_WO, 16384, 1,
+ gmf_debug_lane_marker_fields
+ },
+ { GMF_IFG_MAX_ADJUST_SLACK, 4, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_max_adjust_slack_fields
+ },
+ { GMF_IFG_SET_CLOCK_DELTA, 2, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_set_clock_delta_fields
+ },
+ { GMF_IFG_SET_CLOCK_DELTA_ADJUST, 3, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_set_clock_delta_adjust_fields
+ },
+ { GMF_IFG_TX_NOW_ON_TS, 5, 64, REGISTER_TYPE_WO, 0, 1,
+ gmf_ifg_tx_now_on_ts_fields
+ },
+ { GMF_SPEED, 1, 64, REGISTER_TYPE_WO, 0, 1, gmf_speed_fields },
+ { GMF_STAT_DATA_BUFFER, 9, 15, REGISTER_TYPE_RO, 0, 1,
+ gmf_stat_data_buffer_fields
+ },
+ { GMF_STAT_MAX_DELAYED_PKT, 11, 64, REGISTER_TYPE_RC1, 0, 1,
+ gmf_stat_max_delayed_pkt_fields
+ },
+ { GMF_STAT_NEXT_PKT, 10, 64, REGISTER_TYPE_RO, 0, 1,
+ gmf_stat_next_pkt_fields
+ },
+ { GMF_STAT_STICKY, 8, 2, REGISTER_TYPE_RC1, 0, 2,
+ gmf_stat_sticky_fields
+ },
+ { GMF_TS_INJECT, 6, 16, REGISTER_TYPE_WO, 0, 2, gmf_ts_inject_fields },
+};
+
+static nt_fpga_field_init_t gpio_phy_cfg_fields[] = {
+ { GPIO_PHY_CFG_E_PORT0_RXLOS, 1, 8, 0 },
+ { GPIO_PHY_CFG_E_PORT1_RXLOS, 1, 9, 0 },
+ { GPIO_PHY_CFG_PORT0_INT_B, 1, 1, 1 },
+ { GPIO_PHY_CFG_PORT0_LPMODE, 1, 0, 0 },
+ { GPIO_PHY_CFG_PORT0_MODPRS_B, 1, 3, 1 },
+ { GPIO_PHY_CFG_PORT0_RESET_B, 1, 2, 0 },
+ { GPIO_PHY_CFG_PORT1_INT_B, 1, 5, 1 },
+ { GPIO_PHY_CFG_PORT1_LPMODE, 1, 4, 0 },
+ { GPIO_PHY_CFG_PORT1_MODPRS_B, 1, 7, 1 },
+ { GPIO_PHY_CFG_PORT1_RESET_B, 1, 6, 0 },
+};
+
+static nt_fpga_field_init_t gpio_phy_gpio_fields[] = {
+ { GPIO_PHY_GPIO_E_PORT0_RXLOS, 1, 8, 0 },
+ { GPIO_PHY_GPIO_E_PORT1_RXLOS, 1, 9, 0 },
+ { GPIO_PHY_GPIO_PORT0_INT_B, 1, 1, 0x0000 },
+ { GPIO_PHY_GPIO_PORT0_LPMODE, 1, 0, 1 },
+ { GPIO_PHY_GPIO_PORT0_MODPRS_B, 1, 3, 0x0000 },
+ { GPIO_PHY_GPIO_PORT0_RESET_B, 1, 2, 0 },
+ { GPIO_PHY_GPIO_PORT1_INT_B, 1, 5, 0x0000 },
+ { GPIO_PHY_GPIO_PORT1_LPMODE, 1, 4, 1 },
+ { GPIO_PHY_GPIO_PORT1_MODPRS_B, 1, 7, 0x0000 },
+ { GPIO_PHY_GPIO_PORT1_RESET_B, 1, 6, 0 },
+};
+
+static nt_fpga_register_init_t gpio_phy_registers[] = {
+ { GPIO_PHY_CFG, 0, 10, REGISTER_TYPE_RW, 170, 10, gpio_phy_cfg_fields },
+ { GPIO_PHY_GPIO, 1, 10, REGISTER_TYPE_RW, 17, 10,
+ gpio_phy_gpio_fields
+ },
+};
+
+static nt_fpga_field_init_t hfu_rcp_ctrl_fields[] = {
+ { HFU_RCP_CTRL_ADR, 6, 0, 0x0000 },
+ { HFU_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t hfu_rcp_data_fields[] = {
+ { HFU_RCP_DATA_CSINF, 1, 111, 0x0000 },
+ { HFU_RCP_DATA_IL3OFS, 8, 139, 0x0000 },
+ { HFU_RCP_DATA_IL4OFS, 8, 147, 0x0000 },
+ { HFU_RCP_DATA_L3FRAG, 2, 114, 0x0000 },
+ { HFU_RCP_DATA_L3PRT, 2, 112, 0x0000 },
+ { HFU_RCP_DATA_L4PRT, 3, 120, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_ADD_DYN, 5, 15, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_ADD_OFS, 8, 20, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_OL4LEN, 1, 1, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_POS_DYN, 5, 2, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_POS_OFS, 8, 7, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_SUB_DYN, 5, 28, 0x0000 },
+ { HFU_RCP_DATA_LEN_A_WR, 1, 0, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_ADD_DYN, 5, 47, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_ADD_OFS, 8, 52, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_POS_DYN, 5, 34, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_POS_OFS, 8, 39, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_SUB_DYN, 5, 60, 0x0000 },
+ { HFU_RCP_DATA_LEN_B_WR, 1, 33, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_ADD_DYN, 5, 79, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_ADD_OFS, 8, 84, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_POS_DYN, 5, 66, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_POS_OFS, 8, 71, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_SUB_DYN, 5, 92, 0x0000 },
+ { HFU_RCP_DATA_LEN_C_WR, 1, 65, 0x0000 },
+ { HFU_RCP_DATA_OL3OFS, 8, 123, 0x0000 },
+ { HFU_RCP_DATA_OL4OFS, 8, 131, 0x0000 },
+ { HFU_RCP_DATA_TTL_POS_DYN, 5, 98, 0x0000 },
+ { HFU_RCP_DATA_TTL_POS_OFS, 8, 103, 0x0000 },
+ { HFU_RCP_DATA_TTL_WR, 1, 97, 0x0000 },
+ { HFU_RCP_DATA_TUNNEL, 4, 116, 0x0000 },
+};
+
+static nt_fpga_register_init_t hfu_registers[] = {
+ { HFU_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hfu_rcp_ctrl_fields },
+ { HFU_RCP_DATA, 1, 155, REGISTER_TYPE_WO, 0, 31, hfu_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t hif_build_time_fields[] = {
+ { HIF_BUILD_TIME_TIME, 32, 0, 1689706895 },
+};
+
+static nt_fpga_field_init_t hif_config_fields[] = {
+ { HIF_CONFIG_EXT_TAG, 1, 6, 0x0000 },
+ { HIF_CONFIG_MAX_READ, 3, 3, 0x0000 },
+ { HIF_CONFIG_MAX_TLP, 3, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t hif_control_fields[] = {
+ { HIF_CONTROL_BLESSED, 8, 4, 0 },
+ { HIF_CONTROL_WRAW, 4, 0, 1 },
+};
+
+static nt_fpga_field_init_t hif_prod_id_ex_fields[] = {
+ { HIF_PROD_ID_EX_LAYOUT, 1, 31, 0 },
+ { HIF_PROD_ID_EX_LAYOUT_VERSION, 8, 0, 1 },
+ { HIF_PROD_ID_EX_RESERVED, 23, 8, 0 },
+};
+
+static nt_fpga_field_init_t hif_prod_id_lsb_fields[] = {
+ { HIF_PROD_ID_LSB_GROUP_ID, 16, 16, 9563 },
+ { HIF_PROD_ID_LSB_REV_ID, 8, 0, 24 },
+ { HIF_PROD_ID_LSB_VER_ID, 8, 8, 55 },
+};
+
+static nt_fpga_field_init_t hif_prod_id_msb_fields[] = {
+ { HIF_PROD_ID_MSB_BUILD_NO, 10, 12, 0 },
+ { HIF_PROD_ID_MSB_TYPE_ID, 12, 0, 200 },
+};
+
+static nt_fpga_field_init_t hif_sample_time_fields[] = {
+ { HIF_SAMPLE_TIME_SAMPLE_TIME, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t hif_status_fields[] = {
+ { HIF_STATUS_RD_ERR, 1, 9, 0 },
+ { HIF_STATUS_TAGS_IN_USE, 8, 0, 0 },
+ { HIF_STATUS_WR_ERR, 1, 8, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_ctrl_fields[] = {
+ { HIF_STAT_CTRL_STAT_ENA, 1, 1, 0 },
+ { HIF_STAT_CTRL_STAT_REQ, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_refclk_fields[] = {
+ { HIF_STAT_REFCLK_REFCLK250, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_rx_fields[] = {
+ { HIF_STAT_RX_COUNTER, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_stat_tx_fields[] = {
+ { HIF_STAT_TX_COUNTER, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t hif_test0_fields[] = {
+ { HIF_TEST0_DATA, 32, 0, 287454020 },
+};
+
+static nt_fpga_field_init_t hif_test1_fields[] = {
+ { HIF_TEST1_DATA, 32, 0, 2864434397 },
+};
+
+static nt_fpga_field_init_t hif_uuid0_fields[] = {
+ { HIF_UUID0_UUID0, 32, 0, 456073826 },
+};
+
+static nt_fpga_field_init_t hif_uuid1_fields[] = {
+ { HIF_UUID1_UUID1, 32, 0, 3051597623 },
+};
+
+static nt_fpga_field_init_t hif_uuid2_fields[] = {
+ { HIF_UUID2_UUID2, 32, 0, 3265543206 },
+};
+
+static nt_fpga_field_init_t hif_uuid3_fields[] = {
+ { HIF_UUID3_UUID3, 32, 0, 599637710 },
+};
+
+static nt_fpga_register_init_t hif_registers[] = {
+ { HIF_BUILD_TIME, 16, 32, REGISTER_TYPE_RO, 1689706895, 1,
+ hif_build_time_fields
+ },
+ { HIF_CONFIG, 24, 7, REGISTER_TYPE_RW, 0, 3, hif_config_fields },
+ { HIF_CONTROL, 40, 12, REGISTER_TYPE_RW, 1, 2, hif_control_fields },
+ { HIF_PROD_ID_EX, 112, 32, REGISTER_TYPE_RO, 1, 3,
+ hif_prod_id_ex_fields
+ },
+ { HIF_PROD_ID_LSB, 0, 32, REGISTER_TYPE_RO, 626734872, 3,
+ hif_prod_id_lsb_fields
+ },
+ { HIF_PROD_ID_MSB, 8, 22, REGISTER_TYPE_RO, 200, 2,
+ hif_prod_id_msb_fields
+ },
+ { HIF_SAMPLE_TIME, 96, 1, REGISTER_TYPE_WO, 0, 1,
+ hif_sample_time_fields
+ },
+ { HIF_STATUS, 32, 10, REGISTER_TYPE_MIXED, 0, 3, hif_status_fields },
+ { HIF_STAT_CTRL, 64, 2, REGISTER_TYPE_WO, 0, 2, hif_stat_ctrl_fields },
+ { HIF_STAT_REFCLK, 72, 32, REGISTER_TYPE_RO, 0, 1,
+ hif_stat_refclk_fields
+ },
+ { HIF_STAT_RX, 88, 32, REGISTER_TYPE_RO, 0, 1, hif_stat_rx_fields },
+ { HIF_STAT_TX, 80, 32, REGISTER_TYPE_RO, 0, 1, hif_stat_tx_fields },
+ { HIF_TEST0, 48, 32, REGISTER_TYPE_RW, 287454020, 1, hif_test0_fields },
+ { HIF_TEST1, 56, 32, REGISTER_TYPE_RW, 2864434397, 1,
+ hif_test1_fields
+ },
+ { HIF_UUID0, 128, 32, REGISTER_TYPE_RO, 456073826, 1,
+ hif_uuid0_fields
+ },
+ { HIF_UUID1, 144, 32, REGISTER_TYPE_RO, 3051597623, 1,
+ hif_uuid1_fields
+ },
+ { HIF_UUID2, 160, 32, REGISTER_TYPE_RO, 3265543206, 1,
+ hif_uuid2_fields
+ },
+ { HIF_UUID3, 176, 32, REGISTER_TYPE_RO, 599637710, 1,
+ hif_uuid3_fields
+ },
+};
+
+static nt_fpga_field_init_t hsh_rcp_ctrl_fields[] = {
+ { HSH_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { HSH_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t hsh_rcp_data_fields[] = {
+ { HSH_RCP_DATA_AUTO_IPV4_MASK, 1, 742, 0x0000 },
+ { HSH_RCP_DATA_HSH_TYPE, 5, 416, 0x0000 },
+ { HSH_RCP_DATA_HSH_VALID, 1, 415, 0x0000 },
+ { HSH_RCP_DATA_K, 320, 422, 0x0000 },
+ { HSH_RCP_DATA_LOAD_DIST_TYPE, 2, 0, 0x0000 },
+ { HSH_RCP_DATA_MAC_PORT_MASK, 2, 2, 0x0000 },
+ { HSH_RCP_DATA_P_MASK, 1, 61, 0x0000 },
+ { HSH_RCP_DATA_QW0_OFS, 8, 11, 0x0000 },
+ { HSH_RCP_DATA_QW0_PE, 5, 6, 0x0000 },
+ { HSH_RCP_DATA_QW4_OFS, 8, 24, 0x0000 },
+ { HSH_RCP_DATA_QW4_PE, 5, 19, 0x0000 },
+ { HSH_RCP_DATA_SEED, 32, 382, 0x0000 },
+ { HSH_RCP_DATA_SORT, 2, 4, 0x0000 },
+ { HSH_RCP_DATA_TNL_P, 1, 414, 0x0000 },
+ { HSH_RCP_DATA_TOEPLITZ, 1, 421, 0x0000 },
+ { HSH_RCP_DATA_W8_OFS, 8, 37, 0x0000 },
+ { HSH_RCP_DATA_W8_PE, 5, 32, 0x0000 },
+ { HSH_RCP_DATA_W8_SORT, 1, 45, 0x0000 },
+ { HSH_RCP_DATA_W9_OFS, 8, 51, 0x0000 },
+ { HSH_RCP_DATA_W9_P, 1, 60, 0x0000 },
+ { HSH_RCP_DATA_W9_PE, 5, 46, 0x0000 },
+ { HSH_RCP_DATA_W9_SORT, 1, 59, 0x0000 },
+ { HSH_RCP_DATA_WORD_MASK, 320, 62, 0x0000 },
+};
+
+static nt_fpga_register_init_t hsh_registers[] = {
+ { HSH_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hsh_rcp_ctrl_fields },
+ { HSH_RCP_DATA, 1, 743, REGISTER_TYPE_WO, 0, 23, hsh_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t hst_rcp_ctrl_fields[] = {
+ { HST_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { HST_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t hst_rcp_data_fields[] = {
+ { HST_RCP_DATA_END_DYN, 5, 16, 0x0000 },
+ { HST_RCP_DATA_END_OFS, 10, 21, 0x0000 },
+ { HST_RCP_DATA_MODIF0_CMD, 3, 31, 0x0000 },
+ { HST_RCP_DATA_MODIF0_DYN, 5, 34, 0x0000 },
+ { HST_RCP_DATA_MODIF0_OFS, 10, 39, 0x0000 },
+ { HST_RCP_DATA_MODIF0_VALUE, 16, 49, 0x0000 },
+ { HST_RCP_DATA_MODIF1_CMD, 3, 65, 0x0000 },
+ { HST_RCP_DATA_MODIF1_DYN, 5, 68, 0x0000 },
+ { HST_RCP_DATA_MODIF1_OFS, 10, 73, 0x0000 },
+ { HST_RCP_DATA_MODIF1_VALUE, 16, 83, 0x0000 },
+ { HST_RCP_DATA_MODIF2_CMD, 3, 99, 0x0000 },
+ { HST_RCP_DATA_MODIF2_DYN, 5, 102, 0x0000 },
+ { HST_RCP_DATA_MODIF2_OFS, 10, 107, 0x0000 },
+ { HST_RCP_DATA_MODIF2_VALUE, 16, 117, 0x0000 },
+ { HST_RCP_DATA_START_DYN, 5, 1, 0x0000 },
+ { HST_RCP_DATA_START_OFS, 10, 6, 0x0000 },
+ { HST_RCP_DATA_STRIP_MODE, 1, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t hst_registers[] = {
+ { HST_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, hst_rcp_ctrl_fields },
+ { HST_RCP_DATA, 1, 133, REGISTER_TYPE_WO, 0, 17, hst_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t ifr_rcp_ctrl_fields[] = {
+ { IFR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { IFR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t ifr_rcp_data_fields[] = {
+ { IFR_RCP_DATA_EN, 1, 0, 0x0000 },
+ { IFR_RCP_DATA_MTU, 14, 1, 0x0000 },
+};
+
+static nt_fpga_register_init_t ifr_registers[] = {
+ { IFR_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, ifr_rcp_ctrl_fields },
+ { IFR_RCP_DATA, 1, 15, REGISTER_TYPE_WO, 0, 2, ifr_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t iic_adr_fields[] = {
+ { IIC_ADR_SLV_ADR, 7, 1, 0 },
+};
+
+static nt_fpga_field_init_t iic_cr_fields[] = {
+ { IIC_CR_EN, 1, 0, 0 }, { IIC_CR_GC_EN, 1, 6, 0 },
+ { IIC_CR_MSMS, 1, 2, 0 }, { IIC_CR_RST, 1, 7, 0 },
+ { IIC_CR_RSTA, 1, 5, 0 }, { IIC_CR_TX, 1, 3, 0 },
+ { IIC_CR_TXAK, 1, 4, 0 }, { IIC_CR_TXFIFO_RESET, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t iic_dgie_fields[] = {
+ { IIC_DGIE_GIE, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t iic_gpo_fields[] = {
+ { IIC_GPO_GPO_VAL, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_ier_fields[] = {
+ { IIC_IER_INT0, 1, 0, 0 }, { IIC_IER_INT1, 1, 1, 0 },
+ { IIC_IER_INT2, 1, 2, 0 }, { IIC_IER_INT3, 1, 3, 0 },
+ { IIC_IER_INT4, 1, 4, 0 }, { IIC_IER_INT5, 1, 5, 0 },
+ { IIC_IER_INT6, 1, 6, 0 }, { IIC_IER_INT7, 1, 7, 0 },
+};
+
+static nt_fpga_field_init_t iic_isr_fields[] = {
+ { IIC_ISR_INT0, 1, 0, 0 }, { IIC_ISR_INT1, 1, 1, 0 },
+ { IIC_ISR_INT2, 1, 2, 0 }, { IIC_ISR_INT3, 1, 3, 0 },
+ { IIC_ISR_INT4, 1, 4, 0 }, { IIC_ISR_INT5, 1, 5, 0 },
+ { IIC_ISR_INT6, 1, 6, 0 }, { IIC_ISR_INT7, 1, 7, 0 },
+};
+
+static nt_fpga_field_init_t iic_rx_fifo_fields[] = {
+ { IIC_RX_FIFO_RXDATA, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_rx_fifo_ocy_fields[] = {
+ { IIC_RX_FIFO_OCY_OCY_VAL, 4, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_rx_fifo_pirq_fields[] = {
+ { IIC_RX_FIFO_PIRQ_CMP_VAL, 4, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_softr_fields[] = {
+ { IIC_SOFTR_RKEY, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t iic_sr_fields[] = {
+ { IIC_SR_AAS, 1, 1, 0 }, { IIC_SR_ABGC, 1, 0, 0 },
+ { IIC_SR_BB, 1, 2, 0 }, { IIC_SR_RXFIFO_EMPTY, 1, 6, 1 },
+ { IIC_SR_RXFIFO_FULL, 1, 5, 0 }, { IIC_SR_SRW, 1, 3, 0 },
+ { IIC_SR_TXFIFO_EMPTY, 1, 7, 1 }, { IIC_SR_TXFIFO_FULL, 1, 4, 0 },
+};
+
+static nt_fpga_field_init_t iic_tbuf_fields[] = {
+ { IIC_TBUF_TBUF_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_ten_adr_fields[] = {
+ { IIC_TEN_ADR_MSB_SLV_ADR, 3, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_thddat_fields[] = {
+ { IIC_THDDAT_THDDAT_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_thdsta_fields[] = {
+ { IIC_THDSTA_THDSTA_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_thigh_fields[] = {
+ { IIC_THIGH_THIGH_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tlow_fields[] = {
+ { IIC_TLOW_TLOW_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tsudat_fields[] = {
+ { IIC_TSUDAT_TSUDAT_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tsusta_fields[] = {
+ { IIC_TSUSTA_TSUSTA_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tsusto_fields[] = {
+ { IIC_TSUSTO_TSUSTO_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tx_fifo_fields[] = {
+ { IIC_TX_FIFO_START, 1, 8, 0 },
+ { IIC_TX_FIFO_STOP, 1, 9, 0 },
+ { IIC_TX_FIFO_TXDATA, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t iic_tx_fifo_ocy_fields[] = {
+ { IIC_TX_FIFO_OCY_OCY_VAL, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t iic_registers[] = {
+ { IIC_ADR, 68, 8, REGISTER_TYPE_RW, 0, 1, iic_adr_fields },
+ { IIC_CR, 64, 8, REGISTER_TYPE_RW, 0, 8, iic_cr_fields },
+ { IIC_DGIE, 7, 32, REGISTER_TYPE_RW, 0, 1, iic_dgie_fields },
+ { IIC_GPO, 73, 1, REGISTER_TYPE_RW, 0, 1, iic_gpo_fields },
+ { IIC_IER, 10, 8, REGISTER_TYPE_RW, 0, 8, iic_ier_fields },
+ { IIC_ISR, 8, 8, REGISTER_TYPE_RW, 0, 8, iic_isr_fields },
+ { IIC_RX_FIFO, 67, 8, REGISTER_TYPE_RO, 0, 1, iic_rx_fifo_fields },
+ { IIC_RX_FIFO_OCY, 70, 4, REGISTER_TYPE_RO, 0, 1,
+ iic_rx_fifo_ocy_fields
+ },
+ { IIC_RX_FIFO_PIRQ, 72, 4, REGISTER_TYPE_RW, 0, 1,
+ iic_rx_fifo_pirq_fields
+ },
+ { IIC_SOFTR, 16, 4, REGISTER_TYPE_WO, 0, 1, iic_softr_fields },
+ { IIC_SR, 65, 8, REGISTER_TYPE_RO, 192, 8, iic_sr_fields },
+ { IIC_TBUF, 78, 32, REGISTER_TYPE_RW, 0, 1, iic_tbuf_fields },
+ { IIC_TEN_ADR, 71, 3, REGISTER_TYPE_RO, 0, 1, iic_ten_adr_fields },
+ { IIC_THDDAT, 81, 32, REGISTER_TYPE_RW, 0, 1, iic_thddat_fields },
+ { IIC_THDSTA, 76, 32, REGISTER_TYPE_RW, 0, 1, iic_thdsta_fields },
+ { IIC_THIGH, 79, 32, REGISTER_TYPE_RW, 0, 1, iic_thigh_fields },
+ { IIC_TLOW, 80, 32, REGISTER_TYPE_RW, 0, 1, iic_tlow_fields },
+ { IIC_TSUDAT, 77, 32, REGISTER_TYPE_RW, 0, 1, iic_tsudat_fields },
+ { IIC_TSUSTA, 74, 32, REGISTER_TYPE_RW, 0, 1, iic_tsusta_fields },
+ { IIC_TSUSTO, 75, 32, REGISTER_TYPE_RW, 0, 1, iic_tsusto_fields },
+ { IIC_TX_FIFO, 66, 10, REGISTER_TYPE_WO, 0, 3, iic_tx_fifo_fields },
+ { IIC_TX_FIFO_OCY, 69, 4, REGISTER_TYPE_RO, 0, 1,
+ iic_tx_fifo_ocy_fields
+ },
+};
+
+static nt_fpga_field_init_t ins_rcp_ctrl_fields[] = {
+ { INS_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { INS_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t ins_rcp_data_fields[] = {
+ { INS_RCP_DATA_DYN, 5, 0, 0x0000 },
+ { INS_RCP_DATA_LEN, 8, 15, 0x0000 },
+ { INS_RCP_DATA_OFS, 10, 5, 0x0000 },
+};
+
+static nt_fpga_register_init_t ins_registers[] = {
+ { INS_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, ins_rcp_ctrl_fields },
+ { INS_RCP_DATA, 1, 23, REGISTER_TYPE_WO, 0, 3, ins_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t km_cam_ctrl_fields[] = {
+ { KM_CAM_CTRL_ADR, 13, 0, 0x0000 },
+ { KM_CAM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_cam_data_fields[] = {
+ { KM_CAM_DATA_FT0, 4, 192, 0x0000 },
+ { KM_CAM_DATA_FT1, 4, 196, 0x0000 },
+ { KM_CAM_DATA_FT2, 4, 200, 0x0000 },
+ { KM_CAM_DATA_FT3, 4, 204, 0x0000 },
+ { KM_CAM_DATA_FT4, 4, 208, 0x0000 },
+ { KM_CAM_DATA_FT5, 4, 212, 0x0000 },
+ { KM_CAM_DATA_W0, 32, 0, 0x0000 },
+ { KM_CAM_DATA_W1, 32, 32, 0x0000 },
+ { KM_CAM_DATA_W2, 32, 64, 0x0000 },
+ { KM_CAM_DATA_W3, 32, 96, 0x0000 },
+ { KM_CAM_DATA_W4, 32, 128, 0x0000 },
+ { KM_CAM_DATA_W5, 32, 160, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_rcp_ctrl_fields[] = {
+ { KM_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { KM_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_rcp_data_fields[] = {
+ { KM_RCP_DATA_BANK_A, 12, 694, 0x0000 },
+ { KM_RCP_DATA_BANK_B, 12, 706, 0x0000 },
+ { KM_RCP_DATA_DUAL, 1, 651, 0x0000 },
+ { KM_RCP_DATA_DW0_B_DYN, 5, 729, 0x0000 },
+ { KM_RCP_DATA_DW0_B_OFS, 8, 734, 0x0000 },
+ { KM_RCP_DATA_DW10_DYN, 5, 55, 0x0000 },
+ { KM_RCP_DATA_DW10_OFS, 8, 60, 0x0000 },
+ { KM_RCP_DATA_DW10_SEL_A, 2, 68, 0x0000 },
+ { KM_RCP_DATA_DW10_SEL_B, 2, 70, 0x0000 },
+ { KM_RCP_DATA_DW2_B_DYN, 5, 742, 0x0000 },
+ { KM_RCP_DATA_DW2_B_OFS, 8, 747, 0x0000 },
+ { KM_RCP_DATA_DW8_DYN, 5, 36, 0x0000 },
+ { KM_RCP_DATA_DW8_OFS, 8, 41, 0x0000 },
+ { KM_RCP_DATA_DW8_SEL_A, 3, 49, 0x0000 },
+ { KM_RCP_DATA_DW8_SEL_B, 3, 52, 0x0000 },
+ { KM_RCP_DATA_EL_A, 4, 653, 0x0000 },
+ { KM_RCP_DATA_EL_B, 3, 657, 0x0000 },
+ { KM_RCP_DATA_FTM_A, 16, 662, 0x0000 },
+ { KM_RCP_DATA_FTM_B, 16, 678, 0x0000 },
+ { KM_RCP_DATA_INFO_A, 1, 660, 0x0000 },
+ { KM_RCP_DATA_INFO_B, 1, 661, 0x0000 },
+ { KM_RCP_DATA_KEYWAY_A, 1, 725, 0x0000 },
+ { KM_RCP_DATA_KEYWAY_B, 1, 726, 0x0000 },
+ { KM_RCP_DATA_KL_A, 4, 718, 0x0000 },
+ { KM_RCP_DATA_KL_B, 3, 722, 0x0000 },
+ { KM_RCP_DATA_MASK_A, 384, 75, 0x0000 },
+ { KM_RCP_DATA_MASK_B, 192, 459, 0x0000 },
+ { KM_RCP_DATA_PAIRED, 1, 652, 0x0000 },
+ { KM_RCP_DATA_QW0_DYN, 5, 0, 0x0000 },
+ { KM_RCP_DATA_QW0_OFS, 8, 5, 0x0000 },
+ { KM_RCP_DATA_QW0_SEL_A, 3, 13, 0x0000 },
+ { KM_RCP_DATA_QW0_SEL_B, 3, 16, 0x0000 },
+ { KM_RCP_DATA_QW4_DYN, 5, 19, 0x0000 },
+ { KM_RCP_DATA_QW4_OFS, 8, 24, 0x0000 },
+ { KM_RCP_DATA_QW4_SEL_A, 2, 32, 0x0000 },
+ { KM_RCP_DATA_QW4_SEL_B, 2, 34, 0x0000 },
+ { KM_RCP_DATA_SW4_B_DYN, 5, 755, 0x0000 },
+ { KM_RCP_DATA_SW4_B_OFS, 8, 760, 0x0000 },
+ { KM_RCP_DATA_SW5_B_DYN, 5, 768, 0x0000 },
+ { KM_RCP_DATA_SW5_B_OFS, 8, 773, 0x0000 },
+ { KM_RCP_DATA_SWX_CCH, 1, 72, 0x0000 },
+ { KM_RCP_DATA_SWX_SEL_A, 1, 73, 0x0000 },
+ { KM_RCP_DATA_SWX_SEL_B, 1, 74, 0x0000 },
+ { KM_RCP_DATA_SYNERGY_MODE, 2, 727, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_status_fields[] = {
+ { KM_STATUS_TCQ_RDY, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcam_ctrl_fields[] = {
+ { KM_TCAM_CTRL_ADR, 14, 0, 0x0000 },
+ { KM_TCAM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcam_data_fields[] = {
+ { KM_TCAM_DATA_T, 72, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tci_ctrl_fields[] = {
+ { KM_TCI_CTRL_ADR, 10, 0, 0x0000 },
+ { KM_TCI_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tci_data_fields[] = {
+ { KM_TCI_DATA_COLOR, 32, 0, 0x0000 },
+ { KM_TCI_DATA_FT, 4, 32, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcq_ctrl_fields[] = {
+ { KM_TCQ_CTRL_ADR, 7, 0, 0x0000 },
+ { KM_TCQ_CTRL_CNT, 5, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t km_tcq_data_fields[] = {
+ { KM_TCQ_DATA_BANK_MASK, 12, 0, 0x0000 },
+ { KM_TCQ_DATA_QUAL, 3, 12, 0x0000 },
+};
+
+static nt_fpga_register_init_t km_registers[] = {
+ { KM_CAM_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, km_cam_ctrl_fields },
+ { KM_CAM_DATA, 3, 216, REGISTER_TYPE_WO, 0, 12, km_cam_data_fields },
+ { KM_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, km_rcp_ctrl_fields },
+ { KM_RCP_DATA, 1, 781, REGISTER_TYPE_WO, 0, 44, km_rcp_data_fields },
+ { KM_STATUS, 10, 1, REGISTER_TYPE_RO, 0, 1, km_status_fields },
+ { KM_TCAM_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, km_tcam_ctrl_fields },
+ { KM_TCAM_DATA, 5, 72, REGISTER_TYPE_WO, 0, 1, km_tcam_data_fields },
+ { KM_TCI_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, km_tci_ctrl_fields },
+ { KM_TCI_DATA, 7, 36, REGISTER_TYPE_WO, 0, 2, km_tci_data_fields },
+ { KM_TCQ_CTRL, 8, 21, REGISTER_TYPE_WO, 0, 2, km_tcq_ctrl_fields },
+ { KM_TCQ_DATA, 9, 15, REGISTER_TYPE_WO, 0, 2, km_tcq_data_fields },
+};
+
+static nt_fpga_field_init_t mac_pcs_bad_code_fields[] = {
+ { MAC_PCS_BAD_CODE_CODE_ERR, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_bip_err_fields[] = {
+ { MAC_PCS_BIP_ERR_BIP_ERR, 640, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_block_lock_fields[] = {
+ { MAC_PCS_BLOCK_LOCK_LOCK, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_block_lock_chg_fields[] = {
+ { MAC_PCS_BLOCK_LOCK_CHG_LOCK_CHG, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_debounce_ctrl_fields[] = {
+ { MAC_PCS_DEBOUNCE_CTRL_NT_DEBOUNCE_LATENCY, 8, 8, 10 },
+ { MAC_PCS_DEBOUNCE_CTRL_NT_FORCE_LINK_DOWN, 1, 16, 0 },
+ { MAC_PCS_DEBOUNCE_CTRL_NT_LINKUP_LATENCY, 8, 0, 10 },
+ { MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL, 2, 17, 2 },
+};
+
+static nt_fpga_field_init_t mac_pcs_drp_ctrl_fields[] = {
+ { MAC_PCS_DRP_CTRL_ADR, 10, 16, 0 },
+ { MAC_PCS_DRP_CTRL_DATA, 16, 0, 0 },
+ { MAC_PCS_DRP_CTRL_DBG_BUSY, 1, 30, 0x0000 },
+ { MAC_PCS_DRP_CTRL_DONE, 1, 31, 0x0000 },
+ { MAC_PCS_DRP_CTRL_MOD_ADR, 3, 26, 0 },
+ { MAC_PCS_DRP_CTRL_WREN, 1, 29, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_ctrl_fields[] = {
+ { MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN, 5, 0, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_cw_cnt_fields[] = {
+ { MAC_PCS_FEC_CW_CNT_CW_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_0_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_0_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_1_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_1_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_2_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_2_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_err_cnt_3_fields[] = {
+ { MAC_PCS_FEC_ERR_CNT_3_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_0_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_0_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_1_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_1_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_2_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_2_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_dly_3_fields[] = {
+ { MAC_PCS_FEC_LANE_DLY_3_DLY, 14, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_lane_map_fields[] = {
+ { MAC_PCS_FEC_LANE_MAP_MAPPING, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_stat_fields[] = {
+ { MAC_PCS_FEC_STAT_AM_LOCK, 1, 10, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_0, 1, 3, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_1, 1, 4, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_2, 1, 5, 0x0000 },
+ { MAC_PCS_FEC_STAT_AM_LOCK_3, 1, 6, 0x0000 },
+ { MAC_PCS_FEC_STAT_BLOCK_LOCK, 1, 9, 0x0000 },
+ { MAC_PCS_FEC_STAT_BYPASS, 1, 0, 0x0000 },
+ { MAC_PCS_FEC_STAT_FEC_LANE_ALGN, 1, 7, 0x0000 },
+ { MAC_PCS_FEC_STAT_HI_SER, 1, 2, 0x0000 },
+ { MAC_PCS_FEC_STAT_PCS_LANE_ALGN, 1, 8, 0x0000 },
+ { MAC_PCS_FEC_STAT_VALID, 1, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_fec_ucw_cnt_fields[] = {
+ { MAC_PCS_FEC_UCW_CNT_UCW_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_ctl_rx_fields[] = {
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_0, 1, 24, 0 },
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_1, 1, 25, 0 },
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_2, 1, 26, 0 },
+ { MAC_PCS_GTY_CTL_RX_CDR_HOLD_3, 1, 27, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_0, 1, 20, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_1, 1, 21, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_2, 1, 22, 0 },
+ { MAC_PCS_GTY_CTL_RX_EQUA_RST_3, 1, 23, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_0, 1, 16, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_1, 1, 17, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_2, 1, 18, 0 },
+ { MAC_PCS_GTY_CTL_RX_LPM_EN_3, 1, 19, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_0, 1, 0, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_1, 1, 1, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_2, 1, 2, 0 },
+ { MAC_PCS_GTY_CTL_RX_POLARITY_3, 1, 3, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_0, 3, 4, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_1, 3, 7, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_2, 3, 10, 0 },
+ { MAC_PCS_GTY_CTL_RX_RATE_3, 3, 13, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_ctl_tx_fields[] = {
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_0, 1, 4, 0 },
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_1, 1, 5, 0 },
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_2, 1, 6, 0 },
+ { MAC_PCS_GTY_CTL_TX_INHIBIT_3, 1, 7, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_0, 1, 0, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_1, 1, 1, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_2, 1, 2, 0 },
+ { MAC_PCS_GTY_CTL_TX_POLARITY_3, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_diff_ctl_fields[] = {
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0, 5, 0, 24 },
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1, 5, 5, 24 },
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2, 5, 10, 24 },
+ { MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3, 5, 15, 24 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_loop_fields[] = {
+ { MAC_PCS_GTY_LOOP_GT_LOOP_0, 3, 0, 0 },
+ { MAC_PCS_GTY_LOOP_GT_LOOP_1, 3, 3, 0 },
+ { MAC_PCS_GTY_LOOP_GT_LOOP_2, 3, 6, 0 },
+ { MAC_PCS_GTY_LOOP_GT_LOOP_3, 3, 9, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_post_cursor_fields[] = {
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0, 5, 0, 20 },
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1, 5, 5, 20 },
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2, 5, 10, 20 },
+ { MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3, 5, 15, 20 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_prbs_sel_fields[] = {
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_0, 4, 16, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_1, 4, 20, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_2, 4, 24, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_3, 4, 28, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_0, 4, 0, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_1, 4, 4, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_2, 4, 8, 0 },
+ { MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_3, 4, 12, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_pre_cursor_fields[] = {
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0, 5, 0, 0 },
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1, 5, 5, 0 },
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2, 5, 10, 0 },
+ { MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3, 5, 15, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_rx_buf_stat_fields[] = {
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0, 3, 0, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1, 3, 3, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2, 3, 6, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3, 3, 9, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0, 3, 12, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1, 3, 15, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2, 3, 18, 0x0000 },
+ { MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3, 3, 21, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_scan_ctl_fields[] = {
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_0, 1, 0, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_1, 1, 1, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_2, 1, 2, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_3, 1, 3, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_0, 1, 4, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_1, 1, 5, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_2, 1, 6, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_3, 1, 7, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_0, 1, 12, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_1, 1, 13, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_2, 1, 14, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_3, 1, 15, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_0, 1, 8, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_1, 1, 9, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_2, 1, 10, 0 },
+ { MAC_PCS_GTY_SCAN_CTL_PRBS_RST_3, 1, 11, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_scan_stat_fields[] = {
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_0, 1, 0, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_1, 1, 1, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_2, 1, 2, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_3, 1, 3, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_0, 1, 4, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_1, 1, 5, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_2, 1, 6, 0x0000 },
+ { MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_3, 1, 7, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_gty_stat_fields[] = {
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_0, 1, 4, 0x0000 },
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_1, 1, 5, 0x0000 },
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_2, 1, 6, 0x0000 },
+ { MAC_PCS_GTY_STAT_RX_RST_DONE_3, 1, 7, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_0, 2, 8, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_1, 2, 10, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_2, 2, 12, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_BUF_STAT_3, 2, 14, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_0, 1, 0, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_1, 1, 1, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_2, 1, 2, 0x0000 },
+ { MAC_PCS_GTY_STAT_TX_RST_DONE_3, 1, 3, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_link_summary_fields[] = {
+ { MAC_PCS_LINK_SUMMARY_ABS, 1, 0, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_LH_ABS, 1, 2, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT, 1, 13, 0 },
+ { MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT, 1, 14, 0 },
+ { MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT, 8, 4, 0 },
+ { MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE, 1, 3, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_LOCAL_FAULT, 1, 17, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_NIM_INTERR, 1, 12, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE, 1, 1, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_REMOTE_FAULT, 1, 18, 0x0000 },
+ { MAC_PCS_LINK_SUMMARY_RESERVED, 2, 15, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_mac_pcs_config_fields[] = {
+ { MAC_PCS_MAC_PCS_CONFIG_RX_CORE_RST, 1, 3, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE, 1, 5, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC, 1, 6, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST, 1, 1, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN, 1, 7, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_CORE_RST, 1, 2, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE, 1, 8, 1 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_FCS_REMOVE, 1, 4, 1 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST, 1, 0, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE, 1, 9, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI, 1, 10, 0 },
+ { MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN, 1, 11, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_max_pkt_len_fields[] = {
+ { MAC_PCS_MAX_PKT_LEN_MAX_LEN, 14, 0, 10000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_phymac_misc_fields[] = {
+ { MAC_PCS_PHYMAC_MISC_TS_EOP, 1, 3, 1 },
+ { MAC_PCS_PHYMAC_MISC_TX_MUX_STATE, 4, 4, 0x0000 },
+ { MAC_PCS_PHYMAC_MISC_TX_SEL_HOST, 1, 0, 1 },
+ { MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP, 1, 2, 0 },
+ { MAC_PCS_PHYMAC_MISC_TX_SEL_TFG, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t mac_pcs_phy_stat_fields[] = {
+ { MAC_PCS_PHY_STAT_ALARM, 1, 2, 0x0000 },
+ { MAC_PCS_PHY_STAT_MOD_PRS, 1, 1, 0x0000 },
+ { MAC_PCS_PHY_STAT_RX_LOS, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_stat_pcs_rx_fields[] = {
+ { MAC_PCS_STAT_PCS_RX_ALIGNED, 1, 1, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_ALIGNED_ERR, 1, 2, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_GOT_SIGNAL_OS, 1, 9, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_HI_BER, 1, 8, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT, 1, 4, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LOCAL_FAULT, 1, 6, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_MISALIGNED, 1, 3, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT, 1, 5, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_REMOTE_FAULT, 1, 7, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_STATUS, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_stat_pcs_rx_latch_fields[] = {
+ { MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED, 1, 1, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED_ERR, 1, 2, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_GOT_SIGNAL_OS, 1, 9, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_HI_BER, 1, 8, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_INTERNAL_LOCAL_FAULT, 1, 4, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_LOCAL_FAULT, 1, 6, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_MISALIGNED, 1, 3, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_RECEIVED_LOCAL_FAULT, 1, 5, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_REMOTE_FAULT, 1, 7, 0x0000 },
+ { MAC_PCS_STAT_PCS_RX_LATCH_STATUS, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_stat_pcs_tx_fields[] = {
+ { MAC_PCS_STAT_PCS_TX_LOCAL_FAULT, 1, 0, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_LOCAL_FAULT_CHANGED, 1, 5, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR, 1, 4, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR_CHANGED, 1, 9, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR, 1, 3, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR_CHANGED, 1, 8, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_OVFOUT, 1, 2, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_OVFOUT_CHANGED, 1, 7, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_UNFOUT, 1, 1, 0x0000 },
+ { MAC_PCS_STAT_PCS_TX_TX_UNFOUT_CHANGED, 1, 6, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_synced_fields[] = {
+ { MAC_PCS_SYNCED_SYNC, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_synced_err_fields[] = {
+ { MAC_PCS_SYNCED_ERR_SYNC_ERROR, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_test_err_fields[] = {
+ { MAC_PCS_TEST_ERR_CODE_ERR, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_timestamp_comp_fields[] = {
+ { MAC_PCS_TIMESTAMP_COMP_RX_DLY, 16, 0, 1451 },
+ { MAC_PCS_TIMESTAMP_COMP_TX_DLY, 16, 16, 1440 },
+};
+
+static nt_fpga_field_init_t mac_pcs_vl_demuxed_fields[] = {
+ { MAC_PCS_VL_DEMUXED_LOCK, 20, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_pcs_vl_demuxed_chg_fields[] = {
+ { MAC_PCS_VL_DEMUXED_CHG_LOCK_CHG, 20, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t mac_pcs_registers[] = {
+ { MAC_PCS_BAD_CODE, 26, 16, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_bad_code_fields
+ },
+ { MAC_PCS_BIP_ERR, 31, 640, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_bip_err_fields
+ },
+ { MAC_PCS_BLOCK_LOCK, 27, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_block_lock_fields
+ },
+ { MAC_PCS_BLOCK_LOCK_CHG, 28, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_block_lock_chg_fields
+ },
+ { MAC_PCS_DEBOUNCE_CTRL, 1, 19, REGISTER_TYPE_RW, 264714, 4,
+ mac_pcs_debounce_ctrl_fields
+ },
+ { MAC_PCS_DRP_CTRL, 43, 32, REGISTER_TYPE_MIXED, 0, 6,
+ mac_pcs_drp_ctrl_fields
+ },
+ { MAC_PCS_FEC_CTRL, 2, 5, REGISTER_TYPE_RW, 0, 1,
+ mac_pcs_fec_ctrl_fields
+ },
+ { MAC_PCS_FEC_CW_CNT, 9, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_cw_cnt_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_0, 11, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_0_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_1, 12, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_1_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_2, 13, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_2_fields
+ },
+ { MAC_PCS_FEC_ERR_CNT_3, 14, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_err_cnt_3_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_0, 5, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_0_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_1, 6, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_1_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_2, 7, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_2_fields
+ },
+ { MAC_PCS_FEC_LANE_DLY_3, 8, 14, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_dly_3_fields
+ },
+ { MAC_PCS_FEC_LANE_MAP, 4, 8, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_lane_map_fields
+ },
+ { MAC_PCS_FEC_STAT, 3, 11, REGISTER_TYPE_RO, 0, 11,
+ mac_pcs_fec_stat_fields
+ },
+ { MAC_PCS_FEC_UCW_CNT, 10, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_fec_ucw_cnt_fields
+ },
+ { MAC_PCS_GTY_CTL_RX, 38, 28, REGISTER_TYPE_RW, 0, 20,
+ mac_pcs_gty_ctl_rx_fields
+ },
+ { MAC_PCS_GTY_CTL_TX, 39, 8, REGISTER_TYPE_RW, 0, 8,
+ mac_pcs_gty_ctl_tx_fields
+ },
+ { MAC_PCS_GTY_DIFF_CTL, 35, 20, REGISTER_TYPE_RW, 811800, 4,
+ mac_pcs_gty_diff_ctl_fields
+ },
+ { MAC_PCS_GTY_LOOP, 20, 12, REGISTER_TYPE_RW, 0, 4,
+ mac_pcs_gty_loop_fields
+ },
+ { MAC_PCS_GTY_POST_CURSOR, 36, 20, REGISTER_TYPE_RW, 676500, 4,
+ mac_pcs_gty_post_cursor_fields
+ },
+ { MAC_PCS_GTY_PRBS_SEL, 40, 32, REGISTER_TYPE_RW, 0, 8,
+ mac_pcs_gty_prbs_sel_fields
+ },
+ { MAC_PCS_GTY_PRE_CURSOR, 37, 20, REGISTER_TYPE_RW, 0, 4,
+ mac_pcs_gty_pre_cursor_fields
+ },
+ { MAC_PCS_GTY_RX_BUF_STAT, 34, 24, REGISTER_TYPE_RO, 0, 8,
+ mac_pcs_gty_rx_buf_stat_fields
+ },
+ { MAC_PCS_GTY_SCAN_CTL, 41, 16, REGISTER_TYPE_RW, 0, 16,
+ mac_pcs_gty_scan_ctl_fields
+ },
+ { MAC_PCS_GTY_SCAN_STAT, 42, 8, REGISTER_TYPE_RO, 0, 8,
+ mac_pcs_gty_scan_stat_fields
+ },
+ { MAC_PCS_GTY_STAT, 33, 16, REGISTER_TYPE_RO, 0, 12,
+ mac_pcs_gty_stat_fields
+ },
+ { MAC_PCS_LINK_SUMMARY, 0, 19, REGISTER_TYPE_RO, 0, 11,
+ mac_pcs_link_summary_fields
+ },
+ { MAC_PCS_MAC_PCS_CONFIG, 19, 12, REGISTER_TYPE_RW, 272, 12,
+ mac_pcs_mac_pcs_config_fields
+ },
+ { MAC_PCS_MAX_PKT_LEN, 17, 14, REGISTER_TYPE_RW, 10000, 1,
+ mac_pcs_max_pkt_len_fields
+ },
+ { MAC_PCS_PHYMAC_MISC, 16, 8, REGISTER_TYPE_MIXED, 9, 5,
+ mac_pcs_phymac_misc_fields
+ },
+ { MAC_PCS_PHY_STAT, 15, 3, REGISTER_TYPE_RO, 0, 3,
+ mac_pcs_phy_stat_fields
+ },
+ { MAC_PCS_STAT_PCS_RX, 21, 10, REGISTER_TYPE_RO, 0, 10,
+ mac_pcs_stat_pcs_rx_fields
+ },
+ { MAC_PCS_STAT_PCS_RX_LATCH, 22, 10, REGISTER_TYPE_RO, 0, 10,
+ mac_pcs_stat_pcs_rx_latch_fields
+ },
+ { MAC_PCS_STAT_PCS_TX, 23, 10, REGISTER_TYPE_RO, 0, 10,
+ mac_pcs_stat_pcs_tx_fields
+ },
+ { MAC_PCS_SYNCED, 24, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_synced_fields
+ },
+ { MAC_PCS_SYNCED_ERR, 25, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_synced_err_fields
+ },
+ { MAC_PCS_TEST_ERR, 32, 16, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_test_err_fields
+ },
+ { MAC_PCS_TIMESTAMP_COMP, 18, 32, REGISTER_TYPE_RW, 94373291, 2,
+ mac_pcs_timestamp_comp_fields
+ },
+ { MAC_PCS_VL_DEMUXED, 29, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_vl_demuxed_fields
+ },
+ { MAC_PCS_VL_DEMUXED_CHG, 30, 20, REGISTER_TYPE_RO, 0, 1,
+ mac_pcs_vl_demuxed_chg_fields
+ },
+};
+
+static nt_fpga_field_init_t mac_rx_bad_fcs_fields[] = {
+ { MAC_RX_BAD_FCS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_fragment_fields[] = {
+ { MAC_RX_FRAGMENT_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_packet_bad_fcs_fields[] = {
+ { MAC_RX_PACKET_BAD_FCS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_packet_small_fields[] = {
+ { MAC_RX_PACKET_SMALL_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_bytes_fields[] = {
+ { MAC_RX_TOTAL_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_good_bytes_fields[] = {
+ { MAC_RX_TOTAL_GOOD_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_good_packets_fields[] = {
+ { MAC_RX_TOTAL_GOOD_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_total_packets_fields[] = {
+ { MAC_RX_TOTAL_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_rx_undersize_fields[] = {
+ { MAC_RX_UNDERSIZE_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t mac_rx_registers[] = {
+ { MAC_RX_BAD_FCS, 0, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_bad_fcs_fields
+ },
+ { MAC_RX_FRAGMENT, 6, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_fragment_fields
+ },
+ { MAC_RX_PACKET_BAD_FCS, 7, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_packet_bad_fcs_fields
+ },
+ { MAC_RX_PACKET_SMALL, 3, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_packet_small_fields
+ },
+ { MAC_RX_TOTAL_BYTES, 4, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_bytes_fields
+ },
+ { MAC_RX_TOTAL_GOOD_BYTES, 5, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_good_bytes_fields
+ },
+ { MAC_RX_TOTAL_GOOD_PACKETS, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_good_packets_fields
+ },
+ { MAC_RX_TOTAL_PACKETS, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_total_packets_fields
+ },
+ { MAC_RX_UNDERSIZE, 8, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_rx_undersize_fields
+ },
+};
+
+static nt_fpga_field_init_t mac_tx_packet_small_fields[] = {
+ { MAC_TX_PACKET_SMALL_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_bytes_fields[] = {
+ { MAC_TX_TOTAL_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_good_bytes_fields[] = {
+ { MAC_TX_TOTAL_GOOD_BYTES_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_good_packets_fields[] = {
+ { MAC_TX_TOTAL_GOOD_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t mac_tx_total_packets_fields[] = {
+ { MAC_TX_TOTAL_PACKETS_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t mac_tx_registers[] = {
+ { MAC_TX_PACKET_SMALL, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_packet_small_fields
+ },
+ { MAC_TX_TOTAL_BYTES, 3, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_bytes_fields
+ },
+ { MAC_TX_TOTAL_GOOD_BYTES, 4, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_good_bytes_fields
+ },
+ { MAC_TX_TOTAL_GOOD_PACKETS, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_good_packets_fields
+ },
+ { MAC_TX_TOTAL_PACKETS, 0, 32, REGISTER_TYPE_RO, 0, 1,
+ mac_tx_total_packets_fields
+ },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_ctrl_fields[] = {
+ { PCI_RD_TG_TG_CTRL_TG_RD_RDY, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rdaddr_fields[] = {
+ { PCI_RD_TG_TG_RDADDR_RAM_ADDR, 9, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rddata0_fields[] = {
+ { PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rddata1_fields[] = {
+ { PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rddata2_fields[] = {
+ { PCI_RD_TG_TG_RDDATA2_REQ_HID, 6, 22, 0 },
+ { PCI_RD_TG_TG_RDDATA2_REQ_SIZE, 22, 0, 0 },
+ { PCI_RD_TG_TG_RDDATA2_WAIT, 1, 30, 0 },
+ { PCI_RD_TG_TG_RDDATA2_WRAP, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t pci_rd_tg_tg_rd_run_fields[] = {
+ { PCI_RD_TG_TG_RD_RUN_RD_ITERATION, 16, 0, 0 },
+};
+
+static nt_fpga_register_init_t pci_rd_tg_registers[] = {
+ { PCI_RD_TG_TG_CTRL, 5, 1, REGISTER_TYPE_RO, 0, 1,
+ pci_rd_tg_tg_ctrl_fields
+ },
+ { PCI_RD_TG_TG_RDADDR, 3, 9, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rdaddr_fields
+ },
+ { PCI_RD_TG_TG_RDDATA0, 0, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rddata0_fields
+ },
+ { PCI_RD_TG_TG_RDDATA1, 1, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rddata1_fields
+ },
+ { PCI_RD_TG_TG_RDDATA2, 2, 32, REGISTER_TYPE_WO, 0, 4,
+ pci_rd_tg_tg_rddata2_fields
+ },
+ { PCI_RD_TG_TG_RD_RUN, 4, 16, REGISTER_TYPE_WO, 0, 1,
+ pci_rd_tg_tg_rd_run_fields
+ },
+};
+
+static nt_fpga_field_init_t pci_ta_control_fields[] = {
+ { PCI_TA_CONTROL_ENABLE, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_ta_length_error_fields[] = {
+ { PCI_TA_LENGTH_ERROR_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t pci_ta_packet_bad_fields[] = {
+ { PCI_TA_PACKET_BAD_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t pci_ta_packet_good_fields[] = {
+ { PCI_TA_PACKET_GOOD_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t pci_ta_payload_error_fields[] = {
+ { PCI_TA_PAYLOAD_ERROR_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t pci_ta_registers[] = {
+ { PCI_TA_CONTROL, 0, 1, REGISTER_TYPE_WO, 0, 1, pci_ta_control_fields },
+ { PCI_TA_LENGTH_ERROR, 3, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_length_error_fields
+ },
+ { PCI_TA_PACKET_BAD, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_packet_bad_fields
+ },
+ { PCI_TA_PACKET_GOOD, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_packet_good_fields
+ },
+ { PCI_TA_PAYLOAD_ERROR, 4, 32, REGISTER_TYPE_RO, 0, 1,
+ pci_ta_payload_error_fields
+ },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_ctrl_fields[] = {
+ { PCI_WR_TG_TG_CTRL_TG_WR_RDY, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_seq_fields[] = {
+ { PCI_WR_TG_TG_SEQ_SEQUENCE, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wraddr_fields[] = {
+ { PCI_WR_TG_TG_WRADDR_RAM_ADDR, 9, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wrdata0_fields[] = {
+ { PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wrdata1_fields[] = {
+ { PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wrdata2_fields[] = {
+ { PCI_WR_TG_TG_WRDATA2_INC_MODE, 1, 29, 0 },
+ { PCI_WR_TG_TG_WRDATA2_REQ_HID, 6, 22, 0 },
+ { PCI_WR_TG_TG_WRDATA2_REQ_SIZE, 22, 0, 0 },
+ { PCI_WR_TG_TG_WRDATA2_WAIT, 1, 30, 0 },
+ { PCI_WR_TG_TG_WRDATA2_WRAP, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t pci_wr_tg_tg_wr_run_fields[] = {
+ { PCI_WR_TG_TG_WR_RUN_WR_ITERATION, 16, 0, 0 },
+};
+
+static nt_fpga_register_init_t pci_wr_tg_registers[] = {
+ { PCI_WR_TG_TG_CTRL, 5, 1, REGISTER_TYPE_RO, 0, 1,
+ pci_wr_tg_tg_ctrl_fields
+ },
+ { PCI_WR_TG_TG_SEQ, 6, 16, REGISTER_TYPE_RW, 0, 1,
+ pci_wr_tg_tg_seq_fields
+ },
+ { PCI_WR_TG_TG_WRADDR, 3, 9, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wraddr_fields
+ },
+ { PCI_WR_TG_TG_WRDATA0, 0, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wrdata0_fields
+ },
+ { PCI_WR_TG_TG_WRDATA1, 1, 32, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wrdata1_fields
+ },
+ { PCI_WR_TG_TG_WRDATA2, 2, 32, REGISTER_TYPE_WO, 0, 5,
+ pci_wr_tg_tg_wrdata2_fields
+ },
+ { PCI_WR_TG_TG_WR_RUN, 4, 16, REGISTER_TYPE_WO, 0, 1,
+ pci_wr_tg_tg_wr_run_fields
+ },
+};
+
+static nt_fpga_field_init_t pdb_config_fields[] = {
+ { PDB_CONFIG_PORT_OFS, 6, 3, 0 },
+ { PDB_CONFIG_TS_FORMAT, 3, 0, 0 },
+};
+
+static nt_fpga_field_init_t pdb_rcp_ctrl_fields[] = {
+ { PDB_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { PDB_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t pdb_rcp_data_fields[] = {
+ { PDB_RCP_DATA_ALIGN, 1, 17, 0x0000 },
+ { PDB_RCP_DATA_CRC_OVERWRITE, 1, 16, 0x0000 },
+ { PDB_RCP_DATA_DESCRIPTOR, 4, 0, 0x0000 },
+ { PDB_RCP_DATA_DESC_LEN, 5, 4, 0 },
+ { PDB_RCP_DATA_DUPLICATE_BIT, 5, 61, 0x0000 },
+ { PDB_RCP_DATA_DUPLICATE_EN, 1, 60, 0x0000 },
+ { PDB_RCP_DATA_IP_PROT_TNL, 1, 57, 0x0000 },
+ { PDB_RCP_DATA_OFS0_DYN, 5, 18, 0x0000 },
+ { PDB_RCP_DATA_OFS0_REL, 8, 23, 0x0000 },
+ { PDB_RCP_DATA_OFS1_DYN, 5, 31, 0x0000 },
+ { PDB_RCP_DATA_OFS1_REL, 8, 36, 0x0000 },
+ { PDB_RCP_DATA_OFS2_DYN, 5, 44, 0x0000 },
+ { PDB_RCP_DATA_OFS2_REL, 8, 49, 0x0000 },
+ { PDB_RCP_DATA_PCAP_KEEP_FCS, 1, 66, 0x0000 },
+ { PDB_RCP_DATA_PPC_HSH, 2, 58, 0x0000 },
+ { PDB_RCP_DATA_TX_IGNORE, 1, 14, 0x0000 },
+ { PDB_RCP_DATA_TX_NOW, 1, 15, 0x0000 },
+ { PDB_RCP_DATA_TX_PORT, 5, 9, 0x0000 },
+};
+
+static nt_fpga_register_init_t pdb_registers[] = {
+ { PDB_CONFIG, 2, 10, REGISTER_TYPE_WO, 0, 2, pdb_config_fields },
+ { PDB_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, pdb_rcp_ctrl_fields },
+ { PDB_RCP_DATA, 1, 67, REGISTER_TYPE_WO, 0, 18, pdb_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t pdi_cr_fields[] = {
+ { PDI_CR_EN, 1, 0, 0 }, { PDI_CR_PARITY, 1, 4, 0 },
+ { PDI_CR_RST, 1, 1, 0 }, { PDI_CR_RXRST, 1, 2, 0 },
+ { PDI_CR_STOP, 1, 5, 0 }, { PDI_CR_TXRST, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t pdi_drr_fields[] = {
+ { PDI_DRR_DRR, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t pdi_dtr_fields[] = {
+ { PDI_DTR_DTR, 8, 0, 0 },
+};
+
+static nt_fpga_field_init_t pdi_pre_fields[] = {
+ { PDI_PRE_PRE, 7, 0, 3 },
+};
+
+static nt_fpga_field_init_t pdi_sr_fields[] = {
+ { PDI_SR_DISABLE_BUSY, 1, 2, 0 }, { PDI_SR_DONE, 1, 0, 0 },
+ { PDI_SR_ENABLE_BUSY, 1, 1, 0 }, { PDI_SR_FRAME_ERR, 1, 5, 0 },
+ { PDI_SR_OVERRUN_ERR, 1, 7, 0 }, { PDI_SR_PARITY_ERR, 1, 6, 0 },
+ { PDI_SR_RXLVL, 7, 8, 0 }, { PDI_SR_RX_BUSY, 1, 4, 0 },
+ { PDI_SR_TXLVL, 7, 15, 0 }, { PDI_SR_TX_BUSY, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t pdi_srr_fields[] = {
+ { PDI_SRR_RST, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t pdi_registers[] = {
+ { PDI_CR, 1, 6, REGISTER_TYPE_WO, 0, 6, pdi_cr_fields },
+ { PDI_DRR, 4, 8, REGISTER_TYPE_RO, 0, 1, pdi_drr_fields },
+ { PDI_DTR, 3, 8, REGISTER_TYPE_WO, 0, 1, pdi_dtr_fields },
+ { PDI_PRE, 5, 7, REGISTER_TYPE_WO, 3, 1, pdi_pre_fields },
+ { PDI_SR, 2, 22, REGISTER_TYPE_RO, 0, 10, pdi_sr_fields },
+ { PDI_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, pdi_srr_fields },
+};
+
+static nt_fpga_field_init_t ptp1588_conf_fields[] = {
+ { PTP1588_CONF_MII_RX_TX_LOOP, 1, 0, 0 },
+ { PTP1588_CONF_MII_TX_RX_LOOP, 1, 1, 0 },
+ { PTP1588_CONF_PHY_RST1, 1, 10, 1 },
+ { PTP1588_CONF_PHY_RST2, 1, 11, 1 },
+ { PTP1588_CONF_PTP_CTRL_LOCAL, 1, 24, 0 },
+ { PTP1588_CONF_PTP_RX_CTRL, 2, 19, 0 },
+ { PTP1588_CONF_PTP_TX_CTRL, 2, 21, 0 },
+ { PTP1588_CONF_PTP_TX_CTRL_OS, 1, 23, 0 },
+ { PTP1588_CONF_RX_IGNORE_DEST_ADDR, 1, 25, 0 },
+ { PTP1588_CONF_TG_CMD, 2, 13, 0 },
+ { PTP1588_CONF_TG_MODE, 1, 12, 0 },
+ { PTP1588_CONF_TSM_MI_ACK, 1, 16, 0 },
+ { PTP1588_CONF_TSM_MI_BUSY, 1, 15, 0 },
+ { PTP1588_CONF_TSM_MI_ENA, 1, 18, 0 },
+ { PTP1588_CONF_TSM_MI_REQ, 1, 17, 0 },
+ { PTP1588_CONF_TX_IFG, 8, 2, 0 },
+ { PTP1588_CONF_TX_IGNORE_DEST_ADDR, 1, 26, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_data_fields[] = {
+ { PTP1588_GP_DATA_GPIO, 9, 1, 0 },
+ { PTP1588_GP_DATA_PWRDOWN_INTN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_data_lh_fields[] = {
+ { PTP1588_GP_DATA_LH_GPIO, 9, 1, 0 },
+ { PTP1588_GP_DATA_LH_PWRDOWN_INTN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_data_ll_fields[] = {
+ { PTP1588_GP_DATA_LL_GPIO, 9, 1, 511 },
+ { PTP1588_GP_DATA_LL_PWRDOWN_INTN, 1, 0, 1 },
+};
+
+static nt_fpga_field_init_t ptp1588_gp_oe_fields[] = {
+ { PTP1588_GP_OE_GPIO, 9, 1, 0 },
+ { PTP1588_GP_OE_PWRDOWN_INTN, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_mac_inband_stat_fields[] = {
+ { PTP1588_MAC_INBAND_STAT_DUPLEX, 1, 3, 0x0000 },
+ { PTP1588_MAC_INBAND_STAT_LINK, 1, 0, 0x0000 },
+ { PTP1588_MAC_INBAND_STAT_SPEED, 2, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_mac_mi_conf_fields[] = {
+ { PTP1588_MAC_MI_CONF_ACCESS_TYPE, 1, 16, 0 },
+ { PTP1588_MAC_MI_CONF_ADDRESS, 16, 0, 0 },
+ { PTP1588_MAC_MI_CONF_RDY, 1, 17, 1 },
+};
+
+static nt_fpga_field_init_t ptp1588_mac_mi_data_fields[] = {
+ { PTP1588_MAC_MI_DATA_DATA, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_rx_host_adr_lsb_fields[] = {
+ { PTP1588_RX_HOST_ADR_LSB_LSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_rx_host_adr_msb_fields[] = {
+ { PTP1588_RX_HOST_ADR_MSB_MSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_rx_host_conf_fields[] = {
+ { PTP1588_RX_HOST_CONF_ENA, 1, 11, 0 },
+ { PTP1588_RX_HOST_CONF_RDPTR, 11, 0, 0 },
+ { PTP1588_RX_HOST_CONF_REDUCED, 1, 12, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_stat_fields[] = {
+ { PTP1588_STAT_DATA, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_stat_conf_fields[] = {
+ { PTP1588_STAT_CONF_INDEX, 5, 0, 0 },
+ { PTP1588_STAT_CONF_LOCK, 1, 5, 0 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_first_dat_fields[] = {
+ { PTP1588_TX_FIRST_DAT_DAT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last1_dat_fields[] = {
+ { PTP1588_TX_LAST1_DAT_DAT, 8, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last2_dat_fields[] = {
+ { PTP1588_TX_LAST2_DAT_DAT, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last3_dat_fields[] = {
+ { PTP1588_TX_LAST3_DAT_DAT, 24, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_last4_dat_fields[] = {
+ { PTP1588_TX_LAST4_DAT_DAT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_mid_dat_fields[] = {
+ { PTP1588_TX_MID_DAT_DAT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_packet_state_fields[] = {
+ { PTP1588_TX_PACKET_STATE_MSG_TYPE, 4, 16, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_PCK_TYPE, 3, 20, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_SEQ_ID, 16, 0, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_TEST_MARGIN, 7, 23, 0x0000 },
+ { PTP1588_TX_PACKET_STATE_VALID, 1, 30, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_status_fields[] = {
+ { PTP1588_TX_STATUS_DB_ERR, 1, 10, 1 },
+ { PTP1588_TX_STATUS_DB_FULL, 1, 9, 1 },
+ { PTP1588_TX_STATUS_FIFO_STATUS, 9, 0, 0 },
+ { PTP1588_TX_STATUS_RDY, 1, 11, 1 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_timestamp_ns_fields[] = {
+ { PTP1588_TX_TIMESTAMP_NS_TIMESTAMP, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t ptp1588_tx_timestamp_sec_fields[] = {
+ { PTP1588_TX_TIMESTAMP_SEC_TIMESTAMP, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t ptp1588_registers[] = {
+ { PTP1588_CONF, 0, 27, REGISTER_TYPE_MIXED, 3072, 17,
+ ptp1588_conf_fields
+ },
+ { PTP1588_GP_DATA, 20, 10, REGISTER_TYPE_RW, 0, 2,
+ ptp1588_gp_data_fields
+ },
+ { PTP1588_GP_DATA_LH, 22, 10, REGISTER_TYPE_RO, 0, 2,
+ ptp1588_gp_data_lh_fields
+ },
+ { PTP1588_GP_DATA_LL, 21, 10, REGISTER_TYPE_RO, 1023, 2,
+ ptp1588_gp_data_ll_fields
+ },
+ { PTP1588_GP_OE, 19, 10, REGISTER_TYPE_WO, 0, 2, ptp1588_gp_oe_fields },
+ { PTP1588_MAC_INBAND_STAT, 3, 4, REGISTER_TYPE_RO, 0, 3,
+ ptp1588_mac_inband_stat_fields
+ },
+ { PTP1588_MAC_MI_CONF, 17, 18, REGISTER_TYPE_MIXED, 131072, 3,
+ ptp1588_mac_mi_conf_fields
+ },
+ { PTP1588_MAC_MI_DATA, 18, 32, REGISTER_TYPE_RW, 0, 1,
+ ptp1588_mac_mi_data_fields
+ },
+ { PTP1588_RX_HOST_ADR_LSB, 8, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_rx_host_adr_lsb_fields
+ },
+ { PTP1588_RX_HOST_ADR_MSB, 9, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_rx_host_adr_msb_fields
+ },
+ { PTP1588_RX_HOST_CONF, 7, 13, REGISTER_TYPE_RW, 0, 3,
+ ptp1588_rx_host_conf_fields
+ },
+ { PTP1588_STAT, 6, 32, REGISTER_TYPE_RO, 0, 1, ptp1588_stat_fields },
+ { PTP1588_STAT_CONF, 5, 6, REGISTER_TYPE_WO, 0, 2,
+ ptp1588_stat_conf_fields
+ },
+ { PTP1588_TX_FIRST_DAT, 10, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_first_dat_fields
+ },
+ { PTP1588_TX_LAST1_DAT, 12, 8, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last1_dat_fields
+ },
+ { PTP1588_TX_LAST2_DAT, 13, 16, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last2_dat_fields
+ },
+ { PTP1588_TX_LAST3_DAT, 14, 24, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last3_dat_fields
+ },
+ { PTP1588_TX_LAST4_DAT, 15, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_last4_dat_fields
+ },
+ { PTP1588_TX_MID_DAT, 11, 32, REGISTER_TYPE_WO, 0, 1,
+ ptp1588_tx_mid_dat_fields
+ },
+ { PTP1588_TX_PACKET_STATE, 4, 31, REGISTER_TYPE_RO, 0, 5,
+ ptp1588_tx_packet_state_fields
+ },
+ { PTP1588_TX_STATUS, 16, 12, REGISTER_TYPE_RO, 3584, 4,
+ ptp1588_tx_status_fields
+ },
+ { PTP1588_TX_TIMESTAMP_NS, 2, 32, REGISTER_TYPE_RO, 0, 1,
+ ptp1588_tx_timestamp_ns_fields
+ },
+ { PTP1588_TX_TIMESTAMP_SEC, 1, 32, REGISTER_TYPE_RO, 0, 1,
+ ptp1588_tx_timestamp_sec_fields
+ },
+};
+
+static nt_fpga_field_init_t qsl_qen_ctrl_fields[] = {
+ { QSL_QEN_CTRL_ADR, 5, 0, 0x0000 },
+ { QSL_QEN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_qen_data_fields[] = {
+ { QSL_QEN_DATA_EN, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_qst_ctrl_fields[] = {
+ { QSL_QST_CTRL_ADR, 12, 0, 0x0000 },
+ { QSL_QST_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_qst_data_fields[] = {
+ { QSL_QST_DATA_LRE, 1, 9, 0x0000 },
+ { QSL_QST_DATA_QEN, 1, 7, 0x0000 },
+ { QSL_QST_DATA_QUEUE, 7, 0, 0x0000 },
+ { QSL_QST_DATA_TCI, 16, 10, 0x0000 },
+ { QSL_QST_DATA_TX_PORT, 1, 8, 0x0000 },
+ { QSL_QST_DATA_VEN, 1, 26, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_rcp_ctrl_fields[] = {
+ { QSL_RCP_CTRL_ADR, 5, 0, 0x0000 },
+ { QSL_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_rcp_data_fields[] = {
+ { QSL_RCP_DATA_DISCARD, 1, 0, 0x0000 },
+ { QSL_RCP_DATA_DROP, 2, 1, 0x0000 },
+ { QSL_RCP_DATA_LR, 2, 51, 0x0000 },
+ { QSL_RCP_DATA_TBL_HI, 12, 15, 0x0000 },
+ { QSL_RCP_DATA_TBL_IDX, 12, 27, 0x0000 },
+ { QSL_RCP_DATA_TBL_LO, 12, 3, 0x0000 },
+ { QSL_RCP_DATA_TBL_MSK, 12, 39, 0x0000 },
+ { QSL_RCP_DATA_TSA, 1, 53, 0x0000 },
+ { QSL_RCP_DATA_VLI, 2, 54, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_unmq_ctrl_fields[] = {
+ { QSL_UNMQ_CTRL_ADR, 1, 0, 0x0000 },
+ { QSL_UNMQ_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t qsl_unmq_data_fields[] = {
+ { QSL_UNMQ_DATA_DEST_QUEUE, 7, 0, 0x0000 },
+ { QSL_UNMQ_DATA_EN, 1, 7, 0x0000 },
+};
+
+static nt_fpga_register_init_t qsl_registers[] = {
+ { QSL_QEN_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, qsl_qen_ctrl_fields },
+ { QSL_QEN_DATA, 5, 4, REGISTER_TYPE_WO, 0, 1, qsl_qen_data_fields },
+ { QSL_QST_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, qsl_qst_ctrl_fields },
+ { QSL_QST_DATA, 3, 27, REGISTER_TYPE_WO, 0, 6, qsl_qst_data_fields },
+ { QSL_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, qsl_rcp_ctrl_fields },
+ { QSL_RCP_DATA, 1, 56, REGISTER_TYPE_WO, 0, 9, qsl_rcp_data_fields },
+ { QSL_UNMQ_CTRL, 6, 32, REGISTER_TYPE_WO, 0, 2, qsl_unmq_ctrl_fields },
+ { QSL_UNMQ_DATA, 7, 8, REGISTER_TYPE_WO, 0, 2, qsl_unmq_data_fields },
+};
+
+static nt_fpga_field_init_t qspi_cr_fields[] = {
+ { QSPI_CR_CPHA, 1, 4, 0 }, { QSPI_CR_CPOL, 1, 3, 0 },
+ { QSPI_CR_LOOP, 1, 0, 0 }, { QSPI_CR_LSBF, 1, 9, 0 },
+ { QSPI_CR_MSSAE, 1, 7, 1 }, { QSPI_CR_MST, 1, 2, 0 },
+ { QSPI_CR_MTI, 1, 8, 1 }, { QSPI_CR_RXFIFO_RST, 1, 6, 0 },
+ { QSPI_CR_SPE, 1, 1, 0 }, { QSPI_CR_TXFIFO_RST, 1, 5, 0 },
+};
+
+static nt_fpga_field_init_t qspi_dgie_fields[] = {
+ { QSPI_DGIE_GIE, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t qspi_drr_fields[] = {
+ { QSPI_DRR_DATA_VAL, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t qspi_dtr_fields[] = {
+ { QSPI_DTR_DATA_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t qspi_ier_fields[] = {
+ { QSPI_IER_CMD_ERR, 1, 13, 0 }, { QSPI_IER_CPOL_CPHA_ERR, 1, 9, 0 },
+ { QSPI_IER_DRR_FULL, 1, 4, 0 }, { QSPI_IER_DRR_NEMPTY, 1, 8, 0 },
+ { QSPI_IER_DRR_OR, 1, 5, 0 }, { QSPI_IER_DTR_EMPTY, 1, 2, 0 },
+ { QSPI_IER_DTR_UR, 1, 3, 0 }, { QSPI_IER_LOOP_ERR, 1, 12, 0 },
+ { QSPI_IER_MODF, 1, 0, 0 }, { QSPI_IER_MSB_ERR, 1, 11, 0 },
+ { QSPI_IER_SLV_ERR, 1, 10, 0 }, { QSPI_IER_SLV_MODF, 1, 1, 0 },
+ { QSPI_IER_SLV_MS, 1, 7, 0 }, { QSPI_IER_TXFIFO_HEMPTY, 1, 6, 0 },
+};
+
+static nt_fpga_field_init_t qspi_isr_fields[] = {
+ { QSPI_ISR_CMD_ERR, 1, 13, 0 }, { QSPI_ISR_CPOL_CPHA_ERR, 1, 9, 0 },
+ { QSPI_ISR_DRR_FULL, 1, 4, 0 }, { QSPI_ISR_DRR_NEMPTY, 1, 8, 0 },
+ { QSPI_ISR_DRR_OR, 1, 5, 0 }, { QSPI_ISR_DTR_EMPTY, 1, 2, 0 },
+ { QSPI_ISR_DTR_UR, 1, 3, 0 }, { QSPI_ISR_LOOP_ERR, 1, 12, 0 },
+ { QSPI_ISR_MODF, 1, 0, 0 }, { QSPI_ISR_MSB_ERR, 1, 11, 0 },
+ { QSPI_ISR_SLV_ERR, 1, 10, 0 }, { QSPI_ISR_SLV_MODF, 1, 1, 0 },
+ { QSPI_ISR_SLV_MS, 1, 7, 0 }, { QSPI_ISR_TXFIFO_HEMPTY, 1, 6, 0 },
+};
+
+static nt_fpga_field_init_t qspi_rx_fifo_ocy_fields[] = {
+ { QSPI_RX_FIFO_OCY_OCY_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t qspi_sr_fields[] = {
+ { QSPI_SR_CMD_ERR, 1, 10, 0 }, { QSPI_SR_CPOL_CPHA_ERR, 1, 6, 0 },
+ { QSPI_SR_LOOP_ERR, 1, 9, 0 }, { QSPI_SR_MODF, 1, 4, 0 },
+ { QSPI_SR_MSB_ERR, 1, 8, 0 }, { QSPI_SR_RXEMPTY, 1, 0, 1 },
+ { QSPI_SR_RXFULL, 1, 1, 0 }, { QSPI_SR_SLVMS, 1, 5, 1 },
+ { QSPI_SR_SLV_ERR, 1, 7, 0 }, { QSPI_SR_TXEMPTY, 1, 2, 1 },
+ { QSPI_SR_TXFULL, 1, 3, 0 },
+};
+
+static nt_fpga_field_init_t qspi_srr_fields[] = {
+ { QSPI_SRR_RST, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t qspi_ssr_fields[] = {
+ { QSPI_SSR_SEL_SLV, 32, 0, 4294967295 },
+};
+
+static nt_fpga_field_init_t qspi_tx_fifo_ocy_fields[] = {
+ { QSPI_TX_FIFO_OCY_OCY_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_register_init_t qspi_registers[] = {
+ { QSPI_CR, 24, 10, REGISTER_TYPE_RW, 384, 10, qspi_cr_fields },
+ { QSPI_DGIE, 7, 32, REGISTER_TYPE_RW, 0, 1, qspi_dgie_fields },
+ { QSPI_DRR, 27, 32, REGISTER_TYPE_RO, 0, 1, qspi_drr_fields },
+ { QSPI_DTR, 26, 32, REGISTER_TYPE_WO, 0, 1, qspi_dtr_fields },
+ { QSPI_IER, 10, 14, REGISTER_TYPE_RW, 0, 14, qspi_ier_fields },
+ { QSPI_ISR, 8, 14, REGISTER_TYPE_RW, 0, 14, qspi_isr_fields },
+ { QSPI_RX_FIFO_OCY, 30, 32, REGISTER_TYPE_RO, 0, 1,
+ qspi_rx_fifo_ocy_fields
+ },
+ { QSPI_SR, 25, 11, REGISTER_TYPE_RO, 37, 11, qspi_sr_fields },
+ { QSPI_SRR, 16, 4, REGISTER_TYPE_WO, 0, 1, qspi_srr_fields },
+ { QSPI_SSR, 28, 32, REGISTER_TYPE_RW, 4294967295, 1, qspi_ssr_fields },
+ { QSPI_TX_FIFO_OCY, 29, 32, REGISTER_TYPE_RO, 0, 1,
+ qspi_tx_fifo_ocy_fields
+ },
+};
+
+static nt_fpga_field_init_t rac_dbg_ctrl_fields[] = {
+ { RAC_DBG_CTRL_C, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rac_dbg_data_fields[] = {
+ { RAC_DBG_DATA_D, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rac_rab_buf_free_fields[] = {
+ { RAC_RAB_BUF_FREE_IB_FREE, 9, 0, 511 },
+ { RAC_RAB_BUF_FREE_IB_OVF, 1, 12, 0 },
+ { RAC_RAB_BUF_FREE_OB_FREE, 9, 16, 511 },
+ { RAC_RAB_BUF_FREE_OB_OVF, 1, 28, 0 },
+ { RAC_RAB_BUF_FREE_TIMEOUT, 1, 31, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_buf_used_fields[] = {
+ { RAC_RAB_BUF_USED_FLUSH, 1, 31, 0 },
+ { RAC_RAB_BUF_USED_IB_USED, 9, 0, 0 },
+ { RAC_RAB_BUF_USED_OB_USED, 9, 16, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_hi_fields[] = {
+ { RAC_RAB_DMA_IB_HI_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_lo_fields[] = {
+ { RAC_RAB_DMA_IB_LO_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_rd_fields[] = {
+ { RAC_RAB_DMA_IB_RD_PTR, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ib_wr_fields[] = {
+ { RAC_RAB_DMA_IB_WR_PTR, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ob_hi_fields[] = {
+ { RAC_RAB_DMA_OB_HI_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ob_lo_fields[] = {
+ { RAC_RAB_DMA_OB_LO_PHYADDR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_dma_ob_wr_fields[] = {
+ { RAC_RAB_DMA_OB_WR_PTR, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t rac_rab_ib_data_fields[] = {
+ { RAC_RAB_IB_DATA_D, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rac_rab_init_fields[] = {
+ { RAC_RAB_INIT_RAB, 3, 0, 7 },
+};
+
+static nt_fpga_field_init_t rac_rab_ob_data_fields[] = {
+ { RAC_RAB_OB_DATA_D, 32, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t rac_registers[] = {
+ { RAC_DBG_CTRL, 4200, 32, REGISTER_TYPE_RW, 0, 1, rac_dbg_ctrl_fields },
+ { RAC_DBG_DATA, 4208, 32, REGISTER_TYPE_RW, 0, 1, rac_dbg_data_fields },
+ { RAC_RAB_BUF_FREE, 4176, 32, REGISTER_TYPE_MIXED, 33489407, 5,
+ rac_rab_buf_free_fields
+ },
+ { RAC_RAB_BUF_USED, 4184, 32, REGISTER_TYPE_MIXED, 0, 3,
+ rac_rab_buf_used_fields
+ },
+ { RAC_RAB_DMA_IB_HI, 4360, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ib_hi_fields
+ },
+ { RAC_RAB_DMA_IB_LO, 4352, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ib_lo_fields
+ },
+ { RAC_RAB_DMA_IB_RD, 4424, 16, REGISTER_TYPE_RO, 0, 1,
+ rac_rab_dma_ib_rd_fields
+ },
+ { RAC_RAB_DMA_IB_WR, 4416, 16, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ib_wr_fields
+ },
+ { RAC_RAB_DMA_OB_HI, 4376, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ob_hi_fields
+ },
+ { RAC_RAB_DMA_OB_LO, 4368, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_dma_ob_lo_fields
+ },
+ { RAC_RAB_DMA_OB_WR, 4480, 16, REGISTER_TYPE_RO, 0, 1,
+ rac_rab_dma_ob_wr_fields
+ },
+ { RAC_RAB_IB_DATA, 4160, 32, REGISTER_TYPE_WO, 0, 1,
+ rac_rab_ib_data_fields
+ },
+ { RAC_RAB_INIT, 4192, 3, REGISTER_TYPE_RW, 7, 1, rac_rab_init_fields },
+ { RAC_RAB_OB_DATA, 4168, 32, REGISTER_TYPE_RC1, 0, 1,
+ rac_rab_ob_data_fields
+ },
+};
+
+static nt_fpga_field_init_t rfd_ctrl_fields[] = {
+ { RFD_CTRL_CFP, 1, 2, 1 },
+ { RFD_CTRL_ISL, 1, 0, 1 },
+ { RFD_CTRL_PWMCW, 1, 1, 1 },
+};
+
+static nt_fpga_field_init_t rfd_max_frame_size_fields[] = {
+ { RFD_MAX_FRAME_SIZE_MAX, 14, 0, 9018 },
+};
+
+static nt_fpga_field_init_t rfd_tnl_vlan_fields[] = {
+ { RFD_TNL_VLAN_TPID0, 16, 0, 33024 },
+ { RFD_TNL_VLAN_TPID1, 16, 16, 33024 },
+};
+
+static nt_fpga_field_init_t rfd_vlan_fields[] = {
+ { RFD_VLAN_TPID0, 16, 0, 33024 },
+ { RFD_VLAN_TPID1, 16, 16, 33024 },
+};
+
+static nt_fpga_field_init_t rfd_vxlan_fields[] = {
+ { RFD_VXLAN_DP0, 16, 0, 4789 },
+ { RFD_VXLAN_DP1, 16, 16, 4789 },
+};
+
+static nt_fpga_register_init_t rfd_registers[] = {
+ { RFD_CTRL, 0, 3, REGISTER_TYPE_WO, 7, 3, rfd_ctrl_fields },
+ { RFD_MAX_FRAME_SIZE, 1, 14, REGISTER_TYPE_WO, 9018, 1,
+ rfd_max_frame_size_fields
+ },
+ { RFD_TNL_VLAN, 3, 32, REGISTER_TYPE_WO, 2164293888, 2,
+ rfd_tnl_vlan_fields
+ },
+ { RFD_VLAN, 2, 32, REGISTER_TYPE_WO, 2164293888, 2, rfd_vlan_fields },
+ { RFD_VXLAN, 4, 32, REGISTER_TYPE_WO, 313856693, 2, rfd_vxlan_fields },
+};
+
+static nt_fpga_field_init_t rmc_ctrl_fields[] = {
+ { RMC_CTRL_BLOCK_KEEPA, 1, 1, 1 },
+ { RMC_CTRL_BLOCK_MAC_PORT, 2, 8, 3 },
+ { RMC_CTRL_BLOCK_RPP_SLICE, 8, 10, 0 },
+ { RMC_CTRL_BLOCK_STATT, 1, 0, 1 },
+ { RMC_CTRL_LAG_PHY_ODD_EVEN, 1, 24, 0 },
+};
+
+static nt_fpga_field_init_t rmc_dbg_fields[] = {
+ { RMC_DBG_MERGE, 31, 0, 0 },
+};
+
+static nt_fpga_field_init_t rmc_mac_if_fields[] = {
+ { RMC_MAC_IF_ERR, 31, 0, 0 },
+};
+
+static nt_fpga_field_init_t rmc_status_fields[] = {
+ { RMC_STATUS_DESCR_FIFO_OF, 1, 16, 0 },
+ { RMC_STATUS_SF_RAM_OF, 1, 0, 0 },
+};
+
+static nt_fpga_register_init_t rmc_registers[] = {
+ { RMC_CTRL, 0, 25, REGISTER_TYPE_RW, 771, 5, rmc_ctrl_fields },
+ { RMC_DBG, 2, 31, REGISTER_TYPE_RO, 0, 1, rmc_dbg_fields },
+ { RMC_MAC_IF, 3, 31, REGISTER_TYPE_RO, 0, 1, rmc_mac_if_fields },
+ { RMC_STATUS, 1, 17, REGISTER_TYPE_RO, 0, 2, rmc_status_fields },
+};
+
+static nt_fpga_field_init_t rpl_ext_ctrl_fields[] = {
+ { RPL_EXT_CTRL_ADR, 10, 0, 0x0000 },
+ { RPL_EXT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_ext_data_fields[] = {
+ { RPL_EXT_DATA_RPL_PTR, 12, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rcp_ctrl_fields[] = {
+ { RPL_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { RPL_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rcp_data_fields[] = {
+ { RPL_RCP_DATA_DYN, 5, 0, 0x0000 },
+ { RPL_RCP_DATA_EXT_PRIO, 1, 35, 0x0000 },
+ { RPL_RCP_DATA_LEN, 8, 15, 0x0000 },
+ { RPL_RCP_DATA_OFS, 10, 5, 0x0000 },
+ { RPL_RCP_DATA_RPL_PTR, 12, 23, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rpl_ctrl_fields[] = {
+ { RPL_RPL_CTRL_ADR, 12, 0, 0x0000 },
+ { RPL_RPL_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpl_rpl_data_fields[] = {
+ { RPL_RPL_DATA_VALUE, 128, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t rpl_registers[] = {
+ { RPL_EXT_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2, rpl_ext_ctrl_fields },
+ { RPL_EXT_DATA, 3, 12, REGISTER_TYPE_WO, 0, 1, rpl_ext_data_fields },
+ { RPL_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, rpl_rcp_ctrl_fields },
+ { RPL_RCP_DATA, 1, 36, REGISTER_TYPE_WO, 0, 5, rpl_rcp_data_fields },
+ { RPL_RPL_CTRL, 4, 32, REGISTER_TYPE_WO, 0, 2, rpl_rpl_ctrl_fields },
+ { RPL_RPL_DATA, 5, 128, REGISTER_TYPE_WO, 0, 1, rpl_rpl_data_fields },
+};
+
+static nt_fpga_field_init_t rpp_lr_ifr_rcp_ctrl_fields[] = {
+ { RPP_LR_IFR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { RPP_LR_IFR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpp_lr_ifr_rcp_data_fields[] = {
+ { RPP_LR_IFR_RCP_DATA_EN, 1, 0, 0x0000 },
+ { RPP_LR_IFR_RCP_DATA_MTU, 14, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpp_lr_rcp_ctrl_fields[] = {
+ { RPP_LR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+ { RPP_LR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t rpp_lr_rcp_data_fields[] = {
+ { RPP_LR_RCP_DATA_EXP, 14, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t rpp_lr_registers[] = {
+ { RPP_LR_IFR_RCP_CTRL, 2, 32, REGISTER_TYPE_WO, 0, 2,
+ rpp_lr_ifr_rcp_ctrl_fields
+ },
+ { RPP_LR_IFR_RCP_DATA, 3, 15, REGISTER_TYPE_WO, 0, 2,
+ rpp_lr_ifr_rcp_data_fields
+ },
+ { RPP_LR_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2,
+ rpp_lr_rcp_ctrl_fields
+ },
+ { RPP_LR_RCP_DATA, 1, 14, REGISTER_TYPE_WO, 0, 1,
+ rpp_lr_rcp_data_fields
+ },
+};
+
+static nt_fpga_field_init_t rst9563_ctrl_fields[] = {
+ { RST9563_CTRL_PTP_MMCM_CLKSEL, 1, 2, 1 },
+ { RST9563_CTRL_TS_CLKSEL, 1, 1, 1 },
+ { RST9563_CTRL_TS_CLKSEL_OVERRIDE, 1, 0, 1 },
+};
+
+static nt_fpga_field_init_t rst9563_power_fields[] = {
+ { RST9563_POWER_PU_NSEB, 1, 1, 0 },
+ { RST9563_POWER_PU_PHY, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t rst9563_rst_fields[] = {
+ { RST9563_RST_CORE_MMCM, 1, 15, 0 }, { RST9563_RST_DDR4, 3, 3, 7 },
+ { RST9563_RST_MAC_RX, 2, 9, 3 }, { RST9563_RST_PERIPH, 1, 13, 0 },
+ { RST9563_RST_PHY, 2, 7, 3 }, { RST9563_RST_PTP, 1, 11, 1 },
+ { RST9563_RST_PTP_MMCM, 1, 16, 0 }, { RST9563_RST_RPP, 1, 2, 1 },
+ { RST9563_RST_SDC, 1, 6, 1 }, { RST9563_RST_SYS, 1, 0, 1 },
+ { RST9563_RST_SYS_MMCM, 1, 14, 0 }, { RST9563_RST_TMC, 1, 1, 1 },
+ { RST9563_RST_TS, 1, 12, 1 }, { RST9563_RST_TS_MMCM, 1, 17, 0 },
+};
+
+static nt_fpga_field_init_t rst9563_stat_fields[] = {
+ { RST9563_STAT_CORE_MMCM_LOCKED, 1, 5, 0x0000 },
+ { RST9563_STAT_DDR4_MMCM_LOCKED, 1, 2, 0x0000 },
+ { RST9563_STAT_DDR4_PLL_LOCKED, 1, 3, 0x0000 },
+ { RST9563_STAT_PTP_MMCM_LOCKED, 1, 0, 0x0000 },
+ { RST9563_STAT_SYS_MMCM_LOCKED, 1, 4, 0x0000 },
+ { RST9563_STAT_TS_MMCM_LOCKED, 1, 1, 0x0000 },
+};
+
+static nt_fpga_field_init_t rst9563_sticky_fields[] = {
+ { RST9563_STICKY_CORE_MMCM_UNLOCKED, 1, 5, 0x0000 },
+ { RST9563_STICKY_DDR4_MMCM_UNLOCKED, 1, 2, 0x0000 },
+ { RST9563_STICKY_DDR4_PLL_UNLOCKED, 1, 3, 0x0000 },
+ { RST9563_STICKY_PTP_MMCM_UNLOCKED, 1, 0, 0x0000 },
+ { RST9563_STICKY_SYS_MMCM_UNLOCKED, 1, 4, 0x0000 },
+ { RST9563_STICKY_TS_MMCM_UNLOCKED, 1, 1, 0x0000 },
+};
+
+static nt_fpga_register_init_t rst9563_registers[] = {
+ { RST9563_CTRL, 1, 3, REGISTER_TYPE_RW, 7, 3, rst9563_ctrl_fields },
+ { RST9563_POWER, 4, 2, REGISTER_TYPE_RW, 0, 2, rst9563_power_fields },
+ { RST9563_RST, 0, 18, REGISTER_TYPE_RW, 8191, 14, rst9563_rst_fields },
+ { RST9563_STAT, 2, 6, REGISTER_TYPE_RO, 0, 6, rst9563_stat_fields },
+ { RST9563_STICKY, 3, 6, REGISTER_TYPE_RC1, 0, 6,
+ rst9563_sticky_fields
+ },
+};
+
+static nt_fpga_field_init_t slc_rcp_ctrl_fields[] = {
+ { SLC_RCP_CTRL_ADR, 6, 0, 0x0000 },
+ { SLC_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nt_fpga_field_init_t slc_rcp_data_fields[] = {
+ { SLC_RCP_DATA_PCAP, 1, 35, 0x0000 },
+ { SLC_RCP_DATA_TAIL_DYN, 5, 15, 0x0000 },
+ { SLC_RCP_DATA_TAIL_OFS, 15, 20, 0x0000 },
+ { SLC_RCP_DATA_TAIL_SLC_EN, 1, 14, 0x0000 },
+};
+
+static nt_fpga_register_init_t slc_registers[] = {
+ { SLC_RCP_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 2, slc_rcp_ctrl_fields },
+ { SLC_RCP_DATA, 1, 36, REGISTER_TYPE_WO, 0, 4, slc_rcp_data_fields },
+};
+
+static nt_fpga_field_init_t spim_cfg_fields[] = {
+ { SPIM_CFG_PRE, 3, 0, 5 },
+};
+
+static nt_fpga_field_init_t spim_cr_fields[] = {
+ { SPIM_CR_EN, 1, 1, 0 },
+ { SPIM_CR_LOOP, 1, 0, 0 },
+ { SPIM_CR_RXRST, 1, 3, 0 },
+ { SPIM_CR_TXRST, 1, 2, 0 },
+};
+
+static nt_fpga_field_init_t spim_drr_fields[] = {
+ { SPIM_DRR_DRR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spim_dtr_fields[] = {
+ { SPIM_DTR_DTR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spim_sr_fields[] = {
+ { SPIM_SR_DONE, 1, 0, 0 }, { SPIM_SR_RXEMPTY, 1, 2, 1 },
+ { SPIM_SR_RXFULL, 1, 4, 0 }, { SPIM_SR_RXLVL, 8, 16, 0 },
+ { SPIM_SR_TXEMPTY, 1, 1, 1 }, { SPIM_SR_TXFULL, 1, 3, 0 },
+ { SPIM_SR_TXLVL, 8, 8, 0 },
+};
+
+static nt_fpga_field_init_t spim_srr_fields[] = {
+ { SPIM_SRR_RST, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t spim_registers[] = {
+ { SPIM_CFG, 5, 3, REGISTER_TYPE_WO, 5, 1, spim_cfg_fields },
+ { SPIM_CR, 1, 4, REGISTER_TYPE_WO, 0, 4, spim_cr_fields },
+ { SPIM_DRR, 4, 32, REGISTER_TYPE_RO, 0, 1, spim_drr_fields },
+ { SPIM_DTR, 3, 32, REGISTER_TYPE_WO, 0, 1, spim_dtr_fields },
+ { SPIM_SR, 2, 24, REGISTER_TYPE_RO, 6, 7, spim_sr_fields },
+ { SPIM_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, spim_srr_fields },
+};
+
+static nt_fpga_field_init_t spis_cr_fields[] = {
+ { SPIS_CR_DEBUG, 1, 4, 0 }, { SPIS_CR_EN, 1, 1, 0 },
+ { SPIS_CR_LOOP, 1, 0, 0 }, { SPIS_CR_RXRST, 1, 3, 0 },
+ { SPIS_CR_TXRST, 1, 2, 0 },
+};
+
+static nt_fpga_field_init_t spis_drr_fields[] = {
+ { SPIS_DRR_DRR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spis_dtr_fields[] = {
+ { SPIS_DTR_DTR, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spis_ram_ctrl_fields[] = {
+ { SPIS_RAM_CTRL_ADR, 6, 0, 0 },
+ { SPIS_RAM_CTRL_CNT, 6, 6, 0 },
+};
+
+static nt_fpga_field_init_t spis_ram_data_fields[] = {
+ { SPIS_RAM_DATA_DATA, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t spis_sr_fields[] = {
+ { SPIS_SR_DONE, 1, 0, 0 }, { SPIS_SR_FRAME_ERR, 1, 24, 0 },
+ { SPIS_SR_READ_ERR, 1, 25, 0 }, { SPIS_SR_RXEMPTY, 1, 2, 1 },
+ { SPIS_SR_RXFULL, 1, 4, 0 }, { SPIS_SR_RXLVL, 8, 16, 0 },
+ { SPIS_SR_TXEMPTY, 1, 1, 1 }, { SPIS_SR_TXFULL, 1, 3, 0 },
+ { SPIS_SR_TXLVL, 8, 8, 0 }, { SPIS_SR_WRITE_ERR, 1, 26, 0 },
+};
+
+static nt_fpga_field_init_t spis_srr_fields[] = {
+ { SPIS_SRR_RST, 4, 0, 0 },
+};
+
+static nt_fpga_register_init_t spis_registers[] = {
+ { SPIS_CR, 1, 5, REGISTER_TYPE_WO, 0, 5, spis_cr_fields },
+ { SPIS_DRR, 4, 32, REGISTER_TYPE_RO, 0, 1, spis_drr_fields },
+ { SPIS_DTR, 3, 32, REGISTER_TYPE_WO, 0, 1, spis_dtr_fields },
+ { SPIS_RAM_CTRL, 5, 12, REGISTER_TYPE_RW, 0, 2, spis_ram_ctrl_fields },
+ { SPIS_RAM_DATA, 6, 32, REGISTER_TYPE_RW, 0, 1, spis_ram_data_fields },
+ { SPIS_SR, 2, 27, REGISTER_TYPE_RO, 6, 10, spis_sr_fields },
+ { SPIS_SRR, 0, 4, REGISTER_TYPE_WO, 0, 1, spis_srr_fields },
+};
+
+static nt_fpga_field_init_t sta_byte_fields[] = {
+ { STA_BYTE_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_cfg_fields[] = {
+ { STA_CFG_CNT_CLEAR, 1, 1, 0 },
+ { STA_CFG_DMA_ENA, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t sta_cv_err_fields[] = {
+ { STA_CV_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_fcs_err_fields[] = {
+ { STA_FCS_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_host_adr_lsb_fields[] = {
+ { STA_HOST_ADR_LSB_LSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t sta_host_adr_msb_fields[] = {
+ { STA_HOST_ADR_MSB_MSB, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t sta_pckt_fields[] = {
+ { STA_PCKT_CNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t sta_status_fields[] = {
+ { STA_STATUS_STAT_TOGGLE_MISSED, 1, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t sta_registers[] = {
+ { STA_BYTE, 4, 32, REGISTER_TYPE_RO, 0, 1, sta_byte_fields },
+ { STA_CFG, 0, 2, REGISTER_TYPE_RW, 0, 2, sta_cfg_fields },
+ { STA_CV_ERR, 5, 32, REGISTER_TYPE_RO, 0, 1, sta_cv_err_fields },
+ { STA_FCS_ERR, 6, 32, REGISTER_TYPE_RO, 0, 1, sta_fcs_err_fields },
+ { STA_HOST_ADR_LSB, 1, 32, REGISTER_TYPE_WO, 0, 1,
+ sta_host_adr_lsb_fields
+ },
+ { STA_HOST_ADR_MSB, 2, 32, REGISTER_TYPE_WO, 0, 1,
+ sta_host_adr_msb_fields
+ },
+ { STA_PCKT, 3, 32, REGISTER_TYPE_RO, 0, 1, sta_pckt_fields },
+ { STA_STATUS, 7, 1, REGISTER_TYPE_RC1, 0, 1, sta_status_fields },
+};
+
+static nt_fpga_field_init_t tempmon_alarms_fields[] = {
+ { TEMPMON_ALARMS_OT, 1, 1, 0x0000 },
+ { TEMPMON_ALARMS_OT_OVERWR, 1, 2, 0 },
+ { TEMPMON_ALARMS_OT_OVERWRVAL, 1, 3, 0 },
+ { TEMPMON_ALARMS_TEMP, 1, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tempmon_stat_fields[] = {
+ { TEMPMON_STAT_TEMP, 12, 0, 0x0000 },
+};
+
+static nt_fpga_register_init_t tempmon_registers[] = {
+ { TEMPMON_ALARMS, 1, 4, REGISTER_TYPE_MIXED, 0, 4,
+ tempmon_alarms_fields
+ },
+ { TEMPMON_STAT, 0, 12, REGISTER_TYPE_RO, 0, 1, tempmon_stat_fields },
+};
+
+static nt_fpga_field_init_t tint_ctrl_fields[] = {
+ { TINT_CTRL_INTERVAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tint_status_fields[] = {
+ { TINT_STATUS_DELAYED, 8, 8, 0 },
+ { TINT_STATUS_SKIPPED, 8, 0, 0 },
+};
+
+static nt_fpga_register_init_t tint_registers[] = {
+ { TINT_CTRL, 0, 32, REGISTER_TYPE_WO, 0, 1, tint_ctrl_fields },
+ { TINT_STATUS, 1, 16, REGISTER_TYPE_RC1, 0, 2, tint_status_fields },
+};
+
+static nt_fpga_field_init_t tmc_port_rpl_fields[] = {
+ { TMC_PORT_RPL_P0, 1, 0, 0 },
+ { TMC_PORT_RPL_P1, 1, 1, 1 },
+};
+
+static nt_fpga_register_init_t tmc_registers[] = {
+ { TMC_PORT_RPL, 0, 2, REGISTER_TYPE_WO, 2, 2, tmc_port_rpl_fields },
+};
+
+static nt_fpga_field_init_t tsm_con0_config_fields[] = {
+ { TSM_CON0_CONFIG_BLIND, 5, 8, 9 },
+ { TSM_CON0_CONFIG_DC_SRC, 3, 5, 0 },
+ { TSM_CON0_CONFIG_PORT, 3, 0, 0 },
+ { TSM_CON0_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+ { TSM_CON0_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nt_fpga_field_init_t tsm_con0_interface_fields[] = {
+ { TSM_CON0_INTERFACE_EX_TERM, 2, 0, 3 },
+ { TSM_CON0_INTERFACE_IN_REF_PWM, 8, 12, 128 },
+ { TSM_CON0_INTERFACE_PWM_ENA, 1, 2, 0 },
+ { TSM_CON0_INTERFACE_RESERVED, 1, 3, 0 },
+ { TSM_CON0_INTERFACE_VTERM_PWM, 8, 4, 0 },
+};
+
+static nt_fpga_field_init_t tsm_con0_sample_hi_fields[] = {
+ { TSM_CON0_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con0_sample_lo_fields[] = {
+ { TSM_CON0_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con1_config_fields[] = {
+ { TSM_CON1_CONFIG_BLIND, 5, 8, 9 },
+ { TSM_CON1_CONFIG_DC_SRC, 3, 5, 0 },
+ { TSM_CON1_CONFIG_PORT, 3, 0, 0 },
+ { TSM_CON1_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+ { TSM_CON1_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nt_fpga_field_init_t tsm_con1_sample_hi_fields[] = {
+ { TSM_CON1_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con1_sample_lo_fields[] = {
+ { TSM_CON1_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con2_config_fields[] = {
+ { TSM_CON2_CONFIG_BLIND, 5, 8, 9 },
+ { TSM_CON2_CONFIG_DC_SRC, 3, 5, 0 },
+ { TSM_CON2_CONFIG_PORT, 3, 0, 0 },
+ { TSM_CON2_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+ { TSM_CON2_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nt_fpga_field_init_t tsm_con2_sample_hi_fields[] = {
+ { TSM_CON2_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con2_sample_lo_fields[] = {
+ { TSM_CON2_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con3_config_fields[] = {
+ { TSM_CON3_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON3_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON3_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con3_sample_hi_fields[] = {
+ { TSM_CON3_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con3_sample_lo_fields[] = {
+ { TSM_CON3_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con4_config_fields[] = {
+ { TSM_CON4_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON4_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON4_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con4_sample_hi_fields[] = {
+ { TSM_CON4_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con4_sample_lo_fields[] = {
+ { TSM_CON4_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con5_config_fields[] = {
+ { TSM_CON5_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON5_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON5_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con5_sample_hi_fields[] = {
+ { TSM_CON5_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con5_sample_lo_fields[] = {
+ { TSM_CON5_SAMPLE_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con6_config_fields[] = {
+ { TSM_CON6_CONFIG_BLIND, 5, 5, 26 },
+ { TSM_CON6_CONFIG_PORT, 3, 0, 1 },
+ { TSM_CON6_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nt_fpga_field_init_t tsm_con6_sample_hi_fields[] = {
+ { TSM_CON6_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con6_sample_lo_fields[] = {
+ { TSM_CON6_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con7_host_sample_hi_fields[] = {
+ { TSM_CON7_HOST_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_con7_host_sample_lo_fields[] = {
+ { TSM_CON7_HOST_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_config_fields[] = {
+ { TSM_CONFIG_NTTS_SRC, 2, 5, 0 },
+ { TSM_CONFIG_NTTS_SYNC, 1, 4, 0 },
+ { TSM_CONFIG_TIMESET_EDGE, 2, 8, 1 },
+ { TSM_CONFIG_TIMESET_SRC, 3, 10, 0 },
+ { TSM_CONFIG_TIMESET_UP, 1, 7, 0 },
+ { TSM_CONFIG_TS_FORMAT, 4, 0, 1 },
+};
+
+static nt_fpga_field_init_t tsm_int_config_fields[] = {
+ { TSM_INT_CONFIG_AUTO_DISABLE, 1, 0, 0 },
+ { TSM_INT_CONFIG_MASK, 19, 1, 0 },
+};
+
+static nt_fpga_field_init_t tsm_int_stat_fields[] = {
+ { TSM_INT_STAT_CAUSE, 19, 1, 0 },
+ { TSM_INT_STAT_ENABLE, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_led_fields[] = {
+ { TSM_LED_LED0_BG_COLOR, 2, 3, 0 }, { TSM_LED_LED0_COLOR, 2, 1, 0 },
+ { TSM_LED_LED0_MODE, 1, 0, 0 }, { TSM_LED_LED0_SRC, 4, 5, 0 },
+ { TSM_LED_LED1_BG_COLOR, 2, 12, 0 }, { TSM_LED_LED1_COLOR, 2, 10, 0 },
+ { TSM_LED_LED1_MODE, 1, 9, 0 }, { TSM_LED_LED1_SRC, 4, 14, 1 },
+ { TSM_LED_LED2_BG_COLOR, 2, 21, 0 }, { TSM_LED_LED2_COLOR, 2, 19, 0 },
+ { TSM_LED_LED2_MODE, 1, 18, 0 }, { TSM_LED_LED2_SRC, 4, 23, 2 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_config_fields[] = {
+ { TSM_NTTS_CONFIG_AUTO_HARDSET, 1, 5, 1 },
+ { TSM_NTTS_CONFIG_EXT_CLK_ADJ, 1, 6, 0 },
+ { TSM_NTTS_CONFIG_HIGH_SAMPLE, 1, 4, 0 },
+ { TSM_NTTS_CONFIG_TS_SRC_FORMAT, 4, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ext_stat_fields[] = {
+ { TSM_NTTS_EXT_STAT_MASTER_ID, 8, 16, 0x0000 },
+ { TSM_NTTS_EXT_STAT_MASTER_REV, 8, 24, 0x0000 },
+ { TSM_NTTS_EXT_STAT_MASTER_STAT, 16, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_limit_hi_fields[] = {
+ { TSM_NTTS_LIMIT_HI_SEC, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_limit_lo_fields[] = {
+ { TSM_NTTS_LIMIT_LO_NS, 32, 0, 100000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_offset_fields[] = {
+ { TSM_NTTS_OFFSET_NS, 30, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_sample_hi_fields[] = {
+ { TSM_NTTS_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_sample_lo_fields[] = {
+ { TSM_NTTS_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_stat_fields[] = {
+ { TSM_NTTS_STAT_NTTS_VALID, 1, 0, 0 },
+ { TSM_NTTS_STAT_SIGNAL_LOST, 8, 1, 0 },
+ { TSM_NTTS_STAT_SYNC_LOST, 8, 9, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ts_t0_hi_fields[] = {
+ { TSM_NTTS_TS_T0_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ts_t0_lo_fields[] = {
+ { TSM_NTTS_TS_T0_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ntts_ts_t0_offset_fields[] = {
+ { TSM_NTTS_TS_T0_OFFSET_COUNT, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_pb_ctrl_fields[] = {
+ { TSM_PB_CTRL_INSTMEM_WR, 1, 1, 0 },
+ { TSM_PB_CTRL_RST, 1, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_pb_instmem_fields[] = {
+ { TSM_PB_INSTMEM_MEM_ADDR, 14, 0, 0 },
+ { TSM_PB_INSTMEM_MEM_DATA, 18, 14, 0 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_i_fields[] = {
+ { TSM_PI_CTRL_I_VAL, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_ki_fields[] = {
+ { TSM_PI_CTRL_KI_GAIN, 24, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_kp_fields[] = {
+ { TSM_PI_CTRL_KP_GAIN, 24, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_pi_ctrl_shl_fields[] = {
+ { TSM_PI_CTRL_SHL_VAL, 4, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_stat_fields[] = {
+ { TSM_STAT_HARD_SYNC, 8, 8, 0 }, { TSM_STAT_LINK_CON0, 1, 0, 0 },
+ { TSM_STAT_LINK_CON1, 1, 1, 0 }, { TSM_STAT_LINK_CON2, 1, 2, 0 },
+ { TSM_STAT_LINK_CON3, 1, 3, 0 }, { TSM_STAT_LINK_CON4, 1, 4, 0 },
+ { TSM_STAT_LINK_CON5, 1, 5, 0 }, { TSM_STAT_NTTS_INSYNC, 1, 6, 0 },
+ { TSM_STAT_PTP_MI_PRESENT, 1, 7, 0 },
+};
+
+static nt_fpga_field_init_t tsm_timer_ctrl_fields[] = {
+ { TSM_TIMER_CTRL_TIMER_EN_T0, 1, 0, 0 },
+ { TSM_TIMER_CTRL_TIMER_EN_T1, 1, 1, 0 },
+};
+
+static nt_fpga_field_init_t tsm_timer_t0_fields[] = {
+ { TSM_TIMER_T0_MAX_COUNT, 30, 0, 50000 },
+};
+
+static nt_fpga_field_init_t tsm_timer_t1_fields[] = {
+ { TSM_TIMER_T1_MAX_COUNT, 30, 0, 50000 },
+};
+
+static nt_fpga_field_init_t tsm_time_hardset_hi_fields[] = {
+ { TSM_TIME_HARDSET_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_hardset_lo_fields[] = {
+ { TSM_TIME_HARDSET_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_hi_fields[] = {
+ { TSM_TIME_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_lo_fields[] = {
+ { TSM_TIME_LO_NS, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_time_rate_adj_fields[] = {
+ { TSM_TIME_RATE_ADJ_FRACTION, 29, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_hi_fields[] = {
+ { TSM_TS_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ts_lo_fields[] = {
+ { TSM_TS_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nt_fpga_field_init_t tsm_ts_offset_fields[] = {
+ { TSM_TS_OFFSET_NS, 30, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_fields[] = {
+ { TSM_TS_STAT_OVERRUN, 1, 16, 0 },
+ { TSM_TS_STAT_SAMPLES, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_hi_offset_fields[] = {
+ { TSM_TS_STAT_HI_OFFSET_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_lo_offset_fields[] = {
+ { TSM_TS_STAT_LO_OFFSET_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_tar_hi_fields[] = {
+ { TSM_TS_STAT_TAR_HI_SEC, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_tar_lo_fields[] = {
+ { TSM_TS_STAT_TAR_LO_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_x_fields[] = {
+ { TSM_TS_STAT_X_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_x2_hi_fields[] = {
+ { TSM_TS_STAT_X2_HI_NS, 16, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_ts_stat_x2_lo_fields[] = {
+ { TSM_TS_STAT_X2_LO_NS, 32, 0, 0 },
+};
+
+static nt_fpga_field_init_t tsm_utc_offset_fields[] = {
+ { TSM_UTC_OFFSET_SEC, 8, 0, 0 },
+};
+
+static nt_fpga_register_init_t tsm_registers[] = {
+ { TSM_CON0_CONFIG, 24, 14, REGISTER_TYPE_RW, 2320, 5,
+ tsm_con0_config_fields
+ },
+ { TSM_CON0_INTERFACE, 25, 20, REGISTER_TYPE_RW, 524291, 5,
+ tsm_con0_interface_fields
+ },
+ { TSM_CON0_SAMPLE_HI, 27, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con0_sample_hi_fields
+ },
+ { TSM_CON0_SAMPLE_LO, 26, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con0_sample_lo_fields
+ },
+ { TSM_CON1_CONFIG, 28, 14, REGISTER_TYPE_RW, 2320, 5,
+ tsm_con1_config_fields
+ },
+ { TSM_CON1_SAMPLE_HI, 30, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con1_sample_hi_fields
+ },
+ { TSM_CON1_SAMPLE_LO, 29, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con1_sample_lo_fields
+ },
+ { TSM_CON2_CONFIG, 31, 14, REGISTER_TYPE_RW, 2320, 5,
+ tsm_con2_config_fields
+ },
+ { TSM_CON2_SAMPLE_HI, 33, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con2_sample_hi_fields
+ },
+ { TSM_CON2_SAMPLE_LO, 32, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con2_sample_lo_fields
+ },
+ { TSM_CON3_CONFIG, 34, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con3_config_fields
+ },
+ { TSM_CON3_SAMPLE_HI, 36, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con3_sample_hi_fields
+ },
+ { TSM_CON3_SAMPLE_LO, 35, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con3_sample_lo_fields
+ },
+ { TSM_CON4_CONFIG, 37, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con4_config_fields
+ },
+ { TSM_CON4_SAMPLE_HI, 39, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con4_sample_hi_fields
+ },
+ { TSM_CON4_SAMPLE_LO, 38, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con4_sample_lo_fields
+ },
+ { TSM_CON5_CONFIG, 40, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con5_config_fields
+ },
+ { TSM_CON5_SAMPLE_HI, 42, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con5_sample_hi_fields
+ },
+ { TSM_CON5_SAMPLE_LO, 41, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con5_sample_lo_fields
+ },
+ { TSM_CON6_CONFIG, 43, 10, REGISTER_TYPE_RW, 841, 3,
+ tsm_con6_config_fields
+ },
+ { TSM_CON6_SAMPLE_HI, 45, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con6_sample_hi_fields
+ },
+ { TSM_CON6_SAMPLE_LO, 44, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con6_sample_lo_fields
+ },
+ { TSM_CON7_HOST_SAMPLE_HI, 47, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con7_host_sample_hi_fields
+ },
+ { TSM_CON7_HOST_SAMPLE_LO, 46, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_con7_host_sample_lo_fields
+ },
+ { TSM_CONFIG, 0, 13, REGISTER_TYPE_RW, 257, 6, tsm_config_fields },
+ { TSM_INT_CONFIG, 2, 20, REGISTER_TYPE_RW, 0, 2,
+ tsm_int_config_fields
+ },
+ { TSM_INT_STAT, 3, 20, REGISTER_TYPE_MIXED, 0, 2, tsm_int_stat_fields },
+ { TSM_LED, 4, 27, REGISTER_TYPE_RW, 16793600, 12, tsm_led_fields },
+ { TSM_NTTS_CONFIG, 13, 7, REGISTER_TYPE_RW, 32, 4,
+ tsm_ntts_config_fields
+ },
+ { TSM_NTTS_EXT_STAT, 15, 32, REGISTER_TYPE_MIXED, 0, 3,
+ tsm_ntts_ext_stat_fields
+ },
+ { TSM_NTTS_LIMIT_HI, 23, 16, REGISTER_TYPE_RW, 0, 1,
+ tsm_ntts_limit_hi_fields
+ },
+ { TSM_NTTS_LIMIT_LO, 22, 32, REGISTER_TYPE_RW, 100000, 1,
+ tsm_ntts_limit_lo_fields
+ },
+ { TSM_NTTS_OFFSET, 21, 30, REGISTER_TYPE_RW, 0, 1,
+ tsm_ntts_offset_fields
+ },
+ { TSM_NTTS_SAMPLE_HI, 19, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_sample_hi_fields
+ },
+ { TSM_NTTS_SAMPLE_LO, 18, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_sample_lo_fields
+ },
+ { TSM_NTTS_STAT, 14, 17, REGISTER_TYPE_RO, 0, 3, tsm_ntts_stat_fields },
+ { TSM_NTTS_TS_T0_HI, 17, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_ts_t0_hi_fields
+ },
+ { TSM_NTTS_TS_T0_LO, 16, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_ts_t0_lo_fields
+ },
+ { TSM_NTTS_TS_T0_OFFSET, 20, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ntts_ts_t0_offset_fields
+ },
+ { TSM_PB_CTRL, 63, 2, REGISTER_TYPE_WO, 0, 2, tsm_pb_ctrl_fields },
+ { TSM_PB_INSTMEM, 64, 32, REGISTER_TYPE_WO, 0, 2,
+ tsm_pb_instmem_fields
+ },
+ { TSM_PI_CTRL_I, 54, 32, REGISTER_TYPE_WO, 0, 1, tsm_pi_ctrl_i_fields },
+ { TSM_PI_CTRL_KI, 52, 24, REGISTER_TYPE_RW, 0, 1,
+ tsm_pi_ctrl_ki_fields
+ },
+ { TSM_PI_CTRL_KP, 51, 24, REGISTER_TYPE_RW, 0, 1,
+ tsm_pi_ctrl_kp_fields
+ },
+ { TSM_PI_CTRL_SHL, 53, 4, REGISTER_TYPE_WO, 0, 1,
+ tsm_pi_ctrl_shl_fields
+ },
+ { TSM_STAT, 1, 16, REGISTER_TYPE_RO, 0, 9, tsm_stat_fields },
+ { TSM_TIMER_CTRL, 48, 2, REGISTER_TYPE_RW, 0, 2,
+ tsm_timer_ctrl_fields
+ },
+ { TSM_TIMER_T0, 49, 30, REGISTER_TYPE_RW, 50000, 1,
+ tsm_timer_t0_fields
+ },
+ { TSM_TIMER_T1, 50, 30, REGISTER_TYPE_RW, 50000, 1,
+ tsm_timer_t1_fields
+ },
+ { TSM_TIME_HARDSET_HI, 12, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_time_hardset_hi_fields
+ },
+ { TSM_TIME_HARDSET_LO, 11, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_time_hardset_lo_fields
+ },
+ { TSM_TIME_HI, 9, 32, REGISTER_TYPE_RW, 0, 1, tsm_time_hi_fields },
+ { TSM_TIME_LO, 8, 32, REGISTER_TYPE_RW, 0, 1, tsm_time_lo_fields },
+ { TSM_TIME_RATE_ADJ, 10, 29, REGISTER_TYPE_RW, 0, 1,
+ tsm_time_rate_adj_fields
+ },
+ { TSM_TS_HI, 6, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_hi_fields },
+ { TSM_TS_LO, 5, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_lo_fields },
+ { TSM_TS_OFFSET, 7, 30, REGISTER_TYPE_RW, 0, 1, tsm_ts_offset_fields },
+ { TSM_TS_STAT, 55, 17, REGISTER_TYPE_RO, 0, 2, tsm_ts_stat_fields },
+ { TSM_TS_STAT_HI_OFFSET, 62, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_hi_offset_fields
+ },
+ { TSM_TS_STAT_LO_OFFSET, 61, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_lo_offset_fields
+ },
+ { TSM_TS_STAT_TAR_HI, 57, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_tar_hi_fields
+ },
+ { TSM_TS_STAT_TAR_LO, 56, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_tar_lo_fields
+ },
+ { TSM_TS_STAT_X, 58, 32, REGISTER_TYPE_RO, 0, 1, tsm_ts_stat_x_fields },
+ { TSM_TS_STAT_X2_HI, 60, 16, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_x2_hi_fields
+ },
+ { TSM_TS_STAT_X2_LO, 59, 32, REGISTER_TYPE_RO, 0, 1,
+ tsm_ts_stat_x2_lo_fields
+ },
+ { TSM_UTC_OFFSET, 65, 8, REGISTER_TYPE_RW, 0, 1,
+ tsm_utc_offset_fields
+ },
+};
+
+static nt_fpga_module_init_t fpga_modules[] = {
+ { MOD_CAT, 0, MOD_CAT, 0, 21, BUS_TYPE_RAB1, 768, 34,
+ cat_registers
+ }, /* CAT:0 CAT v0.21: CAT @ RAB1,768 (CAT CAT CAT) */
+ { MOD_CSU, 0, MOD_CSU, 0, 0, BUS_TYPE_RAB1, 9728, 2,
+ csu_registers
+ }, /* CSU:0 CSU v0.0: CSU @ RAB1,9728 (CSU CSU CSU) */
+ { MOD_DBS, 0, MOD_DBS, 0, 11, BUS_TYPE_RAB2, 12832, 27,
+ dbs_registers
+ }, /* DBS:0 DBS v0.11: DBS @ RAB2,12832 (DBS DBS DBS) */
+ { MOD_FLM, 0, MOD_FLM, 0, 20, BUS_TYPE_RAB1, 1280, 43,
+ flm_registers
+ }, /* FLM:0 FLM v0.20: FLM @ RAB1,1280 (FLM FLM FLM) */
+ { MOD_GFG, 0, MOD_GFG, 1, 1, BUS_TYPE_RAB2, 8704, 10,
+ gfg_registers
+ }, /* GFG:0 GFG v1.1: GFG @ RAB2,8704 (GFG GFG GFG) */
+ { MOD_GMF, 0, MOD_GMF, 2, 5, BUS_TYPE_RAB2, 9216, 12,
+ gmf_registers
+ }, /* GMF:0 GMF v2.5: GMF_0 @ RAB2,9216 (GMF GMF_0 GMF) */
+ { MOD_GMF, 1, MOD_GMF, 2, 5, BUS_TYPE_RAB2, 9728, 12,
+ gmf_registers
+ }, /* GMF:1 GMF v2.5: GMF_1 @ RAB2,9728 (GMF GMF_1 GMF) */
+ { MOD_GPIO_PHY, 0, MOD_GPIO_PHY, 1, 0, BUS_TYPE_RAB0, 16386, 2,
+ gpio_phy_registers
+ }, /* GPIO_PHY:0 GPIO_PHY v1.0: GPIO_PHY @ RAB0,16386 (GPIO_PHY GPIO_PHY GPIO_PHY) */
+ { MOD_HFU, 0, MOD_HFU, 0, 1, BUS_TYPE_RAB1, 9472, 2,
+ hfu_registers
+ }, /* HFU:0 HFU v0.1: HFU @ RAB1,9472 (HFU HFU HFU) */
+ { MOD_HIF, 0, MOD_HIF, 0, 0, BUS_TYPE_PCI, 0, 18,
+ hif_registers
+ }, /* HIF:0 HIF v0.0: HIF @ PCI,0 (HIF HIF HIF) */
+ { MOD_HSH, 0, MOD_HSH, 0, 5, BUS_TYPE_RAB1, 1536, 2,
+ hsh_registers
+ }, /* HSH:0 HSH v0.5: HSH @ RAB1,1536 (HSH HSH HSH) */
+ { MOD_HST, 0, MOD_HST, 0, 2, BUS_TYPE_RAB1, 2048, 2,
+ hst_registers
+ }, /* HST:0 HST v0.2: HST @ RAB1,2048 (HST HST HST) */
+ { MOD_IFR, 0, MOD_IFR, 0, 1, BUS_TYPE_RAB1, 9984, 2,
+ ifr_registers
+ }, /* IFR:0 IFR v0.1: IFR @ RAB1,9984 (IFR IFR IFR) */
+ { MOD_IIC, 0, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 768, 22,
+ iic_registers
+ }, /* IIC:0 IIC v0.1: IIC0 @ RAB0,768 (IIC IIC0 IIC) */
+ { MOD_IIC, 1, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 896, 22,
+ iic_registers
+ }, /* IIC:1 IIC v0.1: IIC1 @ RAB0,896 (IIC IIC1 IIC) */
+ { MOD_IIC, 2, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 24832, 22,
+ iic_registers
+ }, /* IIC:2 IIC v0.1: IIC2 @ RAB0,24832 (IIC IIC2 IIC) */
+ { MOD_IIC, 3, MOD_IIC, 0, 1, BUS_TYPE_RAB0, 24960, 22,
+ iic_registers
+ }, /* IIC:3 IIC v0.1: IIC3 @ RAB0,24960 (IIC IIC3 IIC) */
+ { MOD_KM, 0, MOD_KM, 0, 7, BUS_TYPE_RAB1, 1024, 11,
+ km_registers
+ }, /* KM:0 KM v0.7: KM @ RAB1,1024 (KM KM KM) */
+ { MOD_MAC_PCS, 0, MOD_MAC_PCS, 0, 2, BUS_TYPE_RAB2, 10240, 44,
+ mac_pcs_registers
+ }, /* MAC_PCS:0 MAC_PCS v0.2: MAC_PCS_0 @ RAB2,10240 (MAC_PCS MAC_PCS_0 MAC_PCS) */
+ { MOD_MAC_PCS, 1, MOD_MAC_PCS, 0, 2, BUS_TYPE_RAB2, 11776, 44,
+ mac_pcs_registers
+ }, /* MAC_PCS:1 MAC_PCS v0.2: MAC_PCS_1 @ RAB2,11776 (MAC_PCS MAC_PCS_1 MAC_PCS) */
+ { MOD_MAC_RX, 0, MOD_MAC_RX, 0, 0, BUS_TYPE_RAB2, 10752, 9,
+ mac_rx_registers
+ }, /* MAC_RX:0 MAC_RX v0.0: MAC_RX_0 @ RAB2,10752 (MAC_RX MAC_RX_0 MAC_RX) */
+ { MOD_MAC_RX, 1, MOD_MAC_RX, 0, 0, BUS_TYPE_RAB2, 12288, 9,
+ mac_rx_registers
+ }, /* MAC_RX:1 MAC_RX v0.0: MAC_RX_1 @ RAB2,12288 (MAC_RX MAC_RX_1 MAC_RX) */
+ { MOD_MAC_TX, 0, MOD_MAC_TX, 0, 0, BUS_TYPE_RAB2, 11264, 5,
+ mac_tx_registers
+ }, /* MAC_TX:0 MAC_TX v0.0: MAC_TX_0 @ RAB2,11264 (MAC_TX MAC_TX_0 MAC_TX) */
+ { MOD_MAC_TX, 1, MOD_MAC_TX, 0, 0, BUS_TYPE_RAB2, 12800, 5,
+ mac_tx_registers
+ }, /* MAC_TX:1 MAC_TX v0.0: MAC_TX_1 @ RAB2,12800 (MAC_TX MAC_TX_1 MAC_TX) */
+ { MOD_PCI_RD_TG, 0, MOD_PCI_RD_TG, 0, 1, BUS_TYPE_RAB0, 2320, 6,
+ pci_rd_tg_registers
+ }, /* PCI_RD_TG:0 PCI_RD_TG v0.1: PCI_RD_TG @ RAB0,2320 (PCI_RD_TG PCI_RD_TG PCI_RD_TG) */
+ { MOD_PCI_TA, 0, MOD_PCI_TA, 0, 0, BUS_TYPE_RAB0, 2336, 5,
+ pci_ta_registers
+ }, /* PCI_TA:0 PCI_TA v0.0: PCI_TA @ RAB0,2336 (PCI_TA PCI_TA PCI_TA) */
+ { MOD_PCI_WR_TG, 0, MOD_PCI_WR_TG, 0, 1, BUS_TYPE_RAB0, 2304, 7,
+ pci_wr_tg_registers
+ }, /* PCI_WR_TG:0 PCI_WR_TG v0.1: PCI_WR_TG @ RAB0,2304 (PCI_WR_TG PCI_WR_TG PCI_WR_TG) */
+ { MOD_PDB, 0, MOD_PDB, 0, 9, BUS_TYPE_RAB1, 2816, 3,
+ pdb_registers
+ }, /* PDB:0 PDB v0.9: PDB @ RAB1,2816 (PDB PDB PDB) */
+ { MOD_PDI, 0, MOD_PDI, 1, 1, BUS_TYPE_RAB0, 64, 6,
+ pdi_registers
+ }, /* PDI:0 PDI v1.1: PDI @ RAB0,64 (PDI PDI PDI) */
+ { MOD_PTP1588, 0, MOD_PTP1588, 2, 1, BUS_TYPE_RAB2, 512, 23,
+ ptp1588_registers
+ }, /* PTP1588:0 PTP1588 v2.1: PTP1588 @ RAB2,512 (PTP1588 PTP1588 PTP1588) */
+ { MOD_QSL, 0, MOD_QSL, 0, 7, BUS_TYPE_RAB1, 1792, 8,
+ qsl_registers
+ }, /* QSL:0 QSL v0.7: QSL @ RAB1,1792 (QSL QSL QSL) */
+ { MOD_QSPI, 0, MOD_QSPI, 0, 0, BUS_TYPE_RAB0, 512, 11,
+ qspi_registers
+ }, /* QSPI:0 QSPI v0.0: QSPI @ RAB0,512 (QSPI QSPI QSPI) */
+ { MOD_RAC, 0, MOD_RAC, 3, 0, BUS_TYPE_PCI, 8192, 14,
+ rac_registers
+ }, /* RAC:0 RAC v3.0: RAC @ PCI,8192 (RAC RAC RAC) */
+ { MOD_RFD, 0, MOD_RFD, 0, 4, BUS_TYPE_RAB1, 256, 5,
+ rfd_registers
+ }, /* RFD:0 RFD v0.4: RFD @ RAB1,256 (RFD RFD RFD) */
+ { MOD_RMC, 0, MOD_RMC, 1, 3, BUS_TYPE_RAB0, 12288, 4,
+ rmc_registers
+ }, /* RMC:0 RMC v1.3: RMC @ RAB0,12288 (RMC RMC RMC) */
+ { MOD_RPP_LR, 0, MOD_RPP_LR, 0, 1, BUS_TYPE_RAB1, 2560, 4,
+ rpp_lr_registers
+ }, /* RPP_LR:0 RPP_LR v0.1: RPP_LR @ RAB1,2560 (RPP_LR RPP_LR RPP_LR) */
+ { MOD_RST9563, 0, MOD_RST9563, 0, 5, BUS_TYPE_RAB0, 1024, 5,
+ rst9563_registers
+ }, /* RST9563:0 RST9563 v0.5: RST9563 @ RAB0,1024 (RST9563 RST9563 RST9563) */
+ { MOD_SLC_LR, 0, MOD_SLC, 0, 2, BUS_TYPE_RAB1, 2304, 2,
+ slc_registers
+ }, /* SLC_LR:0 SLC v0.2: SLC_LR @ RAB1,2304 (SLC SLC_LR SLC_LR) */
+ { MOD_SPIM, 0, MOD_SPIM, 1, 0, BUS_TYPE_RAB0, 80, 6,
+ spim_registers
+ }, /* SPIM:0 SPIM v1.0: SPIM @ RAB0,80 (SPIM SPIM SPIM) */
+ { MOD_SPIS, 0, MOD_SPIS, 1, 0, BUS_TYPE_RAB0, 256, 7,
+ spis_registers
+ }, /* SPIS:0 SPIS v1.0: SPIS @ RAB0,256 (SPIS SPIS SPIS) */
+ { MOD_STA, 0, MOD_STA, 0, 8, BUS_TYPE_RAB0, 2048, 8,
+ sta_registers
+ }, /* STA:0 STA v0.8: STA @ RAB0,2048 (STA STA STA) */
+ { MOD_TEMPMON, 0, MOD_TEMPMON, 0, 0, BUS_TYPE_RAB0, 16384, 2,
+ tempmon_registers
+ }, /* TEMPMON:0 TEMPMON v0.0: TEMPMON @ RAB0,16384 (TEMPMON TEMPMON TEMPMON) */
+ { MOD_TINT, 0, MOD_TINT, 0, 0, BUS_TYPE_RAB0, 1280, 2,
+ tint_registers
+ }, /* TINT:0 TINT v0.0: TINT @ RAB0,1280 (TINT TINT TINT) */
+ { MOD_TMC, 0, MOD_TMC, 0, 1, BUS_TYPE_RAB2, 8192, 1,
+ tmc_registers
+ }, /* TMC:0 TMC v0.1: TMC @ RAB2,8192 (TMC TMC TMC) */
+ { MOD_TSM, 0, MOD_TSM, 0, 8, BUS_TYPE_RAB2, 1024, 66,
+ tsm_registers
+ }, /* TSM:0 TSM v0.8: TSM @ RAB2,1024 (TSM TSM TSM) */
+ { MOD_TX_CPY, 0, MOD_CPY, 0, 1, BUS_TYPE_RAB1, 9216, 20,
+ cpy_registers
+ }, /* TX_CPY:0 CPY v0.1: TX_CPY @ RAB1,9216 (CPY TX_CPY TX_CPY) */
+ { MOD_TX_INS, 0, MOD_INS, 0, 1, BUS_TYPE_RAB1, 8704, 2,
+ ins_registers
+ }, /* TX_INS:0 INS v0.1: TX_INS @ RAB1,8704 (INS TX_INS TX_INS) */
+ { MOD_TX_RPL, 0, MOD_RPL, 0, 2, BUS_TYPE_RAB1, 8960, 6,
+ rpl_registers
+ }, /* TX_RPL:0 RPL v0.2: TX_RPL @ RAB1,8960 (RPL TX_RPL TX_RPL) */
+};
+
+static nt_fpga_prod_param_t product_parameters[] = {
+ { NT_BUILD_NUMBER, 0 },
+ { NT_BUILD_TIME, 1689706895 },
+ { NT_CATEGORIES, 64 },
+ { NT_CAT_DCT_PRESENT, 0 },
+ { NT_CAT_END_OFS_SUPPORT, 0 },
+ { NT_CAT_FUNCS, 64 },
+ { NT_CAT_KCC_BANKS, 3 },
+ { NT_CAT_KCC_PRESENT, 0 },
+ { NT_CAT_KCC_SIZE, 1536 },
+ { NT_CAT_KM_IF_CNT, 2 },
+ { NT_CAT_KM_IF_M0, 0 },
+ { NT_CAT_KM_IF_M1, 1 },
+ { NT_CAT_N_CMP, 8 },
+ { NT_CAT_N_EXT, 4 },
+ { NT_CAT_N_LEN, 8 },
+ { NT_CB_DEBUG, 0 },
+ { NT_COR_CATEGORIES, 16 },
+ { NT_COR_PRESENT, 0 },
+ { NT_CSU_PRESENT, 1 },
+ { NT_DBS_PRESENT, 1 },
+ { NT_DBS_RX_QUEUES, 128 },
+ { NT_DBS_TX_PORTS, 2 },
+ { NT_DBS_TX_QUEUES, 128 },
+ { NT_DDP_PRESENT, 0 },
+ { NT_DDP_TBL_DEPTH, 4096 },
+ { NT_EMI_SPLIT_STEPS, 16 },
+ { NT_EOF_TIMESTAMP_ONLY, 1 },
+ { NT_EPP_CATEGORIES, 32 },
+ { NT_FLM_CACHE, 1 },
+ { NT_FLM_CATEGORIES, 32 },
+ { NT_FLM_ENTRY_SIZE, 64 },
+ { NT_FLM_PRESENT, 1 },
+ { NT_FLM_PRIOS, 4 },
+ { NT_FLM_PST_PROFILES, 16 },
+ { NT_FLM_SIZE_MB, 12288 },
+ { NT_FLM_STATEFUL, 1 },
+ { NT_FLM_VARIANT, 2 },
+ { NT_GFG_PRESENT, 1 },
+ { NT_GFG_TX_LIVE_RECONFIG_SUPPORT, 1 },
+ { NT_GMF_FCS_PRESENT, 0 },
+ { NT_GMF_IFG_SPEED_DIV, 33 },
+ { NT_GMF_IFG_SPEED_DIV100G, 33 },
+ { NT_GMF_IFG_SPEED_MUL, 20 },
+ { NT_GMF_IFG_SPEED_MUL100G, 20 },
+ { NT_GROUP_ID, 9563 },
+ { NT_HFU_PRESENT, 1 },
+ { NT_HIF_MSIX_BAR, 1 },
+ { NT_HIF_MSIX_PBA_OFS, 8192 },
+ { NT_HIF_MSIX_PRESENT, 1 },
+ { NT_HIF_MSIX_TBL_OFS, 0 },
+ { NT_HIF_MSIX_TBL_SIZE, 8 },
+ { NT_HIF_PER_PS, 4000 },
+ { NT_HIF_SRIOV_PRESENT, 1 },
+ { NT_HSH_CATEGORIES, 16 },
+ { NT_HSH_TOEPLITZ, 1 },
+ { NT_HST_CATEGORIES, 32 },
+ { NT_HST_PRESENT, 1 },
+ { NT_IOA_CATEGORIES, 1024 },
+ { NT_IOA_PRESENT, 0 },
+ { NT_IPF_PRESENT, 0 },
+ { NT_KM_CAM_BANKS, 3 },
+ { NT_KM_CAM_RECORDS, 2048 },
+ { NT_KM_CAM_REC_WORDS, 6 },
+ { NT_KM_CATEGORIES, 32 },
+ { NT_KM_END_OFS_SUPPORT, 0 },
+ { NT_KM_EXT_EXTRACTORS, 0 },
+ { NT_KM_FLOW_TYPES, 16 },
+ { NT_KM_PRESENT, 1 },
+ { NT_KM_SWX_PRESENT, 0 },
+ { NT_KM_SYNERGY_MATCH, 0 },
+ { NT_KM_TCAM_BANKS, 12 },
+ { NT_KM_TCAM_BANK_WIDTH, 72 },
+ { NT_KM_TCAM_HIT_QUAL, 0 },
+ { NT_KM_TCAM_KEYWAY, 1 },
+ { NT_KM_WIDE, 1 },
+ { NT_LR_PRESENT, 1 },
+ { NT_MCU_PRESENT, 0 },
+ { NT_MDG_DEBUG_FLOW_CONTROL, 0 },
+ { NT_MDG_DEBUG_REG_READ_BACK, 0 },
+ { NT_MSK_CATEGORIES, 32 },
+ { NT_MSK_PRESENT, 0 },
+ { NT_NFV_OVS_PRODUCT, 0 },
+ { NT_NIMS, 2 },
+ { NT_PCI_DEVICE_ID, 453 },
+ { NT_PCI_TA_TG_PRESENT, 1 },
+ { NT_PCI_VENDOR_ID, 6388 },
+ { NT_PDB_CATEGORIES, 16 },
+ { NT_PHY_ANEG_PRESENT, 0 },
+ { NT_PHY_KRFEC_PRESENT, 0 },
+ { NT_PHY_PORTS, 2 },
+ { NT_PHY_PORTS_PER_QUAD, 1 },
+ { NT_PHY_QUADS, 2 },
+ { NT_PHY_RSFEC_PRESENT, 1 },
+ { NT_QM_CELLS, 2097152 },
+ { NT_QM_CELL_SIZE, 6144 },
+ { NT_QM_PRESENT, 0 },
+ { NT_QSL_CATEGORIES, 32 },
+ { NT_QSL_COLOR_SEL_BW, 7 },
+ { NT_QSL_QST_SIZE, 4096 },
+ { NT_QUEUES, 128 },
+ { NT_RAC_RAB_INTERFACES, 3 },
+ { NT_RAC_RAB_OB_UPDATE, 0 },
+ { NT_REVISION_ID, 24 },
+ { NT_RMC_LAG_GROUPS, 1 },
+ { NT_ROA_CATEGORIES, 1024 },
+ { NT_ROA_PRESENT, 0 },
+ { NT_RPP_PER_PS, 3333 },
+ { NT_RTX_PRESENT, 0 },
+ { NT_RX_HOST_BUFFERS, 128 },
+ { NT_RX_PORTS, 2 },
+ { NT_RX_PORT_REPLICATE, 0 },
+ { NT_SLB_PRESENT, 0 },
+ { NT_SLC_LR_PRESENT, 1 },
+ { NT_STA_COLORS, 64 },
+ { NT_STA_RX_PORTS, 2 },
+ { NT_TBH_DEBUG_DLN, 1 },
+ { NT_TBH_PRESENT, 0 },
+ { NT_TFD_PRESENT, 1 },
+ { NT_TPE_CATEGORIES, 16 },
+ { NT_TSM_OST_ONLY, 0 },
+ { NT_TS_APPEND, 0 },
+ { NT_TS_INJECT_PRESENT, 0 },
+ { NT_TX_CPY_PACKET_READERS, 0 },
+ { NT_TX_CPY_PRESENT, 1 },
+ { NT_TX_CPY_SIDEBAND_READERS, 6 },
+ { NT_TX_CPY_VARIANT, 0 },
+ { NT_TX_CPY_WRITERS, 5 },
+ { NT_TX_HOST_BUFFERS, 128 },
+ { NT_TX_INS_PRESENT, 1 },
+ { NT_TX_MTU_PROFILE_IFR, 16 },
+ { NT_TX_ON_TIMESTAMP, 1 },
+ { NT_TX_PORTS, 2 },
+ { NT_TX_PORT_REPLICATE, 1 },
+ { NT_TX_RPL_DEPTH, 4096 },
+ { NT_TX_RPL_EXT_CATEGORIES, 1024 },
+ { NT_TX_RPL_PRESENT, 1 },
+ { NT_TYPE_ID, 200 },
+ { NT_USE_TRIPLE_SPEED, 0 },
+ { NT_VERSION_ID, 55 },
+ { NT_VLI_PRESENT, 0 },
+ { 0, -1 }, /* END */
+};
+
+nt_fpga_prod_init_t nthw_fpga_9563_055_024_0000 = {
+ 200, /* fpgaTypeId */
+ 9563, /* fpga_product_id */
+ 55, /* fpga_version */
+ 24, /* fpga_revision */
+ 0, /* fpga_patch_no */
+ 0, /* fpga_build_no */
+ 1689706895, /* fpga_build_time */
+ 140, product_parameters, 48, fpga_modules,
+};
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
new file mode 100644
index 0000000000..1d707d6925
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_FPGA_INSTANCES_H
+#define NTHW_FPGA_INSTANCES_H
+
+#include "fpga_model.h"
+
+extern nt_fpga_prod_init_t *nthw_fpga_instances[];
+
+extern nt_fpga_prod_init_t nthw_fpga_9563_055_024_0000;
+
+#endif /* NTHW_FPGA_INSTANCES_H */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h
new file mode 100644
index 0000000000..38a15bec87
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_modules_defs.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTHW_FPGA_MODULES_DEFS_H_
+#define _NTHW_FPGA_MODULES_DEFS_H_
+
+/* Unknown/uninitialized - keep this as the first element */
+#define MOD_UNKNOWN (0L)
+#define MOD_CAT (1L)
+#define MOD_CB (2L)
+#define MOD_CCIP (3L)
+#define MOD_CFP4_CTRL_GBOX (4L)
+#define MOD_COR (5L)
+#define MOD_CPY (6L)
+#define MOD_CSU (7L)
+#define MOD_DBS (8L)
+#define MOD_DDP (9L)
+#define MOD_EPP (10L)
+#define MOD_EQM (11L)
+#define MOD_FHM (12L)
+#define MOD_FLM (13L)
+#define MOD_GFG (14L)
+#define MOD_GMF (15L)
+#define MOD_GPIO_PHY (16L)
+#define MOD_GPIO_PHY_PORTS (17L)
+#define MOD_GPIO_SFPP (18L)
+#define MOD_HFU (19L)
+#define MOD_HIF (20L)
+#define MOD_HSH (21L)
+#define MOD_HST (22L)
+#define MOD_ICORE_10G (23L)
+#define MOD_IFR (24L)
+#define MOD_IIC (25L)
+#define MOD_INS (26L)
+#define MOD_IOA (27L)
+#define MOD_IPF (28L)
+#define MOD_KM (29L)
+#define MOD_LAO (30L)
+#define MOD_MAC (31L)
+#define MOD_MAC100 (33L)
+#define MOD_MAC10G (34L)
+#define MOD_MAC1G (35L)
+#define MOD_MAC_PCS (36L)
+#define MOD_MAC_PCS_XXV (37L)
+#define MOD_MAC_RX (38L)
+#define MOD_MAC_TFG (39L)
+#define MOD_MAC_TX (40L)
+#define MOD_MCU (41L)
+#define MOD_MDG (42L)
+#define MOD_MSK (43L)
+#define MOD_NIF (44L)
+#define MOD_PCIE3 (45L)
+#define MOD_PCI_RD_TG (46L)
+#define MOD_PCI_TA (47L)
+#define MOD_PCI_WR_TG (48L)
+#define MOD_PCM_NT100A01_01 (49L)
+#define MOD_PCM_NT50B01_01 (50L)
+#define MOD_PCS (51L)
+#define MOD_PCS100 (52L)
+#define MOD_PDB (53L)
+#define MOD_PDI (54L)
+#define MOD_PHY10G (55L)
+#define MOD_PHY3S10G (56L)
+#define MOD_PM (57L)
+#define MOD_PRM_NT100A01_01 (58L)
+#define MOD_PRM_NT50B01_01 (59L)
+#define MOD_PTP1588 (60L)
+#define MOD_QM (61L)
+#define MOD_QSL (62L)
+#define MOD_QSPI (63L)
+#define MOD_R2DRP (64L)
+#define MOD_RAC (65L)
+#define MOD_RBH (66L)
+#define MOD_RFD (67L)
+#define MOD_RMC (68L)
+#define MOD_RNTC (69L)
+#define MOD_ROA (70L)
+#define MOD_RPL (71L)
+#define MOD_RPP_LR (72L)
+#define MOD_RST7000 (73L)
+#define MOD_RST7001 (74L)
+#define MOD_RST9500 (75L)
+#define MOD_RST9501 (76L)
+#define MOD_RST9502 (77L)
+#define MOD_RST9503 (78L)
+#define MOD_RST9504 (79L)
+#define MOD_RST9505 (80L)
+#define MOD_RST9506 (81L)
+#define MOD_RST9507 (82L)
+#define MOD_RST9508 (83L)
+#define MOD_RST9509 (84L)
+#define MOD_RST9510 (85L)
+#define MOD_RST9512 (86L)
+#define MOD_RST9513 (87L)
+#define MOD_RST9515 (88L)
+#define MOD_RST9516 (89L)
+#define MOD_RST9517 (90L)
+#define MOD_RST9519 (91L)
+#define MOD_RST9520 (92L)
+#define MOD_RST9521 (93L)
+#define MOD_RST9522 (94L)
+#define MOD_RST9523 (95L)
+#define MOD_RST9524 (96L)
+#define MOD_RST9525 (97L)
+#define MOD_RST9526 (98L)
+#define MOD_RST9527 (99L)
+#define MOD_RST9528 (100L)
+#define MOD_RST9529 (101L)
+#define MOD_RST9530 (102L)
+#define MOD_RST9531 (103L)
+#define MOD_RST9532 (104L)
+#define MOD_RST9533 (105L)
+#define MOD_RST9534 (106L)
+#define MOD_RST9535 (107L)
+#define MOD_RST9536 (108L)
+#define MOD_RST9537 (109L)
+#define MOD_RST9538 (110L)
+#define MOD_RST9539 (111L)
+#define MOD_RST9540 (112L)
+#define MOD_RST9541 (113L)
+#define MOD_RST9542 (114L)
+#define MOD_RST9543 (115L)
+#define MOD_RST9544 (116L)
+#define MOD_RST9545 (117L)
+#define MOD_RST9546 (118L)
+#define MOD_RST9547 (119L)
+#define MOD_RST9548 (120L)
+#define MOD_RST9549 (121L)
+#define MOD_RST9553 (122L)
+#define MOD_RST9555 (123L)
+#define MOD_RST9559 (124L)
+#define MOD_RST9563 (125L)
+#define MOD_RTD (126L)
+#define MOD_RTD_HMP (127L)
+#define MOD_RTX (128L)
+#define MOD_SDC (129L)
+#define MOD_SLC (130L)
+#define MOD_SLC_LR (131L)
+#define MOD_SMM (132L)
+#define MOD_SMM_RX (133L)
+#define MOD_SMM_TX (134L)
+#define MOD_SPIM (135L)
+#define MOD_SPIS (136L)
+#define MOD_STA (137L)
+#define MOD_TBH (138L)
+#define MOD_TEMPMON (139L)
+#define MOD_TINT (140L)
+#define MOD_TMC (141L)
+#define MOD_TSM (142L)
+#define MOD_TX_CPY (143L)
+#define MOD_TX_CSI (144L)
+#define MOD_TX_CSO (145L)
+#define MOD_TX_INS (146L)
+#define MOD_TX_RPL (147L)
+/*
+ * NOTE: Keep this as the last element!
+ * End indicator - keep this as the last element - only aliases go below this point
+ */
+#define MOD_UNKNOWN_MAX (148L)
+/* End indicator - keep this as the last element - only aliases go below this point */
+#define MOD_COUNT_MAX (148L)
+/* aliases */
+#define MOD_MAC10 (MOD_MAC10G) /* alias */
+
+#endif /* _NTHW_FPGA_MODULES_DEFS_H_ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h
new file mode 100644
index 0000000000..b6187a257f
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_parameters_defs.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTHW_FPGA_PARAMETERS_DEFS_
+#define _NTHW_FPGA_PARAMETERS_DEFS_
+
+#define NT_PARAM_UNKNOWN (0L)
+#define NT_BUILD_NUMBER (1L)
+#define NT_BUILD_TIME (2L)
+#define NT_CATEGORIES (3L)
+#define NT_CAT_CCT_SIZE (4L)
+#define NT_CAT_CTE_SIZE (5L)
+#define NT_CAT_CTS_SIZE (6L)
+#define NT_CAT_DCT_PRESENT (7L)
+#define NT_CAT_DCT_SIZE (8L)
+#define NT_CAT_END_OFS_SUPPORT (9L)
+#define NT_CAT_FPC (10L)
+#define NT_CAT_FTE_SIZE (11L)
+#define NT_CAT_FUNCS (12L)
+#define NT_CAT_KCC_BANKS (13L)
+#define NT_CAT_KCC_PRESENT (14L)
+#define NT_CAT_KCC_SIZE (15L)
+#define NT_CAT_KCE_SIZE (16L)
+#define NT_CAT_KM_IF_CNT (17L)
+#define NT_CAT_KM_IF_M0 (18L)
+#define NT_CAT_KM_IF_M1 (19L)
+#define NT_CAT_N_CMP (20L)
+#define NT_CAT_N_EXT (21L)
+#define NT_CAT_N_LEN (22L)
+#define NT_CAT_RCK_SIZE (23L)
+#define NT_CAT_VALUES (24L)
+#define NT_CB_DEBUG (25L)
+#define NT_COR_CATEGORIES (26L)
+#define NT_COR_PRESENT (27L)
+#define NT_CPY_MASK_MEM (28L)
+#define NT_CSU_PRESENT (29L)
+#define NT_DBS_PRESENT (30L)
+#define NT_DBS_RX_QUEUES (31L)
+#define NT_DBS_TX_PORTS (32L)
+#define NT_DBS_TX_QUEUES (33L)
+#define NT_DDP_PRESENT (34L)
+#define NT_DDP_TBL_DEPTH (35L)
+#define NT_EMI_SPLIT_STEPS (36L)
+#define NT_EOF_TIMESTAMP_ONLY (37L)
+#define NT_EPP_CATEGORIES (38L)
+#define NT_EXT_MEM_NUM (39L)
+#define NT_EXT_MEM_SINGLE_SIZE_GB (40L)
+#define NT_FLM_CACHE (41L)
+#define NT_FLM_CATEGORIES (42L)
+#define NT_FLM_ENTRY_SIZE (43L)
+#define NT_FLM_PRESENT (44L)
+#define NT_FLM_PRIOS (45L)
+#define NT_FLM_PST_PROFILES (46L)
+#define NT_FLM_SIZE_MB (47L)
+#define NT_FLM_STATEFUL (48L)
+#define NT_FLM_VARIANT (49L)
+#define NT_GFG_PRESENT (50L)
+#define NT_GFG_TX_LIVE_RECONFIG_SUPPORT (51L)
+#define NT_GMF_FCS_PRESENT (52L)
+#define NT_GMF_IFG_SPEED_DIV (53L)
+#define NT_GMF_IFG_SPEED_DIV100G (54L)
+#define NT_GMF_IFG_SPEED_DIV100M (55L)
+#define NT_GMF_IFG_SPEED_DIV10G (56L)
+#define NT_GMF_IFG_SPEED_DIV1G (57L)
+#define NT_GMF_IFG_SPEED_DIV2 (58L)
+#define NT_GMF_IFG_SPEED_DIV25G (59L)
+#define NT_GMF_IFG_SPEED_DIV3 (60L)
+#define NT_GMF_IFG_SPEED_DIV4 (61L)
+#define NT_GMF_IFG_SPEED_DIV40G (62L)
+#define NT_GMF_IFG_SPEED_DIV50G (63L)
+#define NT_GMF_IFG_SPEED_MUL (64L)
+#define NT_GMF_IFG_SPEED_MUL100G (65L)
+#define NT_GMF_IFG_SPEED_MUL100M (66L)
+#define NT_GMF_IFG_SPEED_MUL10G (67L)
+#define NT_GMF_IFG_SPEED_MUL1G (68L)
+#define NT_GMF_IFG_SPEED_MUL2 (69L)
+#define NT_GMF_IFG_SPEED_MUL25G (70L)
+#define NT_GMF_IFG_SPEED_MUL3 (71L)
+#define NT_GMF_IFG_SPEED_MUL4 (72L)
+#define NT_GMF_IFG_SPEED_MUL40G (73L)
+#define NT_GMF_IFG_SPEED_MUL50G (74L)
+#define NT_GROUP_ID (75L)
+#define NT_HFU_PRESENT (76L)
+#define NT_HIF_MSIX_BAR (77L)
+#define NT_HIF_MSIX_PBA_OFS (78L)
+#define NT_HIF_MSIX_PRESENT (79L)
+#define NT_HIF_MSIX_TBL_OFS (80L)
+#define NT_HIF_MSIX_TBL_SIZE (81L)
+#define NT_HIF_PER_PS (82L)
+#define NT_HIF_SRIOV_PRESENT (83L)
+#define NT_HSH_CATEGORIES (84L)
+#define NT_HSH_TOEPLITZ (85L)
+#define NT_HST_CATEGORIES (86L)
+#define NT_HST_PRESENT (87L)
+#define NT_IOA_CATEGORIES (88L)
+#define NT_IOA_PRESENT (89L)
+#define NT_IPF_PRESENT (90L)
+#define NT_KM_CAM_BANKS (91L)
+#define NT_KM_CAM_RECORDS (92L)
+#define NT_KM_CAM_REC_WORDS (93L)
+#define NT_KM_CATEGORIES (94L)
+#define NT_KM_END_OFS_SUPPORT (95L)
+#define NT_KM_EXT_EXTRACTORS (96L)
+#define NT_KM_FLOW_SETS (97L)
+#define NT_KM_FLOW_TYPES (98L)
+#define NT_KM_PRESENT (99L)
+#define NT_KM_SWX_PRESENT (100L)
+#define NT_KM_SYNERGY_MATCH (101L)
+#define NT_KM_TCAM_BANKS (102L)
+#define NT_KM_TCAM_BANK_WIDTH (103L)
+#define NT_KM_TCAM_HIT_QUAL (104L)
+#define NT_KM_TCAM_KEYWAY (105L)
+#define NT_KM_WIDE (106L)
+#define NT_LR_PRESENT (107L)
+#define NT_LTX_CATEGORIES (108L)
+#define NT_MCU_DRAM_SIZE (109L)
+#define NT_MCU_PRESENT (110L)
+#define NT_MCU_TYPE (111L)
+#define NT_MDG_DEBUG_FLOW_CONTROL (112L)
+#define NT_MDG_DEBUG_REG_READ_BACK (113L)
+#define NT_MSK_CATEGORIES (114L)
+#define NT_MSK_PRESENT (115L)
+#define NT_NAME (116L)
+#define NT_NFV_OVS_PRODUCT (117L)
+#define NT_NIMS (118L)
+#define NT_PATCH_NUMBER (119L)
+#define NT_PCI_DEVICE_ID (120L)
+#define NT_PCI_INT_AVR (121L)
+#define NT_PCI_INT_EQM (122L)
+#define NT_PCI_INT_IIC0 (123L)
+#define NT_PCI_INT_IIC1 (124L)
+#define NT_PCI_INT_IIC2 (125L)
+#define NT_PCI_INT_IIC3 (126L)
+#define NT_PCI_INT_IIC4 (127L)
+#define NT_PCI_INT_IIC5 (128L)
+#define NT_PCI_INT_PORT (129L)
+#define NT_PCI_INT_PORT0 (130L)
+#define NT_PCI_INT_PORT1 (131L)
+#define NT_PCI_INT_PPS (132L)
+#define NT_PCI_INT_QSPI (133L)
+#define NT_PCI_INT_SPIM (134L)
+#define NT_PCI_INT_SPIS (135L)
+#define NT_PCI_INT_STA (136L)
+#define NT_PCI_INT_TIMER (137L)
+#define NT_PCI_INT_TINT (138L)
+#define NT_PCI_TA_TG_PRESENT (139L)
+#define NT_PCI_VENDOR_ID (140L)
+#define NT_PDB_CATEGORIES (141L)
+#define NT_PHY_ANEG_PRESENT (142L)
+#define NT_PHY_KRFEC_PRESENT (143L)
+#define NT_PHY_PORTS (144L)
+#define NT_PHY_PORTS_PER_QUAD (145L)
+#define NT_PHY_QUADS (146L)
+#define NT_PHY_RSFEC_PRESENT (147L)
+#define NT_PORTS (148L)
+#define NT_PROD_ID_LAYOUT_VERSION (149L)
+#define NT_QM_BLOCKS (150L)
+#define NT_QM_CELLS (151L)
+#define NT_QM_CELL_SIZE (152L)
+#define NT_QM_PRESENT (153L)
+#define NT_QSL_CATEGORIES (154L)
+#define NT_QSL_COLOR_SEL_BW (155L)
+#define NT_QSL_QST_SIZE (156L)
+#define NT_QUEUES (157L)
+#define NT_RAC_RAB_INTERFACES (158L)
+#define NT_RAC_RAB_OB_UPDATE (159L)
+#define NT_REVISION_ID (160L)
+#define NT_RMC_LAG_GROUPS (161L)
+#define NT_ROA_CATEGORIES (162L)
+#define NT_ROA_PRESENT (163L)
+#define NT_RPP_PER_PS (164L)
+#define NT_RTX_PRESENT (165L)
+#define NT_RX_HOST_BUFFERS (166L)
+#define NT_RX_PORTS (167L)
+#define NT_RX_PORT_REPLICATE (168L)
+#define NT_SLB_PRESENT (169L)
+#define NT_SLC_LR_PRESENT (170L)
+#define NT_STA_COLORS (171L)
+#define NT_STA_RX_PORTS (172L)
+#define NT_TBH_DEBUG_DLN (173L)
+#define NT_TBH_PRESENT (174L)
+#define NT_TFD_PRESENT (175L)
+#define NT_TPE_CATEGORIES (176L)
+#define NT_TSM_OST_ONLY (177L)
+#define NT_TS_APPEND (178L)
+#define NT_TS_INJECT_PRESENT (179L)
+#define NT_TX_CPY_PACKET_READERS (180L)
+#define NT_TX_CPY_PRESENT (181L)
+#define NT_TX_CPY_SIDEBAND_READERS (182L)
+#define NT_TX_CPY_VARIANT (183L)
+#define NT_TX_CPY_WRITERS (184L)
+#define NT_TX_HOST_BUFFERS (185L)
+#define NT_TX_INS_PRESENT (186L)
+#define NT_TX_MTU_PROFILE_IFR (187L)
+#define NT_TX_ON_TIMESTAMP (188L)
+#define NT_TX_PORTS (189L)
+#define NT_TX_PORT_REPLICATE (190L)
+#define NT_TX_RPL_DEPTH (191L)
+#define NT_TX_RPL_EXT_CATEGORIES (192L)
+#define NT_TX_RPL_PRESENT (193L)
+#define NT_TYPE_ID (194L)
+#define NT_USE_TRIPLE_SPEED (195L)
+#define NT_UUID (196L)
+#define NT_VERSION (197L)
+#define NT_VERSION_ID (198L)
+#define NT_VLI_PRESENT (199L)
+
+#endif /* _NTHW_FPGA_PARAMETERS_DEFS_ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h
new file mode 100644
index 0000000000..3948ed3ae3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_registers_defs.h
@@ -0,0 +1,7277 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTHW_FPGA_REGISTERS_DEFS_
+#define _NTHW_FPGA_REGISTERS_DEFS_
+
+/* CAT */
+#define CAT_CCE_CTRL (1000L)
+#define CAT_CCE_CTRL_ADR (1001L)
+#define CAT_CCE_CTRL_CNT (1002L)
+#define CAT_CCE_DATA (1003L)
+#define CAT_CCE_DATA_IMM (1004L)
+#define CAT_CCE_DATA_IND (1005L)
+#define CAT_CCS_CTRL (1006L)
+#define CAT_CCS_CTRL_ADR (1007L)
+#define CAT_CCS_CTRL_CNT (1008L)
+#define CAT_CCS_DATA (1009L)
+#define CAT_CCS_DATA_COR (1010L)
+#define CAT_CCS_DATA_COR_EN (1011L)
+#define CAT_CCS_DATA_EPP (1012L)
+#define CAT_CCS_DATA_EPP_EN (1013L)
+#define CAT_CCS_DATA_HSH (1014L)
+#define CAT_CCS_DATA_HSH_EN (1015L)
+#define CAT_CCS_DATA_HST (1016L)
+#define CAT_CCS_DATA_HST_EN (1017L)
+#define CAT_CCS_DATA_IPF (1018L)
+#define CAT_CCS_DATA_IPF_EN (1019L)
+#define CAT_CCS_DATA_MSK (1020L)
+#define CAT_CCS_DATA_MSK_EN (1021L)
+#define CAT_CCS_DATA_PDB (1022L)
+#define CAT_CCS_DATA_PDB_EN (1023L)
+#define CAT_CCS_DATA_QSL (1024L)
+#define CAT_CCS_DATA_QSL_EN (1025L)
+#define CAT_CCS_DATA_RRB (1026L)
+#define CAT_CCS_DATA_RRB_EN (1027L)
+#define CAT_CCS_DATA_SB0_DATA (1028L)
+#define CAT_CCS_DATA_SB0_TYPE (1029L)
+#define CAT_CCS_DATA_SB1_DATA (1030L)
+#define CAT_CCS_DATA_SB1_TYPE (1031L)
+#define CAT_CCS_DATA_SB2_DATA (1032L)
+#define CAT_CCS_DATA_SB2_TYPE (1033L)
+#define CAT_CCS_DATA_SLC (1034L)
+#define CAT_CCS_DATA_SLC_EN (1035L)
+#define CAT_CCS_DATA_TPE (1036L)
+#define CAT_CCS_DATA_TPE_EN (1037L)
+#define CAT_CCT_CTRL (1038L)
+#define CAT_CCT_CTRL_ADR (1039L)
+#define CAT_CCT_CTRL_CNT (1040L)
+#define CAT_CCT_DATA (1041L)
+#define CAT_CCT_DATA_COLOR (1042L)
+#define CAT_CCT_DATA_KM (1043L)
+#define CAT_CFN_CTRL (1044L)
+#define CAT_CFN_CTRL_ADR (1045L)
+#define CAT_CFN_CTRL_CNT (1046L)
+#define CAT_CFN_DATA (1047L)
+#define CAT_CFN_DATA_ENABLE (1048L)
+#define CAT_CFN_DATA_ERR_CV (1049L)
+#define CAT_CFN_DATA_ERR_FCS (1050L)
+#define CAT_CFN_DATA_ERR_INV (1051L)
+#define CAT_CFN_DATA_ERR_L3_CS (1052L)
+#define CAT_CFN_DATA_ERR_L4_CS (1053L)
+#define CAT_CFN_DATA_ERR_TNL_L3_CS (1054L)
+#define CAT_CFN_DATA_ERR_TNL_L4_CS (1055L)
+#define CAT_CFN_DATA_ERR_TNL_TTL_EXP (1056L)
+#define CAT_CFN_DATA_ERR_TRUNC (1057L)
+#define CAT_CFN_DATA_ERR_TTL_EXP (1058L)
+#define CAT_CFN_DATA_FLM_OR (1059L)
+#define CAT_CFN_DATA_INV (1060L)
+#define CAT_CFN_DATA_KM0_OR (1061L)
+#define CAT_CFN_DATA_KM1_OR (1062L)
+#define CAT_CFN_DATA_KM_OR (1063L)
+#define CAT_CFN_DATA_LC (1064L)
+#define CAT_CFN_DATA_LC_INV (1065L)
+#define CAT_CFN_DATA_MAC_PORT (1066L)
+#define CAT_CFN_DATA_PM_AND_INV (1067L)
+#define CAT_CFN_DATA_PM_CMB (1068L)
+#define CAT_CFN_DATA_PM_CMP (1069L)
+#define CAT_CFN_DATA_PM_DCT (1070L)
+#define CAT_CFN_DATA_PM_EXT_INV (1071L)
+#define CAT_CFN_DATA_PM_INV (1072L)
+#define CAT_CFN_DATA_PM_OR_INV (1073L)
+#define CAT_CFN_DATA_PTC_CFP (1074L)
+#define CAT_CFN_DATA_PTC_FRAG (1075L)
+#define CAT_CFN_DATA_PTC_INV (1076L)
+#define CAT_CFN_DATA_PTC_IP_PROT (1077L)
+#define CAT_CFN_DATA_PTC_ISL (1078L)
+#define CAT_CFN_DATA_PTC_L2 (1079L)
+#define CAT_CFN_DATA_PTC_L3 (1080L)
+#define CAT_CFN_DATA_PTC_L4 (1081L)
+#define CAT_CFN_DATA_PTC_MAC (1082L)
+#define CAT_CFN_DATA_PTC_MPLS (1083L)
+#define CAT_CFN_DATA_PTC_TNL_FRAG (1084L)
+#define CAT_CFN_DATA_PTC_TNL_IP_PROT (1085L)
+#define CAT_CFN_DATA_PTC_TNL_L2 (1086L)
+#define CAT_CFN_DATA_PTC_TNL_L3 (1087L)
+#define CAT_CFN_DATA_PTC_TNL_L4 (1088L)
+#define CAT_CFN_DATA_PTC_TNL_MPLS (1089L)
+#define CAT_CFN_DATA_PTC_TNL_VLAN (1090L)
+#define CAT_CFN_DATA_PTC_TUNNEL (1091L)
+#define CAT_CFN_DATA_PTC_VLAN (1092L)
+#define CAT_CFN_DATA_PTC_VNTAG (1093L)
+#define CAT_COT_CTRL (1094L)
+#define CAT_COT_CTRL_ADR (1095L)
+#define CAT_COT_CTRL_CNT (1096L)
+#define CAT_COT_DATA (1097L)
+#define CAT_COT_DATA_COLOR (1098L)
+#define CAT_COT_DATA_KM (1099L)
+#define CAT_COT_DATA_NFV_SB (1100L)
+#define CAT_CTE_CTRL (1101L)
+#define CAT_CTE_CTRL_ADR (1102L)
+#define CAT_CTE_CTRL_CNT (1103L)
+#define CAT_CTE_DATA (1104L)
+#define CAT_CTE_DATA_COL_ENABLE (1105L)
+#define CAT_CTE_DATA_COR_ENABLE (1106L)
+#define CAT_CTE_DATA_EPP_ENABLE (1107L)
+#define CAT_CTE_DATA_HSH_ENABLE (1108L)
+#define CAT_CTE_DATA_HST_ENABLE (1109L)
+#define CAT_CTE_DATA_IPF_ENABLE (1110L)
+#define CAT_CTE_DATA_MSK_ENABLE (1111L)
+#define CAT_CTE_DATA_PDB_ENABLE (1112L)
+#define CAT_CTE_DATA_QSL_ENABLE (1113L)
+#define CAT_CTE_DATA_RRB_ENABLE (1114L)
+#define CAT_CTE_DATA_SLC_ENABLE (1115L)
+#define CAT_CTE_DATA_TPE_ENABLE (1116L)
+#define CAT_CTE_DATA_TX_INS_ENABLE (1117L)
+#define CAT_CTE_DATA_TX_RPL_ENABLE (1118L)
+#define CAT_CTS_CTRL (1119L)
+#define CAT_CTS_CTRL_ADR (1120L)
+#define CAT_CTS_CTRL_CNT (1121L)
+#define CAT_CTS_DATA (1122L)
+#define CAT_CTS_DATA_CAT_A (1123L)
+#define CAT_CTS_DATA_CAT_B (1124L)
+#define CAT_DCT_CTRL (1125L)
+#define CAT_DCT_CTRL_ADR (1126L)
+#define CAT_DCT_CTRL_CNT (1127L)
+#define CAT_DCT_DATA (1128L)
+#define CAT_DCT_DATA_RES (1129L)
+#define CAT_DCT_SEL (1130L)
+#define CAT_DCT_SEL_LU (1131L)
+#define CAT_EXO_CTRL (1132L)
+#define CAT_EXO_CTRL_ADR (1133L)
+#define CAT_EXO_CTRL_CNT (1134L)
+#define CAT_EXO_DATA (1135L)
+#define CAT_EXO_DATA_DYN (1136L)
+#define CAT_EXO_DATA_OFS (1137L)
+#define CAT_FCE_CTRL (1138L)
+#define CAT_FCE_CTRL_ADR (1139L)
+#define CAT_FCE_CTRL_CNT (1140L)
+#define CAT_FCE_DATA (1141L)
+#define CAT_FCE_DATA_ENABLE (1142L)
+#define CAT_FCS_CTRL (1143L)
+#define CAT_FCS_CTRL_ADR (1144L)
+#define CAT_FCS_CTRL_CNT (1145L)
+#define CAT_FCS_DATA (1146L)
+#define CAT_FCS_DATA_CATEGORY (1147L)
+#define CAT_FTE0_CTRL (1148L)
+#define CAT_FTE0_CTRL_ADR (1149L)
+#define CAT_FTE0_CTRL_CNT (1150L)
+#define CAT_FTE0_DATA (1151L)
+#define CAT_FTE0_DATA_ENABLE (1152L)
+#define CAT_FTE1_CTRL (1153L)
+#define CAT_FTE1_CTRL_ADR (1154L)
+#define CAT_FTE1_CTRL_CNT (1155L)
+#define CAT_FTE1_DATA (1156L)
+#define CAT_FTE1_DATA_ENABLE (1157L)
+#define CAT_FTE_CTRL (1158L)
+#define CAT_FTE_CTRL_ADR (1159L)
+#define CAT_FTE_CTRL_CNT (1160L)
+#define CAT_FTE_DATA (1161L)
+#define CAT_FTE_DATA_ENABLE (1162L)
+#define CAT_FTE_FLM_CTRL (1163L)
+#define CAT_FTE_FLM_CTRL_ADR (1164L)
+#define CAT_FTE_FLM_CTRL_CNT (1165L)
+#define CAT_FTE_FLM_DATA (1166L)
+#define CAT_FTE_FLM_DATA_ENABLE (1167L)
+#define CAT_JOIN (1168L)
+#define CAT_JOIN_J1 (1169L)
+#define CAT_JOIN_J2 (1170L)
+#define CAT_KCC (1171L)
+#define CAT_KCC_CTRL (1172L)
+#define CAT_KCC_CTRL_ADR (1173L)
+#define CAT_KCC_CTRL_CNT (1174L)
+#define CAT_KCC_DATA (1175L)
+#define CAT_KCC_DATA_CATEGORY (1176L)
+#define CAT_KCC_DATA_ID (1177L)
+#define CAT_KCC_DATA_KEY (1178L)
+#define CAT_KCE0_CTRL (1179L)
+#define CAT_KCE0_CTRL_ADR (1180L)
+#define CAT_KCE0_CTRL_CNT (1181L)
+#define CAT_KCE0_DATA (1182L)
+#define CAT_KCE0_DATA_ENABLE (1183L)
+#define CAT_KCE1_CTRL (1184L)
+#define CAT_KCE1_CTRL_ADR (1185L)
+#define CAT_KCE1_CTRL_CNT (1186L)
+#define CAT_KCE1_DATA (1187L)
+#define CAT_KCE1_DATA_ENABLE (1188L)
+#define CAT_KCE_CTRL (1189L)
+#define CAT_KCE_CTRL_ADR (1190L)
+#define CAT_KCE_CTRL_CNT (1191L)
+#define CAT_KCE_DATA (1192L)
+#define CAT_KCE_DATA_ENABLE (1193L)
+#define CAT_KCS0_CTRL (1194L)
+#define CAT_KCS0_CTRL_ADR (1195L)
+#define CAT_KCS0_CTRL_CNT (1196L)
+#define CAT_KCS0_DATA (1197L)
+#define CAT_KCS0_DATA_CATEGORY (1198L)
+#define CAT_KCS1_CTRL (1199L)
+#define CAT_KCS1_CTRL_ADR (1200L)
+#define CAT_KCS1_CTRL_CNT (1201L)
+#define CAT_KCS1_DATA (1202L)
+#define CAT_KCS1_DATA_CATEGORY (1203L)
+#define CAT_KCS_CTRL (1204L)
+#define CAT_KCS_CTRL_ADR (1205L)
+#define CAT_KCS_CTRL_CNT (1206L)
+#define CAT_KCS_DATA (1207L)
+#define CAT_KCS_DATA_CATEGORY (1208L)
+#define CAT_LEN_CTRL (1209L)
+#define CAT_LEN_CTRL_ADR (1210L)
+#define CAT_LEN_CTRL_CNT (1211L)
+#define CAT_LEN_DATA (1212L)
+#define CAT_LEN_DATA_DYN1 (1213L)
+#define CAT_LEN_DATA_DYN2 (1214L)
+#define CAT_LEN_DATA_INV (1215L)
+#define CAT_LEN_DATA_LOWER (1216L)
+#define CAT_LEN_DATA_UPPER (1217L)
+#define CAT_RCK_CTRL (1218L)
+#define CAT_RCK_CTRL_ADR (1219L)
+#define CAT_RCK_CTRL_CNT (1220L)
+#define CAT_RCK_DATA (1221L)
+#define CAT_RCK_DATA_CM0U (1222L)
+#define CAT_RCK_DATA_CM1U (1223L)
+#define CAT_RCK_DATA_CM2U (1224L)
+#define CAT_RCK_DATA_CM3U (1225L)
+#define CAT_RCK_DATA_CM4U (1226L)
+#define CAT_RCK_DATA_CM5U (1227L)
+#define CAT_RCK_DATA_CM6U (1228L)
+#define CAT_RCK_DATA_CM7U (1229L)
+#define CAT_RCK_DATA_CML0 (1230L)
+#define CAT_RCK_DATA_CML1 (1231L)
+#define CAT_RCK_DATA_CML2 (1232L)
+#define CAT_RCK_DATA_CML3 (1233L)
+#define CAT_RCK_DATA_CML4 (1234L)
+#define CAT_RCK_DATA_CML5 (1235L)
+#define CAT_RCK_DATA_CML6 (1236L)
+#define CAT_RCK_DATA_CML7 (1237L)
+#define CAT_RCK_DATA_SEL0 (1238L)
+#define CAT_RCK_DATA_SEL1 (1239L)
+#define CAT_RCK_DATA_SEL2 (1240L)
+#define CAT_RCK_DATA_SEL3 (1241L)
+#define CAT_RCK_DATA_SEL4 (1242L)
+#define CAT_RCK_DATA_SEL5 (1243L)
+#define CAT_RCK_DATA_SEL6 (1244L)
+#define CAT_RCK_DATA_SEL7 (1245L)
+#define CAT_RCK_DATA_SEU0 (1246L)
+#define CAT_RCK_DATA_SEU1 (1247L)
+#define CAT_RCK_DATA_SEU2 (1248L)
+#define CAT_RCK_DATA_SEU3 (1249L)
+#define CAT_RCK_DATA_SEU4 (1250L)
+#define CAT_RCK_DATA_SEU5 (1251L)
+#define CAT_RCK_DATA_SEU6 (1252L)
+#define CAT_RCK_DATA_SEU7 (1253L)
+/* CB */
+#define CB_CTRL (1254L)
+#define CB_CTRL_BP (1255L)
+#define CB_CTRL_BYPASS (1256L)
+#define CB_CTRL_ENABLE (1257L)
+#define CB_CTRL_QMA (1258L)
+#define CB_CTRL_QME (1259L)
+#define CB_DBG_BP (1260L)
+#define CB_DBG_BP_CNT (1261L)
+#define CB_DBG_DQ (1262L)
+#define CB_DBG_DQ_MAX (1263L)
+#define CB_DBG_EGS_QUEUE (1264L)
+#define CB_DBG_EGS_QUEUE_ADD (1265L)
+#define CB_DBG_EGS_QUEUE_AND (1266L)
+#define CB_DBG_FREE1200 (1267L)
+#define CB_DBG_FREE1200_CNT (1268L)
+#define CB_DBG_FREE1800 (1269L)
+#define CB_DBG_FREE1800_CNT (1270L)
+#define CB_DBG_FREE600 (1271L)
+#define CB_DBG_FREE600_CNT (1272L)
+#define CB_DBG_H16 (1273L)
+#define CB_DBG_H16_CNT (1274L)
+#define CB_DBG_H32 (1275L)
+#define CB_DBG_H32_CNT (1276L)
+#define CB_DBG_H64 (1277L)
+#define CB_DBG_H64_CNT (1278L)
+#define CB_DBG_HAVE (1279L)
+#define CB_DBG_HAVE_CNT (1280L)
+#define CB_DBG_IGS_QUEUE (1281L)
+#define CB_DBG_IGS_QUEUE_ADD (1282L)
+#define CB_DBG_IGS_QUEUE_AND (1283L)
+#define CB_DBG_QM_CELL_CNT (1284L)
+#define CB_DBG_QM_CELL_CNT_CNT (1285L)
+#define CB_DBG_QM_CELL_XOR (1286L)
+#define CB_DBG_QM_CELL_XOR_XOR (1287L)
+#define CB_QPM_CTRL (1288L)
+#define CB_QPM_CTRL_ADR (1289L)
+#define CB_QPM_CTRL_CNT (1290L)
+#define CB_QPM_DATA (1291L)
+#define CB_QPM_DATA_P (1292L)
+#define CB_QUEUE_MAX (1293L)
+#define CB_QUEUE_MAX_MAX (1294L)
+#define CB_STATUS (1295L)
+#define CB_STATUS_BP (1296L)
+#define CB_STATUS_DB (1297L)
+#define CB_STATUS_EMPTY (1298L)
+#define CB_STATUS_IDLE (1299L)
+#define CB_STATUS_OVF (1300L)
+#define CB_TS_RATE (1301L)
+#define CB_TS_RATE_CNT (1302L)
+#define CB_TS_SAVE (1303L)
+#define CB_TS_SAVE_MAX (1304L)
+/* CCIP */
+#define CCIP_AFU_ID_L (1305L)
+#define CCIP_AFU_ID_L_ID (1306L)
+#define CCIP_AFU_ID_U (1307L)
+#define CCIP_AFU_ID_U_ID (1308L)
+#define CCIP_CONTROL (1309L)
+#define CCIP_CONTROL_FENCE (1310L)
+#define CCIP_DFH (1311L)
+#define CCIP_DFH_AFU_VER_MAJOR (1312L)
+#define CCIP_DFH_AFU_VER_MINOR (1313L)
+#define CCIP_DFH_CCIP_VER (1314L)
+#define CCIP_DFH_END (1315L)
+#define CCIP_DFH_FEATURE_TYPE (1316L)
+#define CCIP_DFH_NEXT (1317L)
+#define CCIP_RSVD0 (1318L)
+#define CCIP_RSVD0_RSVD (1319L)
+#define CCIP_RSVD1 (1320L)
+#define CCIP_RSVD1_RSVD (1321L)
+#define CCIP_STATUS (1322L)
+#define CCIP_STATUS_ERR (1323L)
+#define CCIP_STATUS_PWR (1324L)
+/* CFP4_CTRL_GBOX */
+#define CFP4_CTRL_GBOX_CFG (1325L)
+#define CFP4_CTRL_GBOX_CFG_GLB_ALARMN (1326L)
+#define CFP4_CTRL_GBOX_CFG_INTERR (1327L)
+#define CFP4_CTRL_GBOX_CFG_MOD_ABS (1328L)
+#define CFP4_CTRL_GBOX_CFG_MOD_LOPWR (1329L)
+#define CFP4_CTRL_GBOX_CFG_MOD_RSTN (1330L)
+#define CFP4_CTRL_GBOX_CFG_NRESET (1331L)
+#define CFP4_CTRL_GBOX_CFG_RXLOS (1332L)
+#define CFP4_CTRL_GBOX_CFG_TXDIS (1333L)
+#define CFP4_CTRL_GBOX_CFP4 (1334L)
+#define CFP4_CTRL_GBOX_CFP4_GLB_ALARMN (1335L)
+#define CFP4_CTRL_GBOX_CFP4_MOD_ABS (1336L)
+#define CFP4_CTRL_GBOX_CFP4_MOD_LOPWR (1337L)
+#define CFP4_CTRL_GBOX_CFP4_MOD_RSTN (1338L)
+#define CFP4_CTRL_GBOX_CFP4_RXLOS (1339L)
+#define CFP4_CTRL_GBOX_CFP4_TXDIS (1340L)
+#define CFP4_CTRL_GBOX_GBOX (1341L)
+#define CFP4_CTRL_GBOX_GBOX_INTERR (1342L)
+#define CFP4_CTRL_GBOX_GBOX_NRESET (1343L)
+#define CFP4_CTRL_GBOX_GPIO (1344L)
+#define CFP4_CTRL_GBOX_GPIO_GLB_ALARMN (1345L)
+#define CFP4_CTRL_GBOX_GPIO_INTERR (1346L)
+#define CFP4_CTRL_GBOX_GPIO_MOD_ABS (1347L)
+#define CFP4_CTRL_GBOX_GPIO_MOD_LOPWR (1348L)
+#define CFP4_CTRL_GBOX_GPIO_MOD_RSTN (1349L)
+#define CFP4_CTRL_GBOX_GPIO_NRESET (1350L)
+#define CFP4_CTRL_GBOX_GPIO_RXLOS (1351L)
+#define CFP4_CTRL_GBOX_GPIO_TXDIS (1352L)
+/* COR */
+#define COR_CTRL (1393L)
+#define COR_CTRL_EN (1394L)
+#define COR_DBG_COR_CNT (1395L)
+#define COR_DBG_COR_CNT_VAL (1396L)
+#define COR_DBG_COR_ID (1397L)
+#define COR_DBG_COR_ID_VAL (1398L)
+#define COR_DBG_COR_LO (1399L)
+#define COR_DBG_COR_LO_VAL (1400L)
+#define COR_DBG_COR_UP (1401L)
+#define COR_DBG_COR_UP_VAL (1402L)
+#define COR_DCEO (1403L)
+#define COR_DCEO_VAL (1404L)
+#define COR_DCSO (1405L)
+#define COR_DCSO_VAL (1406L)
+#define COR_DEEO (1407L)
+#define COR_DEEO_VAL (1408L)
+#define COR_DEO (1409L)
+#define COR_DEO_VAL (1410L)
+#define COR_DESO (1411L)
+#define COR_DESO_VAL (1412L)
+#define COR_DSEO (1413L)
+#define COR_DSEO_VAL (1414L)
+#define COR_DSO (1415L)
+#define COR_DSO_VAL (1416L)
+#define COR_DSSO (1417L)
+#define COR_DSSO_VAL (1418L)
+#define COR_RCP_CTRL (1419L)
+#define COR_RCP_CTRL_ADR (1420L)
+#define COR_RCP_CTRL_CNT (1421L)
+#define COR_RCP_DATA (1422L)
+#define COR_RCP_DATA_CBM1 (1423L)
+#define COR_RCP_DATA_EN (1424L)
+#define COR_RCP_DATA_END_PROT (1425L)
+#define COR_RCP_DATA_END_STATIC (1426L)
+#define COR_RCP_DATA_IP_CHK (1427L)
+#define COR_RCP_DATA_IP_DSCP (1428L)
+#define COR_RCP_DATA_IP_DST (1429L)
+#define COR_RCP_DATA_IP_ECN (1430L)
+#define COR_RCP_DATA_IP_FLAGS (1431L)
+#define COR_RCP_DATA_IP_FLOW (1432L)
+#define COR_RCP_DATA_IP_HOP (1433L)
+#define COR_RCP_DATA_IP_IDENT (1434L)
+#define COR_RCP_DATA_IP_NXTHDR (1435L)
+#define COR_RCP_DATA_IP_SRC (1436L)
+#define COR_RCP_DATA_IP_TC (1437L)
+#define COR_RCP_DATA_IP_TTL (1438L)
+#define COR_RCP_DATA_MAX_LEN (1439L)
+#define COR_RCP_DATA_PROT_OFS1 (1440L)
+#define COR_RCP_DATA_START_PROT (1441L)
+#define COR_RCP_DATA_START_STATIC (1442L)
+#define COR_RCP_DATA_STTC_OFS1 (1443L)
+#define COR_RCP_DATA_TCP_CHK (1444L)
+#define COR_RCP_DATA_TCP_DST (1445L)
+#define COR_RCP_DATA_TCP_SEQ (1446L)
+#define COR_RCP_DATA_TCP_SRC (1447L)
+#define COR_RCP_DATA_TNL (1448L)
+#define COR_RCP_DATA_UDP_CHK (1449L)
+#define COR_RCP_DATA_UDP_DST (1450L)
+#define COR_RCP_DATA_UDP_SRC (1451L)
+/* CPY */
+#define CPY_WRITER0_CTRL (1452L)
+#define CPY_WRITER0_CTRL_ADR (1453L)
+#define CPY_WRITER0_CTRL_CNT (1454L)
+#define CPY_WRITER0_DATA (1455L)
+#define CPY_WRITER0_DATA_DYN (1456L)
+#define CPY_WRITER0_DATA_LEN (1457L)
+#define CPY_WRITER0_DATA_MASK_POINTER (1458L)
+#define CPY_WRITER0_DATA_OFS (1459L)
+#define CPY_WRITER0_DATA_READER_SELECT (1460L)
+#define CPY_WRITER0_MASK_CTRL (1461L)
+#define CPY_WRITER0_MASK_CTRL_ADR (1462L)
+#define CPY_WRITER0_MASK_CTRL_CNT (1463L)
+#define CPY_WRITER0_MASK_DATA (1464L)
+#define CPY_WRITER0_MASK_DATA_BYTE_MASK (1465L)
+#define CPY_WRITER1_CTRL (1466L)
+#define CPY_WRITER1_CTRL_ADR (1467L)
+#define CPY_WRITER1_CTRL_CNT (1468L)
+#define CPY_WRITER1_DATA (1469L)
+#define CPY_WRITER1_DATA_DYN (1470L)
+#define CPY_WRITER1_DATA_LEN (1471L)
+#define CPY_WRITER1_DATA_MASK_POINTER (1472L)
+#define CPY_WRITER1_DATA_OFS (1473L)
+#define CPY_WRITER1_DATA_READER_SELECT (1474L)
+#define CPY_WRITER1_MASK_CTRL (1475L)
+#define CPY_WRITER1_MASK_CTRL_ADR (1476L)
+#define CPY_WRITER1_MASK_CTRL_CNT (1477L)
+#define CPY_WRITER1_MASK_DATA (1478L)
+#define CPY_WRITER1_MASK_DATA_BYTE_MASK (1479L)
+#define CPY_WRITER2_CTRL (1480L)
+#define CPY_WRITER2_CTRL_ADR (1481L)
+#define CPY_WRITER2_CTRL_CNT (1482L)
+#define CPY_WRITER2_DATA (1483L)
+#define CPY_WRITER2_DATA_DYN (1484L)
+#define CPY_WRITER2_DATA_LEN (1485L)
+#define CPY_WRITER2_DATA_MASK_POINTER (1486L)
+#define CPY_WRITER2_DATA_OFS (1487L)
+#define CPY_WRITER2_DATA_READER_SELECT (1488L)
+#define CPY_WRITER2_MASK_CTRL (1489L)
+#define CPY_WRITER2_MASK_CTRL_ADR (1490L)
+#define CPY_WRITER2_MASK_CTRL_CNT (1491L)
+#define CPY_WRITER2_MASK_DATA (1492L)
+#define CPY_WRITER2_MASK_DATA_BYTE_MASK (1493L)
+#define CPY_WRITER3_CTRL (1494L)
+#define CPY_WRITER3_CTRL_ADR (1495L)
+#define CPY_WRITER3_CTRL_CNT (1496L)
+#define CPY_WRITER3_DATA (1497L)
+#define CPY_WRITER3_DATA_DYN (1498L)
+#define CPY_WRITER3_DATA_LEN (1499L)
+#define CPY_WRITER3_DATA_MASK_POINTER (1500L)
+#define CPY_WRITER3_DATA_OFS (1501L)
+#define CPY_WRITER3_DATA_READER_SELECT (1502L)
+#define CPY_WRITER3_MASK_CTRL (1503L)
+#define CPY_WRITER3_MASK_CTRL_ADR (1504L)
+#define CPY_WRITER3_MASK_CTRL_CNT (1505L)
+#define CPY_WRITER3_MASK_DATA (1506L)
+#define CPY_WRITER3_MASK_DATA_BYTE_MASK (1507L)
+#define CPY_WRITER4_CTRL (1508L)
+#define CPY_WRITER4_CTRL_ADR (1509L)
+#define CPY_WRITER4_CTRL_CNT (1510L)
+#define CPY_WRITER4_DATA (1511L)
+#define CPY_WRITER4_DATA_DYN (1512L)
+#define CPY_WRITER4_DATA_LEN (1513L)
+#define CPY_WRITER4_DATA_MASK_POINTER (1514L)
+#define CPY_WRITER4_DATA_OFS (1515L)
+#define CPY_WRITER4_DATA_READER_SELECT (1516L)
+#define CPY_WRITER4_MASK_CTRL (1517L)
+#define CPY_WRITER4_MASK_CTRL_ADR (1518L)
+#define CPY_WRITER4_MASK_CTRL_CNT (1519L)
+#define CPY_WRITER4_MASK_DATA (1520L)
+#define CPY_WRITER4_MASK_DATA_BYTE_MASK (1521L)
+#define CPY_WRITER5_CTRL (1522L)
+#define CPY_WRITER5_CTRL_ADR (1523L)
+#define CPY_WRITER5_CTRL_CNT (1524L)
+#define CPY_WRITER5_DATA (1525L)
+#define CPY_WRITER5_DATA_DYN (1526L)
+#define CPY_WRITER5_DATA_LEN (1527L)
+#define CPY_WRITER5_DATA_MASK_POINTER (1528L)
+#define CPY_WRITER5_DATA_OFS (1529L)
+#define CPY_WRITER5_DATA_READER_SELECT (1530L)
+#define CPY_WRITER5_MASK_CTRL (1531L)
+#define CPY_WRITER5_MASK_CTRL_ADR (1532L)
+#define CPY_WRITER5_MASK_CTRL_CNT (1533L)
+#define CPY_WRITER5_MASK_DATA (1534L)
+#define CPY_WRITER5_MASK_DATA_BYTE_MASK (1535L)
+/* CSU */
+#define CSU_RCP_CTRL (1536L)
+#define CSU_RCP_CTRL_ADR (1537L)
+#define CSU_RCP_CTRL_CNT (1538L)
+#define CSU_RCP_DATA (1539L)
+#define CSU_RCP_DATA_IL3_CMD (1540L)
+#define CSU_RCP_DATA_IL4_CMD (1541L)
+#define CSU_RCP_DATA_OL3_CMD (1542L)
+#define CSU_RCP_DATA_OL4_CMD (1543L)
+/* DBS */
+#define DBS_RX_AM_CTRL (1544L)
+#define DBS_RX_AM_CTRL_ADR (1545L)
+#define DBS_RX_AM_CTRL_CNT (1546L)
+#define DBS_RX_AM_DATA (1547L)
+#define DBS_RX_AM_DATA_ENABLE (1548L)
+#define DBS_RX_AM_DATA_GPA (1549L)
+#define DBS_RX_AM_DATA_HID (1550L)
+#define DBS_RX_AM_DATA_INT (1551L)
+#define DBS_RX_AM_DATA_PCKED (1552L)
+#define DBS_RX_CONTROL (1553L)
+#define DBS_RX_CONTROL_AME (1554L)
+#define DBS_RX_CONTROL_AMS (1555L)
+#define DBS_RX_CONTROL_LQ (1556L)
+#define DBS_RX_CONTROL_QE (1557L)
+#define DBS_RX_CONTROL_UWE (1558L)
+#define DBS_RX_CONTROL_UWS (1559L)
+#define DBS_RX_DR_CTRL (1560L)
+#define DBS_RX_DR_CTRL_ADR (1561L)
+#define DBS_RX_DR_CTRL_CNT (1562L)
+#define DBS_RX_DR_DATA (1563L)
+#define DBS_RX_DR_DATA_GPA (1564L)
+#define DBS_RX_DR_DATA_HDR (1565L)
+#define DBS_RX_DR_DATA_HID (1566L)
+#define DBS_RX_DR_DATA_PCKED (1567L)
+#define DBS_RX_DR_DATA_QS (1568L)
+#define DBS_RX_IDLE (1569L)
+#define DBS_RX_IDLE_BUSY (1570L)
+#define DBS_RX_IDLE_IDLE (1571L)
+#define DBS_RX_IDLE_QUEUE (1572L)
+#define DBS_RX_INIT (1573L)
+#define DBS_RX_INIT_BUSY (1574L)
+#define DBS_RX_INIT_INIT (1575L)
+#define DBS_RX_INIT_QUEUE (1576L)
+#define DBS_RX_INIT_VAL (1577L)
+#define DBS_RX_INIT_VAL_IDX (1578L)
+#define DBS_RX_INIT_VAL_PTR (1579L)
+#define DBS_RX_PTR (1580L)
+#define DBS_RX_PTR_PTR (1581L)
+#define DBS_RX_PTR_QUEUE (1582L)
+#define DBS_RX_PTR_VALID (1583L)
+#define DBS_RX_UW_CTRL (1584L)
+#define DBS_RX_UW_CTRL_ADR (1585L)
+#define DBS_RX_UW_CTRL_CNT (1586L)
+#define DBS_RX_UW_DATA (1587L)
+#define DBS_RX_UW_DATA_GPA (1588L)
+#define DBS_RX_UW_DATA_HID (1589L)
+#define DBS_RX_UW_DATA_INT (1590L)
+#define DBS_RX_UW_DATA_ISTK (1591L)
+#define DBS_RX_UW_DATA_PCKED (1592L)
+#define DBS_RX_UW_DATA_QS (1593L)
+#define DBS_RX_UW_DATA_VEC (1594L)
+#define DBS_STATUS (1595L)
+#define DBS_STATUS_OK (1596L)
+#define DBS_TX_AM_CTRL (1597L)
+#define DBS_TX_AM_CTRL_ADR (1598L)
+#define DBS_TX_AM_CTRL_CNT (1599L)
+#define DBS_TX_AM_DATA (1600L)
+#define DBS_TX_AM_DATA_ENABLE (1601L)
+#define DBS_TX_AM_DATA_GPA (1602L)
+#define DBS_TX_AM_DATA_HID (1603L)
+#define DBS_TX_AM_DATA_INT (1604L)
+#define DBS_TX_AM_DATA_PCKED (1605L)
+#define DBS_TX_CONTROL (1606L)
+#define DBS_TX_CONTROL_AME (1607L)
+#define DBS_TX_CONTROL_AMS (1608L)
+#define DBS_TX_CONTROL_LQ (1609L)
+#define DBS_TX_CONTROL_QE (1610L)
+#define DBS_TX_CONTROL_UWE (1611L)
+#define DBS_TX_CONTROL_UWS (1612L)
+#define DBS_TX_DR_CTRL (1613L)
+#define DBS_TX_DR_CTRL_ADR (1614L)
+#define DBS_TX_DR_CTRL_CNT (1615L)
+#define DBS_TX_DR_DATA (1616L)
+#define DBS_TX_DR_DATA_GPA (1617L)
+#define DBS_TX_DR_DATA_HDR (1618L)
+#define DBS_TX_DR_DATA_HID (1619L)
+#define DBS_TX_DR_DATA_PCKED (1620L)
+#define DBS_TX_DR_DATA_PORT (1621L)
+#define DBS_TX_DR_DATA_QS (1622L)
+#define DBS_TX_IDLE (1623L)
+#define DBS_TX_IDLE_BUSY (1624L)
+#define DBS_TX_IDLE_IDLE (1625L)
+#define DBS_TX_IDLE_QUEUE (1626L)
+#define DBS_TX_INIT (1627L)
+#define DBS_TX_INIT_BUSY (1628L)
+#define DBS_TX_INIT_INIT (1629L)
+#define DBS_TX_INIT_QUEUE (1630L)
+#define DBS_TX_INIT_VAL (1631L)
+#define DBS_TX_INIT_VAL_IDX (1632L)
+#define DBS_TX_INIT_VAL_PTR (1633L)
+#define DBS_TX_PTR (1634L)
+#define DBS_TX_PTR_PTR (1635L)
+#define DBS_TX_PTR_QUEUE (1636L)
+#define DBS_TX_PTR_VALID (1637L)
+#define DBS_TX_QOS_CTRL (1638L)
+#define DBS_TX_QOS_CTRL_ADR (1639L)
+#define DBS_TX_QOS_CTRL_CNT (1640L)
+#define DBS_TX_QOS_DATA (1641L)
+#define DBS_TX_QOS_DATA_BS (1642L)
+#define DBS_TX_QOS_DATA_EN (1643L)
+#define DBS_TX_QOS_DATA_IR (1644L)
+#define DBS_TX_QOS_DATA_MUL (1645L)
+#define DBS_TX_QOS_RATE (1646L)
+#define DBS_TX_QOS_RATE_DIV (1647L)
+#define DBS_TX_QOS_RATE_MUL (1648L)
+#define DBS_TX_QP_CTRL (1649L)
+#define DBS_TX_QP_CTRL_ADR (1650L)
+#define DBS_TX_QP_CTRL_CNT (1651L)
+#define DBS_TX_QP_DATA (1652L)
+#define DBS_TX_QP_DATA_VPORT (1653L)
+#define DBS_TX_UW_CTRL (1654L)
+#define DBS_TX_UW_CTRL_ADR (1655L)
+#define DBS_TX_UW_CTRL_CNT (1656L)
+#define DBS_TX_UW_DATA (1657L)
+#define DBS_TX_UW_DATA_GPA (1658L)
+#define DBS_TX_UW_DATA_HID (1659L)
+#define DBS_TX_UW_DATA_INO (1660L)
+#define DBS_TX_UW_DATA_INT (1661L)
+#define DBS_TX_UW_DATA_ISTK (1662L)
+#define DBS_TX_UW_DATA_PCKED (1663L)
+#define DBS_TX_UW_DATA_QS (1664L)
+#define DBS_TX_UW_DATA_VEC (1665L)
+/* DDP */
+#define DDP_AGING_CTRL (1666L)
+#define DDP_AGING_CTRL_AGING_RATE (1667L)
+#define DDP_AGING_CTRL_MAX_CNT (1668L)
+#define DDP_CTRL (1669L)
+#define DDP_CTRL_INIT (1670L)
+#define DDP_CTRL_INIT_DONE (1671L)
+#define DDP_RCP_CTRL (1672L)
+#define DDP_RCP_CTRL_ADR (1673L)
+#define DDP_RCP_CTRL_CNT (1674L)
+#define DDP_RCP_DATA (1675L)
+#define DDP_RCP_DATA_EN (1676L)
+#define DDP_RCP_DATA_GROUPID (1677L)
+/* EPP */
+#define EPP_QUEUE_MTU_CTRL (1755L)
+#define EPP_QUEUE_MTU_CTRL_ADR (1756L)
+#define EPP_QUEUE_MTU_CTRL_CNT (1757L)
+#define EPP_QUEUE_MTU_DATA (1758L)
+#define EPP_QUEUE_MTU_DATA_MAX_MTU (1759L)
+#define EPP_QUEUE_VPORT_CTRL (1760L)
+#define EPP_QUEUE_VPORT_CTRL_ADR (1761L)
+#define EPP_QUEUE_VPORT_CTRL_CNT (1762L)
+#define EPP_QUEUE_VPORT_DATA (1763L)
+#define EPP_QUEUE_VPORT_DATA_VPORT (1764L)
+#define EPP_RCP_CTRL (1765L)
+#define EPP_RCP_CTRL_ADR (1766L)
+#define EPP_RCP_CTRL_CNT (1767L)
+#define EPP_RCP_DATA (1768L)
+#define EPP_RCP_DATA_FIXED_18B_L2_MTU (1769L)
+#define EPP_RCP_DATA_QUEUE_MTU_EPP_EN (1770L)
+#define EPP_RCP_DATA_QUEUE_QOS_EPP_EN (1771L)
+#define EPP_RCP_DATA_SIZE_ADJUST_TXP (1772L)
+#define EPP_RCP_DATA_SIZE_ADJUST_VPORT (1773L)
+#define EPP_RCP_DATA_TX_MTU_EPP_EN (1774L)
+#define EPP_RCP_DATA_TX_QOS_EPP_EN (1775L)
+#define EPP_TXP_MTU_CTRL (1776L)
+#define EPP_TXP_MTU_CTRL_ADR (1777L)
+#define EPP_TXP_MTU_CTRL_CNT (1778L)
+#define EPP_TXP_MTU_DATA (1779L)
+#define EPP_TXP_MTU_DATA_MAX_MTU (1780L)
+#define EPP_TXP_QOS_CTRL (1781L)
+#define EPP_TXP_QOS_CTRL_ADR (1782L)
+#define EPP_TXP_QOS_CTRL_CNT (1783L)
+#define EPP_TXP_QOS_DATA (1784L)
+#define EPP_TXP_QOS_DATA_BS (1785L)
+#define EPP_TXP_QOS_DATA_EN (1786L)
+#define EPP_TXP_QOS_DATA_IR (1787L)
+#define EPP_TXP_QOS_DATA_IR_FRACTION (1788L)
+#define EPP_VPORT_QOS_CTRL (1789L)
+#define EPP_VPORT_QOS_CTRL_ADR (1790L)
+#define EPP_VPORT_QOS_CTRL_CNT (1791L)
+#define EPP_VPORT_QOS_DATA (1792L)
+#define EPP_VPORT_QOS_DATA_BS (1793L)
+#define EPP_VPORT_QOS_DATA_EN (1794L)
+#define EPP_VPORT_QOS_DATA_IR (1795L)
+#define EPP_VPORT_QOS_DATA_IR_FRACTION (1796L)
+/* EQM */
+#define EQM_CTRL (1797L)
+#define EQM_CTRL_DBG_CRC_ERR (1798L)
+#define EQM_CTRL_DBG_FORCE_ERR (1799L)
+#define EQM_CTRL_DBG_RMT_ERR (1800L)
+#define EQM_CTRL_DBG_SYNC_ERR (1801L)
+#define EQM_CTRL_ENABLE (1802L)
+#define EQM_CTRL_MODE (1803L)
+#define EQM_CTRL_PP_RST (1804L)
+#define EQM_DBG (1805L)
+#define EQM_DBG_FIFO_OF (1806L)
+#define EQM_DBG_LCL_EGS_QKA_OF (1807L)
+#define EQM_DBG_LCL_EGS_QLVL_OF (1808L)
+#define EQM_DBG_QBLK_CREDITS (1809L)
+#define EQM_STATUS (1810L)
+#define EQM_STATUS_LCL_EGS_OF_ERR (1811L)
+#define EQM_STATUS_NIF_CRC_ERR (1812L)
+#define EQM_STATUS_NIF_PP_LOOP_LCK (1813L)
+#define EQM_STATUS_NIF_RX_OF_ERR (1814L)
+#define EQM_STATUS_NIF_SYNC_ERR (1815L)
+#define EQM_STATUS_QM_CRC_ERR (1816L)
+#define EQM_STATUS_RMT_EGS_OF_ERR (1817L)
+#define EQM_STATUS_RMT_ERR (1818L)
+#define EQM_STATUS_RMT_IGS_OF_ERR (1819L)
+/* FHM */
+#define FHM_BACK_PRESSURE (1820L)
+#define FHM_BACK_PRESSURE_NIF (1821L)
+#define FHM_BACK_PRESSURE_RMC (1822L)
+#define FHM_BACK_PRESSURE_RMC_S (1823L)
+#define FHM_CRC_ERROR_NIF (1824L)
+#define FHM_CRC_ERROR_NIF_CNT (1825L)
+#define FHM_CRC_ERROR_SDC (1826L)
+#define FHM_CRC_ERROR_SDC_CNT (1827L)
+#define FHM_CTRL (1828L)
+#define FHM_CTRL_CNT_CLR (1829L)
+#define FHM_CTRL_ENABLE (1830L)
+#define FHM_CTRL_MODE (1831L)
+#define FHM_DEBUG_CRC (1832L)
+#define FHM_DEBUG_CRC_FORCE_ERROR (1833L)
+#define FHM_DEBUG_SDRAM_SIZE (1834L)
+#define FHM_DEBUG_SDRAM_SIZE_MASK (1835L)
+#define FHM_FILL_LEVEL (1836L)
+#define FHM_FILL_LEVEL_CELLS (1837L)
+#define FHM_MAC_MICRO_DROP (1838L)
+#define FHM_MAC_MICRO_DROP_CNT (1839L)
+#define FHM_MAX_FILL_LEVEL (1840L)
+#define FHM_MAX_FILL_LEVEL_CELLS (1841L)
+#define FHM_PKT_DROP (1842L)
+#define FHM_PKT_DROP_CNT (1843L)
+#define FHM_PKT_DROP_BYTES (1844L)
+#define FHM_PKT_DROP_BYTES_CNT (1845L)
+/* FLM */
+#define FLM_BUF_CTRL (1855L)
+#define FLM_BUF_CTRL_INF_AVAIL (1856L)
+#define FLM_BUF_CTRL_LRN_FREE (1857L)
+#define FLM_BUF_CTRL_STA_AVAIL (1858L)
+#define FLM_CONTROL (1859L)
+#define FLM_CONTROL_CRCRD (1860L)
+#define FLM_CONTROL_CRCWR (1861L)
+#define FLM_CONTROL_EAB (1862L)
+#define FLM_CONTROL_ENABLE (1863L)
+#define FLM_CONTROL_INIT (1864L)
+#define FLM_CONTROL_LDS (1865L)
+#define FLM_CONTROL_LFS (1866L)
+#define FLM_CONTROL_LIS (1867L)
+#define FLM_CONTROL_PDS (1868L)
+#define FLM_CONTROL_PIS (1869L)
+#define FLM_CONTROL_RBL (1870L)
+#define FLM_CONTROL_RDS (1871L)
+#define FLM_CONTROL_RIS (1872L)
+#define FLM_CONTROL_SPLIT_SDRAM_USAGE (1873L)
+#define FLM_CONTROL_UDS (1874L)
+#define FLM_CONTROL_UIS (1875L)
+#define FLM_CONTROL_WPD (1876L)
+#define FLM_INF_DATA (1877L)
+#define FLM_INF_DATA_BYTES (1878L)
+#define FLM_INF_DATA_BYT_A (1879L)
+#define FLM_INF_DATA_BYT_B (1880L)
+#define FLM_INF_DATA_CAUSE (1881L)
+#define FLM_INF_DATA_EOR (1882L)
+#define FLM_INF_DATA_ID (1883L)
+#define FLM_INF_DATA_PACKETS (1884L)
+#define FLM_INF_DATA_PCK_A (1885L)
+#define FLM_INF_DATA_PCK_B (1886L)
+#define FLM_INF_DATA_RTX_A (1887L)
+#define FLM_INF_DATA_RTX_B (1888L)
+#define FLM_INF_DATA_TCP_A (1889L)
+#define FLM_INF_DATA_TCP_B (1890L)
+#define FLM_INF_DATA_TS (1891L)
+#define FLM_LOAD_APS (1892L)
+#define FLM_LOAD_APS_APS (1893L)
+#define FLM_LOAD_BIN (1894L)
+#define FLM_LOAD_BIN_BIN (1895L)
+#define FLM_LOAD_LPS (1896L)
+#define FLM_LOAD_LPS_LPS (1897L)
+#define FLM_LOAD_PPS (1898L)
+#define FLM_LOAD_PPS_PPS (1899L)
+#define FLM_LRN_CTRL (1900L)
+#define FLM_LRN_CTRL_FREE (1901L)
+#define FLM_LRN_DATA (1902L)
+#define FLM_LRN_DATA_ADJ (1903L)
+#define FLM_LRN_DATA_COLOR (1904L)
+#define FLM_LRN_DATA_DSCP (1905L)
+#define FLM_LRN_DATA_ENT (1906L)
+#define FLM_LRN_DATA_EOR (1907L)
+#define FLM_LRN_DATA_FILL (1908L)
+#define FLM_LRN_DATA_FT (1909L)
+#define FLM_LRN_DATA_FT_MBR (1910L)
+#define FLM_LRN_DATA_FT_MISS (1911L)
+#define FLM_LRN_DATA_GFI (1912L)
+#define FLM_LRN_DATA_ID (1913L)
+#define FLM_LRN_DATA_KID (1914L)
+#define FLM_LRN_DATA_MBR_ID1 (1915L)
+#define FLM_LRN_DATA_MBR_ID2 (1916L)
+#define FLM_LRN_DATA_MBR_ID3 (1917L)
+#define FLM_LRN_DATA_MBR_ID4 (1918L)
+#define FLM_LRN_DATA_NAT_EN (1919L)
+#define FLM_LRN_DATA_NAT_IP (1920L)
+#define FLM_LRN_DATA_NAT_PORT (1921L)
+#define FLM_LRN_DATA_OP (1922L)
+#define FLM_LRN_DATA_PRIO (1923L)
+#define FLM_LRN_DATA_PROT (1924L)
+#define FLM_LRN_DATA_QFI (1925L)
+#define FLM_LRN_DATA_QW0 (1926L)
+#define FLM_LRN_DATA_QW4 (1927L)
+#define FLM_LRN_DATA_RATE (1928L)
+#define FLM_LRN_DATA_RQI (1929L)
+#define FLM_LRN_DATA_SIZE (1930L)
+#define FLM_LRN_DATA_STAT_PROF (1931L)
+#define FLM_LRN_DATA_SW8 (1932L)
+#define FLM_LRN_DATA_SW9 (1933L)
+#define FLM_LRN_DATA_TAU (1934L)
+#define FLM_LRN_DATA_TEID (1935L)
+#define FLM_LRN_DATA_TTL (1936L)
+#define FLM_LRN_DATA_VOL_IDX (1937L)
+#define FLM_PRIO (1938L)
+#define FLM_PRIO_FT0 (1939L)
+#define FLM_PRIO_FT1 (1940L)
+#define FLM_PRIO_FT2 (1941L)
+#define FLM_PRIO_FT3 (1942L)
+#define FLM_PRIO_LIMIT0 (1943L)
+#define FLM_PRIO_LIMIT1 (1944L)
+#define FLM_PRIO_LIMIT2 (1945L)
+#define FLM_PRIO_LIMIT3 (1946L)
+#define FLM_PST_CTRL (1947L)
+#define FLM_PST_CTRL_ADR (1948L)
+#define FLM_PST_CTRL_CNT (1949L)
+#define FLM_PST_DATA (1950L)
+#define FLM_PST_DATA_BP (1951L)
+#define FLM_PST_DATA_PP (1952L)
+#define FLM_PST_DATA_TP (1953L)
+#define FLM_RCP_CTRL (1954L)
+#define FLM_RCP_CTRL_ADR (1955L)
+#define FLM_RCP_CTRL_CNT (1956L)
+#define FLM_RCP_DATA (1957L)
+#define FLM_RCP_DATA_A (1958L)
+#define FLM_RCP_DATA_AUTO_IPV4_MASK (1959L)
+#define FLM_RCP_DATA_B (1960L)
+#define FLM_RCP_DATA_BYT_DYN (1961L)
+#define FLM_RCP_DATA_BYT_OFS (1962L)
+#define FLM_RCP_DATA_IPN (1963L)
+#define FLM_RCP_DATA_ITF (1964L)
+#define FLM_RCP_DATA_KID (1965L)
+#define FLM_RCP_DATA_LOOKUP (1966L)
+#define FLM_RCP_DATA_MASK (1967L)
+#define FLM_RCP_DATA_OPN (1968L)
+#define FLM_RCP_DATA_QW0_DYN (1969L)
+#define FLM_RCP_DATA_QW0_OFS (1970L)
+#define FLM_RCP_DATA_QW0_SEL (1971L)
+#define FLM_RCP_DATA_QW4_DYN (1972L)
+#define FLM_RCP_DATA_QW4_OFS (1973L)
+#define FLM_RCP_DATA_SW8_DYN (1974L)
+#define FLM_RCP_DATA_SW8_OFS (1975L)
+#define FLM_RCP_DATA_SW8_SEL (1976L)
+#define FLM_RCP_DATA_SW9_DYN (1977L)
+#define FLM_RCP_DATA_SW9_OFS (1978L)
+#define FLM_RCP_DATA_TXPLM (1979L)
+#define FLM_SCRUB (1980L)
+#define FLM_SCRUB_I (1981L)
+#define FLM_STATUS (1982L)
+#define FLM_STATUS_CALIBDONE (1983L)
+#define FLM_STATUS_CRCERR (1984L)
+#define FLM_STATUS_CRITICAL (1985L)
+#define FLM_STATUS_EFT_BP (1986L)
+#define FLM_STATUS_EFT_EVICT_BP (1987L)
+#define FLM_STATUS_IDLE (1988L)
+#define FLM_STATUS_INITDONE (1989L)
+#define FLM_STATUS_PANIC (1990L)
+#define FLM_STAT_AUL_DONE (1991L)
+#define FLM_STAT_AUL_DONE_CNT (1992L)
+#define FLM_STAT_AUL_FAIL (1993L)
+#define FLM_STAT_AUL_FAIL_CNT (1994L)
+#define FLM_STAT_AUL_IGNORE (1995L)
+#define FLM_STAT_AUL_IGNORE_CNT (1996L)
+#define FLM_STAT_CSH_HIT (1997L)
+#define FLM_STAT_CSH_HIT_CNT (1998L)
+#define FLM_STAT_CSH_MISS (1999L)
+#define FLM_STAT_CSH_MISS_CNT (2000L)
+#define FLM_STAT_CSH_UNH (2001L)
+#define FLM_STAT_CSH_UNH_CNT (2002L)
+#define FLM_STAT_CUC_MOVE (2003L)
+#define FLM_STAT_CUC_MOVE_CNT (2004L)
+#define FLM_STAT_CUC_START (2005L)
+#define FLM_STAT_CUC_START_CNT (2006L)
+#define FLM_STAT_FLOWS (2007L)
+#define FLM_STAT_FLOWS_CNT (2008L)
+#define FLM_STAT_INF_DONE (2009L)
+#define FLM_STAT_INF_DONE_CNT (2010L)
+#define FLM_STAT_INF_SKIP (2011L)
+#define FLM_STAT_INF_SKIP_CNT (2012L)
+#define FLM_STAT_LRN_DONE (2013L)
+#define FLM_STAT_LRN_DONE_CNT (2014L)
+#define FLM_STAT_LRN_FAIL (2015L)
+#define FLM_STAT_LRN_FAIL_CNT (2016L)
+#define FLM_STAT_LRN_IGNORE (2017L)
+#define FLM_STAT_LRN_IGNORE_CNT (2018L)
+#define FLM_STAT_PCK_DIS (2019L)
+#define FLM_STAT_PCK_DIS_CNT (2020L)
+#define FLM_STAT_PCK_HIT (2021L)
+#define FLM_STAT_PCK_HIT_CNT (2022L)
+#define FLM_STAT_PCK_MISS (2023L)
+#define FLM_STAT_PCK_MISS_CNT (2024L)
+#define FLM_STAT_PCK_UNH (2025L)
+#define FLM_STAT_PCK_UNH_CNT (2026L)
+#define FLM_STAT_PRB_DONE (2027L)
+#define FLM_STAT_PRB_DONE_CNT (2028L)
+#define FLM_STAT_PRB_IGNORE (2029L)
+#define FLM_STAT_PRB_IGNORE_CNT (2030L)
+#define FLM_STAT_REL_DONE (2031L)
+#define FLM_STAT_REL_DONE_CNT (2032L)
+#define FLM_STAT_REL_IGNORE (2033L)
+#define FLM_STAT_REL_IGNORE_CNT (2034L)
+#define FLM_STAT_STA_DONE (2035L)
+#define FLM_STAT_STA_DONE_CNT (2036L)
+#define FLM_STAT_TUL_DONE (2037L)
+#define FLM_STAT_TUL_DONE_CNT (2038L)
+#define FLM_STAT_UNL_DONE (2039L)
+#define FLM_STAT_UNL_DONE_CNT (2040L)
+#define FLM_STAT_UNL_IGNORE (2041L)
+#define FLM_STAT_UNL_IGNORE_CNT (2042L)
+#define FLM_STA_DATA (2043L)
+#define FLM_STA_DATA_EOR (2044L)
+#define FLM_STA_DATA_ID (2045L)
+#define FLM_STA_DATA_LDS (2046L)
+#define FLM_STA_DATA_LFS (2047L)
+#define FLM_STA_DATA_LIS (2048L)
+#define FLM_STA_DATA_PDS (2049L)
+#define FLM_STA_DATA_PIS (2050L)
+#define FLM_STA_DATA_RDS (2051L)
+#define FLM_STA_DATA_RIS (2052L)
+#define FLM_STA_DATA_UDS (2053L)
+#define FLM_STA_DATA_UIS (2054L)
+#define FLM_TIMEOUT (2055L)
+#define FLM_TIMEOUT_T (2056L)
+#define FLM_TRSWIN (2057L)
+#define FLM_TRSWIN_S (2058L)
+#define FLM_TRTWIN (2059L)
+#define FLM_TRTWIN_T (2060L)
+/* GFG */
+#define GFG_BURSTSIZE0 (2061L)
+#define GFG_BURSTSIZE0_VAL (2062L)
+#define GFG_BURSTSIZE1 (2063L)
+#define GFG_BURSTSIZE1_VAL (2064L)
+#define GFG_BURSTSIZE2 (2065L)
+#define GFG_BURSTSIZE2_VAL (2066L)
+#define GFG_BURSTSIZE3 (2067L)
+#define GFG_BURSTSIZE3_VAL (2068L)
+#define GFG_BURSTSIZE4 (2069L)
+#define GFG_BURSTSIZE4_VAL (2070L)
+#define GFG_BURSTSIZE5 (2071L)
+#define GFG_BURSTSIZE5_VAL (2072L)
+#define GFG_BURSTSIZE6 (2073L)
+#define GFG_BURSTSIZE6_VAL (2074L)
+#define GFG_BURSTSIZE7 (2075L)
+#define GFG_BURSTSIZE7_VAL (2076L)
+#define GFG_CTRL0 (2077L)
+#define GFG_CTRL0_ENABLE (2078L)
+#define GFG_CTRL0_MODE (2079L)
+#define GFG_CTRL0_PRBS_EN (2080L)
+#define GFG_CTRL0_SIZE (2081L)
+#define GFG_CTRL1 (2082L)
+#define GFG_CTRL1_ENABLE (2083L)
+#define GFG_CTRL1_MODE (2084L)
+#define GFG_CTRL1_PRBS_EN (2085L)
+#define GFG_CTRL1_SIZE (2086L)
+#define GFG_CTRL2 (2087L)
+#define GFG_CTRL2_ENABLE (2088L)
+#define GFG_CTRL2_MODE (2089L)
+#define GFG_CTRL2_PRBS_EN (2090L)
+#define GFG_CTRL2_SIZE (2091L)
+#define GFG_CTRL3 (2092L)
+#define GFG_CTRL3_ENABLE (2093L)
+#define GFG_CTRL3_MODE (2094L)
+#define GFG_CTRL3_PRBS_EN (2095L)
+#define GFG_CTRL3_SIZE (2096L)
+#define GFG_CTRL4 (2097L)
+#define GFG_CTRL4_ENABLE (2098L)
+#define GFG_CTRL4_MODE (2099L)
+#define GFG_CTRL4_PRBS_EN (2100L)
+#define GFG_CTRL4_SIZE (2101L)
+#define GFG_CTRL5 (2102L)
+#define GFG_CTRL5_ENABLE (2103L)
+#define GFG_CTRL5_MODE (2104L)
+#define GFG_CTRL5_PRBS_EN (2105L)
+#define GFG_CTRL5_SIZE (2106L)
+#define GFG_CTRL6 (2107L)
+#define GFG_CTRL6_ENABLE (2108L)
+#define GFG_CTRL6_MODE (2109L)
+#define GFG_CTRL6_PRBS_EN (2110L)
+#define GFG_CTRL6_SIZE (2111L)
+#define GFG_CTRL7 (2112L)
+#define GFG_CTRL7_ENABLE (2113L)
+#define GFG_CTRL7_MODE (2114L)
+#define GFG_CTRL7_PRBS_EN (2115L)
+#define GFG_CTRL7_SIZE (2116L)
+#define GFG_RUN0 (2117L)
+#define GFG_RUN0_RUN (2118L)
+#define GFG_RUN1 (2119L)
+#define GFG_RUN1_RUN (2120L)
+#define GFG_RUN2 (2121L)
+#define GFG_RUN2_RUN (2122L)
+#define GFG_RUN3 (2123L)
+#define GFG_RUN3_RUN (2124L)
+#define GFG_RUN4 (2125L)
+#define GFG_RUN4_RUN (2126L)
+#define GFG_RUN5 (2127L)
+#define GFG_RUN5_RUN (2128L)
+#define GFG_RUN6 (2129L)
+#define GFG_RUN6_RUN (2130L)
+#define GFG_RUN7 (2131L)
+#define GFG_RUN7_RUN (2132L)
+#define GFG_SIZEMASK0 (2133L)
+#define GFG_SIZEMASK0_VAL (2134L)
+#define GFG_SIZEMASK1 (2135L)
+#define GFG_SIZEMASK1_VAL (2136L)
+#define GFG_SIZEMASK2 (2137L)
+#define GFG_SIZEMASK2_VAL (2138L)
+#define GFG_SIZEMASK3 (2139L)
+#define GFG_SIZEMASK3_VAL (2140L)
+#define GFG_SIZEMASK4 (2141L)
+#define GFG_SIZEMASK4_VAL (2142L)
+#define GFG_SIZEMASK5 (2143L)
+#define GFG_SIZEMASK5_VAL (2144L)
+#define GFG_SIZEMASK6 (2145L)
+#define GFG_SIZEMASK6_VAL (2146L)
+#define GFG_SIZEMASK7 (2147L)
+#define GFG_SIZEMASK7_VAL (2148L)
+#define GFG_STREAMID0 (2149L)
+#define GFG_STREAMID0_VAL (2150L)
+#define GFG_STREAMID1 (2151L)
+#define GFG_STREAMID1_VAL (2152L)
+#define GFG_STREAMID2 (2153L)
+#define GFG_STREAMID2_VAL (2154L)
+#define GFG_STREAMID3 (2155L)
+#define GFG_STREAMID3_VAL (2156L)
+#define GFG_STREAMID4 (2157L)
+#define GFG_STREAMID4_VAL (2158L)
+#define GFG_STREAMID5 (2159L)
+#define GFG_STREAMID5_VAL (2160L)
+#define GFG_STREAMID6 (2161L)
+#define GFG_STREAMID6_VAL (2162L)
+#define GFG_STREAMID7 (2163L)
+#define GFG_STREAMID7_VAL (2164L)
+/* GMF */
+#define GMF_CTRL (2165L)
+#define GMF_CTRL_ENABLE (2166L)
+#define GMF_CTRL_FCS_ALWAYS (2167L)
+#define GMF_CTRL_IFG_AUTO_ADJUST_ENABLE (2168L)
+#define GMF_CTRL_IFG_ENABLE (2169L)
+#define GMF_CTRL_IFG_TX_NOW_ALWAYS (2170L)
+#define GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE (2171L)
+#define GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK (2172L)
+#define GMF_CTRL_IFG_TX_ON_TS_ALWAYS (2173L)
+#define GMF_CTRL_TS_INJECT_ALWAYS (2174L)
+#define GMF_CTRL_TS_INJECT_DUAL_STEP (2175L)
+#define GMF_DEBUG_LANE_MARKER (2176L)
+#define GMF_DEBUG_LANE_MARKER_COMPENSATION (2177L)
+#define GMF_IFG_MAX_ADJUST_SLACK (2178L)
+#define GMF_IFG_MAX_ADJUST_SLACK_SLACK (2179L)
+#define GMF_IFG_SET_CLOCK_DELTA (2180L)
+#define GMF_IFG_SET_CLOCK_DELTA_DELTA (2181L)
+#define GMF_IFG_SET_CLOCK_DELTA_ADJUST (2182L)
+#define GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA (2183L)
+#define GMF_IFG_TX_NOW_ON_TS (2184L)
+#define GMF_IFG_TX_NOW_ON_TS_TS (2185L)
+#define GMF_SPEED (2186L)
+#define GMF_SPEED_IFG_SPEED (2187L)
+#define GMF_STAT (2188L)
+#define GMF_STAT_CTRL_EMPTY (2189L)
+#define GMF_STAT_DATA_CTRL_EMPTY (2190L)
+#define GMF_STAT_SB_EMPTY (2191L)
+#define GMF_STAT_CTRL (2192L)
+#define GMF_STAT_CTRL_FILL_LEVEL (2193L)
+#define GMF_STAT_DATA0 (2194L)
+#define GMF_STAT_DATA0_EMPTY (2195L)
+#define GMF_STAT_DATA1 (2196L)
+#define GMF_STAT_DATA1_EMPTY (2197L)
+#define GMF_STAT_DATA_BUFFER (2198L)
+#define GMF_STAT_DATA_BUFFER_FREE (2199L)
+#define GMF_STAT_DATA_BUFFER_USED (2200L)
+#define GMF_STAT_MAX_DELAYED_PKT (2201L)
+#define GMF_STAT_MAX_DELAYED_PKT_NS (2202L)
+#define GMF_STAT_NEXT_PKT (2203L)
+#define GMF_STAT_NEXT_PKT_NS (2204L)
+#define GMF_STAT_STICKY (2205L)
+#define GMF_STAT_STICKY_DATA_UNDERFLOWED (2206L)
+#define GMF_STAT_STICKY_IFG_ADJUSTED (2207L)
+#define GMF_TS_INJECT (2208L)
+#define GMF_TS_INJECT_OFFSET (2209L)
+#define GMF_TS_INJECT_POS (2210L)
+/* GPIO_PHY */
+#define GPIO_PHY_CFG (2211L)
+#define GPIO_PHY_CFG_E_PORT0_RXLOS (2212L)
+#define GPIO_PHY_CFG_E_PORT1_RXLOS (2213L)
+#define GPIO_PHY_CFG_PORT0_INT_B (2214L)
+#define GPIO_PHY_CFG_PORT0_LPMODE (2215L)
+#define GPIO_PHY_CFG_PORT0_MODPRS_B (2216L)
+#define GPIO_PHY_CFG_PORT0_PLL_INTR (2217L)
+#define GPIO_PHY_CFG_PORT0_RESET_B (2218L)
+#define GPIO_PHY_CFG_PORT1_INT_B (2219L)
+#define GPIO_PHY_CFG_PORT1_LPMODE (2220L)
+#define GPIO_PHY_CFG_PORT1_MODPRS_B (2221L)
+#define GPIO_PHY_CFG_PORT1_PLL_INTR (2222L)
+#define GPIO_PHY_CFG_PORT1_RESET_B (2223L)
+#define GPIO_PHY_GPIO (2224L)
+#define GPIO_PHY_GPIO_E_PORT0_RXLOS (2225L)
+#define GPIO_PHY_GPIO_E_PORT1_RXLOS (2226L)
+#define GPIO_PHY_GPIO_PORT0_INT_B (2227L)
+#define GPIO_PHY_GPIO_PORT0_LPMODE (2228L)
+#define GPIO_PHY_GPIO_PORT0_MODPRS_B (2229L)
+#define GPIO_PHY_GPIO_PORT0_PLL_INTR (2230L)
+#define GPIO_PHY_GPIO_PORT0_RESET_B (2231L)
+#define GPIO_PHY_GPIO_PORT1_INT_B (2232L)
+#define GPIO_PHY_GPIO_PORT1_LPMODE (2233L)
+#define GPIO_PHY_GPIO_PORT1_MODPRS_B (2234L)
+#define GPIO_PHY_GPIO_PORT1_PLL_INTR (2235L)
+#define GPIO_PHY_GPIO_PORT1_RESET_B (2236L)
+/* GPIO_PHY_PORTS */
+#define GPIO_PHY_PORTS_CFG (2237L)
+#define GPIO_PHY_PORTS_CFG_E_PORT0_RXLOS (2238L)
+#define GPIO_PHY_PORTS_CFG_E_PORT0_TXDISABLE (2239L)
+#define GPIO_PHY_PORTS_CFG_E_PORT0_TXFAULT (2240L)
+#define GPIO_PHY_PORTS_CFG_E_PORT1_RXLOS (2241L)
+#define GPIO_PHY_PORTS_CFG_E_PORT1_TXDISABLE (2242L)
+#define GPIO_PHY_PORTS_CFG_E_PORT1_TXFAULT (2243L)
+#define GPIO_PHY_PORTS_CFG_E_PORT2_RXLOS (2244L)
+#define GPIO_PHY_PORTS_CFG_E_PORT2_TXDISABLE (2245L)
+#define GPIO_PHY_PORTS_CFG_E_PORT2_TXFAULT (2246L)
+#define GPIO_PHY_PORTS_CFG_E_PORT3_RXLOS (2247L)
+#define GPIO_PHY_PORTS_CFG_E_PORT3_TXDISABLE (2248L)
+#define GPIO_PHY_PORTS_CFG_E_PORT3_TXFAULT (2249L)
+#define GPIO_PHY_PORTS_CFG_E_PORT4_RXLOS (2250L)
+#define GPIO_PHY_PORTS_CFG_E_PORT4_TXDISABLE (2251L)
+#define GPIO_PHY_PORTS_CFG_E_PORT4_TXFAULT (2252L)
+#define GPIO_PHY_PORTS_CFG_E_PORT5_RXLOS (2253L)
+#define GPIO_PHY_PORTS_CFG_E_PORT5_TXDISABLE (2254L)
+#define GPIO_PHY_PORTS_CFG_E_PORT5_TXFAULT (2255L)
+#define GPIO_PHY_PORTS_CFG_E_PORT6_RXLOS (2256L)
+#define GPIO_PHY_PORTS_CFG_E_PORT6_TXDISABLE (2257L)
+#define GPIO_PHY_PORTS_CFG_E_PORT6_TXFAULT (2258L)
+#define GPIO_PHY_PORTS_CFG_E_PORT7_RXLOS (2259L)
+#define GPIO_PHY_PORTS_CFG_E_PORT7_TXDISABLE (2260L)
+#define GPIO_PHY_PORTS_CFG_E_PORT7_TXFAULT (2261L)
+#define GPIO_PHY_PORTS_GPIO (2262L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT0_RXLOS (2263L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT0_TXDISABLE (2264L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT0_TXFAULT (2265L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT1_RXLOS (2266L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT1_TXDISABLE (2267L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT1_TXFAULT (2268L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT2_RXLOS (2269L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT2_TXDISABLE (2270L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT2_TXFAULT (2271L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT3_RXLOS (2272L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT3_TXDISABLE (2273L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT3_TXFAULT (2274L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT4_RXLOS (2275L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT4_TXDISABLE (2276L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT4_TXFAULT (2277L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT5_RXLOS (2278L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT5_TXDISABLE (2279L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT5_TXFAULT (2280L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT6_RXLOS (2281L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT6_TXDISABLE (2282L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT6_TXFAULT (2283L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT7_RXLOS (2284L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT7_TXDISABLE (2285L)
+#define GPIO_PHY_PORTS_GPIO_E_PORT7_TXFAULT (2286L)
+/* GPIO_SFPP */
+#define GPIO_SFPP_CFG (2287L)
+#define GPIO_SFPP_CFG_ABS (2288L)
+#define GPIO_SFPP_CFG_RS (2289L)
+#define GPIO_SFPP_CFG_RXLOS (2290L)
+#define GPIO_SFPP_CFG_TXDISABLE (2291L)
+#define GPIO_SFPP_CFG_TXFAULT (2292L)
+#define GPIO_SFPP_GPIO (2293L)
+#define GPIO_SFPP_GPIO_ABS (2294L)
+#define GPIO_SFPP_GPIO_RS (2295L)
+#define GPIO_SFPP_GPIO_RXLOS (2296L)
+#define GPIO_SFPP_GPIO_TXDISABLE (2297L)
+#define GPIO_SFPP_GPIO_TXFAULT (2298L)
+/* HFU */
+#define HFU_RCP_CTRL (2381L)
+#define HFU_RCP_CTRL_ADR (2382L)
+#define HFU_RCP_CTRL_CNT (2383L)
+#define HFU_RCP_DATA (2384L)
+#define HFU_RCP_DATA_CSINF (2385L)
+#define HFU_RCP_DATA_IL3OFS (2386L)
+#define HFU_RCP_DATA_IL4OFS (2387L)
+#define HFU_RCP_DATA_L3FRAG (2388L)
+#define HFU_RCP_DATA_L3PRT (2389L)
+#define HFU_RCP_DATA_L4PRT (2390L)
+#define HFU_RCP_DATA_LEN_A_ADD_DYN (2391L)
+#define HFU_RCP_DATA_LEN_A_ADD_OFS (2392L)
+#define HFU_RCP_DATA_LEN_A_OL4LEN (2393L)
+#define HFU_RCP_DATA_LEN_A_POS_DYN (2394L)
+#define HFU_RCP_DATA_LEN_A_POS_OFS (2395L)
+#define HFU_RCP_DATA_LEN_A_SUB_DYN (2396L)
+#define HFU_RCP_DATA_LEN_A_WR (2397L)
+#define HFU_RCP_DATA_LEN_B_ADD_DYN (2398L)
+#define HFU_RCP_DATA_LEN_B_ADD_OFS (2399L)
+#define HFU_RCP_DATA_LEN_B_POS_DYN (2400L)
+#define HFU_RCP_DATA_LEN_B_POS_OFS (2401L)
+#define HFU_RCP_DATA_LEN_B_SUB_DYN (2402L)
+#define HFU_RCP_DATA_LEN_B_WR (2403L)
+#define HFU_RCP_DATA_LEN_C_ADD_DYN (2404L)
+#define HFU_RCP_DATA_LEN_C_ADD_OFS (2405L)
+#define HFU_RCP_DATA_LEN_C_POS_DYN (2406L)
+#define HFU_RCP_DATA_LEN_C_POS_OFS (2407L)
+#define HFU_RCP_DATA_LEN_C_SUB_DYN (2408L)
+#define HFU_RCP_DATA_LEN_C_WR (2409L)
+#define HFU_RCP_DATA_OL3OFS (2410L)
+#define HFU_RCP_DATA_OL4OFS (2411L)
+#define HFU_RCP_DATA_TTL_POS_DYN (2412L)
+#define HFU_RCP_DATA_TTL_POS_OFS (2413L)
+#define HFU_RCP_DATA_TTL_WR (2414L)
+#define HFU_RCP_DATA_TUNNEL (2415L)
+/* HIF */
+#define HIF_BUILD_TIME (2416L)
+#define HIF_BUILD_TIME_TIME (2417L)
+#define HIF_CONFIG (2418L)
+#define HIF_CONFIG_EXT_TAG (2419L)
+#define HIF_CONFIG_MAX_READ (2420L)
+#define HIF_CONFIG_MAX_TLP (2421L)
+#define HIF_CONTROL (2422L)
+#define HIF_CONTROL_BLESSED (2423L)
+#define HIF_CONTROL_WRAW (2424L)
+#define HIF_PROD_ID_EX (2425L)
+#define HIF_PROD_ID_EX_LAYOUT (2426L)
+#define HIF_PROD_ID_EX_LAYOUT_VERSION (2427L)
+#define HIF_PROD_ID_EX_RESERVED (2428L)
+#define HIF_PROD_ID_EXT (2429L)
+#define HIF_PROD_ID_EXT_LAYOUT (2430L)
+#define HIF_PROD_ID_EXT_LAYOUT_VERSION (2431L)
+#define HIF_PROD_ID_EXT_RESERVED (2432L)
+#define HIF_PROD_ID_LSB (2433L)
+#define HIF_PROD_ID_LSB_GROUP_ID (2434L)
+#define HIF_PROD_ID_LSB_REV_ID (2435L)
+#define HIF_PROD_ID_LSB_VER_ID (2436L)
+#define HIF_PROD_ID_MSB (2437L)
+#define HIF_PROD_ID_MSB_BUILD_NO (2438L)
+#define HIF_PROD_ID_MSB_PATCH_NO (2439L)
+#define HIF_PROD_ID_MSB_TYPE_ID (2440L)
+#define HIF_SAMPLE_TIME (2441L)
+#define HIF_SAMPLE_TIME_SAMPLE_TIME (2442L)
+#define HIF_STATUS (2443L)
+#define HIF_STATUS_RD_ERR (2444L)
+#define HIF_STATUS_TAGS_IN_USE (2445L)
+#define HIF_STATUS_WR_ERR (2446L)
+#define HIF_STAT_CTRL (2447L)
+#define HIF_STAT_CTRL_STAT_ENA (2448L)
+#define HIF_STAT_CTRL_STAT_REQ (2449L)
+#define HIF_STAT_REFCLK (2450L)
+#define HIF_STAT_REFCLK_REFCLK250 (2451L)
+#define HIF_STAT_RX (2452L)
+#define HIF_STAT_RX_COUNTER (2453L)
+#define HIF_STAT_TX (2454L)
+#define HIF_STAT_TX_COUNTER (2455L)
+#define HIF_TEST0 (2456L)
+#define HIF_TEST0_DATA (2457L)
+#define HIF_TEST1 (2458L)
+#define HIF_TEST1_DATA (2459L)
+#define HIF_TEST2 (2460L)
+#define HIF_TEST2_DATA (2461L)
+#define HIF_TEST3 (2462L)
+#define HIF_TEST3_DATA (2463L)
+#define HIF_UUID0 (2464L)
+#define HIF_UUID0_UUID0 (2465L)
+#define HIF_UUID1 (2466L)
+#define HIF_UUID1_UUID1 (2467L)
+#define HIF_UUID2 (2468L)
+#define HIF_UUID2_UUID2 (2469L)
+#define HIF_UUID3 (2470L)
+#define HIF_UUID3_UUID3 (2471L)
+/* HSH */
+#define HSH_RCP_CTRL (2472L)
+#define HSH_RCP_CTRL_ADR (2473L)
+#define HSH_RCP_CTRL_CNT (2474L)
+#define HSH_RCP_DATA (2475L)
+#define HSH_RCP_DATA_AUTO_IPV4_MASK (2476L)
+#define HSH_RCP_DATA_HSH_TYPE (2477L)
+#define HSH_RCP_DATA_HSH_VALID (2478L)
+#define HSH_RCP_DATA_K (2479L)
+#define HSH_RCP_DATA_LOAD_DIST_TYPE (2480L)
+#define HSH_RCP_DATA_MAC_PORT_MASK (2481L)
+#define HSH_RCP_DATA_P_MASK (2482L)
+#define HSH_RCP_DATA_QW0_OFS (2483L)
+#define HSH_RCP_DATA_QW0_PE (2484L)
+#define HSH_RCP_DATA_QW4_OFS (2485L)
+#define HSH_RCP_DATA_QW4_PE (2486L)
+#define HSH_RCP_DATA_SEED (2487L)
+#define HSH_RCP_DATA_SORT (2488L)
+#define HSH_RCP_DATA_TNL_P (2489L)
+#define HSH_RCP_DATA_TOEPLITZ (2490L)
+#define HSH_RCP_DATA_W8_OFS (2491L)
+#define HSH_RCP_DATA_W8_PE (2492L)
+#define HSH_RCP_DATA_W8_SORT (2493L)
+#define HSH_RCP_DATA_W9_OFS (2494L)
+#define HSH_RCP_DATA_W9_P (2495L)
+#define HSH_RCP_DATA_W9_PE (2496L)
+#define HSH_RCP_DATA_W9_SORT (2497L)
+#define HSH_RCP_DATA_WORD_MASK (2498L)
+/* HST */
+#define HST_RCP_CTRL (2499L)
+#define HST_RCP_CTRL_ADR (2500L)
+#define HST_RCP_CTRL_CNT (2501L)
+#define HST_RCP_DATA (2502L)
+#define HST_RCP_DATA_END_DYN (2503L)
+#define HST_RCP_DATA_END_OFS (2504L)
+#define HST_RCP_DATA_MODIF0_CMD (2505L)
+#define HST_RCP_DATA_MODIF0_DYN (2506L)
+#define HST_RCP_DATA_MODIF0_OFS (2507L)
+#define HST_RCP_DATA_MODIF0_VALUE (2508L)
+#define HST_RCP_DATA_MODIF1_CMD (2509L)
+#define HST_RCP_DATA_MODIF1_DYN (2510L)
+#define HST_RCP_DATA_MODIF1_OFS (2511L)
+#define HST_RCP_DATA_MODIF1_VALUE (2512L)
+#define HST_RCP_DATA_MODIF2_CMD (2513L)
+#define HST_RCP_DATA_MODIF2_DYN (2514L)
+#define HST_RCP_DATA_MODIF2_OFS (2515L)
+#define HST_RCP_DATA_MODIF2_VALUE (2516L)
+#define HST_RCP_DATA_START_DYN (2517L)
+#define HST_RCP_DATA_START_OFS (2518L)
+#define HST_RCP_DATA_STRIP_MODE (2519L)
+/* ICORE_10G */
+#define ICORE_10G_INDIR_CTRL (2549L)
+#define ICORE_10G_INDIR_CTRL_RD_ENABLE (2550L)
+#define ICORE_10G_INDIR_CTRL_RD_READY (2551L)
+#define ICORE_10G_INDIR_CTRL_SUB_ADDR (2552L)
+#define ICORE_10G_INDIR_DATA (2553L)
+#define ICORE_10G_INDIR_DATA_DATA (2554L)
+#define ICORE_10G_MISC_CTRL (2555L)
+#define ICORE_10G_MISC_CTRL_LINE_LOOP (2556L)
+#define ICORE_10G_MISC_CTRL_LINK_LATENCY (2557L)
+#define ICORE_10G_MISC_CTRL_RES_MAC_RX (2558L)
+#define ICORE_10G_MISC_CTRL_RES_MAC_TX (2559L)
+#define ICORE_10G_MISC_CTRL_SERIAL_LOOP (2560L)
+#define ICORE_10G_MISC_CTRL_SET_LOCK2DATA (2561L)
+#define ICORE_10G_MISC_CTRL_SET_LOCK2REF (2562L)
+#define ICORE_10G_PHY_STATUS (2563L)
+#define ICORE_10G_PHY_STATUS_BLOCK_LOCK (2564L)
+#define ICORE_10G_PHY_STATUS_HI_BER (2565L)
+#define ICORE_10G_PHY_STATUS_HI_BER_CHANGED (2566L)
+#define ICORE_10G_PHY_STATUS_LINK_STATE (2567L)
+#define ICORE_10G_PHY_STATUS_LINK_STATE_CHANGED (2568L)
+#define ICORE_10G_PHY_STATUS_RXCLK_LOCKED (2569L)
+#define ICORE_10G_PHY_STATUS_RXCLK_LOCKED2DATA (2570L)
+#define ICORE_10G_PHY_STATUS_RX_CAL_BUSY (2571L)
+#define ICORE_10G_PHY_STATUS_TXCLK_LOCKED (2572L)
+#define ICORE_10G_PHY_STATUS_TX_CAL_BUSY (2573L)
+#define ICORE_10G_TFG_ADDR (2574L)
+#define ICORE_10G_TFG_ADDR_ADR (2575L)
+#define ICORE_10G_TFG_ADDR_RDENA (2576L)
+#define ICORE_10G_TFG_ADDR_RD_DONE (2577L)
+#define ICORE_10G_TFG_CTRL (2578L)
+#define ICORE_10G_TFG_CTRL_ID_ENA (2579L)
+#define ICORE_10G_TFG_CTRL_ID_POS (2580L)
+#define ICORE_10G_TFG_CTRL_RESTART (2581L)
+#define ICORE_10G_TFG_CTRL_TG_ACT (2582L)
+#define ICORE_10G_TFG_CTRL_TG_ENA (2583L)
+#define ICORE_10G_TFG_CTRL_TIME_MODE (2584L)
+#define ICORE_10G_TFG_CTRL_WRAP (2585L)
+#define ICORE_10G_TFG_DATA (2586L)
+#define ICORE_10G_TFG_DATA_ID (2587L)
+#define ICORE_10G_TFG_DATA_LENGTH (2588L)
+#define ICORE_10G_TFG_FRAME_HDR_0 (2589L)
+#define ICORE_10G_TFG_FRAME_HDR_0_HDR (2590L)
+#define ICORE_10G_TFG_FRAME_HDR_1 (2591L)
+#define ICORE_10G_TFG_FRAME_HDR_1_HDR (2592L)
+#define ICORE_10G_TFG_FRAME_HDR_2 (2593L)
+#define ICORE_10G_TFG_FRAME_HDR_2_HDR (2594L)
+#define ICORE_10G_TFG_FRAME_HDR_3 (2595L)
+#define ICORE_10G_TFG_FRAME_HDR_3_HDR (2596L)
+#define ICORE_10G_TFG_REPETITION (2597L)
+#define ICORE_10G_TFG_REPETITION_CNT (2598L)
+/* IFR */
+#define IFR_RCP_CTRL (2642L)
+#define IFR_RCP_CTRL_ADR (2643L)
+#define IFR_RCP_CTRL_CNT (2644L)
+#define IFR_RCP_DATA (2645L)
+#define IFR_RCP_DATA_EN (2646L)
+#define IFR_RCP_DATA_MTU (2647L)
+/* IIC */
+#define IIC_ADR (2648L)
+#define IIC_ADR_SLV_ADR (2649L)
+#define IIC_CR (2650L)
+#define IIC_CR_EN (2651L)
+#define IIC_CR_GC_EN (2652L)
+#define IIC_CR_MSMS (2653L)
+#define IIC_CR_RST (2654L)
+#define IIC_CR_RSTA (2655L)
+#define IIC_CR_TX (2656L)
+#define IIC_CR_TXAK (2657L)
+#define IIC_CR_TXFIFO_RESET (2658L)
+#define IIC_DGIE (2659L)
+#define IIC_DGIE_GIE (2660L)
+#define IIC_GPO (2661L)
+#define IIC_GPO_GPO_VAL (2662L)
+#define IIC_IER (2663L)
+#define IIC_IER_INT0 (2664L)
+#define IIC_IER_INT1 (2665L)
+#define IIC_IER_INT2 (2666L)
+#define IIC_IER_INT3 (2667L)
+#define IIC_IER_INT4 (2668L)
+#define IIC_IER_INT5 (2669L)
+#define IIC_IER_INT6 (2670L)
+#define IIC_IER_INT7 (2671L)
+#define IIC_ISR (2672L)
+#define IIC_ISR_INT0 (2673L)
+#define IIC_ISR_INT1 (2674L)
+#define IIC_ISR_INT2 (2675L)
+#define IIC_ISR_INT3 (2676L)
+#define IIC_ISR_INT4 (2677L)
+#define IIC_ISR_INT5 (2678L)
+#define IIC_ISR_INT6 (2679L)
+#define IIC_ISR_INT7 (2680L)
+#define IIC_RX_FIFO (2681L)
+#define IIC_RX_FIFO_RXDATA (2682L)
+#define IIC_RX_FIFO_OCY (2683L)
+#define IIC_RX_FIFO_OCY_OCY_VAL (2684L)
+#define IIC_RX_FIFO_PIRQ (2685L)
+#define IIC_RX_FIFO_PIRQ_CMP_VAL (2686L)
+#define IIC_SOFTR (2687L)
+#define IIC_SOFTR_RKEY (2688L)
+#define IIC_SR (2689L)
+#define IIC_SR_AAS (2690L)
+#define IIC_SR_ABGC (2691L)
+#define IIC_SR_BB (2692L)
+#define IIC_SR_RXFIFO_EMPTY (2693L)
+#define IIC_SR_RXFIFO_FULL (2694L)
+#define IIC_SR_SRW (2695L)
+#define IIC_SR_TXFIFO_EMPTY (2696L)
+#define IIC_SR_TXFIFO_FULL (2697L)
+#define IIC_TBUF (2698L)
+#define IIC_TBUF_TBUF_VAL (2699L)
+#define IIC_TEN_ADR (2700L)
+#define IIC_TEN_ADR_MSB_SLV_ADR (2701L)
+#define IIC_THDDAT (2702L)
+#define IIC_THDDAT_THDDAT_VAL (2703L)
+#define IIC_THDSTA (2704L)
+#define IIC_THDSTA_THDSTA_VAL (2705L)
+#define IIC_THIGH (2706L)
+#define IIC_THIGH_THIGH_VAL (2707L)
+#define IIC_TLOW (2708L)
+#define IIC_TLOW_TLOW_VAL (2709L)
+#define IIC_TSUDAT (2710L)
+#define IIC_TSUDAT_TSUDAT_VAL (2711L)
+#define IIC_TSUSTA (2712L)
+#define IIC_TSUSTA_TSUSTA_VAL (2713L)
+#define IIC_TSUSTO (2714L)
+#define IIC_TSUSTO_TSUSTO_VAL (2715L)
+#define IIC_TX_FIFO (2716L)
+#define IIC_TX_FIFO_START (2717L)
+#define IIC_TX_FIFO_STOP (2718L)
+#define IIC_TX_FIFO_TXDATA (2719L)
+#define IIC_TX_FIFO_OCY (2720L)
+#define IIC_TX_FIFO_OCY_OCY_VAL (2721L)
+/* INS */
+#define INS_RCP_CTRL (2722L)
+#define INS_RCP_CTRL_ADR (2723L)
+#define INS_RCP_CTRL_CNT (2724L)
+#define INS_RCP_DATA (2725L)
+#define INS_RCP_DATA_DYN (2726L)
+#define INS_RCP_DATA_LEN (2727L)
+#define INS_RCP_DATA_OFS (2728L)
+/* IOA */
+#define IOA_RECIPE_CTRL (2778L)
+#define IOA_RECIPE_CTRL_ADR (2779L)
+#define IOA_RECIPE_CTRL_CNT (2780L)
+#define IOA_RECIPE_DATA (2781L)
+#define IOA_RECIPE_DATA_QUEUE_ID (2782L)
+#define IOA_RECIPE_DATA_QUEUE_OVERRIDE_EN (2783L)
+#define IOA_RECIPE_DATA_TUNNEL_POP (2784L)
+#define IOA_RECIPE_DATA_VLAN_DEI (2785L)
+#define IOA_RECIPE_DATA_VLAN_PCP (2786L)
+#define IOA_RECIPE_DATA_VLAN_POP (2787L)
+#define IOA_RECIPE_DATA_VLAN_PUSH (2788L)
+#define IOA_RECIPE_DATA_VLAN_TPID_SEL (2789L)
+#define IOA_RECIPE_DATA_VLAN_VID (2790L)
+#define IOA_ROA_EPP_CTRL (2791L)
+#define IOA_ROA_EPP_CTRL_ADR (2792L)
+#define IOA_ROA_EPP_CTRL_CNT (2793L)
+#define IOA_ROA_EPP_DATA (2794L)
+#define IOA_ROA_EPP_DATA_PUSH_TUNNEL (2795L)
+#define IOA_ROA_EPP_DATA_TX_PORT (2796L)
+#define IOA_VLAN_TPID_SPECIAL (2797L)
+#define IOA_VLAN_TPID_SPECIAL_CUSTTPID0 (2798L)
+#define IOA_VLAN_TPID_SPECIAL_CUSTTPID1 (2799L)
+/* IPF */
+#define IPF_CTRL (2800L)
+#define IPF_CTRL_ALL_UNM (2801L)
+#define IPF_CTRL_ALL_UNM_INNER (2802L)
+#define IPF_CTRL_DEL_UNM (2803L)
+#define IPF_CTRL_ENABLE (2804L)
+#define IPF_CTRL_FST_UNM (2805L)
+#define IPF_CTRL_PASSIVE (2806L)
+#define IPF_CTRL_PERSIST (2807L)
+#define IPF_DEBUG (2808L)
+#define IPF_DEBUG_FTF_N (2809L)
+#define IPF_DEBUG_LIMIT_N (2810L)
+#define IPF_EXPIRE (2811L)
+#define IPF_EXPIRE_PERSIST (2812L)
+#define IPF_EXPIRE_T (2813L)
+#define IPF_FTF_DEBUG (2814L)
+#define IPF_FTF_DEBUG_N (2815L)
+#define IPF_RCP_CTRL (2816L)
+#define IPF_RCP_CTRL_ADR (2817L)
+#define IPF_RCP_CTRL_CNT (2818L)
+#define IPF_RCP_DATA (2819L)
+#define IPF_RCP_DATA_ALL_UNM (2820L)
+#define IPF_RCP_DATA_COL_INH (2821L)
+#define IPF_RCP_DATA_DEL_UNM (2822L)
+#define IPF_RCP_DATA_DISC_INH (2823L)
+#define IPF_RCP_DATA_DUP_INH (2824L)
+#define IPF_RCP_DATA_ENABLE (2825L)
+#define IPF_RCP_DATA_FST_UNM (2826L)
+#define IPF_RCP_DATA_GROUP_ID (2827L)
+#define IPF_RCP_DATA_HASH_CENC (2828L)
+#define IPF_RCP_DATA_HSH_INH (2829L)
+#define IPF_RCP_DATA_PORT_GROUP_ID (2830L)
+#define IPF_RCP_DATA_QUEUE_INH (2831L)
+#define IPF_RCP_DATA_UNMQ_HI (2832L)
+#define IPF_RCP_DATA_UNMQ_LO (2833L)
+#define IPF_RCP_DATA_UNM_FLAG_CENC (2834L)
+#define IPF_SIZE_DEBUG (2835L)
+#define IPF_SIZE_DEBUG_N (2836L)
+#define IPF_STAT_MAX1 (2837L)
+#define IPF_STAT_MAX1_N (2838L)
+#define IPF_STAT_MAX2 (2839L)
+#define IPF_STAT_MAX2_N (2840L)
+#define IPF_STAT_MAX3 (2841L)
+#define IPF_STAT_MAX3_N (2842L)
+#define IPF_STAT_MAX4 (2843L)
+#define IPF_STAT_MAX4_N (2844L)
+#define IPF_TIMEOUT (2845L)
+#define IPF_TIMEOUT_T (2846L)
+#define IPF_UNMQ_CTRL (2847L)
+#define IPF_UNMQ_CTRL_ADR (2848L)
+#define IPF_UNMQ_CTRL_CNT (2849L)
+#define IPF_UNMQ_DATA (2850L)
+#define IPF_UNMQ_DATA_CENC (2851L)
+#define IPF_UNMQ_DATA_EN (2852L)
+#define IPF_UNMQ_DATA_ID (2853L)
+#define IPF_UNM_FEED (2854L)
+#define IPF_UNM_FEED_ADDR (2855L)
+#define IPF_UNM_FEED_CNT (2856L)
+#define IPF_UNM_FEED_FEED (2857L)
+#define IPF_UNM_FEED_FEED_VALID (2858L)
+#define IPF_UNM_FEED_RES1 (2859L)
+#define IPF_UNM_FEED_RES2 (2860L)
+#define IPF_UNM_FEED_RES3 (2861L)
+/* KM */
+#define KM_CAM_CTRL (2862L)
+#define KM_CAM_CTRL_ADR (2863L)
+#define KM_CAM_CTRL_CNT (2864L)
+#define KM_CAM_DATA (2865L)
+#define KM_CAM_DATA_FT0 (2866L)
+#define KM_CAM_DATA_FT1 (2867L)
+#define KM_CAM_DATA_FT2 (2868L)
+#define KM_CAM_DATA_FT3 (2869L)
+#define KM_CAM_DATA_FT4 (2870L)
+#define KM_CAM_DATA_FT5 (2871L)
+#define KM_CAM_DATA_W0 (2872L)
+#define KM_CAM_DATA_W1 (2873L)
+#define KM_CAM_DATA_W2 (2874L)
+#define KM_CAM_DATA_W3 (2875L)
+#define KM_CAM_DATA_W4 (2876L)
+#define KM_CAM_DATA_W5 (2877L)
+#define KM_RCP_CTRL (2878L)
+#define KM_RCP_CTRL_ADR (2879L)
+#define KM_RCP_CTRL_CNT (2880L)
+#define KM_RCP_DATA (2881L)
+#define KM_RCP_DATA_BANK_A (2882L)
+#define KM_RCP_DATA_BANK_B (2883L)
+#define KM_RCP_DATA_DUAL (2884L)
+#define KM_RCP_DATA_DW0_B_DYN (2885L)
+#define KM_RCP_DATA_DW0_B_OFS (2886L)
+#define KM_RCP_DATA_DW10_DYN (2887L)
+#define KM_RCP_DATA_DW10_OFS (2888L)
+#define KM_RCP_DATA_DW10_SEL_A (2889L)
+#define KM_RCP_DATA_DW10_SEL_B (2890L)
+#define KM_RCP_DATA_DW2_B_DYN (2891L)
+#define KM_RCP_DATA_DW2_B_OFS (2892L)
+#define KM_RCP_DATA_DW8_B_DYN (2893L)
+#define KM_RCP_DATA_DW8_B_OFS (2894L)
+#define KM_RCP_DATA_DW8_DYN (2895L)
+#define KM_RCP_DATA_DW8_OFS (2896L)
+#define KM_RCP_DATA_DW8_SEL_A (2897L)
+#define KM_RCP_DATA_DW8_SEL_B (2898L)
+#define KM_RCP_DATA_EL_A (2899L)
+#define KM_RCP_DATA_EL_B (2900L)
+#define KM_RCP_DATA_FLOW_SET (2901L)
+#define KM_RCP_DATA_FTM_A (2902L)
+#define KM_RCP_DATA_FTM_B (2903L)
+#define KM_RCP_DATA_INFO_A (2904L)
+#define KM_RCP_DATA_INFO_B (2905L)
+#define KM_RCP_DATA_KEYWAY_A (2906L)
+#define KM_RCP_DATA_KEYWAY_B (2907L)
+#define KM_RCP_DATA_KL_A (2908L)
+#define KM_RCP_DATA_KL_B (2909L)
+#define KM_RCP_DATA_MASK_A (2910L)
+#define KM_RCP_DATA_MASK_B (2911L)
+#define KM_RCP_DATA_PAIRED (2912L)
+#define KM_RCP_DATA_QW0_B_DYN (2913L)
+#define KM_RCP_DATA_QW0_B_OFS (2914L)
+#define KM_RCP_DATA_QW0_DYN (2915L)
+#define KM_RCP_DATA_QW0_OFS (2916L)
+#define KM_RCP_DATA_QW0_SEL_A (2917L)
+#define KM_RCP_DATA_QW0_SEL_B (2918L)
+#define KM_RCP_DATA_QW4_B_DYN (2919L)
+#define KM_RCP_DATA_QW4_B_OFS (2920L)
+#define KM_RCP_DATA_QW4_DYN (2921L)
+#define KM_RCP_DATA_QW4_OFS (2922L)
+#define KM_RCP_DATA_QW4_SEL_A (2923L)
+#define KM_RCP_DATA_QW4_SEL_B (2924L)
+#define KM_RCP_DATA_SW4_B_DYN (2925L)
+#define KM_RCP_DATA_SW4_B_OFS (2926L)
+#define KM_RCP_DATA_SW5_B_DYN (2927L)
+#define KM_RCP_DATA_SW5_B_OFS (2928L)
+#define KM_RCP_DATA_SW8_B_DYN (2929L)
+#define KM_RCP_DATA_SW8_B_OFS (2930L)
+#define KM_RCP_DATA_SW8_DYN (2931L)
+#define KM_RCP_DATA_SW8_OFS (2932L)
+#define KM_RCP_DATA_SW8_SEL_A (2933L)
+#define KM_RCP_DATA_SW8_SEL_B (2934L)
+#define KM_RCP_DATA_SW9_B_DYN (2935L)
+#define KM_RCP_DATA_SW9_B_OFS (2936L)
+#define KM_RCP_DATA_SW9_DYN (2937L)
+#define KM_RCP_DATA_SW9_OFS (2938L)
+#define KM_RCP_DATA_SW9_SEL_A (2939L)
+#define KM_RCP_DATA_SW9_SEL_B (2940L)
+#define KM_RCP_DATA_SWX_CCH (2941L)
+#define KM_RCP_DATA_SWX_OVS_SB (2942L)
+#define KM_RCP_DATA_SWX_SEL_A (2943L)
+#define KM_RCP_DATA_SWX_SEL_B (2944L)
+#define KM_RCP_DATA_SYNERGY_MODE (2945L)
+#define KM_STATUS (2946L)
+#define KM_STATUS_TCQ_RDY (2947L)
+#define KM_TCAM_CTRL (2948L)
+#define KM_TCAM_CTRL_ADR (2949L)
+#define KM_TCAM_CTRL_CNT (2950L)
+#define KM_TCAM_DATA (2951L)
+#define KM_TCAM_DATA_T (2952L)
+#define KM_TCI_CTRL (2953L)
+#define KM_TCI_CTRL_ADR (2954L)
+#define KM_TCI_CTRL_CNT (2955L)
+#define KM_TCI_DATA (2956L)
+#define KM_TCI_DATA_COLOR (2957L)
+#define KM_TCI_DATA_FT (2958L)
+#define KM_TCQ_CTRL (2959L)
+#define KM_TCQ_CTRL_ADR (2960L)
+#define KM_TCQ_CTRL_CNT (2961L)
+#define KM_TCQ_DATA (2962L)
+#define KM_TCQ_DATA_BANK_MASK (2963L)
+#define KM_TCQ_DATA_QUAL (2964L)
+/* LAO */
+/* MAC */
+#define MAC_CONF_SERDES_BITFRAG (2965L)
+#define MAC_CONF_SERDES_BITFRAG_BITFRAG (2966L)
+#define MAC_CONF_SERDES_DELAY (2967L)
+#define MAC_CONF_SERDES_DELAY_DELAY (2968L)
+#define MAC_CONF_SERDES_REORDER (2969L)
+#define MAC_CONF_SERDES_REORDER_REORDER (2970L)
+#define MAC_FAULTY_BLK (2971L)
+#define MAC_FAULTY_BLK_DATA (2972L)
+#define MAC_HOST_STAT_BYTE_FILL (2973L)
+#define MAC_HOST_STAT_BYTE_FILL_CNT (2974L)
+#define MAC_INT (2975L)
+#define MAC_INT_EN (2976L)
+#define MAC_INT_MAX_PACE (2977L)
+#define MAC_LINK_SUMMARY (2978L)
+#define MAC_LINK_SUMMARY_ABS (2979L)
+#define MAC_LINK_SUMMARY_GBOX_INTERR (2980L)
+#define MAC_LINK_SUMMARY_GLB_ALARMN (2981L)
+#define MAC_LINK_SUMMARY_LH_ABS (2982L)
+#define MAC_LINK_SUMMARY_LH_GLB_ALARMN (2983L)
+#define MAC_LINK_SUMMARY_LH_LOCAL_FAULT (2984L)
+#define MAC_LINK_SUMMARY_LH_REMOTE_FAULT (2985L)
+#define MAC_LINK_SUMMARY_LH_RX_LOS (2986L)
+#define MAC_LINK_SUMMARY_LINK_DOWN_CNT (2987L)
+#define MAC_LINK_SUMMARY_LL_PHY_LINK_STATE (2988L)
+#define MAC_LINK_SUMMARY_LOCAL_FAULT (2989L)
+#define MAC_LINK_SUMMARY_NT_PHY_LINK_STATE (2990L)
+#define MAC_LINK_SUMMARY_REMOTE_FAULT (2991L)
+#define MAC_LINK_SUMMARY_RX_LOS (2992L)
+#define MAC_MAC_STAT_BYTE (2993L)
+#define MAC_MAC_STAT_BYTE_CNT (2994L)
+#define MAC_MAC_STAT_CRC (2995L)
+#define MAC_MAC_STAT_CRC_CNT (2996L)
+#define MAC_MAC_STAT_CV (2997L)
+#define MAC_MAC_STAT_CV_CNT (2998L)
+#define MAC_MAC_STAT_FRAME (2999L)
+#define MAC_MAC_STAT_FRAME_CNT (3000L)
+#define MAC_MAC_STAT_MICRO_DROP (3001L)
+#define MAC_MAC_STAT_MICRO_DROP_CNT (3002L)
+#define MAC_MAC_STAT_RATE_DROP (3003L)
+#define MAC_MAC_STAT_RATE_DROP_CNT (3004L)
+#define MAC_MAC_STAT_TRUNC (3005L)
+#define MAC_MAC_STAT_TRUNC_CNT (3006L)
+#define MAC_MDS_CEN_VAL (3007L)
+#define MAC_MDS_CEN_VAL_VAL (3008L)
+#define MAC_MDS_CONF (3009L)
+#define MAC_MDS_CONF_CENTER_REC_ENA (3010L)
+#define MAC_MDS_CONF_CLR_STAT (3011L)
+#define MAC_MDS_CONF_ENA_TS_MOD (3012L)
+#define MAC_MDS_CONF_REC_ENA (3013L)
+#define MAC_MDS_CONF_TIME_MODE (3014L)
+#define MAC_MDS_DATA (3015L)
+#define MAC_MDS_DATA_DATA (3016L)
+#define MAC_MDS_FRAMES (3017L)
+#define MAC_MDS_FRAMES_CNT (3018L)
+#define MAC_MDS_MAX (3019L)
+#define MAC_MDS_MAX_MAX (3020L)
+#define MAC_MDS_MIN (3021L)
+#define MAC_MDS_MIN_MIN (3022L)
+#define MAC_MDS_STAT (3023L)
+#define MAC_MDS_STAT_CLR_BUSY (3024L)
+#define MAC_MDS_STAT_HIT_MAX (3025L)
+#define MAC_MDS_STAT_HIT_MIN (3026L)
+#define MAC_MDS_VAL_REC (3027L)
+#define MAC_MDS_VAL_REC_VALUE (3028L)
+#define MAC_MDS_VAL_REC_FRAME (3029L)
+#define MAC_MDS_VAL_REC_FRAME_VALUE (3030L)
+#define MAC_NT_PORT_CTRL (3031L)
+#define MAC_NT_PORT_CTRL_LED_MODE (3032L)
+#define MAC_RAM_MDS_ADDR (3033L)
+#define MAC_RAM_MDS_ADDR_ADR (3034L)
+#define MAC_RAM_MDS_ADDR_CLR_RAM (3035L)
+#define MAC_RAM_MDS_ADDR_RD_DONE (3036L)
+#define MAC_RAM_MDS_ADDR_RD_ENA (3037L)
+#define MAC_RAW_ADDR (3038L)
+#define MAC_RAW_ADDR_ADR (3039L)
+#define MAC_RAW_ADDR_RDENA (3040L)
+#define MAC_RAW_ADDR_RD_DONE (3041L)
+#define MAC_RAW_CTRL (3042L)
+#define MAC_RAW_CTRL_OVERWR_LM (3043L)
+#define MAC_RAW_CTRL_RESTART (3044L)
+#define MAC_RAW_CTRL_TG_ACT (3045L)
+#define MAC_RAW_CTRL_TG_ENA (3046L)
+#define MAC_RAW_CTRL_WRAP (3047L)
+#define MAC_RAW_DATA (3048L)
+#define MAC_RAW_DATA_RAW_DATA (3049L)
+#define MAC_RAW_REPETITION (3050L)
+#define MAC_RAW_REPETITION_CNT (3051L)
+#define MAC_RX_CONFIG (3052L)
+#define MAC_RX_CONFIG_DESCRAMB (3053L)
+#define MAC_RX_CONFIG_HOST_CLR_CNT (3054L)
+#define MAC_RX_CONFIG_MAC_CLR_CNT (3055L)
+#define MAC_RX_CONFIG_MIN_RX_FRAME (3056L)
+#define MAC_RX_CONFIG_NT_DEBOUNCE_LATENCY (3057L)
+#define MAC_RX_CONFIG_NT_FORCE_LINK_DOWN (3058L)
+#define MAC_RX_CONFIG_NT_LINKUP_LATENCY (3059L)
+#define MAC_RX_CONFIG_RST_BLK_ERR (3060L)
+#define MAC_RX_CONFIG_RX_MAC_EN (3061L)
+#define MAC_RX_CONFIG_TS_EOP (3062L)
+#define MAC_RX_CONFIG_TXRX_LOOP (3063L)
+#define MAC_RX_CONFIG2 (3064L)
+#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_INT (3065L)
+#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_LINK (3066L)
+#define MAC_RX_CONFIG2_NT_MOD_ABS_MASK_RST (3067L)
+#define MAC_RX_CONFIG2_NT_RXLOS_MASK_INT (3068L)
+#define MAC_RX_CONFIG2_NT_RXLOS_MASK_LINK (3069L)
+#define MAC_RX_CONFIG2_NT_RXLOS_MASK_RST (3070L)
+#define MAC_RX_STATUS (3071L)
+#define MAC_RX_STATUS_CORE_MODE (3072L)
+#define MAC_RX_STATUS_LOCAL_FAULT (3073L)
+#define MAC_RX_STATUS_REMOTE_FAULT (3074L)
+#define MAC_RX_STATUS_RXTX_OVERFLOW (3075L)
+#define MAC_RX_STATUS_VERSION (3076L)
+#define MAC_TFG_ADDR (3077L)
+#define MAC_TFG_ADDR_ADR (3078L)
+#define MAC_TFG_ADDR_RDENA (3079L)
+#define MAC_TFG_ADDR_RD_DONE (3080L)
+#define MAC_TFG_CTRL (3081L)
+#define MAC_TFG_CTRL_ID_ENA (3082L)
+#define MAC_TFG_CTRL_ID_POS (3083L)
+#define MAC_TFG_CTRL_RESTART (3084L)
+#define MAC_TFG_CTRL_TG_ACT (3085L)
+#define MAC_TFG_CTRL_TG_ENA (3086L)
+#define MAC_TFG_CTRL_TIME_MODE (3087L)
+#define MAC_TFG_CTRL_WRAP (3088L)
+#define MAC_TFG_DATA (3089L)
+#define MAC_TFG_DATA_GAP (3090L)
+#define MAC_TFG_DATA_ID (3091L)
+#define MAC_TFG_DATA_LENGTH (3092L)
+#define MAC_TFG_FRAME_HDR (3093L)
+#define MAC_TFG_FRAME_HDR_HDR (3094L)
+#define MAC_TFG_REPETITION (3095L)
+#define MAC_TFG_REPETITION_CNT (3096L)
+#define MAC_TX_CONFIG (3097L)
+#define MAC_TX_CONFIG_CLR_STICKY (3098L)
+#define MAC_TX_CONFIG_CRC_ERR_INS (3099L)
+#define MAC_TX_CONFIG_HOST_TX_ENA (3100L)
+#define MAC_TX_CONFIG_MAC_LOOP (3101L)
+#define MAC_TX_CONFIG_PCS_BIP_ERR (3102L)
+#define MAC_TX_CONFIG_PCS_DIS_BIP_INS (3103L)
+#define MAC_TX_CONFIG_PCS_IDLE (3104L)
+#define MAC_TX_CONFIG_PCS_IDLE_DIS (3105L)
+#define MAC_TX_CONFIG_PCS_LOCAL_FAULT (3106L)
+#define MAC_TX_CONFIG_PCS_LOCAL_FAULT_DIS (3107L)
+#define MAC_TX_CONFIG_PCS_REMOTE_FAULT (3108L)
+#define MAC_TX_CONFIG_PCS_REMOTE_FAULT_DIS (3109L)
+#define MAC_TX_CONFIG_PCS_SCRAMB_ENA (3110L)
+#define MAC_TX_CONFIG_PCS_SCRAMB_ERR (3111L)
+#define MAC_TX_CONFIG_TIME_OFFSET_TX (3112L)
+#define MAC_TX_CONFIG_TS_EOP (3113L)
+#define MAC_TX_STATUS (3114L)
+#define MAC_TX_STATUS_PCS_ERR (3115L)
+#define MAC_TX_STATUS_TX_MAC_ST (3116L)
+#define MAC_TX_STATUS_UNDER_FLOW (3117L)
+#define MAC_UPD_RX_COUNTERS (3118L)
+#define MAC_UPD_RX_COUNTERS_TRIGGER (3119L)
+/* MAC10 */
+#define MAC10_CFG_0 (3135L)
+#define MAC10_CFG_0_PAD_ENA (3136L)
+#define MAC10_CFG_0_RX_ENA (3137L)
+#define MAC10_CFG_0_RX_PAUSE_ENA (3138L)
+#define MAC10_CFG_0_STR_ENA (3139L)
+#define MAC10_CFG_0_TX_ENA (3140L)
+#define MAC10_CFG_0_TX_PAUSE_ENA (3141L)
+#define MAC10_MA (3142L)
+#define MAC10_MA_MAC10_ADR_0 (3143L)
+#define MAC10_MA_MAC_ADR_0 (3144L)
+#define MAC10_MA_LO (3145L)
+#define MAC10_MA_LO_MA_LO (3146L)
+#define MAC10_MA_MAX_SIZE (3147L)
+#define MAC10_MA_MAX_SIZE_MAC10_ADR_1 (3148L)
+#define MAC10_MA_MAX_SIZE_MAC_ADR_1 (3149L)
+#define MAC10_MA_MAX_SIZE_MTU (3150L)
+#define MAC10_MA_UP (3151L)
+#define MAC10_MA_UP_MA_UP (3152L)
+#define MAC10_STICKY_XAUI (3153L)
+#define MAC10_STICKY_XAUI_STICKY_XAUI (3154L)
+/* MAC100 */
+#define MAC100_CONF_SERDES_BITFRAG (3155L)
+#define MAC100_CONF_SERDES_BITFRAG_BITFRAG (3156L)
+#define MAC100_CONF_SERDES_DELAY (3157L)
+#define MAC100_CONF_SERDES_DELAY_DELAY (3158L)
+#define MAC100_CONF_SERDES_REORDER (3159L)
+#define MAC100_CONF_SERDES_REORDER_REORDER (3160L)
+#define MAC100_FAULTY_BLK (3161L)
+#define MAC100_FAULTY_BLK_DATA (3162L)
+#define MAC100_HOST_STAT_BYTE (3163L)
+#define MAC100_HOST_STAT_BYTE_CNT (3164L)
+#define MAC100_HOST_STAT_BYTE_FILL (3165L)
+#define MAC100_HOST_STAT_BYTE_FILL_CNT (3166L)
+#define MAC100_HOST_STAT_CRC (3167L)
+#define MAC100_HOST_STAT_CRC_CNT (3168L)
+#define MAC100_HOST_STAT_CV (3169L)
+#define MAC100_HOST_STAT_CV_CNT (3170L)
+#define MAC100_HOST_STAT_DROP (3171L)
+#define MAC100_HOST_STAT_DROP_CNT (3172L)
+#define MAC100_HOST_STAT_DROP_BYTE (3173L)
+#define MAC100_HOST_STAT_DROP_BYTE_CNT (3174L)
+#define MAC100_HOST_STAT_FRAME (3175L)
+#define MAC100_HOST_STAT_FRAME_CNT (3176L)
+#define MAC100_HOST_STAT_FRAME_FILL (3177L)
+#define MAC100_HOST_STAT_FRAME_FILL_CNT (3178L)
+#define MAC100_INT (3179L)
+#define MAC100_INT_EN (3180L)
+#define MAC100_INT_MAX_PACE (3181L)
+#define MAC100_LINK_SUMMARY (3182L)
+#define MAC100_LINK_SUMMARY_ABS (3183L)
+#define MAC100_LINK_SUMMARY_GBOX_INTERR (3184L)
+#define MAC100_LINK_SUMMARY_GLB_ALARMN (3185L)
+#define MAC100_LINK_SUMMARY_LH_ABS (3186L)
+#define MAC100_LINK_SUMMARY_LH_GLB_ALARMN (3187L)
+#define MAC100_LINK_SUMMARY_LH_LOCAL_FAULT (3188L)
+#define MAC100_LINK_SUMMARY_LH_REMOTE_FAULT (3189L)
+#define MAC100_LINK_SUMMARY_LH_RX_LOS (3190L)
+#define MAC100_LINK_SUMMARY_LINK_DOWN_CNT (3191L)
+#define MAC100_LINK_SUMMARY_LL_PHY_LINK_STATE (3192L)
+#define MAC100_LINK_SUMMARY_LOCAL_FAULT (3193L)
+#define MAC100_LINK_SUMMARY_NT_PHY_LINK_STATE (3194L)
+#define MAC100_LINK_SUMMARY_REMOTE_FAULT (3195L)
+#define MAC100_LINK_SUMMARY_RX_LOS (3196L)
+#define MAC100_MAC_STAT_BYTE (3197L)
+#define MAC100_MAC_STAT_BYTE_CNT (3198L)
+#define MAC100_MAC_STAT_CRC (3199L)
+#define MAC100_MAC_STAT_CRC_CNT (3200L)
+#define MAC100_MAC_STAT_CV (3201L)
+#define MAC100_MAC_STAT_CV_CNT (3202L)
+#define MAC100_MAC_STAT_FC (3203L)
+#define MAC100_MAC_STAT_FC_CNT (3204L)
+#define MAC100_MAC_STAT_FRAME (3205L)
+#define MAC100_MAC_STAT_FRAME_CNT (3206L)
+#define MAC100_MAC_STAT_MICRO_DROP (3207L)
+#define MAC100_MAC_STAT_MICRO_DROP_CNT (3208L)
+#define MAC100_MAC_STAT_PAUSE (3209L)
+#define MAC100_MAC_STAT_PAUSE_CNT (3210L)
+#define MAC100_MAC_STAT_RATE_DROP (3211L)
+#define MAC100_MAC_STAT_RATE_DROP_CNT (3212L)
+#define MAC100_MAC_STAT_TRUNC (3213L)
+#define MAC100_MAC_STAT_TRUNC_CNT (3214L)
+#define MAC100_MDS_CEN_VAL (3215L)
+#define MAC100_MDS_CEN_VAL_VAL (3216L)
+#define MAC100_MDS_CONF (3217L)
+#define MAC100_MDS_CONF_CENTER_REC_ENA (3218L)
+#define MAC100_MDS_CONF_CLR_STAT (3219L)
+#define MAC100_MDS_CONF_ENA_TS_MOD (3220L)
+#define MAC100_MDS_CONF_REC_ENA (3221L)
+#define MAC100_MDS_CONF_TIME_MODE (3222L)
+#define MAC100_MDS_DATA (3223L)
+#define MAC100_MDS_DATA_DATA (3224L)
+#define MAC100_MDS_FRAMES (3225L)
+#define MAC100_MDS_FRAMES_CNT (3226L)
+#define MAC100_MDS_MAX (3227L)
+#define MAC100_MDS_MAX_MAX (3228L)
+#define MAC100_MDS_MIN (3229L)
+#define MAC100_MDS_MIN_MIN (3230L)
+#define MAC100_MDS_STAT (3231L)
+#define MAC100_MDS_STAT_CLR_BUSY (3232L)
+#define MAC100_MDS_STAT_HIT_MAX (3233L)
+#define MAC100_MDS_STAT_HIT_MIN (3234L)
+#define MAC100_MDS_VAL_REC (3235L)
+#define MAC100_MDS_VAL_REC_VALUE (3236L)
+#define MAC100_MDS_VAL_REC_FRAME (3237L)
+#define MAC100_MDS_VAL_REC_FRAME_VALUE (3238L)
+#define MAC100_NT_PORT_CTRL (3239L)
+#define MAC100_NT_PORT_CTRL_LED_MODE (3240L)
+#define MAC100_RAM_MDS_ADDR (3241L)
+#define MAC100_RAM_MDS_ADDR_ADR (3242L)
+#define MAC100_RAM_MDS_ADDR_CLR_RAM (3243L)
+#define MAC100_RAM_MDS_ADDR_RD_DONE (3244L)
+#define MAC100_RAM_MDS_ADDR_RD_ENA (3245L)
+#define MAC100_RAW_ADDR (3246L)
+#define MAC100_RAW_ADDR_ADR (3247L)
+#define MAC100_RAW_ADDR_RDENA (3248L)
+#define MAC100_RAW_ADDR_RD_DONE (3249L)
+#define MAC100_RAW_CTRL (3250L)
+#define MAC100_RAW_CTRL_OVERWR_LM (3251L)
+#define MAC100_RAW_CTRL_RESTART (3252L)
+#define MAC100_RAW_CTRL_TG_ACT (3253L)
+#define MAC100_RAW_CTRL_TG_ENA (3254L)
+#define MAC100_RAW_CTRL_WRAP (3255L)
+#define MAC100_RAW_DATA (3256L)
+#define MAC100_RAW_DATA_RAW_DATA (3257L)
+#define MAC100_RAW_REPETITION (3258L)
+#define MAC100_RAW_REPETITION_CNT (3259L)
+#define MAC100_RX_CONFIG (3260L)
+#define MAC100_RX_CONFIG_DESCRAMB (3261L)
+#define MAC100_RX_CONFIG_HADP_RUN_MODE (3262L)
+#define MAC100_RX_CONFIG_HOST_CLR_CNT (3263L)
+#define MAC100_RX_CONFIG_MAC_CLR_CNT (3264L)
+#define MAC100_RX_CONFIG_MIN_RX_FRAME (3265L)
+#define MAC100_RX_CONFIG_NT_DEBOUNCE_LATENCY (3266L)
+#define MAC100_RX_CONFIG_NT_FORCE_LINK_DOWN (3267L)
+#define MAC100_RX_CONFIG_NT_LINKUP_LATENCY (3268L)
+#define MAC100_RX_CONFIG_RST_BLK_ERR (3269L)
+#define MAC100_RX_CONFIG_RX_MAC_EN (3270L)
+#define MAC100_RX_CONFIG_TS_EOP (3271L)
+#define MAC100_RX_CONFIG_TXRX_LOOP (3272L)
+#define MAC100_RX_CONFIG2 (3273L)
+#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_INT (3274L)
+#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_LINK (3275L)
+#define MAC100_RX_CONFIG2_NT_MOD_ABS_MASK_RST (3276L)
+#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_INT (3277L)
+#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_LINK (3278L)
+#define MAC100_RX_CONFIG2_NT_RXLOS_MASK_RST (3279L)
+#define MAC100_RX_STATUS (3280L)
+#define MAC100_RX_STATUS_CORE_MODE (3281L)
+#define MAC100_RX_STATUS_LOCAL_FAULT (3282L)
+#define MAC100_RX_STATUS_REMOTE_FAULT (3283L)
+#define MAC100_RX_STATUS_RXTX_OVERFLOW (3284L)
+#define MAC100_RX_STATUS_VERSION (3285L)
+#define MAC100_TFG_ADDR (3286L)
+#define MAC100_TFG_ADDR_ADR (3287L)
+#define MAC100_TFG_ADDR_RDENA (3288L)
+#define MAC100_TFG_ADDR_RD_DONE (3289L)
+#define MAC100_TFG_CTRL (3290L)
+#define MAC100_TFG_CTRL_ID_ENA (3291L)
+#define MAC100_TFG_CTRL_ID_POS (3292L)
+#define MAC100_TFG_CTRL_RESTART (3293L)
+#define MAC100_TFG_CTRL_TG_ACT (3294L)
+#define MAC100_TFG_CTRL_TG_ENA (3295L)
+#define MAC100_TFG_CTRL_TIME_MODE (3296L)
+#define MAC100_TFG_CTRL_WRAP (3297L)
+#define MAC100_TFG_DATA (3298L)
+#define MAC100_TFG_DATA_GAP (3299L)
+#define MAC100_TFG_DATA_ID (3300L)
+#define MAC100_TFG_DATA_LENGTH (3301L)
+#define MAC100_TFG_FRAME_HDR (3302L)
+#define MAC100_TFG_FRAME_HDR_HDR (3303L)
+#define MAC100_TFG_REPETITION (3304L)
+#define MAC100_TFG_REPETITION_CNT (3305L)
+#define MAC100_TX_CONFIG (3306L)
+#define MAC100_TX_CONFIG_CLR_STICKY (3307L)
+#define MAC100_TX_CONFIG_CRC_ERR_INS (3308L)
+#define MAC100_TX_CONFIG_HADP_LOOP (3309L)
+#define MAC100_TX_CONFIG_HOST_TX_ENA (3310L)
+#define MAC100_TX_CONFIG_MAC_LOOP (3311L)
+#define MAC100_TX_CONFIG_PCS_BIP_ERR (3312L)
+#define MAC100_TX_CONFIG_PCS_DIS_BIP_INS (3313L)
+#define MAC100_TX_CONFIG_PCS_IDLE (3314L)
+#define MAC100_TX_CONFIG_PCS_IDLE_DIS (3315L)
+#define MAC100_TX_CONFIG_PCS_LOCAL_FAULT (3316L)
+#define MAC100_TX_CONFIG_PCS_LOCAL_FAULT_DIS (3317L)
+#define MAC100_TX_CONFIG_PCS_REMOTE_FAULT (3318L)
+#define MAC100_TX_CONFIG_PCS_REMOTE_FAULT_DIS (3319L)
+#define MAC100_TX_CONFIG_PCS_SCRAMB_ENA (3320L)
+#define MAC100_TX_CONFIG_PCS_SCRAMB_ERR (3321L)
+#define MAC100_TX_CONFIG_TIME_OFFSET_TX (3322L)
+#define MAC100_TX_CONFIG_TS_EOP (3323L)
+#define MAC100_TX_STATUS (3324L)
+#define MAC100_TX_STATUS_PCS_ERR (3325L)
+#define MAC100_TX_STATUS_TX_HADP_ST (3326L)
+#define MAC100_TX_STATUS_TX_MAC_ST (3327L)
+#define MAC100_TX_STATUS_UNDER_FLOW (3328L)
+#define MAC100_UPD_RX_COUNTERS (3329L)
+#define MAC100_UPD_RX_COUNTERS_TRIGGER (3330L)
+/* MAC10G */
+#define MAC10G_CFG (3331L)
+#define MAC10G_CFG_MIN_RX_FRAME (3332L)
+#define MAC10G_CFG_RX_ENA (3333L)
+#define MAC10G_CFG_RX_EOP_TS (3334L)
+#define MAC10G_CFG_RX_PAUSE_ENA (3335L)
+#define MAC10G_CFG_STR_ENA (3336L)
+#define MAC10G_CFG_TX_ENA (3337L)
+#define MAC10G_CFG_TX_PAUSE_ENA (3338L)
+#define MAC10G_MA_LO (3339L)
+#define MAC10G_MA_LO_MA_LO (3340L)
+#define MAC10G_MA_UP (3341L)
+#define MAC10G_MA_UP_MA_UP (3342L)
+/* MAC1G */
+#define MAC1G_CFG (3343L)
+#define MAC1G_CFG_MIN_RX_FRAME (3344L)
+#define MAC1G_CFG_RX_ENA (3345L)
+#define MAC1G_CFG_RX_EOP_TS (3346L)
+#define MAC1G_CFG_RX_PAUSE_ENA (3347L)
+#define MAC1G_CFG_SPEED (3348L)
+#define MAC1G_CFG_STR_ENA (3349L)
+#define MAC1G_CFG_TX_ENA (3350L)
+#define MAC1G_CFG_TX_PAUSE_ENA (3351L)
+#define MAC1G_MA_LO (3352L)
+#define MAC1G_MA_LO_MA_LO (3353L)
+#define MAC1G_MA_UP (3354L)
+#define MAC1G_MA_UP_MA_UP (3355L)
+/* MAC_PCS */
+#define MAC_PCS_BAD_CODE (3366L)
+#define MAC_PCS_BAD_CODE_CODE_ERR (3367L)
+#define MAC_PCS_BIP_ERR (3368L)
+#define MAC_PCS_BIP_ERR_BIP_ERR (3369L)
+#define MAC_PCS_BLOCK_LOCK (3370L)
+#define MAC_PCS_BLOCK_LOCK_LOCK (3371L)
+#define MAC_PCS_BLOCK_LOCK_CHG (3372L)
+#define MAC_PCS_BLOCK_LOCK_CHG_LOCK_CHG (3373L)
+#define MAC_PCS_CLKRX_FRQ (3374L)
+#define MAC_PCS_CLKRX_FRQ_RX_FREQ (3375L)
+#define MAC_PCS_CLKTX_FRQ (3376L)
+#define MAC_PCS_CLKTX_FRQ_TX_FREQ (3377L)
+#define MAC_PCS_DEBOUNCE_CTRL (3378L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_DEBOUNCE_LATENCY (3379L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_FORCE_LINK_DOWN (3380L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_LINKUP_LATENCY (3381L)
+#define MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL (3382L)
+#define MAC_PCS_DRP_CONFIG (3383L)
+#define MAC_PCS_DRP_CONFIG_DRP_ADR (3384L)
+#define MAC_PCS_DRP_CONFIG_DRP_DI (3385L)
+#define MAC_PCS_DRP_CONFIG_DRP_EN (3386L)
+#define MAC_PCS_DRP_CONFIG_DRP_MOD_ADR (3387L)
+#define MAC_PCS_DRP_CONFIG_DRP_WREN (3388L)
+#define MAC_PCS_DRP_CTRL (3389L)
+#define MAC_PCS_DRP_CTRL_ADR (3390L)
+#define MAC_PCS_DRP_CTRL_DATA (3391L)
+#define MAC_PCS_DRP_CTRL_DBG_BUSY (3392L)
+#define MAC_PCS_DRP_CTRL_DONE (3393L)
+#define MAC_PCS_DRP_CTRL_MOD_ADR (3394L)
+#define MAC_PCS_DRP_CTRL_WREN (3395L)
+#define MAC_PCS_DRP_DATA (3396L)
+#define MAC_PCS_DRP_DATA_DRP_DO (3397L)
+#define MAC_PCS_DRP_DATA_DRP_RDY (3398L)
+#define MAC_PCS_FEC_CTRL (3399L)
+#define MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN (3400L)
+#define MAC_PCS_FEC_CW_CNT (3401L)
+#define MAC_PCS_FEC_CW_CNT_CW_CNT (3402L)
+#define MAC_PCS_FEC_ERR_CNT_0 (3403L)
+#define MAC_PCS_FEC_ERR_CNT_0_ERR_CNT (3404L)
+#define MAC_PCS_FEC_ERR_CNT_1 (3405L)
+#define MAC_PCS_FEC_ERR_CNT_1_ERR_CNT (3406L)
+#define MAC_PCS_FEC_ERR_CNT_2 (3407L)
+#define MAC_PCS_FEC_ERR_CNT_2_ERR_CNT (3408L)
+#define MAC_PCS_FEC_ERR_CNT_3 (3409L)
+#define MAC_PCS_FEC_ERR_CNT_3_ERR_CNT (3410L)
+#define MAC_PCS_FEC_LANE_DLY_0 (3411L)
+#define MAC_PCS_FEC_LANE_DLY_0_DLY (3412L)
+#define MAC_PCS_FEC_LANE_DLY_1 (3413L)
+#define MAC_PCS_FEC_LANE_DLY_1_DLY (3414L)
+#define MAC_PCS_FEC_LANE_DLY_2 (3415L)
+#define MAC_PCS_FEC_LANE_DLY_2_DLY (3416L)
+#define MAC_PCS_FEC_LANE_DLY_3 (3417L)
+#define MAC_PCS_FEC_LANE_DLY_3_DLY (3418L)
+#define MAC_PCS_FEC_LANE_MAP (3419L)
+#define MAC_PCS_FEC_LANE_MAP_MAPPING (3420L)
+#define MAC_PCS_FEC_STAT (3421L)
+#define MAC_PCS_FEC_STAT_AM_LOCK (3422L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_0 (3423L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_1 (3424L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_2 (3425L)
+#define MAC_PCS_FEC_STAT_AM_LOCK_3 (3426L)
+#define MAC_PCS_FEC_STAT_BLOCK_LOCK (3427L)
+#define MAC_PCS_FEC_STAT_BYPASS (3428L)
+#define MAC_PCS_FEC_STAT_FEC_LANE_ALGN (3429L)
+#define MAC_PCS_FEC_STAT_HI_SER (3430L)
+#define MAC_PCS_FEC_STAT_PCS_LANE_ALGN (3431L)
+#define MAC_PCS_FEC_STAT_VALID (3432L)
+#define MAC_PCS_FEC_UCW_CNT (3433L)
+#define MAC_PCS_FEC_UCW_CNT_UCW_CNT (3434L)
+#define MAC_PCS_FRAMING_ERR (3435L)
+#define MAC_PCS_FRAMING_ERR_FRAMING_ERR (3436L)
+#define MAC_PCS_GTY_CTL (3437L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_0 (3438L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_1 (3439L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_2 (3440L)
+#define MAC_PCS_GTY_CTL_CDR_HOLD_3 (3441L)
+#define MAC_PCS_GTY_CTL_RX (3442L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_0 (3443L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_1 (3444L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_2 (3445L)
+#define MAC_PCS_GTY_CTL_RX_CDR_HOLD_3 (3446L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_0 (3447L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_1 (3448L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_2 (3449L)
+#define MAC_PCS_GTY_CTL_RX_EQUA_RST_3 (3450L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_0 (3451L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_1 (3452L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_2 (3453L)
+#define MAC_PCS_GTY_CTL_RX_LPM_EN_3 (3454L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_0 (3455L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_1 (3456L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_2 (3457L)
+#define MAC_PCS_GTY_CTL_RX_POLARITY_3 (3458L)
+#define MAC_PCS_GTY_CTL_RX_RATE_0 (3459L)
+#define MAC_PCS_GTY_CTL_RX_RATE_1 (3460L)
+#define MAC_PCS_GTY_CTL_RX_RATE_2 (3461L)
+#define MAC_PCS_GTY_CTL_RX_RATE_3 (3462L)
+#define MAC_PCS_GTY_CTL_TX (3463L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_0 (3464L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_1 (3465L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_2 (3466L)
+#define MAC_PCS_GTY_CTL_TX_INHIBIT_3 (3467L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_0 (3468L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_1 (3469L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_2 (3470L)
+#define MAC_PCS_GTY_CTL_TX_POLARITY_3 (3471L)
+#define MAC_PCS_GTY_DIFF_CTL (3472L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0 (3473L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1 (3474L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2 (3475L)
+#define MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3 (3476L)
+#define MAC_PCS_GTY_LOOP (3477L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_0 (3478L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_1 (3479L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_2 (3480L)
+#define MAC_PCS_GTY_LOOP_GT_LOOP_3 (3481L)
+#define MAC_PCS_GTY_POST_CURSOR (3482L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0 (3483L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1 (3484L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2 (3485L)
+#define MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3 (3486L)
+#define MAC_PCS_GTY_PRBS_SEL (3487L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_0 (3488L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_1 (3489L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_2 (3490L)
+#define MAC_PCS_GTY_PRBS_SEL_RX_PRBS_SEL_3 (3491L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_0 (3492L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_1 (3493L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_2 (3494L)
+#define MAC_PCS_GTY_PRBS_SEL_TX_PRBS_SEL_3 (3495L)
+#define MAC_PCS_GTY_PRE_CURSOR (3496L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0 (3497L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1 (3498L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2 (3499L)
+#define MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3 (3500L)
+#define MAC_PCS_GTY_RX_BUF_STAT (3501L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0 (3502L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1 (3503L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2 (3504L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3 (3505L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0 (3506L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1 (3507L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2 (3508L)
+#define MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3 (3509L)
+#define MAC_PCS_GTY_SCAN_CTL (3510L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_0 (3511L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_1 (3512L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_2 (3513L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_RST_3 (3514L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_0 (3515L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_1 (3516L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_2 (3517L)
+#define MAC_PCS_GTY_SCAN_CTL_EYE_SCAN_TRG_3 (3518L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_0 (3519L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_1 (3520L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_2 (3521L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_ERR_INS_3 (3522L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_0 (3523L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_1 (3524L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_2 (3525L)
+#define MAC_PCS_GTY_SCAN_CTL_PRBS_RST_3 (3526L)
+#define MAC_PCS_GTY_SCAN_STAT (3527L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_0 (3528L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_1 (3529L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_2 (3530L)
+#define MAC_PCS_GTY_SCAN_STAT_EYE_SCAN_ERR_3 (3531L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_0 (3532L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_1 (3533L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_2 (3534L)
+#define MAC_PCS_GTY_SCAN_STAT_PRBS_ERR_3 (3535L)
+#define MAC_PCS_GTY_STAT (3536L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_0 (3537L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_1 (3538L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_2 (3539L)
+#define MAC_PCS_GTY_STAT_RX_RST_DONE_3 (3540L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_0 (3541L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_1 (3542L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_2 (3543L)
+#define MAC_PCS_GTY_STAT_TX_BUF_STAT_3 (3544L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_0 (3545L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_1 (3546L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_2 (3547L)
+#define MAC_PCS_GTY_STAT_TX_RST_DONE_3 (3548L)
+#define MAC_PCS_LANE_ALIGNER_FILL (3549L)
+#define MAC_PCS_LANE_ALIGNER_FILL_FILL (3550L)
+#define MAC_PCS_LINK_SUMMARY (3551L)
+#define MAC_PCS_LINK_SUMMARY_ABS (3552L)
+#define MAC_PCS_LINK_SUMMARY_LH_ABS (3553L)
+#define MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT (3554L)
+#define MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT (3555L)
+#define MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT (3556L)
+#define MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE (3557L)
+#define MAC_PCS_LINK_SUMMARY_LOCAL_FAULT (3558L)
+#define MAC_PCS_LINK_SUMMARY_NIM_INTERR (3559L)
+#define MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE (3560L)
+#define MAC_PCS_LINK_SUMMARY_REMOTE_FAULT (3561L)
+#define MAC_PCS_LINK_SUMMARY_RESERVED (3562L)
+#define MAC_PCS_MAC_PCS_CONFIG (3563L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_CORE_RST (3564L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE (3565L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC (3566L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST (3567L)
+#define MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN (3568L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_CORE_RST (3569L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE (3570L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_FCS_REMOVE (3571L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST (3572L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE (3573L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI (3574L)
+#define MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN (3575L)
+#define MAC_PCS_MAX_PKT_LEN (3576L)
+#define MAC_PCS_MAX_PKT_LEN_MAX_LEN (3577L)
+#define MAC_PCS_MF_ERR (3578L)
+#define MAC_PCS_MF_ERR_MF_ERR (3579L)
+#define MAC_PCS_MF_LEN_ERR (3580L)
+#define MAC_PCS_MF_LEN_ERR_MF_LEN_ERR (3581L)
+#define MAC_PCS_MF_REPEAT_ERR (3582L)
+#define MAC_PCS_MF_REPEAT_ERR_MF_REPEAT_ERR (3583L)
+#define MAC_PCS_PHYMAC_MISC (3584L)
+#define MAC_PCS_PHYMAC_MISC_TS_EOP (3585L)
+#define MAC_PCS_PHYMAC_MISC_TX_MUX_STATE (3586L)
+#define MAC_PCS_PHYMAC_MISC_TX_SEL_HOST (3587L)
+#define MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP (3588L)
+#define MAC_PCS_PHYMAC_MISC_TX_SEL_TFG (3589L)
+#define MAC_PCS_PHY_STAT (3590L)
+#define MAC_PCS_PHY_STAT_ALARM (3591L)
+#define MAC_PCS_PHY_STAT_MOD_PRS (3592L)
+#define MAC_PCS_PHY_STAT_RX_LOS (3593L)
+#define MAC_PCS_STAT_PCS_RX (3594L)
+#define MAC_PCS_STAT_PCS_RX_ALIGNED (3595L)
+#define MAC_PCS_STAT_PCS_RX_ALIGNED_ERR (3596L)
+#define MAC_PCS_STAT_PCS_RX_GOT_SIGNAL_OS (3597L)
+#define MAC_PCS_STAT_PCS_RX_HI_BER (3598L)
+#define MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT (3599L)
+#define MAC_PCS_STAT_PCS_RX_LOCAL_FAULT (3600L)
+#define MAC_PCS_STAT_PCS_RX_MISALIGNED (3601L)
+#define MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT (3602L)
+#define MAC_PCS_STAT_PCS_RX_REMOTE_FAULT (3603L)
+#define MAC_PCS_STAT_PCS_RX_STATUS (3604L)
+#define MAC_PCS_STAT_PCS_RX_LATCH (3605L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED (3606L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_ALIGNED_ERR (3607L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_GOT_SIGNAL_OS (3608L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_HI_BER (3609L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_INTERNAL_LOCAL_FAULT (3610L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_LOCAL_FAULT (3611L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_MISALIGNED (3612L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_RECEIVED_LOCAL_FAULT (3613L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_REMOTE_FAULT (3614L)
+#define MAC_PCS_STAT_PCS_RX_LATCH_STATUS (3615L)
+#define MAC_PCS_STAT_PCS_TX (3616L)
+#define MAC_PCS_STAT_PCS_TX_LOCAL_FAULT (3617L)
+#define MAC_PCS_STAT_PCS_TX_LOCAL_FAULT_CHANGED (3618L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR (3619L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_READ_ERROR_CHANGED (3620L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR (3621L)
+#define MAC_PCS_STAT_PCS_TX_PTP_FIFO_WRITE_ERROR_CHANGED (3622L)
+#define MAC_PCS_STAT_PCS_TX_TX_OVFOUT (3623L)
+#define MAC_PCS_STAT_PCS_TX_TX_OVFOUT_CHANGED (3624L)
+#define MAC_PCS_STAT_PCS_TX_TX_UNFOUT (3625L)
+#define MAC_PCS_STAT_PCS_TX_TX_UNFOUT_CHANGED (3626L)
+#define MAC_PCS_SYNCED (3627L)
+#define MAC_PCS_SYNCED_SYNC (3628L)
+#define MAC_PCS_SYNCED_ERR (3629L)
+#define MAC_PCS_SYNCED_ERR_SYNC_ERROR (3630L)
+#define MAC_PCS_TEST_ERR (3631L)
+#define MAC_PCS_TEST_ERR_CODE_ERR (3632L)
+#define MAC_PCS_TIMESTAMP_COMP (3633L)
+#define MAC_PCS_TIMESTAMP_COMP_RX_DLY (3634L)
+#define MAC_PCS_TIMESTAMP_COMP_TX_DLY (3635L)
+#define MAC_PCS_VL_DEMUXED (3636L)
+#define MAC_PCS_VL_DEMUXED_LOCK (3637L)
+#define MAC_PCS_VL_DEMUXED_CHG (3638L)
+#define MAC_PCS_VL_DEMUXED_CHG_LOCK_CHG (3639L)
+#define MAC_PCS_VL_NUMBER (3640L)
+#define MAC_PCS_VL_NUMBER_VL_NUMBER (3641L)
+/* MAC_PCS_XXV */
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0 (3642L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_ASMDIR (3643L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_BYPASS (3644L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_ENABLE (3645L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_PAUSE (3646L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_0_RESTART (3647L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1 (3648L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_ASMDIR (3649L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_BYPASS (3650L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_ENABLE (3651L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_PAUSE (3652L)
+#define MAC_PCS_XXV_ANEG_1G_CONFIG_1_RESTART (3653L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0 (3654L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_COMPLETE (3655L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_ANEG_ABLE (3656L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_ASM (3657L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_PAUSE (3658L)
+#define MAC_PCS_XXV_ANEG_1G_STA_0_LP_RF (3659L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1 (3660L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_COMPLETE (3661L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_ANEG_ABLE (3662L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_ASM (3663L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_PAUSE (3664L)
+#define MAC_PCS_XXV_ANEG_1G_STA_1_LP_RF (3665L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0 (3666L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR (3667L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1 (3668L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S (3669L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR (3670L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1 (3671L)
+#define MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S (3672L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1 (3673L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR (3674L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1 (3675L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S (3676L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR (3677L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1 (3678L)
+#define MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S (3679L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2 (3680L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR (3681L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR1 (3682L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_BASE25G_CR_S (3683L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR (3684L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1 (3685L)
+#define MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S (3686L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3 (3687L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR (3688L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR1 (3689L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_BASE25G_CR_S (3690L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR (3691L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1 (3692L)
+#define MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S (3693L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0 (3694L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR (3695L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS (3696L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE (3697L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST (3698L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G (3699L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY (3700L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST (3701L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74 (3702L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED (3703L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE (3704L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO (3705L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT (3706L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_RESTART (3707L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST (3708L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE (3709L)
+#define MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE (3710L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1 (3711L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR (3712L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS (3713L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE (3714L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST (3715L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G (3716L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY (3717L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST (3718L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74 (3719L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED (3720L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE (3721L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO (3722L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT (3723L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_RESTART (3724L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST (3725L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE (3726L)
+#define MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE (3727L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2 (3728L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR (3729L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS (3730L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE (3731L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST (3732L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G (3733L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY (3734L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST (3735L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74 (3736L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED (3737L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE (3738L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO (3739L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT (3740L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_RESTART (3741L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST (3742L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE (3743L)
+#define MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE (3744L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3 (3745L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR (3746L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS (3747L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE (3748L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST (3749L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G (3750L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY (3751L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST (3752L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74 (3753L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED (3754L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE (3755L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO (3756L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT (3757L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_RESTART (3758L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST (3759L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE (3760L)
+#define MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE (3761L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0 (3762L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_ANEG_END (3763L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_ANEG_STARTED (3764L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_CDR_HOLD (3765L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_LT_END (3766L)
+#define MAC_PCS_XXV_ANEG_DEBUG_0_LT_STARTED (3767L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1 (3768L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_ANEG_END (3769L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_ANEG_STARTED (3770L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_CDR_HOLD (3771L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_LT_END (3772L)
+#define MAC_PCS_XXV_ANEG_DEBUG_1_LT_STARTED (3773L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2 (3774L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_ANEG_END (3775L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_ANEG_STARTED (3776L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_CDR_HOLD (3777L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_LT_END (3778L)
+#define MAC_PCS_XXV_ANEG_DEBUG_2_LT_STARTED (3779L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3 (3780L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_ANEG_END (3781L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_ANEG_STARTED (3782L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_CDR_HOLD (3783L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_LT_END (3784L)
+#define MAC_PCS_XXV_ANEG_DEBUG_3_LT_STARTED (3785L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0 (3786L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR (3787L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR1 (3788L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_0_LINK_CR_S (3789L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1 (3790L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR (3791L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR1 (3792L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_1_LINK_CR_S (3793L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2 (3794L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR (3795L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR1 (3796L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_2_LINK_CR_S (3797L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3 (3798L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR (3799L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR1 (3800L)
+#define MAC_PCS_XXV_ANEG_LINK_STA_3_LINK_CR_S (3801L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0 (3802L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0_LP_25GBASE_CR (3803L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_0_LP_25GBASE_CR_S (3804L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1 (3805L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1_LP_25GBASE_CR (3806L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_1_LP_25GBASE_CR_S (3807L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2 (3808L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2_LP_25GBASE_CR (3809L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_2_LP_25GBASE_CR_S (3810L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3 (3811L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3_LP_25GBASE_CR (3812L)
+#define MAC_PCS_XXV_ANEG_LP_ABILITIES_3_LP_25GBASE_CR_S (3813L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0 (3814L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC74_ABILITY (3815L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC74_REQUEST (3816L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC91_ABILITY (3817L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_C_FEC91_REQUEST (3818L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_LP_25GBASE_CR1 (3819L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_0_LP_EX_ABILITY_VALID (3820L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1 (3821L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC74_ABILITY (3822L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC74_REQUEST (3823L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC91_ABILITY (3824L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_C_FEC91_REQUEST (3825L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_LP_25GBASE_CR1 (3826L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_1_LP_EX_ABILITY_VALID (3827L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2 (3828L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC74_ABILITY (3829L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC74_REQUEST (3830L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC91_ABILITY (3831L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_C_FEC91_REQUEST (3832L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_LP_25GBASE_CR1 (3833L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_2_LP_EX_ABILITY_VALID (3834L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3 (3835L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC74_ABILITY (3836L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC74_REQUEST (3837L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC91_ABILITY (3838L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_C_FEC91_REQUEST (3839L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_LP_25GBASE_CR1 (3840L)
+#define MAC_PCS_XXV_ANEG_LP_EX_ABILITIES_3_LP_EX_ABILITY_VALID (3841L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0 (3842L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ABILITY_VALID (3843L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ANEG_ABLE (3844L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_ASM (3845L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_FEC74_REQ (3846L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_PAUSE (3847L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_RF (3848L)
+#define MAC_PCS_XXV_ANEG_LP_STA_0_LP_RS_FEC_REQ (3849L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1 (3850L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ABILITY_VALID (3851L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ANEG_ABLE (3852L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_ASM (3853L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_FEC74_REQ (3854L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_PAUSE (3855L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_RF (3856L)
+#define MAC_PCS_XXV_ANEG_LP_STA_1_LP_RS_FEC_REQ (3857L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2 (3858L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ABILITY_VALID (3859L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ANEG_ABLE (3860L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_ASM (3861L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_FEC74_REQ (3862L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_PAUSE (3863L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_RF (3864L)
+#define MAC_PCS_XXV_ANEG_LP_STA_2_LP_RS_FEC_REQ (3865L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3 (3866L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ABILITY_VALID (3867L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ANEG_ABLE (3868L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_ASM (3869L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_FEC74_REQ (3870L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_PAUSE (3871L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_RF (3872L)
+#define MAC_PCS_XXV_ANEG_LP_STA_3_LP_RS_FEC_REQ (3873L)
+#define MAC_PCS_XXV_ANEG_STA_0 (3874L)
+#define MAC_PCS_XXV_ANEG_STA_0_COMPLETE (3875L)
+#define MAC_PCS_XXV_ANEG_STA_0_FEC74_EN (3876L)
+#define MAC_PCS_XXV_ANEG_STA_0_PAR_D_FAULT (3877L)
+#define MAC_PCS_XXV_ANEG_STA_0_RS_FEC_EN (3878L)
+#define MAC_PCS_XXV_ANEG_STA_0_RX_PAUSE_EN (3879L)
+#define MAC_PCS_XXV_ANEG_STA_0_TX_PAUSE_EN (3880L)
+#define MAC_PCS_XXV_ANEG_STA_1 (3881L)
+#define MAC_PCS_XXV_ANEG_STA_1_COMPLETE (3882L)
+#define MAC_PCS_XXV_ANEG_STA_1_FEC74_EN (3883L)
+#define MAC_PCS_XXV_ANEG_STA_1_PAR_D_FAULT (3884L)
+#define MAC_PCS_XXV_ANEG_STA_1_RS_FEC_EN (3885L)
+#define MAC_PCS_XXV_ANEG_STA_1_RX_PAUSE_EN (3886L)
+#define MAC_PCS_XXV_ANEG_STA_1_TX_PAUSE_EN (3887L)
+#define MAC_PCS_XXV_ANEG_STA_2 (3888L)
+#define MAC_PCS_XXV_ANEG_STA_2_COMPLETE (3889L)
+#define MAC_PCS_XXV_ANEG_STA_2_FEC74_EN (3890L)
+#define MAC_PCS_XXV_ANEG_STA_2_PAR_D_FAULT (3891L)
+#define MAC_PCS_XXV_ANEG_STA_2_RS_FEC_EN (3892L)
+#define MAC_PCS_XXV_ANEG_STA_2_RX_PAUSE_EN (3893L)
+#define MAC_PCS_XXV_ANEG_STA_2_TX_PAUSE_EN (3894L)
+#define MAC_PCS_XXV_ANEG_STA_3 (3895L)
+#define MAC_PCS_XXV_ANEG_STA_3_COMPLETE (3896L)
+#define MAC_PCS_XXV_ANEG_STA_3_FEC74_EN (3897L)
+#define MAC_PCS_XXV_ANEG_STA_3_PAR_D_FAULT (3898L)
+#define MAC_PCS_XXV_ANEG_STA_3_RS_FEC_EN (3899L)
+#define MAC_PCS_XXV_ANEG_STA_3_RX_PAUSE_EN (3900L)
+#define MAC_PCS_XXV_ANEG_STA_3_TX_PAUSE_EN (3901L)
+#define MAC_PCS_XXV_CLK_REF_ACTIVITY (3902L)
+#define MAC_PCS_XXV_CLK_REF_ACTIVITY_COUNT (3903L)
+#define MAC_PCS_XXV_CORE_CONF_0 (3904L)
+#define MAC_PCS_XXV_CORE_CONF_0_ENHANCED_TS (3905L)
+#define MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE (3906L)
+#define MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK (3907L)
+#define MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE (3908L)
+#define MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC (3909L)
+#define MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP (3910L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE (3911L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS (3912L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS (3913L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE (3914L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI (3915L)
+#define MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI (3916L)
+#define MAC_PCS_XXV_CORE_CONF_1 (3917L)
+#define MAC_PCS_XXV_CORE_CONF_1_ENHANCED_TS (3918L)
+#define MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE (3919L)
+#define MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK (3920L)
+#define MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE (3921L)
+#define MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC (3922L)
+#define MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP (3923L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE (3924L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS (3925L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS (3926L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE (3927L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI (3928L)
+#define MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI (3929L)
+#define MAC_PCS_XXV_CORE_CONF_2 (3930L)
+#define MAC_PCS_XXV_CORE_CONF_2_ENHANCED_TS (3931L)
+#define MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE (3932L)
+#define MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK (3933L)
+#define MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE (3934L)
+#define MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC (3935L)
+#define MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP (3936L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE (3937L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS (3938L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS (3939L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE (3940L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI (3941L)
+#define MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI (3942L)
+#define MAC_PCS_XXV_CORE_CONF_3 (3943L)
+#define MAC_PCS_XXV_CORE_CONF_3_ENHANCED_TS (3944L)
+#define MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE (3945L)
+#define MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK (3946L)
+#define MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE (3947L)
+#define MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC (3948L)
+#define MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP (3949L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE (3950L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS (3951L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS (3952L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE (3953L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI (3954L)
+#define MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI (3955L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0 (3956L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_DEBOUNCE_LATENCY (3957L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_FORCE_LINK_DOWN (3958L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_LINKUP_LATENCY (3959L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL (3960L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1 (3961L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_DEBOUNCE_LATENCY (3962L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_FORCE_LINK_DOWN (3963L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_LINKUP_LATENCY (3964L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL (3965L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2 (3966L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_DEBOUNCE_LATENCY (3967L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_FORCE_LINK_DOWN (3968L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_LINKUP_LATENCY (3969L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL (3970L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3 (3971L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_DEBOUNCE_LATENCY (3972L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_FORCE_LINK_DOWN (3973L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_LINKUP_LATENCY (3974L)
+#define MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL (3975L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_0 (3976L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_0_FEC74_CCW_CNT (3977L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_1 (3978L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_1_FEC74_CCW_CNT (3979L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_2 (3980L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_2_FEC74_CCW_CNT (3981L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_3 (3982L)
+#define MAC_PCS_XXV_FEC74_CCW_CNT_3_FEC74_CCW_CNT (3983L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0 (3984L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0_FEC74_ERRORS_TO_PCS (3985L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0_RX_FEC74_ENABLE (3986L)
+#define MAC_PCS_XXV_FEC74_CONFIG_0_TX_FEC74_ENABLE (3987L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1 (3988L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1_FEC74_ERRORS_TO_PCS (3989L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1_RX_FEC74_ENABLE (3990L)
+#define MAC_PCS_XXV_FEC74_CONFIG_1_TX_FEC74_ENABLE (3991L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2 (3992L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2_FEC74_ERRORS_TO_PCS (3993L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2_RX_FEC74_ENABLE (3994L)
+#define MAC_PCS_XXV_FEC74_CONFIG_2_TX_FEC74_ENABLE (3995L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3 (3996L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3_FEC74_ERRORS_TO_PCS (3997L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3_RX_FEC74_ENABLE (3998L)
+#define MAC_PCS_XXV_FEC74_CONFIG_3_TX_FEC74_ENABLE (3999L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_0 (4000L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_0_FEC74_UCW_CNT (4001L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_1 (4002L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_1_FEC74_UCW_CNT (4003L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_2 (4004L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_2_FEC74_UCW_CNT (4005L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_3 (4006L)
+#define MAC_PCS_XXV_FEC74_UCW_CNT_3_FEC74_UCW_CNT (4007L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0 (4008L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_CDR_HOLD (4009L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST (4010L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN (4011L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY (4012L)
+#define MAC_PCS_XXV_GTY_CTL_RX_0_RATE (4013L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1 (4014L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_CDR_HOLD (4015L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST (4016L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN (4017L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY (4018L)
+#define MAC_PCS_XXV_GTY_CTL_RX_1_RATE (4019L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2 (4020L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_CDR_HOLD (4021L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST (4022L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN (4023L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY (4024L)
+#define MAC_PCS_XXV_GTY_CTL_RX_2_RATE (4025L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3 (4026L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_CDR_HOLD (4027L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST (4028L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN (4029L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY (4030L)
+#define MAC_PCS_XXV_GTY_CTL_RX_3_RATE (4031L)
+#define MAC_PCS_XXV_GTY_CTL_TX_0 (4032L)
+#define MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT (4033L)
+#define MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY (4034L)
+#define MAC_PCS_XXV_GTY_CTL_TX_1 (4035L)
+#define MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT (4036L)
+#define MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY (4037L)
+#define MAC_PCS_XXV_GTY_CTL_TX_2 (4038L)
+#define MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT (4039L)
+#define MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY (4040L)
+#define MAC_PCS_XXV_GTY_CTL_TX_3 (4041L)
+#define MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT (4042L)
+#define MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY (4043L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_0 (4044L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL (4045L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL_ADJUSTED (4046L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_1 (4047L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL (4048L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL_ADJUSTED (4049L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_2 (4050L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL (4051L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL_ADJUSTED (4052L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_3 (4053L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL (4054L)
+#define MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL_ADJUSTED (4055L)
+#define MAC_PCS_XXV_GTY_LOOP_0 (4056L)
+#define MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP (4057L)
+#define MAC_PCS_XXV_GTY_LOOP_1 (4058L)
+#define MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP (4059L)
+#define MAC_PCS_XXV_GTY_LOOP_2 (4060L)
+#define MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP (4061L)
+#define MAC_PCS_XXV_GTY_LOOP_3 (4062L)
+#define MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP (4063L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_0 (4064L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_0_TX_MAIN_CTL (4065L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_1 (4066L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_1_TX_MAIN_CTL (4067L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_2 (4068L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_2_TX_MAIN_CTL (4069L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_3 (4070L)
+#define MAC_PCS_XXV_GTY_MAIN_CTL_3_TX_MAIN_CTL (4071L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_0 (4072L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR (4073L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR_ADJUSTED (4074L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_1 (4075L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR (4076L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR_ADJUSTED (4077L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_2 (4078L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR (4079L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR_ADJUSTED (4080L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_3 (4081L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR (4082L)
+#define MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR_ADJUSTED (4083L)
+#define MAC_PCS_XXV_GTY_PRBS_0 (4084L)
+#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_ERR (4085L)
+#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_ERR_INS (4086L)
+#define MAC_PCS_XXV_GTY_PRBS_0_PRBS_RST (4087L)
+#define MAC_PCS_XXV_GTY_PRBS_0_RX_PRBS_SEL (4088L)
+#define MAC_PCS_XXV_GTY_PRBS_0_TX_PRBS_SEL (4089L)
+#define MAC_PCS_XXV_GTY_PRBS_1 (4090L)
+#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_ERR (4091L)
+#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_ERR_INS (4092L)
+#define MAC_PCS_XXV_GTY_PRBS_1_PRBS_RST (4093L)
+#define MAC_PCS_XXV_GTY_PRBS_1_RX_PRBS_SEL (4094L)
+#define MAC_PCS_XXV_GTY_PRBS_1_TX_PRBS_SEL (4095L)
+#define MAC_PCS_XXV_GTY_PRBS_2 (4096L)
+#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_ERR (4097L)
+#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_ERR_INS (4098L)
+#define MAC_PCS_XXV_GTY_PRBS_2_PRBS_RST (4099L)
+#define MAC_PCS_XXV_GTY_PRBS_2_RX_PRBS_SEL (4100L)
+#define MAC_PCS_XXV_GTY_PRBS_2_TX_PRBS_SEL (4101L)
+#define MAC_PCS_XXV_GTY_PRBS_3 (4102L)
+#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_ERR (4103L)
+#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_ERR_INS (4104L)
+#define MAC_PCS_XXV_GTY_PRBS_3_PRBS_RST (4105L)
+#define MAC_PCS_XXV_GTY_PRBS_3_RX_PRBS_SEL (4106L)
+#define MAC_PCS_XXV_GTY_PRBS_3_TX_PRBS_SEL (4107L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_0 (4108L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_0_COUNT (4109L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_1 (4110L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_1_COUNT (4111L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_2 (4112L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_2_COUNT (4113L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_3 (4114L)
+#define MAC_PCS_XXV_GTY_PRBS_CNT_3_COUNT (4115L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_0 (4116L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR (4117L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR_ADJUSTED (4118L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_1 (4119L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR (4120L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR_ADJUSTED (4121L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_2 (4122L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR (4123L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR_ADJUSTED (4124L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_3 (4125L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR (4126L)
+#define MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR_ADJUSTED (4127L)
+#define MAC_PCS_XXV_GTY_STATUS_0 (4128L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_POWERGOOD (4129L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_RXBUFSTATUS (4130L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_STARTOFSEQ (4131L)
+#define MAC_PCS_XXV_GTY_STATUS_0_GT_TXBUFSTATUS (4132L)
+#define MAC_PCS_XXV_GTY_STATUS_1 (4133L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_POWERGOOD (4134L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_RXBUFSTATUS (4135L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_STARTOFSEQ (4136L)
+#define MAC_PCS_XXV_GTY_STATUS_1_GT_TXBUFSTATUS (4137L)
+#define MAC_PCS_XXV_GTY_STATUS_2 (4138L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_POWERGOOD (4139L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_RXBUFSTATUS (4140L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_STARTOFSEQ (4141L)
+#define MAC_PCS_XXV_GTY_STATUS_2_GT_TXBUFSTATUS (4142L)
+#define MAC_PCS_XXV_GTY_STATUS_3 (4143L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_POWERGOOD (4144L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_RXBUFSTATUS (4145L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_STARTOFSEQ (4146L)
+#define MAC_PCS_XXV_GTY_STATUS_3_GT_TXBUFSTATUS (4147L)
+#define MAC_PCS_XXV_LATENCY_0 (4148L)
+#define MAC_PCS_XXV_LATENCY_0_RX_LATENCY_MEAS (4149L)
+#define MAC_PCS_XXV_LATENCY_1 (4150L)
+#define MAC_PCS_XXV_LATENCY_1_RX_LATENCY_MEAS (4151L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0 (4152L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_MAIN (4153L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_POST (4154L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_DEC_PRE (4155L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_MAIN (4156L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_POST (4157L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INC_PRE (4158L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_INIT (4159L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_0_PRESET (4160L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1 (4161L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_MAIN (4162L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_POST (4163L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_DEC_PRE (4164L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_MAIN (4165L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_POST (4166L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INC_PRE (4167L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_INIT (4168L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_1_PRESET (4169L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2 (4170L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_MAIN (4171L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_POST (4172L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_DEC_PRE (4173L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_MAIN (4174L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_POST (4175L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INC_PRE (4176L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_INIT (4177L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_2_PRESET (4178L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3 (4179L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_MAIN (4180L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_POST (4181L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_DEC_PRE (4182L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_MAIN (4183L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_POST (4184L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INC_PRE (4185L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_INIT (4186L)
+#define MAC_PCS_XXV_LE_LT_COEF_RECEIVED_3_PRESET (4187L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0 (4188L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0_MAIN_STA (4189L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0_POST_STA (4190L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_0_PRE_STA (4191L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1 (4192L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1_MAIN_STA (4193L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1_POST_STA (4194L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_1_PRE_STA (4195L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2 (4196L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2_MAIN_STA (4197L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2_POST_STA (4198L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_2_PRE_STA (4199L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3 (4200L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3_MAIN_STA (4201L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3_POST_STA (4202L)
+#define MAC_PCS_XXV_LE_LT_STA_SEND_3_PRE_STA (4203L)
+#define MAC_PCS_XXV_LINK_SPEED_0 (4204L)
+#define MAC_PCS_XXV_LINK_SPEED_0_10G (4205L)
+#define MAC_PCS_XXV_LINK_SPEED_0_SPEED (4206L)
+#define MAC_PCS_XXV_LINK_SPEED_0_TOGGLE (4207L)
+#define MAC_PCS_XXV_LINK_SPEED_1 (4208L)
+#define MAC_PCS_XXV_LINK_SPEED_1_10G (4209L)
+#define MAC_PCS_XXV_LINK_SPEED_1_SPEED (4210L)
+#define MAC_PCS_XXV_LINK_SPEED_1_TOGGLE (4211L)
+#define MAC_PCS_XXV_LINK_SPEED_2 (4212L)
+#define MAC_PCS_XXV_LINK_SPEED_2_10G (4213L)
+#define MAC_PCS_XXV_LINK_SPEED_2_SPEED (4214L)
+#define MAC_PCS_XXV_LINK_SPEED_2_TOGGLE (4215L)
+#define MAC_PCS_XXV_LINK_SPEED_3 (4216L)
+#define MAC_PCS_XXV_LINK_SPEED_3_10G (4217L)
+#define MAC_PCS_XXV_LINK_SPEED_3_SPEED (4218L)
+#define MAC_PCS_XXV_LINK_SPEED_3_TOGGLE (4219L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0 (4220L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_ABS (4221L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_ANEG_COMPLETE (4222L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_ANEG_CONSORTIUM_MISMATCH (4223L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_INTERNAL_LOCAL_FAULT (4224L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS (4225L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT (4226L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT (4227L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT (4228L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT (4229L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_FEC74_LOCK_ERROR (4230L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE (4231L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE (4232L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER (4233L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_TX_LOCAL_FAULT (4234L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LH_TX_UNDERRUN (4235L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT (4236L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE (4237L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK (4238L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK (4239L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT (4240L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT (4241L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_LT_DONE (4242L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR (4243L)
+#define MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE (4244L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1 (4245L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_ABS (4246L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_ANEG_COMPLETE (4247L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_ANEG_CONSORTIUM_MISMATCH (4248L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_INTERNAL_LOCAL_FAULT (4249L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS (4250L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT (4251L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT (4252L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT (4253L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT (4254L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_FEC74_LOCK_ERROR (4255L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE (4256L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE (4257L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER (4258L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_TX_LOCAL_FAULT (4259L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LH_TX_UNDERRUN (4260L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT (4261L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE (4262L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK (4263L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK (4264L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT (4265L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT (4266L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_LT_DONE (4267L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR (4268L)
+#define MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE (4269L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2 (4270L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_ABS (4271L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_ANEG_COMPLETE (4272L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_ANEG_CONSORTIUM_MISMATCH (4273L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_INTERNAL_LOCAL_FAULT (4274L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS (4275L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT (4276L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT (4277L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT (4278L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT (4279L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_FEC74_LOCK_ERROR (4280L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE (4281L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE (4282L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER (4283L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_TX_LOCAL_FAULT (4284L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LH_TX_UNDERRUN (4285L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT (4286L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE (4287L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK (4288L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK (4289L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT (4290L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT (4291L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_LT_DONE (4292L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR (4293L)
+#define MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE (4294L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3 (4295L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_ABS (4296L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_ANEG_COMPLETE (4297L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_ANEG_CONSORTIUM_MISMATCH (4298L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_INTERNAL_LOCAL_FAULT (4299L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS (4300L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT (4301L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT (4302L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT (4303L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT (4304L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_FEC74_LOCK_ERROR (4305L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE (4306L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE (4307L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER (4308L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_TX_LOCAL_FAULT (4309L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LH_TX_UNDERRUN (4310L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT (4311L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE (4312L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK (4313L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK (4314L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT (4315L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT (4316L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_LT_DONE (4317L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR (4318L)
+#define MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE (4319L)
+#define MAC_PCS_XXV_LT_CONF_0 (4320L)
+#define MAC_PCS_XXV_LT_CONF_0_ENABLE (4321L)
+#define MAC_PCS_XXV_LT_CONF_0_RESTART (4322L)
+#define MAC_PCS_XXV_LT_CONF_0_SEED (4323L)
+#define MAC_PCS_XXV_LT_CONF_1 (4324L)
+#define MAC_PCS_XXV_LT_CONF_1_ENABLE (4325L)
+#define MAC_PCS_XXV_LT_CONF_1_RESTART (4326L)
+#define MAC_PCS_XXV_LT_CONF_1_SEED (4327L)
+#define MAC_PCS_XXV_LT_CONF_2 (4328L)
+#define MAC_PCS_XXV_LT_CONF_2_ENABLE (4329L)
+#define MAC_PCS_XXV_LT_CONF_2_RESTART (4330L)
+#define MAC_PCS_XXV_LT_CONF_2_SEED (4331L)
+#define MAC_PCS_XXV_LT_CONF_3 (4332L)
+#define MAC_PCS_XXV_LT_CONF_3_ENABLE (4333L)
+#define MAC_PCS_XXV_LT_CONF_3_RESTART (4334L)
+#define MAC_PCS_XXV_LT_CONF_3_SEED (4335L)
+#define MAC_PCS_XXV_LT_STA_0 (4336L)
+#define MAC_PCS_XXV_LT_STA_0_DONE (4337L)
+#define MAC_PCS_XXV_LT_STA_0_FAIL (4338L)
+#define MAC_PCS_XXV_LT_STA_0_LOCK (4339L)
+#define MAC_PCS_XXV_LT_STA_0_TRAIN (4340L)
+#define MAC_PCS_XXV_LT_STA_1 (4341L)
+#define MAC_PCS_XXV_LT_STA_1_DONE (4342L)
+#define MAC_PCS_XXV_LT_STA_1_FAIL (4343L)
+#define MAC_PCS_XXV_LT_STA_1_LOCK (4344L)
+#define MAC_PCS_XXV_LT_STA_1_TRAIN (4345L)
+#define MAC_PCS_XXV_LT_STA_2 (4346L)
+#define MAC_PCS_XXV_LT_STA_2_DONE (4347L)
+#define MAC_PCS_XXV_LT_STA_2_FAIL (4348L)
+#define MAC_PCS_XXV_LT_STA_2_LOCK (4349L)
+#define MAC_PCS_XXV_LT_STA_2_TRAIN (4350L)
+#define MAC_PCS_XXV_LT_STA_3 (4351L)
+#define MAC_PCS_XXV_LT_STA_3_DONE (4352L)
+#define MAC_PCS_XXV_LT_STA_3_FAIL (4353L)
+#define MAC_PCS_XXV_LT_STA_3_LOCK (4354L)
+#define MAC_PCS_XXV_LT_STA_3_TRAIN (4355L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0 (4356L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0_ATTRIB (4357L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0_NEXT (4358L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_0_PREV (4359L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1 (4360L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1_ATTRIB (4361L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1_NEXT (4362L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_1_PREV (4363L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2 (4364L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2_ATTRIB (4365L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2_NEXT (4366L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_2_PREV (4367L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3 (4368L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3_ATTRIB (4369L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3_NEXT (4370L)
+#define MAC_PCS_XXV_LT_TABLE_READBACK_3_PREV (4371L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0 (4372L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_ATTRIB (4373L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_NEXT (4374L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_PREV (4375L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_SEL (4376L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_TABLE_ADDR (4377L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_0_UPDATE (4378L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1 (4379L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_ATTRIB (4380L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_NEXT (4381L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_PREV (4382L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_SEL (4383L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_TABLE_ADDR (4384L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_1_UPDATE (4385L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2 (4386L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_ATTRIB (4387L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_NEXT (4388L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_PREV (4389L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_SEL (4390L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_TABLE_ADDR (4391L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_2_UPDATE (4392L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3 (4393L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_ATTRIB (4394L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_NEXT (4395L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_PREV (4396L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_SEL (4397L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_TABLE_ADDR (4398L)
+#define MAC_PCS_XXV_LT_UPDATE_COEF_TABLE_3_UPDATE (4399L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_0 (4400L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_0_RX_MAX_LENGTH (4401L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_1 (4402L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_1_RX_MAX_LENGTH (4403L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_2 (4404L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_2_RX_MAX_LENGTH (4405L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_3 (4406L)
+#define MAC_PCS_XXV_MAC_RX_MAX_LENGTH_3_RX_MAX_LENGTH (4407L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0 (4408L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0_MIN_RX_FRAME (4409L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_0_RX_MIN_LENGTH (4410L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1 (4411L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1_MIN_RX_FRAME (4412L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_1_RX_MIN_LENGTH (4413L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2 (4414L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2_MIN_RX_FRAME (4415L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_2_RX_MIN_LENGTH (4416L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3 (4417L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3_MIN_RX_FRAME (4418L)
+#define MAC_PCS_XXV_MAC_RX_MIN_LENGTH_3_RX_MIN_LENGTH (4419L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_0 (4420L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_0_MAX_LEN (4421L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_1 (4422L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_1_MAX_LEN (4423L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_2 (4424L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_2_MAX_LEN (4425L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_3 (4426L)
+#define MAC_PCS_XXV_MAX_PKT_LEN_3_MAX_LEN (4427L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0 (4428L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_MAIN (4429L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_POST (4430L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ADJ_PRE (4431L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_ENABLE (4432L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_INIT (4433L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_PRESET (4434L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_0_RX_READY (4435L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1 (4436L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_MAIN (4437L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_POST (4438L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ADJ_PRE (4439L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_ENABLE (4440L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_INIT (4441L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_PRESET (4442L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_1_RX_READY (4443L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2 (4444L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_MAIN (4445L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_POST (4446L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ADJ_PRE (4447L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_ENABLE (4448L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_INIT (4449L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_PRESET (4450L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_2_RX_READY (4451L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3 (4452L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_MAIN (4453L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_POST (4454L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ADJ_PRE (4455L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_ENABLE (4456L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_INIT (4457L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_PRESET (4458L)
+#define MAC_PCS_XXV_RE_LT_COEF_TO_TX_3_RX_READY (4459L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0 (4460L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_MAIN_STA (4461L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_POST_STA (4462L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_0_PRE_STA (4463L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1 (4464L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_MAIN_STA (4465L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_POST_STA (4466L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_1_PRE_STA (4467L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2 (4468L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_MAIN_STA (4469L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_POST_STA (4470L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_2_PRE_STA (4471L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3 (4472L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_MAIN_STA (4473L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_POST_STA (4474L)
+#define MAC_PCS_XXV_RE_LT_STA_RECEIVED_3_PRE_STA (4475L)
+#define MAC_PCS_XXV_RST_0 (4476L)
+#define MAC_PCS_XXV_RST_0_MAC_PCS (4477L)
+#define MAC_PCS_XXV_RST_1 (4478L)
+#define MAC_PCS_XXV_RST_1_MAC_PCS (4479L)
+#define MAC_PCS_XXV_RST_2 (4480L)
+#define MAC_PCS_XXV_RST_2_MAC_PCS (4481L)
+#define MAC_PCS_XXV_RST_3 (4482L)
+#define MAC_PCS_XXV_RST_3_MAC_PCS (4483L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_0 (4484L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT (4485L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_1 (4486L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT (4487L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_2 (4488L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT (4489L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_3 (4490L)
+#define MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT (4491L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0 (4492L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_CONSORTIUM (4493L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_CORRECTION (4494L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE (4495L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_IEEE_ERROR_INDICATION (4496L)
+#define MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_INDICATION (4497L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1 (4498L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_CONSORTIUM (4499L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_CORRECTION (4500L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE (4501L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_IEEE_ERROR_INDICATION (4502L)
+#define MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_INDICATION (4503L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2 (4504L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_CONSORTIUM (4505L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_CORRECTION (4506L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE (4507L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_IEEE_ERROR_INDICATION (4508L)
+#define MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_INDICATION (4509L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3 (4510L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_CONSORTIUM (4511L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_CORRECTION (4512L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE (4513L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_IEEE_ERROR_INDICATION (4514L)
+#define MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_INDICATION (4515L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_0 (4516L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_0_RS_FEC_ERR_CNT (4517L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_1 (4518L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_1_RS_FEC_ERR_CNT (4519L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_2 (4520L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_2_RS_FEC_ERR_CNT (4521L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_3 (4522L)
+#define MAC_PCS_XXV_RS_FEC_ERR_CNT_3_RS_FEC_ERR_CNT (4523L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_0 (4524L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT (4525L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_1 (4526L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT (4527L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_2 (4528L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT (4529L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_3 (4530L)
+#define MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT (4531L)
+#define MAC_PCS_XXV_RX_BAD_FCS_0 (4532L)
+#define MAC_PCS_XXV_RX_BAD_FCS_0_COUNT (4533L)
+#define MAC_PCS_XXV_RX_BAD_FCS_1 (4534L)
+#define MAC_PCS_XXV_RX_BAD_FCS_1_COUNT (4535L)
+#define MAC_PCS_XXV_RX_BAD_FCS_2 (4536L)
+#define MAC_PCS_XXV_RX_BAD_FCS_2_COUNT (4537L)
+#define MAC_PCS_XXV_RX_BAD_FCS_3 (4538L)
+#define MAC_PCS_XXV_RX_BAD_FCS_3_COUNT (4539L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_0 (4540L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_0_COUNT (4541L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_1 (4542L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_1_COUNT (4543L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_2 (4544L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_2_COUNT (4545L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_3 (4546L)
+#define MAC_PCS_XXV_RX_FRAMING_ERROR_3_COUNT (4547L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_0 (4548L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_0_COUNT (4549L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_1 (4550L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_1_COUNT (4551L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_2 (4552L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_2_COUNT (4553L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_3 (4554L)
+#define MAC_PCS_XXV_RX_GOOD_BYTES_3_COUNT (4555L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_0 (4556L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_0_COUNT (4557L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_1 (4558L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_1_COUNT (4559L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_2 (4560L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_2_COUNT (4561L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_3 (4562L)
+#define MAC_PCS_XXV_RX_GOOD_PACKETS_3_COUNT (4563L)
+#define MAC_PCS_XXV_RX_LATENCY_0 (4564L)
+#define MAC_PCS_XXV_RX_LATENCY_0_LATENCY (4565L)
+#define MAC_PCS_XXV_RX_LATENCY_1 (4566L)
+#define MAC_PCS_XXV_RX_LATENCY_1_LATENCY (4567L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_0 (4568L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_0_COUNT (4569L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_1 (4570L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_1_COUNT (4571L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_2 (4572L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_2_COUNT (4573L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_3 (4574L)
+#define MAC_PCS_XXV_RX_TOTAL_BYTES_3_COUNT (4575L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_0 (4576L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_0_COUNT (4577L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_1 (4578L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_1_COUNT (4579L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_2 (4580L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_2_COUNT (4581L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_3 (4582L)
+#define MAC_PCS_XXV_RX_TOTAL_PACKETS_3_COUNT (4583L)
+#define MAC_PCS_XXV_SUB_RST_0 (4584L)
+#define MAC_PCS_XXV_SUB_RST_0_AN_LT (4585L)
+#define MAC_PCS_XXV_SUB_RST_0_QPLL (4586L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_BUF (4587L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA (4588L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS (4589L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_PCS (4590L)
+#define MAC_PCS_XXV_SUB_RST_0_RX_PMA (4591L)
+#define MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL (4592L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA (4593L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS (4594L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_PCS (4595L)
+#define MAC_PCS_XXV_SUB_RST_0_TX_PMA (4596L)
+#define MAC_PCS_XXV_SUB_RST_1 (4597L)
+#define MAC_PCS_XXV_SUB_RST_1_AN_LT (4598L)
+#define MAC_PCS_XXV_SUB_RST_1_QPLL (4599L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_BUF (4600L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA (4601L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS (4602L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_PCS (4603L)
+#define MAC_PCS_XXV_SUB_RST_1_RX_PMA (4604L)
+#define MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL (4605L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA (4606L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS (4607L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_PCS (4608L)
+#define MAC_PCS_XXV_SUB_RST_1_TX_PMA (4609L)
+#define MAC_PCS_XXV_SUB_RST_2 (4610L)
+#define MAC_PCS_XXV_SUB_RST_2_AN_LT (4611L)
+#define MAC_PCS_XXV_SUB_RST_2_QPLL (4612L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_BUF (4613L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA (4614L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS (4615L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_PCS (4616L)
+#define MAC_PCS_XXV_SUB_RST_2_RX_PMA (4617L)
+#define MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL (4618L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA (4619L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS (4620L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_PCS (4621L)
+#define MAC_PCS_XXV_SUB_RST_2_TX_PMA (4622L)
+#define MAC_PCS_XXV_SUB_RST_3 (4623L)
+#define MAC_PCS_XXV_SUB_RST_3_AN_LT (4624L)
+#define MAC_PCS_XXV_SUB_RST_3_QPLL (4625L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_BUF (4626L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA (4627L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS (4628L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_PCS (4629L)
+#define MAC_PCS_XXV_SUB_RST_3_RX_PMA (4630L)
+#define MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL (4631L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA (4632L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS (4633L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_PCS (4634L)
+#define MAC_PCS_XXV_SUB_RST_3_TX_PMA (4635L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0 (4636L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK (4637L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST (4638L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST (4639L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1 (4640L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK (4641L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST (4642L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST (4643L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2 (4644L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK (4645L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST (4646L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST (4647L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3 (4648L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK (4649L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST (4650L)
+#define MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST (4651L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_0 (4652L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY (4653L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY (4654L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_1 (4655L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY (4656L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY (4657L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_2 (4658L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY (4659L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY (4660L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_3 (4661L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY (4662L)
+#define MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY (4663L)
+#define MAC_PCS_XXV_TX_BAD_FCS_0 (4664L)
+#define MAC_PCS_XXV_TX_BAD_FCS_0_COUNT (4665L)
+#define MAC_PCS_XXV_TX_BAD_FCS_1 (4666L)
+#define MAC_PCS_XXV_TX_BAD_FCS_1_COUNT (4667L)
+#define MAC_PCS_XXV_TX_BAD_FCS_2 (4668L)
+#define MAC_PCS_XXV_TX_BAD_FCS_2_COUNT (4669L)
+#define MAC_PCS_XXV_TX_BAD_FCS_3 (4670L)
+#define MAC_PCS_XXV_TX_BAD_FCS_3_COUNT (4671L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_0 (4672L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_0_COUNT (4673L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_1 (4674L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_1_COUNT (4675L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_2 (4676L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_2_COUNT (4677L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_3 (4678L)
+#define MAC_PCS_XXV_TX_FRAME_ERROR_3_COUNT (4679L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_0 (4680L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_0_COUNT (4681L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_1 (4682L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_1_COUNT (4683L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_2 (4684L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_2_COUNT (4685L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_3 (4686L)
+#define MAC_PCS_XXV_TX_GOOD_BYTES_3_COUNT (4687L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_0 (4688L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_0_COUNT (4689L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_1 (4690L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_1_COUNT (4691L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_2 (4692L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_2_COUNT (4693L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_3 (4694L)
+#define MAC_PCS_XXV_TX_GOOD_PACKETS_3_COUNT (4695L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_0 (4696L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_0_COUNT (4697L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_1 (4698L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_1_COUNT (4699L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_2 (4700L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_2_COUNT (4701L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_3 (4702L)
+#define MAC_PCS_XXV_TX_TOTAL_BYTES_3_COUNT (4703L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_0 (4704L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_0_COUNT (4705L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_1 (4706L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_1_COUNT (4707L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_2 (4708L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_2_COUNT (4709L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_3 (4710L)
+#define MAC_PCS_XXV_TX_TOTAL_PACKETS_3_COUNT (4711L)
+/* MAC_RX */
+#define MAC_RX_BAD_FCS (4712L)
+#define MAC_RX_BAD_FCS_COUNT (4713L)
+#define MAC_RX_BAD_PREAMBLE (4714L)
+#define MAC_RX_BAD_PREAMBLE_COUNT (4715L)
+#define MAC_RX_BAD_SFD (4716L)
+#define MAC_RX_BAD_SFD_COUNT (4717L)
+#define MAC_RX_BROADCAST (4718L)
+#define MAC_RX_BROADCAST_COUNT (4719L)
+#define MAC_RX_FRAGMENT (4720L)
+#define MAC_RX_FRAGMENT_COUNT (4721L)
+#define MAC_RX_INRANGEERR (4722L)
+#define MAC_RX_INRANGEERR_COUNT (4723L)
+#define MAC_RX_JABBER (4724L)
+#define MAC_RX_JABBER_COUNT (4725L)
+#define MAC_RX_MULTICAST (4726L)
+#define MAC_RX_MULTICAST_COUNT (4727L)
+#define MAC_RX_OVERSIZE (4728L)
+#define MAC_RX_OVERSIZE_COUNT (4729L)
+#define MAC_RX_PACKET_1024_1518_BYTES (4730L)
+#define MAC_RX_PACKET_1024_1518_BYTES_COUNT (4731L)
+#define MAC_RX_PACKET_128_255_BYTES (4732L)
+#define MAC_RX_PACKET_128_255_BYTES_COUNT (4733L)
+#define MAC_RX_PACKET_1519_1522_BYTES (4734L)
+#define MAC_RX_PACKET_1519_1522_BYTES_COUNT (4735L)
+#define MAC_RX_PACKET_1523_1548_BYTES (4736L)
+#define MAC_RX_PACKET_1523_1548_BYTES_COUNT (4737L)
+#define MAC_RX_PACKET_1549_2047_BYTES (4738L)
+#define MAC_RX_PACKET_1549_2047_BYTES_COUNT (4739L)
+#define MAC_RX_PACKET_2048_4095_BYTES (4740L)
+#define MAC_RX_PACKET_2048_4095_BYTES_COUNT (4741L)
+#define MAC_RX_PACKET_256_511_BYTES (4742L)
+#define MAC_RX_PACKET_256_511_BYTES_COUNT (4743L)
+#define MAC_RX_PACKET_4096_8191_BYTES (4744L)
+#define MAC_RX_PACKET_4096_8191_BYTES_COUNT (4745L)
+#define MAC_RX_PACKET_512_1023_BYTES (4746L)
+#define MAC_RX_PACKET_512_1023_BYTES_COUNT (4747L)
+#define MAC_RX_PACKET_64_BYTES (4748L)
+#define MAC_RX_PACKET_64_BYTES_COUNT (4749L)
+#define MAC_RX_PACKET_65_127_BYTES (4750L)
+#define MAC_RX_PACKET_65_127_BYTES_COUNT (4751L)
+#define MAC_RX_PACKET_8192_9215_BYTES (4752L)
+#define MAC_RX_PACKET_8192_9215_BYTES_COUNT (4753L)
+#define MAC_RX_PACKET_BAD_FCS (4754L)
+#define MAC_RX_PACKET_BAD_FCS_COUNT (4755L)
+#define MAC_RX_PACKET_LARGE (4756L)
+#define MAC_RX_PACKET_LARGE_COUNT (4757L)
+#define MAC_RX_PACKET_SMALL (4758L)
+#define MAC_RX_PACKET_SMALL_COUNT (4759L)
+#define MAC_RX_STOMPED_FCS (4760L)
+#define MAC_RX_STOMPED_FCS_COUNT (4761L)
+#define MAC_RX_TOOLONG (4762L)
+#define MAC_RX_TOOLONG_COUNT (4763L)
+#define MAC_RX_TOTAL_BYTES (4764L)
+#define MAC_RX_TOTAL_BYTES_COUNT (4765L)
+#define MAC_RX_TOTAL_GOOD_BYTES (4766L)
+#define MAC_RX_TOTAL_GOOD_BYTES_COUNT (4767L)
+#define MAC_RX_TOTAL_GOOD_PACKETS (4768L)
+#define MAC_RX_TOTAL_GOOD_PACKETS_COUNT (4769L)
+#define MAC_RX_TOTAL_PACKETS (4770L)
+#define MAC_RX_TOTAL_PACKETS_COUNT (4771L)
+#define MAC_RX_TRUNCATED (4772L)
+#define MAC_RX_TRUNCATED_COUNT (4773L)
+#define MAC_RX_UNDERSIZE (4774L)
+#define MAC_RX_UNDERSIZE_COUNT (4775L)
+#define MAC_RX_UNICAST (4776L)
+#define MAC_RX_UNICAST_COUNT (4777L)
+#define MAC_RX_VLAN (4778L)
+#define MAC_RX_VLAN_COUNT (4779L)
+/* MAC_TFG */
+#define MAC_TFG_TFG_ADDR (4780L)
+#define MAC_TFG_TFG_ADDR_ADR (4781L)
+#define MAC_TFG_TFG_ADDR_RDENA (4782L)
+#define MAC_TFG_TFG_ADDR_RD_DONE (4783L)
+#define MAC_TFG_TFG_CTRL (4784L)
+#define MAC_TFG_TFG_CTRL_ID_ENA (4785L)
+#define MAC_TFG_TFG_CTRL_ID_POS (4786L)
+#define MAC_TFG_TFG_CTRL_RESTART (4787L)
+#define MAC_TFG_TFG_CTRL_TG_ACT (4788L)
+#define MAC_TFG_TFG_CTRL_TG_ENA (4789L)
+#define MAC_TFG_TFG_CTRL_TIME_MODE (4790L)
+#define MAC_TFG_TFG_CTRL_WRAP (4791L)
+#define MAC_TFG_TFG_DATA (4792L)
+#define MAC_TFG_TFG_DATA_GAP (4793L)
+#define MAC_TFG_TFG_DATA_ID (4794L)
+#define MAC_TFG_TFG_DATA_LENGTH (4795L)
+#define MAC_TFG_TFG_FRAME_HDR (4796L)
+#define MAC_TFG_TFG_FRAME_HDR_HDR (4797L)
+#define MAC_TFG_TFG_REPETITION (4798L)
+#define MAC_TFG_TFG_REPETITION_CNT (4799L)
+/* MAC_TX */
+#define MAC_TX_BAD_FCS (4800L)
+#define MAC_TX_BAD_FCS_COUNT (4801L)
+#define MAC_TX_BROADCAST (4802L)
+#define MAC_TX_BROADCAST_COUNT (4803L)
+#define MAC_TX_FRAME_ERRORS (4804L)
+#define MAC_TX_FRAME_ERRORS_COUNT (4805L)
+#define MAC_TX_MULTICAST (4806L)
+#define MAC_TX_MULTICAST_COUNT (4807L)
+#define MAC_TX_PACKET_1024_1518_BYTES (4808L)
+#define MAC_TX_PACKET_1024_1518_BYTES_COUNT (4809L)
+#define MAC_TX_PACKET_128_255_BYTES (4810L)
+#define MAC_TX_PACKET_128_255_BYTES_COUNT (4811L)
+#define MAC_TX_PACKET_1519_1522_BYTES (4812L)
+#define MAC_TX_PACKET_1519_1522_BYTES_COUNT (4813L)
+#define MAC_TX_PACKET_1523_1548_BYTES (4814L)
+#define MAC_TX_PACKET_1523_1548_BYTES_COUNT (4815L)
+#define MAC_TX_PACKET_1549_2047_BYTES (4816L)
+#define MAC_TX_PACKET_1549_2047_BYTES_COUNT (4817L)
+#define MAC_TX_PACKET_2048_4095_BYTES (4818L)
+#define MAC_TX_PACKET_2048_4095_BYTES_COUNT (4819L)
+#define MAC_TX_PACKET_256_511_BYTES (4820L)
+#define MAC_TX_PACKET_256_511_BYTES_COUNT (4821L)
+#define MAC_TX_PACKET_4096_8191_BYTES (4822L)
+#define MAC_TX_PACKET_4096_8191_BYTES_COUNT (4823L)
+#define MAC_TX_PACKET_512_1023_BYTES (4824L)
+#define MAC_TX_PACKET_512_1023_BYTES_COUNT (4825L)
+#define MAC_TX_PACKET_64_BYTES (4826L)
+#define MAC_TX_PACKET_64_BYTES_COUNT (4827L)
+#define MAC_TX_PACKET_65_127_BYTES (4828L)
+#define MAC_TX_PACKET_65_127_BYTES_COUNT (4829L)
+#define MAC_TX_PACKET_8192_9215_BYTES (4830L)
+#define MAC_TX_PACKET_8192_9215_BYTES_COUNT (4831L)
+#define MAC_TX_PACKET_LARGE (4832L)
+#define MAC_TX_PACKET_LARGE_COUNT (4833L)
+#define MAC_TX_PACKET_SMALL (4834L)
+#define MAC_TX_PACKET_SMALL_COUNT (4835L)
+#define MAC_TX_TOTAL_BYTES (4836L)
+#define MAC_TX_TOTAL_BYTES_COUNT (4837L)
+#define MAC_TX_TOTAL_GOOD_BYTES (4838L)
+#define MAC_TX_TOTAL_GOOD_BYTES_COUNT (4839L)
+#define MAC_TX_TOTAL_GOOD_PACKETS (4840L)
+#define MAC_TX_TOTAL_GOOD_PACKETS_COUNT (4841L)
+#define MAC_TX_TOTAL_PACKETS (4842L)
+#define MAC_TX_TOTAL_PACKETS_COUNT (4843L)
+#define MAC_TX_UNICAST (4844L)
+#define MAC_TX_UNICAST_COUNT (4845L)
+#define MAC_TX_VLAN (4846L)
+#define MAC_TX_VLAN_COUNT (4847L)
+/* MCU */
+#define MCU_CSR (4848L)
+#define MCU_CSR_HALT (4849L)
+#define MCU_CSR_PAUSE (4850L)
+#define MCU_CSR_RESET (4851L)
+#define MCU_CSR_RESET_MCU (4852L)
+#define MCU_DRAM_CTRL (4853L)
+#define MCU_DRAM_CTRL_ADR (4854L)
+#define MCU_DRAM_CTRL_CNT (4855L)
+#define MCU_DRAM_RD_DATA (4856L)
+#define MCU_DRAM_RD_DATA_DATA (4857L)
+#define MCU_DRAM_WR_DATA (4858L)
+#define MCU_DRAM_WR_DATA_DATA (4859L)
+#define MCU_IRAM_CTRL (4860L)
+#define MCU_IRAM_CTRL_ADR (4861L)
+#define MCU_IRAM_CTRL_CNT (4862L)
+#define MCU_IRAM_DATA (4863L)
+#define MCU_IRAM_DATA_DATA (4864L)
+/* MDG */
+#define MDG_BSO_CTRL (4865L)
+#define MDG_BSO_CTRL_ADR (4866L)
+#define MDG_BSO_CTRL_CNT (4867L)
+#define MDG_BSO_DATA (4868L)
+#define MDG_BSO_DATA_OFFSET (4869L)
+#define MDG_CONTROL (4870L)
+#define MDG_CONTROL_AE (4871L)
+#define MDG_CONTROL_AS (4872L)
+#define MDG_CONTROL_CE (4873L)
+#define MDG_CONTROL_EN (4874L)
+#define MDG_DBG_EGS_FC0 (4875L)
+#define MDG_DBG_EGS_FC0_BLOCKED (4876L)
+#define MDG_DBG_EGS_FC1 (4877L)
+#define MDG_DBG_EGS_FC1_BLOCKED (4878L)
+#define MDG_DBG_EGS_FC2 (4879L)
+#define MDG_DBG_EGS_FC2_BLOCKED (4880L)
+#define MDG_DBG_EGS_FC3 (4881L)
+#define MDG_DBG_EGS_FC3_BLOCKED (4882L)
+#define MDG_DBG_HBM (4883L)
+#define MDG_DBG_HBM_ADR (4884L)
+#define MDG_DBG_HBM_MAIN (4885L)
+#define MDG_DBG_HBM_MAP (4886L)
+#define MDG_DBG_HBM_META (4887L)
+#define MDG_DBG_HBM_VALID (4888L)
+#define MDG_DBG_IGS_FC0 (4889L)
+#define MDG_DBG_IGS_FC0_BLOCKED (4890L)
+#define MDG_DBG_IGS_FC1 (4891L)
+#define MDG_DBG_IGS_FC1_BLOCKED (4892L)
+#define MDG_DBG_IGS_FC2 (4893L)
+#define MDG_DBG_IGS_FC2_BLOCKED (4894L)
+#define MDG_DBG_IGS_FC3 (4895L)
+#define MDG_DBG_IGS_FC3_BLOCKED (4896L)
+#define MDG_HBM_CTRL (4897L)
+#define MDG_HBM_CTRL_ADR (4898L)
+#define MDG_HBM_CTRL_CNT (4899L)
+#define MDG_HBM_DATA (4900L)
+#define MDG_HBM_DATA_MAIN (4901L)
+#define MDG_HBM_DATA_MAP (4902L)
+#define MDG_HBM_DATA_META (4903L)
+#define MDG_HBS_CTRL (4904L)
+#define MDG_HBS_CTRL_ADR (4905L)
+#define MDG_HBS_CTRL_CNT (4906L)
+#define MDG_HBS_DATA (4907L)
+#define MDG_HBS_DATA_SIZE (4908L)
+#define MDG_MAX_BYTES (4909L)
+#define MDG_MAX_BYTES_MAX (4910L)
+#define MDG_MAX_PACKETS (4911L)
+#define MDG_MAX_PACKETS_MAX (4912L)
+#define MDG_TIMEOUT (4913L)
+#define MDG_TIMEOUT_T (4914L)
+/* MSK */
+#define MSK_RCP_CTRL (4980L)
+#define MSK_RCP_CTRL_ADR (4981L)
+#define MSK_RCP_CTRL_CNT (4982L)
+#define MSK_RCP_DATA (4983L)
+#define MSK_RCP_DATA_MASK_DYN0 (4984L)
+#define MSK_RCP_DATA_MASK_DYN1 (4985L)
+#define MSK_RCP_DATA_MASK_DYN2 (4986L)
+#define MSK_RCP_DATA_MASK_DYN3 (4987L)
+#define MSK_RCP_DATA_MASK_EN0 (4988L)
+#define MSK_RCP_DATA_MASK_EN1 (4989L)
+#define MSK_RCP_DATA_MASK_EN2 (4990L)
+#define MSK_RCP_DATA_MASK_EN3 (4991L)
+#define MSK_RCP_DATA_MASK_LEN0 (4992L)
+#define MSK_RCP_DATA_MASK_LEN1 (4993L)
+#define MSK_RCP_DATA_MASK_LEN2 (4994L)
+#define MSK_RCP_DATA_MASK_LEN3 (4995L)
+#define MSK_RCP_DATA_MASK_OFS0 (4996L)
+#define MSK_RCP_DATA_MASK_OFS1 (4997L)
+#define MSK_RCP_DATA_MASK_OFS2 (4998L)
+#define MSK_RCP_DATA_MASK_OFS3 (4999L)
+/* NIF */
+#define NIF_CTRL (5000L)
+#define NIF_CTRL_GT_PWDN (5001L)
+#define NIF_CTRL_GT_SEL (5002L)
+#define NIF_CTRL_LOOPBACK (5003L)
+#define NIF_CTRL_PMA_INIT (5004L)
+#define NIF_CTRL_PRBS_ERR (5005L)
+#define NIF_CTRL_PRBS_RST (5006L)
+#define NIF_CTRL_PRBS_SEL (5007L)
+#define NIF_CTRL_QPLL_SEL (5008L)
+#define NIF_CTRL_RST (5009L)
+#define NIF_CTRL_TX_INHIBIT (5010L)
+#define NIF_DRP_IF (5011L)
+#define NIF_DRP_IF_ADR (5012L)
+#define NIF_DRP_IF_DATA (5013L)
+#define NIF_DRP_IF_DBG_BUSY (5014L)
+#define NIF_DRP_IF_DONE (5015L)
+#define NIF_DRP_IF_WREN (5016L)
+#define NIF_ERROR (5017L)
+#define NIF_ERROR_HARD_ERR (5018L)
+#define NIF_ERROR_SOFT_ERR (5019L)
+#define NIF_ERROR_SOFT_ERR_CNT (5020L)
+#define NIF_GTH_TX_TUNING (5021L)
+#define NIF_GTH_TX_TUNING_DIFF_CTRL (5022L)
+#define NIF_GTH_TX_TUNING_POST_CURSOR (5023L)
+#define NIF_GTH_TX_TUNING_PRE_CURSOR (5024L)
+#define NIF_HARD_ERROR_CNT (5025L)
+#define NIF_HARD_ERROR_CNT_UNCORRECTABLE_ERRORS (5026L)
+#define NIF_STATUS (5027L)
+#define NIF_STATUS_CH_UP (5028L)
+#define NIF_STATUS_EP0_0_UP (5029L)
+#define NIF_STATUS_EP0_1_UP (5030L)
+#define NIF_STATUS_EP0_2_UP (5031L)
+#define NIF_STATUS_EP0_3_UP (5032L)
+#define NIF_STATUS_EP1_0_UP (5033L)
+#define NIF_STATUS_EP1_1_UP (5034L)
+#define NIF_STATUS_EP1_2_UP (5035L)
+#define NIF_STATUS_EP1_3_UP (5036L)
+#define NIF_STATUS_EP1_4_UP (5037L)
+#define NIF_STATUS_EP1_5_UP (5038L)
+#define NIF_STATUS_EP3_0_UP (5039L)
+#define NIF_STATUS_EP3_1_UP (5040L)
+#define NIF_STATUS_EP3_2_UP (5041L)
+#define NIF_STATUS_EP3_3_UP (5042L)
+#define NIF_STATUS_MMCM_ULCK (5043L)
+#define NIF_STATUS_PLL_LCK (5044L)
+#define NIF_STATUS_QPLLOUT_LCK (5045L)
+#define NIF_STATUS_QPLLOUT_REF_LOST (5046L)
+#define NIF_STATUS_QPLL_LCK (5047L)
+#define NIF_STATUS_RXRST_DONE (5048L)
+#define NIF_STATUS_TXRST_DONE (5049L)
+#define NIF_STATUS_STICK (5050L)
+#define NIF_STATUS_STICK_CH_DOWN (5051L)
+#define NIF_STATUS_STICK_LN_DOWN (5052L)
+#define NIF_STATUS_STICK_MMCM_ULCK (5053L)
+#define NIF_STATUS_STICK_PLL_ULCK (5054L)
+#define NIF_USER_REG (5055L)
+#define NIF_USER_REG_MASTER (5056L)
+#define NIF_USER_REG_RST (5057L)
+#define NIF_USER_REG_SLAVE (5058L)
+#define NIF_USER_REG_STAT (5059L)
+#define NIF_USER_REG_STAT_LL (5060L)
+/* PCIE3 */
+#define PCIE3_BUILD_SEED (5228L)
+#define PCIE3_BUILD_SEED_BUILD_SEED (5229L)
+#define PCIE3_BUILD_TIME (5230L)
+#define PCIE3_BUILD_TIME_TIME (5231L)
+#define PCIE3_CONFIG (5232L)
+#define PCIE3_CONFIG_EXT_TAG (5233L)
+#define PCIE3_CONFIG_MAX_READ (5234L)
+#define PCIE3_CONFIG_MAX_TLP (5235L)
+#define PCIE3_CONTROL (5236L)
+#define PCIE3_CONTROL_RD_ATTR (5237L)
+#define PCIE3_CONTROL_WRAW (5238L)
+#define PCIE3_CONTROL_WR_ATTR (5239L)
+#define PCIE3_CORESPEED (5240L)
+#define PCIE3_CORESPEED_CORESPEED (5241L)
+#define PCIE3_CORESPEED_DDR3SPEED (5242L)
+#define PCIE3_DRP_COMMON (5243L)
+#define PCIE3_DRP_COMMON_DRP_ADDR (5244L)
+#define PCIE3_DRP_COMMON_DRP_RDY (5245L)
+#define PCIE3_DRP_COMMON_GTH_SEL (5246L)
+#define PCIE3_DRP_COMMON_WR (5247L)
+#define PCIE3_DRP_DATE (5248L)
+#define PCIE3_DRP_DATE_DRP_DATA (5249L)
+#define PCIE3_EP_TO_RP_ERR (5250L)
+#define PCIE3_EP_TO_RP_ERR_ERR_COR (5251L)
+#define PCIE3_EP_TO_RP_ERR_ERR_FATAL (5252L)
+#define PCIE3_EP_TO_RP_ERR_ERR_NONFATAL (5253L)
+#define PCIE3_INT_CLR (5254L)
+#define PCIE3_INT_CLR_AVR (5255L)
+#define PCIE3_INT_CLR_FHM (5256L)
+#define PCIE3_INT_CLR_INT_0 (5257L)
+#define PCIE3_INT_CLR_INT_1 (5258L)
+#define PCIE3_INT_CLR_INT_10 (5259L)
+#define PCIE3_INT_CLR_INT_11 (5260L)
+#define PCIE3_INT_CLR_INT_12 (5261L)
+#define PCIE3_INT_CLR_INT_13 (5262L)
+#define PCIE3_INT_CLR_INT_14 (5263L)
+#define PCIE3_INT_CLR_INT_15 (5264L)
+#define PCIE3_INT_CLR_INT_16 (5265L)
+#define PCIE3_INT_CLR_INT_17 (5266L)
+#define PCIE3_INT_CLR_INT_18 (5267L)
+#define PCIE3_INT_CLR_INT_19 (5268L)
+#define PCIE3_INT_CLR_INT_2 (5269L)
+#define PCIE3_INT_CLR_INT_20 (5270L)
+#define PCIE3_INT_CLR_INT_21 (5271L)
+#define PCIE3_INT_CLR_INT_22 (5272L)
+#define PCIE3_INT_CLR_INT_23 (5273L)
+#define PCIE3_INT_CLR_INT_24 (5274L)
+#define PCIE3_INT_CLR_INT_25 (5275L)
+#define PCIE3_INT_CLR_INT_26 (5276L)
+#define PCIE3_INT_CLR_INT_27 (5277L)
+#define PCIE3_INT_CLR_INT_28 (5278L)
+#define PCIE3_INT_CLR_INT_29 (5279L)
+#define PCIE3_INT_CLR_INT_3 (5280L)
+#define PCIE3_INT_CLR_INT_30 (5281L)
+#define PCIE3_INT_CLR_INT_31 (5282L)
+#define PCIE3_INT_CLR_INT_4 (5283L)
+#define PCIE3_INT_CLR_INT_5 (5284L)
+#define PCIE3_INT_CLR_INT_6 (5285L)
+#define PCIE3_INT_CLR_INT_7 (5286L)
+#define PCIE3_INT_CLR_INT_8 (5287L)
+#define PCIE3_INT_CLR_INT_9 (5288L)
+#define PCIE3_INT_CLR_PORT (5289L)
+#define PCIE3_INT_CLR_PPS (5290L)
+#define PCIE3_INT_CLR_QSPI (5291L)
+#define PCIE3_INT_CLR_SPIM (5292L)
+#define PCIE3_INT_CLR_SPIS (5293L)
+#define PCIE3_INT_CLR_STA (5294L)
+#define PCIE3_INT_CLR_TIMER (5295L)
+#define PCIE3_INT_FORC (5296L)
+#define PCIE3_INT_FORC_AVR (5297L)
+#define PCIE3_INT_FORC_FHM (5298L)
+#define PCIE3_INT_FORC_INT_0 (5299L)
+#define PCIE3_INT_FORC_INT_1 (5300L)
+#define PCIE3_INT_FORC_INT_10 (5301L)
+#define PCIE3_INT_FORC_INT_11 (5302L)
+#define PCIE3_INT_FORC_INT_12 (5303L)
+#define PCIE3_INT_FORC_INT_13 (5304L)
+#define PCIE3_INT_FORC_INT_14 (5305L)
+#define PCIE3_INT_FORC_INT_15 (5306L)
+#define PCIE3_INT_FORC_INT_16 (5307L)
+#define PCIE3_INT_FORC_INT_17 (5308L)
+#define PCIE3_INT_FORC_INT_18 (5309L)
+#define PCIE3_INT_FORC_INT_19 (5310L)
+#define PCIE3_INT_FORC_INT_2 (5311L)
+#define PCIE3_INT_FORC_INT_20 (5312L)
+#define PCIE3_INT_FORC_INT_21 (5313L)
+#define PCIE3_INT_FORC_INT_22 (5314L)
+#define PCIE3_INT_FORC_INT_23 (5315L)
+#define PCIE3_INT_FORC_INT_24 (5316L)
+#define PCIE3_INT_FORC_INT_25 (5317L)
+#define PCIE3_INT_FORC_INT_26 (5318L)
+#define PCIE3_INT_FORC_INT_27 (5319L)
+#define PCIE3_INT_FORC_INT_28 (5320L)
+#define PCIE3_INT_FORC_INT_29 (5321L)
+#define PCIE3_INT_FORC_INT_3 (5322L)
+#define PCIE3_INT_FORC_INT_30 (5323L)
+#define PCIE3_INT_FORC_INT_31 (5324L)
+#define PCIE3_INT_FORC_INT_4 (5325L)
+#define PCIE3_INT_FORC_INT_5 (5326L)
+#define PCIE3_INT_FORC_INT_6 (5327L)
+#define PCIE3_INT_FORC_INT_7 (5328L)
+#define PCIE3_INT_FORC_INT_8 (5329L)
+#define PCIE3_INT_FORC_INT_9 (5330L)
+#define PCIE3_INT_FORC_PORT (5331L)
+#define PCIE3_INT_FORC_PPS (5332L)
+#define PCIE3_INT_FORC_QSPI (5333L)
+#define PCIE3_INT_FORC_SPIM (5334L)
+#define PCIE3_INT_FORC_SPIS (5335L)
+#define PCIE3_INT_FORC_STA (5336L)
+#define PCIE3_INT_FORC_TIMER (5337L)
+#define PCIE3_INT_MASK (5338L)
+#define PCIE3_INT_MASK_AVR (5339L)
+#define PCIE3_INT_MASK_FHM (5340L)
+#define PCIE3_INT_MASK_IIC0 (5341L)
+#define PCIE3_INT_MASK_IIC1 (5342L)
+#define PCIE3_INT_MASK_IIC2 (5343L)
+#define PCIE3_INT_MASK_IIC3 (5344L)
+#define PCIE3_INT_MASK_IIC4 (5345L)
+#define PCIE3_INT_MASK_IIC5 (5346L)
+#define PCIE3_INT_MASK_INT_0 (5347L)
+#define PCIE3_INT_MASK_INT_1 (5348L)
+#define PCIE3_INT_MASK_INT_10 (5349L)
+#define PCIE3_INT_MASK_INT_11 (5350L)
+#define PCIE3_INT_MASK_INT_12 (5351L)
+#define PCIE3_INT_MASK_INT_13 (5352L)
+#define PCIE3_INT_MASK_INT_14 (5353L)
+#define PCIE3_INT_MASK_INT_15 (5354L)
+#define PCIE3_INT_MASK_INT_16 (5355L)
+#define PCIE3_INT_MASK_INT_17 (5356L)
+#define PCIE3_INT_MASK_INT_18 (5357L)
+#define PCIE3_INT_MASK_INT_19 (5358L)
+#define PCIE3_INT_MASK_INT_2 (5359L)
+#define PCIE3_INT_MASK_INT_20 (5360L)
+#define PCIE3_INT_MASK_INT_21 (5361L)
+#define PCIE3_INT_MASK_INT_22 (5362L)
+#define PCIE3_INT_MASK_INT_23 (5363L)
+#define PCIE3_INT_MASK_INT_24 (5364L)
+#define PCIE3_INT_MASK_INT_25 (5365L)
+#define PCIE3_INT_MASK_INT_26 (5366L)
+#define PCIE3_INT_MASK_INT_27 (5367L)
+#define PCIE3_INT_MASK_INT_28 (5368L)
+#define PCIE3_INT_MASK_INT_29 (5369L)
+#define PCIE3_INT_MASK_INT_3 (5370L)
+#define PCIE3_INT_MASK_INT_30 (5371L)
+#define PCIE3_INT_MASK_INT_31 (5372L)
+#define PCIE3_INT_MASK_INT_4 (5373L)
+#define PCIE3_INT_MASK_INT_5 (5374L)
+#define PCIE3_INT_MASK_INT_6 (5375L)
+#define PCIE3_INT_MASK_INT_7 (5376L)
+#define PCIE3_INT_MASK_INT_8 (5377L)
+#define PCIE3_INT_MASK_INT_9 (5378L)
+#define PCIE3_INT_MASK_PORT (5379L)
+#define PCIE3_INT_MASK_PPS (5380L)
+#define PCIE3_INT_MASK_QSPI (5381L)
+#define PCIE3_INT_MASK_SPIM (5382L)
+#define PCIE3_INT_MASK_SPIS (5383L)
+#define PCIE3_INT_MASK_STA (5384L)
+#define PCIE3_INT_MASK_TIMER (5385L)
+#define PCIE3_LAT_CTRL (5386L)
+#define PCIE3_LAT_CTRL_CLEAR_RAM (5387L)
+#define PCIE3_LAT_CTRL_ENABLE (5388L)
+#define PCIE3_LAT_CTRL_PRESCAL (5389L)
+#define PCIE3_LAT_CTRL_RAM_VLD (5390L)
+#define PCIE3_LAT_CTRL_READ_RAM (5391L)
+#define PCIE3_LAT_CTRL_STATUS (5392L)
+#define PCIE3_LAT_MAX (5393L)
+#define PCIE3_LAT_MAX_MAX (5394L)
+#define PCIE3_LAT_RAMADR (5395L)
+#define PCIE3_LAT_RAMADR_ADR (5396L)
+#define PCIE3_LAT_RAMDATA (5397L)
+#define PCIE3_LAT_RAMDATA_DATA (5398L)
+#define PCIE3_LINK_STATUS (5399L)
+#define PCIE3_LINK_STATUS_CLEAR (5400L)
+#define PCIE3_LINK_STATUS_RETRAIN_CNT (5401L)
+#define PCIE3_MARKADR_LSB (5402L)
+#define PCIE3_MARKADR_LSB_ADR (5403L)
+#define PCIE3_MARKADR_MSB (5404L)
+#define PCIE3_MARKADR_MSB_ADR (5405L)
+#define PCIE3_PB_INTERVAL (5406L)
+#define PCIE3_PB_INTERVAL_INTERVAL (5407L)
+#define PCIE3_PB_MAX_RD (5408L)
+#define PCIE3_PB_MAX_RD_PB (5409L)
+#define PCIE3_PB_MAX_WR (5410L)
+#define PCIE3_PB_MAX_WR_PB (5411L)
+#define PCIE3_PCIE_CTRL (5412L)
+#define PCIE3_PCIE_CTRL_EXT_TAG_ENA (5413L)
+#define PCIE3_PCI_ENDPOINT (5414L)
+#define PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK (5415L)
+#define PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK (5416L)
+#define PCIE3_PCI_ENDPOINT_GET_MSG (5417L)
+#define PCIE3_PCI_ENDPOINT_IF_ID (5418L)
+#define PCIE3_PCI_ENDPOINT_SEND_MSG (5419L)
+#define PCIE3_PCI_TEST0 (5420L)
+#define PCIE3_PCI_TEST0_DATA (5421L)
+#define PCIE3_PCI_TEST1 (5422L)
+#define PCIE3_PCI_TEST1_DATA (5423L)
+#define PCIE3_PCI_TEST2 (5424L)
+#define PCIE3_PCI_TEST2_DATA (5425L)
+#define PCIE3_PCI_TEST3 (5426L)
+#define PCIE3_PCI_TEST3_DATA (5427L)
+#define PCIE3_PROD_ID_EX (5428L)
+#define PCIE3_PROD_ID_EX_LAYOUT (5429L)
+#define PCIE3_PROD_ID_EX_LAYOUT_VERSION (5430L)
+#define PCIE3_PROD_ID_EX_RESERVED (5431L)
+#define PCIE3_PROD_ID_LSB (5432L)
+#define PCIE3_PROD_ID_LSB_GROUP_ID (5433L)
+#define PCIE3_PROD_ID_LSB_REV_ID (5434L)
+#define PCIE3_PROD_ID_LSB_VER_ID (5435L)
+#define PCIE3_PROD_ID_MSB (5436L)
+#define PCIE3_PROD_ID_MSB_BUILD_NO (5437L)
+#define PCIE3_PROD_ID_MSB_PATCH_NO (5438L)
+#define PCIE3_PROD_ID_MSB_TYPE_ID (5439L)
+#define PCIE3_RESET_CTRL (5440L)
+#define PCIE3_RESET_CTRL_MASK (5441L)
+#define PCIE3_RP_TO_EP_ERR (5442L)
+#define PCIE3_RP_TO_EP_ERR_ERR_COR (5443L)
+#define PCIE3_RP_TO_EP_ERR_ERR_FATAL (5444L)
+#define PCIE3_RP_TO_EP_ERR_ERR_NONFATAL (5445L)
+#define PCIE3_SAMPLE_TIME (5446L)
+#define PCIE3_SAMPLE_TIME_SAMPLE_TIME (5447L)
+#define PCIE3_STATUS (5448L)
+#define PCIE3_STATUS_RD_ERR (5449L)
+#define PCIE3_STATUS_TAGS_IN_USE (5450L)
+#define PCIE3_STATUS_WR_ERR (5451L)
+#define PCIE3_STATUS0 (5452L)
+#define PCIE3_STATUS0_TAGS_IN_USE (5453L)
+#define PCIE3_STATUS0_UR_ADDR (5454L)
+#define PCIE3_STATUS0_UR_DWORD (5455L)
+#define PCIE3_STATUS0_UR_FBE (5456L)
+#define PCIE3_STATUS0_UR_FMT (5457L)
+#define PCIE3_STATUS0_UR_LBE (5458L)
+#define PCIE3_STATUS0_UR_REG (5459L)
+#define PCIE3_STAT_CTRL (5460L)
+#define PCIE3_STAT_CTRL_STAT_ENA (5461L)
+#define PCIE3_STAT_CTRL_STAT_REQ (5462L)
+#define PCIE3_STAT_REFCLK (5463L)
+#define PCIE3_STAT_REFCLK_REFCLK250 (5464L)
+#define PCIE3_STAT_RQ_RDY (5465L)
+#define PCIE3_STAT_RQ_RDY_COUNTER (5466L)
+#define PCIE3_STAT_RQ_VLD (5467L)
+#define PCIE3_STAT_RQ_VLD_COUNTER (5468L)
+#define PCIE3_STAT_RX (5469L)
+#define PCIE3_STAT_RX_COUNTER (5470L)
+#define PCIE3_STAT_TX (5471L)
+#define PCIE3_STAT_TX_COUNTER (5472L)
+#define PCIE3_TEST0 (5473L)
+#define PCIE3_TEST0_DATA (5474L)
+#define PCIE3_TEST1 (5475L)
+#define PCIE3_TEST1_DATA (5476L)
+#define PCIE3_TEST2_DATA (5477L)
+#define PCIE3_TEST3_DATA (5478L)
+#define PCIE3_UUID0 (5479L)
+#define PCIE3_UUID0_UUID0 (5480L)
+#define PCIE3_UUID1 (5481L)
+#define PCIE3_UUID1_UUID1 (5482L)
+#define PCIE3_UUID2 (5483L)
+#define PCIE3_UUID2_UUID2 (5484L)
+#define PCIE3_UUID3 (5485L)
+#define PCIE3_UUID3_UUID3 (5486L)
+/* PCI_RD_TG */
+#define PCI_RD_TG_TG_CTRL (5487L)
+#define PCI_RD_TG_TG_CTRL_TG_RD_RDY (5488L)
+#define PCI_RD_TG_TG_RDADDR (5489L)
+#define PCI_RD_TG_TG_RDADDR_RAM_ADDR (5490L)
+#define PCI_RD_TG_TG_RDDATA0 (5491L)
+#define PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW (5492L)
+#define PCI_RD_TG_TG_RDDATA1 (5493L)
+#define PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH (5494L)
+#define PCI_RD_TG_TG_RDDATA2 (5495L)
+#define PCI_RD_TG_TG_RDDATA2_REQ_HID (5496L)
+#define PCI_RD_TG_TG_RDDATA2_REQ_SIZE (5497L)
+#define PCI_RD_TG_TG_RDDATA2_WAIT (5498L)
+#define PCI_RD_TG_TG_RDDATA2_WRAP (5499L)
+#define PCI_RD_TG_TG_RD_RUN (5500L)
+#define PCI_RD_TG_TG_RD_RUN_RD_ITERATION (5501L)
+/* PCI_TA */
+#define PCI_TA_CONTROL (5502L)
+#define PCI_TA_CONTROL_ENABLE (5503L)
+#define PCI_TA_LENGTH_ERROR (5504L)
+#define PCI_TA_LENGTH_ERROR_AMOUNT (5505L)
+#define PCI_TA_PACKET_BAD (5506L)
+#define PCI_TA_PACKET_BAD_AMOUNT (5507L)
+#define PCI_TA_PACKET_GOOD (5508L)
+#define PCI_TA_PACKET_GOOD_AMOUNT (5509L)
+#define PCI_TA_PAYLOAD_ERROR (5510L)
+#define PCI_TA_PAYLOAD_ERROR_AMOUNT (5511L)
+/* PCI_WR_TG */
+#define PCI_WR_TG_TG_CTRL (5512L)
+#define PCI_WR_TG_TG_CTRL_TG_WR_RDY (5513L)
+#define PCI_WR_TG_TG_SEQ (5514L)
+#define PCI_WR_TG_TG_SEQ_SEQUENCE (5515L)
+#define PCI_WR_TG_TG_WRADDR (5516L)
+#define PCI_WR_TG_TG_WRADDR_RAM_ADDR (5517L)
+#define PCI_WR_TG_TG_WRDATA0 (5518L)
+#define PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW (5519L)
+#define PCI_WR_TG_TG_WRDATA1 (5520L)
+#define PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH (5521L)
+#define PCI_WR_TG_TG_WRDATA2 (5522L)
+#define PCI_WR_TG_TG_WRDATA2_INC_MODE (5523L)
+#define PCI_WR_TG_TG_WRDATA2_REQ_HID (5524L)
+#define PCI_WR_TG_TG_WRDATA2_REQ_SIZE (5525L)
+#define PCI_WR_TG_TG_WRDATA2_WAIT (5526L)
+#define PCI_WR_TG_TG_WRDATA2_WRAP (5527L)
+#define PCI_WR_TG_TG_WR_RUN (5528L)
+#define PCI_WR_TG_TG_WR_RUN_WR_ITERATION (5529L)
+/* PCM_NT100A01_01 */
+#define PCM_NT100A01_01_CTRL (5530L)
+#define PCM_NT100A01_01_CTRL_PTP_CLKSEL (5531L)
+#define PCM_NT100A01_01_CTRL_REC_MMCM_RST (5532L)
+#define PCM_NT100A01_01_CTRL_TS_CLKSEL (5533L)
+#define PCM_NT100A01_01_CTRL_TS_MMCM_RST (5534L)
+#define PCM_NT100A01_01_GPIO_I (5535L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_C2B (5536L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_CS_CA (5537L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_INT_C1B (5538L)
+#define PCM_NT100A01_01_GPIO_I_SI5328_LOL (5539L)
+#define PCM_NT100A01_01_GPIO_O (5540L)
+#define PCM_NT100A01_01_GPIO_O_SI5328_CS_CA (5541L)
+#define PCM_NT100A01_01_GPIO_O_SI5328_RST_B (5542L)
+#define PCM_NT100A01_01_GPIO_T (5543L)
+#define PCM_NT100A01_01_GPIO_T_SI5328_CS_CA (5544L)
+#define PCM_NT100A01_01_LATCH (5545L)
+#define PCM_NT100A01_01_LATCH_REC_MMCM_LOCKED (5546L)
+#define PCM_NT100A01_01_LATCH_TCXO_MMCM_LOCKED (5547L)
+#define PCM_NT100A01_01_LATCH_TS_MMCM_LOCKED (5548L)
+#define PCM_NT100A01_01_STAT (5549L)
+#define PCM_NT100A01_01_STAT_REC_MMCM_LOCKED (5550L)
+#define PCM_NT100A01_01_STAT_TCXO_MMCM_LOCKED (5551L)
+#define PCM_NT100A01_01_STAT_TS_MMCM_LOCKED (5552L)
+/* PCM_NT50B01_01 */
+#define PCM_NT50B01_01_CTRL (5553L)
+#define PCM_NT50B01_01_CTRL_TS_CLKSEL (5554L)
+#define PCM_NT50B01_01_CTRL_TS_MMCM_RST (5555L)
+#define PCM_NT50B01_01_LATCH (5556L)
+#define PCM_NT50B01_01_LATCH_TS_MMCM_LOCKED (5557L)
+#define PCM_NT50B01_01_STAT (5558L)
+#define PCM_NT50B01_01_STAT_TS_MMCM_LOCKED (5559L)
+/* PCS */
+#define PCS_BER_COUNT (5560L)
+#define PCS_BER_COUNT_CNT (5561L)
+#define PCS_BIP_COUNT (5562L)
+#define PCS_BIP_COUNT_CNT (5563L)
+#define PCS_BLOCK_LOCK (5564L)
+#define PCS_BLOCK_LOCK_LOCK (5565L)
+#define PCS_BLOCK_LOCK_LATCH (5566L)
+#define PCS_BLOCK_LOCK_LATCH_LATCH_LOCK (5567L)
+#define PCS_BLOCK_LOCK_ST (5568L)
+#define PCS_BLOCK_LOCK_ST_LATCH_STATE (5569L)
+#define PCS_DDR3_STATUS (5570L)
+#define PCS_DDR3_STATUS_CALIB_DONE (5571L)
+#define PCS_DRP_CONFIG (5572L)
+#define PCS_DRP_CONFIG_DRP_ADR (5573L)
+#define PCS_DRP_CONFIG_DRP_DI (5574L)
+#define PCS_DRP_CONFIG_DRP_EN (5575L)
+#define PCS_DRP_CONFIG_DRP_WREN (5576L)
+#define PCS_DRP_DATA (5577L)
+#define PCS_DRP_DATA_DRP_DO (5578L)
+#define PCS_DRP_DATA_DRP_RDY (5579L)
+#define PCS_FSM_DONE (5580L)
+#define PCS_FSM_DONE_RX_RST_DONE (5581L)
+#define PCS_FSM_DONE_TX_RST_DONE (5582L)
+#define PCS_GTH_CONFIG (5583L)
+#define PCS_GTH_CONFIG_EYE_SCAN_RST (5584L)
+#define PCS_GTH_CONFIG_EYE_SCAN_TRIG (5585L)
+#define PCS_GTH_CONFIG_GT_LOOP (5586L)
+#define PCS_GTH_CONFIG_GT_LPM_EN (5587L)
+#define PCS_GTH_CONFIG_GT_MRST (5588L)
+#define PCS_GTH_CONFIG_GT_RX_RST (5589L)
+#define PCS_GTH_CONFIG_GT_SOFT_RST (5590L)
+#define PCS_GTH_CONFIG_GT_TX_RST (5591L)
+#define PCS_GTH_CONFIG_RX_MONITOR_SEL (5592L)
+#define PCS_GTH_CONFIG_RX_PCS_RST (5593L)
+#define PCS_GTH_CONFIG_RX_USER_RDY (5594L)
+#define PCS_GTH_CONFIG_TX_PCS_RST (5595L)
+#define PCS_GTH_CONFIG_TX_USER_RDYU (5596L)
+#define PCS_GTH_CONTROL (5597L)
+#define PCS_GTH_CONTROL_CPLL_LOCK (5598L)
+#define PCS_GTH_CONTROL_CPLL_REFCLK_LOST (5599L)
+#define PCS_GTH_CONTROL_RX_BUF_RST (5600L)
+#define PCS_GTH_TX_TUNING (5601L)
+#define PCS_GTH_TX_TUNING_DIFF_CTRL (5602L)
+#define PCS_GTH_TX_TUNING_POST_CURSOR (5603L)
+#define PCS_GTH_TX_TUNING_PRE_CURSOR (5604L)
+#define PCS_LANE_LOCK (5605L)
+#define PCS_LANE_LOCK_LOCK (5606L)
+#define PCS_LANE_LOCK_LATCH (5607L)
+#define PCS_LANE_LOCK_LATCH_LATCH_LOCK (5608L)
+#define PCS_LANE_LOCK_ST (5609L)
+#define PCS_LANE_LOCK_ST_LATCH_STATE (5610L)
+#define PCS_LANE_MAPPING (5611L)
+#define PCS_LANE_MAPPING_LANE (5612L)
+#define PCS_LANE_OFFSET (5613L)
+#define PCS_LANE_OFFSET_DIFF (5614L)
+#define PCS_PCS_CONFIG (5615L)
+#define PCS_PCS_CONFIG_BER_RST (5616L)
+#define PCS_PCS_CONFIG_BIP_RST (5617L)
+#define PCS_PCS_CONFIG_LANE_ADDR (5618L)
+#define PCS_PCS_CONFIG_LANE_BLOCK_CLR (5619L)
+#define PCS_PCS_CONFIG_TIME_OFFSET_RX (5620L)
+#define PCS_PCS_CONFIG_TXRX_LOOP (5621L)
+#define PCS_PCS_STATUS (5622L)
+#define PCS_PCS_STATUS_ALIGN (5623L)
+#define PCS_PCS_STATUS_DELAY_ERR (5624L)
+#define PCS_PCS_STATUS_FIFO_DELAY (5625L)
+#define PCS_PCS_STATUS_HI_BER (5626L)
+#define PCS_POLARITY (5627L)
+#define PCS_POLARITY_RX_POL (5628L)
+#define PCS_POLARITY_TX_POL (5629L)
+/* PCS100 */
+#define PCS100_BER_COUNT (5630L)
+#define PCS100_BER_COUNT_CNT (5631L)
+#define PCS100_BIP_COUNT (5632L)
+#define PCS100_BIP_COUNT_CNT (5633L)
+#define PCS100_BLOCK_LOCK (5634L)
+#define PCS100_BLOCK_LOCK_LOCK (5635L)
+#define PCS100_BLOCK_LOCK_LATCH (5636L)
+#define PCS100_BLOCK_LOCK_LATCH_LATCH_LOCK (5637L)
+#define PCS100_BLOCK_LOCK_ST (5638L)
+#define PCS100_BLOCK_LOCK_ST_LATCH_STATE (5639L)
+#define PCS100_DDR3_STATUS (5640L)
+#define PCS100_DDR3_STATUS_CALIB_DONE (5641L)
+#define PCS100_DRP_CONFIG (5642L)
+#define PCS100_DRP_CONFIG_DRP_ADR (5643L)
+#define PCS100_DRP_CONFIG_DRP_DI (5644L)
+#define PCS100_DRP_CONFIG_DRP_EN (5645L)
+#define PCS100_DRP_CONFIG_DRP_WREN (5646L)
+#define PCS100_DRP_DATA (5647L)
+#define PCS100_DRP_DATA_DRP_DO (5648L)
+#define PCS100_DRP_DATA_DRP_RDY (5649L)
+#define PCS100_FSM_DONE (5650L)
+#define PCS100_FSM_DONE_RX_RST_DONE (5651L)
+#define PCS100_FSM_DONE_TX_RST_DONE (5652L)
+#define PCS100_GTH_CONFIG (5653L)
+#define PCS100_GTH_CONFIG_EYE_SCAN_RST (5654L)
+#define PCS100_GTH_CONFIG_EYE_SCAN_TRIG (5655L)
+#define PCS100_GTH_CONFIG_GT_LOOP (5656L)
+#define PCS100_GTH_CONFIG_GT_MRST (5657L)
+#define PCS100_GTH_CONFIG_GT_RX_RST (5658L)
+#define PCS100_GTH_CONFIG_GT_SOFT_RST (5659L)
+#define PCS100_GTH_CONFIG_GT_TX_RST (5660L)
+#define PCS100_GTH_CONFIG_RX_MONITOR_SEL (5661L)
+#define PCS100_GTH_CONFIG_RX_PCS_RST (5662L)
+#define PCS100_GTH_CONFIG_RX_USER_RDY (5663L)
+#define PCS100_GTH_CONFIG_TX_PCS_RST (5664L)
+#define PCS100_GTH_CONFIG_TX_USER_RDYU (5665L)
+#define PCS100_GTH_CONTROL (5666L)
+#define PCS100_GTH_CONTROL_CPLL_LOCK (5667L)
+#define PCS100_GTH_CONTROL_CPLL_REFCLK_LOST (5668L)
+#define PCS100_GTH_CONTROL_QPLL_LOCK (5669L)
+#define PCS100_GTH_CONTROL_QPLL_REFCLK_LOST (5670L)
+#define PCS100_GTH_CONTROL_RX_BUF_RST (5671L)
+#define PCS100_GTH_TX_TUNING (5672L)
+#define PCS100_GTH_TX_TUNING_DIFF_CTRL (5673L)
+#define PCS100_GTH_TX_TUNING_POST_CURSOR (5674L)
+#define PCS100_GTH_TX_TUNING_PRE_CURSOR (5675L)
+#define PCS100_LANE_LOCK (5676L)
+#define PCS100_LANE_LOCK_LOCK (5677L)
+#define PCS100_LANE_LOCK_LATCH (5678L)
+#define PCS100_LANE_LOCK_LATCH_LATCH_LOCK (5679L)
+#define PCS100_LANE_LOCK_ST (5680L)
+#define PCS100_LANE_LOCK_ST_LATCH_STATE (5681L)
+#define PCS100_LANE_MAPPING (5682L)
+#define PCS100_LANE_MAPPING_LANE (5683L)
+#define PCS100_LANE_OFFSET (5684L)
+#define PCS100_LANE_OFFSET_DIFF (5685L)
+#define PCS100_PCS_CONFIG (5686L)
+#define PCS100_PCS_CONFIG_BER_RST (5687L)
+#define PCS100_PCS_CONFIG_BIP_RST (5688L)
+#define PCS100_PCS_CONFIG_LANE_ADDR (5689L)
+#define PCS100_PCS_CONFIG_LANE_BLOCK_CLR (5690L)
+#define PCS100_PCS_CONFIG_TIME_OFFSET_RX (5691L)
+#define PCS100_PCS_CONFIG_TXRX_LOOP (5692L)
+#define PCS100_PCS_STATUS (5693L)
+#define PCS100_PCS_STATUS_ALIGN (5694L)
+#define PCS100_PCS_STATUS_DELAY_ERR (5695L)
+#define PCS100_PCS_STATUS_FIFO_DELAY (5696L)
+#define PCS100_PCS_STATUS_HI_BER (5697L)
+/* PDB */
+#define PDB_CONFIG (5698L)
+#define PDB_CONFIG_PORT_OFS (5699L)
+#define PDB_CONFIG_TS_FORMAT (5700L)
+#define PDB_RCP_CTRL (5701L)
+#define PDB_RCP_CTRL_ADR (5702L)
+#define PDB_RCP_CTRL_CNT (5703L)
+#define PDB_RCP_DATA (5704L)
+#define PDB_RCP_DATA_ALIGN (5705L)
+#define PDB_RCP_DATA_CRC_OVERWRITE (5706L)
+#define PDB_RCP_DATA_DESCRIPTOR (5707L)
+#define PDB_RCP_DATA_DESC_LEN (5708L)
+#define PDB_RCP_DATA_DUPLICATE_BIT (5709L)
+#define PDB_RCP_DATA_DUPLICATE_EN (5710L)
+#define PDB_RCP_DATA_IP_PROT_TNL (5711L)
+#define PDB_RCP_DATA_OFS0_DYN (5712L)
+#define PDB_RCP_DATA_OFS0_REL (5713L)
+#define PDB_RCP_DATA_OFS1_DYN (5714L)
+#define PDB_RCP_DATA_OFS1_REL (5715L)
+#define PDB_RCP_DATA_OFS2_DYN (5716L)
+#define PDB_RCP_DATA_OFS2_REL (5717L)
+#define PDB_RCP_DATA_PCAP_KEEP_FCS (5718L)
+#define PDB_RCP_DATA_PPC_HSH (5719L)
+#define PDB_RCP_DATA_TX_IGNORE (5720L)
+#define PDB_RCP_DATA_TX_NOW (5721L)
+#define PDB_RCP_DATA_TX_PORT (5722L)
+/* PDI */
+#define PDI_CR (5723L)
+#define PDI_CR_EN (5724L)
+#define PDI_CR_PARITY (5725L)
+#define PDI_CR_RST (5726L)
+#define PDI_CR_RXRST (5727L)
+#define PDI_CR_STOP (5728L)
+#define PDI_CR_TXRST (5729L)
+#define PDI_DRR (5730L)
+#define PDI_DRR_DRR (5731L)
+#define PDI_DTR (5732L)
+#define PDI_DTR_DTR (5733L)
+#define PDI_PRE (5734L)
+#define PDI_PRE_PRE (5735L)
+#define PDI_SR (5736L)
+#define PDI_SR_DISABLE_BUSY (5737L)
+#define PDI_SR_DONE (5738L)
+#define PDI_SR_ENABLE_BUSY (5739L)
+#define PDI_SR_FRAME_ERR (5740L)
+#define PDI_SR_OVERRUN_ERR (5741L)
+#define PDI_SR_PARITY_ERR (5742L)
+#define PDI_SR_RXLVL (5743L)
+#define PDI_SR_RX_BUSY (5744L)
+#define PDI_SR_TXLVL (5745L)
+#define PDI_SR_TX_BUSY (5746L)
+#define PDI_SRR (5747L)
+#define PDI_SRR_RST (5748L)
+/* PHY10G */
+#define PHY10G_CORE_CONF (5749L)
+#define PHY10G_CORE_CONF_CLEAR_PCS_LINK_FAULTS (5750L)
+#define PHY10G_CORE_CONF_CLEAR_PCS_STATUS2 (5751L)
+#define PHY10G_CORE_CONF_CLEAR_PMA_PMD_LINK_FAULTS (5752L)
+#define PHY10G_CORE_CONF_CLEAR_TEST_PATT_ERR_COUNT (5753L)
+#define PHY10G_CORE_CONF_DATA_PATT_SEL (5754L)
+#define PHY10G_CORE_CONF_GLOBAL_TX_DISABLE (5755L)
+#define PHY10G_CORE_CONF_NT_FORCE_LINK_DOWN (5756L)
+#define PHY10G_CORE_CONF_NT_LINKUP_LATENCY (5757L)
+#define PHY10G_CORE_CONF_PCS_LOOPBACK (5758L)
+#define PHY10G_CORE_CONF_PCS_RESET (5759L)
+#define PHY10G_CORE_CONF_PMA_LOOPBACK (5760L)
+#define PHY10G_CORE_CONF_PMA_RESET (5761L)
+#define PHY10G_CORE_CONF_PMD_TX_DISABLE (5762L)
+#define PHY10G_CORE_CONF_PRBS31_RX_EN (5763L)
+#define PHY10G_CORE_CONF_PRBS31_TX_EN (5764L)
+#define PHY10G_CORE_CONF_RX_TEST_PATT_EN (5765L)
+#define PHY10G_CORE_CONF_SET_PCS_LINK_STATUS (5766L)
+#define PHY10G_CORE_CONF_SET_PMA_LINK_STATUS (5767L)
+#define PHY10G_CORE_CONF_TEST_PATT_SEL (5768L)
+#define PHY10G_CORE_CONF_TX_TEST_PATT_EN (5769L)
+#define PHY10G_CORE_STAT (5770L)
+#define PHY10G_CORE_STAT_NT_LINK_STATE (5771L)
+#define PHY10G_CORE_STAT_PCS_BER_COUNT (5772L)
+#define PHY10G_CORE_STAT_PCS_BLOCK_LOCK (5773L)
+#define PHY10G_CORE_STAT_PCS_ERR_BLOCK_COUNT (5774L)
+#define PHY10G_CORE_STAT_PCS_HIBER (5775L)
+#define PHY10G_CORE_STAT_PCS_RESET (5776L)
+#define PHY10G_CORE_STAT_PCS_RX_FAULT (5777L)
+#define PHY10G_CORE_STAT_PCS_RX_HIBER_LH (5778L)
+#define PHY10G_CORE_STAT_PCS_RX_LINK_STATUS (5779L)
+#define PHY10G_CORE_STAT_PCS_RX_LOCKED (5780L)
+#define PHY10G_CORE_STAT_PCS_RX_LOCKED_LL (5781L)
+#define PHY10G_CORE_STAT_PCS_TEST_PATT_ERR_COUNT (5782L)
+#define PHY10G_CORE_STAT_PCS_TX_FAULT (5783L)
+#define PHY10G_CORE_STAT_PMA_PMD_LINK_STAT (5784L)
+#define PHY10G_CORE_STAT_PMA_PMD_RX_FAULT (5785L)
+#define PHY10G_CORE_STAT_PMA_PMD_TX_FAULT (5786L)
+#define PHY10G_CORE_STAT_PMA_RESET (5787L)
+#define PHY10G_CORE_STAT_RX_SIG_DET (5788L)
+#define PHY10G_CORE_STAT_TENG_PCS_RX_LINK_STATUS (5789L)
+#define PHY10G_CTRL (5790L)
+#define PHY10G_CTRL_FORCE_LINK_DOWN (5791L)
+#define PHY10G_CTRL_HOST_LOOPBACK (5792L)
+#define PHY10G_CTRL_LINE_LOOPBACK (5793L)
+#define PHY10G_CTRL_LINKUP_LATENCY (5794L)
+#define PHY10G_CTRL_SOFT_RESET (5795L)
+#define PHY10G_GPIO (5796L)
+#define PHY10G_GPIO_ABS (5797L)
+#define PHY10G_GPIO_LED_MODE (5798L)
+#define PHY10G_GPIO_LED_MODE_NIM (5799L)
+#define PHY10G_GPIO_LED_MODE_PHY (5800L)
+#define PHY10G_GPIO_PWR_EN (5801L)
+#define PHY10G_GPIO_RX_LOS (5802L)
+#define PHY10G_GPIO_TX_FAULT (5803L)
+#define PHY10G_GT_CTRL (5804L)
+#define PHY10G_GT_CTRL_EYESCANRESET (5805L)
+#define PHY10G_GT_CTRL_EYESCANTRIGGER (5806L)
+#define PHY10G_GT_CTRL_RXCDRHOLD (5807L)
+#define PHY10G_GT_CTRL_RXDFELPMRESET (5808L)
+#define PHY10G_GT_CTRL_RXLPMEN (5809L)
+#define PHY10G_GT_CTRL_RXPMARESET (5810L)
+#define PHY10G_GT_CTRL_RXPRBSENABLE (5811L)
+#define PHY10G_GT_CTRL_RXRATE (5812L)
+#define PHY10G_GT_CTRL_TXDIFFCTRL (5813L)
+#define PHY10G_GT_CTRL_TXPCSRESET (5814L)
+#define PHY10G_GT_CTRL_TXPMARESET (5815L)
+#define PHY10G_GT_CTRL_TXPOSTCURSOR (5816L)
+#define PHY10G_GT_CTRL_TXPRBSENABLE (5817L)
+#define PHY10G_GT_CTRL_TXPRBSFORCEERR (5818L)
+#define PHY10G_GT_CTRL_TXPRECURSOR (5819L)
+#define PHY10G_GT_STAT (5820L)
+#define PHY10G_GT_STAT_DMONITOROUT (5821L)
+#define PHY10G_GT_STAT_EYESCANDATAERROR (5822L)
+#define PHY10G_GT_STAT_RXBUFSTATUS (5823L)
+#define PHY10G_GT_STAT_RXPMARESETDONE (5824L)
+#define PHY10G_GT_STAT_RXPRBSERR (5825L)
+#define PHY10G_GT_STAT_RXPRBSLOCKED (5826L)
+#define PHY10G_GT_STAT_RXRESETDONE (5827L)
+#define PHY10G_GT_STAT_TXBUFSTATUS (5828L)
+#define PHY10G_GT_STAT_TXRESETDONE (5829L)
+#define PHY10G_GT_STAT2 (5830L)
+#define PHY10G_GT_STAT2_DMONITOR (5831L)
+#define PHY10G_GT_STAT2_RXPRBSCNT (5832L)
+#define PHY10G_INT (5833L)
+#define PHY10G_INT_EN (5834L)
+#define PHY10G_INT_MAX_PACE (5835L)
+#define PHY10G_LINK_SUMMARY (5836L)
+#define PHY10G_LINK_SUMMARY_ABS (5837L)
+#define PHY10G_LINK_SUMMARY_CORE_STATUS (5838L)
+#define PHY10G_LINK_SUMMARY_LINK_DOWN_CNT (5839L)
+#define PHY10G_LINK_SUMMARY_NT_LINK_STATE (5840L)
+#define PHY10G_LINK_SUMMARY_RES (5841L)
+#define PHY10G_TS_COMP (5842L)
+#define PHY10G_TS_COMP_RX (5843L)
+/* PHY3S10G */
+#define PHY3S10G_ANEG_ADV_3S (5844L)
+#define PHY3S10G_ANEG_ADV_3S_DUPLEX (5845L)
+#define PHY3S10G_ANEG_ADV_3S_PAUSE (5846L)
+#define PHY3S10G_ANEG_ADV_3S_REMOTE_FAULT (5847L)
+#define PHY3S10G_CORE_CONF_10G (5848L)
+#define PHY3S10G_CORE_CONF_10G_CLEAR_PCS_LINK_FAULTS (5849L)
+#define PHY3S10G_CORE_CONF_10G_CLEAR_PCS_STATUS2 (5850L)
+#define PHY3S10G_CORE_CONF_10G_CLEAR_PMA_PMD_LINK_FAULTS (5851L)
+#define PHY3S10G_CORE_CONF_10G_PCS_LOOPBACK (5852L)
+#define PHY3S10G_CORE_CONF_10G_PCS_RESET (5853L)
+#define PHY3S10G_CORE_CONF_10G_PMA_LOOPBACK (5854L)
+#define PHY3S10G_CORE_CONF_10G_PMA_RESET (5855L)
+#define PHY3S10G_CORE_CONF_10G_SET_PCS_LINK_STATUS (5856L)
+#define PHY3S10G_CORE_CONF_10G_SET_PMA_LINK_STATUS (5857L)
+#define PHY3S10G_CORE_CONF_3S (5858L)
+#define PHY3S10G_CORE_CONF_3S_ANEG_BYPASS_EN (5859L)
+#define PHY3S10G_CORE_CONF_3S_ANEG_EN (5860L)
+#define PHY3S10G_CORE_CONF_3S_ANEG_RESTART (5861L)
+#define PHY3S10G_CORE_CONF_3S_BASEX_OR_SGMII (5862L)
+#define PHY3S10G_CORE_CONF_3S_LINK_TIMER_BASEX (5863L)
+#define PHY3S10G_CORE_CONF_3S_LOOPBACK_CTRL (5864L)
+#define PHY3S10G_CORE_CONF_3S_POWER_DOWN (5865L)
+#define PHY3S10G_CORE_CONF_3S_SPEED (5866L)
+#define PHY3S10G_CORE_CONF_3S_UNIDIRECT_EN (5867L)
+#define PHY3S10G_CORE_STAT_10G (5868L)
+#define PHY3S10G_CORE_STAT_10G_NT_LINK_STATE (5869L)
+#define PHY3S10G_CORE_STAT_10G_PCS_BER_COUNT (5870L)
+#define PHY3S10G_CORE_STAT_10G_PCS_BLOCK_LOCK (5871L)
+#define PHY3S10G_CORE_STAT_10G_PCS_ERR_BLOCK_COUNT (5872L)
+#define PHY3S10G_CORE_STAT_10G_PCS_HIBER (5873L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_HIBER_LH (5874L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_LINK_STATUS (5875L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_LOCKED (5876L)
+#define PHY3S10G_CORE_STAT_10G_PCS_RX_LOCKED_LL (5877L)
+#define PHY3S10G_CORE_STAT_10G_PMA_PMD_LINK_STAT (5878L)
+#define PHY3S10G_CORE_STAT_10G_RX_SIG_DET (5879L)
+#define PHY3S10G_CORE_STAT_10G_TENG_PCS_RX_LINK_STATUS (5880L)
+#define PHY3S10G_CORE_STAT_3S (5881L)
+#define PHY3S10G_CORE_STAT_3S_ANEG_COMPLETE (5882L)
+#define PHY3S10G_CORE_STAT_3S_DUPLEX_MODE (5883L)
+#define PHY3S10G_CORE_STAT_3S_LINK_STATUS (5884L)
+#define PHY3S10G_CORE_STAT_3S_LINK_SYNC (5885L)
+#define PHY3S10G_CORE_STAT_3S_NT_LINK_STATE (5886L)
+#define PHY3S10G_CORE_STAT_3S_PAUSE (5887L)
+#define PHY3S10G_CORE_STAT_3S_PHY_LINK_STAT (5888L)
+#define PHY3S10G_CORE_STAT_3S_REM_FAULT_ENC (5889L)
+#define PHY3S10G_CORE_STAT_3S_RESERVED (5890L)
+#define PHY3S10G_CORE_STAT_3S_RUDI_C (5891L)
+#define PHY3S10G_CORE_STAT_3S_RUDI_I (5892L)
+#define PHY3S10G_CORE_STAT_3S_RUDI_INVALID (5893L)
+#define PHY3S10G_CORE_STAT_3S_RXDISPERR (5894L)
+#define PHY3S10G_CORE_STAT_3S_RXNOTINTABLE (5895L)
+#define PHY3S10G_CORE_STAT_3S_SPEED (5896L)
+#define PHY3S10G_CTRL (5897L)
+#define PHY3S10G_CTRL_FORCE_LINK_DOWN (5898L)
+#define PHY3S10G_CTRL_HOST_LOOPBACK_10G (5899L)
+#define PHY3S10G_CTRL_HOST_LOOPBACK_3S (5900L)
+#define PHY3S10G_CTRL_LINE_LOOPBACK_10G (5901L)
+#define PHY3S10G_CTRL_LINE_LOOPBACK_3S (5902L)
+#define PHY3S10G_CTRL_LINKUP_LATENCY (5903L)
+#define PHY3S10G_CTRL_PHY_CHANGE_FSM_DONE (5904L)
+#define PHY3S10G_CTRL_PHY_SEL (5905L)
+#define PHY3S10G_CTRL_SOFT_RESET (5906L)
+#define PHY3S10G_GPIO (5907L)
+#define PHY3S10G_GPIO_ABS (5908L)
+#define PHY3S10G_GPIO_LED_MODE (5909L)
+#define PHY3S10G_GPIO_RATE_SEL (5910L)
+#define PHY3S10G_GPIO_RX_LOS (5911L)
+#define PHY3S10G_GPIO_TX_DISABLE (5912L)
+#define PHY3S10G_GPIO_TX_FAULT (5913L)
+#define PHY3S10G_GT_CR (5914L)
+#define PHY3S10G_GT_CR_EYESCANRESET (5915L)
+#define PHY3S10G_GT_CR_EYESCANTRIGGER (5916L)
+#define PHY3S10G_GT_CR_LOOPBACK (5917L)
+#define PHY3S10G_GT_CR_RXCDRHOLD (5918L)
+#define PHY3S10G_GT_CR_RXDFELPMRESET (5919L)
+#define PHY3S10G_GT_CR_RXLPMEN (5920L)
+#define PHY3S10G_GT_CR_RXPMARESET (5921L)
+#define PHY3S10G_GT_CR_RXPRBSCNTRESET (5922L)
+#define PHY3S10G_GT_CR_RXPRBSSEL (5923L)
+#define PHY3S10G_GT_CR_TXDIFFCTRL (5924L)
+#define PHY3S10G_GT_CR_TXPMARESET (5925L)
+#define PHY3S10G_GT_CR_TXPOSTCURSOR (5926L)
+#define PHY3S10G_GT_CR_TXPRBSFORCEERR (5927L)
+#define PHY3S10G_GT_CR_TXPRBSSEL (5928L)
+#define PHY3S10G_GT_CR_TXPRECURSOR (5929L)
+#define PHY3S10G_GT_SR (5930L)
+#define PHY3S10G_GT_SR_EYESCANDATAERROR (5931L)
+#define PHY3S10G_GT_SR_RXBUFSTATUS (5932L)
+#define PHY3S10G_GT_SR_RXPMARESETDONE (5933L)
+#define PHY3S10G_GT_SR_RXPRBSERR (5934L)
+#define PHY3S10G_GT_SR_RXRESETDONE (5935L)
+#define PHY3S10G_GT_SR_TXBUFSTATUS (5936L)
+#define PHY3S10G_GT_SR_TXRESETDONE (5937L)
+#define PHY3S10G_INT (5938L)
+#define PHY3S10G_INT_EN (5939L)
+#define PHY3S10G_INT_MAX_PACE (5940L)
+#define PHY3S10G_LINK_SUMMARY (5941L)
+#define PHY3S10G_LINK_SUMMARY_ABS (5942L)
+#define PHY3S10G_LINK_SUMMARY_ANEG_BYPASS (5943L)
+#define PHY3S10G_LINK_SUMMARY_LINK_DOWN_CNT (5944L)
+#define PHY3S10G_LINK_SUMMARY_NT_LINK_STATE (5945L)
+#define PHY3S10G_TS_COMP (5946L)
+#define PHY3S10G_TS_COMP_RX (5947L)
+#define PHY3S10G_TS_COMP_RX_10G (5948L)
+#define PHY3S10G_TS_COMP_RX_3S (5949L)
+/* PM */
+#define PM_CTRL (5950L)
+#define PM_CTRL_SW_CLEAN_DONE (5951L)
+#define PM_DEBUG_RP (5952L)
+#define PM_DEBUG_RP_RP (5953L)
+#define PM_DEBUG_RP_SETUP (5954L)
+#define PM_DEBUG_RP_SETUP_HB (5955L)
+#define PM_DEBUG_RX_BLOCK (5956L)
+#define PM_DEBUG_RX_BLOCK_MASK (5957L)
+#define PM_HB_SIZE_RX_MEM_CTRL (5958L)
+#define PM_HB_SIZE_RX_MEM_CTRL_A (5959L)
+#define PM_HB_SIZE_RX_MEM_CTRL_CNT (5960L)
+#define PM_HB_SIZE_RX_MEM_DATA (5961L)
+#define PM_HB_SIZE_RX_MEM_DATA_SIZE (5962L)
+#define PM_HB_SIZE_RX_THRESHOLD (5963L)
+#define PM_HB_SIZE_RX_THRESHOLD_D (5964L)
+#define PM_HB_SIZE_TX_THRESHOLD (5965L)
+#define PM_HB_SIZE_TX_THRESHOLD_D (5966L)
+#define PM_PBI_MEM_CTRL (5967L)
+#define PM_PBI_MEM_CTRL_A (5968L)
+#define PM_PBI_MEM_CTRL_CNT (5969L)
+#define PM_PBI_MEM_DATA (5970L)
+#define PM_PBI_MEM_DATA_PHYADDR (5971L)
+#define PM_PBI_MEM_DATA_SIZE (5972L)
+#define PM_POINTER_BANKS (5973L)
+#define PM_POINTER_BANKS_D (5974L)
+#define PM_RXTX_FAST_MEM_CTRL (5975L)
+#define PM_RXTX_FAST_MEM_CTRL_A (5976L)
+#define PM_RXTX_FAST_MEM_CTRL_CNT (5977L)
+#define PM_RXTX_FAST_MEM_DATA (5978L)
+#define PM_RXTX_FAST_MEM_DATA_BANK (5979L)
+#define PM_RXTX_FAST_MEM_DATA_ENTRY (5980L)
+#define PM_RXTX_FAST_MEM_DATA_HOST_BUFFER (5981L)
+#define PM_RXTX_FAST_MEM_DATA_RX_TX (5982L)
+#define PM_RXTX_FAST_MEM_DATA_VLD (5983L)
+#define PM_RXTX_SLOW_MEM_CTRL (5984L)
+#define PM_RXTX_SLOW_MEM_CTRL_A (5985L)
+#define PM_RXTX_SLOW_MEM_CTRL_CNT (5986L)
+#define PM_RXTX_SLOW_MEM_DATA (5987L)
+#define PM_RXTX_SLOW_MEM_DATA_BANK (5988L)
+#define PM_RXTX_SLOW_MEM_DATA_ENTRY (5989L)
+#define PM_RXTX_SLOW_MEM_DATA_HOST_BUFFER (5990L)
+#define PM_RXTX_SLOW_MEM_DATA_RX_TX (5991L)
+#define PM_RXTX_SLOW_MEM_DATA_VLD (5992L)
+#define PM_RXWP_MEM_CTRL (5993L)
+#define PM_RXWP_MEM_CTRL_A (5994L)
+#define PM_RXWP_MEM_CTRL_CNT (5995L)
+#define PM_RXWP_MEM_DATA (5996L)
+#define PM_RXWP_MEM_DATA_BANK (5997L)
+#define PM_RXWP_MEM_DATA_ENTRY (5998L)
+#define PM_RXWP_MEM_DATA_HOST_BUFFER (5999L)
+#define PM_RXWP_MEM_DATA_VLD (6000L)
+#define PM_RX_BLOCKED_STATUS (6001L)
+#define PM_RX_BLOCKED_STATUS_D (6002L)
+#define PM_RX_BLOCKED_STATUS_HI (6003L)
+#define PM_RX_BLOCKED_STATUS_HI_D (6004L)
+#define PM_RX_OVERFLOW_STATUS (6005L)
+#define PM_RX_OVERFLOW_STATUS_D (6006L)
+#define PM_RX_READER (6007L)
+#define PM_RX_READER_MASK (6008L)
+#define PM_RX_TX_FAST_POINTER_BLOCK_INTERVAL (6009L)
+#define PM_RX_TX_FAST_POINTER_BLOCK_INTERVAL_D (6010L)
+#define PM_RX_TX_SLOW_POINTER_BLOCK_INTERVAL (6011L)
+#define PM_RX_TX_SLOW_POINTER_BLOCK_INTERVAL_D (6012L)
+#define PM_RX_WRITE_POINTER_BLOCK_INTERVAL (6013L)
+#define PM_RX_WRITE_POINTER_BLOCK_INTERVAL_D (6014L)
+#define PM_TXRP_MEM_CTRL (6015L)
+#define PM_TXRP_MEM_CTRL_A (6016L)
+#define PM_TXRP_MEM_CTRL_CNT (6017L)
+#define PM_TXRP_MEM_DATA (6018L)
+#define PM_TXRP_MEM_DATA_BANK (6019L)
+#define PM_TXRP_MEM_DATA_ENTRY (6020L)
+#define PM_TXRP_MEM_DATA_HOST_BUFFER (6021L)
+#define PM_TXRP_MEM_DATA_VLD (6022L)
+#define PM_TX_READ_POINTER_BLOCK_INTERVAL (6023L)
+#define PM_TX_READ_POINTER_BLOCK_INTERVAL_D (6024L)
+/* PRM_NT100A01_01 */
+#define PRM_NT100A01_01_POWER (6025L)
+#define PRM_NT100A01_01_POWER_PU_NSEB (6026L)
+#define PRM_NT100A01_01_POWER_PU_PHY (6027L)
+#define PRM_NT100A01_01_RST (6028L)
+#define PRM_NT100A01_01_RST_PERIPH (6029L)
+#define PRM_NT100A01_01_RST_PLATFORM (6030L)
+/* PRM_NT50B01_01 */
+#define PRM_NT50B01_01_POWER (6031L)
+#define PRM_NT50B01_01_POWER_PU_NSEB (6032L)
+#define PRM_NT50B01_01_POWER_PU_PHY (6033L)
+#define PRM_NT50B01_01_RST (6034L)
+#define PRM_NT50B01_01_RST_PERIPH (6035L)
+#define PRM_NT50B01_01_RST_PLATFORM (6036L)
+/* PTP1588 */
+#define PTP1588_CONF (6037L)
+#define PTP1588_CONF_MII_RX_TX_LOOP (6038L)
+#define PTP1588_CONF_MII_TX_RX_LOOP (6039L)
+#define PTP1588_CONF_PHY_RST (6040L)
+#define PTP1588_CONF_PHY_RST1 (6041L)
+#define PTP1588_CONF_PHY_RST2 (6042L)
+#define PTP1588_CONF_PTP_CTRL_LOCAL (6043L)
+#define PTP1588_CONF_PTP_RX_CTRL (6044L)
+#define PTP1588_CONF_PTP_TX_CTRL (6045L)
+#define PTP1588_CONF_PTP_TX_CTRL_OS (6046L)
+#define PTP1588_CONF_RX_IGNORE_DEST_ADDR (6047L)
+#define PTP1588_CONF_TG_CMD (6048L)
+#define PTP1588_CONF_TG_MODE (6049L)
+#define PTP1588_CONF_TSM_MI_ACK (6050L)
+#define PTP1588_CONF_TSM_MI_BUSY (6051L)
+#define PTP1588_CONF_TSM_MI_ENA (6052L)
+#define PTP1588_CONF_TSM_MI_REQ (6053L)
+#define PTP1588_CONF_TX_IFG (6054L)
+#define PTP1588_CONF_TX_IGNORE_DEST_ADDR (6055L)
+#define PTP1588_CTRL (6056L)
+#define PTP1588_CTRL_CLK_ENABLE (6057L)
+#define PTP1588_CTRL_MII_RX_TX_LOOP (6058L)
+#define PTP1588_CTRL_MII_TX_RX_LOOP (6059L)
+#define PTP1588_CTRL_PRESENT (6060L)
+#define PTP1588_CTRL_RESET_N (6061L)
+#define PTP1588_CTRL_TS_MI_ACK (6062L)
+#define PTP1588_CTRL_TS_MI_BUSY (6063L)
+#define PTP1588_CTRL_TS_MI_ENA (6064L)
+#define PTP1588_CTRL_TS_MI_REQ (6065L)
+#define PTP1588_CTRL_TX_IFG (6066L)
+#define PTP1588_GP_DATA (6067L)
+#define PTP1588_GP_DATA_GPIO (6068L)
+#define PTP1588_GP_DATA_PWRDOWN_INTN (6069L)
+#define PTP1588_GP_DATA_TIMESYNC_CON (6070L)
+#define PTP1588_GP_DATA_LH (6071L)
+#define PTP1588_GP_DATA_LH_GPIO (6072L)
+#define PTP1588_GP_DATA_LH_PWRDOWN_INTN (6073L)
+#define PTP1588_GP_DATA_LH_TIMESYNC_CON (6074L)
+#define PTP1588_GP_DATA_LL (6075L)
+#define PTP1588_GP_DATA_LL_GPIO (6076L)
+#define PTP1588_GP_DATA_LL_PWRDOWN_INTN (6077L)
+#define PTP1588_GP_DATA_LL_TIMESYNC_CON (6078L)
+#define PTP1588_GP_OE (6079L)
+#define PTP1588_GP_OE_GPIO (6080L)
+#define PTP1588_GP_OE_PWRDOWN_INTN (6081L)
+#define PTP1588_GP_OE_TIMESYNC_CON (6082L)
+#define PTP1588_MAC_HOST_ADDR (6083L)
+#define PTP1588_MAC_HOST_ADDR_ADDR (6084L)
+#define PTP1588_MAC_HOST_ADDR_MDIO_ACCESS (6085L)
+#define PTP1588_MAC_HOST_ADDR_OPCODE (6086L)
+#define PTP1588_MAC_HOST_ADDR_RDY (6087L)
+#define PTP1588_MAC_HOST_DATA_LSB (6088L)
+#define PTP1588_MAC_HOST_DATA_LSB_DATA (6089L)
+#define PTP1588_MAC_HOST_DATA_MSB (6090L)
+#define PTP1588_MAC_HOST_DATA_MSB_DATA (6091L)
+#define PTP1588_MAC_INBAND_STAT (6092L)
+#define PTP1588_MAC_INBAND_STAT_DUPLEX (6093L)
+#define PTP1588_MAC_INBAND_STAT_LINK (6094L)
+#define PTP1588_MAC_INBAND_STAT_SPEED (6095L)
+#define PTP1588_MAC_MI_CONF (6096L)
+#define PTP1588_MAC_MI_CONF_ACCESS_TYPE (6097L)
+#define PTP1588_MAC_MI_CONF_ADDRESS (6098L)
+#define PTP1588_MAC_MI_CONF_RDY (6099L)
+#define PTP1588_MAC_MI_DATA (6100L)
+#define PTP1588_MAC_MI_DATA_DATA (6101L)
+#define PTP1588_RX_HOST_ADR_LSB (6102L)
+#define PTP1588_RX_HOST_ADR_LSB_LSB (6103L)
+#define PTP1588_RX_HOST_ADR_MSB (6104L)
+#define PTP1588_RX_HOST_ADR_MSB_MSB (6105L)
+#define PTP1588_RX_HOST_CONF (6106L)
+#define PTP1588_RX_HOST_CONF_ENA (6107L)
+#define PTP1588_RX_HOST_CONF_RDPTR (6108L)
+#define PTP1588_RX_HOST_CONF_REDUCED (6109L)
+#define PTP1588_RX_HOST_CTRL (6110L)
+#define PTP1588_RX_HOST_CTRL_ENA (6111L)
+#define PTP1588_RX_HOST_CTRL_RDPTR (6112L)
+#define PTP1588_RX_HOST_CTRL_REDUCED (6113L)
+#define PTP1588_STAT (6114L)
+#define PTP1588_STAT_DATA (6115L)
+#define PTP1588_STAT_CONF (6116L)
+#define PTP1588_STAT_CONF_INDEX (6117L)
+#define PTP1588_STAT_CONF_LOCK (6118L)
+#define PTP1588_STAT_CTRL (6119L)
+#define PTP1588_STAT_CTRL_INDEX (6120L)
+#define PTP1588_STAT_CTRL_LOCK (6121L)
+#define PTP1588_TX_FIRST_DAT (6122L)
+#define PTP1588_TX_FIRST_DAT_DAT (6123L)
+#define PTP1588_TX_LAST1_DAT (6124L)
+#define PTP1588_TX_LAST1_DAT_DAT (6125L)
+#define PTP1588_TX_LAST2_DAT (6126L)
+#define PTP1588_TX_LAST2_DAT_DAT (6127L)
+#define PTP1588_TX_LAST3_DAT (6128L)
+#define PTP1588_TX_LAST3_DAT_DAT (6129L)
+#define PTP1588_TX_LAST4_DAT (6130L)
+#define PTP1588_TX_LAST4_DAT_DAT (6131L)
+#define PTP1588_TX_MID_DAT (6132L)
+#define PTP1588_TX_MID_DAT_DAT (6133L)
+#define PTP1588_TX_PACKET_STATE (6134L)
+#define PTP1588_TX_PACKET_STATE_MSG_TYPE (6135L)
+#define PTP1588_TX_PACKET_STATE_PCK_TYPE (6136L)
+#define PTP1588_TX_PACKET_STATE_SEQ_ID (6137L)
+#define PTP1588_TX_PACKET_STATE_TEST_MARGIN (6138L)
+#define PTP1588_TX_PACKET_STATE_VALID (6139L)
+#define PTP1588_TX_STATUS (6140L)
+#define PTP1588_TX_STATUS_DB_ERR (6141L)
+#define PTP1588_TX_STATUS_DB_FULL (6142L)
+#define PTP1588_TX_STATUS_FIFO_STATUS (6143L)
+#define PTP1588_TX_STATUS_RDY (6144L)
+#define PTP1588_TX_STATUS_TG_ENA (6145L)
+#define PTP1588_TX_STATUS_TG_MODE (6146L)
+#define PTP1588_TX_TIMESTAMP_NS (6147L)
+#define PTP1588_TX_TIMESTAMP_NS_TIMESTAMP (6148L)
+#define PTP1588_TX_TIMESTAMP_SEC (6149L)
+#define PTP1588_TX_TIMESTAMP_SEC_TIMESTAMP (6150L)
+/* QM */
+#define QM_BLOCK_SIZE (6151L)
+#define QM_BLOCK_SIZE_CELLS (6152L)
+#define QM_CTRL (6153L)
+#define QM_CTRL_ACTIVE_QUEUES (6154L)
+#define QM_CTRL_ACTIVE_QUEUES_QPI_BYPASS (6155L)
+#define QM_CTRL_ENABLE (6156L)
+#define QM_CTRL_PRIORITY_SCHEME (6157L)
+#define QM_DEBUG_BLOCK_SIZE (6158L)
+#define QM_DEBUG_BLOCK_SIZE_CELLS (6159L)
+#define QM_DEBUG_CRC (6160L)
+#define QM_DEBUG_CRC_FORCE_ERROR (6161L)
+#define QM_DEBUG_SDRAM_SIZE (6162L)
+#define QM_DEBUG_SDRAM_SIZE_MASK (6163L)
+#define QM_GROUP_LIMIT_MEM_CTRL (6164L)
+#define QM_GROUP_LIMIT_MEM_CTRL_A (6165L)
+#define QM_GROUP_LIMIT_MEM_CTRL_CNT (6166L)
+#define QM_GROUP_LIMIT_MEM_DATA (6167L)
+#define QM_GROUP_LIMIT_MEM_DATA_LIMIT (6168L)
+#define QM_GROUP_MAPPING_MEM_CTRL (6169L)
+#define QM_GROUP_MAPPING_MEM_CTRL_A (6170L)
+#define QM_GROUP_MAPPING_MEM_CTRL_CNT (6171L)
+#define QM_GROUP_MAPPING_MEM_DATA (6172L)
+#define QM_GROUP_MAPPING_MEM_DATA_GROUP0 (6173L)
+#define QM_GROUP_MAPPING_MEM_DATA_GROUP1 (6174L)
+#define QM_GROUP_MAPPING_MEM_DATA_GROUP2 (6175L)
+#define QM_PRIO_LEVELS_MEM_CTRL (6176L)
+#define QM_PRIO_LEVELS_MEM_CTRL_A (6177L)
+#define QM_PRIO_LEVELS_MEM_CTRL_CNT (6178L)
+#define QM_PRIO_LEVELS_MEM_DATA (6179L)
+#define QM_PRIO_LEVELS_MEM_DATA_PRIO (6180L)
+#define QM_QUEUE_LIMIT_MEM_CTRL (6181L)
+#define QM_QUEUE_LIMIT_MEM_CTRL_A (6182L)
+#define QM_QUEUE_LIMIT_MEM_CTRL_CNT (6183L)
+#define QM_QUEUE_LIMIT_MEM_DATA (6184L)
+#define QM_QUEUE_LIMIT_MEM_DATA_LIMIT (6185L)
+#define QM_STATUS_BLOCKED (6186L)
+#define QM_STATUS_BLOCKED_D (6187L)
+#define QM_STATUS_BLOCKED_HI (6188L)
+#define QM_STATUS_BLOCKED_HI_D (6189L)
+#define QM_STATUS_BLOCKING (6190L)
+#define QM_STATUS_BLOCKING_D (6191L)
+#define QM_STATUS_BLOCKING_HI (6192L)
+#define QM_STATUS_BLOCKING_HI_D (6193L)
+#define QM_STATUS_CRC_ERROR (6194L)
+#define QM_STATUS_CRC_ERROR_CNT (6195L)
+#define QM_STATUS_EMPTY (6196L)
+#define QM_STATUS_EMPTY_D (6197L)
+#define QM_STATUS_EMPTY_HI (6198L)
+#define QM_STATUS_EMPTY_HI_D (6199L)
+#define QM_STATUS_FLUSH_DROP (6200L)
+#define QM_STATUS_FLUSH_DROP_CNT (6201L)
+#define QM_STATUS_SDRAM_BLOCK_MAX_USAGE (6202L)
+#define QM_STATUS_SDRAM_BLOCK_MAX_USAGE_D (6203L)
+#define QM_STATUS_SDRAM_BLOCK_USAGE (6204L)
+#define QM_STATUS_SDRAM_BLOCK_USAGE_D (6205L)
+#define QM_STATUS_SDRAM_CELL_MAX_USAGE (6206L)
+#define QM_STATUS_SDRAM_CELL_MAX_USAGE_D (6207L)
+#define QM_STATUS_SDRAM_CELL_USAGE (6208L)
+#define QM_STATUS_SDRAM_CELL_USAGE_D (6209L)
+/* QSL */
+#define QSL_LTX_CTRL (6210L)
+#define QSL_LTX_CTRL_ADR (6211L)
+#define QSL_LTX_CTRL_CNT (6212L)
+#define QSL_LTX_DATA (6213L)
+#define QSL_LTX_DATA_LR (6214L)
+#define QSL_LTX_DATA_TSA (6215L)
+#define QSL_LTX_DATA_TX_PORT (6216L)
+#define QSL_QEN_CTRL (6217L)
+#define QSL_QEN_CTRL_ADR (6218L)
+#define QSL_QEN_CTRL_CNT (6219L)
+#define QSL_QEN_DATA (6220L)
+#define QSL_QEN_DATA_EN (6221L)
+#define QSL_QST_CTRL (6222L)
+#define QSL_QST_CTRL_ADR (6223L)
+#define QSL_QST_CTRL_CNT (6224L)
+#define QSL_QST_DATA (6225L)
+#define QSL_QST_DATA_EN (6226L)
+#define QSL_QST_DATA_LRE (6227L)
+#define QSL_QST_DATA_QEN (6228L)
+#define QSL_QST_DATA_QUEUE (6229L)
+#define QSL_QST_DATA_TCI (6230L)
+#define QSL_QST_DATA_TX_PORT (6231L)
+#define QSL_QST_DATA_VEN (6232L)
+#define QSL_RCP_CTRL (6233L)
+#define QSL_RCP_CTRL_ADR (6234L)
+#define QSL_RCP_CTRL_CNT (6235L)
+#define QSL_RCP_DATA (6236L)
+#define QSL_RCP_DATA_CAO (6237L)
+#define QSL_RCP_DATA_DISCARD (6238L)
+#define QSL_RCP_DATA_DROP (6239L)
+#define QSL_RCP_DATA_LR (6240L)
+#define QSL_RCP_DATA_TBL_HI (6241L)
+#define QSL_RCP_DATA_TBL_IDX (6242L)
+#define QSL_RCP_DATA_TBL_LO (6243L)
+#define QSL_RCP_DATA_TBL_MSK (6244L)
+#define QSL_RCP_DATA_TSA (6245L)
+#define QSL_RCP_DATA_VLI (6246L)
+#define QSL_UNMQ_CTRL (6247L)
+#define QSL_UNMQ_CTRL_ADR (6248L)
+#define QSL_UNMQ_CTRL_CNT (6249L)
+#define QSL_UNMQ_DATA (6250L)
+#define QSL_UNMQ_DATA_DEST_QUEUE (6251L)
+#define QSL_UNMQ_DATA_EN (6252L)
+/* QSPI */
+#define QSPI_CR (6253L)
+#define QSPI_CR_CPHA (6254L)
+#define QSPI_CR_CPOL (6255L)
+#define QSPI_CR_LOOP (6256L)
+#define QSPI_CR_LSBF (6257L)
+#define QSPI_CR_MSSAE (6258L)
+#define QSPI_CR_MST (6259L)
+#define QSPI_CR_MTI (6260L)
+#define QSPI_CR_RXFIFO_RST (6261L)
+#define QSPI_CR_SPE (6262L)
+#define QSPI_CR_TXFIFO_RST (6263L)
+#define QSPI_DGIE (6264L)
+#define QSPI_DGIE_GIE (6265L)
+#define QSPI_DRR (6266L)
+#define QSPI_DRR_DATA_VAL (6267L)
+#define QSPI_DTR (6268L)
+#define QSPI_DTR_DATA_VAL (6269L)
+#define QSPI_IER (6270L)
+#define QSPI_IER_CMD_ERR (6271L)
+#define QSPI_IER_CPOL_CPHA_ERR (6272L)
+#define QSPI_IER_DRR_FULL (6273L)
+#define QSPI_IER_DRR_NEMPTY (6274L)
+#define QSPI_IER_DRR_OR (6275L)
+#define QSPI_IER_DTR_EMPTY (6276L)
+#define QSPI_IER_DTR_UR (6277L)
+#define QSPI_IER_LOOP_ERR (6278L)
+#define QSPI_IER_MODF (6279L)
+#define QSPI_IER_MSB_ERR (6280L)
+#define QSPI_IER_SLV_ERR (6281L)
+#define QSPI_IER_SLV_MODF (6282L)
+#define QSPI_IER_SLV_MS (6283L)
+#define QSPI_IER_TXFIFO_HEMPTY (6284L)
+#define QSPI_ISR (6285L)
+#define QSPI_ISR_CMD_ERR (6286L)
+#define QSPI_ISR_CPOL_CPHA_ERR (6287L)
+#define QSPI_ISR_DRR_FULL (6288L)
+#define QSPI_ISR_DRR_NEMPTY (6289L)
+#define QSPI_ISR_DRR_OR (6290L)
+#define QSPI_ISR_DTR_EMPTY (6291L)
+#define QSPI_ISR_DTR_UR (6292L)
+#define QSPI_ISR_LOOP_ERR (6293L)
+#define QSPI_ISR_MODF (6294L)
+#define QSPI_ISR_MSB_ERR (6295L)
+#define QSPI_ISR_SLV_ERR (6296L)
+#define QSPI_ISR_SLV_MODF (6297L)
+#define QSPI_ISR_SLV_MS (6298L)
+#define QSPI_ISR_TXFIFO_HEMPTY (6299L)
+#define QSPI_RX_FIFO_OCY (6300L)
+#define QSPI_RX_FIFO_OCY_OCY_VAL (6301L)
+#define QSPI_SR (6302L)
+#define QSPI_SR_CMD_ERR (6303L)
+#define QSPI_SR_CPOL_CPHA_ERR (6304L)
+#define QSPI_SR_LOOP_ERR (6305L)
+#define QSPI_SR_MODF (6306L)
+#define QSPI_SR_MSB_ERR (6307L)
+#define QSPI_SR_RXEMPTY (6308L)
+#define QSPI_SR_RXFULL (6309L)
+#define QSPI_SR_SLVMS (6310L)
+#define QSPI_SR_SLV_ERR (6311L)
+#define QSPI_SR_TXEMPTY (6312L)
+#define QSPI_SR_TXFULL (6313L)
+#define QSPI_SRR (6314L)
+#define QSPI_SRR_RST (6315L)
+#define QSPI_SSR (6316L)
+#define QSPI_SSR_SEL_SLV (6317L)
+#define QSPI_TX_FIFO_OCY (6318L)
+#define QSPI_TX_FIFO_OCY_OCY_VAL (6319L)
+/* R2DRP */
+#define R2DRP_CTRL (6320L)
+#define R2DRP_CTRL_ADR (6321L)
+#define R2DRP_CTRL_DATA (6322L)
+#define R2DRP_CTRL_DBG_BUSY (6323L)
+#define R2DRP_CTRL_DONE (6324L)
+#define R2DRP_CTRL_RES (6325L)
+#define R2DRP_CTRL_WREN (6326L)
+/* RAC */
+#define RAC_DBG_CTRL (6327L)
+#define RAC_DBG_CTRL_C (6328L)
+#define RAC_DBG_DATA (6329L)
+#define RAC_DBG_DATA_D (6330L)
+#define RAC_DUMMY0 (6331L)
+#define RAC_DUMMY1 (6332L)
+#define RAC_DUMMY2 (6333L)
+#define RAC_NDM_REGISTER (6334L)
+#define RAC_NDM_REGISTER_NDM (6335L)
+#define RAC_NMB_DATA (6336L)
+#define RAC_NMB_DATA_NMB_DATA (6337L)
+#define RAC_NMB_RD_ADR (6338L)
+#define RAC_NMB_RD_ADR_ADR (6339L)
+#define RAC_NMB_RD_ADR_RES (6340L)
+#define RAC_NMB_STATUS (6341L)
+#define RAC_NMB_STATUS_BUS_TIMEOUT (6342L)
+#define RAC_NMB_STATUS_NMB_READY (6343L)
+#define RAC_NMB_WR_ADR (6344L)
+#define RAC_NMB_WR_ADR_ADR (6345L)
+#define RAC_NMB_WR_ADR_RES (6346L)
+#define RAC_RAB_BUF_FREE (6347L)
+#define RAC_RAB_BUF_FREE_IB_FREE (6348L)
+#define RAC_RAB_BUF_FREE_IB_OVF (6349L)
+#define RAC_RAB_BUF_FREE_OB_FREE (6350L)
+#define RAC_RAB_BUF_FREE_OB_OVF (6351L)
+#define RAC_RAB_BUF_FREE_TIMEOUT (6352L)
+#define RAC_RAB_BUF_USED (6353L)
+#define RAC_RAB_BUF_USED_FLUSH (6354L)
+#define RAC_RAB_BUF_USED_IB_USED (6355L)
+#define RAC_RAB_BUF_USED_OB_USED (6356L)
+#define RAC_RAB_DMA_IB_HI (6357L)
+#define RAC_RAB_DMA_IB_HI_PHYADDR (6358L)
+#define RAC_RAB_DMA_IB_LO (6359L)
+#define RAC_RAB_DMA_IB_LO_PHYADDR (6360L)
+#define RAC_RAB_DMA_IB_RD (6361L)
+#define RAC_RAB_DMA_IB_RD_PTR (6362L)
+#define RAC_RAB_DMA_IB_WR (6363L)
+#define RAC_RAB_DMA_IB_WR_PTR (6364L)
+#define RAC_RAB_DMA_OB_HI (6365L)
+#define RAC_RAB_DMA_OB_HI_PHYADDR (6366L)
+#define RAC_RAB_DMA_OB_LO (6367L)
+#define RAC_RAB_DMA_OB_LO_PHYADDR (6368L)
+#define RAC_RAB_DMA_OB_WR (6369L)
+#define RAC_RAB_DMA_OB_WR_PTR (6370L)
+#define RAC_RAB_IB_DATA (6371L)
+#define RAC_RAB_IB_DATA_D (6372L)
+#define RAC_RAB_INIT (6373L)
+#define RAC_RAB_INIT_RAB (6374L)
+#define RAC_RAB_OB_DATA (6375L)
+#define RAC_RAB_OB_DATA_D (6376L)
+/* RBH */
+#define RBH_CTRL (6377L)
+#define RBH_CTRL_ENABLE_METADATA_HB (6378L)
+#define RBH_CTRL_ENABLE_PM (6379L)
+#define RBH_CTRL_ENABLE_QHM (6380L)
+#define RBH_CTRL_HB_MAX (6381L)
+#define RBH_CTRL_HB_SEGMENT_SIZE (6382L)
+#define RBH_CTRL_RESERVED (6383L)
+#define RBH_CTRL_RESET_CREDITS_QHM (6384L)
+#define RBH_DEB_REG1 (6385L)
+#define RBH_DEB_REG1_VALUE (6386L)
+#define RBH_DEB_REG2 (6387L)
+#define RBH_DEB_REG2_VALUE (6388L)
+#define RBH_DEB_REG3 (6389L)
+#define RBH_DEB_REG3_VALUE (6390L)
+#define RBH_FLUSH_ADR_HI (6391L)
+#define RBH_FLUSH_ADR_HI_VALUE (6392L)
+#define RBH_FLUSH_ADR_LO (6393L)
+#define RBH_FLUSH_ADR_LO_VALUE (6394L)
+#define RBH_HOST_BUF_SIZE_MEM_CTRL (6395L)
+#define RBH_HOST_BUF_SIZE_MEM_CTRL_A (6396L)
+#define RBH_HOST_BUF_SIZE_MEM_CTRL_CNT (6397L)
+#define RBH_HOST_BUF_SIZE_MEM_DATA (6398L)
+#define RBH_HOST_BUF_SIZE_MEM_DATA_HB_SEGMENT_CNT (6399L)
+#define RBH_STATUS (6400L)
+#define RBH_STATUS_BUFFER_EMPTY (6401L)
+#define RBH_STATUS_DWA_DATAFIFO_EMPTY (6402L)
+#define RBH_STATUS_PWA_DATAFIFO_EMPTY (6403L)
+#define RBH_WP_SET_MEM_CTRL (6404L)
+#define RBH_WP_SET_MEM_CTRL_A (6405L)
+#define RBH_WP_SET_MEM_CTRL_CNT (6406L)
+#define RBH_WP_SET_MEM_DATA (6407L)
+#define RBH_WP_SET_MEM_DATA_WP (6408L)
+/* RFD */
+#define RFD_CTRL (6409L)
+#define RFD_CTRL_CFP (6410L)
+#define RFD_CTRL_ISL (6411L)
+#define RFD_CTRL_PWMCW (6412L)
+#define RFD_MAX_FRAME_SIZE (6413L)
+#define RFD_MAX_FRAME_SIZE_MAX (6414L)
+#define RFD_TNL_VLAN (6415L)
+#define RFD_TNL_VLAN_TPID0 (6416L)
+#define RFD_TNL_VLAN_TPID1 (6417L)
+#define RFD_VLAN (6418L)
+#define RFD_VLAN_TPID0 (6419L)
+#define RFD_VLAN_TPID1 (6420L)
+#define RFD_VXLAN (6421L)
+#define RFD_VXLAN_DP0 (6422L)
+#define RFD_VXLAN_DP1 (6423L)
+/* RMC */
+#define RMC_CTRL (6424L)
+#define RMC_CTRL_BLOCK_KEEPA (6425L)
+#define RMC_CTRL_BLOCK_MAC_PORT (6426L)
+#define RMC_CTRL_BLOCK_RPP_SLICE (6427L)
+#define RMC_CTRL_BLOCK_STATT (6428L)
+#define RMC_CTRL_LAG_PHY_ODD_EVEN (6429L)
+#define RMC_DBG (6430L)
+#define RMC_DBG_MERGE (6431L)
+#define RMC_MAC_IF (6432L)
+#define RMC_MAC_IF_ERR (6433L)
+#define RMC_STATUS (6434L)
+#define RMC_STATUS_DESCR_FIFO_OF (6435L)
+#define RMC_STATUS_SF_RAM_OF (6436L)
+/* RNTC */
+#define RNTC_CTRL (6437L)
+#define RNTC_CTRL_RNTC_ENA (6438L)
+#define RNTC_STAT (6439L)
+#define RNTC_STAT_EMPTY (6440L)
+#define RNTC_TX_DATA (6441L)
+#define RNTC_TX_DATA_D (6442L)
+/* ROA */
+#define ROA_CONFIG (6443L)
+#define ROA_CONFIG_FWD_CELLBUILDER_PCKS (6444L)
+#define ROA_CONFIG_FWD_NON_NORMAL_PCKS (6445L)
+#define ROA_CONFIG_FWD_NORMAL_PCKS (6446L)
+#define ROA_CONFIG_FWD_RECIRCULATE (6447L)
+#define ROA_CONFIG_FWD_TXPORT0 (6448L)
+#define ROA_CONFIG_FWD_TXPORT1 (6449L)
+#define ROA_IGS (6450L)
+#define ROA_IGS_BYTE (6451L)
+#define ROA_IGS_BYTE_DROP (6452L)
+#define ROA_IGS_PKT (6453L)
+#define ROA_IGS_PKT_DROP (6454L)
+#define ROA_LAGCFG_CTRL (6455L)
+#define ROA_LAGCFG_CTRL_ADR (6456L)
+#define ROA_LAGCFG_CTRL_CNT (6457L)
+#define ROA_LAGCFG_DATA (6458L)
+#define ROA_LAGCFG_DATA_TXPHY_PORT (6459L)
+#define ROA_RCC (6460L)
+#define ROA_RCC_BYTE (6461L)
+#define ROA_RCC_BYTE_DROP (6462L)
+#define ROA_RCC_PKT (6463L)
+#define ROA_RCC_PKT_DROP (6464L)
+#define ROA_TUNCFG_CTRL (6465L)
+#define ROA_TUNCFG_CTRL_ADR (6466L)
+#define ROA_TUNCFG_CTRL_CNT (6467L)
+#define ROA_TUNCFG_DATA (6468L)
+#define ROA_TUNCFG_DATA_PUSH_TUNNEL (6469L)
+#define ROA_TUNCFG_DATA_RECIRCULATE (6470L)
+#define ROA_TUNCFG_DATA_RECIRC_BYPASS (6471L)
+#define ROA_TUNCFG_DATA_RECIRC_PORT (6472L)
+#define ROA_TUNCFG_DATA_TUN_IPCS_PRECALC (6473L)
+#define ROA_TUNCFG_DATA_TUN_IPCS_UPD (6474L)
+#define ROA_TUNCFG_DATA_TUN_IPTL_PRECALC (6475L)
+#define ROA_TUNCFG_DATA_TUN_IPTL_UPD (6476L)
+#define ROA_TUNCFG_DATA_TUN_IP_TYPE (6477L)
+#define ROA_TUNCFG_DATA_TUN_LEN (6478L)
+#define ROA_TUNCFG_DATA_TUN_TYPE (6479L)
+#define ROA_TUNCFG_DATA_TUN_VLAN (6480L)
+#define ROA_TUNCFG_DATA_TUN_VXLAN_UDP_LEN_UPD (6481L)
+#define ROA_TUNCFG_DATA_TX_LAG_IX (6482L)
+#define ROA_TUNHDR_CTRL (6483L)
+#define ROA_TUNHDR_CTRL_ADR (6484L)
+#define ROA_TUNHDR_CTRL_CNT (6485L)
+#define ROA_TUNHDR_DATA (6486L)
+#define ROA_TUNHDR_DATA_TUNNEL_HDR (6487L)
+/* RPL */
+#define RPL_EXT_CTRL (6488L)
+#define RPL_EXT_CTRL_ADR (6489L)
+#define RPL_EXT_CTRL_CNT (6490L)
+#define RPL_EXT_DATA (6491L)
+#define RPL_EXT_DATA_RPL_PTR (6492L)
+#define RPL_RCP_CTRL (6493L)
+#define RPL_RCP_CTRL_ADR (6494L)
+#define RPL_RCP_CTRL_CNT (6495L)
+#define RPL_RCP_DATA (6496L)
+#define RPL_RCP_DATA_DYN (6497L)
+#define RPL_RCP_DATA_EXT_PRIO (6498L)
+#define RPL_RCP_DATA_LEN (6499L)
+#define RPL_RCP_DATA_OFS (6500L)
+#define RPL_RCP_DATA_RPL_PTR (6501L)
+#define RPL_RPL_CTRL (6502L)
+#define RPL_RPL_CTRL_ADR (6503L)
+#define RPL_RPL_CTRL_CNT (6504L)
+#define RPL_RPL_DATA (6505L)
+#define RPL_RPL_DATA_VALUE (6506L)
+/* RPP_LR */
+#define RPP_LR_IFR_RCP_CTRL (6507L)
+#define RPP_LR_IFR_RCP_CTRL_ADR (6508L)
+#define RPP_LR_IFR_RCP_CTRL_CNT (6509L)
+#define RPP_LR_IFR_RCP_DATA (6510L)
+#define RPP_LR_IFR_RCP_DATA_EN (6511L)
+#define RPP_LR_IFR_RCP_DATA_MTU (6512L)
+#define RPP_LR_RCP_CTRL (6513L)
+#define RPP_LR_RCP_CTRL_ADR (6514L)
+#define RPP_LR_RCP_CTRL_CNT (6515L)
+#define RPP_LR_RCP_DATA (6516L)
+#define RPP_LR_RCP_DATA_EXP (6517L)
+/* RST7000 */
+#define RST7000_RST (6518L)
+#define RST7000_RST_SYS (6519L)
+/* RST7001 */
+#define RST7001_RST (6520L)
+#define RST7001_RST_SYS (6521L)
+/* RST9500 */
+#define RST9500_CTRL (6598L)
+#define RST9500_CTRL_PTP_MMCM_CLKSEL (6599L)
+#define RST9500_CTRL_TS_CLKSEL (6600L)
+#define RST9500_CTRL_TS_CLKSEL_OVERRIDE (6601L)
+#define RST9500_RST (6602L)
+#define RST9500_RST_DDR3 (6603L)
+#define RST9500_RST_DDR3_IDLY_MMCM (6604L)
+#define RST9500_RST_PERIPH (6605L)
+#define RST9500_RST_PHY10G_QPLL (6606L)
+#define RST9500_RST_PHY3S10G (6607L)
+#define RST9500_RST_PHY3S_MMCM (6608L)
+#define RST9500_RST_PTP (6609L)
+#define RST9500_RST_PTP_MMCM (6610L)
+#define RST9500_RST_RPP (6611L)
+#define RST9500_RST_SDC (6612L)
+#define RST9500_RST_SI5326 (6613L)
+#define RST9500_RST_SYS (6614L)
+#define RST9500_RST_TS (6615L)
+#define RST9500_RST_TS_MMCM (6616L)
+#define RST9500_RST_STAT (6617L)
+#define RST9500_RST_STAT_PCS_RESET_BY_SERDES (6618L)
+#define RST9500_STAT (6619L)
+#define RST9500_STAT_DDR3_IDLY_MMCM_LOCKED (6620L)
+#define RST9500_STAT_DDR3_MMCM_LOCKED (6621L)
+#define RST9500_STAT_DDR3_PLL_LOCKED (6622L)
+#define RST9500_STAT_PHY10G_QPLL_LOCK_0_1 (6623L)
+#define RST9500_STAT_PHY10G_QPLL_LOCK_2_3 (6624L)
+#define RST9500_STAT_PHY3S_MMCM_LOCKED (6625L)
+#define RST9500_STAT_PTP_MMCM_LOCKED (6626L)
+#define RST9500_STAT_SYNCE_MAIN_CLK_LOS (6627L)
+#define RST9500_STAT_SYS_MMCM_LOCKED (6628L)
+#define RST9500_STAT_TS_MMCM_LOCKED (6629L)
+#define RST9500_STICKY (6630L)
+#define RST9500_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6631L)
+#define RST9500_STICKY_DDR3_MMCM_UNLOCKED (6632L)
+#define RST9500_STICKY_DDR3_PLL_UNLOCKED (6633L)
+#define RST9500_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6634L)
+#define RST9500_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6635L)
+#define RST9500_STICKY_PHY3S_MMCM_UNLOCKED (6636L)
+#define RST9500_STICKY_PTP_MMCM_UNLOCKED (6637L)
+#define RST9500_STICKY_TS_MMCM_UNLOCKED (6638L)
+/* RST9501 */
+#define RST9501_CTRL (6639L)
+#define RST9501_CTRL_PTP_MMCM_CLKSEL (6640L)
+#define RST9501_CTRL_TS_CLKSEL (6641L)
+#define RST9501_CTRL_TS_CLKSEL_OVERRIDE (6642L)
+#define RST9501_RST (6643L)
+#define RST9501_RST_DDR3 (6644L)
+#define RST9501_RST_DDR3_IDLY_MMCM (6645L)
+#define RST9501_RST_PERIPH (6646L)
+#define RST9501_RST_PHY10G_QPLL (6647L)
+#define RST9501_RST_PHY3S10G (6648L)
+#define RST9501_RST_PHY3S_MMCM (6649L)
+#define RST9501_RST_PTP (6650L)
+#define RST9501_RST_PTP_MMCM (6651L)
+#define RST9501_RST_RPP (6652L)
+#define RST9501_RST_SDC (6653L)
+#define RST9501_RST_SI5326 (6654L)
+#define RST9501_RST_SYS (6655L)
+#define RST9501_RST_TS (6656L)
+#define RST9501_RST_TS_MMCM (6657L)
+#define RST9501_RST_STAT (6658L)
+#define RST9501_RST_STAT_PCS_RESET_BY_SERDES (6659L)
+#define RST9501_STAT (6660L)
+#define RST9501_STAT_DDR3_IDLY_MMCM_LOCKED (6661L)
+#define RST9501_STAT_DDR3_MMCM_LOCKED (6662L)
+#define RST9501_STAT_DDR3_PLL_LOCKED (6663L)
+#define RST9501_STAT_PHY10G_QPLL_LOCK_0_1 (6664L)
+#define RST9501_STAT_PHY10G_QPLL_LOCK_2_3 (6665L)
+#define RST9501_STAT_PHY3S_MMCM_LOCKED (6666L)
+#define RST9501_STAT_PTP_MMCM_LOCKED (6667L)
+#define RST9501_STAT_SYNCE_MAIN_CLK_LOS (6668L)
+#define RST9501_STAT_SYS_MMCM_LOCKED (6669L)
+#define RST9501_STAT_TS_MMCM_LOCKED (6670L)
+#define RST9501_STICKY (6671L)
+#define RST9501_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6672L)
+#define RST9501_STICKY_DDR3_MMCM_UNLOCKED (6673L)
+#define RST9501_STICKY_DDR3_PLL_UNLOCKED (6674L)
+#define RST9501_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6675L)
+#define RST9501_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6676L)
+#define RST9501_STICKY_PHY3S_MMCM_UNLOCKED (6677L)
+#define RST9501_STICKY_PTP_MMCM_UNLOCKED (6678L)
+#define RST9501_STICKY_TS_MMCM_UNLOCKED (6679L)
+/* RST9502 */
+#define RST9502_CTRL (6680L)
+#define RST9502_CTRL_PTP_MMCM_CLKSEL (6681L)
+#define RST9502_CTRL_TS_CLKSEL (6682L)
+#define RST9502_CTRL_TS_CLKSEL_OVERRIDE (6683L)
+#define RST9502_RST (6684L)
+#define RST9502_RST_DDR3 (6685L)
+#define RST9502_RST_DDR3_IDLY_MMCM (6686L)
+#define RST9502_RST_NSEB (6687L)
+#define RST9502_RST_PERIPH (6688L)
+#define RST9502_RST_PHY10G_QPLL (6689L)
+#define RST9502_RST_PHY3S10G (6690L)
+#define RST9502_RST_PHY3S_MMCM (6691L)
+#define RST9502_RST_PTP (6692L)
+#define RST9502_RST_PTP_MMCM (6693L)
+#define RST9502_RST_RPP (6694L)
+#define RST9502_RST_SDC (6695L)
+#define RST9502_RST_SI5326 (6696L)
+#define RST9502_RST_SYS (6697L)
+#define RST9502_RST_TS (6698L)
+#define RST9502_RST_TS_MMCM (6699L)
+#define RST9502_RST_STAT (6700L)
+#define RST9502_RST_STAT_PCS_RESET_BY_SERDES (6701L)
+#define RST9502_STAT (6702L)
+#define RST9502_STAT_DDR3_IDLY_MMCM_LOCKED (6703L)
+#define RST9502_STAT_DDR3_MMCM_LOCKED (6704L)
+#define RST9502_STAT_DDR3_PLL_LOCKED (6705L)
+#define RST9502_STAT_PHY10G_QPLL_LOCK_0_1 (6706L)
+#define RST9502_STAT_PHY10G_QPLL_LOCK_2_3 (6707L)
+#define RST9502_STAT_PHY3S_MMCM_LOCKED (6708L)
+#define RST9502_STAT_PTP_MMCM_LOCKED (6709L)
+#define RST9502_STAT_SYNCE_MAIN_CLK_LOS (6710L)
+#define RST9502_STAT_SYS_MMCM_LOCKED (6711L)
+#define RST9502_STAT_TS_MMCM_LOCKED (6712L)
+#define RST9502_STICKY (6713L)
+#define RST9502_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6714L)
+#define RST9502_STICKY_DDR3_MMCM_UNLOCKED (6715L)
+#define RST9502_STICKY_DDR3_PLL_UNLOCKED (6716L)
+#define RST9502_STICKY_PHY10G_QPLL_UNLOCK_0_1 (6717L)
+#define RST9502_STICKY_PHY10G_QPLL_UNLOCK_2_3 (6718L)
+#define RST9502_STICKY_PHY3S_MMCM_UNLOCKED (6719L)
+#define RST9502_STICKY_PTP_MMCM_UNLOCKED (6720L)
+#define RST9502_STICKY_TS_MMCM_UNLOCKED (6721L)
+/* RST9503 */
+#define RST9503_CTRL (6722L)
+#define RST9503_CTRL_PTP_MMCM_CLKSEL (6723L)
+#define RST9503_CTRL_TS_CLKSEL (6724L)
+#define RST9503_CTRL_TS_CLKSEL_OVERRIDE (6725L)
+#define RST9503_PORT_CLK_SEL (6726L)
+#define RST9503_PORT_CLK_SEL_PORT0 (6727L)
+#define RST9503_PORT_CLK_SEL_PORT1 (6728L)
+#define RST9503_RST (6729L)
+#define RST9503_RST_DDR3 (6730L)
+#define RST9503_RST_DDR3_IDLY_MMCM (6731L)
+#define RST9503_RST_MAC_RX (6732L)
+#define RST9503_RST_MAC_RX_MMCM (6733L)
+#define RST9503_RST_MAC_TX (6734L)
+#define RST9503_RST_NSEB (6735L)
+#define RST9503_RST_PCS_RX (6736L)
+#define RST9503_RST_PERIPH (6737L)
+#define RST9503_RST_PHY40G (6738L)
+#define RST9503_RST_PTP (6739L)
+#define RST9503_RST_PTP_MMCM (6740L)
+#define RST9503_RST_RPP (6741L)
+#define RST9503_RST_SDC (6742L)
+#define RST9503_RST_SERDES_RX (6743L)
+#define RST9503_RST_SERDES_TX (6744L)
+#define RST9503_RST_SI5326 (6745L)
+#define RST9503_RST_SYS (6746L)
+#define RST9503_RST_TS (6747L)
+#define RST9503_RST_TS_MMCM (6748L)
+#define RST9503_RST_STAT (6749L)
+#define RST9503_RST_STAT_PCS_RESET_BY_SERDES (6750L)
+#define RST9503_STAT (6751L)
+#define RST9503_STAT_DDR3_IDLY_MMCM_LOCKED (6752L)
+#define RST9503_STAT_DDR3_MMCM_LOCKED (6753L)
+#define RST9503_STAT_DDR3_PLL_LOCKED (6754L)
+#define RST9503_STAT_MAC_RX_MMCM_LOCKED (6755L)
+#define RST9503_STAT_PTP_MMCM_LOCKED (6756L)
+#define RST9503_STAT_SYNCE_MAIN_CLK_LOS (6757L)
+#define RST9503_STAT_SYS_MMCM_LOCKED (6758L)
+#define RST9503_STAT_TS_MMCM_LOCKED (6759L)
+#define RST9503_STICKY (6760L)
+#define RST9503_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6761L)
+#define RST9503_STICKY_DDR3_MMCM_UNLOCKED (6762L)
+#define RST9503_STICKY_DDR3_PLL_UNLOCKED (6763L)
+#define RST9503_STICKY_MAC_RX_MMCM_UNLOCKED (6764L)
+#define RST9503_STICKY_PTP_MMCM_UNLOCKED (6765L)
+#define RST9503_STICKY_TS_MMCM_UNLOCKED (6766L)
+/* RST9504 */
+#define RST9504_CTRL (6767L)
+#define RST9504_CTRL_PTP_MMCM_CLKSEL (6768L)
+#define RST9504_CTRL_TS_CLKSEL (6769L)
+#define RST9504_CTRL_TS_CLKSEL_OVERRIDE (6770L)
+#define RST9504_RST (6771L)
+#define RST9504_RST_DDR3 (6772L)
+#define RST9504_RST_DDR3_IDLY_MMCM (6773L)
+#define RST9504_RST_MAC_RX (6774L)
+#define RST9504_RST_MAC_RX_MMCM (6775L)
+#define RST9504_RST_MAC_TX (6776L)
+#define RST9504_RST_NSEB (6777L)
+#define RST9504_RST_PCS_RX (6778L)
+#define RST9504_RST_PERIPH (6779L)
+#define RST9504_RST_PHY100G (6780L)
+#define RST9504_RST_PTP (6781L)
+#define RST9504_RST_PTP_MMCM (6782L)
+#define RST9504_RST_RPP (6783L)
+#define RST9504_RST_SDC (6784L)
+#define RST9504_RST_SERDES_RX (6785L)
+#define RST9504_RST_SERDES_TX (6786L)
+#define RST9504_RST_SI5326 (6787L)
+#define RST9504_RST_SYS (6788L)
+#define RST9504_RST_TS (6789L)
+#define RST9504_RST_TS_MMCM (6790L)
+#define RST9504_RST_STAT (6791L)
+#define RST9504_RST_STAT_PCS_RESET_BY_SERDES (6792L)
+#define RST9504_STAT (6793L)
+#define RST9504_STAT_DDR3_IDLY_MMCM_LOCKED (6794L)
+#define RST9504_STAT_DDR3_MMCM_LOCKED (6795L)
+#define RST9504_STAT_DDR3_PLL_LOCKED (6796L)
+#define RST9504_STAT_MAC_RX_MMCM_LOCKED (6797L)
+#define RST9504_STAT_PTP_MMCM_LOCKED (6798L)
+#define RST9504_STAT_SYNCE_MAIN_CLK_LOS (6799L)
+#define RST9504_STAT_SYS_MMCM_LOCKED (6800L)
+#define RST9504_STAT_TS_MMCM_LOCKED (6801L)
+#define RST9504_STICKY (6802L)
+#define RST9504_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6803L)
+#define RST9504_STICKY_DDR3_MMCM_UNLOCKED (6804L)
+#define RST9504_STICKY_DDR3_PLL_UNLOCKED (6805L)
+#define RST9504_STICKY_MAC_RX_MMCM_UNLOCKED (6806L)
+#define RST9504_STICKY_PTP_MMCM_UNLOCKED (6807L)
+#define RST9504_STICKY_TS_MMCM_UNLOCKED (6808L)
+/* RST9505 */
+#define RST9505_CTRL (6809L)
+#define RST9505_CTRL_PTP_MMCM_CLKSEL (6810L)
+#define RST9505_CTRL_TS_CLKSEL (6811L)
+#define RST9505_CTRL_TS_CLKSEL_OVERRIDE (6812L)
+#define RST9505_RST (6813L)
+#define RST9505_RST_DDR3 (6814L)
+#define RST9505_RST_DDR3_IDLY_MMCM (6815L)
+#define RST9505_RST_MAC_RX (6816L)
+#define RST9505_RST_MAC_RX_MMCM (6817L)
+#define RST9505_RST_MAC_TX (6818L)
+#define RST9505_RST_NSEB (6819L)
+#define RST9505_RST_PCS_RX (6820L)
+#define RST9505_RST_PERIPH (6821L)
+#define RST9505_RST_PHY100G (6822L)
+#define RST9505_RST_PTP (6823L)
+#define RST9505_RST_PTP_MMCM (6824L)
+#define RST9505_RST_RPP (6825L)
+#define RST9505_RST_SDC (6826L)
+#define RST9505_RST_SERDES_RX (6827L)
+#define RST9505_RST_SERDES_TX (6828L)
+#define RST9505_RST_SI5326 (6829L)
+#define RST9505_RST_SYS (6830L)
+#define RST9505_RST_TS (6831L)
+#define RST9505_RST_TS_MMCM (6832L)
+#define RST9505_RST_STAT (6833L)
+#define RST9505_RST_STAT_PCS_RESET_BY_SERDES (6834L)
+#define RST9505_STAT (6835L)
+#define RST9505_STAT_DDR3_IDLY_MMCM_LOCKED (6836L)
+#define RST9505_STAT_DDR3_MMCM_LOCKED (6837L)
+#define RST9505_STAT_DDR3_PLL_LOCKED (6838L)
+#define RST9505_STAT_MAC_RX_MMCM_LOCKED (6839L)
+#define RST9505_STAT_PTP_MMCM_LOCKED (6840L)
+#define RST9505_STAT_SYNCE_MAIN_CLK_LOS (6841L)
+#define RST9505_STAT_SYS_MMCM_LOCKED (6842L)
+#define RST9505_STAT_TS_MMCM_LOCKED (6843L)
+#define RST9505_STICKY (6844L)
+#define RST9505_STICKY_DDR3_IDLY_MMCM_UNLOCKED (6845L)
+#define RST9505_STICKY_DDR3_MMCM_UNLOCKED (6846L)
+#define RST9505_STICKY_DDR3_PLL_UNLOCKED (6847L)
+#define RST9505_STICKY_MAC_RX_MMCM_UNLOCKED (6848L)
+#define RST9505_STICKY_PTP_MMCM_UNLOCKED (6849L)
+#define RST9505_STICKY_TS_MMCM_UNLOCKED (6850L)
+/* RST9506 */
+/* RST9507 */
+/* RST9508 */
+#define RST9508_CTRL (6851L)
+#define RST9508_CTRL_PTP_MMCM_CLKSEL (6852L)
+#define RST9508_CTRL_TS_CLKSEL (6853L)
+#define RST9508_CTRL_TS_CLKSEL_OVERRIDE (6854L)
+#define RST9508_CTRL_TS_CLKSEL_REF (6855L)
+#define RST9508_POWER (6856L)
+#define RST9508_POWER_PU_NSEB (6857L)
+#define RST9508_POWER_PU_PHY (6858L)
+#define RST9508_RST (6859L)
+#define RST9508_RST_CORE_MMCM (6860L)
+#define RST9508_RST_DDR4 (6861L)
+#define RST9508_RST_MAC_RX (6862L)
+#define RST9508_RST_PERIPH (6863L)
+#define RST9508_RST_PHY (6864L)
+#define RST9508_RST_PTP (6865L)
+#define RST9508_RST_PTP_MMCM (6866L)
+#define RST9508_RST_RPP (6867L)
+#define RST9508_RST_SDC (6868L)
+#define RST9508_RST_SYS (6869L)
+#define RST9508_RST_SYS_MMCM (6870L)
+#define RST9508_RST_TMC (6871L)
+#define RST9508_RST_TS (6872L)
+#define RST9508_RST_TSM_REF_MMCM (6873L)
+#define RST9508_RST_TS_MMCM (6874L)
+#define RST9508_STAT (6875L)
+#define RST9508_STAT_CORE_MMCM_LOCKED (6876L)
+#define RST9508_STAT_DDR4_MMCM_LOCKED (6877L)
+#define RST9508_STAT_DDR4_PLL_LOCKED (6878L)
+#define RST9508_STAT_PCI_SYS_MMCM_LOCKED (6879L)
+#define RST9508_STAT_PTP_MMCM_LOCKED (6880L)
+#define RST9508_STAT_SYS_MMCM_LOCKED (6881L)
+#define RST9508_STAT_TSM_REF_MMCM_LOCKED (6882L)
+#define RST9508_STAT_TS_MMCM_LOCKED (6883L)
+#define RST9508_STICKY (6884L)
+#define RST9508_STICKY_CORE_MMCM_UNLOCKED (6885L)
+#define RST9508_STICKY_DDR4_MMCM_UNLOCKED (6886L)
+#define RST9508_STICKY_DDR4_PLL_UNLOCKED (6887L)
+#define RST9508_STICKY_PCI_SYS_MMCM_UNLOCKED (6888L)
+#define RST9508_STICKY_PTP_MMCM_UNLOCKED (6889L)
+#define RST9508_STICKY_SYS_MMCM_UNLOCKED (6890L)
+#define RST9508_STICKY_TSM_REF_MMCM_UNLOCKED (6891L)
+#define RST9508_STICKY_TS_MMCM_UNLOCKED (6892L)
+/* RST9509 */
+/* RST9510 */
+/* RST9512 */
+#define RST9512_CTRL (6893L)
+#define RST9512_CTRL_PTP_MMCM_CLKSEL (6894L)
+#define RST9512_CTRL_TS_CLKSEL (6895L)
+#define RST9512_CTRL_TS_CLKSEL_OVERRIDE (6896L)
+#define RST9512_CTRL_TS_CLKSEL_REF (6897L)
+#define RST9512_POWER (6898L)
+#define RST9512_POWER_PU_NSEB (6899L)
+#define RST9512_POWER_PU_PHY (6900L)
+#define RST9512_RST (6901L)
+#define RST9512_RST_CORE_MMCM (6902L)
+#define RST9512_RST_DDR4 (6903L)
+#define RST9512_RST_MAC_RX (6904L)
+#define RST9512_RST_MAC_TX (6905L)
+#define RST9512_RST_PCS_RX (6906L)
+#define RST9512_RST_PERIPH (6907L)
+#define RST9512_RST_PHY (6908L)
+#define RST9512_RST_PTP (6909L)
+#define RST9512_RST_PTP_MMCM (6910L)
+#define RST9512_RST_RPP (6911L)
+#define RST9512_RST_SDC (6912L)
+#define RST9512_RST_SERDES_RX (6913L)
+#define RST9512_RST_SERDES_RX_DATAPATH (6914L)
+#define RST9512_RST_SERDES_TX (6915L)
+#define RST9512_RST_SYS (6916L)
+#define RST9512_RST_SYS_MMCM (6917L)
+#define RST9512_RST_TS (6918L)
+#define RST9512_RST_TSM_REF_MMCM (6919L)
+#define RST9512_RST_TS_MMCM (6920L)
+#define RST9512_STAT (6921L)
+#define RST9512_STAT_CORE_MMCM_LOCKED (6922L)
+#define RST9512_STAT_DDR4_MMCM_LOCKED (6923L)
+#define RST9512_STAT_DDR4_PLL_LOCKED (6924L)
+#define RST9512_STAT_PCI_SYS_MMCM_LOCKED (6925L)
+#define RST9512_STAT_PTP_MMCM_LOCKED (6926L)
+#define RST9512_STAT_SYS_MMCM_LOCKED (6927L)
+#define RST9512_STAT_TSM_REF_MMCM_LOCKED (6928L)
+#define RST9512_STAT_TS_MMCM_LOCKED (6929L)
+#define RST9512_STICKY (6930L)
+#define RST9512_STICKY_CORE_MMCM_UNLOCKED (6931L)
+#define RST9512_STICKY_DDR4_MMCM_UNLOCKED (6932L)
+#define RST9512_STICKY_DDR4_PLL_UNLOCKED (6933L)
+#define RST9512_STICKY_PCI_SYS_MMCM_UNLOCKED (6934L)
+#define RST9512_STICKY_PTP_MMCM_UNLOCKED (6935L)
+#define RST9512_STICKY_SYS_MMCM_UNLOCKED (6936L)
+#define RST9512_STICKY_TSM_REF_MMCM_UNLOCKED (6937L)
+#define RST9512_STICKY_TS_MMCM_UNLOCKED (6938L)
+/* RST9513 */
+/* RST9515 */
+#define RST9515_CTRL (6939L)
+#define RST9515_CTRL_PTP_MMCM_CLKSEL (6940L)
+#define RST9515_CTRL_TS_CLKSEL (6941L)
+#define RST9515_CTRL_TS_CLKSEL_OVERRIDE (6942L)
+#define RST9515_CTRL_TS_CLKSEL_REF (6943L)
+#define RST9515_POWER (6944L)
+#define RST9515_POWER_PU_NSEB (6945L)
+#define RST9515_POWER_PU_PHY (6946L)
+#define RST9515_RST (6947L)
+#define RST9515_RST_CORE_MMCM (6948L)
+#define RST9515_RST_DDR4 (6949L)
+#define RST9515_RST_MAC_RX (6950L)
+#define RST9515_RST_PERIPH (6951L)
+#define RST9515_RST_PHY (6952L)
+#define RST9515_RST_PTP (6953L)
+#define RST9515_RST_PTP_MMCM (6954L)
+#define RST9515_RST_RPP (6955L)
+#define RST9515_RST_SDC (6956L)
+#define RST9515_RST_SYS (6957L)
+#define RST9515_RST_SYS_MMCM (6958L)
+#define RST9515_RST_TMC (6959L)
+#define RST9515_RST_TS (6960L)
+#define RST9515_RST_TSM_REF_MMCM (6961L)
+#define RST9515_RST_TS_MMCM (6962L)
+#define RST9515_STAT (6963L)
+#define RST9515_STAT_CORE_MMCM_LOCKED (6964L)
+#define RST9515_STAT_DDR4_MMCM_LOCKED (6965L)
+#define RST9515_STAT_DDR4_PLL_LOCKED (6966L)
+#define RST9515_STAT_PCI_SYS_MMCM_LOCKED (6967L)
+#define RST9515_STAT_PTP_MMCM_LOCKED (6968L)
+#define RST9515_STAT_SYS_MMCM_LOCKED (6969L)
+#define RST9515_STAT_TSM_REF_MMCM_LOCKED (6970L)
+#define RST9515_STAT_TS_MMCM_LOCKED (6971L)
+#define RST9515_STICKY (6972L)
+#define RST9515_STICKY_CORE_MMCM_UNLOCKED (6973L)
+#define RST9515_STICKY_DDR4_MMCM_UNLOCKED (6974L)
+#define RST9515_STICKY_DDR4_PLL_UNLOCKED (6975L)
+#define RST9515_STICKY_PCI_SYS_MMCM_UNLOCKED (6976L)
+#define RST9515_STICKY_PTP_MMCM_UNLOCKED (6977L)
+#define RST9515_STICKY_SYS_MMCM_UNLOCKED (6978L)
+#define RST9515_STICKY_TSM_REF_MMCM_UNLOCKED (6979L)
+#define RST9515_STICKY_TS_MMCM_UNLOCKED (6980L)
+/* RST9516 */
+#define RST9516_CTRL (6981L)
+#define RST9516_CTRL_PTP_MMCM_CLKSEL (6982L)
+#define RST9516_CTRL_TS_CLKSEL (6983L)
+#define RST9516_CTRL_TS_CLKSEL_OVERRIDE (6984L)
+#define RST9516_CTRL_TS_CLKSEL_REF (6985L)
+#define RST9516_POWER (6986L)
+#define RST9516_POWER_PU_NSEB (6987L)
+#define RST9516_POWER_PU_PHY (6988L)
+#define RST9516_RST (6989L)
+#define RST9516_RST_CORE_MMCM (6990L)
+#define RST9516_RST_DDR4 (6991L)
+#define RST9516_RST_MAC_RX (6992L)
+#define RST9516_RST_PCS_RX (6993L)
+#define RST9516_RST_PERIPH (6994L)
+#define RST9516_RST_PHY (6995L)
+#define RST9516_RST_PTP (6996L)
+#define RST9516_RST_PTP_MMCM (6997L)
+#define RST9516_RST_RPP (6998L)
+#define RST9516_RST_SDC (6999L)
+#define RST9516_RST_SERDES_RX (7000L)
+#define RST9516_RST_SERDES_TX (7001L)
+#define RST9516_RST_SYS (7002L)
+#define RST9516_RST_SYS_MMCM (7003L)
+#define RST9516_RST_TMC (7004L)
+#define RST9516_RST_TS (7005L)
+#define RST9516_RST_TSM_REF_MMCM (7006L)
+#define RST9516_RST_TS_MMCM (7007L)
+#define RST9516_STAT (7008L)
+#define RST9516_STAT_CORE_MMCM_LOCKED (7009L)
+#define RST9516_STAT_DDR4_MMCM_LOCKED (7010L)
+#define RST9516_STAT_DDR4_PLL_LOCKED (7011L)
+#define RST9516_STAT_PCI_SYS_MMCM_LOCKED (7012L)
+#define RST9516_STAT_PTP_MMCM_LOCKED (7013L)
+#define RST9516_STAT_SYS_MMCM_LOCKED (7014L)
+#define RST9516_STAT_TSM_REF_MMCM_LOCKED (7015L)
+#define RST9516_STAT_TS_MMCM_LOCKED (7016L)
+#define RST9516_STICKY (7017L)
+#define RST9516_STICKY_CORE_MMCM_UNLOCKED (7018L)
+#define RST9516_STICKY_DDR4_MMCM_UNLOCKED (7019L)
+#define RST9516_STICKY_DDR4_PLL_UNLOCKED (7020L)
+#define RST9516_STICKY_PCI_SYS_MMCM_UNLOCKED (7021L)
+#define RST9516_STICKY_PTP_MMCM_UNLOCKED (7022L)
+#define RST9516_STICKY_SYS_MMCM_UNLOCKED (7023L)
+#define RST9516_STICKY_TSM_REF_MMCM_UNLOCKED (7024L)
+#define RST9516_STICKY_TS_MMCM_UNLOCKED (7025L)
+/* RST9517 */
+#define RST9517_CTRL (7026L)
+#define RST9517_CTRL_PTP_MMCM_CLKSEL (7027L)
+#define RST9517_CTRL_TS_CLKSEL (7028L)
+#define RST9517_CTRL_TS_CLKSEL_OVERRIDE (7029L)
+#define RST9517_RST (7030L)
+#define RST9517_RST_DDR3 (7031L)
+#define RST9517_RST_DDR3_IDLY_MMCM (7032L)
+#define RST9517_RST_NSEB (7033L)
+#define RST9517_RST_PERIPH (7034L)
+#define RST9517_RST_PHY10G_QPLL (7035L)
+#define RST9517_RST_PHY3S10G (7036L)
+#define RST9517_RST_PHY3S_MMCM (7037L)
+#define RST9517_RST_PTP (7038L)
+#define RST9517_RST_PTP_MMCM (7039L)
+#define RST9517_RST_RPP (7040L)
+#define RST9517_RST_SDC (7041L)
+#define RST9517_RST_SI5326 (7042L)
+#define RST9517_RST_SYS (7043L)
+#define RST9517_RST_TS (7044L)
+#define RST9517_RST_TS_MMCM (7045L)
+#define RST9517_RST_STAT (7046L)
+#define RST9517_RST_STAT_PCS_RESET_BY_SERDES (7047L)
+#define RST9517_STAT (7048L)
+#define RST9517_STAT_DDR3_IDLY_MMCM_LOCKED (7049L)
+#define RST9517_STAT_DDR3_MMCM_LOCKED (7050L)
+#define RST9517_STAT_DDR3_PLL_LOCKED (7051L)
+#define RST9517_STAT_PHY10G_QPLL_LOCK_0_1 (7052L)
+#define RST9517_STAT_PHY10G_QPLL_LOCK_2_3 (7053L)
+#define RST9517_STAT_PHY3S_MMCM_LOCKED (7054L)
+#define RST9517_STAT_PTP_MMCM_LOCKED (7055L)
+#define RST9517_STAT_SYNCE_MAIN_CLK_LOS (7056L)
+#define RST9517_STAT_SYS_MMCM_LOCKED (7057L)
+#define RST9517_STAT_TS_MMCM_LOCKED (7058L)
+#define RST9517_STICKY (7059L)
+#define RST9517_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7060L)
+#define RST9517_STICKY_DDR3_MMCM_UNLOCKED (7061L)
+#define RST9517_STICKY_DDR3_PLL_UNLOCKED (7062L)
+#define RST9517_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7063L)
+#define RST9517_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7064L)
+#define RST9517_STICKY_PHY3S_MMCM_UNLOCKED (7065L)
+#define RST9517_STICKY_PTP_MMCM_UNLOCKED (7066L)
+#define RST9517_STICKY_TS_MMCM_UNLOCKED (7067L)
+/* RST9519 */
+#define RST9519_CTRL (7068L)
+#define RST9519_CTRL_PTP_MMCM_CLKSEL (7069L)
+#define RST9519_CTRL_TS_CLKSEL (7070L)
+#define RST9519_CTRL_TS_CLKSEL_OVERRIDE (7071L)
+#define RST9519_RST (7072L)
+#define RST9519_RST_DDR3 (7073L)
+#define RST9519_RST_DDR3_IDLY_MMCM (7074L)
+#define RST9519_RST_PERIPH (7075L)
+#define RST9519_RST_PHY10G (7076L)
+#define RST9519_RST_PHY10G_QPLL (7077L)
+#define RST9519_RST_PTP (7078L)
+#define RST9519_RST_PTP_MMCM (7079L)
+#define RST9519_RST_RPP (7080L)
+#define RST9519_RST_SDC (7081L)
+#define RST9519_RST_SI5326 (7082L)
+#define RST9519_RST_SYS (7083L)
+#define RST9519_RST_TS (7084L)
+#define RST9519_RST_TS_MMCM (7085L)
+#define RST9519_RST_STAT (7086L)
+#define RST9519_RST_STAT_PCS_RESET_BY_SERDES (7087L)
+#define RST9519_STAT (7088L)
+#define RST9519_STAT_DDR3_IDLY_MMCM_LOCKED (7089L)
+#define RST9519_STAT_DDR3_MMCM_LOCKED (7090L)
+#define RST9519_STAT_DDR3_PLL_LOCKED (7091L)
+#define RST9519_STAT_PHY10G_QPLL_LOCK (7092L)
+#define RST9519_STAT_PTP_MMCM_LOCKED (7093L)
+#define RST9519_STAT_SYNCE_MAIN_CLK_LOS (7094L)
+#define RST9519_STAT_SYS_MMCM_LOCKED (7095L)
+#define RST9519_STAT_TS_MMCM_LOCKED (7096L)
+#define RST9519_STICKY (7097L)
+#define RST9519_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7098L)
+#define RST9519_STICKY_DDR3_MMCM_UNLOCKED (7099L)
+#define RST9519_STICKY_DDR3_PLL_UNLOCKED (7100L)
+#define RST9519_STICKY_PHY10G_QPLL_UNLOCK (7101L)
+#define RST9519_STICKY_PTP_MMCM_UNLOCKED (7102L)
+#define RST9519_STICKY_TS_MMCM_UNLOCKED (7103L)
+/* RST9520 */
+/* RST9521 */
+#define RST9521_CTRL (7104L)
+#define RST9521_CTRL_PTP_MMCM_CLKSEL (7105L)
+#define RST9521_CTRL_TS_CLKSEL (7106L)
+#define RST9521_CTRL_TS_CLKSEL_OVERRIDE (7107L)
+#define RST9521_POWER (7108L)
+#define RST9521_POWER_PU_NSEB (7109L)
+#define RST9521_POWER_PU_PHY (7110L)
+#define RST9521_RST (7111L)
+#define RST9521_RST_CORE_MMCM (7112L)
+#define RST9521_RST_DDR4 (7113L)
+#define RST9521_RST_MAC_RX (7114L)
+#define RST9521_RST_PERIPH (7115L)
+#define RST9521_RST_PHY (7116L)
+#define RST9521_RST_PTP (7117L)
+#define RST9521_RST_PTP_MMCM (7118L)
+#define RST9521_RST_RPP (7119L)
+#define RST9521_RST_SDC (7120L)
+#define RST9521_RST_SYS (7121L)
+#define RST9521_RST_SYS_MMCM (7122L)
+#define RST9521_RST_TMC (7123L)
+#define RST9521_RST_TS (7124L)
+#define RST9521_RST_TSM_REF_MMCM (7125L)
+#define RST9521_RST_TS_MMCM (7126L)
+#define RST9521_STAT (7127L)
+#define RST9521_STAT_CORE_MMCM_LOCKED (7128L)
+#define RST9521_STAT_DDR4_MMCM_LOCKED (7129L)
+#define RST9521_STAT_DDR4_PLL_LOCKED (7130L)
+#define RST9521_STAT_PTP_MMCM_LOCKED (7131L)
+#define RST9521_STAT_SYS_MMCM_LOCKED (7132L)
+#define RST9521_STAT_TS_MMCM_LOCKED (7133L)
+#define RST9521_STICKY (7134L)
+#define RST9521_STICKY_CORE_MMCM_UNLOCKED (7135L)
+#define RST9521_STICKY_DDR4_MMCM_UNLOCKED (7136L)
+#define RST9521_STICKY_DDR4_PLL_UNLOCKED (7137L)
+#define RST9521_STICKY_PTP_MMCM_UNLOCKED (7138L)
+#define RST9521_STICKY_SYS_MMCM_UNLOCKED (7139L)
+#define RST9521_STICKY_TS_MMCM_UNLOCKED (7140L)
+/* RST9522 */
+#define RST9522_CTRL (7141L)
+#define RST9522_CTRL_PTP_MMCM_CLKSEL (7142L)
+#define RST9522_CTRL_TS_CLKSEL (7143L)
+#define RST9522_CTRL_TS_CLKSEL_OVERRIDE (7144L)
+#define RST9522_CTRL_TS_CLKSEL_REF (7145L)
+#define RST9522_POWER (7146L)
+#define RST9522_POWER_PU_NSEB (7147L)
+#define RST9522_POWER_PU_PHY (7148L)
+#define RST9522_RST (7149L)
+#define RST9522_RST_CORE_MMCM (7150L)
+#define RST9522_RST_DDR4 (7151L)
+#define RST9522_RST_PERIPH (7152L)
+#define RST9522_RST_PHY10G (7153L)
+#define RST9522_RST_PHY10G_QPLL (7154L)
+#define RST9522_RST_PTP (7155L)
+#define RST9522_RST_PTP_MMCM (7156L)
+#define RST9522_RST_RPP (7157L)
+#define RST9522_RST_SDC (7158L)
+#define RST9522_RST_SYS (7159L)
+#define RST9522_RST_SYS_MMCM (7160L)
+#define RST9522_RST_TS (7161L)
+#define RST9522_RST_TSM_REF_MMCM (7162L)
+#define RST9522_RST_TS_MMCM (7163L)
+#define RST9522_STAT (7164L)
+#define RST9522_STAT_CORE_MMCM_LOCKED (7165L)
+#define RST9522_STAT_DDR4_MMCM_LOCKED (7166L)
+#define RST9522_STAT_DDR4_PLL_LOCKED (7167L)
+#define RST9522_STAT_PCI_SYS_MMCM_LOCKED (7168L)
+#define RST9522_STAT_PHY10G_QPLL_LOCKED (7169L)
+#define RST9522_STAT_PTP_MMCM_LOCKED (7170L)
+#define RST9522_STAT_SYS_MMCM_LOCKED (7171L)
+#define RST9522_STAT_TSM_REF_MMCM_LOCKED (7172L)
+#define RST9522_STAT_TS_MMCM_LOCKED (7173L)
+#define RST9522_STICKY (7174L)
+#define RST9522_STICKY_CORE_MMCM_UNLOCKED (7175L)
+#define RST9522_STICKY_DDR4_MMCM_UNLOCKED (7176L)
+#define RST9522_STICKY_DDR4_PLL_UNLOCKED (7177L)
+#define RST9522_STICKY_PCI_SYS_MMCM_UNLOCKED (7178L)
+#define RST9522_STICKY_PHY10G_QPLL_UNLOCKED (7179L)
+#define RST9522_STICKY_PTP_MMCM_UNLOCKED (7180L)
+#define RST9522_STICKY_SYS_MMCM_UNLOCKED (7181L)
+#define RST9522_STICKY_TSM_REF_MMCM_UNLOCKED (7182L)
+#define RST9522_STICKY_TS_MMCM_UNLOCKED (7183L)
+/* RST9523 */
+/* RST9524 */
+#define RST9524_CTRL (7184L)
+#define RST9524_CTRL_PTP_MMCM_CLKSEL (7185L)
+#define RST9524_CTRL_TS_CLKSEL (7186L)
+#define RST9524_CTRL_TS_CLKSEL_OVERRIDE (7187L)
+#define RST9524_POWER (7188L)
+#define RST9524_POWER_PU_NSEB (7189L)
+#define RST9524_POWER_PU_PHY (7190L)
+#define RST9524_RST (7191L)
+#define RST9524_RST_CORE_MMCM (7192L)
+#define RST9524_RST_DDR4 (7193L)
+#define RST9524_RST_MAC_RX (7194L)
+#define RST9524_RST_PERIPH (7195L)
+#define RST9524_RST_PHY (7196L)
+#define RST9524_RST_PTP (7197L)
+#define RST9524_RST_PTP_MMCM (7198L)
+#define RST9524_RST_RPP (7199L)
+#define RST9524_RST_SDC (7200L)
+#define RST9524_RST_SYS (7201L)
+#define RST9524_RST_SYS_MMCM (7202L)
+#define RST9524_RST_TMC (7203L)
+#define RST9524_RST_TS (7204L)
+#define RST9524_RST_TS_MMCM (7205L)
+#define RST9524_STAT (7206L)
+#define RST9524_STAT_CORE_MMCM_LOCKED (7207L)
+#define RST9524_STAT_DDR4_MMCM_LOCKED (7208L)
+#define RST9524_STAT_DDR4_PLL_LOCKED (7209L)
+#define RST9524_STAT_PTP_MMCM_LOCKED (7210L)
+#define RST9524_STAT_SYS_MMCM_LOCKED (7211L)
+#define RST9524_STAT_TS_MMCM_LOCKED (7212L)
+#define RST9524_STICKY (7213L)
+#define RST9524_STICKY_CORE_MMCM_UNLOCKED (7214L)
+#define RST9524_STICKY_DDR4_MMCM_UNLOCKED (7215L)
+#define RST9524_STICKY_DDR4_PLL_UNLOCKED (7216L)
+#define RST9524_STICKY_PTP_MMCM_UNLOCKED (7217L)
+#define RST9524_STICKY_SYS_MMCM_UNLOCKED (7218L)
+#define RST9524_STICKY_TS_MMCM_UNLOCKED (7219L)
+/* RST9525 */
+#define RST9525_CTRL (7220L)
+#define RST9525_CTRL_PTP_MMCM_CLKSEL (7221L)
+#define RST9525_CTRL_TS_CLKSEL (7222L)
+#define RST9525_CTRL_TS_CLKSEL_OVERRIDE (7223L)
+#define RST9525_CTRL_TS_CLKSEL_REF (7224L)
+#define RST9525_POWER (7225L)
+#define RST9525_POWER_PU_NSEB (7226L)
+#define RST9525_POWER_PU_PHY (7227L)
+#define RST9525_RST (7228L)
+#define RST9525_RST_CORE_MMCM (7229L)
+#define RST9525_RST_DDR4 (7230L)
+#define RST9525_RST_MAC_RX (7231L)
+#define RST9525_RST_MAC_TX (7232L)
+#define RST9525_RST_PCS_RX (7233L)
+#define RST9525_RST_PERIPH (7234L)
+#define RST9525_RST_PHY (7235L)
+#define RST9525_RST_PTP (7236L)
+#define RST9525_RST_PTP_MMCM (7237L)
+#define RST9525_RST_RPP (7238L)
+#define RST9525_RST_SDC (7239L)
+#define RST9525_RST_SERDES_RX (7240L)
+#define RST9525_RST_SERDES_RX_DATAPATH (7241L)
+#define RST9525_RST_SERDES_TX (7242L)
+#define RST9525_RST_SYS (7243L)
+#define RST9525_RST_SYS_MMCM (7244L)
+#define RST9525_RST_TS (7245L)
+#define RST9525_RST_TSM_REF_MMCM (7246L)
+#define RST9525_RST_TS_MMCM (7247L)
+#define RST9525_STAT (7248L)
+#define RST9525_STAT_CORE_MMCM_LOCKED (7249L)
+#define RST9525_STAT_DDR4_MMCM_LOCKED (7250L)
+#define RST9525_STAT_DDR4_PLL_LOCKED (7251L)
+#define RST9525_STAT_PCI_SYS_MMCM_LOCKED (7252L)
+#define RST9525_STAT_PTP_MMCM_LOCKED (7253L)
+#define RST9525_STAT_SYS_MMCM_LOCKED (7254L)
+#define RST9525_STAT_TSM_REF_MMCM_LOCKED (7255L)
+#define RST9525_STAT_TS_MMCM_LOCKED (7256L)
+#define RST9525_STICKY (7257L)
+#define RST9525_STICKY_CORE_MMCM_UNLOCKED (7258L)
+#define RST9525_STICKY_DDR4_MMCM_UNLOCKED (7259L)
+#define RST9525_STICKY_DDR4_PLL_UNLOCKED (7260L)
+#define RST9525_STICKY_PCI_SYS_MMCM_UNLOCKED (7261L)
+#define RST9525_STICKY_PTP_MMCM_UNLOCKED (7262L)
+#define RST9525_STICKY_SYS_MMCM_UNLOCKED (7263L)
+#define RST9525_STICKY_TSM_REF_MMCM_UNLOCKED (7264L)
+#define RST9525_STICKY_TS_MMCM_UNLOCKED (7265L)
+/* RST9526 */
+#define RST9526_CTRL (7266L)
+#define RST9526_CTRL_PTP_MMCM_CLKSEL (7267L)
+#define RST9526_CTRL_TS_CLKSEL (7268L)
+#define RST9526_CTRL_TS_CLKSEL_OVERRIDE (7269L)
+#define RST9526_POWER (7270L)
+#define RST9526_POWER_PU_NSEB (7271L)
+#define RST9526_POWER_PU_PHY (7272L)
+#define RST9526_RST (7273L)
+#define RST9526_RST_CORE_MMCM (7274L)
+#define RST9526_RST_DDR4 (7275L)
+#define RST9526_RST_MAC_RX (7276L)
+#define RST9526_RST_MAC_TX (7277L)
+#define RST9526_RST_PCS_RX (7278L)
+#define RST9526_RST_PERIPH (7279L)
+#define RST9526_RST_PHY (7280L)
+#define RST9526_RST_PTP (7281L)
+#define RST9526_RST_PTP_MMCM (7282L)
+#define RST9526_RST_RPP (7283L)
+#define RST9526_RST_SDC (7284L)
+#define RST9526_RST_SERDES_RX (7285L)
+#define RST9526_RST_SERDES_RX_DATAPATH (7286L)
+#define RST9526_RST_SERDES_TX (7287L)
+#define RST9526_RST_SYS (7288L)
+#define RST9526_RST_SYS_MMCM (7289L)
+#define RST9526_RST_TMC (7290L)
+#define RST9526_RST_TS (7291L)
+#define RST9526_RST_TS_MMCM (7292L)
+#define RST9526_STAT (7293L)
+#define RST9526_STAT_CORE_MMCM_LOCKED (7294L)
+#define RST9526_STAT_DDR4_MMCM_LOCKED (7295L)
+#define RST9526_STAT_DDR4_PLL_LOCKED (7296L)
+#define RST9526_STAT_PTP_MMCM_LOCKED (7297L)
+#define RST9526_STAT_SYS_MMCM_LOCKED (7298L)
+#define RST9526_STAT_TS_MMCM_LOCKED (7299L)
+#define RST9526_STICKY (7300L)
+#define RST9526_STICKY_CORE_MMCM_UNLOCKED (7301L)
+#define RST9526_STICKY_DDR4_MMCM_UNLOCKED (7302L)
+#define RST9526_STICKY_DDR4_PLL_UNLOCKED (7303L)
+#define RST9526_STICKY_PTP_MMCM_UNLOCKED (7304L)
+#define RST9526_STICKY_SYS_MMCM_UNLOCKED (7305L)
+#define RST9526_STICKY_TS_MMCM_UNLOCKED (7306L)
+/* RST9527 */
+#define RST9527_CTRL (7307L)
+#define RST9527_CTRL_PTP_MMCM_CLKSEL (7308L)
+#define RST9527_CTRL_TS_CLKSEL (7309L)
+#define RST9527_CTRL_TS_CLKSEL_OVERRIDE (7310L)
+#define RST9527_POWER (7311L)
+#define RST9527_POWER_PU_NSEB (7312L)
+#define RST9527_POWER_PU_PHY (7313L)
+#define RST9527_RST (7314L)
+#define RST9527_RST_CORE_MMCM (7315L)
+#define RST9527_RST_DDR4 (7316L)
+#define RST9527_RST_MAC_RX (7317L)
+#define RST9527_RST_MAC_TX (7318L)
+#define RST9527_RST_PCS_RX (7319L)
+#define RST9527_RST_PERIPH (7320L)
+#define RST9527_RST_PHY (7321L)
+#define RST9527_RST_PTP (7322L)
+#define RST9527_RST_PTP_MMCM (7323L)
+#define RST9527_RST_RPP (7324L)
+#define RST9527_RST_SDC (7325L)
+#define RST9527_RST_SERDES_RX (7326L)
+#define RST9527_RST_SERDES_RX_DATAPATH (7327L)
+#define RST9527_RST_SERDES_TX (7328L)
+#define RST9527_RST_SYS (7329L)
+#define RST9527_RST_SYS_MMCM (7330L)
+#define RST9527_RST_TMC (7331L)
+#define RST9527_RST_TS (7332L)
+#define RST9527_RST_TS_MMCM (7333L)
+#define RST9527_STAT (7334L)
+#define RST9527_STAT_CORE_MMCM_LOCKED (7335L)
+#define RST9527_STAT_DDR4_MMCM_LOCKED (7336L)
+#define RST9527_STAT_DDR4_PLL_LOCKED (7337L)
+#define RST9527_STAT_PTP_MMCM_LOCKED (7338L)
+#define RST9527_STAT_SYS_MMCM_LOCKED (7339L)
+#define RST9527_STAT_TS_MMCM_LOCKED (7340L)
+#define RST9527_STICKY (7341L)
+#define RST9527_STICKY_CORE_MMCM_UNLOCKED (7342L)
+#define RST9527_STICKY_DDR4_MMCM_UNLOCKED (7343L)
+#define RST9527_STICKY_DDR4_PLL_UNLOCKED (7344L)
+#define RST9527_STICKY_PTP_MMCM_UNLOCKED (7345L)
+#define RST9527_STICKY_SYS_MMCM_UNLOCKED (7346L)
+#define RST9527_STICKY_TS_MMCM_UNLOCKED (7347L)
+/* RST9528 */
+/* RST9529 */
+#define RST9529_CTRL (7348L)
+#define RST9529_CTRL_PTP_MMCM_CLKSEL (7349L)
+#define RST9529_CTRL_TS_CLKSEL (7350L)
+#define RST9529_CTRL_TS_CLKSEL_OVERRIDE (7351L)
+#define RST9529_CTRL_TS_CLKSEL_REF (7352L)
+#define RST9529_POWER (7353L)
+#define RST9529_POWER_PU_NSEB (7354L)
+#define RST9529_POWER_PU_PHY (7355L)
+#define RST9529_RST (7356L)
+#define RST9529_RST_CORE_MMCM (7357L)
+#define RST9529_RST_DDR4 (7358L)
+#define RST9529_RST_PERIPH (7359L)
+#define RST9529_RST_PHY (7360L)
+#define RST9529_RST_PTP (7361L)
+#define RST9529_RST_PTP_MMCM (7362L)
+#define RST9529_RST_RPP (7363L)
+#define RST9529_RST_SDC (7364L)
+#define RST9529_RST_SYS (7365L)
+#define RST9529_RST_SYS_MMCM (7366L)
+#define RST9529_RST_TS (7367L)
+#define RST9529_RST_TSM_REF_MMCM (7368L)
+#define RST9529_RST_TS_MMCM (7369L)
+#define RST9529_STAT (7370L)
+#define RST9529_STAT_CORE_MMCM_LOCKED (7371L)
+#define RST9529_STAT_DDR4_MMCM_LOCKED (7372L)
+#define RST9529_STAT_DDR4_PLL_LOCKED (7373L)
+#define RST9529_STAT_PCI_SYS_MMCM_LOCKED (7374L)
+#define RST9529_STAT_PTP_MMCM_LOCKED (7375L)
+#define RST9529_STAT_SYS_MMCM_LOCKED (7376L)
+#define RST9529_STAT_TSM_REF_MMCM_LOCKED (7377L)
+#define RST9529_STAT_TS_MMCM_LOCKED (7378L)
+#define RST9529_STICKY (7379L)
+#define RST9529_STICKY_CORE_MMCM_UNLOCKED (7380L)
+#define RST9529_STICKY_DDR4_MMCM_UNLOCKED (7381L)
+#define RST9529_STICKY_DDR4_PLL_UNLOCKED (7382L)
+#define RST9529_STICKY_PCI_SYS_MMCM_UNLOCKED (7383L)
+#define RST9529_STICKY_PTP_MMCM_UNLOCKED (7384L)
+#define RST9529_STICKY_SYS_MMCM_UNLOCKED (7385L)
+#define RST9529_STICKY_TSM_REF_MMCM_UNLOCKED (7386L)
+#define RST9529_STICKY_TS_MMCM_UNLOCKED (7387L)
+/* RST9530 */
+#define RST9530_CTRL (7388L)
+#define RST9530_CTRL_PTP_MMCM_CLKSEL (7389L)
+#define RST9530_CTRL_TS_CLKSEL (7390L)
+#define RST9530_CTRL_TS_CLKSEL_OVERRIDE (7391L)
+#define RST9530_CTRL_TS_CLKSEL_REF (7392L)
+#define RST9530_POWER (7393L)
+#define RST9530_POWER_PU_NSEB (7394L)
+#define RST9530_POWER_PU_PHY (7395L)
+#define RST9530_RST (7396L)
+#define RST9530_RST_CORE_MMCM (7397L)
+#define RST9530_RST_DDR4 (7398L)
+#define RST9530_RST_NFV_OVS (7399L)
+#define RST9530_RST_PERIPH (7400L)
+#define RST9530_RST_PHY (7401L)
+#define RST9530_RST_PTP (7402L)
+#define RST9530_RST_PTP_MMCM (7403L)
+#define RST9530_RST_RPP (7404L)
+#define RST9530_RST_SDC (7405L)
+#define RST9530_RST_SYS (7406L)
+#define RST9530_RST_SYS_MMCM (7407L)
+#define RST9530_RST_TMC (7408L)
+#define RST9530_RST_TS (7409L)
+#define RST9530_RST_TSM_REF_MMCM (7410L)
+#define RST9530_RST_TS_MMCM (7411L)
+#define RST9530_STAT (7412L)
+#define RST9530_STAT_CORE_MMCM_LOCKED (7413L)
+#define RST9530_STAT_DDR4_MMCM_LOCKED (7414L)
+#define RST9530_STAT_DDR4_PLL_LOCKED (7415L)
+#define RST9530_STAT_PTP_MMCM_LOCKED (7416L)
+#define RST9530_STAT_SYS_MMCM_LOCKED (7417L)
+#define RST9530_STAT_TSM_REF_MMCM_LOCKED (7418L)
+#define RST9530_STAT_TS_MMCM_LOCKED (7419L)
+#define RST9530_STICKY (7420L)
+#define RST9530_STICKY_CORE_MMCM_UNLOCKED (7421L)
+#define RST9530_STICKY_DDR4_MMCM_UNLOCKED (7422L)
+#define RST9530_STICKY_DDR4_PLL_UNLOCKED (7423L)
+#define RST9530_STICKY_PCI_SYS_MMCM_UNLOCKED (7424L)
+#define RST9530_STICKY_PTP_MMCM_UNLOCKED (7425L)
+#define RST9530_STICKY_SYS_MMCM_UNLOCKED (7426L)
+#define RST9530_STICKY_TSM_REF_MMCM_UNLOCKED (7427L)
+#define RST9530_STICKY_TS_MMCM_UNLOCKED (7428L)
+/* RST9531 */
+#define RST9531_CTRL (7429L)
+#define RST9531_CTRL_PTP_MMCM_CLKSEL (7430L)
+#define RST9531_CTRL_TS_CLKSEL (7431L)
+#define RST9531_CTRL_TS_CLKSEL_OVERRIDE (7432L)
+#define RST9531_CTRL_TS_CLKSEL_REF (7433L)
+#define RST9531_POWER (7434L)
+#define RST9531_POWER_PU_NSEB (7435L)
+#define RST9531_POWER_PU_PHY (7436L)
+#define RST9531_RST (7437L)
+#define RST9531_RST_CORE_MMCM (7438L)
+#define RST9531_RST_DDR4 (7439L)
+#define RST9531_RST_PERIPH (7440L)
+#define RST9531_RST_PHY (7441L)
+#define RST9531_RST_PTP (7442L)
+#define RST9531_RST_PTP_MMCM (7443L)
+#define RST9531_RST_RPP (7444L)
+#define RST9531_RST_SDC (7445L)
+#define RST9531_RST_SYS (7446L)
+#define RST9531_RST_SYS_MMCM (7447L)
+#define RST9531_RST_TS (7448L)
+#define RST9531_RST_TSM_REF_MMCM (7449L)
+#define RST9531_RST_TS_MMCM (7450L)
+#define RST9531_STAT (7451L)
+#define RST9531_STAT_CORE_MMCM_LOCKED (7452L)
+#define RST9531_STAT_DDR4_MMCM_LOCKED (7453L)
+#define RST9531_STAT_DDR4_PLL_LOCKED (7454L)
+#define RST9531_STAT_PCI_SYS_MMCM_LOCKED (7455L)
+#define RST9531_STAT_PTP_MMCM_LOCKED (7456L)
+#define RST9531_STAT_SYS_MMCM_LOCKED (7457L)
+#define RST9531_STAT_TSM_REF_MMCM_LOCKED (7458L)
+#define RST9531_STAT_TS_MMCM_LOCKED (7459L)
+#define RST9531_STICKY (7460L)
+#define RST9531_STICKY_CORE_MMCM_UNLOCKED (7461L)
+#define RST9531_STICKY_DDR4_MMCM_UNLOCKED (7462L)
+#define RST9531_STICKY_DDR4_PLL_UNLOCKED (7463L)
+#define RST9531_STICKY_PCI_SYS_MMCM_UNLOCKED (7464L)
+#define RST9531_STICKY_PTP_MMCM_UNLOCKED (7465L)
+#define RST9531_STICKY_SYS_MMCM_UNLOCKED (7466L)
+#define RST9531_STICKY_TSM_REF_MMCM_UNLOCKED (7467L)
+#define RST9531_STICKY_TS_MMCM_UNLOCKED (7468L)
+/* RST9532 */
+#define RST9532_CTRL (7469L)
+#define RST9532_CTRL_PTP_MMCM_CLKSEL (7470L)
+#define RST9532_CTRL_TS_CLKSEL (7471L)
+#define RST9532_CTRL_TS_CLKSEL_OVERRIDE (7472L)
+#define RST9532_POWER (7473L)
+#define RST9532_POWER_PU_NSEB (7474L)
+#define RST9532_POWER_PU_PHY (7475L)
+#define RST9532_RST (7476L)
+#define RST9532_RST_CORE_MMCM (7477L)
+#define RST9532_RST_DDR4 (7478L)
+#define RST9532_RST_PERIPH (7479L)
+#define RST9532_RST_PHY (7480L)
+#define RST9532_RST_PTP (7481L)
+#define RST9532_RST_PTP_MMCM (7482L)
+#define RST9532_RST_RPP (7483L)
+#define RST9532_RST_SDC (7484L)
+#define RST9532_RST_SYS (7485L)
+#define RST9532_RST_SYS_MMCM (7486L)
+#define RST9532_RST_TMC (7487L)
+#define RST9532_RST_TS (7488L)
+#define RST9532_RST_TS_MMCM (7489L)
+#define RST9532_STAT (7490L)
+#define RST9532_STAT_CORE_MMCM_LOCKED (7491L)
+#define RST9532_STAT_DDR4_MMCM_LOCKED (7492L)
+#define RST9532_STAT_DDR4_PLL_LOCKED (7493L)
+#define RST9532_STAT_PTP_MMCM_LOCKED (7494L)
+#define RST9532_STAT_SYS_MMCM_LOCKED (7495L)
+#define RST9532_STAT_TS_MMCM_LOCKED (7496L)
+#define RST9532_STICKY (7497L)
+#define RST9532_STICKY_CORE_MMCM_UNLOCKED (7498L)
+#define RST9532_STICKY_DDR4_MMCM_UNLOCKED (7499L)
+#define RST9532_STICKY_DDR4_PLL_UNLOCKED (7500L)
+#define RST9532_STICKY_PTP_MMCM_UNLOCKED (7501L)
+#define RST9532_STICKY_SYS_MMCM_UNLOCKED (7502L)
+#define RST9532_STICKY_TS_MMCM_UNLOCKED (7503L)
+/* RST9533 */
+#define RST9533_CTRL (7504L)
+#define RST9533_CTRL_PTP_MMCM_CLKSEL (7505L)
+#define RST9533_CTRL_TS_CLKSEL (7506L)
+#define RST9533_CTRL_TS_CLKSEL_OVERRIDE (7507L)
+#define RST9533_POWER (7508L)
+#define RST9533_POWER_PU_NSEB (7509L)
+#define RST9533_POWER_PU_PHY (7510L)
+#define RST9533_RST (7511L)
+#define RST9533_RST_CORE_MMCM (7512L)
+#define RST9533_RST_DDR4 (7513L)
+#define RST9533_RST_PERIPH (7514L)
+#define RST9533_RST_PHY (7515L)
+#define RST9533_RST_PTP (7516L)
+#define RST9533_RST_PTP_MMCM (7517L)
+#define RST9533_RST_RPP (7518L)
+#define RST9533_RST_SDC (7519L)
+#define RST9533_RST_SYS (7520L)
+#define RST9533_RST_SYS_MMCM (7521L)
+#define RST9533_RST_TMC (7522L)
+#define RST9533_RST_TS (7523L)
+#define RST9533_RST_TS_MMCM (7524L)
+#define RST9533_STAT (7525L)
+#define RST9533_STAT_CORE_MMCM_LOCKED (7526L)
+#define RST9533_STAT_DDR4_MMCM_LOCKED (7527L)
+#define RST9533_STAT_DDR4_PLL_LOCKED (7528L)
+#define RST9533_STAT_PTP_MMCM_LOCKED (7529L)
+#define RST9533_STAT_SYS_MMCM_LOCKED (7530L)
+#define RST9533_STAT_TS_MMCM_LOCKED (7531L)
+#define RST9533_STICKY (7532L)
+#define RST9533_STICKY_CORE_MMCM_UNLOCKED (7533L)
+#define RST9533_STICKY_DDR4_MMCM_UNLOCKED (7534L)
+#define RST9533_STICKY_DDR4_PLL_UNLOCKED (7535L)
+#define RST9533_STICKY_PTP_MMCM_UNLOCKED (7536L)
+#define RST9533_STICKY_SYS_MMCM_UNLOCKED (7537L)
+#define RST9533_STICKY_TS_MMCM_UNLOCKED (7538L)
+/* RST9534 */
+#define RST9534_CTRL (7539L)
+#define RST9534_CTRL_PTP_MMCM_CLKSEL (7540L)
+#define RST9534_CTRL_TS_CLKSEL (7541L)
+#define RST9534_CTRL_TS_CLKSEL_OVERRIDE (7542L)
+#define RST9534_POWER (7543L)
+#define RST9534_POWER_PU_NSEB (7544L)
+#define RST9534_POWER_PU_PHY (7545L)
+#define RST9534_RST (7546L)
+#define RST9534_RST_CORE_MMCM (7547L)
+#define RST9534_RST_DDR4 (7548L)
+#define RST9534_RST_PERIPH (7549L)
+#define RST9534_RST_PHY (7550L)
+#define RST9534_RST_PTP (7551L)
+#define RST9534_RST_PTP_MMCM (7552L)
+#define RST9534_RST_RPP (7553L)
+#define RST9534_RST_SDC (7554L)
+#define RST9534_RST_SYS (7555L)
+#define RST9534_RST_SYS_MMCM (7556L)
+#define RST9534_RST_TMC (7557L)
+#define RST9534_RST_TS (7558L)
+#define RST9534_RST_TS_MMCM (7559L)
+#define RST9534_STAT (7560L)
+#define RST9534_STAT_CORE_MMCM_LOCKED (7561L)
+#define RST9534_STAT_DDR4_MMCM_LOCKED (7562L)
+#define RST9534_STAT_DDR4_PLL_LOCKED (7563L)
+#define RST9534_STAT_PTP_MMCM_LOCKED (7564L)
+#define RST9534_STAT_SYS_MMCM_LOCKED (7565L)
+#define RST9534_STAT_TS_MMCM_LOCKED (7566L)
+#define RST9534_STICKY (7567L)
+#define RST9534_STICKY_CORE_MMCM_UNLOCKED (7568L)
+#define RST9534_STICKY_DDR4_MMCM_UNLOCKED (7569L)
+#define RST9534_STICKY_DDR4_PLL_UNLOCKED (7570L)
+#define RST9534_STICKY_PTP_MMCM_UNLOCKED (7571L)
+#define RST9534_STICKY_SYS_MMCM_UNLOCKED (7572L)
+#define RST9534_STICKY_TS_MMCM_UNLOCKED (7573L)
+/* RST9535 */
+#define RST9535_CTRL (7574L)
+#define RST9535_CTRL_PTP_MMCM_CLKSEL (7575L)
+#define RST9535_CTRL_TS_CLKSEL (7576L)
+#define RST9535_CTRL_TS_CLKSEL_OVERRIDE (7577L)
+#define RST9535_POWER (7578L)
+#define RST9535_POWER_PU_NSEB (7579L)
+#define RST9535_POWER_PU_PHY (7580L)
+#define RST9535_RST (7581L)
+#define RST9535_RST_CORE_MMCM (7582L)
+#define RST9535_RST_DDR4 (7583L)
+#define RST9535_RST_MAC_RX (7584L)
+#define RST9535_RST_MAC_TX (7585L)
+#define RST9535_RST_PCS_RX (7586L)
+#define RST9535_RST_PERIPH (7587L)
+#define RST9535_RST_PHY (7588L)
+#define RST9535_RST_PTP (7589L)
+#define RST9535_RST_PTP_MMCM (7590L)
+#define RST9535_RST_RPP (7591L)
+#define RST9535_RST_SDC (7592L)
+#define RST9535_RST_SERDES_RX (7593L)
+#define RST9535_RST_SERDES_RX_DATAPATH (7594L)
+#define RST9535_RST_SERDES_TX (7595L)
+#define RST9535_RST_SYS (7596L)
+#define RST9535_RST_SYS_MMCM (7597L)
+#define RST9535_RST_TMC (7598L)
+#define RST9535_RST_TS (7599L)
+#define RST9535_RST_TS_MMCM (7600L)
+#define RST9535_STAT (7601L)
+#define RST9535_STAT_CORE_MMCM_LOCKED (7602L)
+#define RST9535_STAT_DDR4_MMCM_LOCKED (7603L)
+#define RST9535_STAT_DDR4_PLL_LOCKED (7604L)
+#define RST9535_STAT_PTP_MMCM_LOCKED (7605L)
+#define RST9535_STAT_SYS_MMCM_LOCKED (7606L)
+#define RST9535_STAT_TS_MMCM_LOCKED (7607L)
+#define RST9535_STICKY (7608L)
+#define RST9535_STICKY_CORE_MMCM_UNLOCKED (7609L)
+#define RST9535_STICKY_DDR4_MMCM_UNLOCKED (7610L)
+#define RST9535_STICKY_DDR4_PLL_UNLOCKED (7611L)
+#define RST9535_STICKY_PTP_MMCM_UNLOCKED (7612L)
+#define RST9535_STICKY_SYS_MMCM_UNLOCKED (7613L)
+#define RST9535_STICKY_TS_MMCM_UNLOCKED (7614L)
+/* RST9536 */
+#define RST9536_CTRL (7615L)
+#define RST9536_CTRL_PTP_MMCM_CLKSEL (7616L)
+#define RST9536_CTRL_TS_CLKSEL (7617L)
+#define RST9536_CTRL_TS_CLKSEL_OVERRIDE (7618L)
+#define RST9536_POWER (7619L)
+#define RST9536_POWER_PU_NSEB (7620L)
+#define RST9536_POWER_PU_PHY (7621L)
+#define RST9536_RST (7622L)
+#define RST9536_RST_CORE_MMCM (7623L)
+#define RST9536_RST_DDR4 (7624L)
+#define RST9536_RST_MAC_RX (7625L)
+#define RST9536_RST_PERIPH (7626L)
+#define RST9536_RST_PHY (7627L)
+#define RST9536_RST_PTP (7628L)
+#define RST9536_RST_PTP_MMCM (7629L)
+#define RST9536_RST_RPP (7630L)
+#define RST9536_RST_SDC (7631L)
+#define RST9536_RST_SYS (7632L)
+#define RST9536_RST_SYS_MMCM (7633L)
+#define RST9536_RST_TMC (7634L)
+#define RST9536_RST_TS (7635L)
+#define RST9536_RST_TS_MMCM (7636L)
+#define RST9536_STAT (7637L)
+#define RST9536_STAT_CORE_MMCM_LOCKED (7638L)
+#define RST9536_STAT_DDR4_MMCM_LOCKED (7639L)
+#define RST9536_STAT_DDR4_PLL_LOCKED (7640L)
+#define RST9536_STAT_PTP_MMCM_LOCKED (7641L)
+#define RST9536_STAT_SYS_MMCM_LOCKED (7642L)
+#define RST9536_STAT_TS_MMCM_LOCKED (7643L)
+#define RST9536_STICKY (7644L)
+#define RST9536_STICKY_CORE_MMCM_UNLOCKED (7645L)
+#define RST9536_STICKY_DDR4_MMCM_UNLOCKED (7646L)
+#define RST9536_STICKY_DDR4_PLL_UNLOCKED (7647L)
+#define RST9536_STICKY_PTP_MMCM_UNLOCKED (7648L)
+#define RST9536_STICKY_SYS_MMCM_UNLOCKED (7649L)
+#define RST9536_STICKY_TS_MMCM_UNLOCKED (7650L)
+/* RST9537 */
+#define RST9537_CTRL (7651L)
+#define RST9537_CTRL_PTP_MMCM_CLKSEL (7652L)
+#define RST9537_CTRL_TS_CLKSEL (7653L)
+#define RST9537_CTRL_TS_CLKSEL_OVERRIDE (7654L)
+#define RST9537_RST (7655L)
+#define RST9537_RST_DDR3 (7656L)
+#define RST9537_RST_DDR3_IDLY_MMCM (7657L)
+#define RST9537_RST_NSEB (7658L)
+#define RST9537_RST_PERIPH (7659L)
+#define RST9537_RST_PHY10G_QPLL (7660L)
+#define RST9537_RST_PHY3S10G (7661L)
+#define RST9537_RST_PHY3S_MMCM (7662L)
+#define RST9537_RST_PTP (7663L)
+#define RST9537_RST_PTP_MMCM (7664L)
+#define RST9537_RST_RPP (7665L)
+#define RST9537_RST_SDC (7666L)
+#define RST9537_RST_SI5326 (7667L)
+#define RST9537_RST_SYS (7668L)
+#define RST9537_RST_TS (7669L)
+#define RST9537_RST_TS_MMCM (7670L)
+#define RST9537_RST_STAT (7671L)
+#define RST9537_RST_STAT_PCS_RESET_BY_SERDES (7672L)
+#define RST9537_STAT (7673L)
+#define RST9537_STAT_DDR3_IDLY_MMCM_LOCKED (7674L)
+#define RST9537_STAT_DDR3_MMCM_LOCKED (7675L)
+#define RST9537_STAT_DDR3_PLL_LOCKED (7676L)
+#define RST9537_STAT_PHY10G_QPLL_LOCK_0_1 (7677L)
+#define RST9537_STAT_PHY10G_QPLL_LOCK_2_3 (7678L)
+#define RST9537_STAT_PHY3S_MMCM_LOCKED (7679L)
+#define RST9537_STAT_PTP_MMCM_LOCKED (7680L)
+#define RST9537_STAT_SYNCE_MAIN_CLK_LOS (7681L)
+#define RST9537_STAT_SYS_MMCM_LOCKED (7682L)
+#define RST9537_STAT_TS_MMCM_LOCKED (7683L)
+#define RST9537_STICKY (7684L)
+#define RST9537_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7685L)
+#define RST9537_STICKY_DDR3_MMCM_UNLOCKED (7686L)
+#define RST9537_STICKY_DDR3_PLL_UNLOCKED (7687L)
+#define RST9537_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7688L)
+#define RST9537_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7689L)
+#define RST9537_STICKY_PHY3S_MMCM_UNLOCKED (7690L)
+#define RST9537_STICKY_PTP_MMCM_UNLOCKED (7691L)
+#define RST9537_STICKY_TS_MMCM_UNLOCKED (7692L)
+/* RST9538 */
+#define RST9538_CTRL (7693L)
+#define RST9538_CTRL_PTP_MMCM_CLKSEL (7694L)
+#define RST9538_CTRL_TS_CLKSEL (7695L)
+#define RST9538_CTRL_TS_CLKSEL_OVERRIDE (7696L)
+#define RST9538_RST (7697L)
+#define RST9538_RST_DDR3 (7698L)
+#define RST9538_RST_DDR3_IDLY_MMCM (7699L)
+#define RST9538_RST_NSEB (7700L)
+#define RST9538_RST_PERIPH (7701L)
+#define RST9538_RST_PHY10G_QPLL (7702L)
+#define RST9538_RST_PHY3S10G (7703L)
+#define RST9538_RST_PHY3S_MMCM (7704L)
+#define RST9538_RST_PTP (7705L)
+#define RST9538_RST_PTP_MMCM (7706L)
+#define RST9538_RST_RPP (7707L)
+#define RST9538_RST_SDC (7708L)
+#define RST9538_RST_SI5326 (7709L)
+#define RST9538_RST_SYS (7710L)
+#define RST9538_RST_TS (7711L)
+#define RST9538_RST_TS_MMCM (7712L)
+#define RST9538_RST_STAT (7713L)
+#define RST9538_RST_STAT_PCS_RESET_BY_SERDES (7714L)
+#define RST9538_STAT (7715L)
+#define RST9538_STAT_DDR3_IDLY_MMCM_LOCKED (7716L)
+#define RST9538_STAT_DDR3_MMCM_LOCKED (7717L)
+#define RST9538_STAT_DDR3_PLL_LOCKED (7718L)
+#define RST9538_STAT_PHY10G_QPLL_LOCK_0_1 (7719L)
+#define RST9538_STAT_PHY10G_QPLL_LOCK_2_3 (7720L)
+#define RST9538_STAT_PHY3S_MMCM_LOCKED (7721L)
+#define RST9538_STAT_PTP_MMCM_LOCKED (7722L)
+#define RST9538_STAT_SYNCE_MAIN_CLK_LOS (7723L)
+#define RST9538_STAT_SYS_MMCM_LOCKED (7724L)
+#define RST9538_STAT_TS_MMCM_LOCKED (7725L)
+#define RST9538_STICKY (7726L)
+#define RST9538_STICKY_DDR3_IDLY_MMCM_UNLOCKED (7727L)
+#define RST9538_STICKY_DDR3_MMCM_UNLOCKED (7728L)
+#define RST9538_STICKY_DDR3_PLL_UNLOCKED (7729L)
+#define RST9538_STICKY_PHY10G_QPLL_UNLOCK_0_1 (7730L)
+#define RST9538_STICKY_PHY10G_QPLL_UNLOCK_2_3 (7731L)
+#define RST9538_STICKY_PHY3S_MMCM_UNLOCKED (7732L)
+#define RST9538_STICKY_PTP_MMCM_UNLOCKED (7733L)
+#define RST9538_STICKY_TS_MMCM_UNLOCKED (7734L)
+/* RST9539 */
+#define RST9539_CTRL (7735L)
+#define RST9539_CTRL_PTP_MMCM_CLKSEL (7736L)
+#define RST9539_CTRL_TS_CLKSEL (7737L)
+#define RST9539_CTRL_TS_CLKSEL_OVERRIDE (7738L)
+#define RST9539_POWER (7739L)
+#define RST9539_POWER_PU_NSEB (7740L)
+#define RST9539_POWER_PU_PHY (7741L)
+#define RST9539_RST (7742L)
+#define RST9539_RST_CORE_MMCM (7743L)
+#define RST9539_RST_DDR4 (7744L)
+#define RST9539_RST_PERIPH (7745L)
+#define RST9539_RST_PHY (7746L)
+#define RST9539_RST_PTP (7747L)
+#define RST9539_RST_PTP_MMCM (7748L)
+#define RST9539_RST_RPP (7749L)
+#define RST9539_RST_SDC (7750L)
+#define RST9539_RST_SYS (7751L)
+#define RST9539_RST_SYS_MMCM (7752L)
+#define RST9539_RST_TMC (7753L)
+#define RST9539_RST_TS (7754L)
+#define RST9539_RST_TS_MMCM (7755L)
+#define RST9539_STAT (7756L)
+#define RST9539_STAT_CORE_MMCM_LOCKED (7757L)
+#define RST9539_STAT_DDR4_MMCM_LOCKED (7758L)
+#define RST9539_STAT_DDR4_PLL_LOCKED (7759L)
+#define RST9539_STAT_PTP_MMCM_LOCKED (7760L)
+#define RST9539_STAT_SYS_MMCM_LOCKED (7761L)
+#define RST9539_STAT_TS_MMCM_LOCKED (7762L)
+#define RST9539_STICKY (7763L)
+#define RST9539_STICKY_CORE_MMCM_UNLOCKED (7764L)
+#define RST9539_STICKY_DDR4_MMCM_UNLOCKED (7765L)
+#define RST9539_STICKY_DDR4_PLL_UNLOCKED (7766L)
+#define RST9539_STICKY_PTP_MMCM_UNLOCKED (7767L)
+#define RST9539_STICKY_SYS_MMCM_UNLOCKED (7768L)
+#define RST9539_STICKY_TS_MMCM_UNLOCKED (7769L)
+/* RST9540 */
+#define RST9540_CTRL (7770L)
+#define RST9540_CTRL_PTP_MMCM_CLKSEL (7771L)
+#define RST9540_CTRL_TS_CLKSEL (7772L)
+#define RST9540_CTRL_TS_CLKSEL_OVERRIDE (7773L)
+#define RST9540_POWER (7774L)
+#define RST9540_POWER_PU_NSEB (7775L)
+#define RST9540_POWER_PU_PHY (7776L)
+#define RST9540_RST (7777L)
+#define RST9540_RST_CORE_MMCM (7778L)
+#define RST9540_RST_DDR4 (7779L)
+#define RST9540_RST_MAC_RX (7780L)
+#define RST9540_RST_MAC_TX (7781L)
+#define RST9540_RST_PCS_RX (7782L)
+#define RST9540_RST_PERIPH (7783L)
+#define RST9540_RST_PHY (7784L)
+#define RST9540_RST_PTP (7785L)
+#define RST9540_RST_PTP_MMCM (7786L)
+#define RST9540_RST_RPP (7787L)
+#define RST9540_RST_SDC (7788L)
+#define RST9540_RST_SERDES_RX (7789L)
+#define RST9540_RST_SERDES_RX_DATAPATH (7790L)
+#define RST9540_RST_SERDES_TX (7791L)
+#define RST9540_RST_SYS (7792L)
+#define RST9540_RST_SYS_MMCM (7793L)
+#define RST9540_RST_TMC (7794L)
+#define RST9540_RST_TS (7795L)
+#define RST9540_RST_TS_MMCM (7796L)
+#define RST9540_STAT (7797L)
+#define RST9540_STAT_CORE_MMCM_LOCKED (7798L)
+#define RST9540_STAT_DDR4_MMCM_LOCKED (7799L)
+#define RST9540_STAT_DDR4_PLL_LOCKED (7800L)
+#define RST9540_STAT_PTP_MMCM_LOCKED (7801L)
+#define RST9540_STAT_SYS_MMCM_LOCKED (7802L)
+#define RST9540_STAT_TS_MMCM_LOCKED (7803L)
+#define RST9540_STICKY (7804L)
+#define RST9540_STICKY_CORE_MMCM_UNLOCKED (7805L)
+#define RST9540_STICKY_DDR4_MMCM_UNLOCKED (7806L)
+#define RST9540_STICKY_DDR4_PLL_UNLOCKED (7807L)
+#define RST9540_STICKY_PTP_MMCM_UNLOCKED (7808L)
+#define RST9540_STICKY_SYS_MMCM_UNLOCKED (7809L)
+#define RST9540_STICKY_TS_MMCM_UNLOCKED (7810L)
+/* RST9541 */
+#define RST9541_LATCH (7811L)
+#define RST9541_LATCH_DDR4_CALIB_COMPLETE (7812L)
+#define RST9541_LATCH_PHY_RDY (7813L)
+#define RST9541_POWER (7814L)
+#define RST9541_POWER_PU_PHY (7815L)
+#define RST9541_RST (7816L)
+#define RST9541_RST_DDR4 (7817L)
+#define RST9541_RST_PERIPH (7818L)
+#define RST9541_RST_PHY (7819L)
+#define RST9541_RST_POWER (7820L)
+#define RST9541_RST_SYS (7821L)
+#define RST9541_STAT (7822L)
+#define RST9541_STAT_DDR4_CALIB_COMPLETE (7823L)
+#define RST9541_STAT_PHY_RDY (7824L)
+/* RST9542 */
+#define RST9542_LATCH (7825L)
+#define RST9542_LATCH_DDR4_CALIB_COMPLETE (7826L)
+#define RST9542_LATCH_PHY_RDY (7827L)
+#define RST9542_POWER (7828L)
+#define RST9542_POWER_PU_PHY (7829L)
+#define RST9542_RST (7830L)
+#define RST9542_RST_DDR4 (7831L)
+#define RST9542_RST_PERIPH (7832L)
+#define RST9542_RST_PHY (7833L)
+#define RST9542_RST_SYS (7834L)
+#define RST9542_STAT (7835L)
+#define RST9542_STAT_DDR4_CALIB_COMPLETE (7836L)
+#define RST9542_STAT_PHY_RDY (7837L)
+/* RST9543 */
+#define RST9543_CTRL (7838L)
+#define RST9543_CTRL_PTP_MMCM_CLKSEL (7839L)
+#define RST9543_CTRL_TS_CLKSEL (7840L)
+#define RST9543_CTRL_TS_CLKSEL_OVERRIDE (7841L)
+#define RST9543_POWER (7842L)
+#define RST9543_POWER_PU_NSEB (7843L)
+#define RST9543_POWER_PU_PHY (7844L)
+#define RST9543_RST (7845L)
+#define RST9543_RST_CORE_MMCM (7846L)
+#define RST9543_RST_DDR4 (7847L)
+#define RST9543_RST_MAC_RX (7848L)
+#define RST9543_RST_PERIPH (7849L)
+#define RST9543_RST_PHY (7850L)
+#define RST9543_RST_PTP (7851L)
+#define RST9543_RST_PTP_MMCM (7852L)
+#define RST9543_RST_RPP (7853L)
+#define RST9543_RST_SDC (7854L)
+#define RST9543_RST_SYS (7855L)
+#define RST9543_RST_SYS_MMCM (7856L)
+#define RST9543_RST_TMC (7857L)
+#define RST9543_RST_TS (7858L)
+#define RST9543_RST_TS_MMCM (7859L)
+#define RST9543_STAT (7860L)
+#define RST9543_STAT_CORE_MMCM_LOCKED (7861L)
+#define RST9543_STAT_DDR4_MMCM_LOCKED (7862L)
+#define RST9543_STAT_DDR4_PLL_LOCKED (7863L)
+#define RST9543_STAT_PTP_MMCM_LOCKED (7864L)
+#define RST9543_STAT_SYS_MMCM_LOCKED (7865L)
+#define RST9543_STAT_TS_MMCM_LOCKED (7866L)
+#define RST9543_STICKY (7867L)
+#define RST9543_STICKY_CORE_MMCM_UNLOCKED (7868L)
+#define RST9543_STICKY_DDR4_MMCM_UNLOCKED (7869L)
+#define RST9543_STICKY_DDR4_PLL_UNLOCKED (7870L)
+#define RST9543_STICKY_PTP_MMCM_UNLOCKED (7871L)
+#define RST9543_STICKY_SYS_MMCM_UNLOCKED (7872L)
+#define RST9543_STICKY_TS_MMCM_UNLOCKED (7873L)
+/* RST9544 */
+#define RST9544_CTRL (7874L)
+#define RST9544_CTRL_PTP_MMCM_CLKSEL (7875L)
+#define RST9544_CTRL_TS_CLKSEL (7876L)
+#define RST9544_CTRL_TS_CLKSEL_OVERRIDE (7877L)
+#define RST9544_CTRL_TS_CLKSEL_REF (7878L)
+#define RST9544_POWER (7879L)
+#define RST9544_POWER_PU_NSEB (7880L)
+#define RST9544_POWER_PU_PHY (7881L)
+#define RST9544_RST (7882L)
+#define RST9544_RST_CORE_MMCM (7883L)
+#define RST9544_RST_DDR4 (7884L)
+#define RST9544_RST_NFV_OVS (7885L)
+#define RST9544_RST_PERIPH (7886L)
+#define RST9544_RST_PHY (7887L)
+#define RST9544_RST_PTP (7888L)
+#define RST9544_RST_PTP_MMCM (7889L)
+#define RST9544_RST_RPP (7890L)
+#define RST9544_RST_SDC (7891L)
+#define RST9544_RST_SYS (7892L)
+#define RST9544_RST_SYS_MMCM (7893L)
+#define RST9544_RST_TMC (7894L)
+#define RST9544_RST_TS (7895L)
+#define RST9544_RST_TSM_REF_MMCM (7896L)
+#define RST9544_RST_TS_MMCM (7897L)
+#define RST9544_STAT (7898L)
+#define RST9544_STAT_CORE_MMCM_LOCKED (7899L)
+#define RST9544_STAT_DDR4_MMCM_LOCKED (7900L)
+#define RST9544_STAT_DDR4_PLL_LOCKED (7901L)
+#define RST9544_STAT_PTP_MMCM_LOCKED (7902L)
+#define RST9544_STAT_SYS_MMCM_LOCKED (7903L)
+#define RST9544_STAT_TSM_REF_MMCM_LOCKED (7904L)
+#define RST9544_STAT_TS_MMCM_LOCKED (7905L)
+#define RST9544_STICKY (7906L)
+#define RST9544_STICKY_CORE_MMCM_UNLOCKED (7907L)
+#define RST9544_STICKY_DDR4_MMCM_UNLOCKED (7908L)
+#define RST9544_STICKY_DDR4_PLL_UNLOCKED (7909L)
+#define RST9544_STICKY_PCI_SYS_MMCM_UNLOCKED (7910L)
+#define RST9544_STICKY_PTP_MMCM_UNLOCKED (7911L)
+#define RST9544_STICKY_SYS_MMCM_UNLOCKED (7912L)
+#define RST9544_STICKY_TSM_REF_MMCM_UNLOCKED (7913L)
+#define RST9544_STICKY_TS_MMCM_UNLOCKED (7914L)
+/* RST9545 */
+#define RST9545_CTRL (7915L)
+#define RST9545_CTRL_PTP_MMCM_CLKSEL (7916L)
+#define RST9545_CTRL_TS_CLKSEL (7917L)
+#define RST9545_CTRL_TS_CLKSEL_OVERRIDE (7918L)
+#define RST9545_POWER (7919L)
+#define RST9545_POWER_PU_NSEB (7920L)
+#define RST9545_POWER_PU_PHY (7921L)
+#define RST9545_RST (7922L)
+#define RST9545_RST_CORE_MMCM (7923L)
+#define RST9545_RST_DDR4 (7924L)
+#define RST9545_RST_PERIPH (7925L)
+#define RST9545_RST_PHY (7926L)
+#define RST9545_RST_PTP (7927L)
+#define RST9545_RST_PTP_MMCM (7928L)
+#define RST9545_RST_RPP (7929L)
+#define RST9545_RST_SDC (7930L)
+#define RST9545_RST_SYS (7931L)
+#define RST9545_RST_SYS_MMCM (7932L)
+#define RST9545_RST_TMC (7933L)
+#define RST9545_RST_TS (7934L)
+#define RST9545_RST_TS_MMCM (7935L)
+#define RST9545_STAT (7936L)
+#define RST9545_STAT_CORE_MMCM_LOCKED (7937L)
+#define RST9545_STAT_DDR4_MMCM_LOCKED (7938L)
+#define RST9545_STAT_DDR4_PLL_LOCKED (7939L)
+#define RST9545_STAT_PTP_MMCM_LOCKED (7940L)
+#define RST9545_STAT_SYS_MMCM_LOCKED (7941L)
+#define RST9545_STAT_TS_MMCM_LOCKED (7942L)
+#define RST9545_STICKY (7943L)
+#define RST9545_STICKY_CORE_MMCM_UNLOCKED (7944L)
+#define RST9545_STICKY_DDR4_MMCM_UNLOCKED (7945L)
+#define RST9545_STICKY_DDR4_PLL_UNLOCKED (7946L)
+#define RST9545_STICKY_PTP_MMCM_UNLOCKED (7947L)
+#define RST9545_STICKY_SYS_MMCM_UNLOCKED (7948L)
+#define RST9545_STICKY_TS_MMCM_UNLOCKED (7949L)
+/* RST9546 */
+#define RST9546_CTRL (7950L)
+#define RST9546_CTRL_PTP_MMCM_CLKSEL (7951L)
+#define RST9546_CTRL_TS_CLKSEL (7952L)
+#define RST9546_CTRL_TS_CLKSEL_OVERRIDE (7953L)
+#define RST9546_POWER (7954L)
+#define RST9546_POWER_PU_NSEB (7955L)
+#define RST9546_POWER_PU_PHY (7956L)
+#define RST9546_RST (7957L)
+#define RST9546_RST_CORE_MMCM (7958L)
+#define RST9546_RST_DDR4 (7959L)
+#define RST9546_RST_MAC_RX (7960L)
+#define RST9546_RST_MAC_TX (7961L)
+#define RST9546_RST_PCS_RX (7962L)
+#define RST9546_RST_PERIPH (7963L)
+#define RST9546_RST_PHY (7964L)
+#define RST9546_RST_PTP (7965L)
+#define RST9546_RST_PTP_MMCM (7966L)
+#define RST9546_RST_RPP (7967L)
+#define RST9546_RST_SDC (7968L)
+#define RST9546_RST_SERDES_RX (7969L)
+#define RST9546_RST_SERDES_RX_DATAPATH (7970L)
+#define RST9546_RST_SERDES_TX (7971L)
+#define RST9546_RST_SYS (7972L)
+#define RST9546_RST_SYS_MMCM (7973L)
+#define RST9546_RST_TMC (7974L)
+#define RST9546_RST_TS (7975L)
+#define RST9546_RST_TS_MMCM (7976L)
+#define RST9546_STAT (7977L)
+#define RST9546_STAT_CORE_MMCM_LOCKED (7978L)
+#define RST9546_STAT_DDR4_MMCM_LOCKED (7979L)
+#define RST9546_STAT_DDR4_PLL_LOCKED (7980L)
+#define RST9546_STAT_PTP_MMCM_LOCKED (7981L)
+#define RST9546_STAT_SYS_MMCM_LOCKED (7982L)
+#define RST9546_STAT_TS_MMCM_LOCKED (7983L)
+#define RST9546_STICKY (7984L)
+#define RST9546_STICKY_CORE_MMCM_UNLOCKED (7985L)
+#define RST9546_STICKY_DDR4_MMCM_UNLOCKED (7986L)
+#define RST9546_STICKY_DDR4_PLL_UNLOCKED (7987L)
+#define RST9546_STICKY_PTP_MMCM_UNLOCKED (7988L)
+#define RST9546_STICKY_SYS_MMCM_UNLOCKED (7989L)
+#define RST9546_STICKY_TS_MMCM_UNLOCKED (7990L)
+/* RST9547 */
+#define RST9547_LATCH (7991L)
+#define RST9547_LATCH_DDR4_CALIB_COMPLETE (7992L)
+#define RST9547_LATCH_PHY_RDY (7993L)
+#define RST9547_POWER (7994L)
+#define RST9547_POWER_PU_PHY (7995L)
+#define RST9547_RST (7996L)
+#define RST9547_RST_DDR4 (7997L)
+#define RST9547_RST_PERIPH (7998L)
+#define RST9547_RST_PHY (7999L)
+#define RST9547_RST_SYS (8000L)
+#define RST9547_STAT (8001L)
+#define RST9547_STAT_DDR4_CALIB_COMPLETE (8002L)
+#define RST9547_STAT_PHY_RDY (8003L)
+/* RST9548 */
+#define RST9548_CTRL (8004L)
+#define RST9548_CTRL_PTP_MMCM_CLKSEL (8005L)
+#define RST9548_CTRL_TS_CLKSEL (8006L)
+#define RST9548_CTRL_TS_CLKSEL_OVERRIDE (8007L)
+#define RST9548_POWER (8008L)
+#define RST9548_POWER_PU_NSEB (8009L)
+#define RST9548_POWER_PU_PHY (8010L)
+#define RST9548_RST (8011L)
+#define RST9548_RST_CORE_MMCM (8012L)
+#define RST9548_RST_DDR4 (8013L)
+#define RST9548_RST_PERIPH (8014L)
+#define RST9548_RST_PHY (8015L)
+#define RST9548_RST_PTP (8016L)
+#define RST9548_RST_PTP_MMCM (8017L)
+#define RST9548_RST_RPP (8018L)
+#define RST9548_RST_SDC (8019L)
+#define RST9548_RST_SYS (8020L)
+#define RST9548_RST_SYS_MMCM (8021L)
+#define RST9548_RST_TMC (8022L)
+#define RST9548_RST_TS (8023L)
+#define RST9548_RST_TS_MMCM (8024L)
+#define RST9548_STAT (8025L)
+#define RST9548_STAT_CORE_MMCM_LOCKED (8026L)
+#define RST9548_STAT_DDR4_MMCM_LOCKED (8027L)
+#define RST9548_STAT_DDR4_PLL_LOCKED (8028L)
+#define RST9548_STAT_PTP_MMCM_LOCKED (8029L)
+#define RST9548_STAT_SYS_MMCM_LOCKED (8030L)
+#define RST9548_STAT_TS_MMCM_LOCKED (8031L)
+#define RST9548_STICKY (8032L)
+#define RST9548_STICKY_CORE_MMCM_UNLOCKED (8033L)
+#define RST9548_STICKY_DDR4_MMCM_UNLOCKED (8034L)
+#define RST9548_STICKY_DDR4_PLL_UNLOCKED (8035L)
+#define RST9548_STICKY_PTP_MMCM_UNLOCKED (8036L)
+#define RST9548_STICKY_SYS_MMCM_UNLOCKED (8037L)
+#define RST9548_STICKY_TS_MMCM_UNLOCKED (8038L)
+/* RST9549 */
+#define RST9549_CTRL (8039L)
+#define RST9549_CTRL_PTP_MMCM_CLKSEL (8040L)
+#define RST9549_CTRL_TS_CLKSEL (8041L)
+#define RST9549_CTRL_TS_CLKSEL_OVERRIDE (8042L)
+#define RST9549_POWER (8043L)
+#define RST9549_POWER_PU_NSEB (8044L)
+#define RST9549_POWER_PU_PHY (8045L)
+#define RST9549_RST (8046L)
+#define RST9549_RST_CORE_MMCM (8047L)
+#define RST9549_RST_DDR4 (8048L)
+#define RST9549_RST_PERIPH (8049L)
+#define RST9549_RST_PHY (8050L)
+#define RST9549_RST_PTP (8051L)
+#define RST9549_RST_PTP_MMCM (8052L)
+#define RST9549_RST_RPP (8053L)
+#define RST9549_RST_SDC (8054L)
+#define RST9549_RST_SYS (8055L)
+#define RST9549_RST_SYS_MMCM (8056L)
+#define RST9549_RST_TMC (8057L)
+#define RST9549_RST_TS (8058L)
+#define RST9549_RST_TS_MMCM (8059L)
+#define RST9549_STAT (8060L)
+#define RST9549_STAT_CORE_MMCM_LOCKED (8061L)
+#define RST9549_STAT_DDR4_MMCM_LOCKED (8062L)
+#define RST9549_STAT_DDR4_PLL_LOCKED (8063L)
+#define RST9549_STAT_PTP_MMCM_LOCKED (8064L)
+#define RST9549_STAT_SYS_MMCM_LOCKED (8065L)
+#define RST9549_STAT_TS_MMCM_LOCKED (8066L)
+#define RST9549_STICKY (8067L)
+#define RST9549_STICKY_CORE_MMCM_UNLOCKED (8068L)
+#define RST9549_STICKY_DDR4_MMCM_UNLOCKED (8069L)
+#define RST9549_STICKY_DDR4_PLL_UNLOCKED (8070L)
+#define RST9549_STICKY_PTP_MMCM_UNLOCKED (8071L)
+#define RST9549_STICKY_SYS_MMCM_UNLOCKED (8072L)
+#define RST9549_STICKY_TS_MMCM_UNLOCKED (8073L)
+/* RST9553 */
+#define RST9553_LATCH (8074L)
+#define RST9553_LATCH_DDR4_CALIB_COMPLETE (8075L)
+#define RST9553_LATCH_PHY_RDY (8076L)
+#define RST9553_RST (8077L)
+#define RST9553_RST_DDR4 (8078L)
+#define RST9553_RST_PHY (8079L)
+#define RST9553_RST_SYS (8080L)
+#define RST9553_STAT (8081L)
+#define RST9553_STAT_DDR4_CALIB_COMPLETE (8082L)
+#define RST9553_STAT_PHY_RDY (8083L)
+/* RST9555 */
+#define RST9555_CTRL (8094L)
+#define RST9555_CTRL_PTP_MMCM_CLKSEL (8095L)
+#define RST9555_CTRL_TS_CLKSEL (8096L)
+#define RST9555_CTRL_TS_CLKSEL_OVERRIDE (8097L)
+#define RST9555_POWER (8098L)
+#define RST9555_POWER_PU_NSEB (8099L)
+#define RST9555_POWER_PU_PHY (8100L)
+#define RST9555_RST (8101L)
+#define RST9555_RST_CORE_MMCM (8102L)
+#define RST9555_RST_DDR4 (8103L)
+#define RST9555_RST_PERIPH (8104L)
+#define RST9555_RST_PHY (8105L)
+#define RST9555_RST_PTP (8106L)
+#define RST9555_RST_PTP_MMCM (8107L)
+#define RST9555_RST_RPP (8108L)
+#define RST9555_RST_SDC (8109L)
+#define RST9555_RST_SYS (8110L)
+#define RST9555_RST_SYS_MMCM (8111L)
+#define RST9555_RST_TMC (8112L)
+#define RST9555_RST_TS (8113L)
+#define RST9555_RST_TS_MMCM (8114L)
+#define RST9555_STAT (8115L)
+#define RST9555_STAT_CORE_MMCM_LOCKED (8116L)
+#define RST9555_STAT_DDR4_MMCM_LOCKED (8117L)
+#define RST9555_STAT_DDR4_PLL_LOCKED (8118L)
+#define RST9555_STAT_PTP_MMCM_LOCKED (8119L)
+#define RST9555_STAT_SYS_MMCM_LOCKED (8120L)
+#define RST9555_STAT_TS_MMCM_LOCKED (8121L)
+#define RST9555_STICKY (8122L)
+#define RST9555_STICKY_CORE_MMCM_UNLOCKED (8123L)
+#define RST9555_STICKY_DDR4_MMCM_UNLOCKED (8124L)
+#define RST9555_STICKY_DDR4_PLL_UNLOCKED (8125L)
+#define RST9555_STICKY_PTP_MMCM_UNLOCKED (8126L)
+#define RST9555_STICKY_SYS_MMCM_UNLOCKED (8127L)
+#define RST9555_STICKY_TS_MMCM_UNLOCKED (8128L)
+/* RST9559 */
+#define RST9559_LATCH (8129L)
+#define RST9559_LATCH_DDR4_CALIB_COMPLETE (8130L)
+#define RST9559_LATCH_PHY_RDY (8131L)
+#define RST9559_RST (8132L)
+#define RST9559_RST_DDR4 (8133L)
+#define RST9559_RST_PHY (8134L)
+#define RST9559_RST_SYS (8135L)
+#define RST9559_STAT (8136L)
+#define RST9559_STAT_DDR4_CALIB_COMPLETE (8137L)
+#define RST9559_STAT_PHY_RDY (8138L)
+/* RST9563 */
+#define RST9563_CTRL (8159L)
+#define RST9563_CTRL_PTP_MMCM_CLKSEL (8160L)
+#define RST9563_CTRL_TS_CLKSEL (8161L)
+#define RST9563_CTRL_TS_CLKSEL_OVERRIDE (8162L)
+#define RST9563_POWER (8163L)
+#define RST9563_POWER_PU_NSEB (8164L)
+#define RST9563_POWER_PU_PHY (8165L)
+#define RST9563_RST (8166L)
+#define RST9563_RST_CORE_MMCM (8167L)
+#define RST9563_RST_DDR4 (8168L)
+#define RST9563_RST_MAC_RX (8169L)
+#define RST9563_RST_PERIPH (8170L)
+#define RST9563_RST_PHY (8171L)
+#define RST9563_RST_PTP (8172L)
+#define RST9563_RST_PTP_MMCM (8173L)
+#define RST9563_RST_RPP (8174L)
+#define RST9563_RST_SDC (8175L)
+#define RST9563_RST_SYS (8176L)
+#define RST9563_RST_SYS_MMCM (8177L)
+#define RST9563_RST_TMC (8178L)
+#define RST9563_RST_TS (8179L)
+#define RST9563_RST_TSM_REF_MMCM (8180L)
+#define RST9563_RST_TS_MMCM (8181L)
+#define RST9563_STAT (8182L)
+#define RST9563_STAT_CORE_MMCM_LOCKED (8183L)
+#define RST9563_STAT_DDR4_MMCM_LOCKED (8184L)
+#define RST9563_STAT_DDR4_PLL_LOCKED (8185L)
+#define RST9563_STAT_PTP_MMCM_LOCKED (8186L)
+#define RST9563_STAT_SYS_MMCM_LOCKED (8187L)
+#define RST9563_STAT_TS_MMCM_LOCKED (8188L)
+#define RST9563_STICKY (8189L)
+#define RST9563_STICKY_CORE_MMCM_UNLOCKED (8190L)
+#define RST9563_STICKY_DDR4_MMCM_UNLOCKED (8191L)
+#define RST9563_STICKY_DDR4_PLL_UNLOCKED (8192L)
+#define RST9563_STICKY_PTP_MMCM_UNLOCKED (8193L)
+#define RST9563_STICKY_SYS_MMCM_UNLOCKED (8194L)
+#define RST9563_STICKY_TS_MMCM_UNLOCKED (8195L)
+/* RTD */
+#define RTD_CTRL (8196L)
+#define RTD_CTRL_ENABLE_RTD (8197L)
+#define RTD_CTRL_ENABLE_TX_FLUSH (8198L)
+#define RTD_CTRL_ENABLE_TX_MACPHY (8199L)
+#define RTD_CTRL_RDPTR_UPDATE_TIMER (8200L)
+#define RTD_CTRL_RESERVED (8201L)
+#define RTD_CTRL_TX_SPEED (8202L)
+#define RTD_DEB_REG1 (8203L)
+#define RTD_DEB_REG1_VALUE (8204L)
+#define RTD_DEB_REG2 (8205L)
+#define RTD_DEB_REG2_VALUE (8206L)
+#define RTD_DEB_REG3 (8207L)
+#define RTD_DEB_REG3_VALUE (8208L)
+#define RTD_HOSTBUFFER_ADR_HI (8209L)
+#define RTD_HOSTBUFFER_ADR_HI_VALUE (8210L)
+#define RTD_HOSTBUFFER_ADR_LO (8211L)
+#define RTD_HOSTBUFFER_ADR_LO_VALUE (8212L)
+#define RTD_RDPTR_ADR_HI (8213L)
+#define RTD_RDPTR_ADR_HI_VALUE (8214L)
+#define RTD_RDPTR_ADR_LO (8215L)
+#define RTD_RDPTR_ADR_LO_VALUE (8216L)
+#define RTD_STATUS (8217L)
+#define RTD_STATUS_HB_EMPTY (8218L)
+#define RTD_STATUS_LHF_EMPTY (8219L)
+#define RTD_STATUS_UNPACKER_STATUS (8220L)
+#define RTD_WRPTR (8221L)
+#define RTD_WRPTR_VALUE (8222L)
+/* RTD_HMP */
+#define RTD_HMP_CTRL (8223L)
+#define RTD_HMP_CTRL_ENABLE_HMP_0 (8224L)
+#define RTD_HMP_CTRL_ENABLE_HMP_1 (8225L)
+#define RTD_HMP_CTRL_ENABLE_HMP_2 (8226L)
+#define RTD_HMP_CTRL_ENABLE_HMP_3 (8227L)
+#define RTD_HMP_CTRL_WRPTR_POLL_TIMER (8228L)
+#define RTD_HMP_DEB_REG1 (8229L)
+#define RTD_HMP_DEB_REG1_VALUE (8230L)
+#define RTD_HMP_DEB_REG2 (8231L)
+#define RTD_HMP_DEB_REG2_VALUE (8232L)
+#define RTD_HMP_DEB_REG3 (8233L)
+#define RTD_HMP_DEB_REG3_VALUE (8234L)
+#define RTD_HMP_STATUS (8235L)
+#define RTD_HMP_STATUS_HMP_ACTIVE (8236L)
+#define RTD_HMP_WRPTR_ADR_HI (8237L)
+#define RTD_HMP_WRPTR_ADR_HI_VALUE (8238L)
+#define RTD_HMP_WRPTR_ADR_LO (8239L)
+#define RTD_HMP_WRPTR_ADR_LO_VALUE (8240L)
+/* RTX */
+#define RTX_CTRL (8241L)
+#define RTX_CTRL_PORT (8242L)
+#define RTX_CTRL_SIZE (8243L)
+#define RTX_STATUS (8244L)
+#define RTX_STATUS_AF (8245L)
+#define RTX_STATUS_BUSY (8246L)
+#define RTX_TXF_CTRL (8247L)
+#define RTX_TXF_CTRL_CNT (8248L)
+#define RTX_TXF_DATA (8249L)
+#define RTX_TXF_DATA_PAYLOAD (8250L)
+#define RXAUI_DEBUG (8268L)
+#define RXAUI_DEBUG_MGT_CV_0 (8269L)
+#define RXAUI_DEBUG_MGT_CV_1 (8270L)
+#define RXAUI_DEBUG_MGT_CV_2 (8271L)
+#define RXAUI_DEBUG_MGT_CV_3 (8272L)
+#define RXAUI_DEBUG_MGT_CV_4 (8273L)
+#define RXAUI_DEBUG_MGT_CV_5 (8274L)
+#define RXAUI_DEBUG_MGT_CV_6 (8275L)
+#define RXAUI_DEBUG_MGT_CV_7 (8276L)
+#define RXAUI_DEBUG_MGT_RXLOCK_0 (8277L)
+#define RXAUI_DEBUG_MGT_RXLOCK_1 (8278L)
+#define RXAUI_DEBUG_MGT_RX_RESET (8279L)
+#define RXAUI_DEBUG_MGT_TX_RESET (8280L)
+#define RXAUI_DEBUG_MMCM1_LOCKED (8281L)
+#define RXAUI_DRP_AD (8282L)
+#define RXAUI_DRP_AD_ADDRESS (8283L)
+#define RXAUI_DRP_AD_DFEEYEDACMON (8284L)
+#define RXAUI_DRP_AD_GTX_NO (8285L)
+#define RXAUI_DRP_AD_READY (8286L)
+#define RXAUI_DRP_AD_RESERVED3 (8287L)
+#define RXAUI_DRP_AD_RESERVED4 (8288L)
+#define RXAUI_DRP_DA (8289L)
+#define RXAUI_DRP_DA_DATA (8290L)
+#define RXAUI_GTX_CONFIG (8291L)
+#define RXAUI_GTX_CONFIG_LOOPBACK (8292L)
+#define RXAUI_GTX_CONFIG_LOOPBACKMUX (8293L)
+#define RXAUI_GTX_CONFIG_PRBSCNTRESET (8294L)
+#define RXAUI_GTX_CONFIG_RESERVED6 (8295L)
+#define RXAUI_GTX_CONFIG_RESERVED7 (8296L)
+#define RXAUI_GTX_CONFIG_RXENPRBSTST (8297L)
+#define RXAUI_GTX_CONFIG_RXEQMIX (8298L)
+#define RXAUI_GTX_CONFIG_TXDIFFCTRL (8299L)
+#define RXAUI_GTX_CONFIG_TXENPRBSTST (8300L)
+#define RXAUI_GTX_CONFIG_TXPOSTEMPHAS (8301L)
+#define RXAUI_GTX_CONFIG_TXPRBSFORCEE (8302L)
+#define RXAUI_GTX_CONFIG_TXPREEMPHASI (8303L)
+#define RXAUI_GTX_STAT (8304L)
+#define RXAUI_GTX_STAT_RESERVED10 (8305L)
+#define RXAUI_GTX_STAT_RESERVED11 (8306L)
+#define RXAUI_GTX_STAT_RESERVED12 (8307L)
+#define RXAUI_GTX_STAT_RESERVED13 (8308L)
+#define RXAUI_GTX_STAT_RESERVED8 (8309L)
+#define RXAUI_GTX_STAT_RESERVED9 (8310L)
+#define RXAUI_GTX_STAT_RXBUFSTATUS0 (8311L)
+#define RXAUI_GTX_STAT_RXBUFSTATUS1 (8312L)
+#define RXAUI_GTX_STAT_RXBYTEISAL_0 (8313L)
+#define RXAUI_GTX_STAT_RXBYTEISAL_1 (8314L)
+#define RXAUI_GTX_STAT_RXBYTEREAL_0 (8315L)
+#define RXAUI_GTX_STAT_RXBYTEREAL_1 (8316L)
+#define RXAUI_GTX_STAT_RXCHANREAL_0 (8317L)
+#define RXAUI_GTX_STAT_RXCHANREAL_1 (8318L)
+#define RXAUI_GTX_STAT_RXCOMMADET_0 (8319L)
+#define RXAUI_GTX_STAT_RXCOMMADET_1 (8320L)
+#define RXAUI_GTX_STAT_RXPRBSERR_0 (8321L)
+#define RXAUI_GTX_STAT_RXPRBSERR_1 (8322L)
+/* SDC */
+#define SDC_CELL_CNT (8612L)
+#define SDC_CELL_CNT_CELL_CNT (8613L)
+#define SDC_CELL_CNT_PERIOD (8614L)
+#define SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD (8615L)
+#define SDC_CTRL (8616L)
+#define SDC_CTRL_INIT (8617L)
+#define SDC_CTRL_RESET_POINTERS (8618L)
+#define SDC_CTRL_RUN_TEST (8619L)
+#define SDC_CTRL_STOP_CLIENT (8620L)
+#define SDC_CTRL_TEST_EN (8621L)
+#define SDC_FILL_LVL (8622L)
+#define SDC_FILL_LVL_FILL_LVL (8623L)
+#define SDC_MAX_FILL_LVL (8624L)
+#define SDC_MAX_FILL_LVL_MAX_FILL_LVL (8625L)
+#define SDC_STAT (8626L)
+#define SDC_STAT_CALIB (8627L)
+#define SDC_STAT_CELL_CNT_STOPPED (8628L)
+#define SDC_STAT_ERR_FOUND (8629L)
+#define SDC_STAT_INIT_DONE (8630L)
+#define SDC_STAT_MMCM_LOCK (8631L)
+#define SDC_STAT_PLL_LOCK (8632L)
+#define SDC_STAT_RESETTING (8633L)
+/* SLC */
+#define SLC_RCP_CTRL (8681L)
+#define SLC_RCP_CTRL_ADR (8682L)
+#define SLC_RCP_CTRL_CNT (8683L)
+#define SLC_RCP_DATA (8684L)
+#define SLC_RCP_DATA_PCAP (8685L)
+#define SLC_RCP_DATA_TAIL_DYN (8686L)
+#define SLC_RCP_DATA_TAIL_OFS (8687L)
+#define SLC_RCP_DATA_TAIL_SLC_EN (8688L)
+/* SLC_LR */
+/* SMM */
+#define SMM_CTRL (8770L)
+#define SMM_CTRL_ENABLE (8771L)
+#define SMM_READY_STATUS (8772L)
+#define SMM_READY_STATUS_D (8773L)
+#define SMM_SEG_INVLD_STICKY_STATUS (8774L)
+#define SMM_SEG_INVLD_STICKY_STATUS_D (8775L)
+#define SMM_SEG_MEM_CTRL (8776L)
+#define SMM_SEG_MEM_CTRL_A (8777L)
+#define SMM_SEG_MEM_CTRL_CNT (8778L)
+#define SMM_SEG_MEM_DATA (8779L)
+#define SMM_SEG_MEM_DATA_PHYADDR (8780L)
+#define SMM_SEG_MEM_DATA_SIZE (8781L)
+#define SMM_START_SEG_MEM_CTRL (8782L)
+#define SMM_START_SEG_MEM_CTRL_A (8783L)
+#define SMM_START_SEG_MEM_CTRL_CNT (8784L)
+#define SMM_START_SEG_MEM_DATA (8785L)
+#define SMM_START_SEG_MEM_DATA_SEG (8786L)
+/* SPIM */
+#define SPIM_CFG (8793L)
+#define SPIM_CFG_PRE (8794L)
+#define SPIM_CMD (8795L)
+#define SPIM_CMD_ADDR (8796L)
+#define SPIM_CMD_CMD (8797L)
+#define SPIM_CMD_DATA (8798L)
+#define SPIM_CONF0 (8799L)
+#define SPIM_CONF0_BYTE_PACE (8800L)
+#define SPIM_CONF0_MIRROR_EN (8801L)
+#define SPIM_CONF0_MSB_FIRST (8802L)
+#define SPIM_CONF0_PRESCAL_CLK (8803L)
+#define SPIM_CONF0_RESTART (8804L)
+#define SPIM_CONF0_RST (8805L)
+#define SPIM_CONF0_SYNC_MON_EN (8806L)
+#define SPIM_CONF1 (8807L)
+#define SPIM_CONF1_MIRROR_PACE (8808L)
+#define SPIM_CONF1_MIRROR_SCAN (8809L)
+#define SPIM_CONF1_SYNCTIMEOUT (8810L)
+#define SPIM_CONF2 (8811L)
+#define SPIM_CONF2_MIRROR_PRESC (8812L)
+#define SPIM_CONF2_OPCODE_RD (8813L)
+#define SPIM_CONF2_OPCODE_WR (8814L)
+#define SPIM_CONF3 (8815L)
+#define SPIM_CONF3_MIRROR_RDADR (8816L)
+#define SPIM_CONF3_MIRROR_WRADR (8817L)
+#define SPIM_CR (8818L)
+#define SPIM_CR_EN (8819L)
+#define SPIM_CR_LOOP (8820L)
+#define SPIM_CR_RXRST (8821L)
+#define SPIM_CR_TXRST (8822L)
+#define SPIM_DRR (8823L)
+#define SPIM_DRR_DRR (8824L)
+#define SPIM_DTR (8825L)
+#define SPIM_DTR_DTR (8826L)
+#define SPIM_REPLY (8827L)
+#define SPIM_REPLY_RDDATA (8828L)
+#define SPIM_SR (8829L)
+#define SPIM_SR_DONE (8830L)
+#define SPIM_SR_RXEMPTY (8831L)
+#define SPIM_SR_RXFULL (8832L)
+#define SPIM_SR_RXLVL (8833L)
+#define SPIM_SR_TXEMPTY (8834L)
+#define SPIM_SR_TXFULL (8835L)
+#define SPIM_SR_TXLVL (8836L)
+#define SPIM_SRR (8837L)
+#define SPIM_SRR_RST (8838L)
+#define SPIM_STATUS (8839L)
+#define SPIM_STATUS_CMDPENDING (8840L)
+#define SPIM_STATUS_RESERVED (8841L)
+#define SPIM_STATUS_RESYNCDETECT (8842L)
+#define SPIM_STATUS_RESYNCING (8843L)
+/* SPIS */
+#define SPIS_CR (8844L)
+#define SPIS_CR_DEBUG (8845L)
+#define SPIS_CR_EN (8846L)
+#define SPIS_CR_LOOP (8847L)
+#define SPIS_CR_RXRST (8848L)
+#define SPIS_CR_TXRST (8849L)
+#define SPIS_DRR (8850L)
+#define SPIS_DRR_DRR (8851L)
+#define SPIS_DTR (8852L)
+#define SPIS_DTR_DTR (8853L)
+#define SPIS_RAM_CTRL (8854L)
+#define SPIS_RAM_CTRL_ADR (8855L)
+#define SPIS_RAM_CTRL_CNT (8856L)
+#define SPIS_RAM_DATA (8857L)
+#define SPIS_RAM_DATA_DATA (8858L)
+#define SPIS_SR (8859L)
+#define SPIS_SR_DONE (8860L)
+#define SPIS_SR_FRAME_ERR (8861L)
+#define SPIS_SR_READ_ERR (8862L)
+#define SPIS_SR_RXEMPTY (8863L)
+#define SPIS_SR_RXFULL (8864L)
+#define SPIS_SR_RXLVL (8865L)
+#define SPIS_SR_TXEMPTY (8866L)
+#define SPIS_SR_TXFULL (8867L)
+#define SPIS_SR_TXLVL (8868L)
+#define SPIS_SR_WRITE_ERR (8869L)
+#define SPIS_SRR (8870L)
+#define SPIS_SRR_RST (8871L)
+/* STA */
+#define STA_BYTE (8872L)
+#define STA_BYTE_CNT (8873L)
+#define STA_CFG (8874L)
+#define STA_CFG_CNT_CLEAR (8875L)
+#define STA_CFG_CNT_FRZ (8876L)
+#define STA_CFG_DMA_ENA (8877L)
+#define STA_CFG_TX_DISABLE (8878L)
+#define STA_CV_ERR (8879L)
+#define STA_CV_ERR_CNT (8880L)
+#define STA_FCS_ERR (8881L)
+#define STA_FCS_ERR_CNT (8882L)
+#define STA_HOST_ADR_LSB (8883L)
+#define STA_HOST_ADR_LSB_LSB (8884L)
+#define STA_HOST_ADR_MSB (8885L)
+#define STA_HOST_ADR_MSB_MSB (8886L)
+#define STA_PCKT (8887L)
+#define STA_PCKT_CNT (8888L)
+#define STA_STATUS (8889L)
+#define STA_STATUS_STAT_TOGGLE_MISSED (8890L)
+/* TBH */
+#define TBH_CTRL (9103L)
+#define TBH_CTRL_DISABLE_LR_LB (9104L)
+#define TBH_CTRL_ENABLE (9105L)
+#define TBH_CTRL_PORT (9106L)
+#define TBH_CTRL_PORT_AUS (9107L)
+#define TBH_CTRL_SEGMENT (9108L)
+#define TBH_CTRL_SEGMENT_SIZE (9109L)
+#define TBH_DBG_DLN_ERR (9110L)
+#define TBH_DBG_DLN_ERR_E (9111L)
+#define TBH_DBG_DLN_ERR_HB (9112L)
+#define TBH_DBG_ILLEGAL_RANGE (9113L)
+#define TBH_DBG_ILLEGAL_RANGE_E (9114L)
+#define TBH_DBG_ILLEGAL_RANGE_HB (9115L)
+#define TBH_DBG_MAX_PCI_QUIET (9116L)
+#define TBH_DBG_MAX_PCI_QUIET_CYCLES (9117L)
+#define TBH_DISABLE (9118L)
+#define TBH_DISABLE_DISABLE (9119L)
+#define TBH_DISABLE_HB (9120L)
+#define TBH_HB_DSC_MEM_CTRL (9121L)
+#define TBH_HB_DSC_MEM_CTRL_ADR (9122L)
+#define TBH_HB_DSC_MEM_CTRL_CNT (9123L)
+#define TBH_HB_DSC_MEM_DATA (9124L)
+#define TBH_HB_DSC_MEM_DATA_DT (9125L)
+#define TBH_HB_DSC_MEM_DATA_FCS (9126L)
+#define TBH_HB_DSC_MEM_DATA_FCS_CTL_POS (9127L)
+#define TBH_HB_DSC_MEM_DATA_FCS_CTL_USE (9128L)
+#define TBH_HB_DSC_MEM_DATA_IG_POS (9129L)
+#define TBH_HB_DSC_MEM_DATA_IG_USE (9130L)
+#define TBH_HB_DSC_MEM_DATA_OCS_CMD_POS (9131L)
+#define TBH_HB_DSC_MEM_DATA_OCS_CMD_USE (9132L)
+#define TBH_HB_DSC_MEM_DATA_OFS0_POS (9133L)
+#define TBH_HB_DSC_MEM_DATA_OFS0_USE (9134L)
+#define TBH_HB_DSC_MEM_DATA_OFS1_POS (9135L)
+#define TBH_HB_DSC_MEM_DATA_OFS1_USE (9136L)
+#define TBH_HB_DSC_MEM_DATA_OFS2_POS (9137L)
+#define TBH_HB_DSC_MEM_DATA_OFS2_USE (9138L)
+#define TBH_HB_DSC_MEM_DATA_PFD (9139L)
+#define TBH_HB_DSC_MEM_DATA_PORT (9140L)
+#define TBH_HB_DSC_MEM_DATA_PORT_MASK (9141L)
+#define TBH_HB_DSC_MEM_DATA_PORT_POS (9142L)
+#define TBH_HB_DSC_MEM_DATA_SET_CLOCK_POS (9143L)
+#define TBH_HB_DSC_MEM_DATA_SET_CLOCK_USE (9144L)
+#define TBH_HB_DSC_MEM_DATA_SW_TFD_TYPE_POS (9145L)
+#define TBH_HB_DSC_MEM_DATA_SW_TFD_TYPE_USE (9146L)
+#define TBH_HB_DSC_MEM_DATA_TS_APPEND (9147L)
+#define TBH_HB_DSC_MEM_DATA_TS_FMT (9148L)
+#define TBH_HB_DSC_MEM_DATA_TS_INJECT_POS (9149L)
+#define TBH_HB_DSC_MEM_DATA_TS_INJECT_USE (9150L)
+#define TBH_HB_DSC_MEM_DATA_TX_NOW_POS (9151L)
+#define TBH_HB_DSC_MEM_DATA_TX_NOW_USE (9152L)
+#define TBH_HB_DSC_MEM_DATA_TX_ON_TS (9153L)
+#define TBH_HB_DSC_MEM_DATA_WL_USE (9154L)
+#define TBH_HB_INFO_MEM_CTRL (9155L)
+#define TBH_HB_INFO_MEM_CTRL_A (9156L)
+#define TBH_HB_INFO_MEM_CTRL_CNT (9157L)
+#define TBH_HB_INFO_MEM_DATA (9158L)
+#define TBH_HB_INFO_MEM_DATA_SIZE (9159L)
+#define TBH_HB_PORTS_MEM_CTRL (9160L)
+#define TBH_HB_PORTS_MEM_CTRL_A (9161L)
+#define TBH_HB_PORTS_MEM_CTRL_CNT (9162L)
+#define TBH_HB_PORTS_MEM_DATA (9163L)
+#define TBH_HB_PORTS_MEM_DATA_MAPPING (9164L)
+#define TBH_PORT_MAPPING (9165L)
+#define TBH_PORT_MAPPING_P0 (9166L)
+#define TBH_PORT_MAPPING_P1 (9167L)
+#define TBH_PORT_MAPPING_P2 (9168L)
+#define TBH_PORT_MAPPING_P3 (9169L)
+#define TBH_PORT_MAPPING_P4 (9170L)
+#define TBH_PORT_MAPPING_P5 (9171L)
+#define TBH_PORT_MAPPING_P6 (9172L)
+#define TBH_PORT_MAPPING_P7 (9173L)
+#define TBH_SET_RD_POINTER (9174L)
+#define TBH_SET_RD_POINTER_HB (9175L)
+#define TBH_SET_RD_POINTER_OFFSET (9176L)
+#define TBH_STATUS (9177L)
+#define TBH_STATUS_STOPPED (9178L)
+/* TEMPMON */
+#define TEMPMON_ALARMS (9179L)
+#define TEMPMON_ALARMS_OT (9180L)
+#define TEMPMON_ALARMS_OT_OVERWR (9181L)
+#define TEMPMON_ALARMS_OT_OVERWRVAL (9182L)
+#define TEMPMON_ALARMS_TEMP (9183L)
+#define TEMPMON_STAT (9184L)
+#define TEMPMON_STAT_TEMP (9185L)
+/* TINT */
+#define TINT_CTRL (9186L)
+#define TINT_CTRL_INTERVAL (9187L)
+#define TINT_STATUS (9188L)
+#define TINT_STATUS_DELAYED (9189L)
+#define TINT_STATUS_SKIPPED (9190L)
+/* TMC */
+#define TMC_PORT_RPL (9191L)
+#define TMC_PORT_RPL_P0 (9192L)
+#define TMC_PORT_RPL_P1 (9193L)
+#define TMC_PORT_RPL_P2 (9194L)
+#define TMC_PORT_RPL_P3 (9195L)
+#define TMC_PORT_RPL_P4 (9196L)
+#define TMC_PORT_RPL_P5 (9197L)
+#define TMC_PORT_RPL_P6 (9198L)
+#define TMC_PORT_RPL_P7 (9199L)
+/* TSM */
+#define TSM_ADJ_FINE_N (9200L)
+#define TSM_ADJ_FINE_N_2DY (9201L)
+#define TSM_ADJ_FINE_N_2DY2DX (9202L)
+#define TSM_ADJ_FINE_P (9203L)
+#define TSM_ADJ_FINE_P_2DY (9204L)
+#define TSM_ADJ_FINE_P_2DY2DX (9205L)
+#define TSM_ADJ_LIMIT_HI (9206L)
+#define TSM_ADJ_LIMIT_HI_LIMIT (9207L)
+#define TSM_ADJ_LIMIT_LO (9208L)
+#define TSM_ADJ_LIMIT_LO_LIMIT (9209L)
+#define TSM_BASIC_2DY (9210L)
+#define TSM_BASIC_2DY_2DY (9211L)
+#define TSM_BASIC_2DY2DX (9212L)
+#define TSM_BASIC_2DY2DX_2DY2DX (9213L)
+#define TSM_CON0_CONFIG (9214L)
+#define TSM_CON0_CONFIG_BLIND (9215L)
+#define TSM_CON0_CONFIG_DC_SRC (9216L)
+#define TSM_CON0_CONFIG_PORT (9217L)
+#define TSM_CON0_CONFIG_PPSIN_2_5V (9218L)
+#define TSM_CON0_CONFIG_SAMPLE_EDGE (9219L)
+#define TSM_CON0_INTERFACE (9220L)
+#define TSM_CON0_INTERFACE_EX_TERM (9221L)
+#define TSM_CON0_INTERFACE_IN_REF_PWM (9222L)
+#define TSM_CON0_INTERFACE_PWM_ENA (9223L)
+#define TSM_CON0_INTERFACE_RESERVED (9224L)
+#define TSM_CON0_INTERFACE_VTERM_PWM (9225L)
+#define TSM_CON0_SAMPLE_HI (9226L)
+#define TSM_CON0_SAMPLE_HI_SEC (9227L)
+#define TSM_CON0_SAMPLE_LO (9228L)
+#define TSM_CON0_SAMPLE_LO_NS (9229L)
+#define TSM_CON1_CONFIG (9230L)
+#define TSM_CON1_CONFIG_BLIND (9231L)
+#define TSM_CON1_CONFIG_DC_SRC (9232L)
+#define TSM_CON1_CONFIG_PORT (9233L)
+#define TSM_CON1_CONFIG_PPSIN_2_5V (9234L)
+#define TSM_CON1_CONFIG_SAMPLE_EDGE (9235L)
+#define TSM_CON1_SAMPLE_HI (9236L)
+#define TSM_CON1_SAMPLE_HI_SEC (9237L)
+#define TSM_CON1_SAMPLE_LO (9238L)
+#define TSM_CON1_SAMPLE_LO_NS (9239L)
+#define TSM_CON2_CONFIG (9240L)
+#define TSM_CON2_CONFIG_BLIND (9241L)
+#define TSM_CON2_CONFIG_DC_SRC (9242L)
+#define TSM_CON2_CONFIG_PORT (9243L)
+#define TSM_CON2_CONFIG_PPSIN_2_5V (9244L)
+#define TSM_CON2_CONFIG_SAMPLE_EDGE (9245L)
+#define TSM_CON2_SAMPLE_HI (9246L)
+#define TSM_CON2_SAMPLE_HI_SEC (9247L)
+#define TSM_CON2_SAMPLE_LO (9248L)
+#define TSM_CON2_SAMPLE_LO_NS (9249L)
+#define TSM_CON3_CONFIG (9250L)
+#define TSM_CON3_CONFIG_BLIND (9251L)
+#define TSM_CON3_CONFIG_PORT (9252L)
+#define TSM_CON3_CONFIG_SAMPLE_EDGE (9253L)
+#define TSM_CON3_SAMPLE_HI (9254L)
+#define TSM_CON3_SAMPLE_HI_SEC (9255L)
+#define TSM_CON3_SAMPLE_LO (9256L)
+#define TSM_CON3_SAMPLE_LO_NS (9257L)
+#define TSM_CON4_CONFIG (9258L)
+#define TSM_CON4_CONFIG_BLIND (9259L)
+#define TSM_CON4_CONFIG_PORT (9260L)
+#define TSM_CON4_CONFIG_SAMPLE_EDGE (9261L)
+#define TSM_CON4_SAMPLE_HI (9262L)
+#define TSM_CON4_SAMPLE_HI_SEC (9263L)
+#define TSM_CON4_SAMPLE_LO (9264L)
+#define TSM_CON4_SAMPLE_LO_NS (9265L)
+#define TSM_CON5_CONFIG (9266L)
+#define TSM_CON5_CONFIG_BLIND (9267L)
+#define TSM_CON5_CONFIG_PORT (9268L)
+#define TSM_CON5_CONFIG_SAMPLE_EDGE (9269L)
+#define TSM_CON5_SAMPLE_HI (9270L)
+#define TSM_CON5_SAMPLE_HI_SEC (9271L)
+#define TSM_CON5_SAMPLE_LO (9272L)
+#define TSM_CON5_SAMPLE_LO_TIME (9273L)
+#define TSM_CON6_CONFIG (9274L)
+#define TSM_CON6_CONFIG_BLIND (9275L)
+#define TSM_CON6_CONFIG_PORT (9276L)
+#define TSM_CON6_CONFIG_SAMPLE_EDGE (9277L)
+#define TSM_CON6_SAMPLE_HI (9278L)
+#define TSM_CON6_SAMPLE_HI_SEC (9279L)
+#define TSM_CON6_SAMPLE_LO (9280L)
+#define TSM_CON6_SAMPLE_LO_NS (9281L)
+#define TSM_CON7_HOST_SAMPLE_HI (9282L)
+#define TSM_CON7_HOST_SAMPLE_HI_SEC (9283L)
+#define TSM_CON7_HOST_SAMPLE_LO (9284L)
+#define TSM_CON7_HOST_SAMPLE_LO_NS (9285L)
+#define TSM_CONFIG (9286L)
+#define TSM_CONFIG_NTTS_SRC (9287L)
+#define TSM_CONFIG_NTTS_SYNC (9288L)
+#define TSM_CONFIG_TIMESET_EDGE (9289L)
+#define TSM_CONFIG_TIMESET_SRC (9290L)
+#define TSM_CONFIG_TIMESET_UP (9291L)
+#define TSM_CONFIG_TS_FORMAT (9292L)
+#define TSM_CTRL (9293L)
+#define TSM_CTRL_DCEN_CON0 (9294L)
+#define TSM_CTRL_DCEN_CON1 (9295L)
+#define TSM_CTRL_DCEN_CON2 (9296L)
+#define TSM_CTRL_FORMAT (9297L)
+#define TSM_CTRL_HIGH_SAMPLE (9298L)
+#define TSM_CTRL_LED_CON0 (9299L)
+#define TSM_CTRL_LED_CON1 (9300L)
+#define TSM_CTRL_LED_CON2 (9301L)
+#define TSM_CTRL_MASTER_STAT (9302L)
+#define TSM_CTRL_OEN_CON0 (9303L)
+#define TSM_CTRL_OEN_CON1 (9304L)
+#define TSM_CTRL_OEN_CON2 (9305L)
+#define TSM_CTRL_PPSEN (9306L)
+#define TSM_CTRL_PPS_NEGEDGE (9307L)
+#define TSM_CTRL_PPS_TIME_UP (9308L)
+#define TSM_CTRL_PTP_TIME_UP (9309L)
+#define TSM_CTRL_RESERVED (9310L)
+#define TSM_CTRL_SEL_EXTSRC (9311L)
+#define TSM_CTRL_SYNEN (9312L)
+#define TSM_CTRL_TS_CON0 (9313L)
+#define TSM_CTRL_TS_CON1 (9314L)
+#define TSM_CTRL_TS_CON2 (9315L)
+#define TSM_EXT_STAT (9316L)
+#define TSM_EXT_STAT_STAT (9317L)
+#define TSM_EXT_TIME_HI (9318L)
+#define TSM_EXT_TIME_HI_TIME (9319L)
+#define TSM_EXT_TIME_LO (9320L)
+#define TSM_EXT_TIME_LO_TIME (9321L)
+#define TSM_INTERFACE (9322L)
+#define TSM_INTERFACE_EX_TERM (9323L)
+#define TSM_INTERFACE_IN_REF_PWM (9324L)
+#define TSM_INTERFACE_PWM_ENA (9325L)
+#define TSM_INTERFACE_RESERVED (9326L)
+#define TSM_INTERFACE_VTERM_PWM (9327L)
+#define TSM_INT_CONFIG (9328L)
+#define TSM_INT_CONFIG_AUTO_DISABLE (9329L)
+#define TSM_INT_CONFIG_MASK (9330L)
+#define TSM_INT_STAT (9331L)
+#define TSM_INT_STAT_CAUSE (9332L)
+#define TSM_INT_STAT_ENABLE (9333L)
+#define TSM_INT_TIME_HI (9334L)
+#define TSM_INT_TIME_HI_TIME (9335L)
+#define TSM_INT_TIME_LO (9336L)
+#define TSM_INT_TIME_LO_TIME (9337L)
+#define TSM_LED (9338L)
+#define TSM_LED_LED0_BG_COLOR (9339L)
+#define TSM_LED_LED0_COLOR (9340L)
+#define TSM_LED_LED0_MODE (9341L)
+#define TSM_LED_LED0_SRC (9342L)
+#define TSM_LED_LED1_BG_COLOR (9343L)
+#define TSM_LED_LED1_COLOR (9344L)
+#define TSM_LED_LED1_MODE (9345L)
+#define TSM_LED_LED1_SRC (9346L)
+#define TSM_LED_LED2_BG_COLOR (9347L)
+#define TSM_LED_LED2_COLOR (9348L)
+#define TSM_LED_LED2_MODE (9349L)
+#define TSM_LED_LED2_SRC (9350L)
+#define TSM_NTTS_CONFIG (9351L)
+#define TSM_NTTS_CONFIG_AUTO_HARDSET (9352L)
+#define TSM_NTTS_CONFIG_EXT_CLK_ADJ (9353L)
+#define TSM_NTTS_CONFIG_HIGH_SAMPLE (9354L)
+#define TSM_NTTS_CONFIG_TS_SRC_FORMAT (9355L)
+#define TSM_NTTS_CTRL (9356L)
+#define TSM_NTTS_CTRL_NTTS_CMD (9357L)
+#define TSM_NTTS_DATA_HI (9358L)
+#define TSM_NTTS_DATA_HI_DATA (9359L)
+#define TSM_NTTS_DATA_LO (9360L)
+#define TSM_NTTS_DATA_LO_DATA (9361L)
+#define TSM_NTTS_EXT_STAT (9362L)
+#define TSM_NTTS_EXT_STAT_MASTER_ID (9363L)
+#define TSM_NTTS_EXT_STAT_MASTER_REV (9364L)
+#define TSM_NTTS_EXT_STAT_MASTER_STAT (9365L)
+#define TSM_NTTS_LIMIT_HI (9366L)
+#define TSM_NTTS_LIMIT_HI_SEC (9367L)
+#define TSM_NTTS_LIMIT_LO (9368L)
+#define TSM_NTTS_LIMIT_LO_NS (9369L)
+#define TSM_NTTS_OFFSET (9370L)
+#define TSM_NTTS_OFFSET_NS (9371L)
+#define TSM_NTTS_SAMPLE_HI (9372L)
+#define TSM_NTTS_SAMPLE_HI_SEC (9373L)
+#define TSM_NTTS_SAMPLE_LO (9374L)
+#define TSM_NTTS_SAMPLE_LO_NS (9375L)
+#define TSM_NTTS_STAT (9376L)
+#define TSM_NTTS_STAT_NTTS_VALID (9377L)
+#define TSM_NTTS_STAT_SIGNAL_LOST (9378L)
+#define TSM_NTTS_STAT_SYNC_LOST (9379L)
+#define TSM_NTTS_TS_T0_HI (9380L)
+#define TSM_NTTS_TS_T0_HI_TIME (9381L)
+#define TSM_NTTS_TS_T0_LO (9382L)
+#define TSM_NTTS_TS_T0_LO_TIME (9383L)
+#define TSM_NTTS_TS_T0_OFFSET (9384L)
+#define TSM_NTTS_TS_T0_OFFSET_COUNT (9385L)
+#define TSM_OFFSET_HI (9386L)
+#define TSM_OFFSET_HI_OFFSET (9387L)
+#define TSM_OFFSET_LO (9388L)
+#define TSM_OFFSET_LO_OFFSET (9389L)
+#define TSM_PB_CTRL (9390L)
+#define TSM_PB_CTRL_INSTMEM_WR (9391L)
+#define TSM_PB_CTRL_RESET (9392L)
+#define TSM_PB_CTRL_RST (9393L)
+#define TSM_PB_INSTMEM (9394L)
+#define TSM_PB_INSTMEM_ADDR (9395L)
+#define TSM_PB_INSTMEM_DATA (9396L)
+#define TSM_PB_INSTMEM_MEM_ADDR (9397L)
+#define TSM_PB_INSTMEM_MEM_DATA (9398L)
+#define TSM_PI_CTRL_I (9399L)
+#define TSM_PI_CTRL_I_VAL (9400L)
+#define TSM_PI_CTRL_KI (9401L)
+#define TSM_PI_CTRL_KI_GAIN (9402L)
+#define TSM_PI_CTRL_KP (9403L)
+#define TSM_PI_CTRL_KP_GAIN (9404L)
+#define TSM_PI_CTRL_SHL (9405L)
+#define TSM_PI_CTRL_SHL_VAL (9406L)
+#define TSM_RSYNC_COUNT (9407L)
+#define TSM_RSYNC_COUNT_COUNT (9408L)
+#define TSM_STAT (9409L)
+#define TSM_STAT_EXT_SRC_OK (9410L)
+#define TSM_STAT_HARD_SYNC (9411L)
+#define TSM_STAT_INSYNC (9412L)
+#define TSM_STAT_LINK_ACTIVE (9413L)
+#define TSM_STAT_LINK_CON0 (9414L)
+#define TSM_STAT_LINK_CON1 (9415L)
+#define TSM_STAT_LINK_CON2 (9416L)
+#define TSM_STAT_LINK_CON3 (9417L)
+#define TSM_STAT_LINK_CON4 (9418L)
+#define TSM_STAT_LINK_CON5 (9419L)
+#define TSM_STAT_NTTS_INSYNC (9420L)
+#define TSM_STAT_PTP_MI_PRESENT (9421L)
+#define TSM_TIMER_CTRL (9422L)
+#define TSM_TIMER_CTRL_TIMER_EN_T0 (9423L)
+#define TSM_TIMER_CTRL_TIMER_EN_T1 (9424L)
+#define TSM_TIMER_CTRL_TRIGGER_SEL (9425L)
+#define TSM_TIMER_D_T0 (9426L)
+#define TSM_TIMER_D_T0_MAX_COUNT (9427L)
+#define TSM_TIMER_T0 (9428L)
+#define TSM_TIMER_T0_MAX_COUNT (9429L)
+#define TSM_TIMER_T1 (9430L)
+#define TSM_TIMER_T1_MAX_COUNT (9431L)
+#define TSM_TIMESTAMP_HI (9432L)
+#define TSM_TIMESTAMP_HI_TIME (9433L)
+#define TSM_TIMESTAMP_LO (9434L)
+#define TSM_TIMESTAMP_LO_TIME (9435L)
+#define TSM_TIME_HARDSET_HI (9436L)
+#define TSM_TIME_HARDSET_HI_TIME (9437L)
+#define TSM_TIME_HARDSET_LO (9438L)
+#define TSM_TIME_HARDSET_LO_TIME (9439L)
+#define TSM_TIME_HI (9440L)
+#define TSM_TIME_HI_SEC (9441L)
+#define TSM_TIME_HI_TIME (9442L)
+#define TSM_TIME_LO (9443L)
+#define TSM_TIME_LO_NS (9444L)
+#define TSM_TIME_RATE_ADJ (9445L)
+#define TSM_TIME_RATE_ADJ_FRACTION (9446L)
+#define TSM_TS_HI (9447L)
+#define TSM_TS_HI_TIME (9448L)
+#define TSM_TS_LO (9449L)
+#define TSM_TS_LO_TIME (9450L)
+#define TSM_TS_OFFSET (9451L)
+#define TSM_TS_OFFSET_NS (9452L)
+#define TSM_TS_STAT (9453L)
+#define TSM_TS_STAT_OVERRUN (9454L)
+#define TSM_TS_STAT_SAMPLES (9455L)
+#define TSM_TS_STAT_HI_OFFSET (9456L)
+#define TSM_TS_STAT_HI_OFFSET_NS (9457L)
+#define TSM_TS_STAT_LO_OFFSET (9458L)
+#define TSM_TS_STAT_LO_OFFSET_NS (9459L)
+#define TSM_TS_STAT_TAR_HI (9460L)
+#define TSM_TS_STAT_TAR_HI_SEC (9461L)
+#define TSM_TS_STAT_TAR_LO (9462L)
+#define TSM_TS_STAT_TAR_LO_NS (9463L)
+#define TSM_TS_STAT_X (9464L)
+#define TSM_TS_STAT_X_NS (9465L)
+#define TSM_TS_STAT_X2_HI (9466L)
+#define TSM_TS_STAT_X2_HI_NS (9467L)
+#define TSM_TS_STAT_X2_LO (9468L)
+#define TSM_TS_STAT_X2_LO_NS (9469L)
+#define TSM_UTC_OFFSET (9470L)
+#define TSM_UTC_OFFSET_SEC (9471L)
+
+#endif /* _NTHW_FPGA_REGISTERS_DEFS_ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH v2 2/8] net/ntnic: adds core registers and fpga functionality
2023-08-17 14:43 ` [PATCH v2 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
@ 2023-08-17 14:43 ` Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 3/8] net/ntnic: adds NT200A02 adapter support Mykola Kostenok
` (6 subsequent siblings)
7 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-17 14:43 UTC (permalink / raw)
To: dev, mko-plv; +Cc: ckm
From: Christian Koue Muf <ckm@napatech.com>
Includes functionality to reset, initialize, program, and collect
stats for the NTNIC FPGA.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
v2:
* Fixed WARNING:TYPO_SPELLING
* Fix compilation for Fedora38
---
drivers/net/ntnic/include/nthw_bus.h | 10 +
drivers/net/ntnic/meson.build | 32 +
.../net/ntnic/nthw/core/nthw_clock_profiles.c | 9 +
.../net/ntnic/nthw/core/nthw_clock_profiles.h | 39 +
drivers/net/ntnic/nthw/core/nthw_core.h | 31 +
drivers/net/ntnic/nthw/core/nthw_fpga.c | 914 +++++++++
drivers/net/ntnic/nthw/core/nthw_fpga.h | 47 +
.../net/ntnic/nthw/core/nthw_fpga_nt200a0x.c | 46 +
.../net/ntnic/nthw/core/nthw_fpga_nt200a0x.h | 14 +
drivers/net/ntnic/nthw/core/nthw_fpga_rst.c | 10 +
drivers/net/ntnic/nthw/core/nthw_fpga_rst.h | 17 +
.../net/ntnic/nthw/core/nthw_fpga_rst9563.c | 241 +++
.../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c | 674 +++++++
.../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h | 89 +
drivers/net/ntnic/nthw/core/nthw_gpio_phy.c | 271 +++
drivers/net/ntnic/nthw/core/nthw_gpio_phy.h | 57 +
drivers/net/ntnic/nthw/core/nthw_hif.c | 342 ++++
drivers/net/ntnic/nthw/core/nthw_hif.h | 156 ++
drivers/net/ntnic/nthw/core/nthw_iic.c | 570 ++++++
drivers/net/ntnic/nthw/core/nthw_iic.h | 101 +
drivers/net/ntnic/nthw/core/nthw_mac_pcs.c | 1034 ++++++++++
drivers/net/ntnic/nthw/core/nthw_mac_pcs.h | 261 +++
.../net/ntnic/nthw/core/nthw_mac_pcs_xxv.c | 1631 ++++++++++++++++
.../net/ntnic/nthw/core/nthw_mac_pcs_xxv.h | 291 +++
drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c | 121 ++
drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h | 51 +
drivers/net/ntnic/nthw/core/nthw_pci_ta.c | 99 +
drivers/net/ntnic/nthw/core/nthw_pci_ta.h | 40 +
drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c | 127 ++
drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h | 55 +
drivers/net/ntnic/nthw/core/nthw_pcie3.c | 274 +++
drivers/net/ntnic/nthw/core/nthw_pcie3.h | 100 +
drivers/net/ntnic/nthw/core/nthw_sdc.c | 177 ++
drivers/net/ntnic/nthw/core/nthw_sdc.h | 43 +
drivers/net/ntnic/nthw/core/nthw_si5340.c | 206 ++
drivers/net/ntnic/nthw/core/nthw_si5340.h | 34 +
drivers/net/ntnic/nthw/core/nthw_spi_v3.c | 380 ++++
drivers/net/ntnic/nthw/core/nthw_spi_v3.h | 106 ++
drivers/net/ntnic/nthw/core/nthw_spim.c | 117 ++
drivers/net/ntnic/nthw/core/nthw_spim.h | 52 +
drivers/net/ntnic/nthw/core/nthw_spis.c | 147 ++
drivers/net/ntnic/nthw/core/nthw_spis.h | 63 +
drivers/net/ntnic/nthw/core/nthw_tsm.c | 179 ++
drivers/net/ntnic/nthw/core/nthw_tsm.h | 53 +
drivers/net/ntnic/nthw/nthw_dbs.c | 1301 +++++++++++++
drivers/net/ntnic/nthw/nthw_dbs.h | 313 +++
drivers/net/ntnic/nthw/nthw_drv.h | 82 +
drivers/net/ntnic/nthw/nthw_epp.c | 335 ++++
drivers/net/ntnic/nthw/nthw_epp.h | 99 +
drivers/net/ntnic/nthw/nthw_fpga_model.c | 1677 +++++++++++++++++
drivers/net/ntnic/nthw/nthw_fpga_model.h | 308 +++
drivers/net/ntnic/nthw/nthw_helper.h | 21 +
drivers/net/ntnic/nthw/nthw_platform.c | 35 +
drivers/net/ntnic/nthw/nthw_platform_drv.h | 42 +
drivers/net/ntnic/nthw/nthw_profile.h | 15 +
drivers/net/ntnic/nthw/nthw_rac.c | 976 ++++++++++
drivers/net/ntnic/nthw/nthw_rac.h | 161 ++
drivers/net/ntnic/nthw/nthw_register.h | 2 +
drivers/net/ntnic/nthw/nthw_stat.c | 266 +++
drivers/net/ntnic/nthw/nthw_stat.h | 72 +
drivers/net/ntnic/ntlog/include/ntlog.h | 162 ++
drivers/net/ntnic/ntlog/ntlog.c | 114 ++
drivers/net/ntnic/ntutil/include/nt_util.h | 71 +
drivers/net/ntnic/ntutil/nt_util.c | 77 +
64 files changed, 15440 insertions(+)
create mode 100644 drivers/net/ntnic/include/nthw_bus.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_core.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.h
create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.c
create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.h
create mode 100644 drivers/net/ntnic/nthw/nthw_drv.h
create mode 100644 drivers/net/ntnic/nthw/nthw_epp.c
create mode 100644 drivers/net/ntnic/nthw/nthw_epp.h
create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.c
create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.h
create mode 100644 drivers/net/ntnic/nthw/nthw_helper.h
create mode 100644 drivers/net/ntnic/nthw/nthw_platform.c
create mode 100644 drivers/net/ntnic/nthw/nthw_platform_drv.h
create mode 100644 drivers/net/ntnic/nthw/nthw_profile.h
create mode 100644 drivers/net/ntnic/nthw/nthw_rac.c
create mode 100644 drivers/net/ntnic/nthw/nthw_rac.h
create mode 100644 drivers/net/ntnic/nthw/nthw_stat.c
create mode 100644 drivers/net/ntnic/nthw/nthw_stat.h
create mode 100644 drivers/net/ntnic/ntlog/include/ntlog.h
create mode 100644 drivers/net/ntnic/ntlog/ntlog.c
create mode 100644 drivers/net/ntnic/ntutil/include/nt_util.h
create mode 100644 drivers/net/ntnic/ntutil/nt_util.c
diff --git a/drivers/net/ntnic/include/nthw_bus.h b/drivers/net/ntnic/include/nthw_bus.h
new file mode 100644
index 0000000000..975cc95e78
--- /dev/null
+++ b/drivers/net/ntnic/include/nthw_bus.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_BUS_H__
+#define __NTHW_BUS_H__
+
+typedef uint8_t rab_bus_id_t;
+
+#endif /* __NTHW_BUS_H__ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 99569c2843..65064f44ab 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -10,13 +10,45 @@ cflags += [
includes = [
include_directories('.'),
include_directories('include'),
+ include_directories('ntlog/include'),
+ include_directories('ntutil/include'),
include_directories('nthw'),
+ include_directories('nthw/core'),
include_directories('nthw/supported'),
]
# all sources
sources = files(
+ 'nthw/core/nthw_clock_profiles.c',
+ 'nthw/core/nthw_fpga.c',
+ 'nthw/core/nthw_fpga_nt200a0x.c',
+ 'nthw/core/nthw_fpga_rst.c',
+ 'nthw/core/nthw_fpga_rst9563.c',
+ 'nthw/core/nthw_fpga_rst_nt200a0x.c',
+ 'nthw/core/nthw_gpio_phy.c',
+ 'nthw/core/nthw_hif.c',
+ 'nthw/core/nthw_iic.c',
+ 'nthw/core/nthw_mac_pcs.c',
+ 'nthw/core/nthw_mac_pcs_xxv.c',
+ 'nthw/core/nthw_pci_rd_tg.c',
+ 'nthw/core/nthw_pci_ta.c',
+ 'nthw/core/nthw_pci_wr_tg.c',
+ 'nthw/core/nthw_pcie3.c',
+ 'nthw/core/nthw_sdc.c',
+ 'nthw/core/nthw_si5340.c',
+ 'nthw/core/nthw_spi_v3.c',
+ 'nthw/core/nthw_spim.c',
+ 'nthw/core/nthw_spis.c',
+ 'nthw/core/nthw_tsm.c',
+ 'nthw/nthw_fpga_model.c',
+ 'nthw/nthw_dbs.c',
+ 'nthw/nthw_epp.c',
+ 'nthw/nthw_platform.c',
+ 'nthw/nthw_rac.c',
+ 'nthw/nthw_stat.c',
'nthw/supported/nthw_fpga_9563_055_024_0000.c',
+ 'ntlog/ntlog.c',
+ 'ntutil/nt_util.c',
)
if is_variable('default_cflags')
diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
new file mode 100644
index 0000000000..efdcc222a8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_clock_profiles.h"
+
+/* Clock profile for NT200A02 2x40G, 2x100G */
+const int n_data_si5340_nt200a02_u23_v5;
+const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;
diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h
new file mode 100644
index 0000000000..4252f69e92
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_CLOCK_PROFILES_H__
+#define __NTHW_CLOCK_PROFILES_H__
+
+#include <stdint.h>
+
+#include "nthw_helper.h"
+
+#define clk_profile_size_error_msg "size test failed"
+
+typedef struct {
+ unsigned char reg_addr;
+ unsigned char reg_val;
+ unsigned char reg_mask;
+} clk_profile_data_fmt0_t;
+
+typedef struct {
+ uint16_t reg_addr;
+ uint8_t reg_val;
+} clk_profile_data_fmt1_t;
+
+typedef struct {
+ unsigned int reg_addr;
+ unsigned char reg_val;
+} clk_profile_data_fmt2_t;
+
+typedef enum {
+ CLK_PROFILE_DATA_FMT_0,
+ CLK_PROFILE_DATA_FMT_1,
+ CLK_PROFILE_DATA_FMT_2
+} clk_profile_data_fmt_t;
+
+extern const int n_data_si5340_nt200a02_u23_v5;
+extern const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;
+
+#endif /* __NTHW_CLOCK_PROFILES_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h
new file mode 100644
index 0000000000..798a95d5cf
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_core.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_CORE_H__
+#define __NTHW_CORE_H__
+
+#include "nthw_helper.h"
+
+#include "nthw_platform_drv.h"
+#include "nthw_fpga_model.h"
+#include "nthw_hif.h"
+#include "nthw_pcie3.h"
+#include "nthw_pci_rd_tg.h"
+#include "nthw_pci_wr_tg.h"
+#include "nthw_pci_ta.h"
+#include "nthw_iic.h"
+
+#include "nthw_gpio_phy.h"
+#include "nthw_mac_pcs.h"
+#include "nthw_mac_pcs_xxv.h"
+#include "nthw_sdc.h"
+
+#include "nthw_spim.h"
+#include "nthw_spis.h"
+
+#include "nthw_tsm.h"
+
+#include "nthw_si5340.h"
+
+#endif /* __NTHW_CORE_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c
new file mode 100644
index 0000000000..646d45b7eb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c
@@ -0,0 +1,914 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_fpga.h"
+#include "nthw_fpga_instances.h"
+
+#include "nthw_spi_v3.h"
+
+#include <arpa/inet.h>
+
+int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga)
+{
+ const int n_nims = fpga_get_product_param(p_fpga, NT_NIMS, -1);
+ const int n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, -1);
+ const int n_phy_quads = fpga_get_product_param(p_fpga, NT_PHY_QUADS, -1);
+ const int n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, -1);
+ const int n_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, -1);
+
+ p_fpga_info->n_nims = n_nims;
+ p_fpga_info->n_phy_ports = n_phy_ports;
+ p_fpga_info->n_phy_quads = n_phy_quads;
+ p_fpga_info->n_rx_ports = n_rx_ports;
+ p_fpga_info->n_tx_ports = n_tx_ports;
+ p_fpga_info->profile = FPGA_INFO_PROFILE_UNKNOWN;
+
+ /* Check for VSWITCH FPGA */
+ if (fpga_get_product_param(p_fpga, NT_NFV_OVS_PRODUCT, 0) != 0)
+ p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH;
+ /* Check for VSWITCH FPGA - legacy */
+ else if (fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0) != 0)
+ p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH;
+
+ else if (fpga_get_product_param(p_fpga, NT_QM_PRESENT, 0) != 0)
+ p_fpga_info->profile = FPGA_INFO_PROFILE_CAPTURE;
+
+ else
+ p_fpga_info->profile = FPGA_INFO_PROFILE_INLINE;
+
+ return 0;
+}
+
+int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr)
+{
+ nthw_iic_t nthw_iic;
+ uint8_t val = 0;
+
+ if (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0)
+ return -1;
+
+ if (nthw_iic_readbyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) == 0)
+ return val;
+
+ else
+ return -1;
+}
+
+int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr,
+ uint8_t val)
+{
+ nthw_iic_t nthw_iic;
+
+ if (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0)
+ return -1;
+
+ if (nthw_iic_writebyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) != 0)
+ return -1;
+
+ return 0;
+}
+
+int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin,
+ const int n_instance_no_end)
+{
+ int i;
+
+ assert(n_instance_no_begin <= n_instance_no_end);
+
+ for (i = n_instance_no_begin; i <= n_instance_no_end; i++) {
+ nthw_iic_t *p_nthw_iic = nthw_iic_new();
+
+ if (p_nthw_iic) {
+ const int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8);
+
+ if (rc == 0) {
+ nthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100,
+ 3, 3);
+ nthw_iic_scan(p_nthw_iic);
+ }
+ nthw_iic_delete(p_nthw_iic);
+ p_nthw_iic = NULL;
+ }
+ }
+ return 0;
+}
+
+int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no,
+ const int n_dev_addr, const int n_page_reg_addr)
+{
+ const char *const p_adapter_id_str _unused =
+ p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint64_t ident = -1;
+ int res = -1;
+
+ nthw_iic_t *p_nthw_iic = nthw_iic_new();
+
+ if (p_nthw_iic) {
+ uint8_t data;
+ uint8_t a_silabs_ident[8];
+
+ nthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8);
+
+ data = 0;
+ /* switch to page 0 */
+ nthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr,
+ (uint8_t)n_page_reg_addr, 1, &data);
+ res = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00,
+ sizeof(a_silabs_ident), a_silabs_ident);
+ if (res == 0) {
+ int i;
+
+ for (i = 0; i < (int)sizeof(a_silabs_ident); i++) {
+ ident <<= 8;
+ ident |= a_silabs_ident[i];
+ }
+ }
+ nthw_iic_delete(p_nthw_iic);
+ p_nthw_iic = NULL;
+
+ /* Conclude SiLabs part */
+ if (res == 0) {
+ if (a_silabs_ident[3] == 0x53) {
+ if (a_silabs_ident[2] == 0x40)
+ res = 5340;
+ else if (a_silabs_ident[2] == 0x41)
+ res = 5341;
+ } else if (a_silabs_ident[2] == 38) {
+ res = 5338;
+ } else {
+ res = -1;
+ }
+ }
+ }
+
+ NT_LOG(DBG, NTHW, "%s: %016" PRIX64 ": %d\n", p_adapter_id_str, ident,
+ res);
+ return res;
+}
+
+/*
+ * Calculate CRC-16-CCITT of passed data
+ * CRC-16-CCITT ^16 + ^12 + ^5 + 1 (0x1021) (X.25, HDLC, XMODEM, Bluetooth,
+ * SD, many others; known as CRC-CCITT)
+ */
+static uint16_t crc16(uint8_t *buffer, size_t length)
+{
+ uint16_t seed = 0;
+
+ while (length--) {
+ seed = (uint16_t)(seed >> 8 | seed << 8);
+ seed = (uint16_t)(seed ^ *buffer++);
+ seed = (uint16_t)(seed ^ (seed & 0xff) >> 4);
+ seed = (uint16_t)(seed ^ seed << 8 << 4);
+ seed = (uint16_t)(seed ^ (seed & 0xff) << 4 << 1);
+ }
+ return seed;
+}
+
+int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no)
+{
+ struct fpga_info_s *p_fpga_info = p_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ nthw_spi_v3_t *p_avr_spi;
+ int res = -1;
+
+ p_avr_spi = nthw_spi_v3_new();
+ if (p_avr_spi) {
+ struct avr_vpd_info_s {
+ /* avr info */
+ uint32_t n_avr_spi_version;
+ uint8_t n_avr_fw_ver_major;
+ uint8_t n_avr_fw_ver_minor;
+ uint8_t n_avr_fw_ver_micro;
+ uint8_t a_avr_fw_ver_str[50];
+ uint8_t a_avr_fw_plat_id_str[20];
+
+ /* vpdEeprom_t */
+ uint8_t psu_hw_version;
+ uint8_t vpd_pn[GEN2_PN_SIZE];
+ uint8_t vpd_pba[GEN2_PBA_SIZE];
+ uint8_t vpd_sn[GEN2_SN_SIZE];
+ uint8_t vpd_board_name[GEN2_BNAME_SIZE];
+ uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];
+
+ /* BoardInfo_t aka vpd_platform_section: */
+ uint32_t product_family; /* uint8_t 1: capture, 2: Inline, 3: analysis */
+ uint32_t feature_mask; /* Bit 0: OC192 capable */
+ uint32_t invfeature_mask;
+ uint8_t no_of_macs;
+ uint8_t mac_address[6];
+ uint16_t custom_id;
+ uint8_t user_id[8];
+ /*
+ * Reserved NT operations to monitor the reprogram count of userId with
+ * vpduser
+ */
+ uint16_t user_id_erase_write_count;
+
+ /*
+ * AVR_OP_SYSINFO: struct version_sysinfo_request_container
+ * Which version of the sysinfo container to retrieve. Set to zero to fetch
+ * latest. offset zero of latest always contain an uint8_t version info
+ */
+ uint8_t sysinfo_container_version;
+
+ /* AVR_OP_SYSINFO: struct AvrLibcVersion */
+ uint32_t sysinfo_avr_libc_version; /* The constant __AVR_LIBC_VERSION__ */
+
+ /* AVR_OP_SYSINFO: struct AvrLibcSignature */
+ uint8_t sysinfo_signature_0; /* The constant SIGNATURE_0 */
+ uint8_t sysinfo_signature_1; /* The constant SIGNATURE_1 */
+ uint8_t sysinfo_signature_2; /* The constant SIGNATURE_2 */
+
+ /* AVR_OP_SYSINFO: struct AvrOs */
+ uint8_t sysinfo_spi_version; /* SPI command layer version */
+ /*
+ * Hardware revision. Locked to eeprom address zero. Is also available via
+ * VPD read opcode (prior to v1.4b, this is required)
+ */
+ uint8_t sysinfo_hw_revision;
+ /*
+ * Number of ticks/second (Note: Be aware this may become zero if timer
+ * module is rewritten to a tickles system!)
+ */
+ uint8_t sysinfo_ticks_per_second;
+ uint32_t sysinfo_uptime; /* Uptime in seconds since last AVR reset */
+ uint8_t sysinfo_osccal; /* OSCCAL value */
+
+ /*
+ * Meta data concluded/calculated from req/reply
+ */
+ bool b_feature_mask_valid;
+ bool b_crc16_valid;
+ uint16_t n_crc16_stored;
+ uint16_t n_crc16_calced;
+ uint64_t n_mac_val;
+ };
+
+ struct avr_vpd_info_s avr_vpd_info;
+ struct tx_rx_buf tx_buf;
+ struct tx_rx_buf rx_buf;
+ char rx_data[MAX_AVR_CONTAINER_SIZE];
+ uint32_t u32;
+
+ memset(&avr_vpd_info, 0, sizeof(avr_vpd_info));
+
+ nthw_spi_v3_init(p_avr_spi, p_fpga, n_instance_no);
+
+ /* AVR_OP_SPI_VERSION */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(u32);
+ rx_buf.p_buf = &u32;
+ u32 = 0;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SPI_VERSION, &tx_buf,
+ &rx_buf);
+ avr_vpd_info.n_avr_spi_version = u32;
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n", p_adapter_id_str,
+ n_instance_no, avr_vpd_info.n_avr_spi_version);
+
+ /* AVR_OP_VERSION */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VERSION, &tx_buf,
+ &rx_buf);
+
+ avr_vpd_info.n_avr_fw_ver_major = rx_data[0];
+ avr_vpd_info.n_avr_fw_ver_minor = rx_data[1];
+ avr_vpd_info.n_avr_fw_ver_micro = rx_data[2];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER: %c.%c.%c\n",
+ p_adapter_id_str, n_instance_no, avr_vpd_info.n_avr_fw_ver_major,
+ avr_vpd_info.n_avr_fw_ver_minor,
+ avr_vpd_info.n_avr_fw_ver_micro);
+
+ memcpy(avr_vpd_info.a_avr_fw_ver_str, &rx_data[0 + 3],
+ sizeof(avr_vpd_info.a_avr_fw_ver_str));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER_STR: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ (int)sizeof(avr_vpd_info.a_avr_fw_ver_str),
+ avr_vpd_info.a_avr_fw_ver_str);
+
+ memcpy(avr_vpd_info.a_avr_fw_plat_id_str, &rx_data[0 + 3 + 50],
+ sizeof(avr_vpd_info.a_avr_fw_plat_id_str));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: FW_HW_ID_STR: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ (int)sizeof(avr_vpd_info.a_avr_fw_plat_id_str),
+ avr_vpd_info.a_avr_fw_plat_id_str);
+
+ rte_strscpy(p_fpga_info->nthw_hw_info.hw_plat_id_str,
+ (char *)avr_vpd_info.a_avr_fw_plat_id_str,
+ sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str));
+ p_fpga_info->nthw_hw_info.hw_plat_id_str
+ [sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str) - 1] =
+ 0;
+
+ /* AVR_OP_SYSINFO_2 */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO_2, &tx_buf,
+ &rx_buf);
+ if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+ rx_buf.size >= 16) {
+ if (rx_buf.size != 16) {
+ NT_LOG(WRN, NTHW,
+ "%s: AVR%d: SYSINFO2: reply is larger than expected: %04X %04X\n",
+ p_adapter_id_str, n_instance_no, rx_buf.size,
+ 16);
+ } else {
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SYSINFO2: OK: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res,
+ rx_buf.size);
+ }
+
+ avr_vpd_info.sysinfo_container_version = rx_data[0];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_container_version);
+
+ memcpy(&avr_vpd_info.sysinfo_avr_libc_version,
+ &rx_data[0 + 1],
+ sizeof(avr_vpd_info.sysinfo_avr_libc_version));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_avr_libc_version);
+
+ avr_vpd_info.sysinfo_signature_0 = rx_data[5];
+ avr_vpd_info.sysinfo_signature_1 = rx_data[6];
+ avr_vpd_info.sysinfo_signature_2 = rx_data[7];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SIGNATURE: %02x%02x%02x\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_signature_0,
+ avr_vpd_info.sysinfo_signature_1,
+ avr_vpd_info.sysinfo_signature_2);
+
+ avr_vpd_info.sysinfo_spi_version = rx_data[8];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_spi_version);
+
+ avr_vpd_info.sysinfo_hw_revision = rx_data[9];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_hw_revision);
+
+ avr_vpd_info.sysinfo_ticks_per_second = rx_data[10];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_ticks_per_second);
+
+ memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11],
+ sizeof(avr_vpd_info.sysinfo_uptime));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_uptime);
+
+ avr_vpd_info.sysinfo_osccal = rx_data[15];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_osccal);
+
+ {
+ bool b_spi_ver_match _unused =
+ (avr_vpd_info.n_avr_spi_version ==
+ avr_vpd_info.sysinfo_spi_version);
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n",
+ p_adapter_id_str, n_instance_no,
+ (b_spi_ver_match ? "OK" : "MISMATCH"),
+ avr_vpd_info.n_avr_spi_version,
+ avr_vpd_info.sysinfo_spi_version);
+ }
+ /* SYSINFO2: if response: only populate hw_id not hw_id_emulated */
+ p_fpga_info->nthw_hw_info.hw_id =
+ avr_vpd_info.sysinfo_hw_revision;
+ } else {
+ /* AVR_OP_SYSINFO */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO,
+ &tx_buf, &rx_buf);
+ if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+ rx_buf.size >= 16) {
+ if (rx_buf.size != 16) {
+ NT_LOG(WRN, NTHW,
+ "%s: AVR%d: SYSINFO: reply is larger than expected: %04X %04X\n",
+ p_adapter_id_str, n_instance_no,
+ rx_buf.size, 16);
+ } else {
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SYSINFO: OK: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res,
+ rx_buf.size);
+ }
+
+ avr_vpd_info.sysinfo_container_version =
+ rx_data[0];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SYSINFO_REQ_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_container_version);
+
+ memcpy(&avr_vpd_info.sysinfo_avr_libc_version,
+ &rx_data[0 + 1],
+ sizeof(avr_vpd_info
+ .sysinfo_avr_libc_version));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_avr_libc_version);
+
+ avr_vpd_info.sysinfo_signature_0 = rx_data[5];
+ avr_vpd_info.sysinfo_signature_1 = rx_data[6];
+ avr_vpd_info.sysinfo_signature_2 = rx_data[7];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SIGNATURE: %02x%02x%02x\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_signature_0,
+ avr_vpd_info.sysinfo_signature_1,
+ avr_vpd_info.sysinfo_signature_2);
+
+ avr_vpd_info.sysinfo_spi_version = rx_data[8];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_spi_version);
+
+ avr_vpd_info.sysinfo_hw_revision = rx_data[9];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_hw_revision);
+ NT_LOG(INF, NTHW, "%s: AVR%d: HW_REV: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_hw_revision);
+
+ avr_vpd_info.sysinfo_ticks_per_second =
+ rx_data[10];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: TICKS_PER_SEC: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_ticks_per_second);
+
+ memcpy(&avr_vpd_info.sysinfo_uptime,
+ &rx_data[11],
+ sizeof(avr_vpd_info.sysinfo_uptime));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_uptime);
+
+ avr_vpd_info.sysinfo_osccal = rx_data[15];
+ NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.sysinfo_osccal);
+
+ {
+ bool b_spi_ver_match _unused =
+ (avr_vpd_info.n_avr_spi_version ==
+ avr_vpd_info
+ .sysinfo_spi_version);
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: SPI_VER_TST: %s (%d %d)\n",
+ p_adapter_id_str, n_instance_no,
+ (b_spi_ver_match ? "OK" :
+ "MISMATCH"),
+ avr_vpd_info.n_avr_spi_version,
+ avr_vpd_info.sysinfo_spi_version);
+ }
+
+ p_fpga_info->nthw_hw_info.hw_id =
+ avr_vpd_info.sysinfo_hw_revision;
+ p_fpga_info->nthw_hw_info.hw_id_emulated =
+ avr_vpd_info.sysinfo_hw_revision;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: AVR%d: SYSINFO: NA: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res,
+ rx_buf.size);
+ }
+ }
+
+ /* AVR_OP_VPD_READ */
+ tx_buf.size = 0;
+ tx_buf.p_buf = NULL;
+ rx_buf.size = sizeof(rx_data);
+ rx_buf.p_buf = &rx_data;
+ res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VPD_READ, &tx_buf,
+ &rx_buf);
+ if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+ rx_buf.size >= GEN2_VPD_SIZE_TOTAL) {
+ avr_vpd_info.n_crc16_calced =
+ crc16(rx_buf.p_buf, rx_buf.size - 2);
+ memcpy(&avr_vpd_info.n_crc16_stored,
+ &rx_data[rx_buf.size - 2],
+ sizeof(avr_vpd_info.n_crc16_stored));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: VPD_CRC: %04X %04X\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.n_crc16_stored,
+ avr_vpd_info.n_crc16_calced);
+
+ avr_vpd_info.b_crc16_valid = (avr_vpd_info.n_crc16_stored ==
+ avr_vpd_info.n_crc16_calced);
+ NT_LOG(DBG, NTHW, "%s: AVR%d: CRC_TST: %s\n",
+ p_adapter_id_str, n_instance_no,
+ (avr_vpd_info.b_crc16_valid ? "OK" : "ERROR"));
+
+ if (avr_vpd_info.b_crc16_valid) {
+ memcpy(&avr_vpd_info.psu_hw_version, &rx_data[0],
+ sizeof(avr_vpd_info.psu_hw_version));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: PSU_HW_VER: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.psu_hw_version);
+
+ memcpy(&avr_vpd_info.vpd_pn, &rx_data[0 + 1],
+ sizeof(avr_vpd_info.vpd_pn));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: PN: '%.*s'\n",
+ p_adapter_id_str, n_instance_no, GEN2_PN_SIZE,
+ avr_vpd_info.vpd_pn);
+
+ memcpy(&avr_vpd_info.vpd_pba,
+ &rx_data[0 + 1 + GEN2_PN_SIZE],
+ sizeof(avr_vpd_info.vpd_pba));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: PBA: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ GEN2_PBA_SIZE, avr_vpd_info.vpd_pba);
+
+ memcpy(&avr_vpd_info.vpd_sn,
+ &rx_data[0 + 1 + GEN2_PN_SIZE +
+ GEN2_PBA_SIZE],
+ sizeof(avr_vpd_info.vpd_sn));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: SN: '%.*s'\n",
+ p_adapter_id_str, n_instance_no, GEN2_SN_SIZE,
+ avr_vpd_info.vpd_sn);
+
+ memcpy(&avr_vpd_info.vpd_board_name,
+ &rx_data[0 + 1 + GEN2_PN_SIZE +
+ GEN2_PBA_SIZE + GEN2_SN_SIZE],
+ sizeof(avr_vpd_info.vpd_board_name));
+ NT_LOG(DBG, NTHW, "%s: AVR%d: BN: '%.*s'\n",
+ p_adapter_id_str, n_instance_no,
+ GEN2_BNAME_SIZE,
+ avr_vpd_info.vpd_board_name);
+
+ {
+ uint32_t u1;
+ union mac_u {
+ uint8_t a_u8[8];
+ uint16_t a_u16[4];
+ uint32_t a_u32[2];
+ uint64_t a_u64[1];
+ } mac;
+
+ /* vpd_platform_section */
+ uint8_t *p_vpd_board_info =
+ (uint8_t *)(&rx_data[1 +
+ GEN2_PN_SIZE +
+ GEN2_PBA_SIZE +
+ GEN2_SN_SIZE +
+ GEN2_BNAME_SIZE]);
+ memcpy(&avr_vpd_info.product_family,
+ &p_vpd_board_info[0],
+ sizeof(avr_vpd_info
+ .product_family));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: PROD_FAM: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.product_family);
+
+ memcpy(&avr_vpd_info.feature_mask,
+ &p_vpd_board_info[0 + 4],
+ sizeof(avr_vpd_info.feature_mask));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: FMSK_VAL: 0x%08X\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.feature_mask);
+
+ memcpy(&avr_vpd_info.invfeature_mask,
+ &p_vpd_board_info[0 + 4 + 4],
+ sizeof(avr_vpd_info
+ .invfeature_mask));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: FMSK_INV: 0x%08X\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.invfeature_mask);
+
+ avr_vpd_info.b_feature_mask_valid =
+ (avr_vpd_info.feature_mask ==
+ ~avr_vpd_info.invfeature_mask);
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: FMSK_TST: %s\n",
+ p_adapter_id_str, n_instance_no,
+ (avr_vpd_info.b_feature_mask_valid ?
+ "OK" :
+ "ERROR"));
+
+ memcpy(&avr_vpd_info.no_of_macs,
+ &p_vpd_board_info[0 + 4 + 4 + 4],
+ sizeof(avr_vpd_info.no_of_macs));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: NUM_MACS: %d\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.no_of_macs);
+
+ memcpy(&avr_vpd_info.mac_address,
+ &p_vpd_board_info[0 + 4 + 4 + 4 + 1],
+ sizeof(avr_vpd_info.mac_address));
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: MAC_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.mac_address[0],
+ avr_vpd_info.mac_address[1],
+ avr_vpd_info.mac_address[2],
+ avr_vpd_info.mac_address[3],
+ avr_vpd_info.mac_address[4],
+ avr_vpd_info.mac_address[5]);
+
+ mac.a_u64[0] = 0;
+ memcpy(&mac.a_u8[2],
+ &avr_vpd_info.mac_address,
+ sizeof(avr_vpd_info.mac_address));
+ u1 = ntohl(mac.a_u32[0]);
+ if (u1 != mac.a_u32[0]) {
+ const uint32_t u0 = ntohl(mac.a_u32[1]);
+ mac.a_u32[0] = u0;
+ mac.a_u32[1] = u1;
+ }
+ avr_vpd_info.n_mac_val = mac.a_u64[0];
+ NT_LOG(DBG, NTHW,
+ "%s: AVR%d: MAC_U64: %012" PRIX64
+ "\n",
+ p_adapter_id_str, n_instance_no,
+ avr_vpd_info.n_mac_val);
+ }
+ }
+ p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count =
+ avr_vpd_info.no_of_macs;
+ p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value =
+ avr_vpd_info.n_mac_val;
+ memcpy(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets,
+ avr_vpd_info.mac_address,
+ ARRAY_SIZE(p_fpga_info->nthw_hw_info.vpd_info
+ .ma_mac_addr_octets));
+ } else {
+ NT_LOG(ERR, NTHW, "%s:%u: res=%d\n", __func__, __LINE__,
+ res);
+ NT_LOG(ERR, NTHW,
+ "%s: AVR%d: SYSINFO2: NA: res=%d sz=%d\n",
+ p_adapter_id_str, n_instance_no, res, rx_buf.size);
+ }
+ }
+
+ return res;
+}
+
+/*
+ * NT50B01, NT200A02, NT200A01-HWbuild2
+ */
+int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga,
+ const uint8_t n_iic_addr,
+ const clk_profile_data_fmt2_t *p_clk_profile,
+ const int n_clk_profile_rec_cnt)
+{
+ int res;
+ nthw_iic_t *p_nthw_iic = nthw_iic_new();
+ nthw_si5340_t *p_nthw_si5340 = nthw_si5340_new();
+
+ assert(p_nthw_iic);
+ assert(p_nthw_si5340);
+ nthw_iic_init(p_nthw_iic, p_fpga, 0, 8); /* I2C cycle time 125Mhz ~ 8ns */
+
+ nthw_si5340_init(p_nthw_si5340, p_nthw_iic,
+ n_iic_addr); /* Si5340_U23_I2c_Addr_7bit */
+ res = nthw_si5340_config_fmt2(p_nthw_si5340, p_clk_profile,
+ n_clk_profile_rec_cnt);
+ nthw_si5340_delete(p_nthw_si5340);
+ p_nthw_si5340 = NULL;
+
+ return res;
+}
+
+int nthw_fpga_init(struct fpga_info_s *p_fpga_info)
+{
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+
+ nthw_hif_t *p_nthw_hif = NULL;
+ nthw_pcie3_t *p_nthw_pcie3 = NULL;
+ nthw_rac_t *p_nthw_rac = NULL;
+ nthw_tsm_t *p_nthw_tsm = NULL;
+
+ uint64_t n_fpga_ident = 0;
+ nt_fpga_mgr_t *p_fpga_mgr = NULL;
+ nt_fpga_t *p_fpga = NULL;
+
+ char s_fpga_prod_ver_rev_str[32] = { 0 };
+
+ int res = 0;
+
+ assert(p_fpga_info);
+
+ {
+ int n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id;
+ uint64_t n_fpga_ident;
+ uint32_t n_fpga_ident_low, n_fpga_ident_high, n_fpga_build_time;
+
+ nthw_rac_reg_read32(p_fpga_info, 0x0, &n_fpga_ident_low);
+ nthw_rac_reg_read32(p_fpga_info, 0x8, &n_fpga_ident_high);
+ nthw_rac_reg_read32(p_fpga_info, 0x10, &n_fpga_build_time);
+
+ n_fpga_ident = (((uint64_t)n_fpga_ident_high << 32) | n_fpga_ident_low);
+ n_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident);
+ n_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident);
+ n_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident);
+ n_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident);
+
+ p_fpga_info->n_fpga_ident = n_fpga_ident;
+ p_fpga_info->n_fpga_type_id = n_fpga_type_id;
+ p_fpga_info->n_fpga_prod_id = n_fpga_prod_id;
+ p_fpga_info->n_fpga_ver_id = n_fpga_ver_id;
+ p_fpga_info->n_fpga_rev_id = n_fpga_rev_id;
+ p_fpga_info->n_fpga_build_time = n_fpga_build_time;
+
+ snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str),
+ "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id,
+ n_fpga_ver_id, n_fpga_rev_id);
+
+ NT_LOG(INF, NTHW, "%s: FPGA %s (%" PRIX64 ") [%08X]\n",
+ p_adapter_id_str, s_fpga_prod_ver_rev_str, n_fpga_ident,
+ n_fpga_build_time);
+ }
+
+ n_fpga_ident = p_fpga_info->n_fpga_ident;
+
+ p_fpga_mgr = fpga_mgr_new();
+ fpga_mgr_init(p_fpga_mgr);
+ fpga_mgr_log_dump(p_fpga_mgr);
+ p_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info);
+ p_fpga_info->mp_fpga = p_fpga;
+ if (p_fpga == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: %s (%08X)\n",
+ p_adapter_id_str, s_fpga_prod_ver_rev_str,
+ p_fpga_info->n_fpga_build_time);
+ return -1;
+ }
+
+ if (p_fpga_mgr) {
+ fpga_mgr_delete(p_fpga_mgr);
+ p_fpga_mgr = NULL;
+ }
+
+ /* Read Fpga param info */
+ nthw_fpga_get_param_info(p_fpga_info, p_fpga);
+
+ /* debug: report params */
+ NT_LOG(DBG, NTHW, "%s: NT_NIMS=%d\n", p_adapter_id_str, p_fpga_info->n_nims);
+ NT_LOG(DBG, NTHW, "%s: NT_PHY_PORTS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_phy_ports);
+ NT_LOG(DBG, NTHW, "%s: NT_PHY_QUADS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_phy_quads);
+ NT_LOG(DBG, NTHW, "%s: NT_RX_PORTS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_rx_ports);
+ NT_LOG(DBG, NTHW, "%s: NT_TX_PORTS=%d\n", p_adapter_id_str,
+ p_fpga_info->n_tx_ports);
+ NT_LOG(DBG, NTHW, "%s: nProfile=%d\n", p_adapter_id_str,
+ (int)p_fpga_info->profile);
+
+ p_nthw_rac = nthw_rac_new();
+ if (p_nthw_rac == NULL) {
+ NT_LOG(ERR, NTHW,
+ "%s: Unsupported FPGA: RAC is not found: %s (%08X)\n",
+ p_adapter_id_str, s_fpga_prod_ver_rev_str,
+ p_fpga_info->n_fpga_build_time);
+ return -1;
+ }
+
+ nthw_rac_init(p_nthw_rac, p_fpga, p_fpga_info);
+ nthw_rac_rab_flush(p_nthw_rac);
+ p_fpga_info->mp_nthw_rac = p_nthw_rac;
+
+ /* special case: values below 0x100 will disable debug on RAC communication */
+ {
+ const int n_fpga_initial_debug_mode = p_fpga_info->n_fpga_debug_mode;
+
+ fpga_set_debug_mode(p_fpga, n_fpga_initial_debug_mode);
+ }
+
+ switch (p_fpga_info->n_nthw_adapter_id) {
+ case NT_HW_ADAPTER_ID_NT200A01: /* fallthrough */
+ case NT_HW_ADAPTER_ID_NT200A02:
+ res = nthw_fpga_nt200a0x_init(p_fpga_info);
+ break;
+ default:
+ NT_LOG(ERR, NTHW, "%s: Unsupported HW product id: %d\n",
+ p_adapter_id_str, p_fpga_info->n_nthw_adapter_id);
+ res = -1;
+ break;
+ }
+
+ if (res) {
+ NT_LOG(ERR, NTHW, "%s: status: 0x%08X\n", p_adapter_id_str, res);
+ return res;
+ }
+
+ res = nthw_pcie3_init(NULL, p_fpga, 0); /* Probe for module */
+ if (res == 0) {
+ p_nthw_pcie3 = nthw_pcie3_new();
+ if (p_nthw_pcie3) {
+ res = nthw_pcie3_init(p_nthw_pcie3, p_fpga, 0);
+ if (res == 0) {
+ NT_LOG(DBG, NTHW, "%s: Pcie3 module found\n",
+ p_adapter_id_str);
+ nthw_pcie3_trigger_sample_time(p_nthw_pcie3);
+ } else {
+ nthw_pcie3_delete(p_nthw_pcie3);
+ p_nthw_pcie3 = NULL;
+ }
+ }
+ p_fpga_info->mp_nthw_pcie3 = p_nthw_pcie3;
+ }
+
+ if (p_nthw_pcie3 == NULL) {
+ p_nthw_hif = nthw_hif_new();
+ if (p_nthw_hif) {
+ res = nthw_hif_init(p_nthw_hif, p_fpga, 0);
+ if (res == 0) {
+ NT_LOG(DBG, NTHW, "%s: Hif module found\n",
+ p_adapter_id_str);
+ nthw_hif_trigger_sample_time(p_nthw_hif);
+ } else {
+ nthw_hif_delete(p_nthw_hif);
+ p_nthw_hif = NULL;
+ }
+ }
+ }
+ p_fpga_info->mp_nthw_hif = p_nthw_hif;
+
+ p_nthw_tsm = nthw_tsm_new();
+ if (p_nthw_tsm) {
+ nthw_tsm_init(p_nthw_tsm, p_fpga, 0);
+
+ nthw_tsm_set_config_ts_format(p_nthw_tsm,
+ 1); /* 1 = TSM: TS format native */
+
+ /* Timer T0 - stat toggle timer */
+ nthw_tsm_set_timer_t0_enable(p_nthw_tsm, false);
+ nthw_tsm_set_timer_t0_max_count(p_nthw_tsm, 50 * 1000 * 1000); /* ns */
+ nthw_tsm_set_timer_t0_enable(p_nthw_tsm, true);
+
+ /* Timer T1 - keep alive timer */
+ nthw_tsm_set_timer_t1_enable(p_nthw_tsm, false);
+ nthw_tsm_set_timer_t1_max_count(p_nthw_tsm,
+ 100 * 1000 * 1000); /* ns */
+ nthw_tsm_set_timer_t1_enable(p_nthw_tsm, true);
+ }
+ p_fpga_info->mp_nthw_tsm = p_nthw_tsm;
+
+ /* TSM sample triggering: test validation... */
+#if defined(DEBUG) && (1)
+ {
+ uint64_t n_time, n_ts;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (p_nthw_hif)
+ nthw_hif_trigger_sample_time(p_nthw_hif);
+
+ else if (p_nthw_pcie3)
+ nthw_pcie3_trigger_sample_time(p_nthw_pcie3);
+ nthw_tsm_get_time(p_nthw_tsm, &n_time);
+ nthw_tsm_get_ts(p_nthw_tsm, &n_ts);
+
+ NT_LOG(DBG, NTHW,
+ "%s: TSM time: %016" PRIX64 " %016" PRIX64 "\n",
+ p_adapter_id_str, n_time, n_ts);
+
+ NT_OS_WAIT_USEC(1000);
+ }
+ }
+#endif
+
+ return res;
+}
+
+int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info)
+{
+ int res = -1;
+
+ if (p_fpga_info) {
+ if (p_fpga_info && p_fpga_info->mp_nthw_rac)
+ res = nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.h b/drivers/net/ntnic/nthw/core/nthw_fpga.h
new file mode 100644
index 0000000000..336d81f337
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_H__
+#define __NTHW_FPGA_H__
+
+#include "nthw_drv.h"
+
+#include "nthw_fpga_model.h"
+
+#include "nthw_rac.h"
+#include "nthw_iic.h"
+
+#include "nthw_stat.h"
+
+#include "nthw_fpga_rst.h"
+
+#include "nthw_fpga_nt200a0x.h"
+
+#include "nthw_dbs.h"
+
+int nthw_fpga_init(struct fpga_info_s *p_fpga_info);
+int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info);
+
+int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga);
+
+int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no);
+
+int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin,
+ const int n_instance_no_end);
+
+int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr);
+int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no,
+ const uint8_t n_dev_addr, const uint8_t n_reg_addr,
+ uint8_t val);
+
+int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no,
+ const int n_dev_addr, const int n_page_reg_addr);
+
+int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga,
+ const uint8_t n_iic_addr,
+ const clk_profile_data_fmt2_t *p_clk_profile,
+ const int n_clk_profile_rec_cnt);
+
+#endif /* __NTHW_FPGA_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c
new file mode 100644
index 0000000000..70338fdfd7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_fpga.h"
+#include "nthw_fpga_nt200a0x.h"
+
+int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info)
+{
+ assert(p_fpga_info);
+
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ struct nthw_fpga_rst_nt200a0x rst;
+ int res = -1;
+
+ /* reset common */
+ res = nthw_fpga_rst_nt200a0x_init(p_fpga_info, &rst);
+ if (res) {
+ NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n",
+ p_adapter_id_str, __func__, __LINE__,
+ p_fpga_info->n_fpga_prod_id, res);
+ return res;
+ }
+
+ /* reset specific */
+ switch (p_fpga_info->n_fpga_prod_id) {
+ case 9563:
+ res = nthw_fpga_rst9563_init(p_fpga_info, &rst);
+ break;
+ default:
+ NT_LOG(ERR, NTHW, "%s: Unsupported FPGA product: %04d\n",
+ p_adapter_id_str, p_fpga_info->n_fpga_prod_id);
+ res = -1;
+ break;
+ }
+ if (res) {
+ NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d\n",
+ p_adapter_id_str, __func__, __LINE__,
+ p_fpga_info->n_fpga_prod_id, res);
+ return res;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h
new file mode 100644
index 0000000000..ff324bee39
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_NT200A0X_H__
+#define __NTHW_FPGA_NT200A0X_H__
+
+int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info);
+
+/* NT200A02: 9563 */
+int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *const p);
+
+#endif /* __NTHW_FPGA_NT200A0X_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c
new file mode 100644
index 0000000000..66c148bab2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_fpga.h"
+#include "nthw_fpga_nt200a0x.h"
+
+#include "nthw_fpga_rst.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h
new file mode 100644
index 0000000000..2099c4b677
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_RST_H__
+#define __NTHW_FPGA_RST_H__
+
+#include "nthw_drv.h"
+
+#include "nthw_fpga_model.h"
+
+#include "nthw_rac.h"
+#include "nthw_iic.h"
+
+#include "nthw_fpga_rst_nt200a0x.h"
+
+#endif /* __NTHW_FPGA_RST_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c
new file mode 100644
index 0000000000..077b043c60
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+#include "nthw_clock_profiles.h"
+
+static int nthw_fpga_rst9563_setup(nt_fpga_t *p_fpga,
+ struct nthw_fpga_rst_nt200a0x *const p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const int n_fpga_product_id = p_fpga->m_product_id;
+ const int n_fpga_version = p_fpga->m_fpga_version;
+ const int n_fpga_revision = p_fpga->m_fpga_revision;
+
+ nt_module_t *p_mod_rst;
+ nt_register_t *p_curr_reg;
+
+ assert(p);
+ p->mn_fpga_product_id = n_fpga_product_id;
+ p->mn_fpga_version = n_fpga_version;
+ p->mn_fpga_revision = n_fpga_revision;
+
+ NT_LOG(DBG, NTHW, "%s: %s: FPGA reset setup: FPGA %04d-%02d-%02d\n",
+ p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version,
+ n_fpga_revision);
+
+ p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);
+ if (p_mod_rst == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n",
+ p_adapter_id_str, 0);
+ return -1;
+ }
+
+ p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);
+ if (p_mod_rst == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n",
+ p_adapter_id_str, 0);
+ return -1;
+ }
+
+ /* RST register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_RST);
+ p->mp_fld_rst_sys = register_get_field(p_curr_reg, RST9563_RST_SYS);
+ p->mp_fld_rst_sys_mmcm = register_get_field(p_curr_reg, RST9563_RST_SYS_MMCM);
+ p->mp_fld_rst_core_mmcm =
+ register_get_field(p_curr_reg, RST9563_RST_CORE_MMCM);
+ p->mp_fld_rst_rpp = register_get_field(p_curr_reg, RST9563_RST_RPP);
+ p->mp_fld_rst_ddr4 = register_get_field(p_curr_reg, RST9563_RST_DDR4);
+ p->mp_fld_rst_sdc = register_get_field(p_curr_reg, RST9563_RST_SDC);
+ p->mp_fld_rst_phy = register_get_field(p_curr_reg, RST9563_RST_PHY);
+ p->mp_fld_rst_serdes_rx = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_serdes_tx = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_serdes_rx_datapath = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_pcs_rx = NULL; /* Field not present on 9563 */
+ p->mp_fld_rst_mac_rx = register_get_field(p_curr_reg, RST9563_RST_MAC_RX);
+ p->mp_fld_rst_mac_tx = NULL;
+ p->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP);
+ p->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP);
+ p->mp_fld_rst_ts = register_get_field(p_curr_reg, RST9563_RST_TS);
+ p->mp_fld_rst_ptp_mmcm = register_get_field(p_curr_reg, RST9563_RST_PTP_MMCM);
+ p->mp_fld_rst_ts_mmcm = register_get_field(p_curr_reg, RST9563_RST_TS_MMCM);
+ /* referenced in separate function */
+ p->mp_fld_rst_periph = register_get_field(p_curr_reg, RST9563_RST_PERIPH);
+ p->mp_fld_rst_tsm_ref_mmcm =
+ register_query_field(p_curr_reg, RST9563_RST_TSM_REF_MMCM);
+ p->mp_fld_rst_tmc = register_query_field(p_curr_reg, RST9563_RST_TMC);
+
+ if (!p->mp_fld_rst_tsm_ref_mmcm) {
+ NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TSM_REF_MMCM found\n",
+ p_adapter_id_str);
+ }
+ if (!p->mp_fld_rst_tmc) {
+ NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TMC found\n",
+ p_adapter_id_str);
+ }
+ register_update(p_curr_reg);
+
+ /* CTRL register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_CTRL);
+ p->mp_fld_ctrl_ts_clk_sel_override =
+ register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL_OVERRIDE);
+ /* Field not present on 9563 */
+ p->mp_fld_ctrl_ts_clk_sel =
+ register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL);
+ p->mp_fld_ctrl_ts_clk_sel_ref = NULL; /* Field not present on 9563 */
+ p->mp_fld_ctrl_ptp_mmcm_clk_sel =
+ register_get_field(p_curr_reg, RST9563_CTRL_PTP_MMCM_CLKSEL);
+ register_update(p_curr_reg);
+
+ /* STAT register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_STAT);
+ p->mp_fld_stat_ddr4_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_DDR4_MMCM_LOCKED);
+ p->mp_fld_stat_sys_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_SYS_MMCM_LOCKED);
+ p->mp_fld_stat_core_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_CORE_MMCM_LOCKED);
+ p->mp_fld_stat_ddr4_pll_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_DDR4_PLL_LOCKED);
+ p->mp_fld_stat_ptp_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_PTP_MMCM_LOCKED);
+ p->mp_fld_stat_ts_mmcm_locked =
+ register_get_field(p_curr_reg, RST9563_STAT_TS_MMCM_LOCKED);
+ p->mp_fld_stat_tsm_ref_mmcm_locked = NULL; /* Field not present on 9563 */
+
+ if (!p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ NT_LOG(DBG, NTHW,
+ "%s: No RST9563_STAT_TSM_REF_MMCM_LOCKED found\n",
+ p_adapter_id_str);
+ }
+ register_update(p_curr_reg);
+
+ /* STICKY register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_STICKY);
+ p->mp_fld_sticky_ptp_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_PTP_MMCM_UNLOCKED);
+ p->mp_fld_sticky_ts_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_TS_MMCM_UNLOCKED);
+ p->mp_fld_sticky_ddr4_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_DDR4_MMCM_UNLOCKED);
+ p->mp_fld_sticky_ddr4_pll_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_DDR4_PLL_UNLOCKED);
+ p->mp_fld_sticky_core_mmcm_unlocked =
+ register_get_field(p_curr_reg, RST9563_STICKY_CORE_MMCM_UNLOCKED);
+ p->mp_fld_sticky_pci_sys_mmcm_unlocked = NULL; /* Field not present on 9563 */
+ p->mp_fld_sticky_tsm_ref_mmcm_unlocked = NULL; /* Field not present on 9563 */
+
+ if (!p->mp_fld_sticky_tsm_ref_mmcm_unlocked) {
+ NT_LOG(DBG, NTHW,
+ "%s: No RST9563_STICKY_TSM_REF_MMCM_UNLOCKED found\n",
+ p_adapter_id_str);
+ }
+ register_update(p_curr_reg);
+
+ /* POWER register field pointers */
+ p_curr_reg = module_get_register(p_mod_rst, RST9563_POWER);
+ p->mp_fld_power_pu_phy = register_get_field(p_curr_reg, RST9563_POWER_PU_PHY);
+ p->mp_fld_power_pu_nseb =
+ register_get_field(p_curr_reg, RST9563_POWER_PU_NSEB);
+ register_update(p_curr_reg);
+
+ return 0;
+}
+
+static int nthw_fpga_rst9563_periph_reset(nt_fpga_t *p_fpga)
+{
+ const char *const _unused p_adapter_id_str =
+ p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);
+
+ if (p_mod_rst) {
+ nt_register_t *p_reg_rst;
+ nt_field_t *p_fld_rst_periph;
+
+ NT_LOG(DBG, NTHW, "%s: PERIPH RST\n", p_adapter_id_str);
+ p_reg_rst = module_get_register(p_mod_rst, RST9563_RST);
+ p_fld_rst_periph = register_get_field(p_reg_rst, RST9563_RST_PERIPH);
+ field_set_flush(p_fld_rst_periph);
+ field_clr_flush(p_fld_rst_periph);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+nthw_fpga_rst9563_clock_synth_init(nt_fpga_t *p_fpga,
+ const int n_si_labs_clock_synth_model,
+ const uint8_t n_si_labs_clock_synth_i2c_addr)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const int n_fpga_product_id = p_fpga->m_product_id;
+ int res;
+
+ if (n_si_labs_clock_synth_model == 5340) {
+ res = nthw_fpga_si5340_clock_synth_init_fmt2(p_fpga,
+ n_si_labs_clock_synth_i2c_addr,
+ p_data_si5340_nt200a02_u23_v5,
+ n_data_si5340_nt200a02_u23_v5);
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: Fpga %d: Unsupported clock synth model (%d)\n",
+ p_adapter_id_str, n_fpga_product_id, n_si_labs_clock_synth_model);
+ res = -1;
+ }
+ return res;
+}
+
+int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *p_rst)
+{
+ assert(p_fpga_info);
+ assert(p_rst);
+
+ const char *const _unused p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = -1;
+ int n_si_labs_clock_synth_model;
+ uint8_t n_si_labs_clock_synth_i2c_addr;
+ nt_fpga_t *p_fpga = NULL;
+
+ p_fpga = p_fpga_info->mp_fpga;
+ n_si_labs_clock_synth_model = p_rst->mn_si_labs_clock_synth_model;
+ n_si_labs_clock_synth_i2c_addr = p_rst->mn_si_labs_clock_synth_i2c_addr;
+
+ res = nthw_fpga_rst9563_periph_reset(p_fpga);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ res = nthw_fpga_rst9563_clock_synth_init(p_fpga, n_si_labs_clock_synth_model,
+ n_si_labs_clock_synth_i2c_addr);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ res = nthw_fpga_rst9563_setup(p_fpga, p_rst);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ res = nthw_fpga_rst_nt200a0x_reset(p_fpga, p_rst);
+ if (res) {
+ NT_LOG(DBG, NTHW, "%s: ERROR: res=%d [%s:%u]\n", p_adapter_id_str,
+ res, __func__, __LINE__);
+ return res;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c
new file mode 100644
index 0000000000..ae63fefb09
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c
@@ -0,0 +1,674 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+static const uint8_t si5338_u23_i2c_addr_7bit = 0x70;
+static const uint8_t si5340_u23_i2c_addr_7bit = 0x74;
+
+/*
+ * Wait until DDR4 PLL LOCKED
+ */
+static int nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint32_t locked;
+ uint32_t retrycount = 5;
+ uint32_t timeout = 50000; /* initial timeout must be set to 5 sec. */
+ /* 14: wait until DDR4 PLL LOCKED */
+ NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock\n", p_adapter_id_str);
+ /*
+ * The following retry count gives a total timeout of 1 * 5 + 5 * 8 = 45sec
+ * It has been observed that at least 21sec can be necessary
+ */
+ while (true) {
+ int locked = field_wait_set_any32(p->mp_fld_stat_ddr4_pll_locked,
+ timeout, 100);
+ if (locked == 0)
+ break;
+ NT_LOG(DBG, NTHW,
+ "%s: Waiting for DDR4 PLL to lock - timeout\n",
+ p_adapter_id_str);
+ if (retrycount <= 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for DDR4 PLL to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ break;
+ }
+ field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */
+ field_clr_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */
+ retrycount--;
+ timeout =
+ 80000; /* Increase timeout for second attempt to 8 sec. */
+ }
+
+ NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ddr4_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for DDR4 MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ return -1;
+ }
+
+ if ((true) && p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1,
+ -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ return -1;
+ }
+ }
+
+ /* 10: Clear all MMCM/PLL lock sticky bits before testing them */
+ NT_LOG(DBG, NTHW, "%s: Clear sticky MMCM unlock bits\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ /* Clear all sticky bits */
+ field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);
+ field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);
+
+ /* 11: Ensure sticky bits are not unlocked except PTP MMCM and TS MMCM */
+ if (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_pll_unlocked() returned true\n",
+ p_adapter_id_str);
+ }
+
+ return 0;
+}
+
+/*
+ * Wait for SDRAM controller has been calibrated - On some adapters we have seen
+ * calibration time of 2.3 seconds
+ */
+static int
+nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nthw_sdc_t *p_nthw_sdc = NULL;
+ const int n_retry_cnt_max = 5;
+ int n_retry_cnt;
+ int res;
+
+ res = nthw_sdc_init(NULL, p_fpga, 0); /* probe for module */
+ if (res == 0) {
+ p_nthw_sdc = nthw_sdc_new();
+ if (p_nthw_sdc) {
+ res = nthw_sdc_init(p_nthw_sdc, p_fpga, 0);
+ if (res) {
+ NT_LOG(ERR, NTHW,
+ "%s: SDC init failed: res=%d [%s:%d]\n",
+ p_adapter_id_str, res, __func__, __LINE__);
+ nthw_sdc_delete(p_nthw_sdc);
+ p_nthw_sdc = NULL;
+ return -1;
+ }
+ } else {
+ nthw_sdc_delete(p_nthw_sdc);
+ p_nthw_sdc = NULL;
+ }
+ } else {
+ NT_LOG(DBG, NTHW, "%s: No SDC found\n", p_adapter_id_str);
+ }
+ n_retry_cnt = 0;
+ res = -1;
+ while ((res != 0) && (n_retry_cnt <= n_retry_cnt_max)) {
+ /* wait until DDR4 PLL LOCKED */
+ res = nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(p_fpga, p);
+ if (res == 0) {
+ if (p_nthw_sdc) {
+ /*
+ * Wait for SDRAM controller has been calibrated
+ * On some adapters we have seen calibration time of 2.3 seconds
+ */
+ NT_LOG(DBG, NTHW,
+ "%s: Waiting for SDRAM to calibrate\n",
+ p_adapter_id_str);
+ res = nthw_sdc_wait_states(p_nthw_sdc, 10000, 1000);
+ {
+ uint64_t n_result_mask;
+
+ int n_state_code _unused =
+ nthw_sdc_get_states(p_nthw_sdc,
+ &n_result_mask);
+ NT_LOG(DBG, NTHW,
+ "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n",
+ p_adapter_id_str, n_result_mask,
+ n_state_code, n_retry_cnt, res);
+ }
+ if (res == 0)
+ break;
+ }
+
+ if (n_retry_cnt >= n_retry_cnt_max) {
+ uint64_t n_result_mask;
+ int n_state_code _unused = nthw_sdc_get_states(p_nthw_sdc,
+ &n_result_mask);
+
+ NT_LOG(DBG, NTHW,
+ "%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n",
+ p_adapter_id_str, n_result_mask, n_state_code,
+ n_retry_cnt, res);
+ if (res != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Timeout waiting for SDRAM controller calibration\n",
+ p_adapter_id_str);
+ }
+ }
+ }
+
+ /*
+ * SDRAM controller is not calibrated with DDR4 ram blocks:
+ * reset DDR and perform calibration retry
+ */
+ field_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */
+ NT_OS_WAIT_USEC(100);
+ field_clr_flush(p->mp_fld_rst_ddr4);
+
+ n_retry_cnt++;
+ }
+ nthw_sdc_delete(p_nthw_sdc);
+
+ return res;
+}
+
+int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const fpga_info_t *const p_fpga_info = p_fpga->p_fpga_info;
+
+ const int n_fpga_product_id = p->mn_fpga_product_id;
+ const int n_fpga_version = p->mn_fpga_version;
+ const int n_fpga_revision = p->mn_fpga_revision;
+ const int n_nthw_adapter_id = p_fpga_info->n_nthw_adapter_id;
+ const bool b_is_nt200a01 = (n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01);
+ const int n_hw_id = p_fpga_info->nthw_hw_info.hw_id;
+ const uint8_t index = 0;
+ int locked;
+ int res = -1;
+
+ NT_LOG(DBG, NTHW,
+ "%s: %s: FPGA reset sequence: FPGA %04d-%02d-%02d @ HWId%d\n",
+ p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version,
+ n_fpga_revision, n_hw_id);
+ assert(n_fpga_product_id == p_fpga->m_product_id);
+
+ /*
+ * Reset all domains / modules except peripherals
+ * Set default reset values to ensure that all modules are reset correctly
+ * no matter if nic has been powercycled or ntservice has been reloaded
+ */
+
+ /*
+ * Reset to defaults
+ * 1: Reset all domains
+ */
+ NT_LOG(DBG, NTHW, "%s: RST defaults\n", p_adapter_id_str);
+
+ field_update_register(p->mp_fld_rst_sys);
+ field_set_flush(p->mp_fld_rst_sys);
+ if (p->mp_fld_rst_tmc)
+ field_set_flush(p->mp_fld_rst_tmc);
+ field_set_flush(p->mp_fld_rst_rpp);
+ field_set_flush(p->mp_fld_rst_ddr4); /* 0x07 3 banks */
+ field_set_flush(p->mp_fld_rst_sdc);
+
+ /* Reset port 0 and 1 in the following registers: */
+ field_set_flush(p->mp_fld_rst_phy); /* 0x03 2 ports */
+ if (p->mp_fld_rst_mac_rx)
+ field_set_flush(p->mp_fld_rst_mac_rx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_mac_tx)
+ field_set_flush(p->mp_fld_rst_mac_tx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_pcs_rx)
+ field_set_flush(p->mp_fld_rst_pcs_rx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_serdes_rx)
+ field_set_flush(p->mp_fld_rst_serdes_rx); /* 0x03 2 ports */
+
+ if (p->mp_fld_rst_serdes_rx_datapath) {
+ field_set_flush(p->mp_fld_rst_serdes_rx_datapath);
+ field_clr_flush(p->mp_fld_rst_serdes_rx);
+ }
+ if (p->mp_fld_rst_serdes_tx)
+ field_set_flush(p->mp_fld_rst_serdes_tx);
+
+ field_set_flush(p->mp_fld_rst_ptp);
+ field_set_flush(p->mp_fld_rst_ts);
+ field_set_flush(p->mp_fld_rst_sys_mmcm);
+ field_set_flush(p->mp_fld_rst_core_mmcm);
+ field_set_flush(p->mp_fld_rst_ptp_mmcm);
+ field_set_flush(p->mp_fld_rst_ts_mmcm);
+
+ if ((true) && p->mp_fld_rst_tsm_ref_mmcm)
+ field_set_flush(p->mp_fld_rst_tsm_ref_mmcm);
+
+ /* Write all changes to register */
+ field_flush_register(p->mp_fld_rst_sys);
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ if (p->mp_fld_rst_tsm_ref_mmcm) {
+ field_update_register(p->mp_fld_rst_tsm_ref_mmcm);
+ field_set_flush(p->mp_fld_rst_tsm_ref_mmcm);
+ }
+ }
+
+ /*
+ * 2: Force use of 50 MHz reference clock for timesync;
+ * NOTE: From 9508-05-18 this is a 20 MHz clock
+ */
+ NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL OVERRIDE\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_ctrl_ts_clk_sel_override);
+ field_set_flush(p->mp_fld_ctrl_ts_clk_sel_override);
+
+ NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_ctrl_ts_clk_sel);
+ field_set_flush(p->mp_fld_ctrl_ts_clk_sel);
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ NT_LOG(DBG, NTHW, "%s: _selecting 20MHz TS CLK SEL REF\n",
+ p_adapter_id_str);
+ if (p->mp_fld_ctrl_ts_clk_sel_ref) {
+ field_update_register(p->mp_fld_ctrl_ts_clk_sel_ref);
+ field_clr_flush(p->mp_fld_ctrl_ts_clk_sel_ref);
+ }
+ }
+
+ /* 4: De-assert sys reset, CORE and SYS MMCM resets */
+ NT_LOG(DBG, NTHW, "%s: De-asserting SYS, CORE and SYS MMCM resets\n",
+ p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_sys);
+ field_clr_flush(p->mp_fld_rst_sys);
+ field_clr_flush(p->mp_fld_rst_sys_mmcm);
+ field_clr_flush(p->mp_fld_rst_core_mmcm);
+
+ /* 5: wait until CORE MMCM and SYS MMCM are LOCKED */
+ NT_LOG(DBG, NTHW, "%s: Waiting for SYS MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_sys_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for SYS MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+
+ NT_LOG(DBG, NTHW, "%s: Waiting for CORE MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_core_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for CORE MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+
+ /* RAC RAB bus "flip/flip" reset second stage - new impl (ref RMT#37020) */
+ /* RAC/RAB init - SYS/CORE MMCM is locked - pull the remaining RAB buses out of reset */
+ {
+ nthw_rac_t *p_nthw_rac = p_fpga_info->mp_nthw_rac;
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting remaining RAB buses\n",
+ p_adapter_id_str);
+ nthw_rac_rab_init(p_nthw_rac, 0);
+ }
+
+ if ((true) && p->mp_fld_rst_tsm_ref_mmcm) {
+ NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n",
+ p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);
+ if (p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ NT_LOG(DBG, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked,
+ -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+ }
+
+ /*
+ * 5.2: Having ensured CORE MMCM and SYS MMCM are LOCKED,
+ * we need to select the alternative 20 MHz reference clock,
+ * the external TSM reference clock
+ * on NT200A01 - build 2 HW only (see SSF00024 p.32)
+ */
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL REF\n",
+ p_adapter_id_str);
+ if (p->mp_fld_ctrl_ts_clk_sel_ref)
+ field_set_flush(p->mp_fld_ctrl_ts_clk_sel_ref);
+ if (p->mp_fld_rst_tsm_ref_mmcm) {
+ NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n",
+ p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);
+ }
+ NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n",
+ p_adapter_id_str);
+ if (p->mp_fld_stat_tsm_ref_mmcm_locked) {
+ locked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked,
+ -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+ }
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting all PHY resets\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_phy);
+ field_clr_flush(p->mp_fld_rst_phy);
+
+ /* MAC_PCS_XXV 10G/25G: 9530 / 9544 */
+ if (n_fpga_product_id == 9530 || n_fpga_product_id == 9544) {
+ {
+ /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */
+ nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv0 = nthw_mac_pcs_xxv_new();
+
+ assert(p_nthw_mac_pcs_xxv0);
+ nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv0, p_fpga, 0, 1);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, true,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, false,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv0);
+ }
+
+ {
+ /* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */
+ nthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv1 = nthw_mac_pcs_xxv_new();
+
+ assert(p_nthw_mac_pcs_xxv1);
+ nthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv1, p_fpga, 1, 1);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, true,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, false,
+ index);
+ NT_OS_WAIT_USEC(1000);
+
+ nthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv1);
+ }
+ NT_OS_WAIT_USEC(3000);
+ }
+
+ /*
+ * 8: De-assert reset for remaining domains/modules resets except
+ * TS, PTP, PTP_MMCM and TS_MMCM
+ */
+ NT_LOG(DBG, NTHW, "%s: De-asserting TMC RST\n", p_adapter_id_str);
+ if (p->mp_fld_rst_tmc) {
+ field_update_register(p->mp_fld_rst_tmc);
+ field_clr_flush(p->mp_fld_rst_tmc);
+ }
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting RPP RST\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_rpp);
+ field_clr_flush(p->mp_fld_rst_rpp);
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting DDR4 RST\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_ddr4);
+ field_clr_flush(p->mp_fld_rst_ddr4);
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting SDC RST\n", p_adapter_id_str);
+ field_update_register(p->mp_fld_rst_sdc);
+ field_clr_flush(p->mp_fld_rst_sdc);
+
+ /* NOTE: 9522 implements PHY10G_QPLL reset and lock at this stage in mac_rx_rst() */
+ NT_LOG(DBG, NTHW, "%s: De-asserting MAC RX RST\n", p_adapter_id_str);
+ if (p->mp_fld_rst_mac_rx) {
+ field_update_register(p->mp_fld_rst_mac_rx);
+ field_clr_flush(p->mp_fld_rst_mac_rx);
+ }
+
+ /* await until DDR4 PLL LOCKED and SDRAM controller has been calibrated */
+ res = nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(p_fpga, p);
+ if (res) {
+ NT_LOG(ERR, NTHW,
+ "%s: nthw_fpga_rst_nt200a0x_wait_sdc_calibrated() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_core_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_tsm_ref_mmcm_unlocked returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+ }
+
+ /*
+ * Timesync/PTP reset sequence
+ * De-assert TS_MMCM reset
+ */
+ NT_LOG(DBG, NTHW, "%s: De-asserting TS MMCM RST\n", p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ts_mmcm);
+
+ /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */
+ NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to lock\n", p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TS MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+
+ NT_LOG(DBG, NTHW, "%s: Calling clear_sticky_mmcm_unlock_bits()\n",
+ p_adapter_id_str);
+ field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ /* Clear all sticky bits */
+ field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);
+ field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);
+ field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked)
+ field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);
+
+ /* De-assert TS reset bit */
+ NT_LOG(DBG, NTHW, "%s: De-asserting TS RST\n", p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ts);
+
+ if (field_get_updated(p->mp_fld_sticky_ts_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ts_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_ddr4_pll_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_core_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ if (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */
+ if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked &&
+ field_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) {
+ NT_LOG(ERR, NTHW,
+ "%s: get_sticky_tsm_ref_mmcm_unlocked() returned true\n",
+ p_adapter_id_str);
+ return -1;
+ }
+ }
+
+ if (false) {
+ /* Deassert PTP_MMCM */
+ NT_LOG(DBG, NTHW, "%s: De-asserting PTP MMCM RST\n",
+ p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ptp_mmcm);
+
+ if ((b_is_nt200a01 && n_fpga_version >= 9) || !b_is_nt200a01) {
+ /* Wait until PTP_MMCM LOCKED */
+ NT_LOG(DBG, NTHW, "%s: Waiting for PTP MMCM to lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ptp_mmcm_locked,
+ -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for PTP MMCM to lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+
+ /* Switch PTP MMCM sel to use ptp clk */
+ NT_LOG(DBG, NTHW, "%s: Setting PTP MMCM CLK SEL\n",
+ p_adapter_id_str);
+ field_set_flush(p->mp_fld_ctrl_ptp_mmcm_clk_sel);
+
+ /* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */
+ NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to re-lock\n",
+ p_adapter_id_str);
+ locked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);
+ if (locked != 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: Waiting for TS MMCM to re-lock failed (%d)\n",
+ p_adapter_id_str, locked);
+ }
+ }
+
+ NT_LOG(DBG, NTHW, "%s: De-asserting PTP RST\n", p_adapter_id_str);
+ field_clr_flush(p->mp_fld_rst_ptp);
+
+ /* POWER staging introduced in 9508-05-09 and always for 9512 */
+ if (n_fpga_product_id == 9508 && n_fpga_version <= 5 &&
+ n_fpga_revision <= 8) {
+ NT_LOG(DBG, NTHW, "%s: No power staging\n", p_adapter_id_str);
+ } else {
+ NT_LOG(DBG, NTHW, "%s: Staging power\n", p_adapter_id_str);
+ field_set_flush(p->mp_fld_power_pu_phy); /* PHY power up */
+ field_clr_flush(p->mp_fld_power_pu_nseb); /* NSEB power down */
+ }
+
+ NT_LOG(DBG, NTHW, "%s: %s: END\n", p_adapter_id_str, __func__);
+
+ return 0;
+}
+
+int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *p_rst)
+{
+ assert(p_fpga_info);
+
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = -1;
+ int n_si_labs_clock_synth_model = -1;
+ uint8_t n_si_labs_clock_synth_i2c_addr = 0;
+ nt_fpga_t *p_fpga = NULL;
+
+ p_fpga = p_fpga_info->mp_fpga;
+
+ NT_LOG(DBG, NTHW, "%s: %s: RAB init/reset\n", p_adapter_id_str, __func__);
+ nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);
+ nthw_rac_rab_setup(p_fpga_info->mp_nthw_rac);
+
+ res = nthw_fpga_avr_probe(p_fpga, 0);
+
+ res = nthw_fpga_iic_scan(p_fpga, 0, 0);
+ res = nthw_fpga_iic_scan(p_fpga, 2, 3);
+
+ /*
+ * Detect clock synth model
+ * check for NT200A02/NT200A01 HW-build2 - most commonly seen
+ */
+ n_si_labs_clock_synth_i2c_addr = si5340_u23_i2c_addr_7bit;
+ n_si_labs_clock_synth_model =
+ nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 1);
+ if (n_si_labs_clock_synth_model == -1) {
+ /* check for old NT200A01 HW-build1 */
+ n_si_labs_clock_synth_i2c_addr = si5338_u23_i2c_addr_7bit;
+ n_si_labs_clock_synth_model =
+ nthw_fpga_silabs_detect(p_fpga, 0,
+ n_si_labs_clock_synth_i2c_addr, 255);
+ if (n_si_labs_clock_synth_model == -1) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed to detect clock synth model (%d)\n",
+ p_adapter_id_str, n_si_labs_clock_synth_model);
+ return -1;
+ }
+ }
+ p_rst->mn_si_labs_clock_synth_model = n_si_labs_clock_synth_model;
+ p_rst->mn_si_labs_clock_synth_i2c_addr = n_si_labs_clock_synth_i2c_addr;
+ p_rst->mn_hw_id = p_fpga_info->nthw_hw_info.hw_id;
+ NT_LOG(DBG, NTHW, "%s: %s: Si%04d @ 0x%02x\n", p_adapter_id_str, __func__,
+ p_rst->mn_si_labs_clock_synth_model, p_rst->mn_si_labs_clock_synth_i2c_addr);
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h
new file mode 100644
index 0000000000..1f192f5ecc
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_RST_NT200A0X_H__
+#define __NTHW_FPGA_RST_NT200A0X_H__
+
+#include "nthw_drv.h"
+#include "nthw_fpga_model.h"
+
+struct nthw_fpga_rst_nt200a0x {
+ int mn_fpga_product_id;
+ int mn_fpga_version;
+ int mn_fpga_revision;
+
+ int mn_hw_id;
+
+ int mn_si_labs_clock_synth_model;
+ uint8_t mn_si_labs_clock_synth_i2c_addr;
+
+ nt_field_t *mp_fld_rst_sys;
+ nt_field_t *mp_fld_rst_sys_mmcm;
+ nt_field_t *mp_fld_rst_core_mmcm;
+ nt_field_t *mp_fld_rst_rpp;
+ nt_field_t *mp_fld_rst_ddr4;
+ nt_field_t *mp_fld_rst_sdc;
+ nt_field_t *mp_fld_rst_phy;
+ nt_field_t *mp_fld_rst_serdes_rx;
+ nt_field_t *mp_fld_rst_serdes_tx;
+ nt_field_t *mp_fld_rst_serdes_rx_datapath;
+ nt_field_t *mp_fld_rst_pcs_rx;
+ nt_field_t *mp_fld_rst_mac_rx;
+ nt_field_t *mp_fld_rst_mac_tx;
+ nt_field_t *mp_fld_rst_ptp;
+ nt_field_t *mp_fld_rst_ts;
+ nt_field_t *mp_fld_rst_ptp_mmcm;
+ nt_field_t *mp_fld_rst_ts_mmcm;
+ nt_field_t *mp_fld_rst_periph;
+ nt_field_t *mp_fld_rst_tsm_ref_mmcm;
+ nt_field_t *mp_fld_rst_tmc;
+
+ /* CTRL register field pointers */
+ nt_field_t *mp_fld_ctrl_ts_clk_sel_override;
+ nt_field_t *mp_fld_ctrl_ts_clk_sel;
+ nt_field_t *mp_fld_ctrl_ts_clk_sel_ref;
+ nt_field_t *mp_fld_ctrl_ptp_mmcm_clk_sel;
+
+ /* STAT register field pointers */
+ nt_field_t *mp_fld_stat_ddr4_mmcm_locked;
+ nt_field_t *mp_fld_stat_sys_mmcm_locked;
+ nt_field_t *mp_fld_stat_core_mmcm_locked;
+ nt_field_t *mp_fld_stat_ddr4_pll_locked;
+ nt_field_t *mp_fld_stat_ptp_mmcm_locked;
+ nt_field_t *mp_fld_stat_ts_mmcm_locked;
+ nt_field_t *mp_fld_stat_tsm_ref_mmcm_locked;
+
+ /* STICKY register field pointers */
+ nt_field_t *mp_fld_sticky_ptp_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_ts_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_ddr4_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_ddr4_pll_unlocked;
+ nt_field_t *mp_fld_sticky_core_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_pci_sys_mmcm_unlocked;
+ nt_field_t *mp_fld_sticky_tsm_ref_mmcm_unlocked;
+
+ /* POWER register field pointers */
+ nt_field_t *mp_fld_power_pu_phy;
+ nt_field_t *mp_fld_power_pu_nseb;
+ /* */
+
+ void (*reset_serdes_rx)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+ uint32_t rst);
+ void (*pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+ uint32_t rst);
+ void (*get_serdes_rx_rst)(struct nthw_fpga_rst_nt200a0x *p,
+ uint32_t intf_no, uint32_t *p_set);
+ void (*get_pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+ uint32_t *p_set);
+ bool (*is_rst_serdes_rx_datapath_implemented)(struct nthw_fpga_rst_nt200a0x *p);
+};
+
+typedef struct nthw_fpga_rst_nt200a0x nthw_fpga_rst_nt200a0x_t;
+
+int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,
+ struct nthw_fpga_rst_nt200a0x *p_rst);
+int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga,
+ const struct nthw_fpga_rst_nt200a0x *p);
+
+#endif /* __NTHW_FPGA_RST_NT200A0X_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c
new file mode 100644
index 0000000000..9b536726d0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_gpio_phy.h"
+
+nthw_gpio_phy_t *nthw_gpio_phy_new(void)
+{
+ nthw_gpio_phy_t *p = malloc(sizeof(nthw_gpio_phy_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_gpio_phy_t));
+ return p;
+}
+
+void nthw_gpio_phy_delete(nthw_gpio_phy_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_gpio_phy_t));
+ free(p);
+ }
+}
+
+int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_GPIO_PHY, n_instance);
+
+ if (p == NULL)
+ return (p_mod == NULL ? -1 : 0);
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: GPIO_PHY %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_gpio_phy = p_mod;
+
+ /* Registers */
+ p->mp_reg_config = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_CFG);
+ p->mp_reg_gpio = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_GPIO);
+
+ /* PORT-0, config fields */
+ p->mpa_fields[0].cfg_fld_lp_mode =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_LPMODE);
+ p->mpa_fields[0].cfg_int =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_INT_B);
+ p->mpa_fields[0].cfg_reset =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_RESET_B);
+ p->mpa_fields[0].cfg_mod_prs =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_MODPRS_B);
+
+ /* PORT-0, Non-mandatory fields (queryField) */
+ p->mpa_fields[0].cfg_pll_int =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_PLL_INTR);
+ p->mpa_fields[0].cfg_port_rxlos =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT0_RXLOS);
+
+ /* PORT-1, config fields */
+ p->mpa_fields[1].cfg_fld_lp_mode =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_LPMODE);
+ p->mpa_fields[1].cfg_int =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_INT_B);
+ p->mpa_fields[1].cfg_reset =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_RESET_B);
+ p->mpa_fields[1].cfg_mod_prs =
+ register_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_MODPRS_B);
+
+ /* PORT-1, Non-mandatory fields (queryField) */
+ p->mpa_fields[1].cfg_pll_int =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_PLL_INTR);
+ p->mpa_fields[1].cfg_port_rxlos =
+ register_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT1_RXLOS);
+
+ /* PORT-0, gpio fields */
+ p->mpa_fields[0].gpio_fld_lp_mode =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_LPMODE);
+ p->mpa_fields[0].gpio_int =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_INT_B);
+ p->mpa_fields[0].gpio_reset =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_RESET_B);
+ p->mpa_fields[0].gpio_mod_prs =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_MODPRS_B);
+
+ /* PORT-0, Non-mandatory fields (queryField) */
+ p->mpa_fields[0].gpio_pll_int =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_PLL_INTR);
+ p->mpa_fields[0].gpio_port_rxlos =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT0_RXLOS);
+
+ /* PORT-1, gpio fields */
+ p->mpa_fields[1].gpio_fld_lp_mode =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_LPMODE);
+ p->mpa_fields[1].gpio_int =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_INT_B);
+ p->mpa_fields[1].gpio_reset =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_RESET_B);
+ p->mpa_fields[1].gpio_mod_prs =
+ register_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_MODPRS_B);
+
+ /* PORT-1, Non-mandatory fields (queryField) */
+ p->mpa_fields[1].gpio_pll_int =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_PLL_INTR);
+ p->mpa_fields[1].gpio_port_rxlos =
+ register_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT1_RXLOS);
+
+ register_update(p->mp_reg_config);
+
+ return 0;
+}
+
+bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ if (field_get_updated(p->mpa_fields[if_no].gpio_fld_lp_mode))
+ return true;
+
+ else
+ return false;
+}
+
+bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a negated GPIO PIN "INT_B" */
+ if (field_get_updated(p->mpa_fields[if_no].gpio_int))
+ return false;
+
+ else
+ return true;
+}
+
+bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a negated GPIO PIN "RESET_B" */
+ if (field_get_updated(p->mpa_fields[if_no].gpio_reset))
+ return false;
+
+ else
+ return true;
+}
+
+bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a negated GPIO PIN "MODPRS_B" */
+ return field_get_updated(p->mpa_fields[if_no].gpio_mod_prs) == 0U ? true :
+ false;
+}
+
+bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ /* NOTE: This is a normal GPIO PIN "PLL_INTR" */
+ if (p->mpa_fields[if_no].gpio_pll_int) {
+ if (field_get_updated(p->mpa_fields[if_no].gpio_pll_int))
+ return true;
+
+ else
+ return false;
+ } else {
+ /* this HW doesn't support "PLL_INTR" (INTR from SyncE jitter attenuater) */
+ return false;
+ }
+}
+
+bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return false;
+ }
+
+ if (p->mpa_fields[if_no].gpio_port_rxlos) {
+ if (field_get_updated(p->mpa_fields[if_no].gpio_port_rxlos))
+ return true;
+ else
+ return false;
+ } else {
+ return false;
+ }
+}
+
+void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ if (enable)
+ field_set_flush(p->mpa_fields[if_no].gpio_fld_lp_mode);
+
+ else
+ field_clr_flush(p->mpa_fields[if_no].gpio_fld_lp_mode);
+ field_clr_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable output */
+}
+
+void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ if (enable)
+ field_clr_flush(p->mpa_fields[if_no].gpio_reset);
+
+ else
+ field_set_flush(p->mpa_fields[if_no].gpio_reset);
+ field_clr_flush(p->mpa_fields[if_no].cfg_reset); /* enable output */
+}
+
+void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ if (p->mpa_fields[if_no].gpio_port_rxlos) {
+ if (enable)
+ field_set_flush(p->mpa_fields[if_no].gpio_port_rxlos);
+
+ else
+ field_clr_flush(p->mpa_fields[if_no].gpio_port_rxlos);
+ }
+}
+
+void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no)
+{
+ if (if_no >= ARRAY_SIZE(p->mpa_fields)) {
+ assert(false);
+ return;
+ }
+
+ field_set_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable input */
+ field_set_flush(p->mpa_fields[if_no].cfg_int); /* enable input */
+ field_set_flush(p->mpa_fields[if_no].cfg_reset); /* enable input */
+ field_set_flush(p->mpa_fields[if_no].cfg_mod_prs); /* enable input */
+ if (p->mpa_fields[if_no].cfg_port_rxlos)
+ field_clr_flush(p->mpa_fields[if_no].cfg_port_rxlos); /* enable output */
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h
new file mode 100644
index 0000000000..1c6185150c
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_GPIO_PHY_H_
+#define NTHW_GPIO_PHY_H_
+
+#define GPIO_PHY_INTERFACES (2)
+
+typedef struct {
+ nt_field_t *cfg_fld_lp_mode; /* Cfg Low Power Mode */
+ nt_field_t *cfg_int; /* Cfg Port Interrupt */
+ nt_field_t *cfg_reset; /* Cfg Reset */
+ nt_field_t *cfg_mod_prs; /* Cfg Module Present */
+ nt_field_t *cfg_pll_int; /* Cfg PLL Interrupt */
+ nt_field_t *cfg_port_rxlos; /* Emulate Cfg Port RXLOS */
+
+ nt_field_t *gpio_fld_lp_mode; /* Gpio Low Power Mode */
+ nt_field_t *gpio_int; /* Gpio Port Interrupt */
+ nt_field_t *gpio_reset; /* Gpio Reset */
+ nt_field_t *gpio_mod_prs; /* Gpio Module Present */
+ nt_field_t *gpio_pll_int; /* Gpio PLL Interrupt */
+ nt_field_t *gpio_port_rxlos; /* Emulate Gpio Port RXLOS */
+} gpio_phy_fields_t;
+
+struct nthw_gpio_phy {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_gpio_phy;
+ int mn_instance;
+
+ /* Registers */
+ nt_register_t *mp_reg_config;
+ nt_register_t *mp_reg_gpio;
+
+ /* Fields */
+ gpio_phy_fields_t mpa_fields[GPIO_PHY_INTERFACES];
+};
+
+typedef struct nthw_gpio_phy nthw_gpio_phy_t;
+typedef struct nthw_gpio_phy nthw_gpio_phy;
+
+nthw_gpio_phy_t *nthw_gpio_phy_new(void);
+void nthw_gpio_phy_delete(nthw_gpio_phy_t *p);
+int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no);
+bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no);
+void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);
+void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);
+void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);
+void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no);
+
+#endif /* NTHW_GPIO_PHY_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c
new file mode 100644
index 0000000000..7b7a919108
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_hif.c
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_hif.h"
+
+nthw_hif_t *nthw_hif_new(void)
+{
+ nthw_hif_t *p = malloc(sizeof(nthw_hif_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_hif_t));
+ return p;
+}
+
+void nthw_hif_delete(nthw_hif_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_hif_t));
+ free(p);
+ }
+}
+
+int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str _unused =
+ p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_HIF, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: HIF %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_hif = mod;
+
+ /* default for (Xilinx-based) products until august 2022: (1e6/4000 = 250 MHz) */
+ p->mn_fpga_param_hif_per_ps =
+ fpga_get_product_param(p->mp_fpga, NT_HIF_PER_PS, 4000);
+ p->mn_fpga_hif_ref_clk_freq =
+ (uint32_t)(1000000000000ULL /
+ (unsigned int)p->mn_fpga_param_hif_per_ps);
+
+ p->mp_reg_prod_id_lsb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_LSB);
+ p->mp_fld_prod_id_lsb_rev_id =
+ register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_REV_ID);
+ p->mp_fld_prod_id_lsb_ver_id =
+ register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_VER_ID);
+ p->mp_fld_prod_id_lsb_group_id =
+ register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_GROUP_ID);
+
+ p->mp_reg_prod_id_msb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_MSB);
+ p->mp_fld_prod_id_msb_type_id =
+ register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_TYPE_ID);
+ p->mp_fld_prod_id_msb_build_no =
+ register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_BUILD_NO);
+
+ p->mp_reg_build_time = module_get_register(p->mp_mod_hif, HIF_BUILD_TIME);
+ p->mp_fld_build_time =
+ register_get_field(p->mp_reg_build_time, HIF_BUILD_TIME_TIME);
+
+ p->mn_fpga_id_prod = field_get_updated(p->mp_fld_prod_id_lsb_group_id);
+ p->mn_fpga_id_ver = field_get_updated(p->mp_fld_prod_id_lsb_ver_id);
+ p->mn_fpga_id_rev = field_get_updated(p->mp_fld_prod_id_lsb_rev_id);
+ p->mn_fpga_id_build_no = field_get_updated(p->mp_fld_prod_id_msb_build_no);
+ p->mn_fpga_id_item = field_get_updated(p->mp_fld_prod_id_msb_type_id);
+
+ NT_LOG(DBG, NTHW, "%s: HIF %d: %s: %d-%d-%d-%d-%d\n", p_adapter_id_str,
+ p->mn_instance, __func__, p->mn_fpga_id_item, p->mn_fpga_id_prod,
+ p->mn_fpga_id_ver, p->mn_fpga_id_rev, p->mn_fpga_id_build_no);
+ NT_LOG(DBG, NTHW,
+ "%s: HIF %d: %s: HIF ref clock: %d Hz (%d ticks/ps)\n",
+ p_adapter_id_str, p->mn_instance, __func__, p->mn_fpga_hif_ref_clk_freq,
+ p->mn_fpga_param_hif_per_ps);
+
+ p->mp_reg_build_seed = NULL; /* Reg/Fld not present on HIF */
+ if (p->mp_reg_build_seed)
+ p->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */
+ else
+ p->mp_fld_build_seed = NULL;
+
+ p->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */
+ if (p->mp_reg_core_speed) {
+ p->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */
+ p->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */
+ } else {
+ p->mp_reg_core_speed = NULL;
+ p->mp_fld_core_speed = NULL;
+ p->mp_fld_ddr3_speed = NULL;
+ }
+
+ /* Optional registers since: 2018-04-25 */
+ p->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */
+ p->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */
+ p->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */
+
+ p->mp_fld_int_mask_timer = NULL;
+ p->mp_fld_int_clr_timer = NULL;
+ p->mp_fld_int_force_timer = NULL;
+
+ p->mp_fld_int_mask_port = NULL;
+ p->mp_fld_int_clr_port = NULL;
+ p->mp_fld_int_force_port = NULL;
+
+ p->mp_fld_int_mask_pps = NULL;
+ p->mp_fld_int_clr_pps = NULL;
+ p->mp_fld_int_force_pps = NULL;
+
+ p->mp_reg_stat_ctrl = module_get_register(p->mp_mod_hif, HIF_STAT_CTRL);
+ p->mp_fld_stat_ctrl_ena =
+ register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA);
+ p->mp_fld_stat_ctrl_req =
+ register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ);
+
+ p->mp_reg_stat_rx = module_get_register(p->mp_mod_hif, HIF_STAT_RX);
+ p->mp_fld_stat_rx_counter =
+ register_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER);
+
+ p->mp_reg_stat_tx = module_get_register(p->mp_mod_hif, HIF_STAT_TX);
+ p->mp_fld_stat_tx_counter =
+ register_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER);
+
+ p->mp_reg_stat_ref_clk = module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK);
+ p->mp_fld_stat_ref_clk_ref_clk = register_get_field(p->mp_reg_stat_ref_clk,
+ HIF_STAT_REFCLK_REFCLK250);
+
+ p->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS);
+ if (p->mp_reg_status) {
+ p->mp_fld_status_tags_in_use =
+ register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE);
+ p->mp_fld_status_wr_err =
+ register_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR);
+ p->mp_fld_status_rd_err =
+ register_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR);
+ } else {
+ p->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS);
+ p->mp_fld_status_tags_in_use =
+ register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE);
+ p->mp_fld_status_wr_err = NULL;
+ p->mp_fld_status_rd_err = NULL;
+ }
+
+ p->mp_reg_pci_test0 = module_get_register(p->mp_mod_hif, HIF_TEST0);
+ p->mp_fld_pci_test0 = register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA);
+
+ p->mp_reg_pci_test1 = module_get_register(p->mp_mod_hif, HIF_TEST1);
+ p->mp_fld_pci_test1 = register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA);
+
+ /* Required to run TSM */
+ p->mp_reg_sample_time = module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME);
+ if (p->mp_reg_sample_time) {
+ p->mp_fld_sample_time =
+ register_get_field(p->mp_reg_sample_time, HIF_SAMPLE_TIME_SAMPLE_TIME);
+ } else {
+ p->mp_fld_sample_time = NULL;
+ }
+
+ /* We need to optimize PCIe3 TLP-size read-request and extended tag usage */
+ {
+ p->mp_reg_config = module_query_register(p->mp_mod_hif, HIF_CONFIG);
+ if (p->mp_reg_config) {
+ p->mp_fld_max_tlp =
+ register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP);
+ p->mp_fld_max_read =
+ register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ);
+ p->mp_fld_ext_tag =
+ register_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG);
+ } else {
+ p->mp_fld_max_tlp = NULL;
+ p->mp_fld_max_read = NULL;
+ p->mp_fld_ext_tag = NULL;
+ }
+ }
+
+ return 0;
+}
+
+int nthw_hif_setup_config(nthw_hif_t *p)
+{
+ const char *const p_adapter_id_str _unused =
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+
+ /*
+ * We need to optimize PCIe3 read-request and extended tag usage
+ * original check: HW_ADAPTER_ID_NT200A02 HW_ADAPTER_ID_NT100A01 HW_ADAPTER_ID_NT50B01
+ */
+ if (p->mp_fpga->p_fpga_info->n_nthw_adapter_id != NT_HW_ADAPTER_ID_NT40E3) {
+ if (p->mp_fld_max_read) {
+ /*
+ * NOTE: On Pandion DELL server, this param was negotiated to 4096
+ * (index=5), but the server crashed. For now we need to limit this value to
+ * 512 (index=2)
+ */
+ const uint32_t n_max_read_req_size =
+ field_get_updated(p->mp_fld_max_read);
+ if (n_max_read_req_size > 2) {
+ field_set_val_flush32(p->mp_fld_max_read, 2);
+ NT_LOG(INF, NTHW,
+ "%s: %s: PCIe: MaxReadReqsize %d - changed to 2 (512B)\n",
+ p_adapter_id_str, __func__,
+ n_max_read_req_size);
+ }
+ }
+
+ if (p->mp_fld_ext_tag)
+ field_set_val_flush32(p->mp_fld_ext_tag, 1);
+
+ if (p->mp_fld_max_tlp && p->mp_fld_max_read && p->mp_fld_ext_tag) {
+ NT_LOG(INF, NTHW,
+ "%s: %s: PCIe config: MaxTlp = %d, MaxReadReqsize = %d, ExtTagEna = %d\n",
+ p_adapter_id_str, __func__,
+ field_get_updated(p->mp_fld_max_tlp),
+ field_get_updated(p->mp_fld_max_read),
+ field_get_updated(p->mp_fld_ext_tag));
+ }
+ }
+ return 0;
+}
+
+int nthw_hif_trigger_sample_time(nthw_hif_t *p)
+{
+ field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);
+
+ return 0;
+}
+
+int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err, uint64_t *p_wr_err)
+{
+ *p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter);
+ *p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter);
+
+ *p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk);
+
+ *p_tg_unit_size = NTHW_TG_CNT_SIZE;
+ *p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq;
+
+ *p_tags_in_use = (p->mp_fld_status_tags_in_use ?
+ field_get_updated(p->mp_fld_status_tags_in_use) :
+ 0);
+
+ *p_rd_err = (p->mp_fld_status_rd_err ? field_get_updated(p->mp_fld_status_rd_err) :
+ 0);
+ *p_wr_err = (p->mp_fld_status_wr_err ? field_get_updated(p->mp_fld_status_wr_err) :
+ 0);
+
+ return 0;
+}
+
+int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt,
+ uint64_t *p_wr_err_cnt)
+{
+ uint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq;
+ uint64_t n_tags_in_use, n_rd_err, n_wr_err;
+
+ nthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq,
+ &n_tags_in_use, &n_rd_err, &n_wr_err);
+
+ *p_tags_in_use = n_tags_in_use;
+ if (n_rd_err)
+ (*p_rd_err_cnt)++;
+ if (n_wr_err)
+ (*p_wr_err_cnt)++;
+
+ if (ref_clk_cnt) {
+ uint64_t rx_rate;
+ uint64_t tx_rate;
+
+ *p_ref_clk_cnt = ref_clk_cnt;
+
+ rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_rx_rate = rx_rate;
+
+ tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_tx_rate = tx_rate;
+ } else {
+ *p_pci_rx_rate = 0;
+ *p_pci_tx_rate = 0;
+ *p_ref_clk_cnt = 0;
+ }
+
+ return 0;
+}
+
+int nthw_hif_stat_req_enable(nthw_hif_t *p)
+{
+ field_set_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_hif_stat_req_disable(nthw_hif_t *p)
+{
+ field_clr_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate,
+ uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt)
+{
+ nthw_hif_stat_req_enable(p);
+ NT_OS_WAIT_USEC(100000);
+ nthw_hif_stat_req_disable(p);
+ nthw_hif_get_stat_rate(p, p_rx_rate, p_tx_rate, p_ref_clk_cnt, p_tags_in_use,
+ p_rd_err_cnt, p_wr_err_cnt);
+
+ return 0;
+}
+
+int nthw_hif_end_point_counters_sample(nthw_hif_t *p,
+ struct nthw_hif_end_point_counters *epc)
+{
+ assert(epc);
+
+ /* Get stat rate and maintain rx/tx min/max */
+ nthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt,
+ &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.h b/drivers/net/ntnic/nthw/core/nthw_hif.h
new file mode 100644
index 0000000000..2701e222b3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_hif.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_HIF_H__
+#define __NTHW_HIF_H__
+
+#define NTHW_TG_CNT_SIZE (4ULL)
+
+struct nthw_hif {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_hif;
+ int mn_instance;
+
+ nt_register_t *mp_reg_prod_id_lsb;
+ nt_field_t *mp_fld_prod_id_lsb_rev_id;
+ nt_field_t *mp_fld_prod_id_lsb_ver_id;
+ nt_field_t *mp_fld_prod_id_lsb_group_id;
+
+ nt_register_t *mp_reg_prod_id_msb;
+ nt_field_t *mp_fld_prod_id_msb_type_id;
+ nt_field_t *mp_fld_prod_id_msb_build_no;
+
+ nt_register_t *mp_reg_build_time;
+ nt_field_t *mp_fld_build_time;
+
+ nt_register_t *mp_reg_build_seed;
+ nt_field_t *mp_fld_build_seed;
+
+ nt_register_t *mp_reg_core_speed;
+ nt_field_t *mp_fld_core_speed;
+ nt_field_t *mp_fld_ddr3_speed;
+
+ nt_register_t *mp_reg_int_mask;
+ nt_field_t *mp_fld_int_mask_timer;
+ nt_field_t *mp_fld_int_mask_port;
+ nt_field_t *mp_fld_int_mask_pps;
+
+ nt_register_t *mp_reg_int_clr;
+ nt_field_t *mp_fld_int_clr_timer;
+ nt_field_t *mp_fld_int_clr_port;
+ nt_field_t *mp_fld_int_clr_pps;
+
+ nt_register_t *mp_reg_int_force;
+ nt_field_t *mp_fld_int_force_timer;
+ nt_field_t *mp_fld_int_force_port;
+ nt_field_t *mp_fld_int_force_pps;
+
+ nt_register_t *mp_reg_sample_time;
+ nt_field_t *mp_fld_sample_time;
+
+ nt_register_t *mp_reg_status;
+ nt_field_t *mp_fld_status_tags_in_use;
+ nt_field_t *mp_fld_status_wr_err;
+ nt_field_t *mp_fld_status_rd_err;
+
+ nt_register_t *mp_reg_stat_ctrl;
+ nt_field_t *mp_fld_stat_ctrl_ena;
+ nt_field_t *mp_fld_stat_ctrl_req;
+
+ nt_register_t *mp_reg_stat_rx;
+ nt_field_t *mp_fld_stat_rx_counter;
+
+ nt_register_t *mp_reg_stat_tx;
+ nt_field_t *mp_fld_stat_tx_counter;
+
+ nt_register_t *mp_reg_stat_ref_clk;
+ nt_field_t *mp_fld_stat_ref_clk_ref_clk;
+
+ nt_register_t *mp_reg_pci_test0;
+ nt_field_t *mp_fld_pci_test0;
+
+ nt_register_t *mp_reg_pci_test1;
+ nt_field_t *mp_fld_pci_test1;
+
+ nt_register_t *mp_reg_pci_test2;
+ nt_field_t *mp_fld_pci_test2;
+
+ nt_register_t *mp_reg_pci_test3;
+ nt_field_t *mp_fld_pci_test3;
+
+ nt_register_t *mp_reg_config;
+ nt_field_t *mp_fld_max_tlp;
+ nt_field_t *mp_fld_max_read;
+ nt_field_t *mp_fld_ext_tag;
+
+ int mn_fpga_id_item;
+ int mn_fpga_id_prod;
+ int mn_fpga_id_ver;
+ int mn_fpga_id_rev;
+ int mn_fpga_id_build_no;
+
+ int mn_fpga_param_hif_per_ps;
+ uint32_t mn_fpga_hif_ref_clk_freq;
+};
+
+typedef struct nthw_hif nthw_hif_t;
+typedef struct nthw_hif nthw_hif;
+
+struct nthw_hif_end_point_err_counters {
+ uint32_t n_err_correctable, n_err_non_fatal, n_err_fatal;
+};
+
+struct nthw_hif_end_point_counters {
+ int n_numa_node;
+
+ int n_tg_direction;
+ int n_tg_pkt_size;
+ int n_tg_num_pkts;
+ int n_tg_delay;
+
+ uint64_t cur_rx, cur_tx;
+ uint64_t cur_pci_nt_util, cur_pci_xil_util;
+ uint64_t n_ref_clk_cnt;
+
+ uint64_t n_tags_in_use;
+ uint64_t n_rd_err;
+ uint64_t n_wr_err;
+
+ struct nthw_hif_end_point_err_counters s_rc_ep_pre, s_rc_ep_post, s_rc_ep_delta;
+ struct nthw_hif_end_point_err_counters s_ep_rc_pre, s_ep_rc_post, s_ep_rc_delta;
+
+ int bo_error;
+};
+
+struct nthw_hif_end_points {
+ struct nthw_hif_end_point_counters pri, sla;
+};
+
+nthw_hif_t *nthw_hif_new(void);
+void nthw_hif_delete(nthw_hif_t *p);
+int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+int nthw_hif_setup_config(nthw_hif_t *p);
+
+int nthw_hif_trigger_sample_time(nthw_hif_t *p);
+
+int nthw_hif_stat_req_enable(nthw_hif_t *p);
+int nthw_hif_stat_req_disable(nthw_hif_t *p);
+int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate,
+ uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt);
+
+int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use,
+ uint64_t *p_rd_err, uint64_t *p_wr_err);
+int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt,
+ uint64_t *p_wr_err_cnt);
+
+int nthw_hif_end_point_counters_sample(nthw_hif_t *p,
+ struct nthw_hif_end_point_counters *epc);
+
+#endif /* __NTHW_HIF_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.c b/drivers/net/ntnic/nthw/core/nthw_iic.c
new file mode 100644
index 0000000000..14aee221ce
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_iic.c
@@ -0,0 +1,570 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_iic.h"
+
+#define I2C_TRANSMIT_WR (0x00)
+#define I2C_TRANSMIT_RD (0x01)
+
+#define I2C_WAIT_US(x) NT_OS_WAIT_USEC(x)
+
+/*
+ * Minimum timing values for I2C for a Marvel 88E11111 Phy.
+ * This Phy is used in many Trispeed NIMs.
+ * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz.
+ */
+static const uint32_t susta = 4700; /* ns */
+static const uint32_t susto = 4000; /* ns */
+static const uint32_t hdsta = 4000; /* ns */
+static const uint32_t sudat = 250; /* ns */
+static const uint32_t buf = 4700; /* ns */
+static const uint32_t high = 4000; /* ns */
+static const uint32_t low = 4700; /* ns */
+static const uint32_t hddat = 300; /* ns */
+
+static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p)
+{
+ field_update_register(p->mp_fld_cr_txfifo_reset);
+
+ field_set_all(p->mp_fld_cr_txfifo_reset);
+ field_flush_register(p->mp_fld_cr_txfifo_reset);
+
+ field_clr_all(p->mp_fld_cr_txfifo_reset);
+ field_flush_register(p->mp_fld_cr_txfifo_reset);
+
+ return 0;
+}
+
+static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start,
+ bool stop)
+{
+ if (start)
+ field_set_all(p->mp_fld_tx_fifo_start);
+
+ else
+ field_clr_all(p->mp_fld_tx_fifo_start);
+
+ if (stop)
+ field_set_all(p->mp_fld_tx_fifo_stop);
+
+ else
+ field_clr_all(p->mp_fld_tx_fifo_stop);
+
+ field_set_val32(p->mp_fld_tx_fifo_txdata, data);
+
+ register_flush(p->mp_reg_tx_fifo, 1);
+
+ return 0;
+}
+
+static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data)
+{
+ assert(p_data);
+
+ *p_data = (uint8_t)field_get_updated(p->mp_fld_rx_fifo_rxdata);
+
+ return 0;
+}
+
+static int nthw_iic_reg_softr(nthw_iic_t *p)
+{
+ field_update_register(p->mp_fld_cr_en);
+ field_set_val_flush32(p->mp_fld_softr_rkey, 0x0A);
+
+ return 0;
+}
+
+static int nthw_iic_reg_enable(nthw_iic_t *p)
+{
+ field_update_register(p->mp_fld_cr_en);
+ field_set_flush(p->mp_fld_cr_en);
+
+ return 0;
+}
+
+static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag)
+{
+ assert(pb_flag);
+
+ *pb_flag = field_get_updated(p->mp_fld_sr_bb) ? true : false;
+
+ return 0;
+}
+
+static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag)
+{
+ assert(pb_flag);
+
+ *pb_flag = field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false;
+
+ return 0;
+}
+
+/*
+ * nIicCycleTime is the I2C clock cycle time in ns ie 125MHz = 8ns
+ */
+static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time)
+{
+ uint32_t val;
+
+ val = susta / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tsusta, &val, 1);
+
+ val = susto / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tsusto, &val, 1);
+
+ val = hdsta / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_thdsta, &val, 1);
+
+ val = sudat / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tsudat, &val, 1);
+
+ val = buf / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tbuf, &val, 1);
+
+ val = high / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_thigh, &val, 1);
+
+ val = low / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_tlow, &val, 1);
+
+ val = hddat / n_iic_cycle_time;
+ field_set_val_flush(p->mp_fld_thddat, &val, 1);
+
+ return 0;
+}
+
+nthw_iic_t *nthw_iic_new(void)
+{
+ nthw_iic_t *p = malloc(sizeof(nthw_iic_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_iic_t));
+ return p;
+}
+
+int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance,
+ uint32_t n_iic_cycle_time)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_IIC, n_iic_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance\n",
+ p_adapter_id_str, n_iic_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_iic_instance = n_iic_instance;
+
+ p->mn_iic_cycle_time = n_iic_cycle_time;
+
+ nthw_iic_set_retry_params(p, -1, -1, -1, -1, -1);
+
+ p->mp_mod_iic = mod;
+
+ /* I2C is a primary communication channel - turn off debug by default */
+ module_set_debug_mode(p->mp_mod_iic, 0x00);
+
+ p->mp_reg_tsusta = module_get_register(p->mp_mod_iic, IIC_TSUSTA);
+ p->mp_fld_tsusta =
+ register_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL);
+
+ p->mp_reg_tsusto = module_get_register(p->mp_mod_iic, IIC_TSUSTO);
+ p->mp_fld_tsusto =
+ register_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL);
+
+ p->mp_reg_thdsta = module_get_register(p->mp_mod_iic, IIC_THDSTA);
+ p->mp_fld_thdsta =
+ register_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL);
+
+ p->mp_reg_tsudat = module_get_register(p->mp_mod_iic, IIC_TSUDAT);
+ p->mp_fld_tsudat =
+ register_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL);
+
+ p->mp_reg_tbuf = module_get_register(p->mp_mod_iic, IIC_TBUF);
+ p->mp_fld_tbuf = register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL);
+
+ p->mp_reg_thigh = module_get_register(p->mp_mod_iic, IIC_THIGH);
+ p->mp_fld_thigh = register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL);
+
+ p->mp_reg_tlow = module_get_register(p->mp_mod_iic, IIC_TLOW);
+ p->mp_fld_tlow = register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL);
+
+ p->mp_reg_thddat = module_get_register(p->mp_mod_iic, IIC_THDDAT);
+ p->mp_fld_thddat =
+ register_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL);
+
+ p->mp_reg_cr = module_get_register(p->mp_mod_iic, IIC_CR);
+ p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, IIC_CR_EN);
+ p->mp_fld_cr_msms = register_get_field(p->mp_reg_cr, IIC_CR_MSMS);
+ p->mp_fld_cr_txfifo_reset =
+ register_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET);
+ p->mp_fld_cr_txak = register_get_field(p->mp_reg_cr, IIC_CR_TXAK);
+
+ p->mp_reg_sr = module_get_register(p->mp_mod_iic, IIC_SR);
+ p->mp_fld_sr_bb = register_get_field(p->mp_reg_sr, IIC_SR_BB);
+ p->mp_fld_sr_rxfifo_full =
+ register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL);
+ p->mp_fld_sr_rxfifo_empty =
+ register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY);
+ p->mp_fld_sr_txfifo_full =
+ register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL);
+ p->mp_fld_sr_txfifo_empty =
+ register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY);
+
+ p->mp_reg_tx_fifo = module_get_register(p->mp_mod_iic, IIC_TX_FIFO);
+ p->mp_fld_tx_fifo_txdata =
+ register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA);
+ p->mp_fld_tx_fifo_start =
+ register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START);
+ p->mp_fld_tx_fifo_stop =
+ register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP);
+
+ p->mp_reg_rx_fifo_pirq =
+ module_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ);
+ p->mp_fld_rx_fifo_pirq_cmp_val =
+ register_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL);
+
+ p->mp_reg_rx_fifo = module_get_register(p->mp_mod_iic, IIC_RX_FIFO);
+ p->mp_fld_rx_fifo_rxdata =
+ register_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA);
+
+ p->mp_reg_softr = module_get_register(p->mp_mod_iic, IIC_SOFTR);
+ p->mp_fld_softr_rkey = register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY);
+
+ /*
+ * Initialize I2C controller by applying soft reset and enable the controller
+ */
+ nthw_iic_reg_softr(p);
+ /* Enable the controller */
+ nthw_iic_reg_enable(p);
+
+ /* Setup controller timing */
+ if (p->mn_iic_cycle_time) {
+ NT_LOG(DBG, NTHW, "%s: I2C%d: cycletime=%d\n", p_adapter_id_str,
+ p->mn_iic_instance, p->mn_iic_cycle_time);
+ nthw_iic_reg_set_timing(p, p->mn_iic_cycle_time);
+ }
+
+ /* Reset TX fifo - must be after enable */
+ nthw_iic_reg_control_txfifo_reset(p);
+ nthw_iic_reg_tx_fifo_write(p, 0, 0, 0);
+
+ return 0;
+}
+
+void nthw_iic_delete(nthw_iic_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_iic_t));
+ free(p);
+ }
+}
+
+int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay,
+ const int n_bus_ready_retry, const int n_data_ready_retry,
+ const int n_read_data_retry, const int n_write_data_retry)
+{
+ p->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10;
+
+ p->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000;
+ p->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000;
+
+ p->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10;
+ p->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10;
+
+ return 0;
+}
+
+int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ const int n_debug_mode = module_get_debug_mode(p->mp_mod_iic);
+
+ uint8_t *pb = (uint8_t *)p_void;
+ int retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10);
+
+ if (n_debug_mode == 0xff) {
+ NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d\n",
+ p_adapter_id_str, dev_addr, reg_addr, data_len);
+ }
+
+ while (nthw_iic_readbyte(p, dev_addr, reg_addr, data_len, pb) != 0) {
+ retry--;
+ if (retry <= 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: I2C%d: Read retry exhausted (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, dev_addr,
+ reg_addr);
+ return -1;
+ }
+#if defined(DEBUG)
+ NT_LOG(DBG, NTHW,
+ "%s: I2C%d: Read retry=%d (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, retry, dev_addr,
+ reg_addr);
+#endif
+ }
+
+ if (n_debug_mode == 0xff) {
+ NT_LOG(DBG, NTHW,
+ "%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\n",
+ p_adapter_id_str, dev_addr, reg_addr, data_len, retry);
+ }
+
+ return 0;
+}
+
+int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+
+ uint32_t value;
+ uint32_t i;
+
+ if (nthw_iic_bus_ready(p)) {
+ /* Reset TX fifo */
+ nthw_iic_reg_control_txfifo_reset(p);
+
+ /* Write device address to TX_FIFO and set start bit!! */
+ value = (dev_addr << 1) | I2C_TRANSMIT_WR;
+ nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
+
+ /* Write reg_addr to TX FIFO */
+ nthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 1);
+
+ if (!nthw_iic_bus_ready(p)) {
+ NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* Write device address + RD bit to TX_FIFO and set start bit!! */
+ value = (dev_addr << 1) | I2C_TRANSMIT_RD;
+ nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
+
+ /* Write DataLen to TX_FIFO and set stop bit!! */
+ nthw_iic_reg_tx_fifo_write(p, data_len, 0, 1);
+
+ for (i = 0; i < data_len; i++) {
+ /* Wait for RX FIFO not empty */
+ if (!nthw_iic_data_ready(p))
+ return -1;
+
+ /* Read DataLen bytes from RX_FIFO */
+ nthw_iic_reg_read_i2c_rx_fifo(p, p_byte);
+ p_byte++;
+ }
+
+ return 0;
+
+ } else {
+ NT_LOG(ERR, NTHW, "%s: error: (%s:%u)\n", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+ return 0;
+}
+
+int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10);
+ uint8_t *pb = (uint8_t *)p_void;
+
+ while (nthw_iic_writebyte(p, dev_addr, reg_addr, data_len, pb) != 0) {
+ retry--;
+ if (retry <= 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: I2C%d: Write retry exhausted (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, dev_addr,
+ reg_addr);
+ return -1;
+ }
+#if defined(DEBUG)
+ NT_LOG(DBG, NTHW,
+ "%s: I2C%d: Write retry=%d (dev_addr=%d reg_addr=%d)\n",
+ p_adapter_id_str, p->mn_iic_instance, retry, dev_addr,
+ reg_addr);
+#endif
+ }
+
+ return 0;
+}
+
+int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte)
+{
+ const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ uint32_t value;
+ int count;
+ int i;
+
+ if (data_len == 0)
+ return -1;
+
+ count = data_len - 1;
+ if (nthw_iic_bus_ready(p)) {
+ /* Reset TX fifo */
+ nthw_iic_reg_control_txfifo_reset(p);
+
+ /* Write device address to TX_FIFO and set start bit!! */
+ value = (dev_addr << 1) | I2C_TRANSMIT_WR;
+ nthw_iic_reg_tx_fifo_write(p, value, 1, 0);
+
+ /* Write reg_addr to TX FIFO */
+ nthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 0);
+
+ for (i = 0; i < count; i++) {
+ /* Write data byte to TX fifo and set stop bit */
+ nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0);
+ p_byte++;
+ }
+
+ /* Write data byte to TX fifo and set stop bit */
+ nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1);
+
+ if (!nthw_iic_bus_ready(p)) {
+ NT_LOG(WRN, NTHW, "%s: warn: !busReady (%s:%u)\n",
+ p_adapter_id_str, __func__, __LINE__);
+ while (true) {
+ if (nthw_iic_bus_ready(p)) {
+ NT_LOG(DBG, NTHW,
+ "%s: info: busReady (%s:%u)\n",
+ p_adapter_id_str, __func__,
+ __LINE__);
+ break;
+ }
+ }
+ }
+
+ return 0;
+
+ } else {
+ NT_LOG(WRN, NTHW, "%s: (%s:%u)\n", p_adapter_id_str, __func__,
+ __LINE__);
+ return -1;
+ }
+}
+
+/*
+ * Support function for read/write functions below. Waits for bus ready.
+ */
+bool nthw_iic_bus_ready(nthw_iic_t *p)
+{
+ int count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000);
+ bool b_bus_busy = true;
+
+ while (true) {
+ nthw_iic_reg_busbusy(p, &b_bus_busy);
+ if (!b_bus_busy)
+ break;
+
+ count--;
+ if (count <= 0) /* Test for timeout */
+ break;
+
+ if (p->mn_poll_delay != 0)
+ I2C_WAIT_US(p->mn_poll_delay);
+ }
+
+ if (count == 0)
+ return false;
+
+ return true;
+}
+
+/*
+ * Support function for read function. Waits for data ready.
+ */
+bool nthw_iic_data_ready(nthw_iic_t *p)
+{
+ int count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000);
+ bool b_rx_fifo_empty = true;
+
+ while (true) {
+ nthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty);
+ if (!b_rx_fifo_empty)
+ break;
+
+ count--;
+ if (count <= 0) /* Test for timeout */
+ break;
+
+ if (p->mn_poll_delay != 0)
+ I2C_WAIT_US(p->mn_poll_delay);
+ }
+
+ if (count == 0)
+ return false;
+
+ return true;
+}
+
+int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr)
+{
+ const char *const p_adapter_id_str _unused =
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int res;
+ uint8_t data_val = -1;
+
+ res = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1,
+ &data_val);
+ if (res == 0) {
+ NT_LOG(DBG, NTHW,
+ "%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\n",
+ p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr,
+ n_reg_addr, data_val, data_val, res);
+ }
+ return res;
+}
+
+int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate)
+{
+ const char *const p_adapter_id_str _unused =
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str;
+
+ int res = 0;
+ int i = 0;
+
+ if (b_increate) {
+ for (i = n_dev_addr_start; i < 128; i++) {
+ res = nthw_iic_scan_dev_addr(p, i, 0x00);
+ if (res == 0)
+ break;
+ }
+ } else {
+ for (i = n_dev_addr_start; i >= 0; i--) {
+ res = nthw_iic_scan_dev_addr(p, i, 0x00);
+ if (res == 0)
+ break;
+ }
+ }
+ NT_LOG(DBG, NTHW, "%s: I2C%d: FOUND: %d\n", p_adapter_id_str,
+ p->mn_iic_instance, i);
+ return (res == 0 ? i : -1);
+}
+
+int nthw_iic_scan(nthw_iic_t *p)
+{
+ int i;
+
+ for (i = 0; i < 128; i++)
+ (void)nthw_iic_scan_dev_addr(p, i, 0x00);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_iic.h b/drivers/net/ntnic/nthw/core/nthw_iic.h
new file mode 100644
index 0000000000..e3bd313c88
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_iic.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_IIC_H__
+#define __NTHW_IIC_H__
+
+#include "nthw_fpga_model.h"
+
+struct nthw_iic {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_iic;
+ int mn_iic_instance;
+
+ uint32_t mn_iic_cycle_time;
+ int mn_poll_delay;
+ int mn_bus_ready_retry;
+ int mn_data_ready_retry;
+ int mn_read_data_retry;
+ int mn_write_data_retry;
+
+ nt_register_t *mp_reg_tsusta;
+ nt_field_t *mp_fld_tsusta;
+
+ nt_register_t *mp_reg_tsusto;
+ nt_field_t *mp_fld_tsusto;
+
+ nt_register_t *mp_reg_thdsta;
+ nt_field_t *mp_fld_thdsta;
+
+ nt_register_t *mp_reg_tsudat;
+ nt_field_t *mp_fld_tsudat;
+
+ nt_register_t *mp_reg_tbuf;
+ nt_field_t *mp_fld_tbuf;
+
+ nt_register_t *mp_reg_thigh;
+ nt_field_t *mp_fld_thigh;
+
+ nt_register_t *mp_reg_tlow;
+ nt_field_t *mp_fld_tlow;
+
+ nt_register_t *mp_reg_thddat;
+ nt_field_t *mp_fld_thddat;
+
+ nt_register_t *mp_reg_cr;
+ nt_field_t *mp_fld_cr_en;
+ nt_field_t *mp_fld_cr_msms;
+ nt_field_t *mp_fld_cr_txfifo_reset;
+ nt_field_t *mp_fld_cr_txak;
+
+ nt_register_t *mp_reg_sr;
+ nt_field_t *mp_fld_sr_bb;
+ nt_field_t *mp_fld_sr_rxfifo_full;
+ nt_field_t *mp_fld_sr_rxfifo_empty;
+ nt_field_t *mp_fld_sr_txfifo_full;
+ nt_field_t *mp_fld_sr_txfifo_empty;
+
+ nt_register_t *mp_reg_tx_fifo;
+ nt_field_t *mp_fld_tx_fifo_txdata;
+ nt_field_t *mp_fld_tx_fifo_start;
+ nt_field_t *mp_fld_tx_fifo_stop;
+
+ nt_register_t *mp_reg_rx_fifo_pirq;
+ nt_field_t *mp_fld_rx_fifo_pirq_cmp_val;
+
+ nt_register_t *mp_reg_rx_fifo;
+ nt_field_t *mp_fld_rx_fifo_rxdata;
+
+ nt_register_t *mp_reg_softr;
+ nt_field_t *mp_fld_softr_rkey;
+};
+
+typedef struct nthw_iic nthw_iic_t;
+typedef struct nthw_iic nthw_iic;
+
+nthw_iic_t *nthw_iic_new(void);
+int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance,
+ uint32_t n_iic_cycle_time);
+void nthw_iic_delete(nthw_iic_t *p);
+
+int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay,
+ const int n_bus_ready_retry, const int n_data_ready_retry,
+ const int n_read_data_retry, const int n_write_data_retry);
+
+int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void);
+int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte);
+int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, void *p_void);
+int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t data_len, uint8_t *p_byte);
+bool nthw_iic_bus_ready(nthw_iic_t *p);
+bool nthw_iic_data_ready(nthw_iic_t *p);
+
+int nthw_iic_scan(nthw_iic_t *p);
+int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr);
+int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate);
+
+#endif /* __NTHW_IIC_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c
new file mode 100644
index 0000000000..d206c374b4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c
@@ -0,0 +1,1034 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_mac_pcs.h"
+
+#define NTHW_MAC_PCS_LANES (20)
+
+static const uint8_t c_pcs_lanes = NTHW_MAC_PCS_LANES;
+static const uint8_t c_mac_pcs_receiver_mode_dfe _unused;
+
+nthw_mac_pcs_t *nthw_mac_pcs_new(void)
+{
+ nthw_mac_pcs_t *p = malloc(sizeof(nthw_mac_pcs_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_mac_pcs_t));
+ return p;
+}
+
+void nthw_mac_pcs_delete(nthw_mac_pcs_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_mac_pcs_t));
+ free(p);
+ }
+}
+
+/*
+ * Parameters:
+ * p != NULL: init struct pointed to by p
+ * p == NULL: check fpga module(s) presence (but no struct to init)
+ *
+ * Return value:
+ * <0: if p == NULL then fpga module(s) is/are not present.
+ * if p != NULL then fpga module(s) is/are not present, struct undefined
+ * ==0: if p == NULL then fpga module(s) is/are are present (no struct to init)
+ * : if p != NULL then fpga module(s) is/are present and struct initialized
+ */
+int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_MAC_PCS, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: MAC_PCS %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_mac_pcs = mod;
+
+ assert(n_instance >= 0 && n_instance <= 255);
+ nthw_mac_pcs_set_port_no(p, (uint8_t)n_instance);
+
+ {
+ nt_register_t *p_reg_block_lock, *p_reg_stat_pcs_rx,
+ *p_reg_stat_pcs_rx_latch;
+ nt_register_t *p_reg_vl_demuxed, *p_reg_gty_stat, *p_reg_pcs_config,
+ *p_reg_phymac_misc;
+ const int product_id = fpga_get_product_id(p_fpga);
+
+ p_reg_block_lock =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BLOCK_LOCK);
+ p->mp_reg_block_lock = p_reg_block_lock;
+ p->mp_fld_block_lock_lock =
+ register_get_field(p_reg_block_lock, MAC_PCS_BLOCK_LOCK_LOCK);
+
+ p_reg_stat_pcs_rx =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_STAT_PCS_RX);
+ p->mp_reg_stat_pcs_rx = p_reg_stat_pcs_rx;
+ p->mp_fld_stat_pcs_rx_status =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_STATUS);
+ p->mp_fld_stat_pcs_rx_aligned =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED);
+ p->mp_fld_stat_pcs_rx_aligned_err =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED_ERR);
+ p->mp_fld_stat_pcs_rx_misaligned =
+ register_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_MISALIGNED);
+ p->mp_fld_stat_pcs_rx_internal_local_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT);
+ p->mp_fld_stat_pcs_rx_received_local_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT);
+ p->mp_fld_stat_pcs_rx_local_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_LOCAL_FAULT);
+ p->mp_fld_stat_pcs_rx_remote_fault =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_REMOTE_FAULT);
+ p->mp_fld_stat_pcs_rx_hi_ber =
+ register_get_field(p_reg_stat_pcs_rx,
+ MAC_PCS_STAT_PCS_RX_HI_BER);
+
+ p_reg_stat_pcs_rx_latch =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_STAT_PCS_RX_LATCH);
+ p->mp_reg_stat_pcs_rx_latch = p_reg_stat_pcs_rx_latch;
+ p->mp_fld_stat_pcs_rx_latch_status =
+ register_get_field(p_reg_stat_pcs_rx_latch,
+ MAC_PCS_STAT_PCS_RX_LATCH_STATUS);
+
+ p_reg_vl_demuxed =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_VL_DEMUXED);
+ p->mp_fld_vl_demuxed_lock =
+ register_get_field(p_reg_vl_demuxed, MAC_PCS_VL_DEMUXED_LOCK);
+
+ p_reg_gty_stat =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_STAT);
+ p->mp_fld_gty_stat_tx_rst_done0 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_0);
+ p->mp_fld_gty_stat_tx_rst_done1 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_1);
+ p->mp_fld_gty_stat_tx_rst_done2 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_2);
+ p->mp_fld_gty_stat_tx_rst_done3 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_3);
+ p->mp_fld_gty_stat_rx_rst_done0 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_0);
+ p->mp_fld_gty_stat_rx_rst_done1 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_1);
+ p->mp_fld_gty_stat_rx_rst_done2 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_2);
+ p->mp_fld_gty_stat_rx_rst_done3 =
+ register_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_3);
+
+ p->m_fld_block_lock_lock_mask = 0;
+ p->m_fld_vl_demuxed_lock_mask = 0;
+ p->m_fld_gty_stat_tx_rst_done_mask = 0;
+ p->m_fld_gty_stat_rx_rst_done_mask = 0;
+
+ if (product_id == 9563) {
+ /* NT200A01_2X100 implements 20 virtual lanes */
+ p->m_fld_block_lock_lock_mask = (1 << 20) - 1;
+ /* NT200A01_2X100 implements 20 virtual lanes */
+ p->m_fld_vl_demuxed_lock_mask = (1 << 20) - 1;
+ p->m_fld_gty_stat_tx_rst_done_mask =
+ 1; /* NT200A01_2X100 implements 4 GTY */
+ p->m_fld_gty_stat_rx_rst_done_mask =
+ 1; /* NT200A01_2X100 implements 4 GTY */
+ } else {
+ /* Remember to add new productIds */
+ assert(0);
+ }
+
+ p_reg_pcs_config = module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_MAC_PCS_CONFIG);
+ p->mp_fld_pcs_config_tx_path_rst =
+ register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST);
+ p->mp_fld_pcs_config_rx_path_rst =
+ register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST);
+ p->mp_fld_pcs_config_rx_enable =
+ register_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE);
+ p->mp_fld_pcs_config_rx_force_resync =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC);
+ p->mp_fld_pcs_config_rx_test_pattern =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN);
+ p->mp_fld_pcs_config_tx_enable =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE);
+ p->mp_fld_pcs_config_tx_send_idle =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE);
+ p->mp_fld_pcs_config_tx_send_rfi =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI);
+ p->mp_fld_pcs_config_tx_test_pattern =
+ register_get_field(p_reg_pcs_config,
+ MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN);
+
+ p->mp_reg_gty_loop =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_LOOP);
+ p->mp_fld_gty_loop_gt_loop0 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_0);
+ p->mp_fld_gty_loop_gt_loop1 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_1);
+ p->mp_fld_gty_loop_gt_loop2 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_2);
+ p->mp_fld_gty_loop_gt_loop3 =
+ register_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_3);
+
+ p_reg_phymac_misc =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_PHYMAC_MISC);
+ p->mp_reg_phymac_misc = p_reg_phymac_misc;
+ p->mp_fld_phymac_misc_tx_sel_host =
+ register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_HOST);
+ p->mp_fld_phymac_misc_tx_sel_tfg =
+ register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_TFG);
+ p->mp_fld_phymac_misc_tx_sel_rx_loop =
+ register_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP);
+
+ /* SOP or EOP TIMESTAMP */
+ p->mp_fld_phymac_misc_ts_eop =
+ register_query_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TS_EOP);
+
+ p->mp_reg_link_summary =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_LINK_SUMMARY);
+ p->mp_fld_link_summary_abs =
+ register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_ABS);
+ p->mp_fld_link_summary_nt_phy_link_state =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE);
+ p->mp_fld_link_summary_lh_abs =
+ register_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_LH_ABS);
+ p->mp_fld_link_summary_ll_nt_phy_link_state =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE);
+ p->mp_fld_link_summary_link_down_cnt =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT);
+ p->mp_fld_link_summary_nim_interr =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_NIM_INTERR);
+ p->mp_fld_link_summary_lh_local_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT);
+ p->mp_fld_link_summary_lh_remote_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT);
+ p->mp_fld_link_summary_local_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_LOCAL_FAULT);
+ p->mp_fld_link_summary_remote_fault =
+ register_get_field(p->mp_reg_link_summary,
+ MAC_PCS_LINK_SUMMARY_REMOTE_FAULT);
+
+ p->mp_reg_bip_err =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_BIP_ERR);
+ p->mp_fld_reg_bip_err_bip_err =
+ register_get_field(p->mp_reg_bip_err, MAC_PCS_BIP_ERR_BIP_ERR);
+
+ p->mp_reg_fec_ctrl =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CTRL);
+ p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in =
+ register_get_field(p->mp_reg_fec_ctrl, MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN);
+
+ p->mp_reg_fec_stat =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_STAT);
+ p->mp_field_fec_stat_bypass =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_BYPASS);
+ p->mp_field_fec_stat_valid =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_VALID);
+ p->mp_field_fec_stat_am_lock0 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_0);
+ p->mp_field_fec_stat_am_lock1 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_1);
+ p->mp_field_fec_stat_am_lock2 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_2);
+ p->mp_field_fec_stat_am_lock3 =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_3);
+ p->mp_field_fec_stat_fec_lane_algn =
+ register_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_FEC_LANE_ALGN);
+
+ p->mp_reg_fec_cw_cnt =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CW_CNT);
+ p->mp_field_fec_cw_cnt_cw_cnt =
+ register_get_field(p->mp_reg_fec_cw_cnt, MAC_PCS_FEC_CW_CNT_CW_CNT);
+
+ p->mp_reg_fec_ucw_cnt =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_UCW_CNT);
+ p->mp_field_fec_ucw_cnt_ucw_cnt =
+ register_get_field(p->mp_reg_fec_ucw_cnt, MAC_PCS_FEC_UCW_CNT_UCW_CNT);
+
+ /* GTY_RX_BUF_STAT */
+#ifdef RXBUFSTAT
+ p->mp_reg_gty_rx_buf_stat =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_RX_BUF_STAT);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat0 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat1 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat2 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat3 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2);
+ p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3 =
+ register_get_field(p->mp_reg_gty_rx_buf_stat,
+ MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3);
+#endif
+
+ /* GTY_PRE_CURSOR */
+ p->mp_reg_gty_pre_cursor =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_PRE_CURSOR);
+ p->mp_field_gty_pre_cursor_tx_pre_csr0 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0);
+ p->mp_field_gty_pre_cursor_tx_pre_csr1 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1);
+ p->mp_field_gty_pre_cursor_tx_pre_csr2 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2);
+ p->mp_field_gty_pre_cursor_tx_pre_csr3 =
+ register_get_field(p->mp_reg_gty_pre_cursor,
+ MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3);
+
+ /* GTY_DIFF_CTL */
+ p->mp_reg_gty_diff_ctl =
+ module_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_DIFF_CTL);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2);
+ p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3 =
+ register_get_field(p->mp_reg_gty_diff_ctl,
+ MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3);
+
+ /* GTY_POST_CURSOR */
+ p->mp_reg_gty_post_cursor =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_GTY_POST_CURSOR);
+ p->mp_field_gty_post_cursor_tx_post_csr0 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0);
+ p->mp_field_gty_post_cursor_tx_post_csr1 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1);
+ p->mp_field_gty_post_cursor_tx_post_csr2 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2);
+ p->mp_field_gty_post_cursor_tx_post_csr3 =
+ register_get_field(p->mp_reg_gty_post_cursor,
+ MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3);
+
+ /* GTY_CTL */
+ p->mp_reg_gty_ctl =
+ module_query_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL);
+ if (p->mp_reg_gty_ctl) {
+ p->mp_field_gty_ctl_tx_pol0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_0);
+ p->mp_field_gty_ctl_tx_pol1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_1);
+ p->mp_field_gty_ctl_tx_pol2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_2);
+ p->mp_field_gty_ctl_tx_pol3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_TX_POLARITY_3);
+ } else {
+ p->mp_reg_gty_ctl =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_GTY_CTL_RX);
+ p->mp_reg_gty_ctl_tx =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_GTY_CTL_TX);
+ p->mp_field_gty_ctl_tx_pol0 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_0);
+ p->mp_field_gty_ctl_tx_pol1 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_1);
+ p->mp_field_gty_ctl_tx_pol2 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_2);
+ p->mp_field_gty_ctl_tx_pol3 =
+ register_get_field(p->mp_reg_gty_ctl_tx,
+ MAC_PCS_GTY_CTL_TX_POLARITY_3);
+ }
+ p->mp_field_gty_ctl_rx_pol0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_0);
+ p->mp_field_gty_ctl_rx_pol1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_1);
+ p->mp_field_gty_ctl_rx_pol2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_2);
+ p->mp_field_gty_ctl_rx_pol3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_POLARITY_3);
+ p->mp_field_gty_ctl_rx_lpm_en0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_0);
+ p->mp_field_gty_ctl_rx_lpm_en1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_1);
+ p->mp_field_gty_ctl_rx_lpm_en2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_2);
+ p->mp_field_gty_ctl_rx_lpm_en3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_LPM_EN_3);
+ p->mp_field_gty_ctl_rx_equa_rst0 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_0);
+ p->mp_field_gty_ctl_rx_equa_rst1 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_1);
+ p->mp_field_gty_ctl_rx_equa_rst2 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_2);
+ p->mp_field_gty_ctl_rx_equa_rst3 =
+ register_get_field(p->mp_reg_gty_ctl,
+ MAC_PCS_GTY_CTL_RX_EQUA_RST_3);
+
+ /* DEBOUNCE_CTRL */
+ p->mp_reg_debounce_ctrl =
+ module_get_register(p->mp_mod_mac_pcs,
+ MAC_PCS_DEBOUNCE_CTRL);
+ p->mp_field_debounce_ctrl_nt_port_ctrl =
+ register_get_field(p->mp_reg_debounce_ctrl,
+ MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL);
+
+ p->mp_reg_time_stamp_comp =
+ module_query_register(p->mp_mod_mac_pcs,
+ MAC_PCS_TIMESTAMP_COMP);
+ if (p->mp_reg_time_stamp_comp) {
+ /* TIMESTAMP_COMP */
+ p->mp_field_time_stamp_comp_rx_dly =
+ register_get_field(p->mp_reg_time_stamp_comp,
+ MAC_PCS_TIMESTAMP_COMP_RX_DLY);
+ p->mp_field_time_stamp_comp_tx_dly =
+ register_get_field(p->mp_reg_time_stamp_comp,
+ MAC_PCS_TIMESTAMP_COMP_TX_DLY);
+ }
+ }
+ return 0;
+}
+
+/* wrapper - for ease of use */
+void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p, bool enable)
+{
+ nthw_mac_pcs_set_tx_sel_host(p, enable);
+ nthw_mac_pcs_set_tx_sel_tfg(p, !enable);
+}
+
+void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_rx_enable);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_rx_enable);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_rx_enable);
+}
+
+void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_tx_enable);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_tx_enable);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_tx_enable);
+}
+
+void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_phymac_misc_tx_sel_host);
+ if (enable)
+ field_set_flush(p->mp_fld_phymac_misc_tx_sel_host);
+
+ else
+ field_clr_flush(p->mp_fld_phymac_misc_tx_sel_host);
+}
+
+void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_phymac_misc_tx_sel_tfg);
+ if (enable)
+ field_set_flush(p->mp_fld_phymac_misc_tx_sel_tfg);
+
+ else
+ field_clr_flush(p->mp_fld_phymac_misc_tx_sel_tfg);
+}
+
+void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable)
+{
+ if (p->mp_fld_phymac_misc_ts_eop) {
+ field_get_updated(p->mp_fld_phymac_misc_ts_eop);
+ if (enable)
+ field_set_flush(p->mp_fld_phymac_misc_ts_eop);
+
+ else
+ field_clr_flush(p->mp_fld_phymac_misc_ts_eop);
+ }
+}
+
+bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p)
+{
+ uint32_t block_lock;
+ uint32_t lane_lock;
+
+ block_lock = field_get_updated(p->mp_fld_block_lock_lock) &
+ p->m_fld_block_lock_lock_mask;
+ lane_lock = field_get_updated(p->mp_fld_vl_demuxed_lock) &
+ p->m_fld_vl_demuxed_lock_mask;
+ if (block_lock == p->m_fld_block_lock_lock_mask &&
+ lane_lock == p->m_fld_vl_demuxed_lock_mask)
+ return true;
+
+ return false;
+}
+
+void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_tx_path_rst);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_tx_path_rst);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_tx_path_rst);
+}
+
+void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_rx_path_rst);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_rx_path_rst);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_rx_path_rst);
+}
+
+bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_pcs_config_rx_path_rst);
+}
+
+void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_tx_send_rfi);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_tx_send_rfi);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_tx_send_rfi);
+}
+
+void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable)
+{
+ field_get_updated(p->mp_fld_pcs_config_rx_force_resync);
+ if (enable)
+ field_set_flush(p->mp_fld_pcs_config_rx_force_resync);
+
+ else
+ field_clr_flush(p->mp_fld_pcs_config_rx_force_resync);
+}
+
+bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p)
+{
+ if ((field_get_updated(p->mp_fld_gty_stat_rx_rst_done0) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_rx_rst_done1) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_rx_rst_done2) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_rx_rst_done3) &
+ p->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask)
+ return true;
+
+ else
+ return false;
+}
+
+bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p)
+{
+ if ((field_get_updated(p->mp_fld_gty_stat_tx_rst_done0) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_tx_rst_done1) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_tx_rst_done2) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&
+ (field_get_updated(p->mp_fld_gty_stat_tx_rst_done3) &
+ p->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask)
+ return true;
+
+ else
+ return false;
+}
+
+void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable)
+{
+ register_update(p->mp_reg_gty_loop);
+ if (enable) {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 2);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 2);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 2);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 2);
+ } else {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0);
+ }
+ register_flush(p->mp_reg_gty_loop, 1);
+}
+
+void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable)
+{
+ register_update(p->mp_reg_gty_loop);
+ if (enable) {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 4);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 4);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 4);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 4);
+ } else {
+ field_set_val32(p->mp_fld_gty_loop_gt_loop0, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop1, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop2, 0);
+ field_set_val32(p->mp_fld_gty_loop_gt_loop3, 0);
+ }
+ register_flush(p->mp_reg_gty_loop, 1);
+}
+
+void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p)
+{
+ uint32_t lane_bit_errors[NTHW_MAC_PCS_LANES];
+
+ register_update(p->mp_reg_bip_err);
+ field_get_val(p->mp_fld_reg_bip_err_bip_err, (uint32_t *)lane_bit_errors,
+ ARRAY_SIZE(lane_bit_errors));
+
+#if defined(DEBUG)
+ {
+ uint8_t lane;
+
+ for (lane = 0; lane < c_pcs_lanes; lane++) {
+ if (lane_bit_errors[lane]) {
+ NT_LOG(DBG, NTHW,
+ "Port %u: pcsLane %2u: BIP8 errors: %u\n",
+ p->m_port_no, lane, lane_bit_errors[lane]);
+ }
+ }
+ }
+#else
+ (void)c_pcs_lanes; /* unused - kill warning */
+#endif
+}
+
+void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status)
+{
+ *status = field_get_updated(p->mp_fld_stat_pcs_rx_status) & 0x01;
+}
+
+bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_stat_pcs_rx_hi_ber);
+}
+
+void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs,
+ uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs,
+ uint32_t *p_ll_nt_phy_link_state,
+ uint32_t *p_link_down_cnt, uint32_t *p_nim_interr,
+ uint32_t *p_lh_local_fault,
+ uint32_t *p_lh_remote_fault, uint32_t *p_local_fault,
+ uint32_t *p_remote_fault)
+{
+ register_update(p->mp_reg_link_summary);
+ if (p_abs)
+ *p_abs = field_get_val32(p->mp_fld_link_summary_abs);
+ if (p_nt_phy_link_state) {
+ *p_nt_phy_link_state =
+ field_get_val32(p->mp_fld_link_summary_nt_phy_link_state);
+ }
+ if (p_lh_abs)
+ *p_lh_abs = field_get_val32(p->mp_fld_link_summary_lh_abs);
+ if (p_ll_nt_phy_link_state) {
+ *p_ll_nt_phy_link_state =
+ field_get_val32(p->mp_fld_link_summary_ll_nt_phy_link_state);
+ }
+ if (p_link_down_cnt)
+ *p_link_down_cnt = field_get_val32(p->mp_fld_link_summary_link_down_cnt);
+ if (p_nim_interr)
+ *p_nim_interr = field_get_val32(p->mp_fld_link_summary_nim_interr);
+ if (p_lh_local_fault) {
+ *p_lh_local_fault =
+ field_get_val32(p->mp_fld_link_summary_lh_local_fault);
+ }
+ if (p_lh_remote_fault) {
+ *p_lh_remote_fault =
+ field_get_val32(p->mp_fld_link_summary_lh_remote_fault);
+ }
+ if (p_local_fault)
+ *p_local_fault = field_get_val32(p->mp_fld_link_summary_local_fault);
+ if (p_remote_fault)
+ *p_remote_fault = field_get_val32(p->mp_fld_link_summary_remote_fault);
+}
+
+/*
+ * Returns true if the lane/block lock bits indicate that a reset is required.
+ * This is the case if Block/Lane lock is not all zero but not all set either.
+ */
+bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p)
+{
+ uint32_t block_lock = nthw_mac_pcs_get_fld_block_lock_lock(p);
+ uint32_t lane_lock = nthw_mac_pcs_get_fld_lane_lock_lock(p);
+ uint32_t block_lock_mask = nthw_mac_pcs_get_fld_block_lock_lock_mask(p);
+ uint32_t lane_lock_mask = nthw_mac_pcs_get_fld_lane_lock_lock_mask(p);
+
+ return ((block_lock != 0) && (block_lock != block_lock_mask)) ||
+ ((lane_lock != 0) && (lane_lock != lane_lock_mask));
+}
+
+void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable)
+{
+ NT_LOG(DBG, NTHW, "Port %u: Set FEC: %u\n", p->m_port_no, enable);
+
+ field_get_updated(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in);
+ if (enable) {
+ field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, 0);
+ } else {
+ field_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in,
+ (1 << 5) - 1);
+ }
+
+ /* Both Rx and Tx must be reset for new FEC state to become active */
+ nthw_mac_pcs_rx_path_rst(p, true);
+ nthw_mac_pcs_tx_path_rst(p, true);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+
+ nthw_mac_pcs_rx_path_rst(p, false);
+ nthw_mac_pcs_tx_path_rst(p, false);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+
+#ifdef DEBUG
+ if (enable) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC valid: %u\n", p->m_port_no,
+ field_get_updated(p->mp_field_fec_stat_valid));
+ } else {
+ NT_LOG(DBG, NTHW, "Port %u: FEC bypass: %u\n", p->m_port_no,
+ field_get_updated(p->mp_field_fec_stat_bypass));
+ }
+#endif
+}
+
+bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_field_fec_stat_bypass);
+}
+
+bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_field_fec_stat_valid);
+}
+
+bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_field_fec_stat_fec_lane_algn);
+}
+
+bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_stat);
+ if ((field_get_val32(p->mp_field_fec_stat_am_lock0)) ||
+ (field_get_val32(p->mp_field_fec_stat_am_lock1)) ||
+ (field_get_val32(p->mp_field_fec_stat_am_lock2)) ||
+ (field_get_val32(p->mp_field_fec_stat_am_lock3)))
+ return true;
+ return false;
+}
+
+bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_stat);
+ if ((field_get_val32(p->mp_field_fec_stat_am_lock0)) &&
+ (field_get_val32(p->mp_field_fec_stat_am_lock1)) &&
+ (field_get_val32(p->mp_field_fec_stat_am_lock2)) &&
+ (field_get_val32(p->mp_field_fec_stat_am_lock3)))
+ return true;
+ return false;
+}
+
+void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_stat);
+ NT_LOG(DBG, NTHW,
+ "Port %u: FEC_STAT VALID: %u, AM_LOCK_0: %u, AM_LOCK_1: %u, AM_LOCK_2: %u, AM_LOCK_0: %u, FEC_LANE_ALGN: %u\n",
+ p->m_port_no, field_get_val32(p->mp_field_fec_stat_valid),
+ field_get_val32(p->mp_field_fec_stat_am_lock0),
+ field_get_val32(p->mp_field_fec_stat_am_lock1),
+ field_get_val32(p->mp_field_fec_stat_am_lock2),
+ field_get_val32(p->mp_field_fec_stat_am_lock3),
+ field_get_val32(p->mp_field_fec_stat_fec_lane_algn));
+}
+
+void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_fec_cw_cnt);
+ register_update(p->mp_reg_fec_ucw_cnt);
+
+ if (field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u\n", p->m_port_no,
+ field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt));
+ }
+ if (field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u\n", p->m_port_no,
+ field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt));
+ }
+}
+
+bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p)
+{
+ register_update(p->mp_reg_gty_rx_buf_stat);
+
+ if (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3)) {
+ if (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2) ||
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3)) {
+ NT_LOG(DBG, NTHW,
+ "Port %u: GTY RX_BUF_STAT_0: %u, RX_BUF_STAT_1: %u, RX_BUF_STAT_2: %u, RX_BUF_STAT_3: %u\n",
+ p->m_port_no,
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0),
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1),
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2),
+ field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3));
+
+ return true;
+ }
+ }
+ return false;
+}
+
+void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr,
+ uint8_t tx_diff_ctl, uint8_t tx_post_csr)
+{
+ /* GTY_PRE_CURSOR */
+ register_update(p->mp_reg_gty_pre_cursor);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr0,
+ tx_pre_csr & 0x1F);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr1,
+ tx_pre_csr & 0x1F);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr2,
+ tx_pre_csr & 0x1F);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr3,
+ tx_pre_csr & 0x1F);
+ break;
+ }
+
+ /* GTY_DIFF_CTL */
+ register_update(p->mp_reg_gty_diff_ctl);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0,
+ tx_diff_ctl & 0x1F);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1,
+ tx_diff_ctl & 0x1F);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2,
+ tx_diff_ctl & 0x1F);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3,
+ tx_diff_ctl & 0x1F);
+ break;
+ }
+
+ /* GTY_POST_CURSOR */
+ register_update(p->mp_reg_gty_post_cursor);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr0,
+ tx_post_csr & 0x1F);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr1,
+ tx_post_csr & 0x1F);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr2,
+ tx_post_csr & 0x1F);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr3,
+ tx_post_csr & 0x1F);
+ break;
+ }
+
+ NT_LOG(DBG, NTHW,
+ "Port %u, lane %u: GTY txPreCsr: %d, txDiffCtl: %d, txPostCsr: %d\n",
+ p->m_port_no, lane, tx_pre_csr, tx_diff_ctl, tx_post_csr);
+}
+
+/*
+ * Set receiver equalization mode
+ * 0: enable DFE
+ * mode 1: enable LPM
+ *
+ * See UltraScale Architecture GTY Transceivers www.xilinx.com page 181,
+ * UG578 (v1.1) November 24, 2015
+ */
+void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode)
+{
+ register_update(p->mp_reg_gty_ctl);
+ field_set_val32(p->mp_field_gty_ctl_rx_lpm_en0, mode & 0x1);
+ field_set_val32(p->mp_field_gty_ctl_rx_lpm_en1, mode & 0x1);
+ field_set_val32(p->mp_field_gty_ctl_rx_lpm_en2, mode & 0x1);
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_lpm_en3, mode & 0x1);
+
+ /* Toggle reset */
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 1);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 1);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 1);
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 1);
+
+ NT_OS_WAIT_USEC(1000); /* 1ms */
+
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 0);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 0);
+ field_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 0);
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 0);
+
+ NT_LOG(DBG, NTHW, "Port %u: GTY receiver mode: %s\n", p->m_port_no,
+ (mode == c_mac_pcs_receiver_mode_dfe ? "DFE" : "LPM"));
+}
+
+void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap)
+{
+ register_update(p->mp_reg_gty_ctl);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol0, swap);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol1, swap);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol2, swap);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_ctl_tx_pol3, swap);
+ break;
+ }
+ NT_LOG(DBG, NTHW, "Port %u: set GTY Tx lane (%d) polarity: %d\n",
+ p->m_port_no, lane, swap);
+}
+
+void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap)
+{
+ register_update(p->mp_reg_gty_ctl);
+ switch (lane) {
+ case 0:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol0, swap);
+ break;
+ case 1:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol1, swap);
+ break;
+ case 2:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol2, swap);
+ break;
+ case 3:
+ field_set_val_flush32(p->mp_field_gty_ctl_rx_pol3, swap);
+ break;
+ }
+ NT_LOG(DBG, NTHW, "Port %u: set GTY Rx lane (%d) polarity: %d\n",
+ p->m_port_no, lane, swap);
+}
+
+void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode)
+{
+ field_get_updated(p->mp_field_debounce_ctrl_nt_port_ctrl);
+ field_set_val_flush32(p->mp_field_debounce_ctrl_nt_port_ctrl, mode);
+}
+
+void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly)
+{
+ if (p->mp_field_time_stamp_comp_rx_dly) {
+ field_get_updated(p->mp_field_time_stamp_comp_rx_dly);
+ field_set_val_flush32(p->mp_field_time_stamp_comp_rx_dly, rx_dly);
+ }
+}
+
+void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no)
+{
+ p->m_port_no = port_no;
+}
+
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_block_lock_lock);
+}
+
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p)
+{
+ return p->m_fld_block_lock_lock_mask;
+}
+
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p)
+{
+ return field_get_updated(p->mp_fld_vl_demuxed_lock);
+}
+
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p)
+{
+ return p->m_fld_vl_demuxed_lock_mask;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h
new file mode 100644
index 0000000000..08197f8b9e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h
@@ -0,0 +1,261 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_MAC_PCS_H_
+#define NTHW_MAC_PCS_H_
+
+enum nthw_mac_pcs_led_mode_e {
+ NTHW_MAC_PCS_LED_AUTO = 0x00,
+ NTHW_MAC_PCS_LED_ON = 0x01,
+ NTHW_MAC_PCS_LED_OFF = 0x02,
+ NTHW_MAC_PCS_LED_PORTID = 0x03,
+};
+
+#define nthw_mac_pcs_receiver_mode_dfe (0)
+#define nthw_mac_pcs_receiver_mode_lpm (1)
+
+struct nthw_mac_pcs {
+ uint8_t m_port_no;
+
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_mac_pcs;
+ int mn_instance;
+
+ /* Block lock status */
+ nt_field_t *mp_fld_block_lock_lock;
+ uint32_t m_fld_block_lock_lock_mask;
+
+ /* Lane lock status */
+ nt_field_t *mp_fld_vl_demuxed_lock;
+ uint32_t m_fld_vl_demuxed_lock_mask;
+
+ /* GTY_STAT */
+ nt_field_t *mp_fld_gty_stat_rx_rst_done0;
+ nt_field_t *mp_fld_gty_stat_rx_rst_done1;
+ nt_field_t *mp_fld_gty_stat_rx_rst_done2;
+ nt_field_t *mp_fld_gty_stat_rx_rst_done3;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done0;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done1;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done2;
+ nt_field_t *mp_fld_gty_stat_tx_rst_done3;
+ uint32_t m_fld_gty_stat_rx_rst_done_mask;
+ uint32_t m_fld_gty_stat_tx_rst_done_mask;
+
+ /* GTY_LOOP */
+ nt_register_t *mp_reg_gty_loop;
+ nt_field_t *mp_fld_gty_loop_gt_loop0;
+ nt_field_t *mp_fld_gty_loop_gt_loop1;
+ nt_field_t *mp_fld_gty_loop_gt_loop2;
+ nt_field_t *mp_fld_gty_loop_gt_loop3;
+
+ /* MAC_PCS_CONFIG */
+ nt_field_t *mp_fld_pcs_config_tx_path_rst;
+ nt_field_t *mp_fld_pcs_config_rx_path_rst;
+ nt_field_t *mp_fld_pcs_config_rx_enable;
+ nt_field_t *mp_fld_pcs_config_rx_force_resync;
+ nt_field_t *mp_fld_pcs_config_rx_test_pattern;
+ nt_field_t *mp_fld_pcs_config_tx_enable;
+ nt_field_t *mp_fld_pcs_config_tx_send_idle;
+ nt_field_t *mp_fld_pcs_config_tx_send_rfi;
+ nt_field_t *mp_fld_pcs_config_tx_test_pattern;
+
+ /* STAT PCS */
+ nt_field_t *mp_fld_stat_pcs_rx_status;
+ nt_field_t *mp_fld_stat_pcs_rx_aligned;
+ nt_field_t *mp_fld_stat_pcs_rx_aligned_err;
+ nt_field_t *mp_fld_stat_pcs_rx_misaligned;
+ nt_field_t *mp_fld_stat_pcs_rx_internal_local_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_received_local_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_local_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_remote_fault;
+ nt_field_t *mp_fld_stat_pcs_rx_hi_ber;
+
+ /* STAT_PCS_RX_LATCH */
+ nt_field_t *mp_fld_stat_pcs_rx_latch_status;
+
+ /* PHYMAC_MISC */
+ nt_field_t *mp_fld_phymac_misc_tx_sel_host;
+ nt_field_t *mp_fld_phymac_misc_tx_sel_tfg;
+ nt_field_t *mp_fld_phymac_misc_tx_sel_rx_loop;
+ nt_field_t *mp_fld_phymac_misc_ts_eop;
+
+ /* LINK_SUMMARY */
+ nt_register_t *mp_reg_link_summary;
+ nt_field_t *mp_fld_link_summary_abs;
+ nt_field_t *mp_fld_link_summary_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_lh_abs;
+ nt_field_t *mp_fld_link_summary_ll_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_link_down_cnt;
+ nt_field_t *mp_fld_link_summary_nim_interr;
+ nt_field_t *mp_fld_link_summary_lh_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_remote_fault;
+ nt_field_t *mp_fld_link_summary_local_fault;
+ nt_field_t *mp_fld_link_summary_remote_fault;
+
+ /* BIP_ERR */
+ nt_register_t *mp_reg_bip_err;
+ nt_field_t *mp_fld_reg_bip_err_bip_err;
+
+ /* FEC_CTRL */
+ nt_register_t *mp_reg_fec_ctrl;
+ nt_field_t *mp_field_fec_ctrl_reg_rs_fec_ctrl_in;
+
+ /* FEC_STAT */
+ nt_register_t *mp_reg_fec_stat;
+ nt_field_t *mp_field_fec_stat_bypass;
+ nt_field_t *mp_field_fec_stat_valid;
+ nt_field_t *mp_field_fec_stat_am_lock0;
+ nt_field_t *mp_field_fec_stat_am_lock1;
+ nt_field_t *mp_field_fec_stat_am_lock2;
+ nt_field_t *mp_field_fec_stat_am_lock3;
+ nt_field_t *mp_field_fec_stat_fec_lane_algn;
+
+ /* FEC Corrected code word count */
+ nt_register_t *mp_reg_fec_cw_cnt;
+ nt_field_t *mp_field_fec_cw_cnt_cw_cnt;
+
+ /* FEC Uncorrected code word count */
+ nt_register_t *mp_reg_fec_ucw_cnt;
+ nt_field_t *mp_field_fec_ucw_cnt_ucw_cnt;
+
+ /* GTY_RX_BUF_STAT */
+ nt_register_t *mp_reg_gty_rx_buf_stat;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat0;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat1;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat2;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat3;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed0;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed1;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed2;
+ nt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed3;
+
+ /* GTY_PRE_CURSOR */
+ nt_register_t *mp_reg_gty_pre_cursor;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr0;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr1;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr2;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr3;
+
+ /* GTY_DIFF_CTL */
+ nt_register_t *mp_reg_gty_diff_ctl;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl0;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl1;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl2;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl3;
+
+ /* GTY_POST_CURSOR */
+ nt_register_t *mp_reg_gty_post_cursor;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr0;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr1;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr2;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr3;
+
+ /* GTY_CTL */
+ nt_register_t *mp_reg_gty_ctl;
+ nt_register_t *mp_reg_gty_ctl_tx;
+ nt_field_t *mp_field_gty_ctl_tx_pol0;
+ nt_field_t *mp_field_gty_ctl_tx_pol1;
+ nt_field_t *mp_field_gty_ctl_tx_pol2;
+ nt_field_t *mp_field_gty_ctl_tx_pol3;
+ nt_field_t *mp_field_gty_ctl_rx_pol0;
+ nt_field_t *mp_field_gty_ctl_rx_pol1;
+ nt_field_t *mp_field_gty_ctl_rx_pol2;
+ nt_field_t *mp_field_gty_ctl_rx_pol3;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en0;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en1;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en2;
+ nt_field_t *mp_field_gty_ctl_rx_lpm_en3;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst0;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst1;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst2;
+ nt_field_t *mp_field_gty_ctl_rx_equa_rst3;
+
+ /* DEBOUNCE_CTRL */
+ nt_register_t *mp_reg_debounce_ctrl;
+ nt_field_t *mp_field_debounce_ctrl_nt_port_ctrl;
+
+ /* TIMESTAMP_COMP */
+ nt_register_t *mp_reg_time_stamp_comp;
+ nt_field_t *mp_field_time_stamp_comp_rx_dly;
+ nt_field_t *mp_field_time_stamp_comp_tx_dly;
+
+ /* STAT_PCS_RX */
+ nt_register_t *mp_reg_stat_pcs_rx;
+
+ /* STAT_PCS_RX */
+ nt_register_t *mp_reg_stat_pcs_rx_latch;
+
+ /* PHYMAC_MISC */
+ nt_register_t *mp_reg_phymac_misc;
+
+ /* BLOCK_LOCK */
+ nt_register_t *mp_reg_block_lock;
+};
+
+typedef struct nthw_mac_pcs nthw_mac_pcs_t;
+typedef struct nthw_mac_pcs nthw_mac_pcs;
+
+nthw_mac_pcs_t *nthw_mac_pcs_new(void);
+int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_mac_pcs_delete(nthw_mac_pcs_t *p);
+
+bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable);
+bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable);
+bool nthw_mac_pcs_is_dd_r3_calib_done(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p,
+ bool enable); /* wrapper - for ease of use */
+void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable);
+void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status);
+bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p);
+
+void nthw_mac_pcs_get_link_summary1(nthw_mac_pcs_t *p, uint32_t *p_status,
+ uint32_t *p_status_latch, uint32_t *p_aligned,
+ uint32_t *p_local_fault, uint32_t *p_remote_fault);
+
+void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs,
+ uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs,
+ uint32_t *p_ll_nt_phy_link_state,
+ uint32_t *p_link_down_cnt, uint32_t *p_nim_interr,
+ uint32_t *p_lh_local_fault,
+ uint32_t *p_lh_remote_fault, uint32_t *p_local_fault,
+ uint32_t *p_remote_fault);
+
+bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable);
+bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p);
+bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p);
+void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr,
+ uint8_t tx_diff_ctl, uint8_t tx_post_csr);
+void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap);
+void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap);
+void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode);
+void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode);
+void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly);
+void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no);
+
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p);
+uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p);
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p);
+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p);
+
+#endif /* NTHW_MAC_PCS_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c
new file mode 100644
index 0000000000..d8e1f0de5d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c
@@ -0,0 +1,1631 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_mac_pcs_xxv.h"
+
+static void nthw_mac_pcs_xxv_field_set_or_clr_flush(const nt_field_t *f, bool set)
+{
+ if (f) {
+ field_get_updated(f);
+ if (set)
+ field_set_flush(f);
+ else
+ field_clr_flush(f);
+ }
+}
+
+nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void)
+{
+ nthw_mac_pcs_xxv_t *p = malloc(sizeof(nthw_mac_pcs_xxv_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_mac_pcs_xxv_t));
+ return p;
+}
+
+void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_mac_pcs_xxv_t));
+ free(p);
+ }
+}
+
+uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return index == 0 ? (uint8_t)p->mn_instance : index;
+}
+
+void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no)
+{
+ p->m_port_no = port_no;
+}
+
+void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p,
+ uint32_t *p_abs, uint32_t *p_nt_phy_link_state,
+ uint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt,
+ uint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault,
+ uint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault,
+ uint8_t index)
+{
+ struct nthw_mac_pcs_xxv__registers_fields *r =
+ &p->regs[index]; /* register and fields */
+
+ assert(p);
+
+ register_update(r->mp_reg_link_summary);
+ if (p_abs)
+ *p_abs = field_get_val32(r->mp_fld_link_summary_abs);
+ if (p_nt_phy_link_state) {
+ *p_nt_phy_link_state =
+ field_get_val32(r->mp_fld_link_summary_nt_phy_link_state);
+ }
+ if (p_lh_abs)
+ *p_lh_abs = field_get_val32(r->mp_fld_link_summary_lh_abs);
+ if (p_ll_nt_phy_link_state) {
+ *p_ll_nt_phy_link_state =
+ field_get_val32(r->mp_fld_link_summary_ll_nt_phy_link_state);
+ }
+ if (p_link_down_cnt)
+ *p_link_down_cnt = field_get_val32(r->mp_fld_link_summary_link_down_cnt);
+ if (p_nim_interr)
+ *p_nim_interr = field_get_val32(r->mp_fld_link_summary_nim_interr);
+ if (p_lh_local_fault) {
+ *p_lh_local_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_local_fault);
+ }
+ if (p_lh_remote_fault) {
+ *p_lh_remote_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_remote_fault);
+ }
+ if (p_lh_internal_local_fault) {
+ *p_lh_internal_local_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_internal_local_fault);
+ }
+ if (p_lh_received_local_fault) {
+ *p_lh_received_local_fault =
+ field_get_val32(r->mp_fld_link_summary_lh_received_local_fault);
+ }
+}
+
+void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_force_resync;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_gt_data;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_gt_data;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_an_lt;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_speed_ctrl;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_rfi;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_lfi;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi,
+ bool enable_rfi, uint8_t index)
+{
+ register_update(p->regs[index].mp_reg_core_conf);
+ field_set_val32(p->regs[index].mp_fld_core_conf_tx_send_lfi, enable_lfi);
+ field_set_val32(p->regs[index].mp_fld_core_conf_tx_send_rfi, enable_rfi);
+ register_flush(p->regs[index].mp_reg_core_conf, 1);
+}
+
+bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en;
+
+ /* NOTE: DFE is enabled when LPM is disabled */
+ return !field_get_updated(f);
+}
+
+void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en;
+ const bool set_dfe =
+ !enable; /* NOTE: Enable DFE mode means setting LPM = 0 */
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, set_dfe);
+
+ /* Toggle GTY_CTL_RX->EQUA_RST to 1 and 0 to assert new LPM_EN setting */
+ f = p->regs[index].mp_fld_gty_ctl_rx_equa_rst;
+ field_get_updated(f);
+ field_set_val_flush32(f, 1); /* Assert GTH SOFT RESET */
+ field_get_updated(f);
+ field_set_val_flush32(f, 0); /* De-Assert GTH SOFT RESET */
+ field_get_updated(f);
+}
+
+void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_polarity;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_polarity;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_inhibit;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_gty_loop_gt_loop;
+
+ field_get_updated(f);
+ field_set_val_flush32(f, enable ? 2U : 0U);
+}
+
+void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_line_loopback;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_rx_rst);
+}
+
+bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_tx_rst);
+}
+
+/*
+ * QPLL lock signal.
+ * For cores capable of 10G only, there are only 1 QPLL. For cores capable of
+ * 10G/25G, there are 2 QPLLs.
+ */
+bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return (field_get_updated(p->regs[index].mp_fld_sub_rst_status_qpll_lock) ==
+ 3);
+}
+
+bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return (nthw_mac_pcs_xxv_is_qpll_lock(p, index) &&
+ !nthw_mac_pcs_xxv_is_user_rx_rst(p, index) &&
+ !nthw_mac_pcs_xxv_is_user_tx_rst(p, index));
+}
+
+bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_aneg_config_enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_idle;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_ins_fcs;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g;
+
+ return field_get_updated(f) != 0; /* 0 = 25g, 1 = 10g */
+}
+
+void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_link_speed_toggle;
+
+ field_get_updated(f);
+ field_set_flush(f);
+}
+
+void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_rs_fec_conf_rs_fec_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index)
+{
+ const nt_field_t *const f =
+ p->regs[index].mp_field_debounce_ctrl_nt_port_ctrl;
+
+ field_get_updated(f);
+ field_set_val_flush32(f, mode);
+}
+
+void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_mac_pcs;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_mac_pcs;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ register_update(p->regs[index].mp_reg_rs_fec_ccw);
+ register_update(p->regs[index].mp_reg_rs_fec_ucw);
+
+ if (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_CW_CNT: %u", p->m_port_no,
+ field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt));
+ }
+ if (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt)) {
+ NT_LOG(DBG, NTHW, "Port %u: FEC_UCW_CNT: %u", p->m_port_no,
+ field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt));
+ }
+}
+
+void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly,
+ uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_timestamp_comp_rx_dly);
+ field_set_val_flush32(p->regs[index].mp_field_timestamp_comp_rx_dly, rx_dly);
+}
+
+void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly,
+ uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_timestamp_comp_tx_dly);
+ field_set_val_flush32(p->regs[index].mp_field_timestamp_comp_tx_dly, tx_dly);
+}
+
+void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_core_conf_ts_at_eop;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl);
+ field_set_val_flush32(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl,
+ value);
+}
+
+void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr);
+ field_set_val_flush32(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr, value);
+}
+
+void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)
+{
+ field_get_updated(p->regs[index].mp_field_gty_post_cursor_tx_post_csr);
+ field_set_val_flush32(p->regs[index].mp_field_gty_post_cursor_tx_post_csr,
+ value);
+}
+
+void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_lt_conf_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec91_request;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_rs_fec_request;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec74_request;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_enable;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index)
+{
+ const nt_field_t *const f = p->regs[index].mp_fld_aneg_config_bypass;
+
+ nthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);
+}
+
+void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode,
+ uint8_t index)
+{
+ if (dac_mode == NTHW_MAC_PCS_XXV_DAC_OFF) {
+ nthw_mac_pcs_xxv_reset_an_lt(p, false, index);
+ nthw_mac_pcs_xxv_set_aneg_config_enable(p, false, index);
+ nthw_mac_pcs_xxv_set_aneg_config_bypass(p, true, index);
+ nthw_mac_pcs_xxv_set_lt_conf_enable(p, false, index);
+ nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, true, index);
+ nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, true, index);
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p, true, index);
+ nthw_mac_pcs_xxv_reset_tx_gt_data(p, true, index);
+ nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, false, index);
+ nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, false, index);
+ nthw_mac_pcs_xxv_reset_rx_gt_data(p, false, index);
+ nthw_mac_pcs_xxv_reset_tx_gt_data(p, false, index);
+
+ return;
+ }
+ assert(0); /* If you end up here you need to implement other DAC modes */
+}
+
+bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_fec74_lock);
+}
+
+bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index)
+{
+ return field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_rsfec_lane_alignment);
+}
+
+int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance,
+ int n_channels)
+{
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_MAC_PCS_XXV, n_instance);
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ const bool m_mac8x10_g = false;
+ nt_module_t *module = p_mod;
+ uint64_t n_module_version_packed64 = -1;
+ nt_register_t *r;
+ nt_register_t *(*get_register)(nt_module_t *, uint32_t) =
+ module_get_register;
+ nt_field_t *(*get_field)(const nt_register_t *, uint32_t) =
+ register_get_field;
+ nt_field_t *(*query_field)(const nt_register_t *, uint32_t) =
+ register_query_field;
+ struct nthw_mac_pcs_xxv__registers_fields *rf;
+
+ if (p == NULL)
+ return (p_mod == NULL ? -1 : 0);
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW,
+ "%s: MAC_PCS_XXV instance=%d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_mac_pcs_xxv = p_mod;
+
+ memset(p->regs, 0, sizeof(p->regs));
+
+ n_module_version_packed64 = module_get_version_packed64(p->mp_mod_mac_pcs_xxv);
+ switch (n_module_version_packed64) {
+ case (0UL << 32) | 0UL: /* 0.0 */
+ case (0UL << 32) | 1UL: /* 0.1 */
+ case (0UL << 32) | 2UL: /* 0.2 */
+ NT_LOG(DBG, NTHW,
+ "%s: MAC_PCS_XXV instance=%d: version=0x%08lX\n",
+ p_adapter_id_str, p->mn_instance, n_module_version_packed64);
+ break;
+ default:
+ NT_LOG(ERR, NTHW,
+ "%s: MAC_PCS_XXV instance=%d: version=0x%08lX: unsupported module version\n",
+ p_adapter_id_str, p->mn_instance, n_module_version_packed64);
+ return -1;
+ }
+
+ assert(n_channels == 1 || n_channels == 2 || n_channels == 4);
+
+ /* Register MAC_PCS_XXV_CORE_CONF_0 -- MAC_PCS_XXV_CORE_CONF_3 */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_0);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_1);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_2);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+ r = get_register(module, MAC_PCS_XXV_CORE_CONF_3);
+
+ rf->mp_reg_core_conf = r;
+ rf->mp_fld_core_conf_rx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE);
+ rf->mp_fld_core_conf_rx_force_resync =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC);
+ rf->mp_fld_core_conf_tx_enable =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE);
+ rf->mp_fld_core_conf_tx_ins_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS);
+ rf->mp_fld_core_conf_tx_ign_fcs =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS);
+ rf->mp_fld_core_conf_tx_send_lfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI);
+ rf->mp_fld_core_conf_tx_send_rfi =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI);
+ rf->mp_fld_core_conf_tx_send_idle =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE);
+ rf->mp_fld_core_conf_inline_mode =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE);
+ rf->mp_fld_core_conf_line_loopback =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK);
+ rf->mp_fld_core_conf_ts_at_eop =
+ get_field(r, MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP);
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_ANEG_CONFIG_0 -- MAC_PCS_XXV_ANEG_CONFIG_3
+ * and MAC_PCS_XXV_ANEG_ABILITY_0 -- MAC_PCS_XXV_ANEG_ABILITY_3
+ * and MAC_PCS_XXV_LT_CONF_0 -- MAC_PCS_XXV_LT_CONF_3
+ */
+ if (!m_mac8x10_g && n_channels < 4) {
+ /* 2 x 10 25 G */
+ /* ANEG_CONFIG */
+ rf = &p->regs[0];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_0);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_0);
+ rf->mp_reg_aneg_ability = r;
+
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr) {
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S);
+ if (!rf->mp_fld_aneg_ability25_g_base_crs) {
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr1) {
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1);
+ }
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_0);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_0_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_0_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_0_SEED);
+ }
+
+ if (!m_mac8x10_g && n_channels >= 2) {
+ /* 2 x 10 25 G */
+ /* ANEG_CONFIG */
+
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_1);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_1);
+ rf->mp_reg_aneg_ability = r;
+
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr) {
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S);
+ if (!rf->mp_fld_aneg_ability25_g_base_crs) {
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S);
+ }
+
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ query_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1);
+ if (!rf->mp_fld_aneg_ability25_g_base_cr1) {
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1);
+ }
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_1);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_1_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_1_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_1_SEED);
+ }
+
+ if (!m_mac8x10_g && n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_2);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_2);
+ rf->mp_reg_aneg_ability = r;
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR);
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S);
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1);
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_2);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_2_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_2_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_2_SEED);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+
+ r = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_3);
+ rf->mp_reg_aneg_config = r;
+ rf->mp_fld_aneg_config_enable =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE);
+ rf->mp_fld_aneg_config_bypass =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS);
+ rf->mp_fld_aneg_config_restart =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RESTART);
+ rf->mp_fld_aneg_config_pseudo =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO);
+ rf->mp_fld_aneg_config_nonce_seed =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED);
+ rf->mp_fld_aneg_config_remote_fault =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT);
+ rf->mp_fld_aneg_config_pause =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE);
+ rf->mp_fld_aneg_config_asmdir =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR);
+ rf->mp_fld_aneg_config_fec74_request10_g =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G);
+ rf->mp_fld_aneg_config_hide_fec74 =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74);
+ rf->mp_fld_aneg_config_fec74_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST);
+ rf->mp_fld_aneg_config_fec91_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST);
+ rf->mp_fld_aneg_config_fec91_ability =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY);
+ rf->mp_fld_aneg_config_rs_fec_request =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST);
+ rf->mp_fld_aneg_config_sw_fec_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE);
+ rf->mp_fld_aneg_config_sw_speed_overwrite =
+ get_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE);
+
+ /* ANEG_ABILITY */
+ r = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_3);
+ rf->mp_reg_aneg_ability = r;
+ rf->mp_fld_aneg_ability25_g_base_cr =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR);
+ rf->mp_fld_aneg_ability25_g_base_crs =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S);
+ rf->mp_fld_aneg_ability25_g_base_cr1 =
+ get_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1);
+
+ /* LT_CONF */
+ r = get_register(module, MAC_PCS_XXV_LT_CONF_3);
+ rf->mp_reg_lt_conf = r;
+ rf->mp_fld_lt_conf_enable =
+ get_field(r, MAC_PCS_XXV_LT_CONF_3_ENABLE);
+ rf->mp_fld_lt_conf_restart =
+ get_field(r, MAC_PCS_XXV_LT_CONF_3_RESTART);
+ rf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_3_SEED);
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_SUB_RST_0 -- MAC_PCS_XXV_SUB_RST_3
+ * and MAC_PCS_XXV_SUB_RST_STATUS_0 -- MAC_PCS_XXV_SUB_RST_STATUS_3
+ */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_0);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_0_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_0);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_1);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_1_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_1);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_2);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_2_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_2);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_3);
+
+ rf->mp_reg_sub_rst = r;
+ rf->mp_fld_sub_rst_rx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS);
+ rf->mp_fld_sub_rst_tx_mac_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS);
+ rf->mp_fld_sub_rst_rx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA);
+ rf->mp_fld_sub_rst_tx_gt_data =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA);
+ rf->mp_fld_sub_rst_rx_buf =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_BUF);
+ rf->mp_fld_sub_rst_rx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PMA);
+ rf->mp_fld_sub_rst_tx_pma =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PMA);
+ rf->mp_fld_sub_rst_rx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PCS);
+ rf->mp_fld_sub_rst_tx_pcs =
+ get_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PCS);
+ rf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_3_AN_LT);
+ rf->mp_fld_sub_rst_speed_ctrl =
+ query_field(r, MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_3);
+ rf->mp_reg_sub_rst_status = r;
+ rf->mp_fld_sub_rst_status_user_rx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST);
+ rf->mp_fld_sub_rst_status_user_tx_rst =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST);
+ rf->mp_fld_sub_rst_status_qpll_lock =
+ get_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK);
+ }
+
+ /* Registers MAC_PCS_XXV_LINK_SUMMARY_0 -- MAC_PCS_XXV_LINK_SUMMARY_3 */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_0);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_1);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_2);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+ r = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_3);
+
+ rf->mp_reg_link_summary = r;
+ rf->mp_fld_link_summary_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_ll_nt_phy_link_state =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE);
+ rf->mp_fld_link_summary_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_ABS);
+ rf->mp_fld_link_summary_lh_abs =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS);
+ rf->mp_fld_link_summary_link_down_cnt =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT);
+ if (!m_mac8x10_g) {
+ rf->mp_fld_link_summary_ll_rx_fec74_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK);
+ rf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER);
+ rf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT);
+ rf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE);
+ }
+ rf->mp_fld_link_summary_ll_rx_block_lock =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK);
+ rf->mp_fld_link_summary_lh_rx_high_bit_error_rate =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE);
+ ;
+ rf->mp_fld_link_summary_lh_internal_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_received_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_local_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT);
+ rf->mp_fld_link_summary_lh_remote_fault =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT);
+ rf->mp_fld_link_summary_nim_interr =
+ get_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR);
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_GTY_LOOP_0 -- MAC_PCS_XXV_GTY_LOOP_3
+ * and MAC_PCS_XXV_GTY_CTL_RX_0 -- MAC_PCS_XXV_GTY_CTL_RX_3
+ * and MAC_PCS_XXV_GTY_CTL_TX_0 -- MAC_PCS_XXV_GTY_CTL_TX_3
+ * and MAC_PCS_XXV_LINK_SPEED_0 -- MAC_PCS_XXV_LINK_SPEED_3
+ * and MAC_PCS_XXV_RS_FEC_CONF_0 -- MAC_PCS_XXV_RS_FEC_CONF_0
+ */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_0);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_0);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_0);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_0);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_0);
+
+ rf->mp_fld_link_speed10_g =
+ query_field(r, MAC_PCS_XXV_LINK_SPEED_0_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_0_10G);
+ }
+
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_0_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_0);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_0);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_0);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT);
+ }
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_1);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_1);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_1);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_1);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_1);
+
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_1_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_1_10G);
+ }
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_1_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_1);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_1);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_1);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT);
+ }
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_2);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_2);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_2);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_2);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_2);
+
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_2_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_2_10G);
+ }
+
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_2_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_2);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_2);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_2);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT);
+ }
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+
+ r = get_register(module, MAC_PCS_XXV_GTY_LOOP_3);
+ rf->mp_reg_gty_loop = r;
+ rf->mp_fld_gty_loop_gt_loop =
+ get_field(r, MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_3);
+ rf->mp_reg_gty_ctl_rx = r;
+ rf->mp_fld_gty_ctl_rx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY);
+ rf->mp_fld_gty_ctl_rx_lpm_en =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN);
+ rf->mp_fld_gty_ctl_rx_equa_rst =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST);
+
+ r = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_3);
+ rf->mp_fld_gty_ctl_tx_polarity =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY);
+ rf->mp_fld_gty_ctl_tx_inhibit =
+ get_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT);
+
+ if (!m_mac8x10_g) {
+ r = get_register(module, MAC_PCS_XXV_LINK_SPEED_3);
+ rf->mp_reg_link_speed =
+ get_register(module, MAC_PCS_XXV_LINK_SPEED_3);
+
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_3_SPEED);
+ if (!rf->mp_fld_link_speed10_g) {
+ rf->mp_fld_link_speed10_g =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_3_10G);
+ }
+ rf->mp_fld_link_speed_toggle =
+ get_field(r, MAC_PCS_XXV_LINK_SPEED_3_TOGGLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_3);
+ rf->mp_reg_rs_fec_conf = r;
+ rf->mp_fld_rs_fec_conf_rs_fec_enable =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_3);
+ rf->mp_reg_rs_fec_ccw = r;
+ rf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT);
+
+ r = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_3);
+ rf->mp_reg_rs_fec_ucw = r;
+ rf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =
+ get_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT);
+ }
+ }
+
+ /*
+ * Registers MAC_PCS_XXV_DEBOUNCE_CTRL_0 -- MAC_PCS_XXV_DEBOUNCE_CTRL_3
+ * and MAC_PCS_XXV_TIMESTAMP_COMP_0 -- MAC_PCS_XXV_TIMESTAMP_COMP_3
+ * and MAC_PCS_XXV_GTY_PRE_CURSOR_0 -- MAC_PCS_XXV_GTY_PRE_CURSOR_3
+ * and MAC_PCS_XXV_GTY_DIFF_CTL_0 -- MAC_PCS_XXV_GTY_DIFF_CTL_0
+ * and MAC_PCS_XXV_GTY_POST_CURSOR_0 -- MAC_PCS_XXV_GTY_POST_CURSOR_3
+ */
+ if (n_channels < 4) {
+ /* Initialize regs/fields for sub-module/channel 0 */
+ rf = &p->regs[0];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_0);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_0);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_0);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_0);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_0);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR);
+ }
+
+ if (n_channels >= 2) {
+ /* Initialize regs/fields for sub-module/channel 1 */
+ rf = &p->regs[1];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_1);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_1);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_1);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_1);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_1);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR);
+ }
+
+ if (n_channels == 4) {
+ /* Initialize regs/fields for sub-module/channel 2 */
+ rf = &p->regs[2];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_2);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_2);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_2);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_2);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_2);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR);
+
+ /* Initialize regs/fields for sub-module/channel 3 */
+ rf = &p->regs[3];
+
+ r = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_3);
+
+ rf->mp_reg_debounce_ctrl = r;
+ rf->mp_field_debounce_ctrl_nt_port_ctrl =
+ get_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL);
+
+ r = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_3);
+ rf->mp_reg_timestamp_comp = r;
+ rf->mp_field_timestamp_comp_rx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY);
+ rf->mp_field_timestamp_comp_tx_dly =
+ get_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY);
+
+ /* GTY_PRE_CURSOR */
+ r = get_register(p->mp_mod_mac_pcs_xxv,
+ MAC_PCS_XXV_GTY_PRE_CURSOR_3);
+ rf->mp_reg_gty_pre_cursor = r;
+ rf->mp_field_gty_pre_cursor_tx_pre_csr =
+ get_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR);
+
+ /* GTY_DIFF_CTL */
+ r = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_3);
+ rf->mp_reg_gty_diff_ctl = r;
+ rf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =
+ get_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL);
+
+ /* GTY_POST_CURSOR */
+ r = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_3);
+ rf->mp_reg_gty_post_cursor = r;
+ rf->mp_field_gty_post_cursor_tx_post_csr =
+ get_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR);
+ }
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h
new file mode 100644
index 0000000000..5a38494f7e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_MAC_PCS_XXV_H_
+#define NTHW_MAC_PCS_XXV_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "nthw_fpga_model.h"
+
+enum nthw_mac_pcs_xxv_led_mode_e {
+ NTHW_MAC_PCS_XXV_LED_AUTO = 0x00,
+ NTHW_MAC_PCS_XXV_LED_ON = 0x01,
+ NTHW_MAC_PCS_XXV_LED_OFF = 0x02,
+ NTHW_MAC_PCS_XXV_LED_PORTID = 0x03,
+};
+
+enum nthw_mac_pcs_xxv_dac_mode_e {
+ NTHW_MAC_PCS_XXV_DAC_OFF = 0x00,
+ NTHW_MAC_PCS_XXV_DAC_CA_25G_N = 0x01,
+ NTHW_MAC_PCS_XXV_DAC_CA_25G_S = 0x02,
+ NTHW_MAC_PCS_XXV_DAC_CA_25G_L = 0x03,
+};
+
+struct nthw_mac_pcs_xxv {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_mac_pcs_xxv;
+ int mn_instance;
+
+ uint8_t m_port_no;
+
+#define NTHW_MAC_PCS_XXV_NUM_ELEMS 4
+ struct nthw_mac_pcs_xxv__registers_fields {
+ /* CORE_CONF */
+ nt_register_t *mp_reg_core_conf;
+ nt_field_t *mp_fld_core_conf_rx_enable;
+ nt_field_t *mp_fld_core_conf_rx_force_resync;
+ nt_field_t *mp_fld_core_conf_tx_enable;
+ nt_field_t *mp_fld_core_conf_tx_ins_fcs;
+ nt_field_t *mp_fld_core_conf_tx_ign_fcs;
+ nt_field_t *mp_fld_core_conf_tx_send_lfi;
+ nt_field_t *mp_fld_core_conf_tx_send_rfi;
+ nt_field_t *mp_fld_core_conf_tx_send_idle;
+ nt_field_t *mp_fld_core_conf_inline_mode;
+ nt_field_t *mp_fld_core_conf_line_loopback;
+ nt_field_t *mp_fld_core_conf_ts_at_eop;
+
+ /* ANEG_CONFIG */
+ nt_register_t *mp_reg_aneg_config;
+ nt_field_t *mp_fld_aneg_config_enable;
+ nt_field_t *mp_fld_aneg_config_bypass;
+ nt_field_t *mp_fld_aneg_config_restart;
+ nt_field_t *mp_fld_aneg_config_pseudo;
+ nt_field_t *mp_fld_aneg_config_nonce_seed;
+ nt_field_t *mp_fld_aneg_config_remote_fault;
+ nt_field_t *mp_fld_aneg_config_pause;
+ nt_field_t *mp_fld_aneg_config_asmdir;
+ nt_field_t *mp_fld_aneg_config_fec74_request10_g;
+ nt_field_t *mp_fld_aneg_config_hide_fec74;
+ nt_field_t *mp_fld_aneg_config_fec74_request;
+ nt_field_t *mp_fld_aneg_config_fec91_request;
+ nt_field_t *mp_fld_aneg_config_fec91_ability;
+ nt_field_t *mp_fld_aneg_config_rs_fec_request;
+ nt_field_t *mp_fld_aneg_config_sw_fec_overwrite;
+ nt_field_t *mp_fld_aneg_config_sw_speed_overwrite;
+
+ /* ANEG_ABILITY */
+ nt_register_t *mp_reg_aneg_ability;
+ nt_field_t *mp_fld_aneg_ability25_g_base_cr;
+ nt_field_t *mp_fld_aneg_ability25_g_base_crs;
+ nt_field_t *mp_fld_aneg_ability25_g_base_cr1;
+
+ /* LT_CONF */
+ nt_register_t *mp_reg_lt_conf;
+ nt_field_t *mp_fld_lt_conf_enable;
+ nt_field_t *mp_fld_lt_conf_restart;
+ nt_field_t *mp_fld_lt_conf_seed;
+
+ /* SUB_RST */
+ nt_register_t *mp_reg_sub_rst;
+ nt_field_t *mp_fld_sub_rst_rx_mac_pcs;
+ nt_field_t *mp_fld_sub_rst_tx_mac_pcs;
+ nt_field_t *mp_fld_sub_rst_rx_gt_data;
+ nt_field_t *mp_fld_sub_rst_tx_gt_data;
+ nt_field_t *mp_fld_sub_rst_rx_buf;
+ nt_field_t *mp_fld_sub_rst_rx_pma;
+ nt_field_t *mp_fld_sub_rst_tx_pma;
+ nt_field_t *mp_fld_sub_rst_rx_pcs;
+ nt_field_t *mp_fld_sub_rst_tx_pcs;
+ nt_field_t *mp_fld_sub_rst_an_lt;
+ nt_field_t *mp_fld_sub_rst_speed_ctrl;
+
+ /* SUB_RST_STATUS */
+ nt_register_t *mp_reg_sub_rst_status;
+ nt_field_t *mp_fld_sub_rst_status_user_rx_rst;
+ nt_field_t *mp_fld_sub_rst_status_user_tx_rst;
+ nt_field_t *mp_fld_sub_rst_status_qpll_lock;
+
+ /* LINK_SUMMARY */
+ nt_register_t *mp_reg_link_summary;
+ nt_field_t *mp_fld_link_summary_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_ll_nt_phy_link_state;
+ nt_field_t *mp_fld_link_summary_abs;
+ nt_field_t *mp_fld_link_summary_lh_abs;
+ nt_field_t *mp_fld_link_summary_link_down_cnt;
+ /* Begin 2 x 10/25 Gbps only fields: */
+ nt_field_t *mp_fld_link_summary_ll_rx_fec74_lock;
+ nt_field_t *mp_fld_link_summary_lh_rx_rsfec_hi_ser;
+ nt_field_t *mp_fld_link_summary_ll_rx_rsfec_lane_alignment;
+ nt_field_t *mp_fld_link_summary_ll_tx_rsfec_lane_alignment;
+ nt_field_t *mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code;
+ /* End 2 x 10/25 Gbps only fields. */
+ nt_field_t *mp_fld_link_summary_ll_rx_block_lock;
+ nt_field_t *mp_fld_link_summary_lh_rx_high_bit_error_rate;
+ nt_field_t *mp_fld_link_summary_lh_internal_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_received_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_local_fault;
+ nt_field_t *mp_fld_link_summary_lh_remote_fault;
+ nt_field_t *mp_fld_link_summary_lh_tx_local_fault;
+ nt_field_t *mp_fld_link_summary_nim_interr;
+
+ /* GTY_LOOP */
+ nt_register_t *mp_reg_gty_loop;
+ nt_field_t *mp_fld_gty_loop_gt_loop;
+
+ /* GTY_CTL_RX */
+ nt_register_t *mp_reg_gty_ctl_rx;
+ nt_field_t *mp_fld_gty_ctl_rx_polarity;
+ nt_field_t *mp_fld_gty_ctl_rx_lpm_en;
+ nt_field_t *mp_fld_gty_ctl_rx_equa_rst;
+
+ /* GTY_CTL_TX */
+ nt_register_t *mp_reg_gty_ctl_tx;
+ nt_field_t *mp_fld_gty_ctl_tx_polarity;
+ nt_field_t *mp_fld_gty_ctl_tx_inhibit;
+
+ /* LINK_SPEED */
+ nt_register_t *mp_reg_link_speed;
+ nt_field_t *mp_fld_link_speed10_g;
+ nt_field_t *mp_fld_link_speed_toggle;
+
+ /* RS_FEC_CONF */
+ nt_register_t *mp_reg_rs_fec_conf;
+ nt_field_t *mp_fld_rs_fec_conf_rs_fec_enable;
+
+ /* DEBOUNCE_CTRL */
+ nt_register_t *mp_reg_debounce_ctrl;
+ nt_field_t *mp_field_debounce_ctrl_nt_port_ctrl;
+
+ /* FEC_CCW_CNT */
+ nt_register_t *mp_reg_rs_fec_ccw;
+ nt_field_t *mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt;
+
+ /* FEC_UCW_CNT */
+ nt_register_t *mp_reg_rs_fec_ucw;
+ nt_field_t *mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt;
+
+ /* TIMESTAMP_COMP */
+ nt_register_t *mp_reg_timestamp_comp;
+ nt_field_t *mp_field_timestamp_comp_rx_dly;
+ nt_field_t *mp_field_timestamp_comp_tx_dly;
+
+ /* GTY_PRE_CURSOR */
+ nt_register_t *mp_reg_gty_pre_cursor;
+ nt_field_t *mp_field_gty_pre_cursor_tx_pre_csr;
+
+ /* GTY_DIFF_CTL */
+ nt_register_t *mp_reg_gty_diff_ctl;
+ nt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl;
+
+ /* GTY_POST_CURSOR */
+ nt_register_t *mp_reg_gty_post_cursor;
+ nt_field_t *mp_field_gty_post_cursor_tx_post_csr;
+ } regs[NTHW_MAC_PCS_XXV_NUM_ELEMS];
+};
+
+typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv_t;
+typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv;
+
+nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void);
+void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p);
+int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance,
+ int n_channels);
+
+void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p,
+ uint32_t *p_abs, uint32_t *p_nt_phy_link_state,
+ uint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt,
+ uint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault,
+ uint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault,
+ uint8_t index);
+
+uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no);
+
+void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi,
+ bool enable_rfi, uint8_t index);
+
+bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index);
+void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+
+bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index);
+void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);
+void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);
+void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);
+
+void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly,
+ uint8_t index);
+
+void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable,
+ uint8_t index);
+
+bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index);
+bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index);
+
+#endif /* NTHW_MAC_PCS_XXV_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c
new file mode 100644
index 0000000000..92089d2fa3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pci_rd_tg.h"
+
+nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void)
+{
+ nthw_pci_rd_tg_t *p = malloc(sizeof(nthw_pci_rd_tg_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pci_rd_tg_t));
+ return p;
+}
+
+void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pci_rd_tg_t));
+ free(p);
+ }
+}
+
+int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_RD_TG, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCI_RD_TG %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pci_rd_tg = mod;
+
+ p->mn_param_pci_ta_tg_present =
+ fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);
+
+ p->mp_reg_pci_rd_tg_rd_data0 =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA0);
+ p->mp_fld_pci_rd_tg_phys_addr_low =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data0,
+ PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW);
+
+ p->mp_reg_pci_rd_tg_rd_data1 =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA1);
+ p->mp_fld_pci_rd_tg_phys_addr_high =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data1,
+ PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH);
+
+ p->mp_reg_pci_rd_tg_rd_data2 =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA2);
+ p->mp_fld_pci_rd_tg_req_size =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_SIZE);
+ p->mp_fld_pci_rd_tg_wait =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WAIT);
+ p->mp_fld_pci_rd_tg_wrap =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WRAP);
+ /* optional VF host id */
+ p->mp_fld_pci_rd_tg_req_hid =
+ register_query_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_HID);
+
+ p->mp_reg_pci_rd_tg_rd_addr =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDADDR);
+ p->mp_fld_pci_rd_tg_ram_addr =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_addr, PCI_RD_TG_TG_RDADDR_RAM_ADDR);
+
+ p->mp_reg_pci_rd_tg_rd_run =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RD_RUN);
+ p->mp_fld_pci_rd_tg_run_iteration =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_run, PCI_RD_TG_TG_RD_RUN_RD_ITERATION);
+
+ p->mp_reg_pci_rd_tg_rd_ctrl =
+ module_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_CTRL);
+ p->mp_fld_pci_rd_tg_ctrl_rdy =
+ register_get_field(p->mp_reg_pci_rd_tg_rd_ctrl, PCI_RD_TG_TG_CTRL_TG_RD_RDY);
+
+ return 0;
+}
+
+void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_low,
+ (uint32_t)(n_phys_addr & ((1UL << 32) - 1)));
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_high,
+ (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1)));
+}
+
+void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_ram_addr, n_ram_addr);
+}
+
+void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap)
+{
+ field_set_val32(p->mp_fld_pci_rd_tg_req_size, req_size);
+ field_set_val32(p->mp_fld_pci_rd_tg_wait, wait);
+ field_set_val32(p->mp_fld_pci_rd_tg_wrap, wrap);
+ field_flush_register(p->mp_fld_pci_rd_tg_wrap);
+}
+
+void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations)
+{
+ field_set_val_flush32(p->mp_fld_pci_rd_tg_run_iteration, n_iterations);
+}
+
+uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p)
+{
+ return field_get_updated(p->mp_fld_pci_rd_tg_ctrl_rdy);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h
new file mode 100644
index 0000000000..b1c912f0f3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCI_RD_TG_H__
+#define __NTHW_PCI_RD_TG_H__
+
+struct nthw_pci_rd_tg {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pci_rd_tg;
+ int mn_instance;
+
+ int mn_param_pci_ta_tg_present;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_data0;
+ nt_field_t *mp_fld_pci_rd_tg_phys_addr_low;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_data1;
+ nt_field_t *mp_fld_pci_rd_tg_phys_addr_high;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_data2;
+ nt_field_t *mp_fld_pci_rd_tg_req_size;
+ nt_field_t *mp_fld_pci_rd_tg_req_hid;
+ nt_field_t *mp_fld_pci_rd_tg_wait;
+ nt_field_t *mp_fld_pci_rd_tg_wrap;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_addr;
+ nt_field_t *mp_fld_pci_rd_tg_ram_addr;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_run;
+ nt_field_t *mp_fld_pci_rd_tg_run_iteration;
+
+ nt_register_t *mp_reg_pci_rd_tg_rd_ctrl;
+ nt_field_t *mp_fld_pci_rd_tg_ctrl_rdy;
+};
+
+typedef struct nthw_pci_rd_tg nthw_pci_rd_tg_t;
+typedef struct nthw_pci_rd_tg nthw_pci_rd_tg;
+
+nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void);
+void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p);
+int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr);
+void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr);
+void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap);
+void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations);
+uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p);
+
+#endif /* __NTHW_PCI_RD_TG_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.c b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c
new file mode 100644
index 0000000000..17e30a670d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pci_ta.h"
+
+nthw_pci_ta_t *nthw_pci_ta_new(void)
+{
+ nthw_pci_ta_t *p = malloc(sizeof(nthw_pci_ta_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pci_ta_t));
+ return p;
+}
+
+void nthw_pci_ta_delete(nthw_pci_ta_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pci_ta_t));
+ free(p);
+ }
+}
+
+int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_TA, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCI_TA %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pci_ta = mod;
+
+ p->mn_param_pci_ta_tg_present =
+ fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);
+
+ p->mp_reg_pci_ta_ctrl = module_get_register(p->mp_mod_pci_ta, PCI_TA_CONTROL);
+ p->mp_fld_pci_ta_ctrl_enable =
+ register_get_field(p->mp_reg_pci_ta_ctrl, PCI_TA_CONTROL_ENABLE);
+
+ p->mp_reg_pci_ta_packet_good =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_GOOD);
+ p->mp_fld_pci_ta_packet_good_amount =
+ register_get_field(p->mp_reg_pci_ta_packet_good, PCI_TA_PACKET_GOOD_AMOUNT);
+
+ p->mp_reg_pci_ta_packet_bad =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_BAD);
+ p->mp_fld_pci_ta_packet_bad_amount =
+ register_get_field(p->mp_reg_pci_ta_packet_bad, PCI_TA_PACKET_BAD_AMOUNT);
+
+ p->mp_reg_pci_ta_length_error =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_LENGTH_ERROR);
+ p->mp_fld_pci_ta_length_error_amount =
+ register_get_field(p->mp_reg_pci_ta_length_error, PCI_TA_LENGTH_ERROR_AMOUNT);
+
+ p->mp_reg_pci_ta_payload_error =
+ module_get_register(p->mp_mod_pci_ta, PCI_TA_PAYLOAD_ERROR);
+ p->mp_fld_pci_ta_payload_error_amount =
+ register_get_field(p->mp_reg_pci_ta_payload_error, PCI_TA_PAYLOAD_ERROR_AMOUNT);
+
+ return 0;
+}
+
+void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val)
+{
+ field_set_val_flush32(p->mp_fld_pci_ta_ctrl_enable, val);
+}
+
+void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_packet_good_amount);
+}
+
+void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_packet_bad_amount);
+}
+
+void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_length_error_amount);
+}
+
+void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val)
+{
+ *val = field_get_updated(p->mp_fld_pci_ta_payload_error_amount);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.h b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h
new file mode 100644
index 0000000000..7968cad9fa
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCI_TA_H__
+#define __NTHW_PCI_TA_H__
+
+struct nthw_pci_ta {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pci_ta;
+ int mn_instance;
+
+ int mn_param_pci_ta_tg_present;
+
+ nt_register_t *mp_reg_pci_ta_ctrl;
+ nt_field_t *mp_fld_pci_ta_ctrl_enable;
+ nt_register_t *mp_reg_pci_ta_packet_good;
+ nt_field_t *mp_fld_pci_ta_packet_good_amount;
+ nt_register_t *mp_reg_pci_ta_packet_bad;
+ nt_field_t *mp_fld_pci_ta_packet_bad_amount;
+ nt_register_t *mp_reg_pci_ta_length_error;
+ nt_field_t *mp_fld_pci_ta_length_error_amount;
+ nt_register_t *mp_reg_pci_ta_payload_error;
+ nt_field_t *mp_fld_pci_ta_payload_error_amount;
+};
+
+typedef struct nthw_pci_ta nthw_pci_ta_t;
+typedef struct nthw_pci_ta nthw_pci_ta;
+
+nthw_pci_ta_t *nthw_pci_ta_new(void);
+void nthw_pci_ta_delete(nthw_pci_ta_t *p);
+int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val);
+void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val);
+void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val);
+void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val);
+void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val);
+
+#endif /* __NTHW_PCI_TA_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c
new file mode 100644
index 0000000000..f830a586b2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pci_wr_tg.h"
+
+nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void)
+{
+ nthw_pci_wr_tg_t *p = malloc(sizeof(nthw_pci_wr_tg_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pci_wr_tg_t));
+ return p;
+}
+
+void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pci_wr_tg_t));
+ free(p);
+ }
+}
+
+int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_WR_TG, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCI_WR_TG %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pci_wr_tg = mod;
+
+ p->mn_param_pci_ta_tg_present =
+ fpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);
+
+ p->mp_reg_pci_wr_tg_data0 =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA0);
+ p->mp_fld_pci_wr_tg_phys_addr_low =
+ register_get_field(p->mp_reg_pci_wr_tg_data0, PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW);
+
+ p->mp_reg_pci_wr_tg_data1 =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA1);
+ p->mp_fld_pci_wr_tg_phys_addr_high =
+ register_get_field(p->mp_reg_pci_wr_tg_data1, PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH);
+
+ p->mp_reg_pci_wr_tg_data2 =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA2);
+ p->mp_fld_pci_wr_tg_req_size =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_SIZE);
+ p->mp_fld_pci_wr_tg_inc_mode =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_INC_MODE);
+ p->mp_fld_pci_wr_tg_wait =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WAIT);
+ p->mp_fld_pci_wr_tg_wrap =
+ register_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WRAP);
+ /* optional VF host id */
+ p->mp_fld_pci_wr_tg_req_hid =
+ register_query_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_HID);
+
+ p->mp_reg_pci_wr_tg_addr =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRADDR);
+ p->mp_fld_pci_wr_tg_ram_addr =
+ register_get_field(p->mp_reg_pci_wr_tg_addr, PCI_WR_TG_TG_WRADDR_RAM_ADDR);
+
+ p->mp_reg_pci_wr_tg_run =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WR_RUN);
+ p->mp_fld_pci_wr_tg_run_iteration =
+ register_get_field(p->mp_reg_pci_wr_tg_run, PCI_WR_TG_TG_WR_RUN_WR_ITERATION);
+
+ p->mp_reg_pci_wr_tg_ctrl =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_CTRL);
+ p->mp_fld_pci_wr_tg_ctrl_rdy =
+ register_get_field(p->mp_reg_pci_wr_tg_ctrl, PCI_WR_TG_TG_CTRL_TG_WR_RDY);
+
+ p->mp_reg_pci_wr_tg_seq =
+ module_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_SEQ);
+ p->mp_fld_pci_wr_tg_seq_sequence =
+ register_get_field(p->mp_reg_pci_wr_tg_seq, PCI_WR_TG_TG_SEQ_SEQUENCE);
+
+ return 0;
+}
+
+void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_low,
+ (uint32_t)(n_phys_addr & ((1UL << 32) - 1)));
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_high,
+ (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1)));
+}
+
+void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr)
+{
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_ram_addr, n_ram_addr);
+}
+
+void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap, bool inc)
+{
+ field_set_val32(p->mp_fld_pci_wr_tg_req_size, req_size);
+ field_set_val32(p->mp_fld_pci_wr_tg_wait, wait);
+ field_set_val32(p->mp_fld_pci_wr_tg_wrap, wrap);
+ field_set_val32(p->mp_fld_pci_wr_tg_inc_mode, inc);
+ field_flush_register(p->mp_fld_pci_wr_tg_inc_mode);
+}
+
+void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations)
+{
+ field_set_val_flush32(p->mp_fld_pci_wr_tg_run_iteration, n_iterations);
+}
+
+uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p)
+{
+ return field_get_updated(p->mp_fld_pci_wr_tg_ctrl_rdy);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h
new file mode 100644
index 0000000000..535b39526e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCI_WR_TG_H__
+#define __NTHW_PCI_WR_TG_H__
+
+struct nthw_pci_wr_tg {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pci_wr_tg;
+ int mn_instance;
+
+ int mn_param_pci_ta_tg_present;
+
+ nt_register_t *mp_reg_pci_wr_tg_data0;
+ nt_field_t *mp_fld_pci_wr_tg_phys_addr_low;
+
+ nt_register_t *mp_reg_pci_wr_tg_data1;
+ nt_field_t *mp_fld_pci_wr_tg_phys_addr_high;
+
+ nt_register_t *mp_reg_pci_wr_tg_data2;
+ nt_field_t *mp_fld_pci_wr_tg_req_size;
+ nt_field_t *mp_fld_pci_wr_tg_req_hid;
+ nt_field_t *mp_fld_pci_wr_tg_inc_mode;
+ nt_field_t *mp_fld_pci_wr_tg_wait;
+ nt_field_t *mp_fld_pci_wr_tg_wrap;
+
+ nt_register_t *mp_reg_pci_wr_tg_addr;
+ nt_field_t *mp_fld_pci_wr_tg_ram_addr;
+
+ nt_register_t *mp_reg_pci_wr_tg_run;
+ nt_field_t *mp_fld_pci_wr_tg_run_iteration;
+
+ nt_register_t *mp_reg_pci_wr_tg_ctrl;
+ nt_field_t *mp_fld_pci_wr_tg_ctrl_rdy;
+
+ nt_register_t *mp_reg_pci_wr_tg_seq;
+ nt_field_t *mp_fld_pci_wr_tg_seq_sequence;
+};
+
+typedef struct nthw_pci_wr_tg nthw_pci_wr_tg_t;
+typedef struct nthw_pci_wr_tg nthw_pci_wr_tg;
+
+nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void);
+void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p);
+int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr);
+void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr);
+void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait,
+ bool wrap, bool inc);
+void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations);
+uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p);
+
+#endif /* __NTHW_PCI_WR_TG_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.c b/drivers/net/ntnic/nthw/core/nthw_pcie3.c
new file mode 100644
index 0000000000..07ad784695
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.c
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pcie3.h"
+
+#define NTHW_TG_REF_FREQ (250000000ULL)
+
+nthw_pcie3_t *nthw_pcie3_new(void)
+{
+ nthw_pcie3_t *p = malloc(sizeof(nthw_pcie3_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_pcie3_t));
+ return p;
+}
+
+void nthw_pcie3_delete(nthw_pcie3_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_pcie3_t));
+ free(p);
+ }
+}
+
+int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_PCIE3, n_instance);
+
+ if (p == NULL)
+ return (mod == NULL ? -1 : 0);
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: PCIE3 %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_pcie3 = mod;
+
+ /* PCIe3 */
+ p->mp_reg_stat_ctrl = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_CTRL);
+ p->mp_fld_stat_ctrl_ena =
+ register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_ENA);
+ p->mp_fld_stat_ctrl_req =
+ register_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_REQ);
+
+ p->mp_reg_stat_rx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RX);
+ p->mp_fld_stat_rx_counter =
+ register_get_field(p->mp_reg_stat_rx, PCIE3_STAT_RX_COUNTER);
+
+ p->mp_reg_stat_tx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_TX);
+ p->mp_fld_stat_tx_counter =
+ register_get_field(p->mp_reg_stat_tx, PCIE3_STAT_TX_COUNTER);
+
+ p->mp_reg_stat_ref_clk =
+ module_get_register(p->mp_mod_pcie3, PCIE3_STAT_REFCLK);
+ p->mp_fld_stat_ref_clk_ref_clk =
+ register_get_field(p->mp_reg_stat_ref_clk, PCIE3_STAT_REFCLK_REFCLK250);
+
+ p->mp_reg_stat_rq_rdy =
+ module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_RDY);
+ p->mp_fld_stat_rq_rdy_counter =
+ register_get_field(p->mp_reg_stat_rq_rdy, PCIE3_STAT_RQ_RDY_COUNTER);
+
+ p->mp_reg_stat_rq_vld =
+ module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_VLD);
+ p->mp_fld_stat_rq_vld_counter =
+ register_get_field(p->mp_reg_stat_rq_vld, PCIE3_STAT_RQ_VLD_COUNTER);
+
+ p->mp_reg_status0 = module_get_register(p->mp_mod_pcie3, PCIE3_STATUS0);
+ p->mp_fld_status0_tags_in_use =
+ register_get_field(p->mp_reg_status0, PCIE3_STATUS0_TAGS_IN_USE);
+
+ p->mp_reg_rp_to_ep_err =
+ module_get_register(p->mp_mod_pcie3, PCIE3_RP_TO_EP_ERR);
+ p->mp_fld_rp_to_ep_err_cor =
+ register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_COR);
+ p->mp_fld_rp_to_ep_err_non_fatal =
+ register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_NONFATAL);
+ p->mp_fld_rp_to_ep_err_fatal =
+ register_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_FATAL);
+
+ p->mp_reg_ep_to_rp_err =
+ module_get_register(p->mp_mod_pcie3, PCIE3_EP_TO_RP_ERR);
+ p->mp_fld_ep_to_rp_err_cor = register_get_field(p->mp_reg_ep_to_rp_err,
+ PCIE3_EP_TO_RP_ERR_ERR_COR);
+ p->mp_fld_ep_to_rp_err_non_fatal =
+ register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_NONFATAL);
+ p->mp_fld_ep_to_rp_err_fatal =
+ register_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_FATAL);
+
+ p->mp_reg_sample_time =
+ module_get_register(p->mp_mod_pcie3, PCIE3_SAMPLE_TIME);
+ p->mp_fld_sample_time =
+ register_get_field(p->mp_reg_sample_time, PCIE3_SAMPLE_TIME_SAMPLE_TIME);
+
+ p->mp_reg_pci_end_point =
+ module_get_register(p->mp_mod_pcie3, PCIE3_PCI_ENDPOINT);
+ p->mp_fld_pci_end_point_if_id =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_IF_ID);
+ p->mp_fld_pci_end_point_send_msg =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_SEND_MSG);
+ p->mp_fld_pci_end_point_get_msg =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_GET_MSG);
+ p->mp_fld_pci_end_point_dmae_p0_allow_mask =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK);
+ p->mp_fld_pci_end_point_dmae_p1_allow_mask =
+ register_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK);
+ if (p->mp_reg_pci_end_point)
+ register_update(p->mp_reg_pci_end_point);
+
+ p->mp_reg_pci_test0 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST0);
+ p->mp_fld_pci_test0 =
+ register_get_field(p->mp_reg_pci_test0, PCIE3_PCI_TEST0_DATA);
+ if (p->mp_reg_pci_test0)
+ register_update(p->mp_reg_pci_test0);
+
+ p->mp_reg_pci_test1 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST1);
+ p->mp_fld_pci_test1 =
+ register_get_field(p->mp_reg_pci_test1, PCIE3_PCI_TEST1_DATA);
+ if (p->mp_reg_pci_test1)
+ register_update(p->mp_reg_pci_test1);
+
+ p->mp_reg_pci_e3_mark_adr_lsb =
+ module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_LSB);
+ p->mp_fld_pci_e3_mark_adr_lsb_adr =
+ register_get_field(p->mp_reg_pci_e3_mark_adr_lsb, PCIE3_MARKADR_LSB_ADR);
+ if (p->mp_reg_pci_e3_mark_adr_lsb)
+ register_update(p->mp_reg_pci_e3_mark_adr_lsb);
+
+ p->mp_reg_pci_e3_mark_adr_msb =
+ module_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_MSB);
+ p->mp_fld_pci_e3_mark_adr_msb_adr =
+ register_get_field(p->mp_reg_pci_e3_mark_adr_msb, PCIE3_MARKADR_MSB_ADR);
+ if (p->mp_reg_pci_e3_mark_adr_msb)
+ register_update(p->mp_reg_pci_e3_mark_adr_msb);
+
+ /* Initial setup - disable markerscheme and bifurcation */
+ if (p->mp_fld_pci_end_point_dmae_p0_allow_mask)
+ field_clr_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask);
+
+ if (p->mp_fld_pci_end_point_dmae_p1_allow_mask)
+ field_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask);
+
+ if (p->mp_fld_pci_e3_mark_adr_lsb_adr)
+ field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_lsb_adr, 0UL);
+
+ if (p->mp_fld_pci_e3_mark_adr_msb_adr)
+ field_set_val_flush32(p->mp_fld_pci_e3_mark_adr_msb_adr, 0UL);
+
+ if (p->mp_fld_pci_end_point_dmae_p0_allow_mask)
+ field_set_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask);
+
+ if (p->mp_fld_pci_end_point_dmae_p1_allow_mask)
+ field_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask);
+ return 0;
+};
+
+int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p)
+{
+ field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);
+
+ return 0;
+}
+
+int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p)
+{
+ field_set_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p)
+{
+ field_clr_all(p->mp_fld_stat_ctrl_ena);
+ field_set_all(p->mp_fld_stat_ctrl_req);
+ field_flush_register(p->mp_fld_stat_ctrl_req);
+ return 0;
+}
+
+int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt,
+ uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt)
+{
+ *p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter);
+ *p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter);
+
+ *p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk);
+
+ *p_tg_unit_size = NTHW_TG_CNT_SIZE;
+ *p_tg_ref_freq = NTHW_TG_REF_FREQ;
+
+ *p_tag_use_cnt = field_get_updated(p->mp_fld_status0_tags_in_use);
+
+ *p_rq_rdy_cnt = field_get_updated(p->mp_fld_stat_rq_rdy_counter);
+ *p_rq_vld_cnt = field_get_updated(p->mp_fld_stat_rq_vld_counter);
+
+ return 0;
+}
+
+int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util,
+ uint64_t *p_pci_xil_bus_util)
+{
+ uint32_t rx_cnt, tx_cnt, ref_clk_cnt;
+ uint32_t tg_unit_size, tg_ref_freq;
+ uint32_t tag_use_cnt, rq_rdy_cnt, rq_vld_cnt;
+
+ nthw_pcie3_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size,
+ &tg_ref_freq, &tag_use_cnt, &rq_rdy_cnt, &rq_vld_cnt);
+
+ if (ref_clk_cnt) {
+ uint64_t nt_bus_util, xil_bus_util;
+ uint64_t rx_rate, tx_rate;
+
+ rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_rx_rate = rx_rate;
+
+ tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) /
+ (uint64_t)ref_clk_cnt;
+ *p_pci_tx_rate = tx_rate;
+
+ *p_ref_clk_cnt = ref_clk_cnt;
+
+ *p_tag_use_cnt = tag_use_cnt;
+
+ nt_bus_util =
+ ((uint64_t)rq_vld_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt;
+ *p_pci_nt_bus_util = nt_bus_util;
+ xil_bus_util =
+ ((uint64_t)rq_rdy_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt;
+ *p_pci_xil_bus_util = xil_bus_util;
+ } else {
+ *p_ref_clk_cnt = 0;
+ *p_pci_nt_bus_util = 0;
+ *p_pci_xil_bus_util = 0;
+ }
+
+ return 0;
+}
+
+int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc)
+{
+ NT_LOG(DBG, NTHW, "%s:%u: empty function\n", __func__, __LINE__);
+
+ (void)p;
+ (void)epc;
+
+ return 0;
+}
+
+int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc)
+{
+ NT_LOG(DBG, NTHW, "%s:%u:\n", __func__, __LINE__);
+ assert(epc);
+ nthw_pcie3_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt,
+ &epc->n_tags_in_use, &epc->cur_pci_nt_util,
+ &epc->cur_pci_xil_util);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.h b/drivers/net/ntnic/nthw/core/nthw_pcie3.h
new file mode 100644
index 0000000000..beb79a9577
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCIE3_H__
+#define __NTHW_PCIE3_H__
+
+struct nthw_pcie3 {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_pcie3;
+ int mn_instance;
+
+ nt_register_t *mp_reg_stat_ctrl;
+ nt_field_t *mp_fld_stat_ctrl_req;
+ nt_field_t *mp_fld_stat_ctrl_ena;
+
+ nt_register_t *mp_reg_stat_rx;
+ nt_field_t *mp_fld_stat_rx_counter;
+
+ nt_register_t *mp_reg_stat_tx;
+ nt_field_t *mp_fld_stat_tx_counter;
+
+ nt_register_t *mp_reg_stat_rq_rdy;
+ nt_field_t *mp_fld_stat_rq_rdy_counter;
+
+ nt_register_t *mp_reg_stat_rq_vld;
+ nt_field_t *mp_fld_stat_rq_vld_counter;
+
+ nt_register_t *mp_reg_status0;
+ nt_field_t *mp_fld_status0_tags_in_use;
+
+ nt_register_t *mp_reg_stat_ref_clk;
+ nt_field_t *mp_fld_stat_ref_clk_ref_clk;
+
+ nt_register_t *mp_reg_rp_to_ep_err;
+ nt_field_t *mp_fld_rp_to_ep_err_cor;
+ nt_field_t *mp_fld_rp_to_ep_err_non_fatal;
+ nt_field_t *mp_fld_rp_to_ep_err_fatal;
+
+ nt_register_t *mp_reg_ep_to_rp_err;
+ nt_field_t *mp_fld_ep_to_rp_err_cor;
+ nt_field_t *mp_fld_ep_to_rp_err_non_fatal;
+ nt_field_t *mp_fld_ep_to_rp_err_fatal;
+
+ nt_register_t *mp_reg_sample_time;
+ nt_field_t *mp_fld_sample_time;
+
+ nt_register_t *mp_reg_pci_end_point;
+ nt_field_t *mp_fld_pci_end_point_if_id;
+ nt_field_t *mp_fld_pci_end_point_send_msg;
+ nt_field_t *mp_fld_pci_end_point_get_msg;
+ nt_field_t *mp_fld_pci_end_point_dmae_p0_allow_mask;
+ nt_field_t *mp_fld_pci_end_point_dmae_p1_allow_mask;
+
+ nt_register_t *mp_reg_pci_e3_mark_adr_lsb;
+ nt_field_t *mp_fld_pci_e3_mark_adr_lsb_adr;
+
+ nt_register_t *mp_reg_pci_e3_mark_adr_msb;
+ nt_field_t *mp_fld_pci_e3_mark_adr_msb_adr;
+
+ nt_register_t *mp_reg_pci_test0;
+ nt_field_t *mp_fld_pci_test0;
+
+ nt_register_t *mp_reg_pci_test1;
+ nt_field_t *mp_fld_pci_test1;
+
+ nt_register_t *mp_reg_pci_test2;
+ nt_field_t *mp_fld_pci_test2;
+
+ nt_register_t *mp_reg_pci_test3;
+ nt_field_t *mp_fld_pci_test3;
+};
+
+typedef struct nthw_pcie3 nthw_pcie3_t;
+typedef struct nthw_pcie3 nthw_pcie3;
+
+nthw_pcie3_t *nthw_pcie3_new(void);
+void nthw_pcie3_delete(nthw_pcie3_t *p);
+int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p);
+
+int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p);
+int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p);
+
+int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,
+ uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,
+ uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt,
+ uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt);
+int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate,
+ uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,
+ uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util,
+ uint64_t *p_pci_xil_bus_util);
+
+int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc);
+int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p,
+ struct nthw_hif_end_point_counters *epc);
+
+#endif /* __NTHW_PCIE3_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.c b/drivers/net/ntnic/nthw/core/nthw_sdc.c
new file mode 100644
index 0000000000..0547b92c47
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.c
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_sdc.h"
+
+nthw_sdc_t *nthw_sdc_new(void)
+{
+ nthw_sdc_t *p = malloc(sizeof(nthw_sdc_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_sdc_t));
+ return p;
+}
+
+void nthw_sdc_delete(nthw_sdc_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_sdc_t));
+ free(p);
+ }
+}
+
+int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_SDC, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: SDC %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_sdc = mod;
+
+ {
+ nt_register_t *p_reg;
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_CTRL);
+ p->mp_fld_ctrl_init = register_get_field(p_reg, SDC_CTRL_INIT);
+ p->mp_fld_ctrl_run_test =
+ register_get_field(p_reg, SDC_CTRL_RUN_TEST);
+ p->mp_fld_ctrl_stop_client =
+ register_get_field(p_reg, SDC_CTRL_STOP_CLIENT);
+ p->mp_fld_ctrl_test_enable =
+ register_get_field(p_reg, SDC_CTRL_TEST_EN);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_STAT);
+ p->mp_fld_stat_calib = register_get_field(p_reg, SDC_STAT_CALIB);
+ p->mp_fld_stat_cell_cnt_stopped =
+ register_get_field(p_reg, SDC_STAT_CELL_CNT_STOPPED);
+ p->mp_fld_stat_err_found =
+ register_get_field(p_reg, SDC_STAT_ERR_FOUND);
+ p->mp_fld_stat_init_done =
+ register_get_field(p_reg, SDC_STAT_INIT_DONE);
+ p->mp_fld_stat_mmcm_lock =
+ register_get_field(p_reg, SDC_STAT_MMCM_LOCK);
+ p->mp_fld_stat_pll_lock =
+ register_get_field(p_reg, SDC_STAT_PLL_LOCK);
+ p->mp_fld_stat_resetting =
+ register_get_field(p_reg, SDC_STAT_RESETTING);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT);
+ p->mp_fld_cell_cnt =
+ register_get_field(p_reg, SDC_CELL_CNT_CELL_CNT);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT_PERIOD);
+ p->mp_fld_cell_cnt_period =
+ register_get_field(p_reg, SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_FILL_LVL);
+ p->mp_fld_fill_level =
+ register_get_field(p_reg, SDC_FILL_LVL_FILL_LVL);
+
+ p_reg = module_get_register(p->mp_mod_sdc, SDC_MAX_FILL_LVL);
+ p->mp_fld_max_fill_level =
+ register_get_field(p_reg, SDC_MAX_FILL_LVL_MAX_FILL_LVL);
+ }
+ return 0;
+}
+
+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask)
+{
+ int n_err_cnt = 0;
+ uint64_t n_mask = 0;
+ uint32_t val;
+ uint32_t val_mask;
+ int n_val_width;
+
+ if (!p || !pn_result_mask)
+ return -1;
+
+ val = field_get_updated(p->mp_fld_stat_calib);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_calib);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_init_done);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_init_done);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_mmcm_lock);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_mmcm_lock);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_pll_lock);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_pll_lock);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != val_mask)
+ n_err_cnt++;
+
+ val = field_get_updated(p->mp_fld_stat_resetting);
+ n_val_width = field_get_bit_width(p->mp_fld_stat_resetting);
+ val_mask = ((1 << n_val_width) - 1);
+ n_mask = (n_mask << n_val_width) | (val & val_mask);
+ if (val != 0)
+ n_err_cnt++;
+
+ if (pn_result_mask)
+ *pn_result_mask = n_mask;
+
+ return n_err_cnt; /* 0 = all ok */
+}
+
+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations,
+ const int n_poll_interval)
+{
+ int res;
+ int n_err_cnt = 0;
+
+ res = field_wait_set_all32(p->mp_fld_stat_calib, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_set_all32(p->mp_fld_stat_init_done, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_set_all32(p->mp_fld_stat_mmcm_lock, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_set_all32(p->mp_fld_stat_pll_lock, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ res = field_wait_clr_all32(p->mp_fld_stat_resetting, n_poll_iterations,
+ n_poll_interval);
+ if (res)
+ n_err_cnt++;
+
+ return n_err_cnt; /* 0 = all ok */
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.h b/drivers/net/ntnic/nthw/core/nthw_sdc.h
new file mode 100644
index 0000000000..e6c08ffbc3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SDC_H__
+#define __NTHW_SDC_H__
+
+struct nthw_sdc {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_sdc;
+ int mn_instance;
+
+ nt_field_t *mp_fld_ctrl_init;
+ nt_field_t *mp_fld_ctrl_run_test;
+ nt_field_t *mp_fld_ctrl_stop_client;
+ nt_field_t *mp_fld_ctrl_test_enable;
+
+ nt_field_t *mp_fld_stat_calib;
+ nt_field_t *mp_fld_stat_cell_cnt_stopped;
+ nt_field_t *mp_fld_stat_err_found;
+ nt_field_t *mp_fld_stat_init_done;
+ nt_field_t *mp_fld_stat_mmcm_lock;
+ nt_field_t *mp_fld_stat_pll_lock;
+ nt_field_t *mp_fld_stat_resetting;
+
+ nt_field_t *mp_fld_cell_cnt;
+ nt_field_t *mp_fld_cell_cnt_period;
+ nt_field_t *mp_fld_fill_level;
+ nt_field_t *mp_fld_max_fill_level;
+};
+
+typedef struct nthw_sdc nthw_sdc_t;
+typedef struct nthw_sdc nthw_sdc;
+
+nthw_sdc_t *nthw_sdc_new(void);
+int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_sdc_delete(nthw_sdc_t *p);
+
+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations,
+ const int n_poll_interval);
+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask);
+
+#endif /* __NTHW_SDC_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.c b/drivers/net/ntnic/nthw/core/nthw_si5340.c
new file mode 100644
index 0000000000..3337f1f9e3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_si5340.c
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ *
+ * This file implements Si5340 clock synthesizer support.
+ * The implementation is generic and must be tailored to a specific use by the
+ * correct initialization data.
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_si5340.h"
+
+#define SI5340_WAIT_US(x) NT_OS_WAIT_USEC(x)
+
+#define SI5340_LOG_DEBUG(...) NT_LOG(DBG, NTHW, __VA_ARGS__)
+#define SI5340_LOG_INFO(...) NT_LOG(INF, NTHW, __VA_ARGS__)
+#define SI5340_LOG_WARN(...) NT_LOG(WRN, NTHW, __VA_ARGS__)
+#define SI5340_LOG_ERROR(...) NT_LOG(ERR, NTHW, __VA_ARGS__)
+
+#define SI5340_PAGE_REG_ADDR (0x01)
+
+nthw_si5340_t *nthw_si5340_new(void)
+{
+ nthw_si5340_t *p = malloc(sizeof(nthw_si5340_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_si5340_t));
+ return p;
+}
+
+int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr)
+{
+ uint8_t data;
+
+ p->mp_nthw_iic = p_nthw_iic;
+ p->mn_iic_addr = n_iic_addr;
+ p->mn_clk_cfg = -1;
+
+ p->m_si5340_page = 0;
+ data = p->m_si5340_page;
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1,
+ &data);
+
+ return 0;
+}
+
+void nthw_si5340_delete(nthw_si5340_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_si5340_t));
+ free(p);
+ }
+}
+
+/*
+ * Read access (via I2C) to the clock synthesizer IC. The IC is located at I2C
+ * 7bit address 0x74
+ */
+static uint8_t nthw_si5340_read(nthw_si5340_t *p, uint16_t reg_addr)
+{
+ const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff);
+ uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff);
+ uint8_t data;
+
+ /* check if we are on the right page */
+ if (page != p->m_si5340_page) {
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr,
+ SI5340_PAGE_REG_ADDR, 1, &page);
+ p->m_si5340_page = page;
+ }
+ nthw_iic_read_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data);
+ return data;
+}
+
+/*
+ * Write access (via I2C) to the clock synthesizer IC. The IC is located at I2C
+ * 7 bit address 0x74
+ */
+static int nthw_si5340_write(nthw_si5340_t *p, uint16_t reg_addr, uint8_t data)
+{
+ const uint8_t offset_adr = (uint8_t)(reg_addr & 0xff);
+ uint8_t page = (uint8_t)((reg_addr >> 8) & 0xff);
+
+ /* check if we are on the right page */
+ if (page != p->m_si5340_page) {
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr,
+ SI5340_PAGE_REG_ADDR, 1, &page);
+ p->m_si5340_page = page;
+ }
+ nthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data);
+
+ return 0;
+}
+
+static int nthw_si5340_cfg(nthw_si5340_t *p, const void *p_data, int data_cnt,
+ clk_profile_data_fmt_t data_format)
+{
+ const char *const p_adapter_id_str =
+ p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int i;
+ uint16_t addr;
+ uint8_t value;
+ uint8_t ctrl_value;
+
+ NT_LOG(DBG, NTHW, "%s: %s: data_cnt = %d, dataFormat = %d\n",
+ p_adapter_id_str, __func__, data_cnt, data_format);
+
+ for (i = 0; i < data_cnt; i++) {
+ if (data_format == CLK_PROFILE_DATA_FMT_1) {
+ addr = ((const clk_profile_data_fmt1_t *)p_data)->reg_addr;
+ value = ((const clk_profile_data_fmt1_t *)p_data)->reg_val;
+ p_data = ((const clk_profile_data_fmt1_t *)p_data) + 1;
+ } else if (data_format == CLK_PROFILE_DATA_FMT_2) {
+ addr = (uint16_t)(((const clk_profile_data_fmt2_t *)p_data)
+ ->reg_addr);
+ value = ((const clk_profile_data_fmt2_t *)p_data)->reg_val;
+ p_data = ((const clk_profile_data_fmt2_t *)p_data) + 1;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: Unhandled Si5340 data format (%d)\n",
+ p_adapter_id_str, data_format);
+ return -1;
+ }
+
+ if (addr == 0x0006) {
+ /* Wait 300ms before continuing. See NT200E3-2-PTP_U23_Si5340_adr0_v2.h */
+ NT_OS_WAIT_USEC(300000);
+ }
+
+ nthw_si5340_write(p, addr, value);
+
+ if (addr == 0x001C) {
+ /* skip readback for "soft reset" register */
+ continue;
+ }
+
+ ctrl_value = nthw_si5340_read(p, addr);
+
+ if (ctrl_value != value) {
+ NT_LOG(ERR, NTHW,
+ "%s: Si5340 configuration readback check failed. (Addr = 0x%04X, Write = 0x%02X, Read = 0x%02X)\n",
+ p_adapter_id_str, addr, value, ctrl_value);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt,
+ clk_profile_data_fmt_t data_format)
+{
+ const char *const p_adapter_id_str =
+ p->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str;
+ int i;
+ bool success = false;
+ uint8_t status, sticky;
+ uint8_t design_id[9];
+
+ (void)nthw_si5340_cfg(p, p_data, data_cnt, data_format);
+
+ /* Check if DPLL is locked and SYS is calibrated */
+ for (i = 0; i < 5; i++) {
+ status = nthw_si5340_read(p, 0x0c);
+ sticky = nthw_si5340_read(p, 0x11);
+ nthw_si5340_write(p, 0x11, 0x00);
+
+ if (((status & 0x09) == 0x00) && ((sticky & 0x09) == 0x00)) {
+ success = true;
+ break;
+ }
+ NT_OS_WAIT_USEC(1000000); /* 1 sec */
+ }
+
+ if (!success) {
+ NT_LOG(ERR, NTHW,
+ "%s: Si5340 configuration failed. (Status = 0x%02X, Sticky = 0x%02X)\n",
+ p_adapter_id_str, status, sticky);
+ return -1;
+ }
+
+ for (i = 0; i < (int)sizeof(design_id) - 1; i++)
+ design_id[i] = nthw_si5340_read(p, (uint16_t)(0x26B + i));
+ design_id[sizeof(design_id) - 1] = 0;
+
+ (void)design_id; /* Only used in debug mode */
+ NT_LOG(DBG, NTHW, "%s: Si5340.DesignId = %s\n", p_adapter_id_str,
+ design_id);
+
+ return 0;
+}
+
+int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data,
+ const int data_cnt)
+{
+ return nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_1);
+}
+
+int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data,
+ const int data_cnt)
+{
+ return nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_2);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.h b/drivers/net/ntnic/nthw/core/nthw_si5340.h
new file mode 100644
index 0000000000..f588b5b825
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_si5340.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SI5340_H__
+#define __NTHW_SI5340_H__
+
+#include "nthw_clock_profiles.h"
+
+#define SI5340_SUCCESS (0)
+#define SI5340_FAILED (999)
+#define SI5340_TIMEOUT (666)
+
+struct nthw_si5340 {
+ uint8_t mn_iic_addr;
+ nthw_iic_t *mp_nthw_iic;
+ int mn_clk_cfg;
+ uint8_t m_si5340_page;
+};
+
+typedef struct nthw_si5340 nthw_si5340_t;
+
+nthw_si5340_t *nthw_si5340_new(void);
+int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr);
+void nthw_si5340_delete(nthw_si5340_t *p);
+
+int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt,
+ clk_profile_data_fmt_t data_format);
+int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data,
+ const int data_cnt);
+int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data,
+ const int data_cnt);
+
+#endif /* __NTHW_SI5338_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.c b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c
new file mode 100644
index 0000000000..454c9b73b8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+
+#include "nthw_spi_v3.h"
+
+#include <arpa/inet.h>
+
+#undef SPI_V3_DEBUG_PRINT
+
+nthw_spi_v3_t *nthw_spi_v3_new(void)
+{
+ nthw_spi_v3_t *p = malloc(sizeof(nthw_spi_v3_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_spi_v3_t));
+ return p;
+}
+
+void nthw_spi_v3_delete(nthw_spi_v3_t *p)
+{
+ if (p) {
+ if (p->mp_spim_mod) {
+ nthw_spim_delete(p->mp_spim_mod);
+ p->mp_spim_mod = NULL;
+ }
+
+ if (p->mp_spis_mod) {
+ nthw_spis_delete(p->mp_spis_mod);
+ p->mp_spis_mod = NULL;
+ }
+
+ memset(p, 0, sizeof(nthw_spi_v3_t));
+ free(p);
+ }
+}
+
+int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out)
+{
+ p->m_time_out = time_out;
+ return 0;
+}
+
+int nthw_spi_v3_get_version(nthw_spi_v3_t *p)
+{
+ (void)p;
+ return 3;
+}
+
+/*
+ * Wait until Tx data have been sent after they have been placed in the Tx FIFO.
+ */
+static int wait_for_tx_data_sent(nthw_spim_t *p_spim_mod, uint64_t time_out)
+{
+ int result;
+ bool empty;
+ uint64_t start_time;
+ uint64_t cur_time;
+
+ start_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+
+ while (true) {
+ NT_OS_WAIT_USEC(1000); /* Every 1ms */
+
+ result = nthw_spim_get_tx_fifo_empty(p_spim_mod, &empty);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spim_get_tx_fifo_empty failed\n");
+ return result;
+ }
+
+ if (empty)
+ break;
+
+ cur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+ if ((cur_time - start_time) > time_out) {
+ NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Wait until Rx data have been received.
+ */
+static int wait_for_rx_data_ready(nthw_spis_t *p_spis_mod, uint64_t time_out)
+{
+ int result;
+ bool empty;
+ uint64_t start_time;
+ uint64_t cur_time;
+
+ start_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+
+ /* Wait for data to become ready in the Rx FIFO */
+ while (true) {
+ NT_OS_WAIT_USEC(10000); /* Every 10ms */
+
+ result = nthw_spis_get_rx_fifo_empty(p_spis_mod, &empty);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spis_get_rx_empty failed\n");
+ return result;
+ }
+
+ if (!empty)
+ break;
+
+ cur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();
+ if ((cur_time - start_time) > time_out) {
+ NT_LOG(WRN, NTHW, "%s: Timed out\n", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef SPI_V3_DEBUG_PRINT
+static void dump_hex(uint8_t *p_data, uint16_t count)
+{
+ int i;
+ int j = 0;
+ char tmp_str[128];
+
+ for (i = 0; i < count; i++) {
+ sprintf(&tmp_str[j * 3], "%02X ", *(p_data++));
+ j++;
+
+ if (j == 16 || (i == count - 1)) {
+ tmp_str[j * 3 - 1] = '\0';
+ NT_LOG(DBG, NTHW, " %s\n", tmp_str);
+ j = 0;
+ }
+ }
+}
+#endif
+
+int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint32_t result;
+
+ p->mn_instance_no = n_instance_no;
+
+ nthw_spi_v3_set_timeout(p, 1);
+
+ /* Initialize SPIM module */
+ p->mp_spim_mod = nthw_spim_new();
+
+ result = nthw_spim_init(p->mp_spim_mod, p_fpga, n_instance_no);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spis_init failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ /* Initialize SPIS module */
+ p->mp_spis_mod = nthw_spis_new();
+
+ result = nthw_spis_init(p->mp_spis_mod, p_fpga, n_instance_no);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spim_init failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ /* Reset SPIM and SPIS modules */
+ result = nthw_spim_reset(p->mp_spim_mod);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spim_reset failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ result = nthw_spis_reset(p->mp_spis_mod);
+ if (result != 0) {
+ NT_LOG(ERR, NTHW, "%s: nthw_spis_reset failed: %d\n",
+ p_adapter_id_str, result);
+ }
+
+ return result;
+}
+
+/*
+ * Send Tx data using the SPIM module and receive any data using the SPIS module.
+ * The data are sent and received being wrapped into a SPI v3 container.
+ */
+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode,
+ struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf)
+{
+ const uint16_t max_payload_rx_size = rx_buf->size;
+ int result = 0;
+
+#pragma pack(push, 1)
+ union {
+ uint32_t raw;
+
+ struct {
+ uint16_t opcode;
+ uint16_t size;
+ };
+ } spi_tx_hdr;
+
+ union {
+ uint32_t raw;
+
+ struct {
+ uint16_t error_code;
+ uint16_t size;
+ };
+ } spi_rx_hdr;
+#pragma pack(pop)
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, "%s: Started\n", __func__);
+#endif
+
+ /* Disable transmission from Tx FIFO */
+ result = nthw_spim_enable(p->mp_spim_mod, false);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n");
+ return result;
+ }
+
+ /* Enable SPIS module */
+ result = nthw_spis_enable(p->mp_spis_mod, true);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spis_enable failed\n");
+ return result;
+ }
+
+ /* Put data into Tx FIFO */
+ spi_tx_hdr.opcode = opcode;
+ spi_tx_hdr.size = tx_buf->size;
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, "opcode=0x%04X tx_bufsize=0x%04X rx_bufsize=0x%04X\n",
+ opcode, tx_buf->size, rx_buf->size);
+
+#endif /* SPI_V3_DEBUG_PRINT */
+
+ result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(spi_tx_hdr.raw));
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed\n");
+ return result;
+ }
+
+ {
+ uint8_t *tx_data = (uint8_t *)tx_buf->p_buf;
+ uint16_t tx_size = tx_buf->size;
+ uint16_t count;
+ uint32_t value;
+
+ while (tx_size > 0) {
+ if (tx_size > 4) {
+ count = 4;
+ } else {
+ count = tx_size;
+ value = 0;
+ }
+
+ memcpy(&value, tx_data, count);
+
+ result = nthw_spim_write_tx_fifo(p->mp_spim_mod,
+ htonl(value));
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spim_write_tx_fifo failed\n");
+ return result;
+ }
+
+ tx_size = (uint16_t)(tx_size - count);
+ tx_data += count;
+ }
+ }
+
+ /* Enable Tx FIFO */
+ result = nthw_spim_enable(p->mp_spim_mod, true);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW, "nthw_spim_enable failed\n");
+ return result;
+ }
+
+ result = wait_for_tx_data_sent(p->mp_spim_mod, p->m_time_out);
+ if (result != 0)
+ return result;
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, "%s: SPI header and payload data have been sent\n",
+ __func__);
+#endif
+
+ {
+ /*
+ * Start receiving data
+ * The first data to read is the header
+ */
+ uint16_t rx_size = sizeof(spi_rx_hdr.raw);
+ uint8_t *rx_data = (uint8_t *)rx_buf->p_buf;
+ bool rx_hdr_read = false;
+
+ rx_buf->size = 0;
+
+ while (true) {
+ uint16_t count;
+ uint32_t value;
+
+ if (!rx_hdr_read) { /* Read the header */
+ result = wait_for_rx_data_ready(p->mp_spis_mod,
+ p->m_time_out);
+ if (result != 0)
+ return result;
+
+ result = nthw_spis_read_rx_fifo(p->mp_spis_mod,
+ &spi_rx_hdr.raw);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spis_read_rx_fifo failed\n");
+ return result;
+ }
+
+ spi_rx_hdr.raw = ntohl(spi_rx_hdr.raw);
+ rx_size = spi_rx_hdr.size;
+ rx_hdr_read = true; /* Next time read payload */
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW,
+ " spi_rx_hdr.error_code = 0x%04X, spi_rx_hdr.size = 0x%04X\n",
+ spi_rx_hdr.error_code, spi_rx_hdr.size);
+#endif
+
+ if (spi_rx_hdr.error_code != 0) {
+ result = -1; /* NT_ERROR_AVR_OPCODE_RETURNED_ERROR; */
+ break;
+ }
+
+ if (rx_size > max_payload_rx_size) {
+ result = 1; /* NT_ERROR_AVR_RX_BUFFER_TOO_SMALL; */
+ break;
+ }
+ } else { /* Read the payload */
+ count = (uint16_t)(rx_size < 4U ? rx_size : 4U);
+
+ if (count == 0)
+ break;
+
+ result = wait_for_rx_data_ready(p->mp_spis_mod,
+ p->m_time_out);
+ if (result != 0)
+ return result;
+
+ result = nthw_spis_read_rx_fifo(p->mp_spis_mod,
+ &value);
+ if (result != 0) {
+ NT_LOG(WRN, NTHW,
+ "nthw_spis_read_rx_fifo failed\n");
+ return result;
+ }
+
+ value = ntohl(value); /* Convert to host endian */
+ memcpy(rx_data, &value, count);
+ rx_buf->size = (uint16_t)(rx_buf->size + count);
+ rx_size = (uint16_t)(rx_size - count);
+ rx_data += count;
+ }
+ }
+ }
+
+#ifdef SPI_V3_DEBUG_PRINT
+ NT_LOG(DBG, NTHW, " RxData: %d\n", rx_buf->size);
+ dump_hex(rx_buf->p_buf, rx_buf->size);
+ NT_LOG(DBG, NTHW, "%s: Ended: %d\n", __func__, result);
+#endif
+
+ return result;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.h b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h
new file mode 100644
index 0000000000..c54379a273
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NT4GA_SPI_V3__
+#define __NT4GA_SPI_V3__
+
+/* Must include v1.x series. The first v1.0a only had 248 bytes of storage. v2.0x have 255 */
+#define MAX_AVR_CONTAINER_SIZE (248)
+
+enum avr_opcodes {
+ AVR_OP_NOP = 0, /* v2 NOP command */
+ /* version handlers */
+ AVR_OP_VERSION = 1,
+ AVR_OP_SPI_VERSION = 2, /* v2.0+ command Get protocol version */
+ AVR_OP_SYSINFO = 3,
+ /* Ping handlers */
+ AVR_OP_PING = 4,
+ AVR_OP_PING_DELAY = 5,
+ /* i2c handlers */
+ AVR_OP_I2C_READ = 9,
+ AVR_OP_I2C_WRITE = 10,
+ AVR_OP_I2C_RANDOM_READ = 11,
+ /* VPD handlers */
+ AVR_OP_VPD_READ = 19,
+ AVR_OP_VPD_WRITE = 20,
+ /* SENSOR handlers */
+ AVR_OP_SENSOR_FETCH = 28,
+ /* The following command are only relevant to V3 */
+ AVR_OP_SENSOR_MON_CONTROL = 42,
+ AVR_OP_SENSOR_MON_SETUP = 43,
+ /* special version handler */
+ AVR_OP_SYSINFO_2 = 62,
+};
+
+#define GEN2_AVR_IDENT_SIZE (20)
+#define GEN2_AVR_VERSION_SIZE (50)
+
+#define GEN2_PN_SIZE (13)
+#define GEN2_PBA_SIZE (16)
+#define GEN2_SN_SIZE (10)
+#define GEN2_BNAME_SIZE (14)
+#define GEN2_PLATFORM_SIZE (72)
+#define GEN2_VPD_SIZE_TOTAL \
+ (1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + GEN2_SN_SIZE + GEN2_BNAME_SIZE + \
+ GEN2_PLATFORM_SIZE + 2)
+
+typedef struct vpd_eeprom_s {
+ uint8_t psu_hw_version; /* Hw revision - MUST NEVER ne overwritten. */
+ /* Vital Product Data: P/N (13bytes ascii 0-9) */
+ uint8_t vpd_pn[GEN2_PN_SIZE];
+ /* Vital Product Data: PBA (16bytes ascii 0-9) */
+ uint8_t vpd_pba[GEN2_PBA_SIZE];
+ /* Vital Product Data: S/N (10bytes ascii 0-9) */
+ uint8_t vpd_sn[GEN2_SN_SIZE];
+ /* Vital Product Data: Board Name (10bytes ascii) (e.g. "ntmainb1e2" or "ntfront20b1") */
+ uint8_t vpd_board_name[GEN2_BNAME_SIZE];
+ /*
+ * Vital Product Data: Other (72bytes of MAC addresses or other stuff.. (gives up to 12 mac
+ * addresses)
+ */
+ uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];
+ /* CRC16 checksum of all of above. This field is not included in the checksum */
+ uint16_t crc16;
+} vpd_eeprom_t;
+
+typedef struct {
+ uint8_t psu_hw_revision;
+ char board_type[GEN2_BNAME_SIZE + 1];
+ char product_id[GEN2_PN_SIZE + 1];
+ char pba_id[GEN2_PBA_SIZE + 1];
+ char serial_number[GEN2_SN_SIZE + 1];
+ uint8_t product_family;
+ uint32_t feature_mask;
+ uint32_t invfeature_mask;
+ uint8_t no_of_macs;
+ uint8_t mac_address[6];
+ uint16_t custom_id;
+ uint8_t user_id[8];
+} board_info_t;
+
+struct tx_rx_buf {
+ uint16_t size;
+ void *p_buf;
+};
+
+struct nthw__spi__v3 {
+ int m_time_out;
+ int mn_instance_no;
+ nthw_spim_t *mp_spim_mod;
+ nthw_spis_t *mp_spis_mod;
+};
+
+typedef struct nthw__spi__v3 nthw_spi_v3_t;
+typedef struct nthw__spi__v3 nthw_spi_v3;
+
+nthw_spi_v3_t *nthw_spi_v3_new(void);
+int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no);
+void nthw_spi_v3_delete(nthw_spi_v3_t *p);
+
+int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out);
+int nthw_spi_v3_get_version(nthw_spi_v3_t *p);
+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode,
+ struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf);
+
+#endif /* __NT4GA_SPI_V3__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.c b/drivers/net/ntnic/nthw/core/nthw_spim.c
new file mode 100644
index 0000000000..ece7db26e1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spim.c
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_spim.h"
+
+nthw_spim_t *nthw_spim_new(void)
+{
+ nthw_spim_t *p = malloc(sizeof(nthw_spim_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_spim_t));
+ return p;
+}
+
+int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIM, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: SPIM %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_spim = mod;
+
+ /* SPIM is a primary communication channel - turn off debug by default */
+ module_set_debug_mode(p->mp_mod_spim, 0x00);
+
+ p->mp_reg_srr = module_get_register(p->mp_mod_spim, SPIM_SRR);
+ p->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIM_SRR_RST);
+
+ p->mp_reg_cr = module_get_register(p->mp_mod_spim, SPIM_CR);
+ p->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIM_CR_LOOP);
+ p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIM_CR_EN);
+ p->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIM_CR_TXRST);
+ p->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIM_CR_RXRST);
+
+ p->mp_reg_sr = module_get_register(p->mp_mod_spim, SPIM_SR);
+ p->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIM_SR_DONE);
+ p->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIM_SR_TXEMPTY);
+ p->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIM_SR_RXEMPTY);
+ p->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIM_SR_TXFULL);
+ p->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIM_SR_RXFULL);
+ p->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIM_SR_TXLVL);
+ p->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIM_SR_RXLVL);
+
+ p->mp_reg_dtr = module_get_register(p->mp_mod_spim, SPIM_DTR);
+ p->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIM_DTR_DTR);
+
+ p->mp_reg_drr = module_get_register(p->mp_mod_spim, SPIM_DRR);
+ p->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIM_DRR_DRR);
+
+ p->mp_reg_cfg = module_get_register(p->mp_mod_spim, SPIM_CFG);
+ p->mp_fld_cfg_pre = register_get_field(p->mp_reg_cfg, SPIM_CFG_PRE);
+
+ return 0;
+}
+
+void nthw_spim_delete(nthw_spim_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_spim_t));
+ free(p);
+ }
+}
+
+uint32_t nthw_spim_reset(nthw_spim_t *p)
+{
+ register_update(p->mp_reg_srr);
+ field_set_val32(p->mp_fld_srr_rst,
+ 0x0A); /* 0x0A hardcoded value - see doc */
+ register_flush(p->mp_reg_srr, 1);
+
+ return 0;
+}
+
+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_cr_en);
+
+ if (b_enable)
+ field_set_all(p->mp_fld_cr_en);
+
+ else
+ field_clr_all(p->mp_fld_cr_en);
+ field_flush_register(p->mp_fld_cr_en);
+
+ return 0;
+}
+
+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data)
+{
+ field_set_val_flush32(p->mp_fld_dtr_dtr, n_data);
+ return 0;
+}
+
+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty)
+{
+ assert(pb_empty);
+
+ *pb_empty = field_get_updated(p->mp_fld_sr_txempty) ? true : false;
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.h b/drivers/net/ntnic/nthw/core/nthw_spim.h
new file mode 100644
index 0000000000..713751e563
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spim.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SPIM_H__
+#define __NTHW_SPIM_H__
+
+struct nthw_spim {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_spim;
+ int mn_instance;
+
+ nt_register_t *mp_reg_srr;
+ nt_field_t *mp_fld_srr_rst;
+
+ nt_register_t *mp_reg_cr;
+ nt_field_t *mp_fld_cr_loop;
+ nt_field_t *mp_fld_cr_en;
+ nt_field_t *mp_fld_cr_txrst;
+ nt_field_t *mp_fld_cr_rxrst;
+
+ nt_register_t *mp_reg_sr;
+ nt_field_t *mp_fld_sr_done;
+ nt_field_t *mp_fld_sr_txempty;
+ nt_field_t *mp_fld_sr_rxempty;
+ nt_field_t *mp_fld_sr_txfull;
+ nt_field_t *mp_fld_sr_rxfull;
+ nt_field_t *mp_fld_sr_txlvl;
+ nt_field_t *mp_fld_sr_rxlvl;
+
+ nt_register_t *mp_reg_dtr;
+ nt_field_t *mp_fld_dtr_dtr;
+
+ nt_register_t *mp_reg_drr;
+ nt_field_t *mp_fld_drr_drr;
+ nt_register_t *mp_reg_cfg;
+ nt_field_t *mp_fld_cfg_pre;
+};
+
+typedef struct nthw_spim nthw_spim_t;
+typedef struct nthw_spim nthw_spim;
+
+nthw_spim_t *nthw_spim_new(void);
+int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_spim_delete(nthw_spim_t *p);
+
+uint32_t nthw_spim_reset(nthw_spim_t *p);
+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable);
+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty);
+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data);
+
+#endif /* __NTHW_SPIM_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.c b/drivers/net/ntnic/nthw/core/nthw_spis.c
new file mode 100644
index 0000000000..8799584194
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spis.c
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_spis.h"
+
+nthw_spis_t *nthw_spis_new(void)
+{
+ nthw_spis_t *p = malloc(sizeof(nthw_spis_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_spis_t));
+ return p;
+}
+
+int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIS, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: SPIS %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_spis = mod;
+
+ /* SPIS is a primary communication channel - turn off debug by default */
+ module_set_debug_mode(p->mp_mod_spis, 0x00);
+
+ p->mp_reg_srr = module_get_register(p->mp_mod_spis, SPIS_SRR);
+ p->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIS_SRR_RST);
+
+ p->mp_reg_cr = module_get_register(p->mp_mod_spis, SPIS_CR);
+ p->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIS_CR_LOOP);
+ p->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIS_CR_EN);
+ p->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIS_CR_TXRST);
+ p->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIS_CR_RXRST);
+ p->mp_fld_cr_debug = register_get_field(p->mp_reg_cr, SPIS_CR_DEBUG);
+
+ p->mp_reg_sr = module_get_register(p->mp_mod_spis, SPIS_SR);
+ p->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIS_SR_DONE);
+ p->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIS_SR_TXEMPTY);
+ p->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIS_SR_RXEMPTY);
+ p->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIS_SR_TXFULL);
+ p->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIS_SR_RXFULL);
+ p->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIS_SR_TXLVL);
+ p->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIS_SR_RXLVL);
+ p->mp_fld_sr_frame_err =
+ register_get_field(p->mp_reg_sr, SPIS_SR_FRAME_ERR);
+ p->mp_fld_sr_read_err = register_get_field(p->mp_reg_sr, SPIS_SR_READ_ERR);
+ p->mp_fld_sr_write_err =
+ register_get_field(p->mp_reg_sr, SPIS_SR_WRITE_ERR);
+
+ p->mp_reg_dtr = module_get_register(p->mp_mod_spis, SPIS_DTR);
+ p->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIS_DTR_DTR);
+
+ p->mp_reg_drr = module_get_register(p->mp_mod_spis, SPIS_DRR);
+ p->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIS_DRR_DRR);
+
+ p->mp_reg_ram_ctrl = module_get_register(p->mp_mod_spis, SPIS_RAM_CTRL);
+ p->mp_fld_ram_ctrl_adr =
+ register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_ADR);
+ p->mp_fld_ram_ctrl_cnt =
+ register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_CNT);
+
+ p->mp_reg_ram_data = module_get_register(p->mp_mod_spis, SPIS_RAM_DATA);
+ p->mp_fld_ram_data_data =
+ register_get_field(p->mp_reg_ram_data, SPIS_RAM_DATA_DATA);
+
+ return 0;
+}
+
+void nthw_spis_delete(nthw_spis_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_spis_t));
+ free(p);
+ }
+}
+
+uint32_t nthw_spis_reset(nthw_spis_t *p)
+{
+ register_update(p->mp_reg_srr);
+ field_set_val32(p->mp_fld_srr_rst,
+ 0x0A); /* 0x0A hardcoded value - see doc */
+ register_flush(p->mp_reg_srr, 1);
+
+ return 0;
+}
+
+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_cr_en);
+
+ if (b_enable)
+ field_set_all(p->mp_fld_cr_en);
+
+ else
+ field_clr_all(p->mp_fld_cr_en);
+ field_flush_register(p->mp_fld_cr_en);
+
+ return 0;
+}
+
+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty)
+{
+ assert(pb_empty);
+
+ *pb_empty = field_get_updated(p->mp_fld_sr_rxempty) ? true : false;
+
+ return 0;
+}
+
+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data)
+{
+ assert(p_data);
+
+ *p_data = field_get_updated(p->mp_fld_drr_drr);
+
+ return 0;
+}
+
+uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx,
+ uint32_t *p_sensor_result)
+{
+ assert(p_sensor_result);
+
+ field_set_val32(p->mp_fld_ram_ctrl_adr, n_result_idx);
+ field_set_val32(p->mp_fld_ram_ctrl_cnt, 1);
+ register_flush(p->mp_reg_ram_ctrl, 1);
+
+ *p_sensor_result = field_get_updated(p->mp_fld_ram_data_data);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.h b/drivers/net/ntnic/nthw/core/nthw_spis.h
new file mode 100644
index 0000000000..2ebe840c9e
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spis.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SPIS_H__
+#define __NTHW_SPIS_H__
+
+struct nthw_spis {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_spis;
+ int mn_instance;
+
+ nt_register_t *mp_reg_srr;
+ nt_field_t *mp_fld_srr_rst;
+
+ nt_register_t *mp_reg_cr;
+ nt_field_t *mp_fld_cr_loop;
+ nt_field_t *mp_fld_cr_en;
+ nt_field_t *mp_fld_cr_txrst;
+ nt_field_t *mp_fld_cr_rxrst;
+ nt_field_t *mp_fld_cr_debug;
+
+ nt_register_t *mp_reg_sr;
+ nt_field_t *mp_fld_sr_done;
+ nt_field_t *mp_fld_sr_txempty;
+ nt_field_t *mp_fld_sr_rxempty;
+ nt_field_t *mp_fld_sr_txfull;
+ nt_field_t *mp_fld_sr_rxfull;
+ nt_field_t *mp_fld_sr_txlvl;
+ nt_field_t *mp_fld_sr_rxlvl;
+ nt_field_t *mp_fld_sr_frame_err;
+ nt_field_t *mp_fld_sr_read_err;
+ nt_field_t *mp_fld_sr_write_err;
+
+ nt_register_t *mp_reg_dtr;
+ nt_field_t *mp_fld_dtr_dtr;
+
+ nt_register_t *mp_reg_drr;
+ nt_field_t *mp_fld_drr_drr;
+
+ nt_register_t *mp_reg_ram_ctrl;
+ nt_field_t *mp_fld_ram_ctrl_adr;
+ nt_field_t *mp_fld_ram_ctrl_cnt;
+
+ nt_register_t *mp_reg_ram_data;
+ nt_field_t *mp_fld_ram_data_data;
+};
+
+typedef struct nthw_spis nthw_spis_t;
+typedef struct nthw_spis nthw_spis;
+
+nthw_spis_t *nthw_spis_new(void);
+int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_spis_delete(nthw_spis_t *p);
+
+uint32_t nthw_spis_reset(nthw_spis_t *p);
+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable);
+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty);
+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data);
+uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx,
+ uint32_t *p_sensor_result);
+
+#endif /* __NTHW_SPIS_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.c b/drivers/net/ntnic/nthw/core/nthw_tsm.c
new file mode 100644
index 0000000000..8ea4a4c440
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_tsm.c
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_tsm.h"
+
+nthw_tsm_t *nthw_tsm_new(void)
+{
+ nthw_tsm_t *p = malloc(sizeof(nthw_tsm_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_tsm_t));
+ return p;
+}
+
+void nthw_tsm_delete(nthw_tsm_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_tsm_t));
+ free(p);
+ }
+}
+
+int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_TSM, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TSM %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_tsm = mod;
+
+ {
+ nt_register_t *p_reg;
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_CONFIG);
+ p->mp_fld_config_ts_format =
+ register_get_field(p_reg, TSM_CONFIG_TS_FORMAT);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_CTRL);
+ p->mp_fld_timer_ctrl_timer_en_t0 =
+ register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T0);
+ p->mp_fld_timer_ctrl_timer_en_t1 =
+ register_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T1);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T0);
+ p->mp_fld_timer_timer_t0_max_count =
+ register_get_field(p_reg, TSM_TIMER_T0_MAX_COUNT);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T1);
+ p->mp_fld_timer_timer_t1_max_count =
+ register_get_field(p_reg, TSM_TIMER_T1_MAX_COUNT);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_LO);
+ p->mp_reg_time_lo = module_get_register(p->mp_mod_tsm, TSM_TIME_LO);
+ p->mp_fld_time_lo = register_get_field(p_reg, TSM_TIME_LO_NS);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_HI);
+ p->mp_reg_time_hi = module_get_register(p->mp_mod_tsm, TSM_TIME_HI);
+ p->mp_fld_time_hi = register_get_field(p_reg, TSM_TIME_HI_SEC);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TS_LO);
+ p->mp_reg_ts_lo = module_get_register(p->mp_mod_tsm, TSM_TS_LO);
+ p->mp_fld_ts_lo = register_get_field(p_reg, TSM_TS_LO_TIME);
+
+ p_reg = module_get_register(p->mp_mod_tsm, TSM_TS_HI);
+ p->mp_reg_ts_hi = module_get_register(p->mp_mod_tsm, TSM_TS_HI);
+ p->mp_fld_ts_hi = register_get_field(p_reg, TSM_TS_HI_TIME);
+ }
+ return 0;
+}
+
+int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts)
+{
+ uint32_t n_ts_lo, n_ts_hi;
+ uint64_t val;
+
+ if (!p_ts)
+ return -1;
+
+ n_ts_lo = field_get_updated(p->mp_fld_ts_lo);
+ n_ts_hi = field_get_updated(p->mp_fld_ts_hi);
+
+ val = ((((uint64_t)n_ts_hi) << 32UL) | n_ts_lo);
+
+ if (p_ts)
+ *p_ts = val;
+
+ return 0;
+}
+
+int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time)
+{
+ uint32_t n_time_lo, n_time_hi;
+ uint64_t val;
+
+ if (!p_time)
+ return -1;
+
+ n_time_lo = field_get_updated(p->mp_fld_time_lo);
+ n_time_hi = field_get_updated(p->mp_fld_time_hi);
+
+ val = ((((uint64_t)n_time_hi) << 32UL) | n_time_lo);
+
+ if (p_time)
+ *p_time = val;
+
+ return 0;
+}
+
+int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time)
+{
+ field_set_val_flush32(p->mp_fld_time_lo, (n_time & 0xFFFFFFFF));
+ field_set_val_flush32(p->mp_fld_time_hi,
+ (uint32_t)((n_time >> 32) & 0xFFFFFFFF));
+ return 0;
+}
+
+int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_timer_ctrl_timer_en_t0);
+ if (b_enable)
+ field_set_flush(p->mp_fld_timer_ctrl_timer_en_t0);
+
+ else
+ field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t0);
+ return 0;
+}
+
+int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val)
+{
+ /* Timer T0 - stat toggle timer */
+ field_update_register(p->mp_fld_timer_timer_t0_max_count);
+ field_set_val_flush32(p->mp_fld_timer_timer_t0_max_count,
+ n_timer_val); /* ns (50*1000*1000) */
+ return 0;
+}
+
+int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable)
+{
+ field_update_register(p->mp_fld_timer_ctrl_timer_en_t1);
+ if (b_enable)
+ field_set_flush(p->mp_fld_timer_ctrl_timer_en_t1);
+
+ else
+ field_clr_flush(p->mp_fld_timer_ctrl_timer_en_t1);
+ return 0;
+}
+
+int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val)
+{
+ /* Timer T1 - keep alive timer */
+ field_update_register(p->mp_fld_timer_timer_t1_max_count);
+ field_set_val_flush32(p->mp_fld_timer_timer_t1_max_count,
+ n_timer_val); /* ns (100*1000*1000) */
+ return 0;
+}
+
+int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val)
+{
+ field_update_register(p->mp_fld_config_ts_format);
+ /* 0x1: Native - 10ns units, start date: 1970-01-01. */
+ field_set_val_flush32(p->mp_fld_config_ts_format, n_val);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.h b/drivers/net/ntnic/nthw/core/nthw_tsm.h
new file mode 100644
index 0000000000..590e04c312
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_tsm.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_TSM_H__
+#define __NTHW_TSM_H__
+
+struct nthw_tsm {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_tsm;
+ int mn_instance;
+
+ nt_field_t *mp_fld_config_ts_format;
+
+ nt_field_t *mp_fld_timer_ctrl_timer_en_t0;
+ nt_field_t *mp_fld_timer_ctrl_timer_en_t1;
+
+ nt_field_t *mp_fld_timer_timer_t0_max_count;
+
+ nt_field_t *mp_fld_timer_timer_t1_max_count;
+
+ nt_register_t *mp_reg_ts_lo;
+ nt_field_t *mp_fld_ts_lo;
+
+ nt_register_t *mp_reg_ts_hi;
+ nt_field_t *mp_fld_ts_hi;
+
+ nt_register_t *mp_reg_time_lo;
+ nt_field_t *mp_fld_time_lo;
+
+ nt_register_t *mp_reg_time_hi;
+ nt_field_t *mp_fld_time_hi;
+};
+
+typedef struct nthw_tsm nthw_tsm_t;
+typedef struct nthw_tsm nthw_tsm;
+
+nthw_tsm_t *nthw_tsm_new(void);
+void nthw_tsm_delete(nthw_tsm_t *p);
+int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts);
+int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time);
+int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time);
+
+int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable);
+int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val);
+int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable);
+int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val);
+
+int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val);
+
+#endif /* __NTHW_TSM_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_dbs.c b/drivers/net/ntnic/nthw/nthw_dbs.c
new file mode 100644
index 0000000000..9fc853da73
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_dbs.c
@@ -0,0 +1,1301 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <errno.h>
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_dbs.h"
+
+#undef DBS_PRINT_REGS
+
+static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable,
+ uint32_t ir, uint32_t bs);
+static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index,
+ uint32_t virtual_port);
+static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed);
+static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t header,
+ uint32_t packed);
+static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order);
+static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec,
+ uint32_t istk);
+static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index);
+static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index);
+
+nthw_dbs_t *nthw_dbs_new(void)
+{
+ nthw_dbs_t *p = malloc(sizeof(nthw_dbs_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_dbs_t));
+ return p;
+}
+
+void nthw_dbs_delete(nthw_dbs_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_dbs_t));
+ free(p);
+ }
+}
+
+int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_DBS, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: DBS %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_dbs = mod;
+
+ p->mn_param_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);
+ if (p->mn_param_dbs_present == 0) {
+ NT_LOG(WRN, NTHW,
+ "%s: DBS %d: logical error: module found but not flagged at present\n",
+ p->mp_fpga->p_fpga_info->mp_adapter_id_str, p->mn_instance);
+ }
+
+ p->mp_reg_rx_control = module_get_register(p->mp_mod_dbs, DBS_RX_CONTROL);
+ p->mp_fld_rx_control_last_queue =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_LQ);
+ p->mp_fld_rx_control_avail_monitor_enable =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AME);
+ p->mp_fld_rx_control_avail_monitor_scan_speed =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AMS);
+ p->mp_fld_rx_control_used_write_enable =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWE);
+ p->mp_fld_rx_control_used_writer_update_speed =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWS);
+ p->mp_fld_rx_control_rx_queues_enable =
+ register_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_QE);
+
+ p->mp_reg_tx_control = module_get_register(p->mp_mod_dbs, DBS_TX_CONTROL);
+ p->mp_fld_tx_control_last_queue =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_LQ);
+ p->mp_fld_tx_control_avail_monitor_enable =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AME);
+ p->mp_fld_tx_control_avail_monitor_scan_speed =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AMS);
+ p->mp_fld_tx_control_used_write_enable =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWE);
+ p->mp_fld_tx_control_used_writer_update_speed =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWS);
+ p->mp_fld_tx_control_tx_queues_enable =
+ register_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_QE);
+
+ p->mp_reg_rx_init = module_get_register(p->mp_mod_dbs, DBS_RX_INIT);
+ p->mp_fld_rx_init_init =
+ register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_INIT);
+ p->mp_fld_rx_init_queue =
+ register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_QUEUE);
+ p->mp_fld_rx_init_busy =
+ register_get_field(p->mp_reg_rx_init, DBS_RX_INIT_BUSY);
+
+ p->mp_reg_rx_init_val = module_query_register(p->mp_mod_dbs, DBS_RX_INIT_VAL);
+ if (p->mp_reg_rx_init_val) {
+ p->mp_fld_rx_init_val_idx = register_query_field(p->mp_reg_rx_init_val,
+ DBS_RX_INIT_VAL_IDX);
+ p->mp_fld_rx_init_val_ptr = register_query_field(p->mp_reg_rx_init_val,
+ DBS_RX_INIT_VAL_PTR);
+ }
+
+ p->mp_reg_rx_ptr = module_query_register(p->mp_mod_dbs, DBS_RX_PTR);
+ if (p->mp_reg_rx_ptr) {
+ p->mp_fld_rx_ptr_ptr =
+ register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_PTR);
+ p->mp_fld_rx_ptr_queue =
+ register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_QUEUE);
+ p->mp_fld_rx_ptr_valid =
+ register_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_VALID);
+ }
+
+ p->mp_reg_tx_init = module_get_register(p->mp_mod_dbs, DBS_TX_INIT);
+ p->mp_fld_tx_init_init =
+ register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_INIT);
+ p->mp_fld_tx_init_queue =
+ register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_QUEUE);
+ p->mp_fld_tx_init_busy =
+ register_get_field(p->mp_reg_tx_init, DBS_TX_INIT_BUSY);
+
+ p->mp_reg_tx_init_val = module_query_register(p->mp_mod_dbs, DBS_TX_INIT_VAL);
+ if (p->mp_reg_tx_init_val) {
+ p->mp_fld_tx_init_val_idx = register_query_field(p->mp_reg_tx_init_val,
+ DBS_TX_INIT_VAL_IDX);
+ p->mp_fld_tx_init_val_ptr = register_query_field(p->mp_reg_tx_init_val,
+ DBS_TX_INIT_VAL_PTR);
+ }
+
+ p->mp_reg_tx_ptr = module_query_register(p->mp_mod_dbs, DBS_TX_PTR);
+ if (p->mp_reg_tx_ptr) {
+ p->mp_fld_tx_ptr_ptr =
+ register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_PTR);
+ p->mp_fld_tx_ptr_queue =
+ register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_QUEUE);
+ p->mp_fld_tx_ptr_valid =
+ register_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_VALID);
+ }
+
+ p->mp_reg_rx_idle = module_query_register(p->mp_mod_dbs, DBS_RX_IDLE);
+ if (p->mp_reg_rx_idle) {
+ p->mp_fld_rx_idle_idle =
+ register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_IDLE);
+ p->mp_fld_rx_idle_queue =
+ register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_QUEUE);
+ p->mp_fld_rx_idle_busy =
+ register_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_BUSY);
+ }
+
+ p->mp_reg_tx_idle = module_query_register(p->mp_mod_dbs, DBS_TX_IDLE);
+ if (p->mp_reg_tx_idle) {
+ p->mp_fld_tx_idle_idle =
+ register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_IDLE);
+ p->mp_fld_tx_idle_queue =
+ register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_QUEUE);
+ p->mp_fld_tx_idle_busy =
+ register_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_BUSY);
+ }
+
+ p->mp_reg_rx_avail_monitor_control =
+ module_get_register(p->mp_mod_dbs, DBS_RX_AM_CTRL);
+ p->mp_fld_rx_avail_monitor_control_adr =
+ register_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_ADR);
+ p->mp_fld_rx_avail_monitor_control_cnt =
+ register_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_CNT);
+
+ p->mp_reg_rx_avail_monitor_data =
+ module_get_register(p->mp_mod_dbs, DBS_RX_AM_DATA);
+ p->mp_fld_rx_avail_monitor_data_guest_physical_address =
+ register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_GPA);
+ p->mp_fld_rx_avail_monitor_data_enable =
+ register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_ENABLE);
+ p->mp_fld_rx_avail_monitor_data_host_id =
+ register_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_HID);
+ p->mp_fld_rx_avail_monitor_data_packed =
+ register_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_PCKED);
+ p->mp_fld_rx_avail_monitor_data_int =
+ register_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_INT);
+
+ p->mp_reg_tx_avail_monitor_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_AM_CTRL);
+ p->mp_fld_tx_avail_monitor_control_adr =
+ register_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_ADR);
+ p->mp_fld_tx_avail_monitor_control_cnt =
+ register_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_CNT);
+
+ p->mp_reg_tx_avail_monitor_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_AM_DATA);
+ p->mp_fld_tx_avail_monitor_data_guest_physical_address =
+ register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_GPA);
+ p->mp_fld_tx_avail_monitor_data_enable =
+ register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_ENABLE);
+ p->mp_fld_tx_avail_monitor_data_host_id =
+ register_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_HID);
+ p->mp_fld_tx_avail_monitor_data_packed =
+ register_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_PCKED);
+ p->mp_fld_tx_avail_monitor_data_int =
+ register_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_INT);
+
+ p->mp_reg_rx_used_writer_control =
+ module_get_register(p->mp_mod_dbs, DBS_RX_UW_CTRL);
+ p->mp_fld_rx_used_writer_control_adr =
+ register_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_ADR);
+ p->mp_fld_rx_used_writer_control_cnt =
+ register_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_CNT);
+
+ p->mp_reg_rx_used_writer_data =
+ module_get_register(p->mp_mod_dbs, DBS_RX_UW_DATA);
+ p->mp_fld_rx_used_writer_data_guest_physical_address =
+ register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_GPA);
+ p->mp_fld_rx_used_writer_data_host_id =
+ register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_HID);
+ p->mp_fld_rx_used_writer_data_queue_size =
+ register_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_QS);
+ p->mp_fld_rx_used_writer_data_packed =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_PCKED);
+ p->mp_fld_rx_used_writer_data_int =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_INT);
+ p->mp_fld_rx_used_writer_data_vec =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_VEC);
+ p->mp_fld_rx_used_writer_data_istk =
+ register_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_ISTK);
+
+ p->mp_reg_tx_used_writer_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_UW_CTRL);
+ p->mp_fld_tx_used_writer_control_adr =
+ register_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_ADR);
+ p->mp_fld_tx_used_writer_control_cnt =
+ register_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_CNT);
+
+ p->mp_reg_tx_used_writer_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_UW_DATA);
+ p->mp_fld_tx_used_writer_data_guest_physical_address =
+ register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_GPA);
+ p->mp_fld_tx_used_writer_data_host_id =
+ register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_HID);
+ p->mp_fld_tx_used_writer_data_queue_size =
+ register_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_QS);
+ p->mp_fld_tx_used_writer_data_packed =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_PCKED);
+ p->mp_fld_tx_used_writer_data_int =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INT);
+ p->mp_fld_tx_used_writer_data_vec =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_VEC);
+ p->mp_fld_tx_used_writer_data_istk =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_ISTK);
+ p->mp_fld_tx_used_writer_data_in_order =
+ register_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INO);
+
+ p->mp_reg_rx_descriptor_reader_control =
+ module_get_register(p->mp_mod_dbs, DBS_RX_DR_CTRL);
+ p->mp_fld_rx_descriptor_reader_control_adr =
+ register_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_ADR);
+ p->mp_fld_rx_descriptor_reader_control_cnt =
+ register_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_CNT);
+
+ p->mp_reg_rx_descriptor_reader_data =
+ module_get_register(p->mp_mod_dbs, DBS_RX_DR_DATA);
+ p->mp_fld_rx_descriptor_reader_data_guest_physical_address =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_GPA);
+ p->mp_fld_rx_descriptor_reader_data_host_id =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HID);
+ p->mp_fld_rx_descriptor_reader_data_queue_size =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_QS);
+ p->mp_fld_rx_descriptor_reader_data_header =
+ register_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HDR);
+ p->mp_fld_rx_descriptor_reader_data_packed =
+ register_query_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_PCKED);
+
+ p->mp_reg_tx_descriptor_reader_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_DR_CTRL);
+ p->mp_fld_tx_descriptor_reader_control_adr =
+ register_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_ADR);
+ p->mp_fld_tx_descriptor_reader_control_cnt =
+ register_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_CNT);
+
+ p->mp_reg_tx_descriptor_reader_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_DR_DATA);
+ p->mp_fld_tx_descriptor_reader_data_guest_physical_address =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_GPA);
+ p->mp_fld_tx_descriptor_reader_data_host_id =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HID);
+ p->mp_fld_tx_descriptor_reader_data_queue_size =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_QS);
+ p->mp_fld_tx_descriptor_reader_data_header =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HDR);
+ p->mp_fld_tx_descriptor_reader_data_port =
+ register_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PORT);
+ p->mp_fld_tx_descriptor_reader_data_packed =
+ register_query_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PCKED);
+
+ p->mp_reg_tx_queue_property_control =
+ module_get_register(p->mp_mod_dbs, DBS_TX_QP_CTRL);
+ p->mp_fld_tx_queue_property_control_adr =
+ register_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_ADR);
+ p->mp_fld_tx_queue_property_control_cnt =
+ register_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_CNT);
+
+ p->mp_reg_tx_queue_property_data =
+ module_get_register(p->mp_mod_dbs, DBS_TX_QP_DATA);
+ p->mp_fld_tx_queue_property_data_v_port =
+ register_get_field(p->mp_reg_tx_queue_property_data, DBS_TX_QP_DATA_VPORT);
+
+ /* HW QoS Tx rate limiting policing RFC2697/RFC4111 */
+ p->mp_reg_tx_queue_qos_control =
+ module_query_register(p->mp_mod_dbs, DBS_TX_QOS_CTRL);
+ p->mp_reg_tx_queue_qos_data =
+ module_query_register(p->mp_mod_dbs, DBS_TX_QOS_DATA);
+ if (p->mp_reg_tx_queue_qos_control) {
+ p->mp_reg_tx_queue_qos_control_adr =
+ register_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_ADR);
+ p->mp_reg_tx_queue_qos_control_cnt =
+ register_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_CNT);
+
+ if (p->mp_reg_tx_queue_qos_data) {
+ p->mp_reg_tx_queue_qos_data_en =
+ register_query_field(p->mp_reg_tx_queue_qos_data,
+ DBS_TX_QOS_DATA_EN);
+ p->mp_reg_tx_queue_qos_data_ir =
+ register_query_field(p->mp_reg_tx_queue_qos_data,
+ DBS_TX_QOS_DATA_IR);
+ p->mp_reg_tx_queue_qos_data_bs =
+ register_query_field(p->mp_reg_tx_queue_qos_data,
+ DBS_TX_QOS_DATA_BS);
+ }
+ }
+
+ p->mp_reg_tx_queue_qos_rate =
+ module_query_register(p->mp_mod_dbs, DBS_TX_QOS_RATE);
+ if (p->mp_reg_tx_queue_qos_rate) {
+ p->mp_reg_tx_queue_qos_rate_mul =
+ register_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_MUL);
+ p->mp_reg_tx_queue_qos_rate_div =
+ register_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_DIV);
+ }
+
+ return 0;
+}
+
+int dbs_reset_rx_control(nthw_dbs_t *p)
+{
+ field_set_val32(p->mp_fld_rx_control_last_queue, 0);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_enable, 0);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed, 8);
+ field_set_val32(p->mp_fld_rx_control_used_write_enable, 0);
+ field_set_val32(p->mp_fld_rx_control_used_writer_update_speed, 5);
+ field_set_val32(p->mp_fld_rx_control_rx_queues_enable, 0);
+ register_flush(p->mp_reg_rx_control, 1);
+ return 0;
+}
+
+int dbs_reset_tx_control(nthw_dbs_t *p)
+{
+ field_set_val32(p->mp_fld_tx_control_last_queue, 0);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_enable, 0);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed, 5);
+ field_set_val32(p->mp_fld_tx_control_used_write_enable, 0);
+ field_set_val32(p->mp_fld_tx_control_used_writer_update_speed, 8);
+ field_set_val32(p->mp_fld_tx_control_tx_queues_enable, 0);
+ register_flush(p->mp_reg_tx_control, 1);
+ return 0;
+}
+
+void dbs_reset(nthw_dbs_t *p)
+{
+ uint32_t i;
+
+ NT_LOG(DBG, NTHW, "NthwDbs::%s: resetting DBS", __func__);
+
+ dbs_reset_rx_control(p);
+ dbs_reset_tx_control(p);
+
+ /* Reset RX memory banks and shado */
+ for (i = 0; i < NT_DBS_RX_QUEUES_MAX; ++i) {
+ set_shadow_rx_am_data(p, i, 0, 0, 0, 0, 0);
+ flush_rx_am_data(p, i);
+
+ set_shadow_rx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0);
+ flush_rx_uw_data(p, i);
+
+ set_shadow_rx_dr_data(p, i, 0, 0, 0, 0, 0);
+ flush_rx_dr_data(p, i);
+ }
+
+ /* Reset TX memory banks and shado */
+ for (i = 0; i < NT_DBS_TX_QUEUES_MAX; ++i) {
+ set_shadow_tx_am_data(p, i, 0, 0, 0, 0, 0);
+ flush_tx_am_data(p, i);
+
+ set_shadow_tx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0, 0);
+ flush_tx_uw_data(p, i);
+
+ set_shadow_tx_dr_data(p, i, 0, 0, 0, 0, 0, 0);
+ flush_tx_dr_data(p, i);
+
+ set_shadow_tx_qp_data(p, i, 0);
+ flush_tx_qp_data(p, i);
+
+ set_shadow_tx_qos_data(p, i, 0, 0, 0);
+ flush_tx_qos_data(p, i);
+ }
+}
+
+int set_rx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t rx_queue_enable)
+{
+#ifdef DBS_PRINT_REGS
+ printf("last_queue %u\n", last_queue);
+ printf("avail_monitor_enable %u\n", avail_monitor_enable);
+ printf("avail_monitor_speed %u\n", avail_monitor_speed);
+ printf("used_write_enable %u\n", used_write_enable);
+ printf("used_write_speed %u\n", used_write_speed);
+ printf("rx_queue_enable %u\n", rx_queue_enable);
+#endif
+
+ field_set_val32(p->mp_fld_rx_control_last_queue, last_queue);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_enable, avail_monitor_enable);
+ field_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed,
+ avail_monitor_speed);
+ field_set_val32(p->mp_fld_rx_control_used_write_enable, used_write_enable);
+ field_set_val32(p->mp_fld_rx_control_used_writer_update_speed, used_write_speed);
+ field_set_val32(p->mp_fld_rx_control_rx_queues_enable, rx_queue_enable);
+ register_flush(p->mp_reg_rx_control, 1);
+ return 0;
+}
+
+int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *rx_queue_enable)
+{
+ *last_queue = field_get_val32(p->mp_fld_rx_control_last_queue);
+ *avail_monitor_enable =
+ field_get_val32(p->mp_fld_rx_control_avail_monitor_enable);
+ *avail_monitor_speed =
+ field_get_val32(p->mp_fld_rx_control_avail_monitor_scan_speed);
+ *used_write_enable = field_get_val32(p->mp_fld_rx_control_used_write_enable);
+ *used_write_speed =
+ field_get_val32(p->mp_fld_rx_control_used_writer_update_speed);
+ *rx_queue_enable = field_get_val32(p->mp_fld_rx_control_rx_queues_enable);
+ return 0;
+}
+
+int set_tx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t tx_queue_enable)
+{
+#ifdef DBS_PRINT_REGS
+ printf("last_queue %u\n", last_queue);
+ printf("avail_monitor_enable %u\n", avail_monitor_enable);
+ printf("avail_monitor_speed %u\n", avail_monitor_speed);
+ printf("used_write_enable %u\n", used_write_enable);
+ printf("used_write_speed %u\n", used_write_speed);
+#endif
+
+ field_set_val32(p->mp_fld_tx_control_last_queue, last_queue);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_enable, avail_monitor_enable);
+ field_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed,
+ avail_monitor_speed);
+ field_set_val32(p->mp_fld_tx_control_used_write_enable, used_write_enable);
+ field_set_val32(p->mp_fld_tx_control_used_writer_update_speed, used_write_speed);
+ field_set_val32(p->mp_fld_tx_control_tx_queues_enable, tx_queue_enable);
+ register_flush(p->mp_reg_tx_control, 1);
+ return 0;
+}
+
+int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *tx_queue_enable)
+{
+ *last_queue = field_get_val32(p->mp_fld_tx_control_last_queue);
+ *avail_monitor_enable =
+ field_get_val32(p->mp_fld_tx_control_avail_monitor_enable);
+ *avail_monitor_speed =
+ field_get_val32(p->mp_fld_tx_control_avail_monitor_scan_speed);
+ *used_write_enable = field_get_val32(p->mp_fld_tx_control_used_write_enable);
+ *used_write_speed =
+ field_get_val32(p->mp_fld_tx_control_used_writer_update_speed);
+ *tx_queue_enable = field_get_val32(p->mp_fld_tx_control_tx_queues_enable);
+ return 0;
+}
+
+int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue)
+{
+ if (p->mp_reg_rx_init_val) {
+ field_set_val32(p->mp_fld_rx_init_val_idx, start_idx);
+ field_set_val32(p->mp_fld_rx_init_val_ptr, start_ptr);
+ register_flush(p->mp_reg_rx_init_val, 1);
+ }
+ field_set_val32(p->mp_fld_rx_init_init, init);
+ field_set_val32(p->mp_fld_rx_init_queue, queue);
+ register_flush(p->mp_reg_rx_init, 1);
+ return 0;
+}
+
+int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy)
+{
+ *init = field_get_val32(p->mp_fld_rx_init_init);
+ *queue = field_get_val32(p->mp_fld_rx_init_queue);
+ *busy = field_get_val32(p->mp_fld_rx_init_busy);
+ return 0;
+}
+
+int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue)
+{
+ if (p->mp_reg_tx_init_val) {
+ field_set_val32(p->mp_fld_tx_init_val_idx, start_idx);
+ field_set_val32(p->mp_fld_tx_init_val_ptr, start_ptr);
+ register_flush(p->mp_reg_tx_init_val, 1);
+ }
+ field_set_val32(p->mp_fld_tx_init_init, init);
+ field_set_val32(p->mp_fld_tx_init_queue, queue);
+ register_flush(p->mp_reg_tx_init, 1);
+ return 0;
+}
+
+int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy)
+{
+ *init = field_get_val32(p->mp_fld_tx_init_init);
+ *queue = field_get_val32(p->mp_fld_tx_init_queue);
+ *busy = field_get_val32(p->mp_fld_tx_init_busy);
+ return 0;
+}
+
+int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue)
+
+{
+ if (!p->mp_reg_rx_idle)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_rx_idle_idle, idle);
+ field_set_val32(p->mp_fld_rx_idle_queue, queue);
+ register_flush(p->mp_reg_rx_idle, 1);
+ return 0;
+}
+
+int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy)
+{
+ if (!p->mp_reg_rx_idle)
+ return -ENOTSUP;
+
+ *idle = field_get_updated(p->mp_fld_rx_idle_idle);
+ *queue = 0;
+ *busy = field_get_updated(p->mp_fld_rx_idle_busy);
+ return 0;
+}
+
+int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue)
+
+{
+ if (!p->mp_reg_tx_idle)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_tx_idle_idle, idle);
+ field_set_val32(p->mp_fld_tx_idle_queue, queue);
+ register_flush(p->mp_reg_tx_idle, 1);
+ return 0;
+}
+
+int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy)
+{
+ if (!p->mp_reg_tx_idle)
+ return -ENOTSUP;
+
+ *idle = field_get_updated(p->mp_fld_tx_idle_idle);
+ *queue = 0;
+ *busy = field_get_updated(p->mp_fld_tx_idle_busy);
+ return 0;
+}
+
+int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue)
+{
+ if (!p->mp_reg_rx_ptr)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_rx_ptr_queue, queue);
+ register_flush(p->mp_reg_rx_ptr, 1);
+ return 0;
+}
+
+int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid)
+{
+ if (!p->mp_reg_rx_ptr)
+ return -ENOTSUP;
+
+ *ptr = field_get_updated(p->mp_fld_rx_ptr_ptr);
+ *queue = 0;
+ *valid = field_get_updated(p->mp_fld_rx_ptr_valid);
+ return 0;
+}
+
+int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue)
+{
+ if (!p->mp_reg_tx_ptr)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_fld_tx_ptr_queue, queue);
+ register_flush(p->mp_reg_tx_ptr, 1);
+ return 0;
+}
+
+int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid)
+{
+ if (!p->mp_reg_tx_ptr)
+ return -ENOTSUP;
+
+ *ptr = field_get_updated(p->mp_fld_tx_ptr_ptr);
+ *queue = 0;
+ *valid = field_get_updated(p->mp_fld_tx_ptr_valid);
+ return 0;
+}
+
+static void set_rx_am_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_rx_avail_monitor_control_adr, index);
+ field_set_val32(p->mp_fld_rx_avail_monitor_control_cnt, 1);
+ register_flush(p->mp_reg_rx_avail_monitor_control, 1);
+}
+
+static void
+set_shadow_rx_am_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_rx_am_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void nthw_dbs_set_shadow_rx_am_data_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t enable)
+{
+ p->m_rx_am_shadow[index].enable = enable;
+}
+
+static void set_shadow_rx_am_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_rx_am_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_rx_am_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_rx_am_shadow[index].packed = packed;
+}
+
+static void set_shadow_rx_am_data_int_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t int_enable)
+{
+ p->m_rx_am_shadow[index].int_enable = int_enable;
+}
+
+static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ set_shadow_rx_am_data_guest_physical_address(p, index, guest_physical_address);
+ nthw_dbs_set_shadow_rx_am_data_enable(p, index, enable);
+ set_shadow_rx_am_data_host_id(p, index, host_id);
+ set_shadow_rx_am_data_packed(p, index, packed);
+ set_shadow_rx_am_data_int_enable(p, index, int_enable);
+}
+
+static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_rx_avail_monitor_data_guest_physical_address,
+ (uint32_t *)&p->m_rx_am_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_enable,
+ p->m_rx_am_shadow[index].enable);
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_host_id,
+ p->m_rx_am_shadow[index].host_id);
+ if (p->mp_fld_rx_avail_monitor_data_packed) {
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_packed,
+ p->m_rx_am_shadow[index].packed);
+ }
+ if (p->mp_fld_rx_avail_monitor_data_int) {
+ field_set_val32(p->mp_fld_rx_avail_monitor_data_int,
+ p->m_rx_am_shadow[index].int_enable);
+ }
+
+ set_rx_am_data_index(p, index);
+ register_flush(p->mp_reg_rx_avail_monitor_data, 1);
+}
+
+int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ if (!p->mp_reg_rx_avail_monitor_data)
+ return -ENOTSUP;
+
+ set_shadow_rx_am_data(p, index, guest_physical_address, enable, host_id,
+ packed, int_enable);
+ flush_rx_am_data(p, index);
+ return 0;
+}
+
+static void set_tx_am_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_avail_monitor_control_adr, index);
+ field_set_val32(p->mp_fld_tx_avail_monitor_control_cnt, 1);
+ register_flush(p->mp_reg_tx_avail_monitor_control, 1);
+}
+
+static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t enable,
+ uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ p->m_tx_am_shadow[index].guest_physical_address = guest_physical_address;
+ p->m_tx_am_shadow[index].enable = enable;
+ p->m_tx_am_shadow[index].host_id = host_id;
+ p->m_tx_am_shadow[index].packed = packed;
+ p->m_tx_am_shadow[index].int_enable = int_enable;
+}
+
+static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_tx_avail_monitor_data_guest_physical_address,
+ (uint32_t *)&p->m_tx_am_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_enable,
+ p->m_tx_am_shadow[index].enable);
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_host_id,
+ p->m_tx_am_shadow[index].host_id);
+ if (p->mp_fld_tx_avail_monitor_data_packed) {
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_packed,
+ p->m_tx_am_shadow[index].packed);
+ }
+ if (p->mp_fld_tx_avail_monitor_data_int) {
+ field_set_val32(p->mp_fld_tx_avail_monitor_data_int,
+ p->m_tx_am_shadow[index].int_enable);
+ }
+
+ set_tx_am_data_index(p, index);
+ register_flush(p->mp_reg_tx_avail_monitor_data, 1);
+}
+
+int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable)
+{
+ if (!p->mp_reg_tx_avail_monitor_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_am_data(p, index, guest_physical_address, enable, host_id,
+ packed, int_enable);
+ flush_tx_am_data(p, index);
+ return 0;
+}
+
+static void set_rx_uw_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_rx_used_writer_control_adr, index);
+ field_set_val32(p->mp_fld_rx_used_writer_control_cnt, 1);
+ register_flush(p->mp_reg_rx_used_writer_control, 1);
+}
+
+static void
+set_shadow_rx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_rx_uw_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_rx_uw_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_rx_uw_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_rx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_rx_uw_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_rx_uw_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_rx_uw_shadow[index].packed = packed;
+}
+
+static void set_shadow_rx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t int_enable)
+{
+ p->m_rx_uw_shadow[index].int_enable = int_enable;
+}
+
+static void set_shadow_rx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec)
+{
+ p->m_rx_uw_shadow[index].vec = vec;
+}
+
+static void set_shadow_rx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk)
+{
+ p->m_rx_uw_shadow[index].istk = istk;
+}
+
+static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk)
+{
+ set_shadow_rx_uw_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_rx_uw_data_host_id(p, index, host_id);
+ set_shadow_rx_uw_data_queue_size(p, index, queue_size);
+ set_shadow_rx_uw_data_packed(p, index, packed);
+ set_shadow_rx_uw_data_int_enable(p, index, int_enable);
+ set_shadow_rx_uw_data_vec(p, index, vec);
+ set_shadow_rx_uw_data_istk(p, index, istk);
+}
+
+static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_rx_used_writer_data_guest_physical_address,
+ (uint32_t *)&p->m_rx_uw_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_rx_used_writer_data_host_id,
+ p->m_rx_uw_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_rx_used_writer_data_queue_size,
+ (1U << p->m_rx_uw_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_rx_used_writer_data_queue_size,
+ p->m_rx_uw_shadow[index].queue_size);
+ }
+ if (p->mp_fld_rx_used_writer_data_packed) {
+ field_set_val32(p->mp_fld_rx_used_writer_data_packed,
+ p->m_rx_uw_shadow[index].packed);
+ }
+ if (p->mp_fld_rx_used_writer_data_int) {
+ field_set_val32(p->mp_fld_rx_used_writer_data_int,
+ p->m_rx_uw_shadow[index].int_enable);
+ field_set_val32(p->mp_fld_rx_used_writer_data_vec,
+ p->m_rx_uw_shadow[index].vec);
+ field_set_val32(p->mp_fld_rx_used_writer_data_istk,
+ p->m_rx_uw_shadow[index].istk);
+ }
+
+ set_rx_uw_data_index(p, index);
+ register_flush(p->mp_reg_rx_used_writer_data, 1);
+}
+
+int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk)
+{
+ if (!p->mp_reg_rx_used_writer_data)
+ return -ENOTSUP;
+
+ set_shadow_rx_uw_data(p, index, guest_physical_address, host_id, queue_size,
+ packed, int_enable, vec, istk);
+ flush_rx_uw_data(p, index);
+ return 0;
+}
+
+static void set_tx_uw_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_used_writer_control_adr, index);
+ field_set_val32(p->mp_fld_tx_used_writer_control_cnt, 1);
+ register_flush(p->mp_reg_tx_used_writer_control, 1);
+}
+
+static void
+set_shadow_tx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_tx_uw_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_tx_uw_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_tx_uw_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_tx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_tx_uw_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_tx_uw_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_tx_uw_shadow[index].packed = packed;
+}
+
+static void set_shadow_tx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t int_enable)
+{
+ p->m_tx_uw_shadow[index].int_enable = int_enable;
+}
+
+static void set_shadow_tx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec)
+{
+ p->m_tx_uw_shadow[index].vec = vec;
+}
+
+static void set_shadow_tx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk)
+{
+ p->m_tx_uw_shadow[index].istk = istk;
+}
+
+static void set_shadow_tx_uw_data_in_order(nthw_dbs_t *p, uint32_t index,
+ uint32_t in_order)
+{
+ p->m_tx_uw_shadow[index].in_order = in_order;
+}
+
+static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order)
+{
+ set_shadow_tx_uw_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_tx_uw_data_host_id(p, index, host_id);
+ set_shadow_tx_uw_data_queue_size(p, index, queue_size);
+ set_shadow_tx_uw_data_packed(p, index, packed);
+ set_shadow_tx_uw_data_int_enable(p, index, int_enable);
+ set_shadow_tx_uw_data_vec(p, index, vec);
+ set_shadow_tx_uw_data_istk(p, index, istk);
+ set_shadow_tx_uw_data_in_order(p, index, in_order);
+}
+
+static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_tx_used_writer_data_guest_physical_address,
+ (uint32_t *)&p->m_tx_uw_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_tx_used_writer_data_host_id,
+ p->m_tx_uw_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_queue_size,
+ (1U << p->m_tx_uw_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_tx_used_writer_data_queue_size,
+ p->m_tx_uw_shadow[index].queue_size);
+ }
+ if (p->mp_fld_tx_used_writer_data_packed) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_packed,
+ p->m_tx_uw_shadow[index].packed);
+ }
+ if (p->mp_fld_tx_used_writer_data_int) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_int,
+ p->m_tx_uw_shadow[index].int_enable);
+ field_set_val32(p->mp_fld_tx_used_writer_data_vec,
+ p->m_tx_uw_shadow[index].vec);
+ field_set_val32(p->mp_fld_tx_used_writer_data_istk,
+ p->m_tx_uw_shadow[index].istk);
+ }
+ if (p->mp_fld_tx_used_writer_data_in_order) {
+ field_set_val32(p->mp_fld_tx_used_writer_data_in_order,
+ p->m_tx_uw_shadow[index].in_order);
+ }
+
+ set_tx_uw_data_index(p, index);
+ register_flush(p->mp_reg_tx_used_writer_data, 1);
+}
+
+int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order)
+{
+ if (!p->mp_reg_tx_used_writer_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_uw_data(p, index, guest_physical_address, host_id, queue_size,
+ packed, int_enable, vec, istk, in_order);
+ flush_tx_uw_data(p, index);
+ return 0;
+}
+
+static void set_rx_dr_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_rx_descriptor_reader_control_adr, index);
+ field_set_val32(p->mp_fld_rx_descriptor_reader_control_cnt, 1);
+ register_flush(p->mp_reg_rx_descriptor_reader_control, 1);
+}
+
+static void
+set_shadow_rx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_rx_dr_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_rx_dr_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_rx_dr_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_rx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_rx_dr_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_rx_dr_data_header(nthw_dbs_t *p, uint32_t index,
+ uint32_t header)
+{
+ p->m_rx_dr_shadow[index].header = header;
+}
+
+static void set_shadow_rx_dr_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_rx_dr_shadow[index].packed = packed;
+}
+
+static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t header,
+ uint32_t packed)
+{
+ set_shadow_rx_dr_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_rx_dr_data_host_id(p, index, host_id);
+ set_shadow_rx_dr_data_queue_size(p, index, queue_size);
+ set_shadow_rx_dr_data_header(p, index, header);
+ set_shadow_rx_dr_data_packed(p, index, packed);
+}
+
+static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_rx_descriptor_reader_data_guest_physical_address,
+ (uint32_t *)&p->m_rx_dr_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_host_id,
+ p->m_rx_dr_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size,
+ (1U << p->m_rx_dr_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size,
+ p->m_rx_dr_shadow[index].queue_size);
+ }
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_header,
+ p->m_rx_dr_shadow[index].header);
+ if (p->mp_fld_rx_descriptor_reader_data_packed) {
+ field_set_val32(p->mp_fld_rx_descriptor_reader_data_packed,
+ p->m_rx_dr_shadow[index].packed);
+ }
+
+ set_rx_dr_data_index(p, index);
+ register_flush(p->mp_reg_rx_descriptor_reader_data, 1);
+}
+
+int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t header,
+ uint32_t packed)
+{
+ if (!p->mp_reg_rx_descriptor_reader_data)
+ return -ENOTSUP;
+
+ set_shadow_rx_dr_data(p, index, guest_physical_address, host_id, queue_size,
+ header, packed);
+ flush_rx_dr_data(p, index);
+ return 0;
+}
+
+static void set_tx_dr_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_descriptor_reader_control_adr, index);
+ field_set_val32(p->mp_fld_tx_descriptor_reader_control_cnt, 1);
+ register_flush(p->mp_reg_tx_descriptor_reader_control, 1);
+}
+
+static void
+set_shadow_tx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address)
+{
+ p->m_tx_dr_shadow[index].guest_physical_address = guest_physical_address;
+}
+
+static void set_shadow_tx_dr_data_host_id(nthw_dbs_t *p, uint32_t index,
+ uint32_t host_id)
+{
+ p->m_tx_dr_shadow[index].host_id = host_id;
+}
+
+static void set_shadow_tx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index,
+ uint32_t queue_size)
+{
+ p->m_tx_dr_shadow[index].queue_size = queue_size;
+}
+
+static void set_shadow_tx_dr_data_header(nthw_dbs_t *p, uint32_t index,
+ uint32_t header)
+{
+ p->m_tx_dr_shadow[index].header = header;
+}
+
+static void set_shadow_tx_dr_data_port(nthw_dbs_t *p, uint32_t index, uint32_t port)
+{
+ p->m_tx_dr_shadow[index].port = port;
+}
+
+static void set_shadow_tx_dr_data_packed(nthw_dbs_t *p, uint32_t index,
+ uint32_t packed)
+{
+ p->m_tx_dr_shadow[index].packed = packed;
+}
+
+static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index,
+ uint64_t guest_physical_address, uint32_t host_id,
+ uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed)
+{
+ set_shadow_tx_dr_data_guest_physical_address(p, index, guest_physical_address);
+ set_shadow_tx_dr_data_host_id(p, index, host_id);
+ set_shadow_tx_dr_data_queue_size(p, index, queue_size);
+ set_shadow_tx_dr_data_header(p, index, header);
+ set_shadow_tx_dr_data_port(p, index, port);
+ set_shadow_tx_dr_data_packed(p, index, packed);
+}
+
+static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val(p->mp_fld_tx_descriptor_reader_data_guest_physical_address,
+ (uint32_t *)&p->m_tx_dr_shadow[index].guest_physical_address,
+ 2);
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_host_id,
+ p->m_tx_dr_shadow[index].host_id);
+ if (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size,
+ (1U << p->m_tx_dr_shadow[index].queue_size) - 1U);
+ } else {
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size,
+ p->m_tx_dr_shadow[index].queue_size);
+ }
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_header,
+ p->m_tx_dr_shadow[index].header);
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_port,
+ p->m_tx_dr_shadow[index].port);
+ if (p->mp_fld_tx_descriptor_reader_data_packed) {
+ field_set_val32(p->mp_fld_tx_descriptor_reader_data_packed,
+ p->m_tx_dr_shadow[index].packed);
+ }
+
+ set_tx_dr_data_index(p, index);
+ register_flush(p->mp_reg_tx_descriptor_reader_data, 1);
+}
+
+int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed)
+{
+ if (!p->mp_reg_tx_descriptor_reader_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_dr_data(p, index, guest_physical_address, host_id, queue_size,
+ port, header, packed);
+ flush_tx_dr_data(p, index);
+ return 0;
+}
+
+static void set_tx_qp_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_queue_property_control_adr, index);
+ field_set_val32(p->mp_fld_tx_queue_property_control_cnt, 1);
+ register_flush(p->mp_reg_tx_queue_property_control, 1);
+}
+
+static void set_shadow_tx_qp_data_virtual_port(nthw_dbs_t *p, uint32_t index,
+ uint32_t virtual_port)
+{
+ p->m_tx_qp_shadow[index].virtual_port = virtual_port;
+}
+
+static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index,
+ uint32_t virtual_port)
+{
+ set_shadow_tx_qp_data_virtual_port(p, index, virtual_port);
+}
+
+static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_fld_tx_queue_property_data_v_port,
+ p->m_tx_qp_shadow[index].virtual_port);
+
+ set_tx_qp_data_index(p, index);
+ register_flush(p->mp_reg_tx_queue_property_data, 1);
+}
+
+int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port)
+{
+ if (!p->mp_reg_tx_queue_property_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_qp_data(p, index, virtual_port);
+ flush_tx_qp_data(p, index);
+ return 0;
+}
+
+static void set_tx_qos_data_index(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_reg_tx_queue_qos_control_adr, index);
+ field_set_val32(p->mp_reg_tx_queue_qos_control_cnt, 1);
+ register_flush(p->mp_reg_tx_queue_qos_control, 1);
+}
+
+static void set_shadow_tx_qos_data_enable(nthw_dbs_t *p, uint32_t index,
+ uint32_t enable)
+{
+ p->m_tx_qos_shadow[index].enable = enable;
+}
+
+static void set_shadow_tx_qos_data_ir(nthw_dbs_t *p, uint32_t index, uint32_t ir)
+{
+ p->m_tx_qos_shadow[index].ir = ir;
+}
+
+static void set_shadow_tx_qos_data_bs(nthw_dbs_t *p, uint32_t index, uint32_t bs)
+{
+ p->m_tx_qos_shadow[index].bs = bs;
+}
+
+static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable,
+ uint32_t ir, uint32_t bs)
+{
+ set_shadow_tx_qos_data_enable(p, index, enable);
+ set_shadow_tx_qos_data_ir(p, index, ir);
+ set_shadow_tx_qos_data_bs(p, index, bs);
+}
+
+static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index)
+{
+ field_set_val32(p->mp_reg_tx_queue_qos_data_en, p->m_tx_qos_shadow[index].enable);
+ field_set_val32(p->mp_reg_tx_queue_qos_data_ir, p->m_tx_qos_shadow[index].ir);
+ field_set_val32(p->mp_reg_tx_queue_qos_data_bs, p->m_tx_qos_shadow[index].bs);
+
+ set_tx_qos_data_index(p, index);
+ register_flush(p->mp_reg_tx_queue_qos_data, 1);
+}
+
+int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir,
+ uint32_t bs)
+{
+ if (!p->mp_reg_tx_queue_qos_data)
+ return -ENOTSUP;
+
+ set_shadow_tx_qos_data(p, index, enable, ir, bs);
+ flush_tx_qos_data(p, index);
+ return 0;
+}
+
+int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div)
+{
+ if (!p->mp_reg_tx_queue_qos_rate)
+ return -ENOTSUP;
+
+ field_set_val32(p->mp_reg_tx_queue_qos_rate_mul, mul);
+ field_set_val32(p->mp_reg_tx_queue_qos_rate_div, div);
+ register_flush(p->mp_reg_tx_queue_qos_rate, 1);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_dbs.h b/drivers/net/ntnic/nthw/nthw_dbs.h
new file mode 100644
index 0000000000..d5891d7538
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_dbs.h
@@ -0,0 +1,313 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_DBS_HPP_
+#define NTHW_DBS_HPP_
+
+#define NT_DBS_RX_QUEUES_MAX (128)
+#define NT_DBS_TX_QUEUES_MAX (128)
+
+/*
+ * Struct for implementation of memory bank shadows
+ */
+
+/* DBS_RX_AM_DATA */
+struct nthw_dbs_rx_am_data_s {
+ uint64_t guest_physical_address;
+ uint32_t enable;
+ uint32_t host_id;
+ uint32_t packed;
+ uint32_t int_enable;
+};
+
+/* DBS_TX_AM_DATA */
+struct nthw_dbs_tx_am_data_s {
+ uint64_t guest_physical_address;
+ uint32_t enable;
+ uint32_t host_id;
+ uint32_t packed;
+ uint32_t int_enable;
+};
+
+/* DBS_RX_UW_DATA */
+struct nthw_dbs_rx_uw_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t packed;
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+};
+
+/* DBS_TX_UW_DATA */
+struct nthw_dbs_tx_uw_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t packed;
+ uint32_t int_enable;
+ uint32_t vec;
+ uint32_t istk;
+ uint32_t in_order;
+};
+
+/* DBS_RX_DR_DATA */
+struct nthw_dbs_rx_dr_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t header;
+ uint32_t packed;
+};
+
+/* DBS_TX_DR_DATA */
+struct nthw_dbs_tx_dr_data_s {
+ uint64_t guest_physical_address;
+ uint32_t host_id;
+ uint32_t queue_size;
+ uint32_t header;
+ uint32_t port;
+ uint32_t packed;
+};
+
+/* DBS_TX_QP_DATA */
+struct nthw_dbs_tx_qp_data_s {
+ uint32_t virtual_port;
+};
+
+struct nthw_dbs_tx_qos_data_s {
+ uint32_t enable;
+ uint32_t ir;
+ uint32_t bs;
+};
+
+struct nthw_dbs_s {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_dbs;
+ int mn_instance;
+
+ int mn_param_dbs_present;
+
+ nt_register_t *mp_reg_rx_control;
+ nt_field_t *mp_fld_rx_control_last_queue;
+ nt_field_t *mp_fld_rx_control_avail_monitor_enable;
+ nt_field_t *mp_fld_rx_control_avail_monitor_scan_speed;
+ nt_field_t *mp_fld_rx_control_used_write_enable;
+ nt_field_t *mp_fld_rx_control_used_writer_update_speed;
+ nt_field_t *mp_fld_rx_control_rx_queues_enable;
+
+ nt_register_t *mp_reg_tx_control;
+ nt_field_t *mp_fld_tx_control_last_queue;
+ nt_field_t *mp_fld_tx_control_avail_monitor_enable;
+ nt_field_t *mp_fld_tx_control_avail_monitor_scan_speed;
+ nt_field_t *mp_fld_tx_control_used_write_enable;
+ nt_field_t *mp_fld_tx_control_used_writer_update_speed;
+ nt_field_t *mp_fld_tx_control_tx_queues_enable;
+
+ nt_register_t *mp_reg_rx_init;
+ nt_field_t *mp_fld_rx_init_init;
+ nt_field_t *mp_fld_rx_init_queue;
+ nt_field_t *mp_fld_rx_init_busy;
+
+ nt_register_t *mp_reg_rx_init_val;
+ nt_field_t *mp_fld_rx_init_val_idx;
+ nt_field_t *mp_fld_rx_init_val_ptr;
+
+ nt_register_t *mp_reg_rx_ptr;
+ nt_field_t *mp_fld_rx_ptr_ptr;
+ nt_field_t *mp_fld_rx_ptr_queue;
+ nt_field_t *mp_fld_rx_ptr_valid;
+
+ nt_register_t *mp_reg_tx_init;
+ nt_field_t *mp_fld_tx_init_init;
+ nt_field_t *mp_fld_tx_init_queue;
+ nt_field_t *mp_fld_tx_init_busy;
+
+ nt_register_t *mp_reg_tx_init_val;
+ nt_field_t *mp_fld_tx_init_val_idx;
+ nt_field_t *mp_fld_tx_init_val_ptr;
+
+ nt_register_t *mp_reg_tx_ptr;
+ nt_field_t *mp_fld_tx_ptr_ptr;
+ nt_field_t *mp_fld_tx_ptr_queue;
+ nt_field_t *mp_fld_tx_ptr_valid;
+
+ nt_register_t *mp_reg_rx_idle;
+ nt_field_t *mp_fld_rx_idle_idle;
+ nt_field_t *mp_fld_rx_idle_queue;
+ nt_field_t *mp_fld_rx_idle_busy;
+
+ nt_register_t *mp_reg_tx_idle;
+ nt_field_t *mp_fld_tx_idle_idle;
+ nt_field_t *mp_fld_tx_idle_queue;
+ nt_field_t *mp_fld_tx_idle_busy;
+
+ nt_register_t *mp_reg_rx_avail_monitor_control;
+ nt_field_t *mp_fld_rx_avail_monitor_control_adr;
+ nt_field_t *mp_fld_rx_avail_monitor_control_cnt;
+
+ nt_register_t *mp_reg_rx_avail_monitor_data;
+ nt_field_t *mp_fld_rx_avail_monitor_data_guest_physical_address;
+ nt_field_t *mp_fld_rx_avail_monitor_data_enable;
+ nt_field_t *mp_fld_rx_avail_monitor_data_host_id;
+ nt_field_t *mp_fld_rx_avail_monitor_data_packed;
+ nt_field_t *mp_fld_rx_avail_monitor_data_int;
+
+ nt_register_t *mp_reg_tx_avail_monitor_control;
+ nt_field_t *mp_fld_tx_avail_monitor_control_adr;
+ nt_field_t *mp_fld_tx_avail_monitor_control_cnt;
+
+ nt_register_t *mp_reg_tx_avail_monitor_data;
+ nt_field_t *mp_fld_tx_avail_monitor_data_guest_physical_address;
+ nt_field_t *mp_fld_tx_avail_monitor_data_enable;
+ nt_field_t *mp_fld_tx_avail_monitor_data_host_id;
+ nt_field_t *mp_fld_tx_avail_monitor_data_packed;
+ nt_field_t *mp_fld_tx_avail_monitor_data_int;
+
+ nt_register_t *mp_reg_rx_used_writer_control;
+ nt_field_t *mp_fld_rx_used_writer_control_adr;
+ nt_field_t *mp_fld_rx_used_writer_control_cnt;
+
+ nt_register_t *mp_reg_rx_used_writer_data;
+ nt_field_t *mp_fld_rx_used_writer_data_guest_physical_address;
+ nt_field_t *mp_fld_rx_used_writer_data_host_id;
+ nt_field_t *mp_fld_rx_used_writer_data_queue_size;
+ nt_field_t *mp_fld_rx_used_writer_data_packed;
+ nt_field_t *mp_fld_rx_used_writer_data_int;
+ nt_field_t *mp_fld_rx_used_writer_data_vec;
+ nt_field_t *mp_fld_rx_used_writer_data_istk;
+
+ nt_register_t *mp_reg_tx_used_writer_control;
+ nt_field_t *mp_fld_tx_used_writer_control_adr;
+ nt_field_t *mp_fld_tx_used_writer_control_cnt;
+
+ nt_register_t *mp_reg_tx_used_writer_data;
+ nt_field_t *mp_fld_tx_used_writer_data_guest_physical_address;
+ nt_field_t *mp_fld_tx_used_writer_data_host_id;
+ nt_field_t *mp_fld_tx_used_writer_data_queue_size;
+ nt_field_t *mp_fld_tx_used_writer_data_packed;
+ nt_field_t *mp_fld_tx_used_writer_data_int;
+ nt_field_t *mp_fld_tx_used_writer_data_vec;
+ nt_field_t *mp_fld_tx_used_writer_data_istk;
+ nt_field_t *mp_fld_tx_used_writer_data_in_order;
+
+ nt_register_t *mp_reg_rx_descriptor_reader_control;
+ nt_field_t *mp_fld_rx_descriptor_reader_control_adr;
+ nt_field_t *mp_fld_rx_descriptor_reader_control_cnt;
+
+ nt_register_t *mp_reg_rx_descriptor_reader_data;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_guest_physical_address;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_host_id;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_queue_size;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_header;
+ nt_field_t *mp_fld_rx_descriptor_reader_data_packed;
+
+ nt_register_t *mp_reg_tx_descriptor_reader_control;
+ nt_field_t *mp_fld_tx_descriptor_reader_control_adr;
+ nt_field_t *mp_fld_tx_descriptor_reader_control_cnt;
+
+ nt_register_t *mp_reg_tx_descriptor_reader_data;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_guest_physical_address;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_host_id;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_queue_size;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_port;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_header;
+ nt_field_t *mp_fld_tx_descriptor_reader_data_packed;
+
+ nt_register_t *mp_reg_tx_queue_property_control;
+ nt_field_t *mp_fld_tx_queue_property_control_adr;
+ nt_field_t *mp_fld_tx_queue_property_control_cnt;
+
+ nt_register_t *mp_reg_tx_queue_property_data;
+ nt_field_t *mp_fld_tx_queue_property_data_v_port;
+
+ nt_register_t *mp_reg_tx_queue_qos_control;
+ nt_field_t *mp_reg_tx_queue_qos_control_adr;
+ nt_field_t *mp_reg_tx_queue_qos_control_cnt;
+
+ nt_register_t *mp_reg_tx_queue_qos_data;
+ nt_field_t *mp_reg_tx_queue_qos_data_en;
+ nt_field_t *mp_reg_tx_queue_qos_data_ir;
+ nt_field_t *mp_reg_tx_queue_qos_data_bs;
+
+ nt_register_t *mp_reg_tx_queue_qos_rate;
+ nt_field_t *mp_reg_tx_queue_qos_rate_mul;
+ nt_field_t *mp_reg_tx_queue_qos_rate_div;
+
+ struct nthw_dbs_rx_am_data_s m_rx_am_shadow[NT_DBS_RX_QUEUES_MAX];
+ struct nthw_dbs_rx_uw_data_s m_rx_uw_shadow[NT_DBS_RX_QUEUES_MAX];
+ struct nthw_dbs_rx_dr_data_s m_rx_dr_shadow[NT_DBS_RX_QUEUES_MAX];
+
+ struct nthw_dbs_tx_am_data_s m_tx_am_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_uw_data_s m_tx_uw_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_dr_data_s m_tx_dr_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_qp_data_s m_tx_qp_shadow[NT_DBS_TX_QUEUES_MAX];
+ struct nthw_dbs_tx_qos_data_s m_tx_qos_shadow[NT_DBS_TX_QUEUES_MAX];
+};
+
+typedef struct nthw_dbs_s nthw_dbs_t;
+
+nthw_dbs_t *nthw_dbs_new(void);
+void nthw_dbs_delete(nthw_dbs_t *p);
+int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance);
+void dbs_reset(nthw_dbs_t *p);
+
+int dbs_reset_rx_control(nthw_dbs_t *p);
+int dbs_reset_tx_control(nthw_dbs_t *p);
+int set_rx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t rx_queue_enable);
+int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *rx_queue_enable);
+int set_tx_control(nthw_dbs_t *p, uint32_t last_queue,
+ uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,
+ uint32_t used_write_enable, uint32_t used_write_speed,
+ uint32_t tx_queue_enable);
+int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue,
+ uint32_t *avail_monitor_enable,
+ uint32_t *avail_monitor_speed, uint32_t *used_write_enable,
+ uint32_t *used_write_speed, uint32_t *tx_queue_enable);
+int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue);
+int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy);
+int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,
+ uint32_t init, uint32_t queue);
+int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy);
+int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue);
+int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy);
+int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue);
+int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy);
+int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue);
+int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid);
+int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue);
+int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid);
+int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t enable, uint32_t host_id, uint32_t packed,
+ uint32_t int_enable);
+int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk);
+int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t packed,
+ uint32_t int_enable, uint32_t vec, uint32_t istk,
+ uint32_t in_order);
+int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t header,
+ uint32_t packed);
+int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,
+ uint32_t host_id, uint32_t queue_size, uint32_t port,
+ uint32_t header, uint32_t packed);
+int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port);
+int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir,
+ uint32_t bs);
+int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div);
+
+#endif /* NTHW_DBS_H_ */
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
new file mode 100644
index 0000000000..7fdd9bf0e2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_DRV_H__
+#define __NTHW_DRV_H__
+
+#include "nthw_profile.h"
+
+typedef enum nt_meta_port_type_e {
+ PORT_TYPE_PHYSICAL,
+ PORT_TYPE_VIRTUAL,
+ PORT_TYPE_OVERRIDE,
+} nt_meta_port_type_t;
+
+#include "nthw_helper.h"
+#include "nthw_platform_drv.h"
+#include "nthw_fpga_model.h"
+#include "nthw_stat.h"
+#include "nthw_dbs.h"
+#include "nthw_epp.h"
+#include "nthw_core.h"
+
+typedef struct nthwhw_info_s {
+ /* From FW */
+ int hw_id;
+ int hw_id_emulated;
+ char hw_plat_id_str[32];
+
+ struct vpd_info_s {
+ int mn_mac_addr_count;
+ uint64_t mn_mac_addr_value;
+ uint8_t ma_mac_addr_octets[6];
+ } vpd_info;
+} nthw_hw_info_t;
+
+typedef struct fpga_info_s {
+ uint64_t n_fpga_ident;
+
+ int n_fpga_type_id;
+ int n_fpga_prod_id;
+ int n_fpga_ver_id;
+ int n_fpga_rev_id;
+
+ int n_fpga_build_time;
+
+ int n_fpga_debug_mode;
+
+ int n_nims;
+ int n_phy_ports;
+ int n_phy_quads;
+ int n_rx_ports;
+ int n_tx_ports;
+
+ enum fpga_info_profile profile;
+
+ struct nt_fpga_s *mp_fpga;
+
+ struct nthw_rac *mp_nthw_rac;
+ struct nthw_hif *mp_nthw_hif;
+ struct nthw_pcie3 *mp_nthw_pcie3;
+ struct nthw_tsm *mp_nthw_tsm;
+
+ nthw_dbs_t *mp_nthw_dbs;
+ nthw_epp_t *mp_nthw_epp;
+
+ uint8_t *bar0_addr; /* Needed for register read/write */
+ size_t bar0_size;
+
+ int adapter_no; /* Needed for nthw_rac DMA array indexing */
+ uint32_t pciident; /* Needed for nthw_rac DMA memzone_reserve */
+ int numa_node; /* Needed for nthw_rac DMA memzone_reserve */
+
+ char *mp_adapter_id_str; /* Pointer to string literal used in nthw log messages */
+
+ struct nthwhw_info_s nthw_hw_info;
+
+ nthw_adapter_id_t n_nthw_adapter_id;
+
+} fpga_info_t;
+
+#endif /* __NTHW_DRV_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_epp.c b/drivers/net/ntnic/nthw/nthw_epp.c
new file mode 100644
index 0000000000..fbe3993b25
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_epp.c
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_epp.h"
+
+#include <errno.h> /* ENOTSUP */
+
+nthw_epp_t *nthw_epp_new(void)
+{
+ nthw_epp_t *p = malloc(sizeof(nthw_epp_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_epp_t));
+ return p;
+}
+
+void nthw_epp_delete(nthw_epp_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_epp_t));
+ free(p);
+ }
+}
+
+int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance)
+{
+ return nthw_epp_init(NULL, p_fpga, n_instance) == 0;
+}
+
+int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_EPP, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: EPP %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_epp = mod;
+
+ p->mn_epp_categories = fpga_get_product_param(p_fpga, NT_EPP_CATEGORIES, 0);
+
+ p->mp_reg_reciepe_memory_control =
+ module_get_register(p->mp_mod_epp, EPP_RCP_CTRL);
+ p->mp_fld_reciepe_memory_control_adr =
+ register_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_ADR);
+ p->mp_fld_reciepe_memory_control_cnt =
+ register_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_CNT);
+
+ p->mp_reg_reciepe_memory_data =
+ module_get_register(p->mp_mod_epp, EPP_RCP_DATA);
+ p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_MTU_EPP_EN);
+ p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_MTU_EPP_EN);
+ p->mp_fld_reciepe_memory_data_size_adjust_tx_port =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_TXP);
+ p->mp_fld_reciepe_memory_data_size_adjust_virtual_port =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_VPORT);
+ p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_FIXED_18B_L2_MTU);
+ p->mp_fld_reciepe_memory_data_txp_qos_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_QOS_EPP_EN);
+ p->mp_fld_reciepe_memory_data_queue_qos_epp_enable =
+ register_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_QOS_EPP_EN);
+
+ p->mp_reg_txp_port_mtu_control =
+ module_get_register(p->mp_mod_epp, EPP_TXP_MTU_CTRL);
+ p->mp_fld_txp_port_mtu_control_adr =
+ register_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_ADR);
+ p->mp_fld_txp_port_mtu_control_cnt =
+ register_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_CNT);
+
+ p->mp_reg_txp_port_mtu_data =
+ module_get_register(p->mp_mod_epp, EPP_TXP_MTU_DATA);
+ p->mp_fld_txp_port_mtu_data_max_mtu =
+ register_get_field(p->mp_reg_txp_port_mtu_data, EPP_TXP_MTU_DATA_MAX_MTU);
+
+ p->mp_reg_queue_mtu_control =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_CTRL);
+ p->mp_fld_queue_mtu_control_adr =
+ register_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_ADR);
+ p->mp_fld_queue_mtu_control_cnt =
+ register_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_CNT);
+
+ p->mp_reg_queue_mtu_data =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_DATA);
+ p->mp_fld_queue_mtu_data_max_mtu =
+ register_get_field(p->mp_reg_queue_mtu_data, EPP_QUEUE_MTU_DATA_MAX_MTU);
+
+ p->mp_reg_txp_qos_control =
+ module_get_register(p->mp_mod_epp, EPP_TXP_QOS_CTRL);
+ p->mp_fld_txp_qos_control_adr =
+ register_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_ADR);
+ p->mp_fld_txp_qos_control_cnt =
+ register_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_CNT);
+
+ p->mp_reg_txp_qos_data = module_get_register(p->mp_mod_epp, EPP_TXP_QOS_DATA);
+ p->mp_fld_txp_qos_data_enable =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_EN);
+ p->mp_fld_txp_qos_data_information_rate =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR);
+ p->mp_fld_txp_qos_data_information_rate_fractional =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR_FRACTION);
+ p->mp_fld_txp_qos_data_burst_size =
+ register_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_BS);
+
+ p->mp_reg_vport_qos_control =
+ module_get_register(p->mp_mod_epp, EPP_VPORT_QOS_CTRL);
+ p->mp_fld_vport_qos_control_adr =
+ register_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_ADR);
+ p->mp_fld_vport_qos_control_cnt =
+ register_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_CNT);
+
+ p->mp_reg_vport_qos_data =
+ module_get_register(p->mp_mod_epp, EPP_VPORT_QOS_DATA);
+ p->mp_fld_vport_qos_data_enable =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_EN);
+ p->mp_fld_vport_qos_data_information_rate =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR);
+ p->mp_fld_vport_qos_data_information_rate_fractional =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR_FRACTION);
+ p->mp_fld_vport_qos_data_burst_size =
+ register_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_BS);
+
+ p->mp_reg_queue_vport_control =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_CTRL);
+ p->mp_fld_queue_vport_control_adr =
+ register_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_ADR);
+ p->mp_fld_queue_vport_control_cnt =
+ register_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_CNT);
+
+ p->mp_reg_queue_vport_data =
+ module_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_DATA);
+ p->mp_fld_queue_vport_data_vport =
+ register_get_field(p->mp_reg_queue_vport_data, EPP_QUEUE_VPORT_DATA_VPORT);
+
+ return 0;
+}
+
+int nthw_epp_setup(nthw_epp_t *p)
+{
+ if (p == NULL)
+ return 0;
+
+ /* Set recieps for 2 first records */
+ field_set_val32(p->mp_fld_reciepe_memory_control_cnt, 1);
+
+ /* Zero all categories */
+ for (int i = 0; i < p->mn_epp_categories; ++i) {
+ field_set_val32(p->mp_fld_reciepe_memory_control_adr, i);
+ register_flush(p->mp_reg_reciepe_memory_control, 1);
+
+ field_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port,
+ 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 0);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 0);
+ register_flush(p->mp_reg_reciepe_memory_data, 1);
+ }
+
+ for (int i = 0; i < NRECIPE; ++i) {
+ field_set_val32(p->mp_fld_reciepe_memory_control_adr, i);
+ register_flush(p->mp_reg_reciepe_memory_control, 1);
+
+ field_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port,
+ rcp_data_size_adjust_txp[i]);
+ field_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port,
+ rcp_data_size_adjust_vport[i]);
+ field_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 1);
+ field_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 1);
+ register_flush(p->mp_reg_reciepe_memory_data, 1);
+ }
+ /* phy mtu setup */
+ field_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1);
+ for (int i = 0; i < 2; ++i) {
+ field_set_val32(p->mp_fld_txp_port_mtu_control_adr, i);
+ register_flush(p->mp_reg_txp_port_mtu_control, 1);
+
+ field_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, MTUINITVAL);
+ register_flush(p->mp_reg_txp_port_mtu_data, 1);
+ }
+ /* phy QoS setup */
+ field_set_val32(p->mp_fld_txp_qos_control_cnt, 1);
+ for (int i = 0; i < 2; ++i) {
+ field_set_val32(p->mp_fld_txp_qos_control_adr, i);
+ register_flush(p->mp_reg_txp_qos_control, 1);
+
+ field_set_val32(p->mp_fld_txp_qos_data_enable, 0);
+ register_flush(p->mp_reg_txp_qos_data, 1);
+ }
+
+ /* virt mtu setup */
+ field_set_val32(p->mp_fld_queue_mtu_control_cnt, 1);
+ for (int i = 0; i < 128; ++i) {
+ field_set_val32(p->mp_fld_queue_mtu_control_adr, i);
+ register_flush(p->mp_reg_queue_mtu_control, 1);
+
+ field_set_val32(p->mp_fld_queue_mtu_data_max_mtu, MTUINITVAL);
+ register_flush(p->mp_reg_queue_mtu_data, 1);
+ }
+
+ /* virt QoS setup */
+ field_set_val32(p->mp_fld_vport_qos_control_cnt, 1);
+ for (int i = 0; i < 128; ++i) {
+ field_set_val32(p->mp_fld_vport_qos_control_adr, i);
+ register_flush(p->mp_reg_vport_qos_control, 1);
+
+ field_set_val32(p->mp_fld_vport_qos_data_enable, 0);
+ register_flush(p->mp_reg_vport_qos_data, 1);
+ }
+
+ return 0;
+}
+
+/*
+ * Set the MTU registers in context with the current setMTU request.
+ */
+int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu,
+ nt_meta_port_type_t port_type)
+{
+ if (p == NULL)
+ return 0;
+
+ if (port_type == PORT_TYPE_PHYSICAL) {
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_txp_port_mtu_control_adr, port);
+ field_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1);
+ register_flush(p->mp_reg_txp_port_mtu_control, 1);
+
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, max_mtu);
+ register_flush(p->mp_reg_txp_port_mtu_data, 1);
+ } else if (port_type == PORT_TYPE_VIRTUAL) {
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_queue_mtu_control_adr, port);
+ field_set_val32(p->mp_fld_queue_mtu_control_cnt, 1);
+ register_flush(p->mp_reg_queue_mtu_control, 1);
+
+ /* Set the TXP Mtu control register */
+ field_set_val32(p->mp_fld_queue_mtu_data_max_mtu, max_mtu);
+ register_flush(p->mp_reg_queue_mtu_data, 1);
+ } else {
+ NT_LOG(DBG, NTHW, "NthwEpp::%s - port_type unsupported",
+ __func__);
+ register_reset(p->mp_reg_queue_mtu_control);
+ register_flush(p->mp_reg_queue_mtu_control, 1);
+ register_reset(p->mp_reg_queue_mtu_data);
+ register_flush(p->mp_reg_queue_mtu_data, 1);
+ register_reset(p->mp_reg_txp_port_mtu_control);
+ register_flush(p->mp_reg_txp_port_mtu_control, 1);
+ register_reset(p->mp_reg_txp_port_mtu_data);
+ register_flush(p->mp_reg_txp_port_mtu_data, 1);
+
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size)
+{
+ if (p == NULL)
+ return 0;
+
+ field_set_val32(p->mp_fld_txp_qos_control_adr, port);
+ field_set_val32(p->mp_fld_txp_qos_control_cnt, 1);
+ register_flush(p->mp_reg_txp_qos_control, 1);
+
+ uint32_t enable = ((information_rate | information_rate_fractional |
+ burst_size) != 0);
+ field_set_val32(p->mp_fld_txp_qos_data_enable, enable);
+ field_set_val32(p->mp_fld_txp_qos_data_information_rate, information_rate);
+ field_set_val32(p->mp_fld_txp_qos_data_information_rate_fractional,
+ information_rate_fractional);
+ field_set_val32(p->mp_fld_txp_qos_data_burst_size, burst_size);
+ register_flush(p->mp_reg_txp_qos_data, 1);
+
+ return 0;
+}
+
+int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size)
+{
+ if (p == NULL)
+ return 0;
+
+ field_set_val32(p->mp_fld_vport_qos_control_adr, port);
+ field_set_val32(p->mp_fld_vport_qos_control_cnt, 1);
+ register_flush(p->mp_reg_vport_qos_control, 1);
+
+ uint32_t enable = ((information_rate | information_rate_fractional |
+ burst_size) != 0);
+ field_set_val32(p->mp_fld_vport_qos_data_enable, enable);
+ field_set_val32(p->mp_fld_vport_qos_data_information_rate, information_rate);
+ field_set_val32(p->mp_fld_vport_qos_data_information_rate_fractional,
+ information_rate_fractional);
+ field_set_val32(p->mp_fld_vport_qos_data_burst_size, burst_size);
+ register_flush(p->mp_reg_vport_qos_data, 1);
+
+ return 0;
+}
+
+int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport)
+{
+ if (p == NULL)
+ return 0;
+
+ field_set_val32(p->mp_fld_queue_vport_control_adr, qid);
+ field_set_val32(p->mp_fld_queue_vport_control_cnt, 1);
+ register_flush(p->mp_reg_queue_vport_control, 1);
+
+ field_set_val32(p->mp_fld_queue_vport_data_vport, vport);
+ register_flush(p->mp_reg_queue_vport_data, 1);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_epp.h b/drivers/net/ntnic/nthw/nthw_epp.h
new file mode 100644
index 0000000000..b404c9b61a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_epp.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_EPP_HPP_
+#define NTHW_EPP_HPP_
+
+/* VXLAN adds extra 50 bytes */
+#define VXLANDATASIZEADJUST 50
+#define VXLANDATASIZEADJUSTIPV6 70
+#define MTUINITVAL 1500
+#define NRECIPE 3
+
+/* List of size adjust values to put in the recipe memory data register at startup */
+static const int rcp_data_size_adjust_txp[NRECIPE] = { 0, VXLANDATASIZEADJUST,
+ VXLANDATASIZEADJUSTIPV6
+ };
+static const int rcp_data_size_adjust_vport[NRECIPE] = { 0, VXLANDATASIZEADJUST,
+ VXLANDATASIZEADJUSTIPV6
+ };
+
+struct nthw_epp_s {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_epp;
+ int mn_instance;
+ int mn_epp_categories;
+
+ nt_register_t *mp_reg_reciepe_memory_control;
+ nt_field_t *mp_fld_reciepe_memory_control_adr;
+ nt_field_t *mp_fld_reciepe_memory_control_cnt;
+
+ nt_register_t *mp_reg_reciepe_memory_data;
+ nt_field_t *mp_fld_reciepe_memory_data_tx_mtu_epp_enable;
+ nt_field_t *mp_fld_reciepe_memory_data_queue_mtu_epp_enable;
+ nt_field_t *mp_fld_reciepe_memory_data_size_adjust_tx_port;
+ nt_field_t *mp_fld_reciepe_memory_data_size_adjust_virtual_port;
+ nt_field_t *mp_fld_reciepe_memory_data_fixed18b_l2_mtu;
+ nt_field_t *mp_fld_reciepe_memory_data_txp_qos_epp_enable;
+ nt_field_t *mp_fld_reciepe_memory_data_queue_qos_epp_enable;
+
+ nt_register_t *mp_reg_txp_port_mtu_control;
+ nt_field_t *mp_fld_txp_port_mtu_control_adr;
+ nt_field_t *mp_fld_txp_port_mtu_control_cnt;
+
+ nt_register_t *mp_reg_txp_port_mtu_data;
+ nt_field_t *mp_fld_txp_port_mtu_data_max_mtu;
+
+ nt_register_t *mp_reg_queue_mtu_control;
+ nt_field_t *mp_fld_queue_mtu_control_adr;
+ nt_field_t *mp_fld_queue_mtu_control_cnt;
+
+ nt_register_t *mp_reg_queue_mtu_data;
+ nt_field_t *mp_fld_queue_mtu_data_max_mtu;
+
+ nt_register_t *mp_reg_txp_qos_control;
+ nt_field_t *mp_fld_txp_qos_control_adr;
+ nt_field_t *mp_fld_txp_qos_control_cnt;
+
+ nt_register_t *mp_reg_txp_qos_data;
+ nt_field_t *mp_fld_txp_qos_data_enable;
+ nt_field_t *mp_fld_txp_qos_data_information_rate;
+ nt_field_t *mp_fld_txp_qos_data_information_rate_fractional;
+ nt_field_t *mp_fld_txp_qos_data_burst_size;
+
+ nt_register_t *mp_reg_vport_qos_control;
+ nt_field_t *mp_fld_vport_qos_control_adr;
+ nt_field_t *mp_fld_vport_qos_control_cnt;
+
+ nt_register_t *mp_reg_vport_qos_data;
+ nt_field_t *mp_fld_vport_qos_data_enable;
+ nt_field_t *mp_fld_vport_qos_data_information_rate;
+ nt_field_t *mp_fld_vport_qos_data_information_rate_fractional;
+ nt_field_t *mp_fld_vport_qos_data_burst_size;
+
+ nt_register_t *mp_reg_queue_vport_control;
+ nt_field_t *mp_fld_queue_vport_control_adr;
+ nt_field_t *mp_fld_queue_vport_control_cnt;
+
+ nt_register_t *mp_reg_queue_vport_data;
+ nt_field_t *mp_fld_queue_vport_data_vport;
+};
+
+typedef struct nthw_epp_s nthw_epp_t;
+
+nthw_epp_t *nthw_epp_new(void);
+void nthw_epp_delete(nthw_epp_t *p);
+
+int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance);
+int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance);
+int nthw_epp_setup(nthw_epp_t *p);
+int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu,
+ nt_meta_port_type_t port_type);
+int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size);
+int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,
+ uint32_t information_rate_fractional, uint32_t burst_size);
+int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport);
+
+#endif /* NTHW_EPP_HPP_ */
diff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.c b/drivers/net/ntnic/nthw/nthw_fpga_model.c
new file mode 100644
index 0000000000..fca13e0f31
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_fpga_model.c
@@ -0,0 +1,1677 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <time.h> /* ctime */
+
+#include "nthw_drv.h" /* fpga_info_s */
+#include "nthw_register.h"
+#include "nthw_fpga_model.h"
+#include "nthw_rac.h"
+#include "ntlog.h"
+
+#include "nthw_fpga_instances.h"
+#include "nthw_fpga_modules_defs.h"
+
+/* Generated code */
+nt_fpga_prod_init_t *nthw_fpga_instances[] = { &nthw_fpga_9563_055_024_0000,
+ NULL
+ };
+
+static const struct {
+ const int a;
+ const char *b;
+} sa_nthw_fpga_mod_map[] = {
+ { MOD_CAT, "CAT" },
+ { MOD_CB, "CB" },
+ { MOD_CCIP, "CCIP" },
+ { MOD_CFP4_CTRL_GBOX, "CFP4_CTRL_GBOX" },
+ { MOD_COR, "COR" },
+ { MOD_CPY, "CPY" },
+ { MOD_CSU, "CSU" },
+ { MOD_DBS, "DBS" },
+ { MOD_DDP, "DDP" },
+ { MOD_EPP, "EPP" },
+ { MOD_EQM, "EQM" },
+ { MOD_FHM, "FHM" },
+ { MOD_FLM, "FLM" },
+ { MOD_GFG, "GFG" },
+ { MOD_GMF, "GMF" },
+ { MOD_GPIO_PHY, "GPIO_PHY" },
+ { MOD_GPIO_PHY_PORTS, "GPIO_PHY_PORTS" },
+ { MOD_GPIO_SFPP, "GPIO_SFPP" },
+ { MOD_HFU, "HFU" },
+ { MOD_HIF, "HIF" },
+ { MOD_HSH, "HSH" },
+ { MOD_HST, "HST" },
+ { MOD_ICORE_10G, "ICORE_10G" },
+ { MOD_IFR, "IFR" },
+ { MOD_IIC, "IIC" },
+ { MOD_INS, "INS" },
+ { MOD_IOA, "IOA" },
+ { MOD_IPF, "IPF" },
+ { MOD_KM, "KM" },
+ { MOD_LAO, "LAO" },
+ { MOD_MAC, "MAC" },
+ { MOD_MAC10, "MAC10" },
+ { MOD_MAC100, "MAC100" },
+ { MOD_MAC10G, "MAC10G" },
+ { MOD_MAC1G, "MAC1G" },
+ { MOD_MAC_PCS, "MAC_PCS" },
+ { MOD_MAC_PCS_XXV, "MAC_PCS_XXV" },
+ { MOD_MAC_RX, "MAC_RX" },
+ { MOD_MAC_TFG, "MAC_TFG" },
+ { MOD_MAC_TX, "MAC_TX" },
+ { MOD_MCU, "MCU" },
+ { MOD_MDG, "MDG" },
+ { MOD_MSK, "MSK" },
+ { MOD_NIF, "NIF" },
+ { MOD_PCIE3, "PCIE3" },
+ { MOD_PCI_RD_TG, "PCI_RD_TG" },
+ { MOD_PCI_TA, "PCI_TA" },
+ { MOD_PCI_WR_TG, "PCI_WR_TG" },
+ { MOD_PCM_NT100A01_01, "PCM_NT100A01_01" },
+ { MOD_PCM_NT50B01_01, "PCM_NT50B01_01" },
+ { MOD_PCS, "PCS" },
+ { MOD_PCS100, "PCS100" },
+ { MOD_PDB, "PDB" },
+ { MOD_PDI, "PDI" },
+ { MOD_PHY10G, "PHY10G" },
+ { MOD_PHY3S10G, "PHY3S10G" },
+ { MOD_PM, "PM" },
+ { MOD_PRM_NT100A01_01, "PRM_NT100A01_01" },
+ { MOD_PRM_NT50B01_01, "PRM_NT50B01_01" },
+ { MOD_PTP1588, "PTP1588" },
+ { MOD_QM, "QM" },
+ { MOD_QSL, "QSL" },
+ { MOD_QSPI, "QSPI" },
+ { MOD_R2DRP, "R2DRP" },
+ { MOD_RAC, "RAC" },
+ { MOD_RBH, "RBH" },
+ { MOD_RFD, "RFD" },
+ { MOD_RMC, "RMC" },
+ { MOD_RNTC, "RNTC" },
+ { MOD_ROA, "ROA" },
+ { MOD_RPL, "RPL" },
+ { MOD_RPP_LR, "RPP_LR" },
+ { MOD_RST7000, "RST7000" },
+ { MOD_RST7001, "RST7001" },
+ { MOD_RST9500, "RST9500" },
+ { MOD_RST9501, "RST9501" },
+ { MOD_RST9502, "RST9502" },
+ { MOD_RST9503, "RST9503" },
+ { MOD_RST9504, "RST9504" },
+ { MOD_RST9505, "RST9505" },
+ { MOD_RST9506, "RST9506" },
+ { MOD_RST9507, "RST9507" },
+ { MOD_RST9508, "RST9508" },
+ { MOD_RST9509, "RST9509" },
+ { MOD_RST9510, "RST9510" },
+ { MOD_RST9512, "RST9512" },
+ { MOD_RST9513, "RST9513" },
+ { MOD_RST9515, "RST9515" },
+ { MOD_RST9516, "RST9516" },
+ { MOD_RST9517, "RST9517" },
+ { MOD_RST9519, "RST9519" },
+ { MOD_RST9520, "RST9520" },
+ { MOD_RST9521, "RST9521" },
+ { MOD_RST9522, "RST9522" },
+ { MOD_RST9523, "RST9523" },
+ { MOD_RST9524, "RST9524" },
+ { MOD_RST9525, "RST9525" },
+ { MOD_RST9526, "RST9526" },
+ { MOD_RST9527, "RST9527" },
+ { MOD_RST9528, "RST9528" },
+ { MOD_RST9529, "RST9529" },
+ { MOD_RST9530, "RST9530" },
+ { MOD_RST9531, "RST9531" },
+ { MOD_RST9532, "RST9532" },
+ { MOD_RST9533, "RST9533" },
+ { MOD_RST9534, "RST9534" },
+ { MOD_RST9535, "RST9535" },
+ { MOD_RST9536, "RST9536" },
+ { MOD_RST9537, "RST9537" },
+ { MOD_RST9538, "RST9538" },
+ { MOD_RST9539, "RST9539" },
+ { MOD_RST9540, "RST9540" },
+ { MOD_RST9541, "RST9541" },
+ { MOD_RST9542, "RST9542" },
+ { MOD_RST9543, "RST9543" },
+ { MOD_RST9544, "RST9544" },
+ { MOD_RST9545, "RST9545" },
+ { MOD_RST9546, "RST9546" },
+ { MOD_RST9547, "RST9547" },
+ { MOD_RST9548, "RST9548" },
+ { MOD_RST9549, "RST9549" },
+ { MOD_RST9553, "RST9553" },
+ { MOD_RST9555, "RST9555" },
+ { MOD_RST9559, "RST9559" },
+ { MOD_RST9563, "RST9563" },
+ { MOD_RTD, "RTD" },
+ { MOD_RTD_HMP, "RTD_HMP" },
+ { MOD_RTX, "RTX" },
+ { MOD_SDC, "SDC" },
+ { MOD_SLC, "SLC" },
+ { MOD_SLC_LR, "SLC_LR" },
+ { MOD_SMM, "SMM" },
+ { MOD_SMM_RX, "SMM_RX" },
+ { MOD_SMM_TX, "SMM_TX" },
+ { MOD_SPIM, "SPIM" },
+ { MOD_SPIS, "SPIS" },
+ { MOD_STA, "STA" },
+ { MOD_TBH, "TBH" },
+ { MOD_TEMPMON, "TEMPMON" },
+ { MOD_TINT, "TINT" },
+ { MOD_TMC, "TMC" },
+ { MOD_TSM, "TSM" },
+ { MOD_TX_CPY, "TX_CPY" },
+ { MOD_TX_CSI, "TX_CSI" },
+ { MOD_TX_CSO, "TX_CSO" },
+ { MOD_TX_INS, "TX_INS" },
+ { MOD_TX_RPL, "TX_RPL" },
+ { 0L, NULL },
+};
+
+/* NOTE: this needs to be (manually) synced with enum */
+static const char *const a_bus_type[] = {
+ "ERR", /* BUS_TYPE_UNKNOWN, */
+ "BAR", /* BUS_TYPE_BAR, */
+ "PCI", /* BUS_TYPE_PCI, */
+ "CCIP", /* BUS_TYPE_CCIP, */
+ "RAB0", /* BUS_TYPE_RAB0, */
+ "RAB1", /* BUS_TYPE_RAB1, */
+ "RAB2", /* BUS_TYPE_RAB2, */
+ "NMB", /* BUS_TYPE_NMB, */
+ "NDM", /* BUS_TYPE_NDM, */
+};
+
+static const char *get_bus_name(int n_bus_type_id)
+{
+ if (n_bus_type_id >= 1 && n_bus_type_id <= (int)ARRAY_SIZE(a_bus_type))
+ return a_bus_type[n_bus_type_id];
+
+ else
+ return "ERR";
+}
+
+/*
+ * Module name lookup by id from array
+ * Uses naive linear search as performance is not an issue here...
+ */
+static const char *nthw_fpga_mod_id_to_str(uint64_t n_fpga_mod_id)
+{
+ int i;
+
+ for (i = 0; i <= (int)ARRAY_SIZE(sa_nthw_fpga_mod_map); i++) {
+ if ((uint64_t)sa_nthw_fpga_mod_map[i].a == n_fpga_mod_id)
+ break;
+ }
+ return (sa_nthw_fpga_mod_map[i].b ? sa_nthw_fpga_mod_map[i].b :
+ "unknown");
+}
+
+/*
+ * Force C linkage for xxx_addr_bases and xxx_module_versions
+ */
+static int read_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id, uint32_t addr,
+ uint32_t len, uint32_t *p_data)
+{
+ int rc = -1;
+
+ assert(p_fpga_info);
+ assert(p_data);
+
+ switch (n_bus_type_id) {
+ case BUS_TYPE_BAR:
+ case BUS_TYPE_PCI:
+ assert(len == 1);
+ nthw_rac_reg_read32(p_fpga_info, addr, p_data);
+ rc = 0;
+ break;
+ case BUS_TYPE_RAB0:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 0, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB1:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 1, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB2:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 2, len,
+ p_data);
+ break;
+ default:
+ assert(false);
+ return -1;
+ }
+
+ return rc;
+}
+
+static int read_data_tsc(struct fpga_info_s *p_fpga_info, int n_bus_type_id,
+ uint32_t addr, uint32_t len, uint32_t *p_data,
+ uint64_t *p_tsc1, uint64_t *p_tsc2)
+{
+ int rc = -1;
+
+ (void)p_tsc1;
+ (void)p_tsc2;
+
+ rc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data);
+
+ return rc;
+}
+
+static int write_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id,
+ uint32_t addr, uint32_t len, const uint32_t *p_data)
+{
+ int rc = -1;
+
+ assert(p_fpga_info);
+ assert(p_data);
+
+ switch (n_bus_type_id) {
+ case BUS_TYPE_BAR:
+ case BUS_TYPE_PCI:
+ assert(len == 1);
+ nthw_rac_reg_write32(p_fpga_info, addr, *p_data);
+ rc = 0;
+ break;
+ case BUS_TYPE_RAB0:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 0, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB1:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 1, len,
+ p_data);
+ break;
+ case BUS_TYPE_RAB2:
+ assert(p_fpga_info->mp_nthw_rac);
+ rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 2, len,
+ p_data);
+ break;
+ default:
+ assert(false);
+ return -1;
+ }
+
+ return rc;
+}
+
+/*
+ * FpgaMgr
+ */
+nt_fpga_mgr_t *fpga_mgr_new(void)
+{
+ nt_fpga_mgr_t *p = malloc(sizeof(nt_fpga_mgr_t));
+ return p;
+}
+
+void fpga_mgr_delete(nt_fpga_mgr_t *p)
+{
+ memset(p, 0, sizeof(nt_fpga_mgr_t));
+ free(p);
+}
+
+void fpga_mgr_init(nt_fpga_mgr_t *p)
+{
+ size_t i;
+
+ /* Count fpga instance in array */
+ p->mpa_fpga_prod_init = nthw_fpga_instances;
+ for (i = 0; i < ARRAY_SIZE(nthw_fpga_instances); i++) {
+ if (p->mpa_fpga_prod_init[i] == NULL)
+ break;
+ }
+ p->mn_fpgas = (int)i;
+}
+
+nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id,
+ struct fpga_info_s *p_fpga_info)
+{
+ int i;
+
+ const int n_fpga_prod = FPGAID_TO_PRODUCTCODE(n_fpga_id);
+ const int n_fpga_ver = FPGAID_TO_VERSIONCODE(n_fpga_id);
+ const int n_fpga_rev = FPGAID_TO_REVISIONCODE(n_fpga_id);
+
+ for (i = 0; i < p->mn_fpgas; i++) {
+ nt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i];
+
+ if (p_init->fpga_product_id == n_fpga_prod &&
+ p_init->fpga_version == n_fpga_ver &&
+ p_init->fpga_revision == n_fpga_rev) {
+ {
+ nt_fpga_t *p_fpga = fpga_new();
+
+ fpga_init(p_fpga, p_init, p_fpga_info);
+ return p_fpga;
+ }
+ }
+ }
+
+ NT_LOG(ERR, NTHW,
+ "FPGA Id 0x%" PRIX64 ": %04d: %d.%d: no match found\n", n_fpga_id,
+ n_fpga_prod, n_fpga_ver, n_fpga_rev);
+
+ return NULL;
+}
+
+void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *fh_out, int detail_level)
+{
+ int i;
+
+ fprintf(fh_out, "\n"); /* start of records */
+ for (i = 0; i < p->mn_fpgas; i++) {
+ nt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i];
+
+ if (detail_level == 0) {
+ fprintf(fh_out, "%04d-%02d-%02d\n",
+ p_init->fpga_product_id, p_init->fpga_version,
+ p_init->fpga_revision);
+ } else {
+ time_t fpga_build_time = p_init->fpga_build_time;
+
+ fprintf(fh_out, "%04d-%02d-%02d: 0x%08lX: %s\n",
+ p_init->fpga_product_id, p_init->fpga_version,
+ p_init->fpga_revision, fpga_build_time,
+ (fpga_build_time ? ctime(&fpga_build_time) :
+ "NA\n"));
+ }
+ }
+ fprintf(fh_out, "\n"); /* end of records */
+ fflush(fh_out);
+}
+
+void fpga_mgr_log_dump(nt_fpga_mgr_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: fpgas=%d\n", __func__, p->mn_fpgas);
+ for (i = 0; i < p->mn_fpgas; i++) {
+ nt_fpga_prod_init_t *p_init _unused = p->mpa_fpga_prod_init[i];
+ NT_LOG(DBG, NTHW, "%s: fpga=%d/%d: %04d-%02d-%02d\n", __func__,
+ i, p->mn_fpgas, p_init->fpga_product_id, p_init->fpga_version,
+ p_init->fpga_revision);
+ }
+}
+
+/*
+ * Fpga
+ */
+nt_fpga_t *fpga_new(void)
+{
+ nt_fpga_t *p = malloc(sizeof(nt_fpga_t));
+
+ if (p)
+ memset(p, 0, sizeof(nt_fpga_t));
+ return p;
+}
+
+void fpga_delete(nt_fpga_t *p)
+{
+ memset(p, 0, sizeof(nt_fpga_t));
+ free(p);
+}
+
+void fpga_delete_all(nt_fpga_t *p)
+{
+ int i;
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ if (p_mod)
+ module_delete(p_mod);
+ }
+
+ fpga_delete(p);
+}
+
+void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init,
+ struct fpga_info_s *p_fpga_info)
+{
+ int i;
+
+ p->p_fpga_info = p_fpga_info;
+ p->mp_init = fpga_prod_init;
+
+ p->m_item_id = fpga_prod_init->fpga_item_id;
+ p->m_product_id = fpga_prod_init->fpga_product_id;
+ p->m_fpga_version = fpga_prod_init->fpga_version;
+ p->m_fpga_revision = fpga_prod_init->fpga_revision;
+ p->m_fpga_patch_no = fpga_prod_init->fpga_patch_no;
+ p->m_fpga_build_no = fpga_prod_init->fpga_build_no;
+ p->m_fpga_build_time = fpga_prod_init->fpga_build_time;
+
+ p->mn_params = fpga_prod_init->nb_prod_params;
+
+ if (p->mn_params) {
+ p->mpa_params = malloc(p->mn_params * sizeof(nt_param_t *));
+ if (p->mpa_params) {
+ memset(p->mpa_params, 0,
+ (p->mn_params * sizeof(nt_param_t *)));
+ for (i = 0; i < p->mn_params; i++) {
+ nt_param_t *p_param = param_new();
+
+ param_init(p_param, p,
+ &fpga_prod_init->product_params[i]);
+ p->mpa_params[i] = p_param;
+ }
+ }
+ }
+
+ p->mn_modules = fpga_prod_init->nb_modules;
+
+ if (p->mn_modules) {
+ p->mpa_modules =
+ malloc(fpga_prod_init->nb_modules * sizeof(nt_module_t *));
+ if (p->mpa_modules) {
+ memset(p->mpa_modules, 0,
+ (p->mn_modules * sizeof(nt_module_t *)));
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = module_new();
+
+ module_init(p_mod, p, &fpga_prod_init->modules[i]);
+ p->mpa_modules[i] = p_mod;
+ }
+ }
+ }
+}
+
+void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode)
+{
+ int i;
+
+ p->m_debug_mode = n_debug_mode;
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ if (p_mod)
+ module_set_debug_mode(p_mod, n_debug_mode);
+ }
+}
+
+nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance)
+{
+ int i;
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ if (p_mod->m_mod_id == id && p_mod->m_instance == instance)
+ return p_mod;
+ }
+ return NULL;
+}
+
+bool fpga_query(nt_fpga_t *p, int id, int instance)
+{
+ return (fpga_query_module(p, id, instance) != NULL);
+}
+
+nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance)
+{
+ int i;
+
+ for (i = 0; i < p->mp_init->nb_modules; i++) {
+ nt_fpga_module_init_t *p_mod_init = &p->mp_init->modules[i];
+
+ if (p_mod_init->id == id && p_mod_init->instance == instance)
+ return p_mod_init;
+ }
+ return NULL;
+}
+
+int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id,
+ const int n_default_value)
+{
+ int i;
+
+ for (i = 0; i < p->mn_params; i++) {
+ nt_param_t *p_param = p->mpa_params[i];
+
+ if (p_param->param_id == n_param_id)
+ return p_param->param_value;
+ }
+
+ return n_default_value;
+}
+
+int fpga_get_product_id(const nt_fpga_t *p)
+{
+ return p->m_product_id;
+}
+
+int fpga_get_fpga_version(const nt_fpga_t *p)
+{
+ return p->m_fpga_version;
+}
+
+int fpga_get_fpga_revision(const nt_fpga_t *p)
+{
+ return p->m_fpga_revision;
+}
+
+void fpga_log_info(const nt_fpga_t *p _unused)
+{
+ NT_LOG(INF, NTHW, "FPGA: %d-%d-%d-%d-%d-%d (%08X)\n", p->m_item_id,
+ p->m_product_id, p->m_fpga_version, p->m_fpga_revision,
+ p->m_fpga_patch_no, p->m_fpga_build_no, p->m_fpga_build_time);
+}
+
+void fpga_dump(const nt_fpga_t *p)
+{
+ NT_LOG(DBG, NTHW, "%s: id=%d ver=%d.%d params=%d modules=%d\n",
+ __func__, p->m_product_id, p->m_fpga_version, p->m_fpga_revision,
+ p->mn_params, p->mn_modules);
+ fpga_dump_params(p);
+ fpga_dump_modules(p);
+}
+
+void fpga_dump_params(const nt_fpga_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: params=%d\n", __func__, p->mn_params);
+
+ for (i = 0; i < p->mn_params; i++) {
+ nt_param_t *p_par = p->mpa_params[i];
+
+ param_dump(p_par);
+ }
+}
+
+void fpga_dump_modules(const nt_fpga_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: modules=%d\n", __func__, p->mn_modules);
+
+ for (i = 0; i < p->mn_modules; i++) {
+ nt_module_t *p_mod = p->mpa_modules[i];
+
+ module_dump(p_mod);
+ }
+}
+
+/*
+ * Param
+ */
+nt_param_t *param_new(void)
+{
+ nt_param_t *p = malloc(sizeof(nt_param_t));
+ return p;
+}
+
+void param_delete(nt_param_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nt_param_t));
+ free(p);
+ }
+}
+
+void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init)
+{
+ p->mp_owner = p_fpga;
+ p->mp_init = p_init;
+
+ p->param_id = p_init->param_id;
+ p->param_value = p_init->param_value;
+}
+
+void param_dump(const nt_param_t *p _unused)
+{
+ NT_LOG(DBG, NTHW, "%s: id=%d value=%d\n", __func__, p->param_id,
+ p->param_value);
+}
+
+/*
+ * Module
+ */
+nt_module_t *module_new(void)
+{
+ nt_module_t *p = malloc(sizeof(nt_module_t));
+ return p;
+}
+
+void module_delete(nt_module_t *p)
+{
+ int i;
+
+ for (i = 0; i < p->mn_registers; i++) {
+ nt_register_t *p_reg = p->mpa_registers[i];
+
+ if (p_reg)
+ register_delete(p_reg);
+ }
+ memset(p, 0, sizeof(nt_module_t));
+ free(p);
+}
+
+void module_init(nt_module_t *p, nt_fpga_t *p_fpga, nt_fpga_module_init_t *p_init)
+{
+ int i;
+
+ p->mp_owner = p_fpga;
+ p->mp_init = p_init;
+
+ p->m_mod_id = p_init->id;
+ p->m_instance = p_init->instance;
+
+ /* Copy debug mode from owner */
+ if (p->mp_owner)
+ p->m_debug_mode = p->mp_owner->m_debug_mode;
+
+ else
+ p->m_debug_mode = 0;
+
+ p->m_mod_def_id = p_init->def_id;
+ p->m_major_version = p_init->major_version;
+ p->m_minor_version = p_init->minor_version;
+ p->m_bus = p_init->bus_id;
+ p->m_addr_base = p_init->addr_base;
+
+ p->mn_registers = p_init->nb_registers;
+ if (p->mn_registers) {
+ p->mpa_registers =
+ malloc(p->mn_registers * sizeof(nt_register_t *));
+ if (p->mpa_registers) {
+ memset(p->mpa_registers, 0,
+ (p->mn_registers * sizeof(nt_register_t *)));
+ for (i = 0; i < p->mn_registers; i++) {
+ nt_register_t *p_reg = register_new();
+
+ register_init(p_reg, p, &p_init->registers[i]);
+ p->mpa_registers[i] = p_reg;
+ }
+ }
+ }
+}
+
+void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance,
+ int debug_mode)
+{
+ nt_fpga_module_init_t *p_init = NULL;
+
+ p_init = fpga_lookup_init(p_fpga, mod_id, instance);
+ module_init(p, p_fpga, p_init);
+
+ /* set debug mode after regulat init... */
+ p->m_debug_mode = debug_mode;
+}
+
+void module_dump(const nt_module_t *p)
+{
+ NT_LOG(DBG, NTHW,
+ "%s: id=%d inst=%d def=%d ver=%d.%d busid=%d base=0x%X regs=%d\n",
+ __func__, p->m_mod_id, p->m_instance, p->m_mod_def_id,
+ p->m_major_version, p->m_minor_version, p->m_bus, p->m_addr_base,
+ p->mn_registers);
+ module_dump_registers(p);
+}
+
+void module_dump_registers(const nt_module_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s: regs=%d\n", __func__, p->mn_registers);
+
+ for (i = 0; i < p->mn_registers; i++) {
+ nt_register_t *p_reg = p->mpa_registers[i];
+
+ register_dump(p_reg);
+ }
+}
+
+int module_get_major_version(const nt_module_t *p)
+{
+ return p->m_major_version;
+}
+
+int module_get_minor_version(const nt_module_t *p)
+{
+ return p->m_minor_version;
+}
+
+uint64_t module_get_version_packed64(const nt_module_t *p)
+{
+ return (((uint64_t)p->m_major_version & 0xFFFFFFFF) << 32) |
+ (p->m_minor_version & 0xFFFFFFFF);
+}
+
+bool module_is_version_newer(const nt_module_t *p, int major_version,
+ int minor_version)
+{
+ if (major_version == p->m_major_version)
+ return p->m_minor_version >= minor_version;
+ return p->m_major_version >= major_version;
+}
+
+static nt_register_t *module_lookup_register(nt_module_t *p, uint32_t id)
+{
+ int i;
+ nt_register_t *p_register = NULL;
+
+ for (i = 0; i < p->mn_registers; i++) {
+ if (p->mpa_registers[i]->m_id == id) {
+ p_register = p->mpa_registers[i];
+ break;
+ }
+ }
+ return p_register;
+}
+
+nt_register_t *module_get_register(nt_module_t *p, uint32_t id)
+{
+ nt_register_t *p_register;
+
+ if (p == NULL) {
+ NT_LOG(ERR, NTHW, "Illegal module context for register %d\n",
+ id);
+ return NULL;
+ }
+
+ p_register = module_lookup_register(p, id);
+ if (!p_register) {
+ NT_LOG(ERR, NTHW, "Register %d not found in module: %s (%d)\n",
+ id, nthw_fpga_mod_id_to_str(p->m_mod_id), p->m_mod_id);
+ }
+ return p_register;
+}
+
+nt_register_t *module_query_register(nt_module_t *p, uint32_t id)
+{
+ return module_lookup_register(p, id);
+}
+
+int module_get_debug_mode(const nt_module_t *p)
+{
+ return p->m_debug_mode;
+}
+
+void module_set_debug_mode(nt_module_t *p, unsigned int n_debug_mode)
+{
+ int i;
+ nt_register_t *p_register = NULL;
+
+ p->m_debug_mode = n_debug_mode;
+
+ for (i = 0; i < p->mn_registers; i++) {
+ p_register = p->mpa_registers[i];
+ if (p_register)
+ register_set_debug_mode(p_register, n_debug_mode);
+ }
+}
+
+int module_get_bus(const nt_module_t *p)
+{
+ return p->m_bus;
+}
+
+uint32_t module_get_addr_base(const nt_module_t *p)
+{
+ return p->m_addr_base;
+}
+
+void module_unsuppported(const nt_module_t *p)
+{
+ NT_LOG(ERR, NTHW, "Module %d not supported", p->mp_init->id);
+}
+
+/*
+ * Register
+ */
+nt_register_t *register_new(void)
+{
+ nt_register_t *p = malloc(sizeof(nt_register_t));
+ return p;
+}
+
+void register_delete(nt_register_t *p)
+{
+ int i;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ nt_field_t *p_field = p->mpa_fields[i];
+
+ if (p_field)
+ field_delete(p_field);
+ }
+
+ if (p->mp_shadow)
+ free(p->mp_shadow);
+
+ if (p->mp_dirty)
+ free(p->mp_dirty);
+
+ memset(p, 0, sizeof(nt_register_t));
+ free(p);
+}
+
+void register_init(nt_register_t *p, nt_module_t *p_module,
+ nt_fpga_register_init_t *p_init)
+{
+ int i;
+
+ p->mp_owner = p_module;
+
+ p->m_id = p_init->id;
+ p->mn_bit_width = p_init->bw;
+ p->mn_addr_rel = p_init->addr_rel;
+ p->m_addr = p_module->m_addr_base + p_init->addr_rel;
+ p->m_type = p_init->type;
+ p->m_len =
+ ((p_init->bw != (uint16_t)-1) ?
+ ((p_init->bw + 31) >> 5) :
+ 1); /* Old P200 registers have no bw at register level - default to BW=-1 */
+ p->m_debug_mode = p_module->m_debug_mode;
+
+ p->mn_fields = p_init->nb_fields;
+ if (p->mn_fields) {
+ p->mpa_fields = malloc(p->mn_fields * sizeof(nt_field_t *));
+
+ if (p->mpa_fields) {
+ memset(p->mpa_fields, 0,
+ (p->mn_fields * sizeof(nt_field_t *)));
+ for (i = 0; i < p->mn_fields; i++) {
+ nt_field_t *p_field = field_new();
+
+ field_init(p_field, p, &p_init->fields[i]);
+ p->mpa_fields[i] = p_field;
+ }
+
+ p->mp_shadow = malloc(p->m_len * sizeof(uint32_t));
+ if (p->mp_shadow) {
+ memset(p->mp_shadow, 0x00,
+ (p->m_len * sizeof(uint32_t)));
+ }
+
+ p->mp_dirty = malloc(p->m_len * sizeof(bool));
+ if (p->mp_dirty) {
+ memset(p->mp_dirty, 0x00,
+ (p->m_len * sizeof(bool)));
+ }
+ }
+ }
+}
+
+void register_dump(const nt_register_t *p)
+{
+ NT_LOG(DBG, NTHW,
+ "%s(id=%d type=%d addr=0x%08X addrrel=0x%08X len=%d bw=%d\n",
+ __func__, p->m_id, p->m_type, p->m_addr, p->mn_addr_rel, p->m_len,
+ p->mn_bit_width);
+ register_dump_fields(p);
+}
+
+void register_dump_fields(const nt_register_t *p)
+{
+ int i;
+
+ NT_LOG(DBG, NTHW, "%s(addr=0x%08X fields=%d\n", __func__, p->m_addr,
+ p->mn_fields);
+ for (i = 0; i < p->mn_fields; i++)
+ field_dump(p->mpa_fields[i]);
+ NT_LOG(DBG, NTHW, "\n");
+}
+
+uint32_t register_get_address(const nt_register_t *p)
+{
+ return p->m_addr;
+}
+
+void register_reset(const nt_register_t *p)
+{
+ int i;
+ nt_field_t *p_field = NULL;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ p_field = p->mpa_fields[i];
+ if (p_field)
+ field_reset(p_field);
+ }
+}
+
+static nt_field_t *register_lookup_field(const nt_register_t *p, uint32_t id)
+{
+ int i;
+ nt_field_t *p_field = NULL;
+
+ if (!p)
+ return NULL;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ if (p->mpa_fields[i]->m_id == id) {
+ p_field = p->mpa_fields[i];
+ break;
+ }
+ }
+ return p_field;
+}
+
+nt_field_t *register_get_field(const nt_register_t *p, uint32_t id)
+{
+ nt_field_t *p_field;
+
+ if (p == NULL) {
+ NT_LOG(ERR, NTHW, "Illegal register context for field %d\n",
+ id);
+ return NULL;
+ }
+
+ p_field = register_lookup_field(p, id);
+ if (!p_field) {
+ NT_LOG(ERR, NTHW, "Field %d not found in module: %s (%d)\n", id,
+ nthw_fpga_mod_id_to_str(p->mp_owner->m_mod_id),
+ p->mp_owner->m_mod_id);
+ }
+ return p_field;
+}
+
+nt_field_t *register_query_field(const nt_register_t *p, uint32_t id)
+{
+ return register_lookup_field(p, id);
+}
+
+int register_get_bit_width(const nt_register_t *p)
+{
+ return p->mn_bit_width;
+}
+
+uint32_t register_get_addr_rel(const nt_register_t *p)
+{
+ return p->mn_addr_rel;
+}
+
+int register_get_debug_mode(const nt_module_t *p)
+{
+ return p->m_debug_mode;
+}
+
+/*
+ * NOTE: do not set debug on fields - as register operation dumps typically are enough
+ */
+void register_set_debug_mode(nt_register_t *p, unsigned int n_debug_mode)
+{
+ int i;
+ nt_field_t *p_field = NULL;
+
+ p->m_debug_mode = n_debug_mode;
+
+ for (i = 0; i < p->mn_fields; i++) {
+ p_field = p->mpa_fields[i];
+ if (p_field)
+ field_set_debug_mode(p_field, n_debug_mode);
+ }
+}
+
+static int register_read_data(const nt_register_t *p)
+{
+ int rc = -1;
+
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ struct fpga_info_s *p_fpga_info = NULL;
+
+ if (p && p->mp_owner && p->mp_owner->mp_owner)
+ p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
+ assert(p_fpga_info);
+ assert(p_data);
+
+ rc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data);
+ return rc;
+}
+
+static int register_read_data_tsc(const nt_register_t *p, uint64_t *p_tsc1,
+ uint64_t *p_tsc2)
+{
+ int rc = -1;
+
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ struct fpga_info_s *p_fpga_info = NULL;
+
+ if (p && p->mp_owner && p->mp_owner->mp_owner)
+ p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
+
+ rc = read_data_tsc(p_fpga_info, n_bus_type_id, addr, len, p_data, p_tsc1, p_tsc2);
+
+ return rc;
+}
+
+static int register_write_data(const nt_register_t *p, uint32_t cnt)
+{
+ int rc = -1;
+
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ struct fpga_info_s *p_fpga_info = NULL;
+
+ if (p && p->mp_owner && p->mp_owner->mp_owner)
+ p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
+ assert(p_fpga_info);
+ assert(p_data);
+
+ rc = write_data(p_fpga_info, n_bus_type_id, addr, (len * cnt), p_data);
+
+ return rc;
+}
+
+void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len)
+{
+ uint32_t i;
+
+ if (len == (uint32_t)-1 || len > p->m_len)
+ len = p->m_len;
+
+ assert(len <= p->m_len);
+ assert(p_data);
+
+ for (i = 0; i < len; i++)
+ p_data[i] = p->mp_shadow[i];
+}
+
+uint32_t register_get_val32(const nt_register_t *p)
+{
+ uint32_t val = 0;
+
+ register_get_val(p, &val, 1);
+ return val;
+}
+
+void register_update(const nt_register_t *p)
+{
+ if (p && p->m_type != REGISTER_TYPE_WO) {
+ const char *const p_dev_name _unused = "NA";
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+
+ const char *const p_bus_name _unused = get_bus_name(n_bus_type_id);
+ const uint32_t addr _unused = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+
+ register_read_data(p);
+ if (p->m_debug_mode & ON_READ) {
+ uint32_t i = len;
+
+ uint32_t *ptr _unused = p_data;
+ NT_LOG(DBG, NTHW,
+ "Register::read(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:",
+ p_dev_name, p_bus_name, addr, len);
+ while (i--)
+ NT_LOG(DBG, NTHW, " 0x%08X ", *ptr++);
+ NT_LOG(DBG, NTHW, ")\n");
+ }
+ }
+}
+
+uint32_t register_get_val_updated32(const nt_register_t *p)
+{
+ uint32_t val = 0;
+
+ register_update(p);
+ register_get_val(p, &val, 1);
+ return val;
+}
+
+void register_make_dirty(nt_register_t *p)
+{
+ uint32_t i;
+
+ for (i = 0; i < p->m_len; i++)
+ p->mp_dirty[i] = true;
+}
+
+void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len)
+{
+ assert(len <= p->m_len);
+ assert(p_data);
+
+ if (len == (uint32_t)-1 || len > p->m_len)
+ len = p->m_len;
+
+ if (p->mp_shadow != p_data)
+ memcpy(p->mp_shadow, p_data, (len * sizeof(uint32_t)));
+}
+
+void register_set_val_flush(nt_register_t *p, const uint32_t *p_data, uint32_t len)
+{
+ register_set_val(p, p_data, len);
+ register_flush(p, 1);
+}
+
+void register_flush(const nt_register_t *p, uint32_t cnt)
+{
+ int rc;
+
+ if (p->m_type != REGISTER_TYPE_RO) {
+ const char *const p_dev_name = "NA";
+ const int n_bus_type_id = module_get_bus(p->mp_owner);
+ const char *p_bus_name = get_bus_name(n_bus_type_id);
+ const uint32_t addr = p->m_addr;
+ const uint32_t len = p->m_len;
+ uint32_t *const p_data = p->mp_shadow;
+ uint32_t i;
+
+ assert(len * cnt <= 256);
+
+ if (p->m_debug_mode & ON_WRITE) {
+ uint32_t i = len * cnt;
+ uint32_t *ptr = p_data;
+ char *tmp_string =
+ ntlog_helper_str_alloc("Register::write");
+ ntlog_helper_str_add(tmp_string,
+ "(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:",
+ p_dev_name, p_bus_name, addr, i);
+ while (i--) {
+ ntlog_helper_str_add(tmp_string, " 0x%08X",
+ *ptr++);
+ }
+ ntlog_helper_str_add(tmp_string, ")\n");
+ NT_LOG(DBG, NTHW, "%s", tmp_string);
+ ntlog_helper_str_free(tmp_string);
+ }
+
+ rc = register_write_data(p, cnt);
+
+ if (rc)
+ NT_LOG(ERR, NTHW, "Register write error %d\n", rc);
+
+ for (i = 0; i < cnt; i++)
+ p->mp_dirty[i] = false;
+ }
+}
+
+void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1,
+ uint64_t *tsc2)
+{
+ register_read_data_tsc(p, tsc1, tsc2);
+}
+
+void register_clr(nt_register_t *p)
+{
+ memset(p->mp_shadow, 0, p->m_len * sizeof(uint32_t));
+ register_make_dirty(p);
+}
+
+void register_set(nt_register_t *p)
+{
+ memset(p->mp_shadow, 0xff, p->m_len * sizeof(uint32_t));
+ register_make_dirty(p);
+}
+
+/*
+ * Field
+ */
+nt_field_t *field_new(void)
+{
+ nt_field_t *p = malloc(sizeof(nt_field_t));
+ return p;
+}
+
+void field_delete(nt_field_t *p)
+{
+ memset(p, 0, sizeof(nt_field_t));
+ free(p);
+}
+
+void field_init(nt_field_t *p, nt_register_t *p_reg,
+ const nt_fpga_field_init_t *p_init)
+{
+ p->mp_owner = p_reg;
+
+ p->m_debug_mode = p_reg->m_debug_mode;
+
+ p->m_id = p_init->id;
+ p->mn_bit_width = p_init->bw;
+ p->mn_bit_pos_low = p_init->low;
+ p->m_reset_val = (uint32_t)p_init->reset_val;
+ p->m_first_word = p_init->low / 32;
+ p->m_first_bit = p_init->low % 32;
+ p->m_front_mask = 0;
+ p->m_body_length = 0;
+ p->mn_words = (p_init->bw + 0x1f) / 0x20;
+ p->m_tail_mask = 0;
+
+ {
+ int bits_remaining = p_init->bw;
+ int front_mask_length = 32 - p->m_first_bit;
+
+ if (front_mask_length > bits_remaining)
+ front_mask_length = bits_remaining;
+ bits_remaining -= front_mask_length;
+
+ p->m_front_mask = (uint32_t)(((1ULL << front_mask_length) - 1)
+ << p->m_first_bit);
+
+ p->m_body_length = bits_remaining / 32;
+ bits_remaining -= p->m_body_length * 32;
+ p->m_tail_mask = (1 << bits_remaining) - 1;
+
+ if (p->m_debug_mode >= 0x100) {
+ NT_LOG(DBG, NTHW,
+ "%s: fldid=%08d: [%08d:%08d] %08d/%08d: (%08d,%08d) (0x%08X,%08d,0x%08X)\n",
+ __func__, p_init->id, p_init->low,
+ (p_init->low + p_init->bw), p_init->bw,
+ ((p_init->bw + 31) / 32), p->m_first_word,
+ p->m_first_bit, p->m_front_mask, p->m_body_length,
+ p->m_tail_mask);
+ }
+ }
+}
+
+int field_get_debug_mode(const nt_module_t *p)
+{
+ return p->m_debug_mode;
+}
+
+void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode)
+{
+ p->m_debug_mode = n_debug_mode;
+}
+
+int field_get_bit_width(const nt_field_t *p)
+{
+ return p->mn_bit_width;
+}
+
+int field_get_bit_pos_low(const nt_field_t *p)
+{
+ return p->mn_bit_pos_low;
+}
+
+int field_get_bit_pos_high(const nt_field_t *p)
+{
+ return p->mn_bit_pos_low + p->mn_bit_width - 1;
+}
+
+uint32_t field_get_mask(const nt_field_t *p)
+{
+ return p->m_front_mask;
+}
+
+void field_reset(const nt_field_t *p)
+{
+ field_set_val32(p, (uint32_t)p->m_reset_val);
+}
+
+uint32_t field_get_val_mask(const nt_field_t *p)
+{
+ return (p->m_front_mask >> p->mn_bit_pos_low);
+}
+
+uint32_t field_get_reset_val(const nt_field_t *p)
+{
+ return (uint32_t)p->m_reset_val;
+}
+
+void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len)
+{
+ uint32_t i;
+ uint32_t data_index = 0;
+ uint32_t shadow_index = p->m_first_word;
+
+ union {
+ uint32_t w32[2];
+ uint64_t w64;
+ } buf;
+
+ (void)len;
+ assert(len == p->mn_words);
+
+ /* handle front */
+ buf.w32[0] = p->mp_owner->mp_shadow[shadow_index++] & p->m_front_mask;
+
+ /* handle body */
+ for (i = 0; i < p->m_body_length; i++) {
+ buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++];
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ assert(data_index < len);
+ p_data[data_index++] = buf.w32[0];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ }
+
+ /* handle tail */
+ if (p->m_tail_mask)
+ buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++] & p->m_tail_mask;
+
+ else
+ buf.w32[1] = 0;
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ p_data[data_index++] = buf.w32[0];
+ if (data_index < p->mn_words)
+ p_data[data_index++] = buf.w32[1];
+}
+
+void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len)
+{
+ uint32_t i;
+ uint32_t data_index = 0;
+ uint32_t shadow_index = p->m_first_word;
+
+ union {
+ uint32_t w32[2];
+ uint64_t w64;
+ } buf;
+
+ (void)len;
+ assert(len == p->mn_words);
+
+ /* handle front */
+ buf.w32[0] = 0;
+ buf.w32[1] = p_data[data_index++];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ p->mp_owner->mp_shadow[shadow_index] =
+ (p->mp_owner->mp_shadow[shadow_index] & ~p->m_front_mask) |
+ (buf.w32[0] & p->m_front_mask);
+ shadow_index++;
+
+ /* handle body */
+ for (i = 0; i < p->m_body_length; i++) {
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ assert(data_index < len);
+ buf.w32[1] = p_data[data_index++];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ p->mp_owner->mp_shadow[shadow_index++] = buf.w32[0];
+ }
+
+ /* handle tail */
+ if (p->m_tail_mask) {
+ buf.w64 = buf.w64 >> (p->m_first_bit);
+ if (data_index < len)
+ buf.w32[1] = p_data[data_index];
+ buf.w64 = buf.w64 >> (32 - p->m_first_bit);
+ p->mp_owner->mp_shadow[shadow_index] =
+ (p->mp_owner->mp_shadow[shadow_index] & ~p->m_tail_mask) |
+ (buf.w32[0] & p->m_tail_mask);
+ }
+
+ register_make_dirty(p->mp_owner);
+}
+
+void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data, uint32_t len)
+{
+ field_set_val(p, p_data, len);
+ field_flush_register(p);
+}
+
+uint32_t field_get_val32(const nt_field_t *p)
+{
+ uint32_t val;
+
+ field_get_val(p, &val, 1);
+ return val;
+}
+
+uint32_t field_get_updated(const nt_field_t *p)
+{
+ uint32_t val;
+
+ register_update(p->mp_owner);
+ field_get_val(p, &val, 1);
+
+ return val;
+}
+
+void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2)
+{
+ register_do_read_trig_ts(p->mp_owner, tsc1, tsc2);
+}
+
+void field_update_register(const nt_field_t *p)
+{
+ register_update(p->mp_owner);
+}
+
+void field_flush_register(const nt_field_t *p)
+{
+ register_flush(p->mp_owner, 1);
+}
+
+void field_set_val32(const nt_field_t *p, uint32_t val)
+{
+ field_set_val(p, &val, 1);
+}
+
+void field_set_val_flush32(const nt_field_t *p, uint32_t val)
+{
+ field_set_val(p, &val, 1);
+ register_flush(p->mp_owner, 1);
+}
+
+void field_clr_all(const nt_field_t *p)
+{
+ assert(p->m_body_length == 0);
+ field_set_val32(p, 0);
+}
+
+void field_clr_flush(const nt_field_t *p)
+{
+ field_clr_all(p);
+ register_flush(p->mp_owner, 1);
+}
+
+void field_set_all(const nt_field_t *p)
+{
+ assert(p->m_body_length == 0);
+ field_set_val32(p, ~0);
+}
+
+void field_set_flush(const nt_field_t *p)
+{
+ field_set_all(p);
+ register_flush(p->mp_owner, 1);
+}
+
+enum field_match {
+ FIELD_MATCH_CLR_ALL,
+ FIELD_MATCH_SET_ALL,
+ FIELD_MATCH_CLR_ANY,
+ FIELD_MATCH_SET_ANY,
+};
+
+static int field_wait_cond32(const nt_field_t *p, enum field_match e_match,
+ int n_poll_iterations, int n_poll_interval)
+{
+ const uint32_t n_mask = (1 << p->mn_bit_width) - 1;
+
+ if (n_poll_iterations == -1)
+ n_poll_iterations = 10000;
+ if (n_poll_interval == -1)
+ n_poll_interval = 100; /* usec */
+
+ if (p->m_debug_mode) {
+ const char *const p_cond_name _unused =
+ ((e_match == FIELD_MATCH_SET_ALL) ?
+ "SetAll" :
+ ((e_match == FIELD_MATCH_CLR_ALL) ?
+ "ClrAll" :
+ ((e_match == FIELD_MATCH_CLR_ANY) ?
+ "ClrAny" :
+ "SetAny")));
+ const char *const p_dev_name _unused = "NA";
+ const char *const p_bus_name _unused =
+ get_bus_name(module_get_bus(p->mp_owner->mp_owner));
+ uint32_t n_reg_addr _unused = register_get_address(p->mp_owner);
+
+ uint32_t n_reg_mask _unused =
+ (((1 << p->mn_bit_width) - 1) << p->mn_bit_pos_low);
+
+ NT_LOG(DBG, NTHW,
+ "Register::Field::wait%s32(Dev: %s, Bus: %s, Addr: 0x%08X, Mask: 0x%08X, Iterations: %d, Interval: %d)\n",
+ p_cond_name, p_dev_name, p_bus_name, n_reg_addr, n_reg_mask,
+ n_poll_iterations, n_poll_interval);
+ }
+
+ while (true) {
+ uint32_t val = field_get_updated(p);
+
+ if (e_match == FIELD_MATCH_SET_ANY && val != 0) {
+ return 0;
+ } else if (e_match == FIELD_MATCH_SET_ALL && val == n_mask) {
+ return 0;
+ } else if (e_match == FIELD_MATCH_CLR_ALL && val == 0) {
+ return 0;
+ } else if (e_match == FIELD_MATCH_CLR_ANY) {
+ uint32_t mask = field_get_mask(p);
+
+ if (val != mask)
+ return 0;
+ }
+
+ n_poll_iterations--;
+ if (n_poll_iterations <= 0)
+ return -1;
+ NT_OS_WAIT_USEC(n_poll_interval);
+ }
+ return 0;
+}
+
+int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_SET_ALL, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_CLR_ALL, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_SET_ANY, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval)
+{
+ return field_wait_cond32(p, FIELD_MATCH_CLR_ANY, n_poll_iterations,
+ n_poll_interval);
+}
+
+int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value,
+ uint32_t n_wait_cond_mask, int n_poll_iterations,
+ int n_poll_interval)
+{
+ if (n_poll_iterations == -1)
+ n_poll_iterations = 10000;
+ if (n_poll_interval == -1)
+ n_poll_interval = 100;
+
+ while (true) {
+ uint32_t val = field_get_updated(p);
+
+ if (val == (n_wait_cond_value & n_wait_cond_mask))
+ break;
+ n_poll_iterations--;
+ if (n_poll_iterations <= 0)
+ return -1;
+ NT_OS_WAIT_USEC(n_poll_interval);
+ }
+ return 0;
+}
+
+void field_dump(const nt_field_t *p _unused)
+{
+ NT_LOG(DBG, NTHW, "%s: %02d: %02d %02d %02d: %02d: %X\n", __func__,
+ p->m_id, p->mn_bit_pos_low, (p->mn_bit_pos_low + p->mn_bit_width),
+ p->mn_bit_width, p->mn_words, p->m_reset_val);
+}
+
+void field_dump_val(const nt_field_t *p)
+{
+ int i;
+ uint32_t buf[32];
+
+ field_get_val(p, buf, p->mn_words);
+ NT_LOG(DBG, NTHW, " @%d:", p->m_first_bit + p->m_first_word * 32);
+ NT_LOG(DBG, NTHW, "%X", buf[p->mn_words - 1]);
+ for (i = p->mn_words - 1; i > 0; i--)
+ NT_LOG(DBG, NTHW, "%08X", buf[i - 1]);
+ NT_LOG(DBG, NTHW, "\n");
+}
+
+void field_dump_init(const nt_fpga_field_init_t *p _unused)
+{
+ NT_LOG(DBG, NTHW, "%s: %02d: %02d %02d %02d: 0x%" PRIX64 "\n", __func__,
+ p->id, p->low, p->low + p->bw, p->bw, p->reset_val);
+}
+
+/*
+ * nthw fpga model helpers
+ */
+
+nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident)
+{
+ nt_fpga_mgr_t *p_fpga_mgr = NULL;
+ nt_fpga_t *p_fpga = NULL;
+ int n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id;
+ char s_fpga_prod_ver_rev_str[32];
+
+ p_fpga_mgr = fpga_mgr_new();
+ fpga_mgr_init(p_fpga_mgr);
+ p_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info);
+
+ n_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident);
+ n_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident);
+ n_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident);
+ n_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident);
+
+ snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str),
+ "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id,
+ n_fpga_rev_id);
+
+ if (p_fpga == NULL) {
+ NT_LOG(ERR, NTHW, "%s: no match for FPGA: %s\n", __func__,
+ s_fpga_prod_ver_rev_str);
+ /* do not return here... */
+ }
+
+ if (p_fpga_mgr) {
+ fpga_mgr_delete(p_fpga_mgr);
+ p_fpga_mgr = NULL;
+ }
+
+ return p_fpga;
+}
+
+nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance)
+{
+ nt_module_t *p_mod = fpga_query_module(p_fpga, n_mod, n_instance);
+ return p_mod;
+}
+
+nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg)
+{
+ nt_register_t *p_reg = module_get_register(p_mod, n_reg);
+ return p_reg;
+}
+
+nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld)
+{
+ nt_field_t *p_fld = register_get_field(p_reg, n_fld);
+ return p_fld;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.h b/drivers/net/ntnic/nthw/nthw_fpga_model.h
new file mode 100644
index 0000000000..b00b7b6cfa
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_fpga_model.h
@@ -0,0 +1,308 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_FPGA_MODEL_H__
+#define __NTHW_FPGA_MODEL_H__
+
+#include <stdbool.h>
+#include <stdio.h>
+#include "fpga_model.h"
+
+#ifndef FPGAID_TO_PRODUCTCODE
+#define FPGAID_TO_PRODUCTTYPE(fpga_id) ((uint16_t)((fpga_id) >> 32) & 0xFF)
+#define FPGAID_TO_PRODUCTCODE(fpga_id) ((uint16_t)((fpga_id) >> 16) & 0xFFFF)
+#define FPGAID_TO_VERSIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 8 & 0xFF))
+#define FPGAID_TO_REVISIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 0 & 0xFF))
+#endif
+
+#define VERSION_PACKED64(_major_, _minor_) \
+ ((((uint64_t)(_major_) & 0xFFFFFFFF) << 32) | ((_minor_) & 0xFFFFFFFF))
+
+enum debug_mode { NO_DEBUG, ON_READ, ON_WRITE };
+
+enum nthw_bus_type {
+ NTHW_BUS_UNKNOWN,
+ NTHW_BUS_BAR,
+ NTHW_BUS_PCI,
+ NTHW_BUS_NMB,
+ NTHW_BUS_NDM,
+ NTHW_BUS_RAB0,
+ NTHW_BUS_RAB1,
+ NTHW_BUS_RAB2
+};
+
+struct nt_fpga_s;
+
+struct nt_param_s;
+
+struct nt_module_s;
+
+struct nt_register_s;
+
+struct nt_field_s;
+
+struct nt_fpga_mgr_s {
+ int mn_fpgas;
+ struct nt_fpga_prod_init **mpa_fpga_prod_init;
+};
+
+typedef struct nt_fpga_mgr_s nt_fpga_mgr_t;
+
+struct nt_fpga_s {
+ struct fpga_info_s *p_fpga_info;
+
+ int m_item_id;
+ int m_product_id;
+ int m_fpga_version;
+ int m_fpga_revision;
+ int m_fpga_patch_no;
+ int m_fpga_build_no;
+ uint32_t m_fpga_build_time;
+
+ int mn_params;
+ struct nt_param_s **mpa_params;
+
+ int mn_modules;
+ struct nt_module_s **mpa_modules;
+
+ nt_fpga_prod_init_t *mp_init;
+
+ int m_debug_mode;
+};
+
+typedef struct nt_fpga_s nt_fpga_t;
+
+struct nt_param_s {
+ nt_fpga_t *mp_owner;
+
+ int param_id;
+ int param_value;
+
+ nt_fpga_prod_param_t *mp_init;
+};
+
+typedef struct nt_param_s nt_param_t;
+
+struct nt_module_s {
+ nt_fpga_t *mp_owner;
+
+ int m_mod_id;
+
+ int m_instance;
+
+ int m_mod_def_id;
+ int m_major_version;
+ int m_minor_version;
+
+ int m_bus;
+ uint32_t m_addr_base;
+
+ int m_debug_mode;
+
+ int mn_registers;
+ struct nt_register_s **mpa_registers;
+
+ nt_fpga_module_init_t *mp_init;
+};
+
+typedef struct nt_module_s nt_module_t;
+
+struct nt_register_s {
+ nt_module_t *mp_owner;
+
+ uint32_t m_id;
+
+ uint32_t mn_bit_width;
+ uint32_t mn_addr_rel;
+ uint32_t m_addr;
+ uint32_t m_type;
+ uint32_t m_len;
+
+ int m_debug_mode;
+
+ int mn_fields;
+ struct nt_field_s **mpa_fields;
+
+ uint32_t *mp_shadow;
+ bool *mp_dirty;
+
+ nt_fpga_register_init_t *mp_init;
+};
+
+typedef struct nt_register_s nt_register_t;
+
+struct nt_field_s {
+ nt_register_t *mp_owner;
+
+ uint32_t m_id;
+
+ uint32_t mn_bit_width;
+ uint32_t mn_bit_pos_low;
+ uint32_t m_reset_val;
+ uint32_t m_first_word;
+ uint32_t m_first_bit;
+ uint32_t m_front_mask;
+ uint32_t m_body_length;
+ uint32_t mn_words;
+ uint32_t m_tail_mask;
+
+ int m_debug_mode;
+
+ nt_fpga_field_init_t *mp_init;
+};
+
+typedef struct nt_field_s nt_field_t;
+
+nt_fpga_mgr_t *fpga_mgr_new(void);
+void fpga_mgr_init(nt_fpga_mgr_t *p);
+void fpga_mgr_delete(nt_fpga_mgr_t *p);
+nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id,
+ struct fpga_info_s *p_fpga_info);
+
+void fpga_mgr_log_dump(nt_fpga_mgr_t *p);
+void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *out, int detail_level);
+
+nt_fpga_t *fpga_new(void);
+void fpga_delete(nt_fpga_t *p);
+void fpga_delete_all(nt_fpga_t *p);
+void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init,
+ struct fpga_info_s *p_fpga_info);
+
+int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id,
+ const int default_value);
+int fpga_get_product_id(const nt_fpga_t *p);
+int fpga_get_fpga_version(const nt_fpga_t *p);
+int fpga_get_fpga_revision(const nt_fpga_t *p);
+nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance);
+nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance);
+bool fpga_query(nt_fpga_t *p, int id, int instance);
+void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode);
+
+void fpga_log_info(const nt_fpga_t *p);
+void fpga_dump(const nt_fpga_t *p);
+void fpga_dump_params(const nt_fpga_t *p);
+void fpga_dump_modules(const nt_fpga_t *p);
+
+nt_param_t *param_new(void);
+void param_delete(nt_param_t *p);
+void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init);
+
+void param_dump(const nt_param_t *p);
+
+nt_module_t *module_new(void);
+void module_delete(nt_module_t *p);
+void module_init(nt_module_t *p, nt_fpga_t *p_fpga,
+ nt_fpga_module_init_t *p_init);
+void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance,
+ int debug_mode);
+
+int module_get_major_version(const nt_module_t *p);
+int module_get_minor_version(const nt_module_t *p);
+uint64_t module_get_version_packed64(const nt_module_t *p);
+bool module_is_version_newer(const nt_module_t *p, int major_version,
+ int minor_version);
+
+int module_get_bus(const nt_module_t *p);
+nt_register_t *module_get_register(nt_module_t *p, uint32_t id);
+nt_register_t *module_query_register(nt_module_t *p, uint32_t id);
+int module_get_debug_mode(const nt_module_t *p);
+void module_set_debug_mode(nt_module_t *p, unsigned int debug_mode);
+uint32_t module_get_addr_base(const nt_module_t *p);
+void module_unsuppported(const nt_module_t *p);
+
+void module_dump(const nt_module_t *p);
+void module_dump_registers(const nt_module_t *p);
+
+nt_register_t *register_new(void);
+void register_delete(nt_register_t *p);
+void register_init(nt_register_t *p, nt_module_t *p_module,
+ nt_fpga_register_init_t *p_init);
+
+nt_field_t *register_get_field(const nt_register_t *p, uint32_t id);
+nt_field_t *register_query_field(const nt_register_t *p, uint32_t id);
+
+uint32_t register_get_address(const nt_register_t *p);
+uint32_t register_get_addr_rel(const nt_register_t *p);
+int register_get_bit_width(const nt_register_t *p);
+int register_get_debug_mode(const nt_module_t *p);
+void register_set_debug_mode(nt_register_t *p, unsigned int debug_mode);
+
+void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len);
+uint32_t register_get_val32(const nt_register_t *p);
+uint32_t register_get_val_updated32(const nt_register_t *p);
+
+void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len);
+void register_set_val_flush(nt_register_t *p, const uint32_t *p_data,
+ uint32_t len);
+
+void register_make_dirty(nt_register_t *p);
+void register_update(const nt_register_t *p);
+void register_reset(const nt_register_t *p);
+void register_flush(const nt_register_t *p, uint32_t cnt);
+void register_clr(nt_register_t *p);
+void register_set(nt_register_t *p);
+
+void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1,
+ uint64_t *tsc2);
+
+void register_dump(const nt_register_t *p);
+void register_dump_fields(const nt_register_t *p);
+
+nt_field_t *field_new(void);
+void field_delete(nt_field_t *p);
+void field_init(nt_field_t *p, nt_register_t *p_reg,
+ const nt_fpga_field_init_t *p_init);
+
+int field_get_debug_mode(const nt_module_t *p);
+void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode);
+int field_get_bit_width(const nt_field_t *p);
+int field_get_bit_pos_low(const nt_field_t *p);
+int field_get_bit_pos_high(const nt_field_t *p);
+uint32_t field_get_mask(const nt_field_t *p);
+void field_reset(const nt_field_t *p);
+uint32_t field_get_reset_val(const nt_field_t *p);
+void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len);
+void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len);
+void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data,
+ uint32_t len);
+uint32_t field_get_val_mask(const nt_field_t *p);
+uint32_t field_get_val32(const nt_field_t *p);
+uint32_t field_get_updated(const nt_field_t *p);
+void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2);
+void field_update_register(const nt_field_t *p);
+void field_flush_register(const nt_field_t *p);
+void field_set_val32(const nt_field_t *p, uint32_t val);
+void field_set_val_flush32(const nt_field_t *p, uint32_t val);
+void field_clr_all(const nt_field_t *p);
+void field_clr_flush(const nt_field_t *p);
+void field_set_all(const nt_field_t *p);
+void field_set_flush(const nt_field_t *p);
+
+int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+
+int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations,
+ int n_poll_interval);
+
+int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value,
+ uint32_t n_wait_cond_mask, int n_poll_iterations,
+ int n_poll_interval);
+
+void field_dump(const nt_field_t *p);
+void field_dump_val(const nt_field_t *p);
+void field_dump_init(const nt_fpga_field_init_t *p);
+
+/*
+ * nthw helpers
+ */
+nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident);
+nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance);
+nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg);
+nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld);
+
+#endif /* __NTHW_FPGA_MODEL_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_helper.h b/drivers/net/ntnic/nthw/nthw_helper.h
new file mode 100644
index 0000000000..22f6a0d471
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_helper.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_HELPER_H__
+#define __NTHW_HELPER_H__
+
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+#endif /* __NTHW_HELPER_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_platform.c b/drivers/net/ntnic/nthw/nthw_platform.c
new file mode 100644
index 0000000000..203947e03a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_platform.c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_platform_drv.h"
+
+nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id)
+{
+ switch (n_pci_device_id) {
+ case NT_HW_PCI_DEVICE_ID_NT40E3:
+ return NT_HW_ADAPTER_ID_NT40E3;
+ case NT_HW_PCI_DEVICE_ID_NT100E3:
+ return NT_HW_ADAPTER_ID_NT100E3;
+ case NT_HW_PCI_DEVICE_ID_NT80E3:
+ return NT_HW_ADAPTER_ID_NT80E3;
+ case NT_HW_PCI_DEVICE_ID_NT40A00:
+ return NT_HW_ADAPTER_ID_NT40E3;
+ case NT_HW_PCI_DEVICE_ID_NT40A01:
+ return NT_HW_ADAPTER_ID_NT40E3;
+ case NT_HW_PCI_DEVICE_ID_NT200E3:
+ return NT_HW_ADAPTER_ID_NT200E3;
+ case NT_HW_PCI_DEVICE_ID_NT200A01:
+ return NT_HW_ADAPTER_ID_NT200A01;
+ case NT_HW_PCI_DEVICE_ID_NT200D01:
+ return NT_HW_ADAPTER_ID_NT200D01;
+ case NT_HW_PCI_DEVICE_ID_NT200A02:
+ return NT_HW_ADAPTER_ID_NT200A02;
+ case NT_HW_PCI_DEVICE_ID_NT50B01:
+ return NT_HW_ADAPTER_ID_NT50B01;
+ case NT_HW_PCI_DEVICE_ID_NT100A01:
+ return NT_HW_ADAPTER_ID_NT100A01;
+ default:
+ return NT_HW_ADAPTER_ID_UNKNOWN;
+ }
+}
diff --git a/drivers/net/ntnic/nthw/nthw_platform_drv.h b/drivers/net/ntnic/nthw/nthw_platform_drv.h
new file mode 100644
index 0000000000..fee2dc4853
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_platform_drv.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PLATFORM_DRV_H__
+#define __NTHW_PLATFORM_DRV_H__
+
+#include "nthw_helper.h"
+
+#define NT_HW_PCI_VENDOR_ID (0x18f4)
+
+#define NT_HW_PCI_DEVICE_ID_NT40E3 (0x145)
+#define NT_HW_PCI_DEVICE_ID_NT100E3 (0x155)
+#define NT_HW_PCI_DEVICE_ID_NT80E3 (0x165)
+#define NT_HW_PCI_DEVICE_ID_NT40A00 (0x175)
+#define NT_HW_PCI_DEVICE_ID_NT40A01 (0x185)
+#define NT_HW_PCI_DEVICE_ID_NT200E3 (0x195)
+#define NT_HW_PCI_DEVICE_ID_NT200A01 (0x1A5)
+#define NT_HW_PCI_DEVICE_ID_NT200D01 (0x1B5)
+#define NT_HW_PCI_DEVICE_ID_NT200A02 (0x1C5)
+#define NT_HW_PCI_DEVICE_ID_NT50B01 (0x1D5)
+#define NT_HW_PCI_DEVICE_ID_NT100A01 (0x1E5)
+
+enum nthw_adapter_id_e {
+ NT_HW_ADAPTER_ID_UNKNOWN = 0,
+ NT_HW_ADAPTER_ID_NT40E3,
+ NT_HW_ADAPTER_ID_NT40A01 = NT_HW_ADAPTER_ID_NT40E3,
+ NT_HW_ADAPTER_ID_NT50B01,
+ NT_HW_ADAPTER_ID_NT80E3,
+ NT_HW_ADAPTER_ID_NT100E3,
+ NT_HW_ADAPTER_ID_NT100A01,
+ NT_HW_ADAPTER_ID_NT200E3,
+ NT_HW_ADAPTER_ID_NT200A01,
+ NT_HW_ADAPTER_ID_NT200D01,
+ NT_HW_ADAPTER_ID_NT200A02,
+};
+
+typedef enum nthw_adapter_id_e nthw_adapter_id_t;
+
+nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id);
+
+#endif /* __NTHW_PLATFORM_DRV_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_profile.h b/drivers/net/ntnic/nthw/nthw_profile.h
new file mode 100644
index 0000000000..2fcb7b4adf
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_profile.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PROFILE_H__
+#define __NTHW_PROFILE_H__
+
+enum fpga_info_profile {
+ FPGA_INFO_PROFILE_UNKNOWN = 0,
+ FPGA_INFO_PROFILE_VSWITCH = 1,
+ FPGA_INFO_PROFILE_INLINE = 2,
+ FPGA_INFO_PROFILE_CAPTURE = 3,
+};
+
+#endif /* __NTHW_PROFILE_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_rac.c b/drivers/net/ntnic/nthw/nthw_rac.c
new file mode 100644
index 0000000000..fc50b1a50b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_rac.c
@@ -0,0 +1,976 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_rac.h"
+
+#include <pthread.h>
+
+/*
+ * Prevent that RAB echo debug trace ever gets into a release build
+ */
+#if defined(DEBUG)
+#undef RAB_DEBUG_ECHO
+#else
+#undef RAB_DEBUG_ECHO
+#endif /* DEBUG */
+
+#define RAB_DMA_WAIT (1000000)
+#define RAB_DMA_BUF_CNT (0x4000)
+
+#define RAB_READ (0x01)
+#define RAB_WRITE (0x02)
+#define RAB_ECHO (0x08)
+#define RAB_COMPLETION (0x0F)
+
+#define RAB_READ_ECHO (RAB_READ | RAB_ECHO)
+#define RAB_WRITE_ECHO (RAB_WRITE | RAB_ECHO)
+
+#define RAB_OPR_LO (28)
+#define RAB_OPR_HI (31)
+#define RAB_OPR_BW (4)
+
+#define RAB_CNT_LO (20)
+#define RAB_CNT_HI (27)
+#define RAB_CNT_BW (8)
+
+#define RAB_BUSID_LO (16)
+#define RAB_BUSID_HI (19)
+#define RAB_BUSID_BW (4)
+
+#define RAB_ADDR_LO (0)
+#define RAB_ADDR_HI (15)
+#define RAB_ADDR_BW (16)
+
+nthw_rac_t *nthw_rac_new(void)
+{
+ nthw_rac_t *p = malloc(sizeof(nthw_rac_t));
+
+ memset(p, 0, sizeof(nthw_rac_t));
+ return p;
+}
+
+void nthw_rac_delete(nthw_rac_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_rac_t));
+ free(p);
+ }
+}
+
+int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info)
+{
+ assert(p_fpga_info);
+
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_RAC, 0);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RAC %d: no such instance\n",
+ p_adapter_id_str, 0);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mp_mod_rac = mod;
+
+ {
+ /*
+ * RAC is a primary communication channel
+ * turn off debug by default
+ * except for rac_rab_init
+ */
+ const int n_debug_mode = module_get_debug_mode(p->mp_mod_rac);
+
+ if (n_debug_mode && n_debug_mode <= 0xff) {
+ module_set_debug_mode(p->mp_mod_rac, 0);
+ register_set_debug_mode(p->mp_reg_rab_init, n_debug_mode);
+ }
+ }
+
+ /* Params */
+ p->mn_param_rac_rab_interfaces =
+ fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_INTERFACES, 3);
+ NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d\n", p_adapter_id_str,
+ p->mn_param_rac_rab_interfaces);
+
+ p->mn_param_rac_rab_ob_update =
+ fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_OB_UPDATE, 0);
+ NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_OB_UPDATE=%d\n", p_adapter_id_str,
+ p->mn_param_rac_rab_ob_update);
+
+ /* Optional dummy test registers */
+ p->mp_reg_dummy0 = module_query_register(p->mp_mod_rac, RAC_DUMMY0);
+ p->mp_reg_dummy1 = module_query_register(p->mp_mod_rac, RAC_DUMMY1);
+ p->mp_reg_dummy2 = module_query_register(p->mp_mod_rac, RAC_DUMMY2);
+
+ p->mp_reg_rab_init = module_get_register(p->mp_mod_rac, RAC_RAB_INIT);
+ p->mp_fld_rab_init = register_get_field(p->mp_reg_rab_init, RAC_RAB_INIT_RAB);
+ p->mn_fld_rab_init_bw = field_get_bit_width(p->mp_fld_rab_init);
+ p->mn_fld_rab_init_mask = field_get_mask(p->mp_fld_rab_init);
+
+ /* RAC_RAB_INIT_RAB reg/field sanity checks: */
+ assert(p->mn_fld_rab_init_mask == ((1UL << p->mn_fld_rab_init_bw) - 1));
+ assert(p->mn_fld_rab_init_bw == p->mn_param_rac_rab_interfaces);
+
+ p->mp_reg_dbg_ctrl = module_query_register(p->mp_mod_rac, RAC_DBG_CTRL);
+ if (p->mp_reg_dbg_ctrl) {
+ p->mp_fld_dbg_ctrl =
+ register_query_field(p->mp_reg_dbg_ctrl, RAC_DBG_CTRL_C);
+ } else {
+ p->mp_fld_dbg_ctrl = NULL;
+ }
+ p->mp_reg_dbg_data = module_query_register(p->mp_mod_rac, RAC_DBG_DATA);
+ if (p->mp_reg_dbg_data) {
+ p->mp_fld_dbg_data =
+ register_query_field(p->mp_reg_dbg_data, RAC_DBG_DATA_D);
+ } else {
+ p->mp_reg_dbg_data = NULL;
+ }
+ p->mp_reg_rab_ib_data = module_get_register(p->mp_mod_rac, RAC_RAB_IB_DATA);
+ p->mp_fld_rab_ib_data =
+ register_get_field(p->mp_reg_rab_ib_data, RAC_RAB_IB_DATA_D);
+
+ p->mp_reg_rab_ob_data = module_get_register(p->mp_mod_rac, RAC_RAB_OB_DATA);
+ p->mp_fld_rab_ob_data =
+ register_get_field(p->mp_reg_rab_ob_data, RAC_RAB_OB_DATA_D);
+
+ p->mp_reg_rab_buf_free = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_FREE);
+ p->mp_fld_rab_buf_free_ib_free =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_FREE);
+ p->mp_fld_rab_buf_free_ib_ovf =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_OVF);
+ p->mp_fld_rab_buf_free_ob_free =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_FREE);
+ p->mp_fld_rab_buf_free_ob_ovf =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_OVF);
+ p->mp_fld_rab_buf_free_timeout =
+ register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_TIMEOUT);
+
+ p->mp_reg_rab_buf_used = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_USED);
+ p->mp_fld_rab_buf_used_ib_used =
+ register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_IB_USED);
+ p->mp_fld_rab_buf_used_ob_used =
+ register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_OB_USED);
+ p->mp_fld_rab_buf_used_flush =
+ register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_FLUSH);
+
+ /*
+ * RAC_RAB_DMA regs are optional - only found in real NT4GA - not found in 9231/9232 and
+ * earlier
+ */
+ p->mp_reg_rab_dma_ib_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_LO);
+ p->mp_fld_rab_dma_ib_lo_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ib_lo, RAC_RAB_DMA_IB_LO_PHYADDR);
+
+ p->mp_reg_rab_dma_ib_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_HI);
+ p->mp_fld_rab_dma_ib_hi_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ib_hi, RAC_RAB_DMA_IB_HI_PHYADDR);
+
+ p->mp_reg_rab_dma_ob_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_LO);
+ p->mp_fld_rab_dma_ob_lo_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ob_lo, RAC_RAB_DMA_OB_LO_PHYADDR);
+
+ p->mp_reg_rab_dma_ob_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_HI);
+ p->mp_fld_rab_dma_ob_hi_phy_addr =
+ register_get_field(p->mp_reg_rab_dma_ob_hi, RAC_RAB_DMA_OB_HI_PHYADDR);
+
+ p->mp_reg_rab_dma_ib_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_WR);
+ p->mp_fld_rab_dma_ib_wr_ptr =
+ register_get_field(p->mp_reg_rab_dma_ib_wr, RAC_RAB_DMA_IB_WR_PTR);
+
+ p->mp_reg_rab_dma_ib_rd = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_RD);
+ p->mp_fld_rab_dma_ib_rd_ptr =
+ register_get_field(p->mp_reg_rab_dma_ib_rd, RAC_RAB_DMA_IB_RD_PTR);
+
+ p->mp_reg_rab_dma_ob_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_WR);
+ p->mp_fld_rab_dma_ob_wr_ptr =
+ register_get_field(p->mp_reg_rab_dma_ob_wr, RAC_RAB_DMA_OB_WR_PTR);
+
+ p->rac_rab_init_addr = register_get_address(p->mp_reg_rab_init);
+ p->rac_rab_ib_data_addr = register_get_address(p->mp_reg_rab_ib_data);
+ p->rac_rab_ob_data_addr = register_get_address(p->mp_reg_rab_ob_data);
+ p->rac_rab_buf_free_addr = register_get_address(p->mp_reg_rab_buf_free);
+ p->rac_rab_buf_used_addr = register_get_address(p->mp_reg_rab_buf_used);
+
+ /*
+ * RAC_RAB_DMA regs are optional - only found in real NT4GA -
+ * not found in 9231/9232 and earlier
+ */
+
+ p->rac_rab_dma_ib_lo_addr = register_get_address(p->mp_reg_rab_dma_ib_lo);
+ p->rac_rab_dma_ib_hi_addr = register_get_address(p->mp_reg_rab_dma_ib_hi);
+ p->rac_rab_dma_ob_lo_addr = register_get_address(p->mp_reg_rab_dma_ob_lo);
+ p->rac_rab_dma_ob_hi_addr = register_get_address(p->mp_reg_rab_dma_ob_hi);
+ p->rac_rab_dma_ib_rd_addr = register_get_address(p->mp_reg_rab_dma_ib_rd);
+ p->rac_rab_dma_ob_wr_addr = register_get_address(p->mp_reg_rab_dma_ob_wr);
+ p->rac_rab_dma_ib_wr_addr = register_get_address(p->mp_reg_rab_dma_ib_wr);
+
+ p->rac_rab_buf_free_ib_free_mask =
+ field_get_mask(p->mp_fld_rab_buf_free_ib_free);
+ p->rac_rab_buf_free_ob_free_mask =
+ field_get_mask(p->mp_fld_rab_buf_free_ob_free);
+ p->rac_rab_buf_used_ib_used_mask =
+ field_get_mask(p->mp_fld_rab_buf_used_ib_used);
+ p->rac_rab_buf_used_ob_used_mask =
+ field_get_mask(p->mp_fld_rab_buf_used_ob_used);
+
+ p->rac_rab_buf_used_flush_mask = field_get_mask(p->mp_fld_rab_buf_used_flush);
+
+ p->rac_rab_buf_used_ob_used_low =
+ field_get_bit_pos_low(p->mp_fld_rab_buf_used_ob_used);
+
+ p->mp_reg_rab_nmb_rd = module_query_register(p->mp_mod_rac, RAC_NMB_RD_ADR);
+ if (p->mp_reg_rab_nmb_rd)
+ p->rac_nmb_rd_adr_addr = register_get_address(p->mp_reg_rab_nmb_rd);
+
+ p->mp_reg_rab_nmb_data = module_query_register(p->mp_mod_rac, RAC_NMB_DATA);
+ if (p->mp_reg_rab_nmb_data)
+ p->rac_nmb_data_addr = register_get_address(p->mp_reg_rab_nmb_data);
+
+ p->mp_reg_rab_nmb_wr = module_query_register(p->mp_mod_rac, RAC_NMB_WR_ADR);
+ if (p->mp_reg_rab_nmb_wr)
+ p->rac_nmb_wr_adr_addr = register_get_address(p->mp_reg_rab_nmb_wr);
+
+ p->mp_reg_rab_nmb_status =
+ module_query_register(p->mp_mod_rac, RAC_NMB_STATUS);
+ if (p->mp_reg_rab_nmb_status) {
+ p->rac_nmb_status_addr =
+ register_get_address(p->mp_reg_rab_nmb_status);
+ }
+
+ p->m_dma = NULL;
+
+ pthread_mutex_init(&p->m_mutex, NULL);
+
+ return 0;
+}
+
+int nthw_rac_get_rab_interface_count(const nthw_rac_t *p)
+{
+ return p->mn_param_rac_rab_interfaces;
+}
+
+static inline int nthw_rac_wait_for_rab_done(const nthw_rac_t *p, uint32_t address,
+ uint32_t word_cnt)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ uint32_t used = 0;
+ uint32_t retry;
+
+ for (retry = 0; retry < 100000; retry++) {
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &used);
+ used = (used & p->rac_rab_buf_used_ob_used_mask) >>
+ p->rac_rab_buf_used_ob_used_low;
+ if (used >= word_cnt)
+ break;
+ }
+
+ if (used < word_cnt) {
+ NT_LOG(ERR, NTHW,
+ "%s: Fail rab bus r/w addr=0x%08X used=%x wordcount=%d\n",
+ p_adapter_id_str, address, used, word_cnt);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * NT_PCI_REG_P9xyz_RAC_RAB_INIT
+ *
+ * Initializes (resets) the programmable registers on the Register Access Busses (RAB).
+ * This initialization must be performed by software as part of the driver load procedure.
+ *
+ * Bit n of this field initializes the programmable registers on RAB interface n.
+ * Software must write one to the bit and then clear the bit again.
+ *
+ * All RAB module registers will be reset to their defaults.
+ * This includes the product specific RESET module (eg RST9xyz)
+ * As a consequence of this behavior the official reset sequence
+ * must be excersised - as all RAB modules will be held in reset.
+ */
+int nthw_rac_rab_init(nthw_rac_t *p, uint32_t n_rab_intf_mask)
+{
+ /*
+ * Write rac_rab_init
+ * Perform operation twice - first to get trace of operation -
+ * second to get things done...
+ */
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ field_set_val_flush32(p->mp_fld_rab_init, n_rab_intf_mask);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_init_addr, n_rab_intf_mask);
+ return 0;
+}
+
+int nthw_rac_rab_reset(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ const char *const p_adapter_id_str _unused = p_fpga_info->mp_adapter_id_str;
+
+ /* RAC RAB bus "flip/flip" reset */
+ const int n_rac_rab_bus_count = nthw_rac_get_rab_interface_count(p);
+ const int n_rac_rab_bus_mask = (1 << n_rac_rab_bus_count) - 1;
+
+ NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d (0x%02X)\n",
+ p_adapter_id_str, n_rac_rab_bus_count, n_rac_rab_bus_mask);
+ assert(n_rac_rab_bus_count);
+ assert(n_rac_rab_bus_mask);
+
+ /* RAC RAB bus "flip/flip" reset first stage - new impl (ref RMT#37020) */
+ nthw_rac_rab_init(p, 0);
+ nthw_rac_rab_init(p, n_rac_rab_bus_mask);
+ nthw_rac_rab_init(p, n_rac_rab_bus_mask & ~0x01);
+
+ return 0;
+}
+
+int nthw_rac_rab_setup(nthw_rac_t *p)
+{
+ int rc = 0;
+
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ uint32_t n_dma_buf_size = 2L * RAB_DMA_BUF_CNT * sizeof(uint32_t);
+ const size_t align_size = ALIGN_SIZE(n_dma_buf_size);
+ int numa_node = p_fpga_info->numa_node;
+ uint64_t dma_addr;
+ uint32_t buf;
+
+ if (!p->m_dma) {
+ struct nt_dma_s *vfio_dma;
+ /* FPGA needs Page alignment (4K) */
+ vfio_dma = nt_dma_alloc(align_size, 0x1000, numa_node);
+
+ if (vfio_dma == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: nt_dma_alloc failed\n",
+ __func__);
+ return -1;
+ }
+ p->m_dma_in_buf = (uint32_t *)vfio_dma->addr;
+ p->m_dma_out_buf = p->m_dma_in_buf + RAB_DMA_BUF_CNT;
+ p->m_dma = vfio_dma;
+ }
+
+ /* Setup DMA on the adapter */
+ dma_addr = p->m_dma->iova;
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_lo_addr,
+ dma_addr & 0xffffffff);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_hi_addr,
+ (uint32_t)(dma_addr >> 32) & 0xffffffff);
+ dma_addr += RAB_DMA_BUF_CNT * sizeof(uint32_t);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_lo_addr,
+ dma_addr & 0xffffffff);
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_hi_addr,
+ (uint32_t)(dma_addr >> 32) & 0xffffffff);
+
+ /* Set initial value of internal pointers */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ib_rd_addr, &buf);
+ p->m_dma_in_ptr_wr = (uint16_t)(buf / sizeof(uint32_t));
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ob_wr_addr, &buf);
+ p->m_dma_out_ptr_rd = (uint16_t)(buf / sizeof(uint32_t));
+ p->m_in_free = RAB_DMA_BUF_CNT;
+
+ return rc;
+}
+
+int nthw_rac_rab_dma_begin(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ if (p->m_dma_active) {
+ pthread_mutex_unlock(&p->m_mutex);
+ NT_LOG(ERR, NTHW,
+ "%s: DMA begin requested, but a DMA transaction is already active\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ p->m_dma_active = true;
+
+ return 0;
+}
+
+static void nthw_rac_rab_dma_activate(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;
+
+ /* Write completion word */
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] = completion;
+ p->m_dma_in_ptr_wr =
+ (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
+
+ /* Clear output completion word */
+ p->m_dma_out_buf[p->m_dma_out_ptr_rd] = 0;
+
+ /* _update DMA pointer and start transfer */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_wr_addr,
+ (uint32_t)(p->m_dma_in_ptr_wr * sizeof(uint32_t)));
+}
+
+static int nthw_rac_rab_dma_wait(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;
+ uint32_t i;
+
+ for (i = 0; i < RAB_DMA_WAIT; i++) {
+ NT_OS_WAIT_USEC_POLL(1);
+ if ((p->m_dma_out_buf[p->m_dma_out_ptr_rd] & completion) ==
+ completion)
+ break;
+ }
+
+ if (i == RAB_DMA_WAIT) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Unexpected value of completion (0x%08X)\n",
+ p_fpga_info->mp_adapter_id_str,
+ p->m_dma_out_buf[p->m_dma_out_ptr_rd]);
+ return -1;
+ }
+
+ p->m_dma_out_ptr_rd =
+ (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));
+ p->m_in_free = RAB_DMA_BUF_CNT;
+
+ return 0;
+}
+
+int nthw_rac_rab_dma_commit(nthw_rac_t *p)
+{
+ int ret;
+
+ if (!p->m_dma_active) {
+ /* Expecting mutex not to be locked! */
+ assert(0); /* alert developer that something is wrong */
+ return -1;
+ }
+
+ nthw_rac_rab_dma_activate(p);
+ ret = nthw_rac_rab_dma_wait(p);
+
+ p->m_dma_active = false;
+
+ pthread_mutex_unlock(&p->m_mutex);
+
+ return ret;
+}
+
+void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t *p_data)
+{
+ *p_data = *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr +
+ reg_addr);
+}
+
+void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t p_data)
+{
+ *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr) =
+ p_data;
+}
+
+int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ if (word_cnt == 0 || word_cnt > 256) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed rab dma write length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\n",
+ p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt,
+ p->m_in_free);
+ assert(0); /* alert developer that something is wrong */
+ return -1;
+ }
+
+ if (p->m_in_free < (word_cnt + 3)) {
+ /*
+ * No more memory available.
+ * nthw_rac_rab_dma_commit() needs to be called to start and finish pending
+ * transfers.
+ */
+ return -1;
+ }
+
+ p->m_in_free -= (word_cnt + 1);
+
+ /* Write the command word */
+#if defined(RAB_DEBUG_ECHO)
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_WRITE_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt + 1) &
+ (RAB_DMA_BUF_CNT - 1));
+#else
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_WRITE << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif
+ p->m_dma_in_ptr_wr =
+ (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
+
+ for (uint32_t i = 0; i < word_cnt; i++) {
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] = p_data[i];
+ p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) &
+ (RAB_DMA_BUF_CNT - 1));
+ }
+
+ return 0;
+}
+
+int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, struct dma_buf_ptr *buf_ptr)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+
+ if (word_cnt == 0 || word_cnt > 256) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\n",
+ p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt,
+ p->m_in_free);
+ assert(0); /* alert developer that something is wrong */
+ return -1;
+ }
+
+ if ((word_cnt + 3) > RAB_DMA_BUF_CNT) {
+ NT_LOG(ERR, NTHW,
+ "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d: 0x%08X",
+ p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt);
+ return -1;
+ }
+
+ if (p->m_in_free < 3) {
+ /*
+ * No more memory available.
+ * nthw_rac_rab_dma_commit() needs to be called to start and finish pending
+ * transfers.
+ */
+ return -1;
+ }
+
+ p->m_in_free -= 1;
+
+ /* Write the command word */
+#if defined(RAB_DEBUG_ECHO)
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_READ_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ p->m_dma_out_ptr_rd =
+ (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));
+#else
+ p->m_dma_in_buf[p->m_dma_in_ptr_wr] =
+ (RAB_READ << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif
+ p->m_dma_in_ptr_wr =
+ (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
+
+ buf_ptr->index = p->m_dma_out_ptr_rd;
+ buf_ptr->size = RAB_DMA_BUF_CNT;
+ buf_ptr->base = p->m_dma_out_buf;
+ p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt) &
+ (RAB_DMA_BUF_CNT - 1U));
+
+ return 0;
+}
+
+int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = 0;
+ uint32_t rab_oper_wr;
+ uint32_t rab_oper_cmpl;
+ uint32_t rab_echo_oper_cmpl;
+ uint32_t word_cnt_expected;
+ uint32_t buf_used;
+ uint32_t buf_free;
+ uint32_t in_buf_free;
+ uint32_t out_buf_free;
+
+ if (address > (1 << RAB_ADDR_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal address: value too large %d - max %d\n",
+ p_adapter_id_str, address, (1 << RAB_ADDR_BW));
+ return -1;
+ }
+
+ if (bus_id > (1 << RAB_BUSID_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal bus id: value too large %d - max %d\n",
+ p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));
+ return -1;
+ }
+
+ if (word_cnt == 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value is zero (%d)\n",
+ p_adapter_id_str, word_cnt);
+ return -1;
+ }
+
+ if (word_cnt > (1 << RAB_CNT_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value too large %d - max %d\n",
+ p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));
+ return -1;
+ }
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ if (p->m_dma_active) {
+ NT_LOG(ERR, NTHW, "%s: RAB: Illegal operation: DMA enabled\n",
+ p_adapter_id_str);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free);
+
+ in_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask;
+ out_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16;
+
+ /* Read buffer used register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used);
+
+ buf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask |
+ p->rac_rab_buf_used_ob_used_mask);
+
+ /*
+ * Verify that output buffer can hold one completion word,
+ * input buffer can hold the number of words to be written +
+ * one write and one completion command
+ * and that the input and output "used" buffer is 0
+ */
+ if ((out_buf_free >= 1 && (in_buf_free >= word_cnt + 2)) && buf_used == 0) {
+ uint32_t i;
+
+ word_cnt_expected = 0;
+
+ /* Compose write command */
+#if defined(RAB_DEBUG_ECHO)
+ rab_oper_wr =
+ (RAB_WRITE_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ word_cnt_expected += word_cnt + 1;
+#else
+ rab_oper_wr =
+ (RAB_WRITE << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif /* RAB_DEBUG_ECHO */
+
+ /* Write command */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ rab_oper_wr);
+
+ /* Write da to input buffer */
+ for (i = 0; i < word_cnt; i++) {
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ *p_data);
+ p_data++;
+ }
+
+ /* Compose completion command */
+ rab_oper_cmpl = (RAB_COMPLETION << RAB_OPR_LO);
+ word_cnt_expected++;
+
+ /* Write command */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ rab_oper_cmpl);
+
+ /* Wait until done */
+ if (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+#if defined(RAB_DEBUG_ECHO)
+ {
+ uint32_t rab_echo_oper_wr;
+
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,
+ &rab_echo_oper_wr);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info,
+ p->rac_rab_ob_data_addr, 0);
+ }
+ if (rab_oper_wr != rab_echo_oper_wr) {
+ NT_LOG(ERR, NTHW,
+ "%s: expected rab read echo oper (0x%08X) - read (0x%08X)\n",
+ p_adapter_id_str, rab_oper_wr, rab_echo_oper_wr);
+ }
+ }
+
+ {
+ /* Read data from output buffer */
+ uint32_t data;
+
+ for (i = 0; i < word_cnt; i++) {
+ nthw_rac_reg_read32(p_fpga_info,
+ p->rac_rab_ob_data_addr,
+ &data);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info,
+ p->rac_rab_ob_data_addr, 0);
+ }
+ }
+ }
+#endif /* RAB_DEBUG_ECHO */
+
+ /* Read completion from out buffer */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,
+ &rab_echo_oper_cmpl);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr,
+ 0);
+ }
+ if (rab_echo_oper_cmpl != rab_oper_cmpl) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Unexpected value of completion (0x%08X)- inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, rab_echo_oper_cmpl, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr,
+ &buf_free);
+ if (buf_free & 0x80000000) {
+ /* Clear Timeout and overflow bits */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr,
+ 0x0);
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ res = 0;
+ goto exit_unlock_res;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, word_cnt, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+exit_unlock_res:
+ pthread_mutex_unlock(&p->m_mutex);
+ return res;
+}
+
+int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, uint32_t *p_data)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ int res = 0;
+ uint32_t rab_oper_rd;
+ uint32_t word_cnt_expected;
+ uint32_t buf_used;
+ uint32_t buf_free;
+ uint32_t in_buf_free;
+ uint32_t out_buf_free;
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ if (address > (1 << RAB_ADDR_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal address: value too large %d - max %d\n",
+ p_adapter_id_str, address, (1 << RAB_ADDR_BW));
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ if (bus_id > (1 << RAB_BUSID_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal bus id: value too large %d - max %d\n",
+ p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ if (word_cnt == 0) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value is zero (%d)\n",
+ p_adapter_id_str, word_cnt);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ if (word_cnt > (1 << RAB_CNT_BW)) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Illegal word count: value too large %d - max %d\n",
+ p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free);
+
+ in_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask;
+ out_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16;
+
+ /* Read buffer used register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used);
+
+ buf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask |
+ p->rac_rab_buf_used_ob_used_mask);
+
+ /*
+ * Verify that output buffer can hold the number of words to be read,
+ * input buffer can hold one read command
+ * and that the input and output "used" buffer is 0
+ */
+ if ((out_buf_free >= word_cnt && in_buf_free >= 1) && buf_used == 0) {
+ word_cnt_expected = word_cnt;
+
+#if defined(RAB_DEBUG_ECHO)
+ rab_oper_rd =
+ (RAB_READ_ECHO << RAB_OPR_LO) |
+ ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+ word_cnt_expected++;
+#else
+ rab_oper_rd = (RAB_READ << RAB_OPR_LO) | (word_cnt << RAB_CNT_LO) |
+ (bus_id << RAB_BUSID_LO) | address;
+#endif /* RAB_DEBUG_ECHO */
+
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,
+ rab_oper_rd);
+
+ /* Wait until done */
+ if (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+#if defined(RAB_DEBUG_ECHO)
+ uint32_t rab_echo_oper_rd;
+
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,
+ &rab_echo_oper_rd);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr,
+ 0);
+ }
+ if (rab_oper_rd != rab_echo_oper_rd) {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: expected rab read echo oper (0x%08X) - read (0x%08X)\n",
+ p_adapter_id_str, rab_oper_rd, rab_echo_oper_rd);
+ }
+#endif /* RAB_DEBUG_ECHO */
+
+ /* Read data from output buffer */
+ {
+ uint32_t i;
+
+ for (i = 0; i < word_cnt; i++) {
+ nthw_rac_reg_read32(p_fpga_info,
+ p->rac_rab_ob_data_addr,
+ p_data);
+ if (p->mn_param_rac_rab_ob_update) {
+ nthw_rac_reg_write32(p_fpga_info,
+ p->rac_rab_ob_data_addr,
+ 0);
+ }
+ p_data++;
+ }
+ }
+
+ /* Read buffer free register */
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr,
+ &buf_free);
+ if (buf_free & 0x80000000) {
+ /* Clear Timeout and overflow bits */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr,
+ 0x0);
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+ res = 0;
+ goto exit_unlock_res;
+ } else {
+ NT_LOG(ERR, NTHW,
+ "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\n",
+ p_adapter_id_str, bus_id, address, word_cnt, in_buf_free,
+ out_buf_free, buf_used);
+ res = -1;
+ goto exit_unlock_res;
+ }
+
+exit_unlock_res:
+ pthread_mutex_unlock(&p->m_mutex);
+ return res;
+}
+
+int nthw_rac_rab_flush(nthw_rac_t *p)
+{
+ const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
+ const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+ uint32_t data = 0;
+ uint32_t retry;
+ int res = 0;
+
+ pthread_mutex_lock(&p->m_mutex);
+
+ /* Set the flush bit */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr,
+ p->rac_rab_buf_used_flush_mask);
+
+ /* Reset BUF FREE register */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr, 0x0);
+
+ /* Wait until OB_USED and IB_USED are 0 */
+ for (retry = 0; retry < 100000; retry++) {
+ nthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &data);
+
+ if ((data & 0xFFFFFFFF) == p->rac_rab_buf_used_flush_mask)
+ break;
+ }
+
+ if (data != p->rac_rab_buf_used_flush_mask) {
+ NT_LOG(ERR, NTHW, "%s: RAB: Rab bus flush error.\n",
+ p_adapter_id_str);
+ res = -1;
+ }
+
+ /* Clear flush bit when done */
+ nthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr, 0x0);
+
+ pthread_mutex_unlock(&p->m_mutex);
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_rac.h b/drivers/net/ntnic/nthw/nthw_rac.h
new file mode 100644
index 0000000000..737598d95a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_rac.h
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_RAC_H__
+#define __NTHW_RAC_H__
+
+#include "nt_util.h"
+#include "nthw_bus.h"
+
+#include <pthread.h>
+
+struct nthw_rac {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_rac;
+
+ pthread_mutex_t m_mutex;
+
+ int mn_param_rac_rab_interfaces;
+ int mn_param_rac_rab_ob_update;
+
+ nt_register_t *mp_reg_dummy0;
+ nt_register_t *mp_reg_dummy1;
+ nt_register_t *mp_reg_dummy2;
+
+ nt_register_t *mp_reg_rab_init;
+ nt_field_t *mp_fld_rab_init;
+
+ int mn_fld_rab_init_bw;
+ uint32_t mn_fld_rab_init_mask;
+
+ nt_register_t *mp_reg_dbg_ctrl;
+ nt_field_t *mp_fld_dbg_ctrl;
+
+ nt_register_t *mp_reg_dbg_data;
+ nt_field_t *mp_fld_dbg_data;
+
+ nt_register_t *mp_reg_rab_ib_data;
+ nt_field_t *mp_fld_rab_ib_data;
+
+ nt_register_t *mp_reg_rab_ob_data;
+ nt_field_t *mp_fld_rab_ob_data;
+
+ nt_register_t *mp_reg_rab_buf_free;
+ nt_field_t *mp_fld_rab_buf_free_ib_free;
+ nt_field_t *mp_fld_rab_buf_free_ib_ovf;
+ nt_field_t *mp_fld_rab_buf_free_ob_free;
+ nt_field_t *mp_fld_rab_buf_free_ob_ovf;
+ nt_field_t *mp_fld_rab_buf_free_timeout;
+
+ nt_register_t *mp_reg_rab_buf_used;
+ nt_field_t *mp_fld_rab_buf_used_ib_used;
+ nt_field_t *mp_fld_rab_buf_used_ob_used;
+ nt_field_t *mp_fld_rab_buf_used_flush;
+
+ nt_register_t *mp_reg_rab_dma_ib_lo;
+ nt_field_t *mp_fld_rab_dma_ib_lo_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ib_hi;
+ nt_field_t *mp_fld_rab_dma_ib_hi_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ob_hi;
+ nt_field_t *mp_fld_rab_dma_ob_hi_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ob_lo;
+ nt_field_t *mp_fld_rab_dma_ob_lo_phy_addr;
+
+ nt_register_t *mp_reg_rab_dma_ib_wr;
+ nt_field_t *mp_fld_rab_dma_ib_wr_ptr;
+
+ nt_register_t *mp_reg_rab_dma_ib_rd;
+ nt_field_t *mp_fld_rab_dma_ib_rd_ptr;
+
+ nt_register_t *mp_reg_rab_dma_ob_wr;
+ nt_field_t *mp_fld_rab_dma_ob_wr_ptr;
+
+ nt_register_t *mp_reg_rab_nmb_rd;
+ nt_register_t *mp_reg_rab_nmb_data;
+ nt_register_t *mp_reg_rab_nmb_wr;
+ nt_register_t *mp_reg_rab_nmb_status;
+
+ uint32_t rac_rab_init_addr;
+ uint32_t rac_rab_ib_data_addr;
+ uint32_t rac_rab_ob_data_addr;
+ uint32_t rac_rab_buf_free_addr;
+ uint32_t rac_rab_buf_used_addr;
+
+ uint32_t rac_rab_dma_ib_lo_addr;
+ uint32_t rac_rab_dma_ib_hi_addr;
+ uint32_t rac_rab_dma_ob_lo_addr;
+ uint32_t rac_rab_dma_ob_hi_addr;
+ uint32_t rac_rab_dma_ib_rd_addr;
+ uint32_t rac_rab_dma_ob_wr_addr;
+ uint32_t rac_rab_dma_ib_wr_addr;
+
+ uint32_t rac_rab_buf_free_ib_free_mask;
+ uint32_t rac_rab_buf_free_ob_free_mask;
+ uint32_t rac_rab_buf_used_ib_used_mask;
+ uint32_t rac_rab_buf_used_ob_used_mask;
+ uint32_t rac_rab_buf_used_flush_mask;
+
+ uint32_t rac_rab_buf_used_ob_used_low;
+
+ uint32_t rac_nmb_rd_adr_addr;
+ uint32_t rac_nmb_data_addr;
+ uint32_t rac_nmb_wr_adr_addr;
+ uint32_t rac_nmb_status_addr;
+
+ bool m_dma_active;
+
+ struct nt_dma_s *m_dma;
+
+ volatile uint32_t *m_dma_in_buf;
+ volatile uint32_t *m_dma_out_buf;
+
+ uint16_t m_dma_out_ptr_rd;
+ uint16_t m_dma_in_ptr_wr;
+ uint32_t m_in_free;
+};
+
+typedef struct nthw_rac nthw_rac_t;
+typedef struct nthw_rac nthw_rac;
+
+struct dma_buf_ptr {
+ uint32_t size;
+ uint32_t index;
+ volatile uint32_t *base;
+};
+
+nthw_rac_t *nthw_rac_new(void);
+void nthw_rac_delete(nthw_rac_t *p);
+int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info);
+
+int nthw_rac_get_rab_interface_count(const nthw_rac_t *p);
+
+int nthw_rac_rab_init(nthw_rac_t *p, uint32_t rab_intf_mask);
+
+int nthw_rac_rab_setup(nthw_rac_t *p);
+
+int nthw_rac_rab_reset(nthw_rac_t *p);
+
+int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data);
+int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, const uint32_t *p_data);
+int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, uint32_t *p_data);
+int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,
+ uint32_t word_cnt, struct dma_buf_ptr *buf_ptr);
+
+int nthw_rac_rab_flush(nthw_rac_t *p);
+
+int nthw_rac_rab_dma_begin(nthw_rac_t *p);
+int nthw_rac_rab_dma_commit(nthw_rac_t *p);
+
+void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t *p_data);
+void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
+ uint32_t p_data);
+
+#endif /* __NTHW_RAC_H__ */
diff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h
index 5cdbd9fc5d..4fe3496b9f 100644
--- a/drivers/net/ntnic/nthw/nthw_register.h
+++ b/drivers/net/ntnic/nthw/nthw_register.h
@@ -10,6 +10,8 @@
#include <stdbool.h>
#include <inttypes.h>
+#include "nthw_fpga_model.h"
+
#include "fpga_model.h"
#include "nthw_fpga_modules_defs.h"
diff --git a/drivers/net/ntnic/nthw/nthw_stat.c b/drivers/net/ntnic/nthw/nthw_stat.c
new file mode 100644
index 0000000000..fbecbc2dba
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_stat.c
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_stat.h"
+
+#include <malloc.h>
+
+nthw_stat_t *nthw_stat_new(void)
+{
+ nthw_stat_t *p = malloc(sizeof(nthw_stat_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_stat_t));
+ return p;
+}
+
+void nthw_stat_delete(nthw_stat_t *p)
+{
+ if (p)
+ free(p);
+}
+
+int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ uint64_t n_module_version_packed64 = -1;
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_STA, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: STAT %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_stat = mod;
+
+ n_module_version_packed64 = module_get_version_packed64(p->mp_mod_stat);
+ NT_LOG(DBG, NTHW, "%s: STAT %d: version=0x%08lX\n", p_adapter_id_str,
+ p->mn_instance, n_module_version_packed64);
+
+ {
+ nt_register_t *p_reg;
+ /* STA_CFG register */
+ p_reg = module_get_register(p->mp_mod_stat, STA_CFG);
+ p->mp_fld_dma_ena = register_get_field(p_reg, STA_CFG_DMA_ENA);
+ p->mp_fld_cnt_clear = register_get_field(p_reg, STA_CFG_CNT_CLEAR);
+
+ /* CFG: fields NOT available from v. 3 */
+ p->mp_fld_tx_disable =
+ register_query_field(p_reg, STA_CFG_TX_DISABLE);
+ p->mp_fld_cnt_freeze = register_query_field(p_reg, STA_CFG_CNT_FRZ);
+
+ /* STA_STATUS register */
+ p_reg = module_get_register(p->mp_mod_stat, STA_STATUS);
+ p->mp_fld_stat_toggle_missed =
+ register_get_field(p_reg, STA_STATUS_STAT_TOGGLE_MISSED);
+
+ /* HOST_ADR registers */
+ p_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_LSB);
+ p->mp_fld_dma_lsb = register_get_field(p_reg, STA_HOST_ADR_LSB_LSB);
+
+ p_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_MSB);
+ p->mp_fld_dma_msb = register_get_field(p_reg, STA_HOST_ADR_MSB_MSB);
+ }
+
+ /* Params */
+ p->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH;
+
+ p->m_nb_nim_ports = fpga_get_product_param(p_fpga, NT_NIMS, 0);
+ p->m_nb_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0);
+
+ p->m_nb_rx_ports =
+ fpga_get_product_param(p_fpga, NT_STA_RX_PORTS, -1); /* VSWITCH */
+ if (p->m_nb_rx_ports == -1) {
+ p->m_nb_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS,
+ -1); /* non-VSWITCH */
+ if (p->m_nb_rx_ports == -1) {
+ p->m_nb_rx_ports = fpga_get_product_param(p_fpga,
+ NT_PORTS,
+ 0); /* non-VSWITCH */
+ }
+ }
+
+ p->m_nb_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, 0);
+ p->m_rx_port_replicate =
+ fpga_get_product_param(p_fpga, NT_RX_PORT_REPLICATE, 0);
+
+ p->m_nb_color_counters = fpga_get_product_param(p_fpga, NT_STA_COLORS, 64) *
+ 2; /* VSWITCH */
+ if (p->m_nb_color_counters == 0) {
+ p->m_nb_color_counters =
+ fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0) *
+ 2; /* non-VSWITCH */
+ }
+
+ p->m_nb_rx_host_buffers = fpga_get_product_param(p_fpga, NT_QUEUES, 0);
+ p->m_nb_tx_host_buffers = p->m_nb_rx_host_buffers;
+
+ p->m_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);
+
+ p->m_nb_rx_hb_counters =
+ (p->m_nb_rx_host_buffers *
+ (6 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?
+ p->m_dbs_present :
+ 0)));
+
+ p->m_nb_tx_hb_counters = 0;
+
+ p->m_nb_rx_port_counters =
+ 42 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?
+ p->m_dbs_present :
+ 0);
+ p->m_nb_tx_port_counters = 0;
+
+ p->m_nb_counters =
+ p->m_nb_color_counters + p->m_nb_rx_hb_counters + p->m_nb_tx_hb_counters;
+
+ p->mn_stat_layout_version = 0;
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 8)) {
+ p->mn_stat_layout_version = 6;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {
+ p->mn_stat_layout_version = 5;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 4)) {
+ p->mn_stat_layout_version = 4;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 3)) {
+ p->mn_stat_layout_version = 3;
+ } else if (n_module_version_packed64 >= VERSION_PACKED64(0, 2)) {
+ p->mn_stat_layout_version = 2;
+ } else if (n_module_version_packed64 > VERSION_PACKED64(0, 0)) {
+ p->mn_stat_layout_version = 1;
+ } else {
+ p->mn_stat_layout_version = 0;
+ NT_LOG(ERR, NTHW,
+ "%s: unknown module_version 0x%08lX layout=%d\n",
+ p_adapter_id_str, n_module_version_packed64,
+ p->mn_stat_layout_version);
+ }
+ assert(p->mn_stat_layout_version);
+
+ /* STA module 0.2+ adds IPF counters per port (Rx feature) */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 2))
+ p->m_nb_rx_port_counters += 6;
+
+ /* STA module 0.3+ adds TX stats */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 3) ||
+ p->m_nb_tx_ports >= 1)
+ p->mb_has_tx_stats = true;
+
+ /* STA module 0.3+ adds TX stat counters */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 3))
+ p->m_nb_tx_port_counters += 22;
+
+ /* STA module 0.4+ adds TX drop event counter */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 4))
+ p->m_nb_tx_port_counters += 1; /* TX drop event counter */
+
+ /*
+ * STA module 0.6+ adds pkt filter drop octets+pkts, retransmit and
+ * duplicate counters
+ */
+ if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {
+ p->m_nb_rx_port_counters += 4;
+ p->m_nb_tx_port_counters += 1;
+ }
+
+ if (p->mb_is_vswitch) {
+ p->m_nb_rx_port_counters = 5;
+ p->m_nb_tx_port_counters = 5;
+ }
+
+ p->m_nb_counters += (p->m_nb_rx_ports * p->m_nb_rx_port_counters);
+
+ if (p->mb_has_tx_stats)
+ p->m_nb_counters += (p->m_nb_tx_ports * p->m_nb_tx_port_counters);
+
+ /* Output params (debug) */
+ NT_LOG(DBG, NTHW,
+ "%s: nims=%d rxports=%d txports=%d rxrepl=%d colors=%d queues=%d\n",
+ p_adapter_id_str, p->m_nb_nim_ports, p->m_nb_rx_ports, p->m_nb_tx_ports,
+ p->m_rx_port_replicate, p->m_nb_color_counters, p->m_nb_rx_host_buffers);
+ NT_LOG(DBG, NTHW,
+ "%s: hbs=%d hbcounters=%d rxcounters=%d txcounters=%d\n",
+ p_adapter_id_str, p->m_nb_rx_host_buffers, p->m_nb_rx_hb_counters,
+ p->m_nb_rx_port_counters, p->m_nb_tx_port_counters);
+ NT_LOG(DBG, NTHW, "%s: layout=%d\n", p_adapter_id_str,
+ p->mn_stat_layout_version);
+ NT_LOG(DBG, NTHW, "%s: counters=%d (0x%X)\n", p_adapter_id_str,
+ p->m_nb_counters, p->m_nb_counters);
+ NT_LOG(DBG, NTHW, "%s: vswitch=%d\n", p_adapter_id_str, p->mb_is_vswitch);
+
+ /* Init */
+ if (p->mp_fld_tx_disable)
+ field_set_flush(p->mp_fld_tx_disable);
+
+ field_update_register(p->mp_fld_cnt_clear);
+ field_set_flush(p->mp_fld_cnt_clear);
+ field_clr_flush(p->mp_fld_cnt_clear);
+
+ field_update_register(p->mp_fld_stat_toggle_missed);
+ field_set_flush(p->mp_fld_stat_toggle_missed);
+
+ field_update_register(p->mp_fld_dma_ena);
+ field_clr_flush(p->mp_fld_dma_ena);
+ field_update_register(p->mp_fld_dma_ena);
+
+ return 0;
+}
+
+int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,
+ uint32_t *p_stat_dma_virtual)
+{
+ assert(p_stat_dma_virtual);
+ p->mp_timestamp = NULL;
+
+ p->m_stat_dma_physical = stat_dma_physical;
+ p->mp_stat_dma_virtual = p_stat_dma_virtual;
+
+ memset(p->mp_stat_dma_virtual, 0, (p->m_nb_counters * sizeof(uint32_t)));
+
+ field_set_val_flush32(p->mp_fld_dma_msb,
+ (uint32_t)((p->m_stat_dma_physical >> 32) &
+ 0xffffffff));
+ field_set_val_flush32(p->mp_fld_dma_lsb,
+ (uint32_t)(p->m_stat_dma_physical & 0xffffffff));
+
+ p->mp_timestamp = (uint64_t *)(p->mp_stat_dma_virtual + p->m_nb_counters);
+ NT_LOG(DBG, NTHW,
+ "%s: statDmaPhysical=%" PRIX64 " p_stat_dma_virtual=%" PRIX64
+ " mp_timestamp=%" PRIX64 "\n",
+ __func__, p->m_stat_dma_physical, p->mp_stat_dma_virtual,
+ p->mp_timestamp);
+ if (p->mb_is_vswitch)
+ *p->mp_timestamp = NT_OS_GET_TIME_NS();
+
+ else
+ *p->mp_timestamp = (uint64_t)(int64_t)-1;
+ return 0;
+}
+
+int nthw_stat_trigger(nthw_stat_t *p)
+{
+ int n_toggle_miss = field_get_updated(p->mp_fld_stat_toggle_missed);
+
+ if (n_toggle_miss)
+ field_set_flush(p->mp_fld_stat_toggle_missed);
+
+ if (p->mp_timestamp)
+ *p->mp_timestamp = -1; /* Clear old ts */
+
+ field_update_register(p->mp_fld_dma_ena);
+ field_set_flush(p->mp_fld_dma_ena);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_stat.h b/drivers/net/ntnic/nthw/nthw_stat.h
new file mode 100644
index 0000000000..7bce7ecd15
--- /dev/null
+++ b/drivers/net/ntnic/nthw/nthw_stat.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_STAT_H__
+#define __NTHW_STAT_H__
+
+struct nthw_stat {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_stat;
+ int mn_instance;
+
+ int mn_stat_layout_version;
+
+ bool mb_is_vswitch;
+ bool mb_has_tx_stats;
+
+ int m_nb_phy_ports;
+ int m_nb_nim_ports;
+
+ int m_nb_rx_ports;
+ int m_nb_tx_ports;
+
+ int m_nb_rx_host_buffers;
+ int m_nb_tx_host_buffers;
+
+ int m_dbs_present;
+
+ int m_rx_port_replicate;
+
+ int m_nb_color_counters;
+
+ int m_nb_rx_hb_counters;
+ int m_nb_tx_hb_counters;
+
+ int m_nb_rx_port_counters;
+ int m_nb_tx_port_counters;
+
+ int m_nb_counters;
+
+ nt_field_t *mp_fld_dma_ena;
+ nt_field_t *mp_fld_cnt_clear;
+
+ nt_field_t *mp_fld_tx_disable;
+
+ nt_field_t *mp_fld_cnt_freeze;
+
+ nt_field_t *mp_fld_stat_toggle_missed;
+
+ nt_field_t *mp_fld_dma_lsb;
+ nt_field_t *mp_fld_dma_msb;
+
+ uint64_t m_stat_dma_physical;
+ uint32_t *mp_stat_dma_virtual;
+
+ uint64_t last_ts;
+
+ uint64_t *mp_timestamp;
+};
+
+typedef struct nthw_stat nthw_stat_t;
+typedef struct nthw_stat nthw_stat;
+
+nthw_stat_t *nthw_stat_new(void);
+int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance);
+void nthw_stat_delete(nthw_stat_t *p);
+
+int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,
+ uint32_t *p_stat_dma_virtual);
+int nthw_stat_trigger(nthw_stat_t *p);
+
+#endif /* __NTHW_STAT_H__ */
diff --git a/drivers/net/ntnic/ntlog/include/ntlog.h b/drivers/net/ntnic/ntlog/include/ntlog.h
new file mode 100644
index 0000000000..81bc014d66
--- /dev/null
+++ b/drivers/net/ntnic/ntlog/include/ntlog.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTOSS_SYSTEM_NTLOG_H
+#define NTOSS_SYSTEM_NTLOG_H
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#ifndef NT_LOG_MODULE_PREFIX
+
+/* DPDK modules */
+#define NT_LOG_MODULE_EAL 0
+#define NT_LOG_MODULE_MALLOC 1
+#define NT_LOG_MODULE_RING 2
+#define NT_LOG_MODULE_MEMPOOL 3
+#define NT_LOG_MODULE_TIMER 4
+#define NT_LOG_MODULE_PMD 5
+#define NT_LOG_MODULE_HASH 6
+#define NT_LOG_MODULE_LPM 7
+#define NT_LOG_MODULE_KNI 8
+#define NT_LOG_MODULE_ACL 9
+#define NT_LOG_MODULE_POWER 10
+#define NT_LOG_MODULE_METER 11
+#define NT_LOG_MODULE_SCHED 12
+#define NT_LOG_MODULE_PORT 13
+#define NT_LOG_MODULE_TABLE 14
+#define NT_LOG_MODULE_PIPELINE 15
+#define NT_LOG_MODULE_MBUF 16
+#define NT_LOG_MODULE_CRYPTODEV 17
+#define NT_LOG_MODULE_EFD 18
+#define NT_LOG_MODULE_EVENTDEV 19
+#define NT_LOG_MODULE_GSO 20
+#define NT_LOG_MODULE_USER1 24
+#define NT_LOG_MODULE_USER2 25
+#define NT_LOG_MODULE_USER3 26
+#define NT_LOG_MODULE_USER4 27
+#define NT_LOG_MODULE_USER5 28
+#define NT_LOG_MODULE_USER6 29
+#define NT_LOG_MODULE_USER7 30
+#define NT_LOG_MODULE_USER8 31
+
+/* NT modules */
+#define NT_LOG_MODULE_GENERAL 10000 /* Should always be a first (smallest) */
+#define NT_LOG_MODULE_NTHW 10001
+#define NT_LOG_MODULE_FILTER 10002
+#define NT_LOG_MODULE_VDPA 10003
+#define NT_LOG_MODULE_FPGA 10004
+#define NT_LOG_MODULE_NTCONNECT 10005
+#define NT_LOG_MODULE_ETHDEV 10006
+#define NT_LOG_MODULE_END 10007 /* Mark for the range end of NT_LOG */
+
+#define NT_LOG_MODULE_COUNT (NT_LOG_MODULE_END - NT_LOG_MODULE_GENERAL)
+#define NT_LOG_MODULE_INDEX(module) ((module) - NT_LOG_MODULE_GENERAL)
+#define NT_LOG_MODULE_PREFIX(type) NT_LOG_MODULE_##type
+
+#endif
+
+#ifndef NT_LOG_ENABLE
+#define NT_LOG_ENABLE 1
+#endif
+
+#if defined NT_LOG_ENABLE && NT_LOG_ENABLE > 0
+#ifndef NT_LOG_ENABLE_ERR
+#define NT_LOG_ENABLE_ERR 1
+#endif
+#ifndef NT_LOG_ENABLE_WRN
+#define NT_LOG_ENABLE_WRN 1
+#endif
+#ifndef NT_LOG_ENABLE_INF
+#define NT_LOG_ENABLE_INF 1
+#endif
+#ifndef NT_LOG_ENABLE_DBG
+#define NT_LOG_ENABLE_DBG 1
+#endif
+#ifndef NT_LOG_ENABLE_DB1
+#define NT_LOG_ENABLE_DB1 0
+#endif
+#ifndef NT_LOG_ENABLE_DB2
+#define NT_LOG_ENABLE_DB2 0
+#endif
+#endif
+
+#if defined NT_LOG_ENABLE_ERR && NT_LOG_ENABLE_ERR > 0
+#define NT_LOG_NT_LOG_ERR(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_ERR(...)
+#endif
+
+#if defined NT_LOG_ENABLE_WRN && NT_LOG_ENABLE_WRN > 0
+#define NT_LOG_NT_LOG_WRN(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_WRN(...)
+#endif
+
+#if defined NT_LOG_ENABLE_INF && NT_LOG_ENABLE_INF > 0
+#define NT_LOG_NT_LOG_INF(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_INF(...)
+#endif
+
+#if defined NT_LOG_ENABLE_DBG && NT_LOG_ENABLE_DBG > 0
+#define NT_LOG_NT_LOG_DBG(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_DBG(...)
+#endif
+
+#if defined NT_LOG_ENABLE_DB1 && NT_LOG_ENABLE_DB1 > 0
+#define NT_LOG_NT_LOG_DB1(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_DB1(...)
+#endif
+
+#if defined NT_LOG_ENABLE_DB2 && NT_LOG_ENABLE_DB2 > 0
+#define NT_LOG_NT_LOG_DB2(...) nt_log(__VA_ARGS__)
+#else
+#define NT_LOG_NT_LOG_DB2(...)
+#endif
+
+#define NT_LOG(level, module, ...) \
+ NT_LOG_NT_LOG_##level(NT_LOG_##level, NT_LOG_MODULE_PREFIX(module), \
+ #module ": " #level ": " __VA_ARGS__)
+
+enum nt_log_level {
+ NT_LOG_ERR = 0x001,
+ NT_LOG_WRN = 0x002,
+ NT_LOG_INF = 0x004,
+ NT_LOG_DBG = 0x008,
+ NT_LOG_DB1 = 0x010,
+ NT_LOG_DB2 = 0x020,
+};
+
+struct nt_log_impl {
+ int (*init)(void);
+ int (*log)(enum nt_log_level level, uint32_t module, const char *format,
+ va_list args);
+ int (*is_debug)(uint32_t module);
+};
+
+int nt_log_init(struct nt_log_impl *impl);
+
+int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...);
+
+/* Returns 1 if RTE_DEBUG, 0 if lower log level, -1 if incorrect module */
+int nt_log_is_debug(uint32_t module);
+
+/*
+ * nt log helper functions
+ * to create a string for NT_LOG usage to output a one-liner log
+ * to use when one single function call to NT_LOG is not optimal - that is
+ * you do not know the number of parameters at programming time or it is variable
+ */
+char *ntlog_helper_str_alloc(const char *sinit);
+
+void ntlog_helper_str_reset(char *s, const char *sinit);
+
+void ntlog_helper_str_add(char *s, const char *format, ...);
+
+void ntlog_helper_str_free(char *s);
+
+#endif /* NTOSS_SYSTEM_NTLOG_H */
diff --git a/drivers/net/ntnic/ntlog/ntlog.c b/drivers/net/ntnic/ntlog/ntlog.c
new file mode 100644
index 0000000000..b9109754ac
--- /dev/null
+++ b/drivers/net/ntnic/ntlog/ntlog.c
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <rte_string_fns.h>
+
+#define NTLOG_HELPER_STR_SIZE_MAX (1024)
+
+static struct nt_log_impl *user_impl;
+
+int nt_log_init(struct nt_log_impl *impl)
+{
+ user_impl = impl;
+ return user_impl->init();
+}
+
+static char *last_trailing_eol(char *s)
+{
+ int i = strlen(s) - 1;
+ /* Skip spaces */
+ while (i > 0 && s[i] == ' ')
+ --i;
+ if (s[i] != '\n')
+ return NULL;
+ /*
+ * Find the last trailing EOL "hello_world\n\n\n"
+ * ^
+ */
+ while (i > 1 && s[i] == '\n' && s[i - 1] == '\n')
+ --i;
+ return &s[i];
+}
+
+/* Always terminates the NT_LOG statement with a !!!single!!! EOL. */
+int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...)
+{
+ int rv = -1;
+ va_list args;
+
+ if (user_impl == NULL)
+ return rv;
+
+ char *actual_format = ntlog_helper_str_alloc(format);
+ char *eol = last_trailing_eol(actual_format);
+
+ if (!eol) { /* If log line is not terminated with '\n' we add it. */
+ strncat(actual_format, "\n",
+ NTLOG_HELPER_STR_SIZE_MAX - strlen(actual_format));
+ } else { /* If multiple trailing EOLs, then keep just one of them. */
+ *(eol + 1) = '\0';
+ }
+
+ va_start(args, format);
+ rv = user_impl->log(level, module, actual_format, args);
+ va_end(args);
+
+ ntlog_helper_str_free(actual_format);
+ return rv;
+}
+
+int nt_log_is_debug(uint32_t module)
+{
+ return user_impl->is_debug(module);
+}
+
+char *ntlog_helper_str_alloc(const char *sinit)
+{
+ char *s = malloc(NTLOG_HELPER_STR_SIZE_MAX);
+
+ if (!s)
+ return NULL;
+ if (sinit)
+ rte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX);
+ else
+ s[0] = '\0';
+ return s;
+}
+
+void ntlog_helper_str_reset(char *s, const char *sinit)
+{
+ if (s) {
+ if (sinit)
+ rte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX);
+ else
+ s[0] = '\0';
+ }
+}
+
+void ntlog_helper_str_add(char *s, const char *format, ...)
+{
+ if (!s)
+ return;
+ va_list args;
+
+ va_start(args, format);
+ int len = strlen(s);
+
+ vsnprintf(&s[len], (NTLOG_HELPER_STR_SIZE_MAX - 1 - len), format, args);
+ va_end(args);
+}
+
+void ntlog_helper_str_free(char *s)
+{
+ free(s);
+}
diff --git a/drivers/net/ntnic/ntutil/include/nt_util.h b/drivers/net/ntnic/ntutil/include/nt_util.h
new file mode 100644
index 0000000000..3850ccd934
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/include/nt_util.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTOSS_SYSTEM_NT_UTIL_H
+#define NTOSS_SYSTEM_NT_UTIL_H
+
+#include <rte_cycles.h>
+#include <rte_string_fns.h>
+
+#define _unused __rte_unused
+
+#define PCIIDENT_TO_DOMAIN(pci_ident) \
+ ((uint16_t)(((unsigned int)(pci_ident) >> 16) & 0xFFFFU))
+#define PCIIDENT_TO_BUSNR(pci_ident) \
+ ((uint8_t)(((unsigned int)(pci_ident) >> 8) & 0xFFU))
+#define PCIIDENT_TO_DEVNR(pci_ident) \
+ ((uint8_t)(((unsigned int)(pci_ident) >> 3) & 0x1FU))
+#define PCIIDENT_TO_FUNCNR(pci_ident) \
+ ((uint8_t)(((unsigned int)(pci_ident) >> 0) & 0x7U))
+
+#define PCIIDENT_PRINT_STR "%04x:%02x:%02x.%x"
+#define BDF_TO_PCIIDENT(dom, bus, dev, fnc) \
+ (((dom) << 16) | ((bus) << 8) | ((dev) << 3) | (fnc))
+
+/* ALIGN: Align x to a boundary */
+#define ALIGN(x, a) \
+ ({ \
+ __typeof__(x) _a = (a); \
+ ((x) + (_a - 1)) & ~(_a - 1); \
+ })
+
+/* PALIGN: Align pointer p to a boundary */
+#define PALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a)))
+
+/* Allocation size matching minimum alignment of specified size */
+#define ALIGN_SIZE(_size_) (1 << rte_log2_u64(_size_))
+
+#define NT_OS_WAIT_USEC(x) \
+ rte_delay_us_sleep( \
+ x) /* uses usleep which schedules out the calling thread */
+/* spins in a waiting loop calling pause asm instruction uses RDTSC - precise wait */
+#define NT_OS_WAIT_USEC_POLL(x) \
+ rte_delay_us( \
+ x)
+
+#define NT_OS_GET_TIME_US() \
+ (rte_get_timer_cycles() / (rte_get_timer_hz() / 1000 / 1000))
+#define NT_OS_GET_TIME_NS() \
+ (rte_get_timer_cycles() * 10 / (rte_get_timer_hz() / 1000 / 1000 / 100))
+#define NT_OS_GET_TIME_MONOTONIC_COUNTER() (rte_get_timer_cycles())
+
+struct nt_dma_s {
+ uint64_t iova;
+ uint64_t addr;
+ uint64_t size;
+};
+
+struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa);
+void nt_dma_free(struct nt_dma_s *vfio_addr);
+
+struct nt_util_vfio_impl {
+ int (*vfio_dma_map)(int vf_num, void *virt_addr, uint64_t *iova_addr,
+ uint64_t size);
+ int (*vfio_dma_unmap)(int vf_num, void *virt_addr, uint64_t iova_addr,
+ uint64_t size);
+};
+
+void nt_util_vfio_init(struct nt_util_vfio_impl *impl);
+
+#endif /* NTOSS_SYSTEM_NT_UTIL_H */
diff --git a/drivers/net/ntnic/ntutil/nt_util.c b/drivers/net/ntnic/ntutil/nt_util.c
new file mode 100644
index 0000000000..8f5812bf8b
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/nt_util.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <rte_malloc.h>
+
+#include "ntlog.h"
+#include "nt_util.h"
+
+static struct nt_util_vfio_impl vfio_cb;
+
+void nt_util_vfio_init(struct nt_util_vfio_impl *impl)
+{
+ vfio_cb = *impl;
+}
+
+struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa)
+{
+ int res;
+ struct nt_dma_s *vfio_addr;
+
+ vfio_addr = rte_malloc(NULL, sizeof(struct nt_dma_s), 0);
+ if (!vfio_addr) {
+ NT_LOG(ERR, GENERAL, "VFIO rte_malloc failed\n");
+ return NULL;
+ }
+ void *addr = rte_malloc_socket(NULL, size, align, numa);
+
+ if (!addr) {
+ rte_free(vfio_addr);
+ NT_LOG(ERR, GENERAL, "VFIO rte_malloc_socket failed\n");
+ return NULL;
+ }
+ res = vfio_cb.vfio_dma_map(0, addr, &vfio_addr->iova,
+ ALIGN_SIZE(size));
+ if (res != 0) {
+ rte_free(addr);
+ rte_free(vfio_addr);
+ NT_LOG(ERR, GENERAL, "VFIO nt_dma_map failed\n");
+ return NULL;
+ }
+
+ vfio_addr->addr = (uint64_t)addr;
+ vfio_addr->size = ALIGN_SIZE(size);
+
+ NT_LOG(DBG, GENERAL,
+ "VFIO DMA alloc addr=%" PRIX64 ", iova=%" PRIX64
+ ", size=%u, align=0x%X\n",
+ vfio_addr->addr, vfio_addr->iova, vfio_addr->size, align);
+
+ return vfio_addr;
+}
+
+void nt_dma_free(struct nt_dma_s *vfio_addr)
+{
+ NT_LOG(DBG, GENERAL,
+ "VFIO DMA free addr=%" PRIX64 ", iova=%" PRIX64 ", size=%u\n",
+ vfio_addr->addr, vfio_addr->iova, vfio_addr->size);
+
+ int res = vfio_cb.vfio_dma_unmap(0, (void *)(vfio_addr->addr),
+ vfio_addr->iova, vfio_addr->size);
+ if (res != 0) {
+ NT_LOG(WRN, GENERAL,
+ "VFIO DMA free FAILED addr=%" PRIX64 ", iova=%" PRIX64
+ ", size=%u\n",
+ vfio_addr->addr, vfio_addr->iova, vfio_addr->size);
+ }
+ rte_free((void *)(vfio_addr->addr));
+ rte_free(vfio_addr);
+}
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH v2 3/8] net/ntnic: adds NT200A02 adapter support
2023-08-17 14:43 ` [PATCH v2 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 2/8] net/ntnic: adds core registers and fpga functionality Mykola Kostenok
@ 2023-08-17 14:43 ` Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 4/8] net/ntnic: adds flow related FPGA functionality Mykola Kostenok
` (5 subsequent siblings)
7 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-17 14:43 UTC (permalink / raw)
To: dev, mko-plv; +Cc: ckm
From: Christian Koue Muf <ckm@napatech.com>
The PMD is designed to support multiple different adapters, and this commit
adds support for NT200A02 2x100G. Sensor and NIM code is included.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
v2:
* Fixed WARNING:TYPO_SPELLING
---
.../net/ntnic/adapter/common_adapter_defs.h | 14 +
drivers/net/ntnic/adapter/nt4ga_adapter.c | 477 ++++
drivers/net/ntnic/adapter/nt4ga_adapter.h | 108 +
drivers/net/ntnic/adapter/nt4ga_filter.h | 15 +
drivers/net/ntnic/adapter/nt4ga_link.c | 178 ++
drivers/net/ntnic/adapter/nt4ga_link.h | 179 ++
drivers/net/ntnic/adapter/nt4ga_link_100g.c | 825 +++++++
drivers/net/ntnic/adapter/nt4ga_link_100g.h | 12 +
drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c | 598 +++++
drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h | 41 +
drivers/net/ntnic/adapter/nt4ga_stat.c | 705 ++++++
drivers/net/ntnic/adapter/nt4ga_stat.h | 202 ++
drivers/net/ntnic/meson.build | 24 +
drivers/net/ntnic/nim/i2c_nim.c | 1974 +++++++++++++++++
drivers/net/ntnic/nim/i2c_nim.h | 122 +
drivers/net/ntnic/nim/nim_defines.h | 146 ++
drivers/net/ntnic/nim/nt_link_speed.c | 105 +
drivers/net/ntnic/nim/nt_link_speed.h | 34 +
drivers/net/ntnic/nim/qsfp_registers.h | 57 +
drivers/net/ntnic/nim/qsfp_sensors.c | 174 ++
drivers/net/ntnic/nim/qsfp_sensors.h | 18 +
drivers/net/ntnic/nim/sfp_p_registers.h | 100 +
drivers/net/ntnic/nim/sfp_sensors.c | 288 +++
drivers/net/ntnic/nim/sfp_sensors.h | 18 +
.../net/ntnic/nthw/core/nthw_clock_profiles.c | 11 +-
drivers/net/ntnic/nthw/core/nthw_core.h | 2 +
drivers/net/ntnic/nthw/core/nthw_gmf.c | 290 +++
drivers/net/ntnic/nthw/core/nthw_gmf.h | 93 +
.../nthw/core/nthw_nt200a02_u23_si5340_v5.h | 344 +++
drivers/net/ntnic/nthw/core/nthw_rmc.c | 156 ++
drivers/net/ntnic/nthw/core/nthw_rmc.h | 57 +
.../ntnic/sensors/avr_sensors/avr_sensors.c | 104 +
.../ntnic/sensors/avr_sensors/avr_sensors.h | 22 +
.../sensors/board_sensors/board_sensors.c | 48 +
.../sensors/board_sensors/board_sensors.h | 18 +
.../net/ntnic/sensors/board_sensors/tempmon.c | 42 +
.../net/ntnic/sensors/board_sensors/tempmon.h | 16 +
.../ntnic/sensors/nim_sensors/nim_sensors.c | 54 +
.../ntnic/sensors/nim_sensors/nim_sensors.h | 19 +
drivers/net/ntnic/sensors/ntavr/avr_intf.h | 89 +
drivers/net/ntnic/sensors/ntavr/ntavr.c | 78 +
drivers/net/ntnic/sensors/ntavr/ntavr.h | 32 +
drivers/net/ntnic/sensors/sensor_types.h | 259 +++
drivers/net/ntnic/sensors/sensors.c | 273 +++
drivers/net/ntnic/sensors/sensors.h | 127 ++
drivers/net/ntnic/sensors/stream_info.h | 86 +
46 files changed, 8632 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/ntnic/adapter/common_adapter_defs.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_adapter.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_adapter.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_filter.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link_100g.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_link_100g.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h
create mode 100644 drivers/net/ntnic/adapter/nt4ga_stat.c
create mode 100644 drivers/net/ntnic/adapter/nt4ga_stat.h
create mode 100644 drivers/net/ntnic/nim/i2c_nim.c
create mode 100644 drivers/net/ntnic/nim/i2c_nim.h
create mode 100644 drivers/net/ntnic/nim/nim_defines.h
create mode 100644 drivers/net/ntnic/nim/nt_link_speed.c
create mode 100644 drivers/net/ntnic/nim/nt_link_speed.h
create mode 100644 drivers/net/ntnic/nim/qsfp_registers.h
create mode 100644 drivers/net/ntnic/nim/qsfp_sensors.c
create mode 100644 drivers/net/ntnic/nim/qsfp_sensors.h
create mode 100644 drivers/net/ntnic/nim/sfp_p_registers.h
create mode 100644 drivers/net/ntnic/nim/sfp_sensors.c
create mode 100644 drivers/net/ntnic/nim/sfp_sensors.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gmf.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_gmf.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h
create mode 100644 drivers/net/ntnic/nthw/core/nthw_rmc.c
create mode 100644 drivers/net/ntnic/nthw/core/nthw_rmc.h
create mode 100644 drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c
create mode 100644 drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h
create mode 100644 drivers/net/ntnic/sensors/board_sensors/board_sensors.c
create mode 100644 drivers/net/ntnic/sensors/board_sensors/board_sensors.h
create mode 100644 drivers/net/ntnic/sensors/board_sensors/tempmon.c
create mode 100644 drivers/net/ntnic/sensors/board_sensors/tempmon.h
create mode 100644 drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c
create mode 100644 drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h
create mode 100644 drivers/net/ntnic/sensors/ntavr/avr_intf.h
create mode 100644 drivers/net/ntnic/sensors/ntavr/ntavr.c
create mode 100644 drivers/net/ntnic/sensors/ntavr/ntavr.h
create mode 100644 drivers/net/ntnic/sensors/sensor_types.h
create mode 100644 drivers/net/ntnic/sensors/sensors.c
create mode 100644 drivers/net/ntnic/sensors/sensors.h
create mode 100644 drivers/net/ntnic/sensors/stream_info.h
diff --git a/drivers/net/ntnic/adapter/common_adapter_defs.h b/drivers/net/ntnic/adapter/common_adapter_defs.h
new file mode 100644
index 0000000000..79167806f1
--- /dev/null
+++ b/drivers/net/ntnic/adapter/common_adapter_defs.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _COMMON_ADAPTER_DEFS_H_
+#define _COMMON_ADAPTER_DEFS_H_
+
+/*
+ * Declarations shared by NT adapter types.
+ */
+#define NUM_ADAPTER_MAX (8)
+#define NUM_ADAPTER_PORTS_MAX (128)
+
+#endif /* _COMMON_ADAPTER_DEFS_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
new file mode 100644
index 0000000000..259aae2831
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -0,0 +1,477 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+#include "nt4ga_adapter.h"
+#include "nt4ga_pci_ta_tg.h"
+#include "nt4ga_link_100g.h"
+
+/* Sensors includes */
+#include "board_sensors.h"
+#include "avr_sensors.h"
+
+/*
+ * Global variables shared by NT adapter types
+ */
+pthread_t monitor_tasks[NUM_ADAPTER_MAX];
+volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
+
+/*
+ * Signal-handler to stop all monitor threads
+ */
+static void stop_monitor_tasks(int signum)
+{
+ const size_t n = ARRAY_SIZE(monitor_task_is_running);
+ size_t i;
+
+ /* Stop all monitor tasks */
+ for (i = 0; i < n; i++) {
+ const int is_running = monitor_task_is_running[i];
+
+ monitor_task_is_running[i] = 0;
+ if (signum == -1 && is_running != 0) {
+ void *ret_val = NULL;
+
+ pthread_join(monitor_tasks[i], &ret_val);
+ memset(&monitor_tasks[i], 0, sizeof(monitor_tasks[0]));
+ }
+ }
+}
+
+int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh)
+{
+ const char *const p_dev_name = p_adapter_info->p_dev_name;
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *p_fpga_info = &p_adapter_info->fpga_info;
+ hw_info_t *p_hw_info = &p_adapter_info->hw_info;
+ char a_pci_ident_str[32];
+
+ snprintf(a_pci_ident_str, sizeof(a_pci_ident_str), "" PCIIDENT_PRINT_STR "",
+ PCIIDENT_TO_DOMAIN(p_fpga_info->pciident),
+ PCIIDENT_TO_BUSNR(p_fpga_info->pciident),
+ PCIIDENT_TO_DEVNR(p_fpga_info->pciident),
+ PCIIDENT_TO_FUNCNR(p_fpga_info->pciident));
+
+ fprintf(pfh, "%s: DeviceName: %s\n", p_adapter_id_str,
+ (p_dev_name ? p_dev_name : "NA"));
+ fprintf(pfh, "%s: PCI Details:\n", p_adapter_id_str);
+ fprintf(pfh, "%s: %s: %08X: %04X:%04X %04X:%04X\n", p_adapter_id_str,
+ a_pci_ident_str, p_fpga_info->pciident, p_hw_info->pci_vendor_id,
+ p_hw_info->pci_device_id, p_hw_info->pci_sub_vendor_id,
+ p_hw_info->pci_sub_device_id);
+ fprintf(pfh, "%s: FPGA Details:\n", p_adapter_id_str);
+ fprintf(pfh, "%s: %03d-%04d-%02d-%02d [%016" PRIX64 "] (%08X)\n",
+ p_adapter_id_str, p_fpga_info->n_fpga_type_id, p_fpga_info->n_fpga_prod_id,
+ p_fpga_info->n_fpga_ver_id, p_fpga_info->n_fpga_rev_id,
+ p_fpga_info->n_fpga_ident, p_fpga_info->n_fpga_build_time);
+ fprintf(pfh, "%s: FpgaDebugMode=0x%x\n", p_adapter_id_str,
+ p_fpga_info->n_fpga_debug_mode);
+ fprintf(pfh,
+ "%s: Nims=%d PhyPorts=%d PhyQuads=%d RxPorts=%d TxPorts=%d\n",
+ p_adapter_id_str, p_fpga_info->n_nims, p_fpga_info->n_phy_ports,
+ p_fpga_info->n_phy_quads, p_fpga_info->n_rx_ports, p_fpga_info->n_tx_ports);
+ fprintf(pfh, "%s: Hw=0x%02X_rev%d: %s\n", p_adapter_id_str,
+ p_hw_info->hw_platform_id, p_fpga_info->nthw_hw_info.hw_id,
+ p_fpga_info->nthw_hw_info.hw_plat_id_str);
+
+ nt4ga_stat_dump(p_adapter_info, pfh);
+
+ return 0;
+}
+
+/*
+ * SPI for sensors initialization
+ */
+static nthw_spi_v3_t *new_sensors_s_spi(struct nt_fpga_s *p_fpga)
+{
+ nthw_spi_v3_t *sensors_s_spi = nthw_spi_v3_new();
+
+ if (sensors_s_spi == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI allocation error\n", __func__);
+ return NULL;
+ }
+
+ if (nthw_spi_v3_init(sensors_s_spi, p_fpga, 0)) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI initialization error\n", __func__);
+ nthw_spi_v3_delete(sensors_s_spi);
+ return NULL;
+ }
+
+ return sensors_s_spi;
+}
+
+/*
+ * SPI for sensors reading
+ */
+nthw_spis_t *new_sensors_t_spi(struct nt_fpga_s *p_fpga)
+{
+ nthw_spis_t *sensors_t_spi = nthw_spis_new();
+ /* init SPI for sensor initialization process */
+ if (sensors_t_spi == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI allocation error\n", __func__);
+ return NULL;
+ }
+
+ if (nthw_spis_init(sensors_t_spi, p_fpga, 0)) {
+ NT_LOG(ERR, ETHDEV, "%s: SPI initialization error\n", __func__);
+ nthw_spis_delete(sensors_t_spi);
+ return NULL;
+ }
+
+ return sensors_t_spi;
+}
+
+static void adapter_sensor_setup(hw_info_t *p_hw_info, struct adapter_info_s *adapter)
+{
+ struct nt_fpga_s *p_fpga = adapter->fpga_info.mp_fpga;
+ struct nt_sensor_group *sensors_list_ptr = NULL;
+ nthw_spi_v3_t *sensors_s_spi = new_sensors_s_spi(p_fpga);
+
+ adapter->adapter_sensors_cnt = 0;
+
+ /* FPGA */
+ adapter->adapter_sensors = fpga_temperature_sensor_init(p_hw_info->n_nthw_adapter_id,
+ NT_SENSOR_FPGA_TEMP, p_fpga);
+ sensors_list_ptr = adapter->adapter_sensors;
+ adapter->adapter_sensors_cnt++;
+
+ /* AVR */
+ if (sensors_s_spi) {
+ if (nt_avr_sensor_mon_ctrl(sensors_s_spi,
+ SENSOR_MON_CTRL_REM_ALL_SENSORS) != 0) {
+ /* stop sensor monitoring */
+ NT_LOG(ERR, ETHDEV,
+ "Failed to stop AVR sensors monitoring\n");
+ } else {
+ NT_LOG(DBG, ETHDEV, "AVR sensors init started\n");
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "FAN0",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_FAN,
+ NT_SENSOR_NT200E3_FAN_SPEED,
+ SENSOR_MON_FAN, 0,
+ SENSOR_MON_BIG_ENDIAN,
+ SENSOR_MON_UNSIGNED,
+ &fan, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "PSU0",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE,
+ NT_SENSOR_NT200E3_PSU0_TEMP,
+ SENSOR_MON_PSU_EXAR_7724_0, 0x15,
+ SENSOR_MON_LITTLE_ENDIAN,
+ SENSOR_MON_UNSIGNED,
+ &exar7724_tj, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "PSU1",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE,
+ NT_SENSOR_NT200A02_PSU1_TEMP,
+ SENSOR_MON_MP2886A, 0x8d,
+ SENSOR_MON_BIG_ENDIAN,
+ SENSOR_MON_UNSIGNED,
+ &mp2886a_tj, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ sensors_list_ptr->next = avr_sensor_init(sensors_s_spi,
+ p_hw_info->n_nthw_adapter_id,
+ "PCB",
+ NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE,
+ NT_SENSOR_NT200E3_PCB_TEMP,
+ SENSOR_MON_DS1775, 0,
+ SENSOR_MON_LITTLE_ENDIAN,
+ SENSOR_MON_SIGNED,
+ &ds1775_t, 0xFFFF);
+ sensors_list_ptr = sensors_list_ptr->next;
+ adapter->adapter_sensors_cnt++;
+
+ NT_LOG(DBG, ETHDEV, "AVR sensors init finished\n");
+
+ if (nt_avr_sensor_mon_ctrl(sensors_s_spi,
+ SENSOR_MON_CTRL_RUN) != 0) {
+ /* start sensor monitoring */
+ NT_LOG(ERR, ETHDEV,
+ "Failed to start AVR sensors monitoring\n");
+ } else {
+ NT_LOG(DBG, ETHDEV,
+ "AVR sensors monitoring starteed\n");
+ }
+ }
+
+ nthw_spi_v3_delete(sensors_s_spi);
+ }
+}
+
+int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info)
+{
+ char *const p_dev_name = malloc(24);
+ char *const p_adapter_id_str = malloc(24);
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ hw_info_t *p_hw_info = &p_adapter_info->hw_info;
+
+ /*
+ * IMPORTANT: Most variables cannot be determined before fpga model is instantiated
+ * (nthw_fpga_init())
+ */
+ int n_phy_ports = -1;
+ int n_nim_ports = -1;
+ int res = -1;
+ nt_fpga_t *p_fpga = NULL;
+
+ (void)n_nim_ports; /* currently UNUSED - prevent warning */
+
+ p_hw_info->n_nthw_adapter_id =
+ nthw_platform_get_nthw_adapter_id(p_hw_info->pci_device_id);
+
+ fpga_info->n_nthw_adapter_id = p_hw_info->n_nthw_adapter_id;
+ p_hw_info->hw_product_type = p_hw_info->pci_device_id &
+ 0x000f; /* ref: DN-0060 section 9 */
+ /* ref: DN-0060 section 9 */
+ p_hw_info->hw_platform_id = (p_hw_info->pci_device_id >> 4) & 0x00ff;
+ /* ref: DN-0060 section 9 */
+ p_hw_info->hw_reserved1 = (p_hw_info->pci_device_id >> 12) & 0x000f;
+
+ /* mp_dev_name */
+ p_adapter_info->p_dev_name = p_dev_name;
+ if (p_dev_name) {
+ snprintf(p_dev_name, 24, "" PCIIDENT_PRINT_STR "",
+ PCIIDENT_TO_DOMAIN(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_BUSNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_DEVNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_FUNCNR(p_adapter_info->fpga_info.pciident));
+ NT_LOG(DBG, ETHDEV, "%s: (0x%08X)\n", p_dev_name,
+ p_adapter_info->fpga_info.pciident);
+ }
+
+ /* mp_adapter_id_str */
+ p_adapter_info->mp_adapter_id_str = p_adapter_id_str;
+
+ p_adapter_info->fpga_info.mp_adapter_id_str = p_adapter_id_str;
+
+ if (p_adapter_id_str) {
+ snprintf(p_adapter_id_str, 24, "PCI:" PCIIDENT_PRINT_STR "",
+ PCIIDENT_TO_DOMAIN(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_BUSNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_DEVNR(p_adapter_info->fpga_info.pciident),
+ PCIIDENT_TO_FUNCNR(p_adapter_info->fpga_info.pciident));
+ NT_LOG(DBG, ETHDEV, "%s: %s\n", p_adapter_id_str, p_dev_name);
+ }
+
+ {
+ int i;
+
+ for (i = 0; i < (int)ARRAY_SIZE(p_adapter_info->mp_port_id_str);
+ i++) {
+ char *p = malloc(32);
+
+ if (p) {
+ snprintf(p, 32, "%s:intf_%d",
+ (p_adapter_id_str ? p_adapter_id_str : "NA"),
+ i);
+ NT_LOG(DBG, ETHDEV, "%s\n", p);
+ }
+ p_adapter_info->mp_port_id_str[i] = p;
+ }
+ }
+
+ res = nthw_fpga_init(&p_adapter_info->fpga_info);
+ if (res) {
+ NT_LOG(ERR, ETHDEV, "%s: %s: FPGA=%04d res=x%08X [%s:%u]\n",
+ p_adapter_id_str, p_dev_name, fpga_info->n_fpga_prod_id, res,
+ __func__, __LINE__);
+ return res;
+ }
+
+ assert(fpga_info);
+ p_fpga = fpga_info->mp_fpga;
+ assert(p_fpga);
+ n_phy_ports = fpga_info->n_phy_ports;
+ assert(n_phy_ports >= 1);
+ n_nim_ports = fpga_info->n_nims;
+ assert(n_nim_ports >= 1);
+
+ /*
+ * HIF/PCI TA/TG
+ */
+ {
+ res = nt4ga_pci_ta_tg_init(p_adapter_info);
+ if (res == 0) {
+ nt4ga_pci_ta_tg_measure_throughput_main(p_adapter_info,
+ 0, 0,
+ TG_PKT_SIZE,
+ TG_NUM_PACKETS,
+ TG_DELAY);
+ } else {
+ NT_LOG(WRN, ETHDEV,
+ "%s: PCI TA/TG is not available - skipping\n",
+ p_adapter_id_str);
+ }
+ }
+
+ adapter_sensor_setup(p_hw_info, p_adapter_info);
+
+ {
+ int i;
+
+ assert(fpga_info->n_fpga_prod_id > 0);
+ for (i = 0; i < NUM_ADAPTER_PORTS_MAX; i++) {
+ /* Disable all ports. Must be enabled later */
+ p_adapter_info->nt4ga_link.port_action[i].port_disable =
+ true;
+ }
+ switch (fpga_info->n_fpga_prod_id) {
+ /* NT200A02: 2x100G */
+ case 9563: /* NT200A02 */
+ res = nt4ga_link_100g_ports_init(p_adapter_info, p_fpga);
+ break;
+ default:
+ NT_LOG(ERR, ETHDEV,
+ "%s: Unsupported FPGA product: %04d\n", __func__,
+ fpga_info->n_fpga_prod_id);
+ res = -1;
+ break;
+ }
+
+ if (res) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: %s: %s: %u: FPGA=%04d res=x%08X\n",
+ p_adapter_id_str, p_dev_name, __func__, __LINE__,
+ fpga_info->n_fpga_prod_id, res);
+ return res;
+ }
+ }
+
+ /*
+ * HostBuffer Systems
+ */
+ p_adapter_info->n_rx_host_buffers = 0;
+ p_adapter_info->n_tx_host_buffers = 0;
+
+ p_adapter_info->fpga_info.mp_nthw_epp = NULL;
+ if (nthw_epp_present(p_adapter_info->fpga_info.mp_fpga, 0)) {
+ p_adapter_info->fpga_info.mp_nthw_epp = nthw_epp_new();
+ if (p_adapter_info->fpga_info.mp_nthw_epp == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot create EPP\n",
+ p_adapter_id_str);
+ return -1;
+ }
+
+ res = nthw_epp_init(p_adapter_info->fpga_info.mp_nthw_epp,
+ p_adapter_info->fpga_info.mp_fpga, 0);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot initialize EPP\n",
+ p_adapter_id_str);
+ return res;
+ }
+ NT_LOG(DBG, ETHDEV, "%s: Initialized EPP\n",
+ p_adapter_id_str);
+
+ res = nthw_epp_setup(p_adapter_info->fpga_info.mp_nthw_epp);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot setup EPP\n",
+ p_adapter_id_str);
+ return res;
+ }
+ }
+
+ /* Nt4ga Stat init/setup */
+ res = nt4ga_stat_init(p_adapter_info);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot initialize the statistics module\n",
+ p_adapter_id_str);
+ return res;
+ }
+ res = nt4ga_stat_setup(p_adapter_info);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot setup the statistics module\n",
+ p_adapter_id_str);
+ return res;
+ }
+
+ return 0;
+}
+
+int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info)
+{
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ int i;
+ int res;
+ struct nt_sensor_group *cur_adapter_sensor = NULL;
+ struct nt_sensor_group *next_adapter_sensor = NULL;
+ struct nim_sensor_group *cur_nim_sensor = NULL;
+ struct nim_sensor_group *next_nim_sensor = NULL;
+
+ stop_monitor_tasks(-1);
+
+ nt4ga_stat_stop(p_adapter_info);
+
+ nthw_fpga_shutdown(&p_adapter_info->fpga_info);
+
+ /* Rac rab reset flip flop */
+ res = nthw_rac_rab_reset(fpga_info->mp_nthw_rac);
+
+ /* Free adapter port ident strings */
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ if (p_adapter_info->mp_port_id_str[i]) {
+ free(p_adapter_info->mp_port_id_str[i]);
+ p_adapter_info->mp_port_id_str[i] = NULL;
+ }
+ }
+
+ /* Free adapter ident string */
+ if (p_adapter_info->mp_adapter_id_str) {
+ free(p_adapter_info->mp_adapter_id_str);
+ p_adapter_info->mp_adapter_id_str = NULL;
+ }
+
+ /* Free devname ident string */
+ if (p_adapter_info->p_dev_name) {
+ free(p_adapter_info->p_dev_name);
+ p_adapter_info->p_dev_name = NULL;
+ }
+
+ /* Free adapter sensors */
+ if (p_adapter_info->adapter_sensors != NULL) {
+ do {
+ cur_adapter_sensor = p_adapter_info->adapter_sensors;
+ next_adapter_sensor =
+ p_adapter_info->adapter_sensors->next;
+ p_adapter_info->adapter_sensors = next_adapter_sensor;
+
+ sensor_deinit(cur_adapter_sensor);
+ } while (next_adapter_sensor != NULL);
+ }
+
+ /* Free NIM sensors */
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ if (p_adapter_info->nim_sensors[i] != NULL) {
+ do {
+ cur_nim_sensor = p_adapter_info->nim_sensors[i];
+ next_nim_sensor =
+ p_adapter_info->nim_sensors[i]->next;
+ p_adapter_info->nim_sensors[i] = next_nim_sensor;
+ free(cur_nim_sensor->sensor);
+ free(cur_nim_sensor);
+ } while (next_nim_sensor != NULL);
+ }
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.h b/drivers/net/ntnic/adapter/nt4ga_adapter.h
new file mode 100644
index 0000000000..6ae78a3743
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NT4GA_ADAPTER_H_
+#define _NT4GA_ADAPTER_H_
+
+#include "common_adapter_defs.h"
+
+struct adapter_info_s;
+
+/*
+ * DN-0060 section 9
+ */
+typedef struct hw_info_s {
+ /* pciids */
+ uint16_t pci_vendor_id;
+ uint16_t pci_device_id;
+ uint16_t pci_sub_vendor_id;
+ uint16_t pci_sub_device_id;
+ uint16_t pci_class_id;
+
+ /* Derived from pciid */
+ nthw_adapter_id_t n_nthw_adapter_id;
+ int hw_platform_id;
+ int hw_product_type;
+ int hw_reserved1;
+} hw_info_t;
+
+/*
+ * Services provided by the adapter module
+ */
+#include "nt4ga_pci_ta_tg.h"
+#include "nt4ga_filter.h"
+#include "nt4ga_stat.h"
+#include "nt4ga_link.h"
+
+#include "sensors.h"
+#include "i2c_nim.h"
+#include "sensor_types.h"
+
+typedef struct adapter_info_s {
+ struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg;
+ struct nt4ga_stat_s nt4ga_stat;
+ struct nt4ga_filter_s nt4ga_filter;
+ struct nt4ga_link_s nt4ga_link;
+
+ struct hw_info_s hw_info;
+ struct fpga_info_s fpga_info;
+
+ uint16_t adapter_sensors_cnt;
+ uint16_t nim_sensors_cnt[NUM_ADAPTER_PORTS_MAX];
+ struct nt_sensor_group *adapter_sensors;
+ struct nim_sensor_group *nim_sensors[NUM_ADAPTER_PORTS_MAX];
+
+ char *mp_port_id_str[NUM_ADAPTER_PORTS_MAX];
+ char *mp_adapter_id_str;
+ char *p_dev_name;
+ volatile bool *pb_shutdown;
+
+ int adapter_no;
+ int n_rx_host_buffers;
+ int n_tx_host_buffers;
+} adapter_info_t;
+
+/*
+ * Monitor task operations. This structure defines the management hooks for
+ * Napatech network devices. The following hooks can be defined; unless noted
+ * otherwise, they are optional and can be filled with a null pointer.
+ *
+ * int (*mto_open)(int adapter, int port);
+ * The function to call when a network device transitions to the up state,
+ * e.g., `ip link set <interface> up`.
+ *
+ * int (*mto_stop)(int adapter, int port);
+ * The function to call when a network device transitions to the down state,
+ * e.g., `ip link set <interface> down`.
+ */
+struct monitor_task_ops {
+ int (*mto_open)(int adapter, int port);
+ int (*mto_stop)(int adapter, int port);
+};
+
+#include <pthread.h>
+#include <signal.h>
+
+/* The file nt4ga_adapter.c defines the next four variables. */
+extern pthread_t monitor_tasks[NUM_ADAPTER_MAX];
+extern volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
+
+/*
+ * Function that sets up signal handler(s) that stop the monitoring tasks.
+ */
+int set_up_signal_handlers_to_stop_monitoring_tasks(void);
+
+int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info);
+int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info);
+
+int nt4ga_adapter_status(struct adapter_info_s *p_adapter_info);
+int nt4ga_adapter_transmit_packet(struct adapter_info_s *p_adapter_info,
+ int n_intf_no, uint8_t *p_pkt, int n_pkt_len);
+
+int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh);
+
+/* SPI for sensors reading */
+nthw_spis_t *new_sensors_t_spi(struct nt_fpga_s *p_fpga);
+
+#endif /* _NT4GA_ADAPTER_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_filter.h b/drivers/net/ntnic/adapter/nt4ga_filter.h
new file mode 100644
index 0000000000..ad7e7d8c71
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_filter.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_FILTER_H_
+#define NT4GA_FILTER_H_
+
+typedef struct nt4ga_filter_s {
+ int n_intf_cnt;
+ int n_queues_per_intf_cnt;
+
+ struct flow_nic_dev *mp_flow_device;
+} nt4ga_filter_t;
+
+#endif /* NT4GA_FILTER_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_link.c b/drivers/net/ntnic/adapter/nt4ga_link.c
new file mode 100644
index 0000000000..7fbdb72897
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link.c
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nt4ga_adapter.h"
+
+#include "nt4ga_link.h"
+#include "nt_util.h"
+
+/*
+ * port: speed capabilitoes
+ * This is actually an adapter capability mapped onto every port
+ */
+uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p _unused,
+ int port _unused)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ const uint32_t nt_link_speed_capa = p_link->speed_capa;
+ return nt_link_speed_capa;
+}
+
+/*
+ * port: nim present
+ */
+bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ const bool nim_present = p_link->link_state[port].nim_present;
+ return nim_present;
+}
+
+/*
+ * port: link mode
+ */
+void nt4ga_port_set_adm_state(struct adapter_info_s *p, int port, bool adm_state)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_disable = !adm_state;
+}
+
+bool nt4ga_port_get_adm_state(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ const bool adm_state = !p_link->port_action[port].port_disable;
+ return adm_state;
+}
+
+/*
+ * port: link status
+ */
+void nt4ga_port_set_link_status(struct adapter_info_s *p, int port,
+ bool link_status)
+{
+ /* Setting link state/status is (currently) the same as controlling the port adm state */
+ nt4ga_port_set_adm_state(p, port, link_status);
+}
+
+bool nt4ga_port_get_link_status(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ bool status = p_link->link_state[port].link_up;
+ return status;
+}
+
+/*
+ * port: link speed
+ */
+void nt4ga_port_set_link_speed(struct adapter_info_s *p, int port,
+ nt_link_speed_t speed)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_speed = speed;
+ p_link->link_info[port].link_speed = speed;
+}
+
+nt_link_speed_t nt4ga_port_get_link_speed(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ nt_link_speed_t speed = p_link->link_info[port].link_speed;
+ return speed;
+}
+
+/*
+ * port: link autoneg
+ * Currently not fully supported by link code
+ */
+void nt4ga_port_set_link_autoneg(struct adapter_info_s *p _unused,
+ int port _unused, bool autoneg _unused)
+{
+ nt4ga_link_t *const p_link _unused = &p->nt4ga_link;
+}
+
+bool nt4ga_port_get_link_autoneg(struct adapter_info_s *p _unused,
+ int port _unused)
+{
+ nt4ga_link_t *const p_link _unused = &p->nt4ga_link;
+ return true;
+}
+
+/*
+ * port: link duplex
+ * Currently not fully supported by link code
+ */
+void nt4ga_port_set_link_duplex(struct adapter_info_s *p, int port,
+ nt_link_duplex_t duplex)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_duplex = duplex;
+}
+
+nt_link_duplex_t nt4ga_port_get_link_duplex(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ nt_link_duplex_t duplex = p_link->link_info[port].link_duplex;
+ return duplex;
+}
+
+/*
+ * port: loopback mode
+ */
+void nt4ga_port_set_loopback_mode(struct adapter_info_s *p, int port,
+ uint32_t mode)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ p_link->port_action[port].port_lpbk_mode = mode;
+}
+
+uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+
+ return p_link->port_action[port].port_lpbk_mode;
+}
+
+/*
+ * port: nim capabilities
+ */
+nim_i2c_ctx_t nt4ga_port_get_nim_capabilities(struct adapter_info_s *p, int port)
+{
+ nt4ga_link_t *const p_link = &p->nt4ga_link;
+ nim_i2c_ctx_t nim_ctx = p_link->u.var100g.nim_ctx[port];
+ return nim_ctx;
+}
+
+/*
+ * port: tx power
+ */
+int nt4ga_port_tx_power(struct adapter_info_s *p, int port, bool disable)
+{
+ nt4ga_link_t *link_info = &p->nt4ga_link;
+
+ if (link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28_SR4 ||
+ link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28 ||
+ link_info->u.nim_ctx[port].port_type == NT_PORT_TYPE_QSFP28_LR4) {
+ nim_i2c_ctx_t *nim_ctx = &link_info->u.var100g.nim_ctx[port];
+
+ if (!nim_ctx->specific_u.qsfp.rx_only) {
+ if (nim_qsfp_plus_nim_set_tx_laser_disable(nim_ctx, disable,
+ -1) != 0)
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_link.h b/drivers/net/ntnic/adapter/nt4ga_link.h
new file mode 100644
index 0000000000..2be9f49075
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_LINK_H_
+#define NT4GA_LINK_H_
+
+#include "common_adapter_defs.h"
+#include "nthw_drv.h"
+#include "i2c_nim.h"
+#include "nthw_fpga_rst_nt200a0x.h"
+
+/*
+ * Link state.\n
+ * Just after start of ntservice the link state might be unknown since the
+ * monitoring routine is busy reading NIM state and NIM data. This might also
+ * be the case after a NIM is plugged into an interface.
+ * The error state indicates a HW reading error.
+ */
+enum nt_link_state_e {
+ NT_LINK_STATE_UNKNOWN = 0, /* The link state has not been read yet */
+ NT_LINK_STATE_DOWN = 1, /* The link state is DOWN */
+ NT_LINK_STATE_UP = 2, /* The link state is UP */
+ NT_LINK_STATE_ERROR = 3 /* The link state could not be read */
+};
+
+typedef enum nt_link_state_e nt_link_state_t, *nt_link_state_p;
+
+/*
+ * Link duplex mode
+ */
+enum nt_link_duplex_e {
+ NT_LINK_DUPLEX_UNKNOWN = 0,
+ NT_LINK_DUPLEX_HALF = 0x01, /* Half duplex */
+ NT_LINK_DUPLEX_FULL = 0x02, /* Full duplex */
+};
+
+typedef enum nt_link_duplex_e nt_link_duplex_t;
+
+/*
+ * Link loopback mode
+ */
+enum nt_link_loopback_e {
+ NT_LINK_LOOPBACK_OFF = 0,
+ NT_LINK_LOOPBACK_HOST = 0x01, /* Host loopback mode */
+ NT_LINK_LOOPBACK_LINE = 0x02, /* Line loopback mode */
+};
+
+/*
+ * Link MDI mode
+ */
+enum nt_link_mdi_e {
+ NT_LINK_MDI_NA = 0,
+ NT_LINK_MDI_AUTO = 0x01, /* MDI auto */
+ NT_LINK_MDI_MDI = 0x02, /* MDI mode */
+ NT_LINK_MDI_MDIX = 0x04, /* MDIX mode */
+};
+
+typedef enum nt_link_mdi_e nt_link_mdi_t;
+
+/*
+ * Link Auto/Manual mode
+ */
+enum nt_link_auto_neg_e {
+ NT_LINK_AUTONEG_NA = 0,
+ NT_LINK_AUTONEG_MANUAL = 0x01,
+ NT_LINK_AUTONEG_OFF = NT_LINK_AUTONEG_MANUAL, /* Auto negotiation OFF */
+ NT_LINK_AUTONEG_AUTO = 0x02,
+ NT_LINK_AUTONEG_ON = NT_LINK_AUTONEG_AUTO, /* Auto negotiation ON */
+};
+
+typedef enum nt_link_auto_neg_e nt_link_auto_neg_t;
+
+/*
+ * Callback functions to setup mac, pcs and phy
+ */
+typedef struct link_state_s {
+ bool link_disabled;
+ bool nim_present;
+ bool lh_nim_absent;
+ bool link_up;
+ enum nt_link_state_e link_state;
+ enum nt_link_state_e link_state_latched;
+} link_state_t;
+
+typedef struct link_info_s {
+ enum nt_link_speed_e link_speed;
+ enum nt_link_duplex_e link_duplex;
+ enum nt_link_auto_neg_e link_auto_neg;
+} link_info_t;
+
+typedef struct port_action_s {
+ bool port_disable;
+ enum nt_link_speed_e port_speed;
+ enum nt_link_duplex_e port_duplex;
+ uint32_t port_lpbk_mode;
+} port_action_t;
+
+typedef struct adapter_100g_s {
+ nim_i2c_ctx_t
+ nim_ctx[NUM_ADAPTER_PORTS_MAX]; /* Should be the first field */
+ nthw_mac_pcs_t mac_pcs100g[NUM_ADAPTER_PORTS_MAX];
+ nthw_gpio_phy_t gpio_phy[NUM_ADAPTER_PORTS_MAX];
+} adapter_100g_t;
+
+typedef union adapter_var_s {
+ nim_i2c_ctx_t nim_ctx
+ [NUM_ADAPTER_PORTS_MAX]; /* First field in all the adaptors type */
+ adapter_100g_t var100g;
+} adapter_var_u;
+
+typedef struct nt4ga_link_s {
+ link_state_t link_state[NUM_ADAPTER_PORTS_MAX];
+ link_info_t link_info[NUM_ADAPTER_PORTS_MAX];
+ port_action_t port_action[NUM_ADAPTER_PORTS_MAX];
+ uint32_t speed_capa;
+ /* */
+ bool variables_initialized;
+ adapter_var_u u;
+} nt4ga_link_t;
+
+bool nt4ga_port_get_nim_present(struct adapter_info_s *p, int port);
+
+/*
+ * port:s link mode
+ */
+void nt4ga_port_set_adm_state(struct adapter_info_s *p, int port,
+ bool adm_state);
+bool nt4ga_port_get_adm_state(struct adapter_info_s *p, int port);
+
+/*
+ * port:s link status
+ */
+void nt4ga_port_set_link_status(struct adapter_info_s *p, int port, bool status);
+bool nt4ga_port_get_link_status(struct adapter_info_s *p, int port);
+
+/*
+ * port: link autoneg
+ */
+void nt4ga_port_set_link_autoneg(struct adapter_info_s *p, int port,
+ bool autoneg);
+bool nt4ga_port_get_link_autoneg(struct adapter_info_s *p, int port);
+
+/*
+ * port: link speed
+ */
+void nt4ga_port_set_link_speed(struct adapter_info_s *p, int port,
+ nt_link_speed_t speed);
+nt_link_speed_t nt4ga_port_get_link_speed(struct adapter_info_s *p, int port);
+
+/*
+ * port: link duplex
+ */
+void nt4ga_port_set_link_duplex(struct adapter_info_s *p, int port,
+ nt_link_duplex_t duplex);
+nt_link_duplex_t nt4ga_port_get_link_duplex(struct adapter_info_s *p, int port);
+
+/*
+ * port: loopback mode
+ */
+void nt4ga_port_set_loopback_mode(struct adapter_info_s *p, int port,
+ uint32_t mode);
+uint32_t nt4ga_port_get_loopback_mode(struct adapter_info_s *p, int port);
+
+uint32_t nt4ga_port_get_link_speed_capabilities(struct adapter_info_s *p,
+ int port);
+
+/*
+ * port: nim capabilities
+ */
+nim_i2c_ctx_t nt4ga_port_get_nim_capabilities(struct adapter_info_s *p,
+ int port);
+
+/*
+ * port: tx power
+ */
+int nt4ga_port_tx_power(struct adapter_info_s *p, int port, bool disable);
+
+#endif /* NT4GA_LINK_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_link_100g.c b/drivers/net/ntnic/adapter/nt4ga_link_100g.c
new file mode 100644
index 0000000000..8465b6a341
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link_100g.c
@@ -0,0 +1,825 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+#include "i2c_nim.h"
+#include "nt4ga_adapter.h"
+#include "nt4ga_link_100g.h"
+
+#include <string.h> /* memcmp, memset */
+
+/*
+ * Prototypes
+ */
+static int swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs,
+ int port, bool swap);
+static int reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs);
+
+/*
+ * Structs and types definitions
+ */
+enum link_up_state {
+ RESET, /* A valid signal is detected by NO local faults. */
+ EXPECT_NO_LF, /* After that we check NO latched local fault bit before */
+ /* de-asserting Remote fault indication. */
+ WAIT_STABLE_LINK, /* Now we expect the link is up. */
+ MONITOR_LINK /* After link-up we monitor link state. */
+};
+
+typedef struct _monitoring_state {
+ /* Fields below are set by monitoring thread */
+ enum link_up_state m_link_up_state;
+ enum nt_link_state_e link_state;
+ enum nt_link_state_e latch_link_state;
+ int m_time_out;
+} monitoring_state_t, *monitoring_state_p;
+
+/*
+ * Global variables
+ */
+
+/*
+ * External state, to be set by the network driver.
+ */
+
+/*
+ * Utility functions
+ */
+
+static void set_loopback(struct adapter_info_s *p_adapter_info,
+ nthw_mac_pcs_t *mac_pcs, int intf_no, uint32_t mode,
+ uint32_t last_mode)
+{
+ bool swap_polerity = true;
+
+ switch (mode) {
+ case 1:
+ NT_LOG(INF, ETHDEV, "%s: Applying host loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_fec(mac_pcs, true);
+ nthw_mac_pcs_set_host_loopback(mac_pcs, true);
+ swap_polerity = false;
+ break;
+ case 2:
+ NT_LOG(INF, ETHDEV, "%s: Applying line loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_line_loopback(mac_pcs, true);
+ break;
+ default:
+ switch (last_mode) {
+ case 1:
+ NT_LOG(INF, ETHDEV, "%s: Removing host loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_host_loopback(mac_pcs, false);
+ break;
+ case 2:
+ NT_LOG(INF, ETHDEV, "%s: Removing line loopback\n",
+ p_adapter_info->mp_port_id_str[intf_no]);
+ nthw_mac_pcs_set_line_loopback(mac_pcs, false);
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+ break;
+ }
+
+ if ((p_adapter_info->fpga_info.nthw_hw_info.hw_id == 2 &&
+ p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01) ||
+ p_adapter_info->hw_info.n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A02) {
+ (void)swap_tx_rx_polarity(p_adapter_info, mac_pcs, intf_no,
+ swap_polerity);
+ }
+
+ /* After changing the loopback the system must be properly reset */
+ reset_rx(p_adapter_info, mac_pcs);
+
+ NT_OS_WAIT_USEC(10000); /* 10ms - arbitrary choice */
+
+ if (!nthw_mac_pcs_is_rx_path_rst(mac_pcs)) {
+ nthw_mac_pcs_reset_bip_counters(mac_pcs);
+ if (!nthw_mac_pcs_get_fec_bypass(mac_pcs))
+ nthw_mac_pcs_reset_fec_counters(mac_pcs);
+ }
+}
+
+/*
+ * Function to retrieve the current state of a link (for one port)
+ */
+static int link_state_build(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs,
+ nthw_gpio_phy_t *gpio_phy, int port,
+ link_state_t *state, bool is_port_disabled)
+{
+ uint32_t abs;
+ uint32_t phy_link_state;
+ uint32_t lh_abs;
+ uint32_t ll_phy_link_state;
+ uint32_t link_down_cnt;
+ uint32_t nim_interr;
+ uint32_t lh_local_fault;
+ uint32_t lh_remote_fault;
+ uint32_t lh_internal_local_fault;
+ uint32_t lh_received_local_fault;
+
+ memset(state, 0, sizeof(*state));
+ state->link_disabled = is_port_disabled;
+ nthw_mac_pcs_get_link_summary(mac_pcs, &abs, &phy_link_state, &lh_abs,
+ &ll_phy_link_state, &link_down_cnt,
+ &nim_interr, &lh_local_fault,
+ &lh_remote_fault, &lh_internal_local_fault,
+ &lh_received_local_fault);
+
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ state->nim_present =
+ nthw_gpio_phy_is_module_present(gpio_phy, (uint8_t)port);
+ state->lh_nim_absent = !state->nim_present;
+ state->link_up = phy_link_state ? true : false;
+
+ {
+ static char lsbuf[NUM_ADAPTER_MAX][NUM_ADAPTER_PORTS_MAX][256];
+ char buf[255];
+ const int adapter_no = drv->adapter_no;
+
+ snprintf(buf, sizeof(buf),
+ "%s: Port = %d: abs = %u, phy_link_state = %u, lh_abs = %u, "
+ "ll_phy_link_state = %u, link_down_cnt = %u, nim_interr = %u, "
+ "lh_local_fault = %u, lh_remote_fault = %u, lh_internal_local_fault = %u, "
+ "lh_received_local_fault = %u",
+ drv->mp_adapter_id_str, mac_pcs->mn_instance, abs,
+ phy_link_state, lh_abs, ll_phy_link_state,
+ link_down_cnt, nim_interr, lh_local_fault,
+ lh_remote_fault, lh_internal_local_fault,
+ lh_received_local_fault);
+ if (strcmp(lsbuf[adapter_no][port], buf) != 0) {
+ rte_strscpy(lsbuf[adapter_no][port], buf,
+ sizeof(lsbuf[adapter_no][port]) - 1U);
+ lsbuf[adapter_no][port]
+ [sizeof(lsbuf[adapter_no][port]) - 1U] = '\0';
+ NT_LOG(DBG, ETHDEV, "%s\n", lsbuf[adapter_no][port]);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Check whether a NIM module is present
+ */
+static bool nim_is_present(nthw_gpio_phy_t *gpio_phy, uint8_t if_no)
+{
+ assert(if_no < NUM_ADAPTER_PORTS_MAX);
+
+ return nthw_gpio_phy_is_module_present(gpio_phy, if_no);
+}
+
+/*
+ * Enable RX
+ */
+static int enable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_rx_enable(mac_pcs, true);
+ return 0;
+}
+
+/*
+ * Enable TX
+ */
+static int enable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_tx_enable(mac_pcs, true);
+ nthw_mac_pcs_set_tx_sel_host(mac_pcs, true);
+ return 0;
+}
+
+/*
+ * Disable RX
+ */
+static int disable_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_rx_enable(mac_pcs, false);
+ return 0;
+}
+
+/*
+ * Disable TX
+ */
+static int disable_tx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv; /* unused */
+ nthw_mac_pcs_set_tx_enable(mac_pcs, false);
+ nthw_mac_pcs_set_tx_sel_host(mac_pcs, false);
+ return 0;
+}
+
+/*
+ * Reset RX
+ */
+static int reset_rx(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ (void)drv;
+
+ nthw_mac_pcs_rx_path_rst(mac_pcs, true);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+ nthw_mac_pcs_rx_path_rst(mac_pcs, false);
+ NT_OS_WAIT_USEC(10000); /* 10ms */
+
+ return 0;
+}
+
+/*
+ * Reset TX
+ */
+
+/*
+ * Swap tx/rx polarity
+ */
+static int swap_tx_rx_polarity(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs,
+ int port, bool swap)
+{
+ const bool tx_polarity_swap[2][4] = { { true, true, false, false },
+ { false, true, false, false }
+ };
+ const bool rx_polarity_swap[2][4] = { { false, true, true, true },
+ { false, true, true, false }
+ };
+ uint8_t lane;
+
+ (void)drv;
+ for (lane = 0U; lane < 4U; lane++) {
+ if (swap) {
+ nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane,
+ tx_polarity_swap[port][lane]);
+ nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane,
+ rx_polarity_swap[port][lane]);
+ } else {
+ nthw_mac_pcs_swap_gty_tx_polarity(mac_pcs, lane, false);
+ nthw_mac_pcs_swap_gty_rx_polarity(mac_pcs, lane, false);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Check link once NIM is installed and link can be expected.
+ */
+static int check_link_state(adapter_info_t *drv, nthw_mac_pcs_t *mac_pcs)
+{
+ bool rst_required;
+ bool ber;
+ bool fec_all_locked;
+
+ rst_required = nthw_mac_pcs_reset_required(mac_pcs);
+
+ ber = nthw_mac_pcs_get_hi_ber(mac_pcs);
+
+ fec_all_locked = nthw_mac_pcs_get_fec_stat_all_am_locked(mac_pcs);
+
+ if (rst_required || ber || !fec_all_locked)
+ reset_rx(drv, mac_pcs);
+
+ return 0;
+}
+
+/*
+ * Initialize NIM, Code based on nt200e3_2_ptp.cpp: MyPort::createNim()
+ */
+static int create_nim(adapter_info_t *drv, nt_fpga_t *fpga, int port,
+ bool enable)
+{
+ int res = 0;
+ const uint8_t valid_nim_id = 17U;
+ nthw_gpio_phy_t *gpio_phy;
+ nim_i2c_ctx_t *nim_ctx;
+ sfp_nim_state_t nim;
+ nt4ga_link_t *link_info = &drv->nt4ga_link;
+ nthw_mac_pcs_t *mac_pcs = &link_info->u.var100g.mac_pcs100g[port];
+
+ (void)fpga; /* unused */
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ assert(link_info->variables_initialized);
+
+ gpio_phy = &link_info->u.var100g.gpio_phy[port];
+ nim_ctx = &link_info->u.var100g.nim_ctx[port];
+
+ /*
+ * Check NIM is present before doing GPIO PHY reset.
+ */
+ if (!nim_is_present(gpio_phy, (uint8_t)port)) {
+ NT_LOG(INF, ETHDEV, "%s: NIM module is absent\n",
+ drv->mp_port_id_str[port]);
+ return 0;
+ }
+
+ if (!enable) {
+ disable_rx(drv, mac_pcs);
+ disable_tx(drv, mac_pcs);
+ reset_rx(drv, mac_pcs);
+ }
+
+ /*
+ * Perform PHY reset.
+ */
+ NT_LOG(DBG, ETHDEV, "%s: Performing NIM reset\n",
+ drv->mp_port_id_str[port]);
+ nthw_gpio_phy_set_reset(gpio_phy, (uint8_t)port, true);
+ NT_OS_WAIT_USEC(100000); /* pause 0.1s */
+ nthw_gpio_phy_set_reset(gpio_phy, (uint8_t)port, false);
+
+ /*
+ * Wait a little after a module has been inserted before trying to access I2C
+ * data, otherwise the module will not respond correctly.
+ */
+ NT_OS_WAIT_USEC(1000000); /* pause 1.0s */
+
+ if (!nim_is_present(gpio_phy, (uint8_t)port)) {
+ NT_LOG(DBG, ETHDEV, "%s: NIM module is no longer absent!\n",
+ drv->mp_port_id_str[port]);
+ return -1;
+ }
+
+ res = construct_and_preinit_nim(nim_ctx, NULL, port,
+ ((struct adapter_info_s *)drv)->nim_sensors,
+ &((struct adapter_info_s *)drv)->nim_sensors_cnt[port]);
+ if (res)
+ return res;
+
+ res = nim_state_build(nim_ctx, &nim);
+ if (res)
+ return res;
+
+ NT_LOG(DBG, NTHW,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n",
+ drv->mp_port_id_str[port], nim_ctx->nim_id,
+ nim_id_to_text(nim_ctx->nim_id), nim.br, nim_ctx->vendor_name,
+ nim_ctx->prod_no, nim_ctx->serial_no);
+
+ /*
+ * Does the driver support the NIM module type?
+ */
+ if (nim_ctx->nim_id != valid_nim_id) {
+ NT_LOG(ERR, NTHW,
+ "%s: The driver does not support the NIM module type %s\n",
+ drv->mp_port_id_str[port], nim_id_to_text(nim_ctx->nim_id));
+ NT_LOG(DBG, NTHW,
+ "%s: The driver supports the NIM module type %s\n",
+ drv->mp_port_id_str[port], nim_id_to_text(valid_nim_id));
+ return -1;
+ }
+
+ if (enable) {
+ NT_LOG(DBG, ETHDEV, "%s: De-asserting low power\n",
+ drv->mp_port_id_str[port]);
+ nthw_gpio_phy_set_low_power(gpio_phy, (uint8_t)port, false);
+ } else {
+ NT_LOG(DBG, ETHDEV, "%s: Asserting low power\n",
+ drv->mp_port_id_str[port]);
+ nthw_gpio_phy_set_low_power(gpio_phy, (uint8_t)port, true);
+ }
+
+ return res;
+}
+
+/*
+ * Initialize one 100 Gbps port.
+ * The function shall not assume anything about the state of the adapter
+ * and/or port.
+ */
+static int port_init(adapter_info_t *drv, nt_fpga_t *fpga, int port)
+{
+ int adapter_id;
+ int hw_id;
+ int res;
+ nt4ga_link_t *link_info = &drv->nt4ga_link;
+
+ nthw_mac_pcs_t *mac_pcs;
+
+ assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+ assert(link_info->variables_initialized);
+
+ if (fpga && fpga->p_fpga_info) {
+ adapter_id = fpga->p_fpga_info->n_nthw_adapter_id;
+ hw_id = fpga->p_fpga_info->nthw_hw_info.hw_id;
+ } else {
+ adapter_id = -1;
+ hw_id = -1;
+ }
+
+ mac_pcs = &link_info->u.var100g.mac_pcs100g[port];
+
+ /*
+ * Phase 1. Pre-state machine (`port init` functions)
+ * 1.1) Nt4gaAdapter::portInit()
+ */
+
+ /* No adapter set-up here, only state variables */
+
+ /* 1.2) MyPort::init() */
+ link_info->link_info[port].link_speed = NT_LINK_SPEED_100G;
+ link_info->link_info[port].link_duplex = NT_LINK_DUPLEX_FULL;
+ link_info->link_info[port].link_auto_neg = NT_LINK_AUTONEG_OFF;
+ link_info->speed_capa |= NT_LINK_SPEED_100G;
+ nthw_mac_pcs_set_led_mode(mac_pcs, NTHW_MAC_PCS_LED_AUTO);
+ nthw_mac_pcs_set_receiver_equalization_mode(mac_pcs,
+ nthw_mac_pcs_receiver_mode_lpm);
+
+ /*
+ * NT200A01 build 2 HW and NT200A02 that require GTY polarity swap
+ * if (adapter is `NT200A01 build 2 HW or NT200A02`)
+ */
+ if (adapter_id == NT_HW_ADAPTER_ID_NT200A02 ||
+ (adapter_id == NT_HW_ADAPTER_ID_NT200A01 && hw_id == 2))
+ (void)swap_tx_rx_polarity(drv, mac_pcs, port, true);
+
+ nthw_mac_pcs_set_ts_eop(mac_pcs, true); /* end-of-frame timestamping */
+
+ /* Work in ABSOLUTE timing mode, don't set IFG mode. */
+
+ /* Phase 2. Pre-state machine (`setup` functions) */
+
+ /* 2.1) nt200a0x.cpp:Myport::setup() */
+ NT_LOG(DBG, ETHDEV, "%s: Setting up port %d\n", drv->mp_port_id_str[port],
+ port);
+
+ NT_LOG(DBG, ETHDEV, "%s: Port %d: PHY TX enable\n",
+ drv->mp_port_id_str[port], port);
+ enable_tx(drv, mac_pcs);
+ reset_rx(drv, mac_pcs);
+
+ /* 2.2) Nt4gaPort::setup() */
+ if (nthw_gmf_init(NULL, fpga, port) == 0) {
+ nthw_gmf_t gmf;
+
+ if (nthw_gmf_init(&gmf, fpga, port) == 0)
+ nthw_gmf_set_enable(&gmf, true);
+ }
+
+ /* Phase 3. Link state machine steps */
+
+ /* 3.1) Create NIM, ::createNim() */
+ res = create_nim(drv, fpga, port, true);
+
+ if (res) {
+ NT_LOG(WRN, ETHDEV, "%s: NIM initialization failed\n",
+ drv->mp_port_id_str[port]);
+ return res;
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: NIM initialized\n", drv->mp_port_id_str[port]);
+
+ /* 3.2) MyPort::nimReady() */
+
+ /* 3.3) MyPort::nimReady100Gb() */
+
+ /* Setting FEC resets the lane counter in one half of the GMF */
+ nthw_mac_pcs_set_fec(mac_pcs, true);
+ NT_LOG(DBG, ETHDEV, "%s: Port %d: HOST FEC enabled\n",
+ drv->mp_port_id_str[port], port);
+
+ if (adapter_id == NT_HW_ADAPTER_ID_NT200A01 && hw_id == 1) {
+ const uint8_t tuning_s_r4[2][4][3] = { { { 8, 15, 8 },
+ { 8, 15, 9 },
+ { 7, 15, 9 },
+ { 6, 15, 8 }
+ },
+ { { 6, 15, 8 },
+ { 3, 15, 12 },
+ { 7, 15, 9 },
+ { 7, 15, 8 }
+ }
+ };
+
+ uint8_t lane = 0;
+
+ for (lane = 0; lane < 4; lane++) {
+ uint8_t pre, diff, post;
+
+ /* Use short-range tuning values */
+ pre = tuning_s_r4[port][lane][0];
+ diff = tuning_s_r4[port][lane][1];
+ post = tuning_s_r4[port][lane][2];
+
+ nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff,
+ post);
+ }
+ } else if ((adapter_id == NT_HW_ADAPTER_ID_NT200A02) ||
+ ((adapter_id == NT_HW_ADAPTER_ID_NT200A01) &&
+ (hw_id == 2))) {
+ const uint8_t pre = 5;
+ const uint8_t diff = 25;
+ const uint8_t post = 12;
+
+ uint8_t lane = 0;
+
+ for (lane = 0; lane < 4; lane++) {
+ nthw_mac_pcs_set_gty_tx_tuning(mac_pcs, lane, pre, diff,
+ post);
+ }
+ } else {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Unhandled AdapterId/HwId: %02x_hwid%d\n", __func__,
+ adapter_id, hw_id);
+ assert(0);
+ }
+ reset_rx(drv, mac_pcs);
+
+ /*
+ * 3.4) MyPort::setLinkState()
+ *
+ * Compensation = 1640 - dly
+ * CMAC-core dly 188 ns
+ * FEC no correction 87 ns
+ * FEC active correction 211
+ */
+ if (nthw_mac_pcs_get_fec_valid(mac_pcs))
+ nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 211));
+
+ else
+ nthw_mac_pcs_set_timestamp_comp_rx(mac_pcs, (1640 - 188 - 87));
+
+ /* 3.5) uint32_t MyPort::macConfig(nt_link_state_t link_state) */
+ enable_rx(drv, mac_pcs);
+
+ nthw_mac_pcs_set_host_loopback(mac_pcs, false);
+
+ return res;
+}
+
+/*
+ * State machine shared between kernel and userland
+ */
+static int common_ptp_nim_state_machine(void *data)
+{
+ adapter_info_t *drv = (adapter_info_t *)data;
+ fpga_info_t *fpga_info = &drv->fpga_info;
+ nt4ga_link_t *link_info = &drv->nt4ga_link;
+ nt_fpga_t *fpga = fpga_info->mp_fpga;
+ const int adapter_no = drv->adapter_no;
+ const int nb_ports = fpga_info->n_phy_ports;
+ uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+
+ nim_i2c_ctx_t *nim_ctx;
+ link_state_t *link_state;
+ nthw_mac_pcs_t *mac_pcs;
+ nthw_gpio_phy_t *gpio_phy;
+
+ if (!fpga) {
+ NT_LOG(ERR, ETHDEV, "%s: fpga is NULL\n", drv->mp_adapter_id_str);
+ goto NT4GA_LINK_100G_MON_EXIT;
+ }
+
+ assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+ nim_ctx = link_info->u.var100g.nim_ctx;
+ link_state = link_info->link_state;
+ mac_pcs = link_info->u.var100g.mac_pcs100g;
+ gpio_phy = link_info->u.var100g.gpio_phy;
+
+ monitor_task_is_running[adapter_no] = 1;
+ memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+
+ if (monitor_task_is_running[adapter_no]) {
+ NT_LOG(DBG, ETHDEV, "%s: link state machine running...\n",
+ drv->mp_adapter_id_str);
+ }
+
+ while (monitor_task_is_running[adapter_no]) {
+ int i;
+ static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
+
+ /* Read sensors */
+ if (drv->adapter_sensors != NULL) {
+ nthw_spis_t *t_spi =
+ new_sensors_t_spi(drv->fpga_info.mp_fpga);
+ if (t_spi) {
+ for (struct nt_sensor_group *ptr =
+ drv->adapter_sensors;
+ ptr != NULL; ptr = ptr->next)
+ ptr->read(ptr, t_spi);
+ nthw_spis_delete(t_spi);
+ }
+ }
+
+ for (i = 0; i < nb_ports; i++) {
+ link_state_t new_link_state;
+ const bool is_port_disabled =
+ link_info->port_action[i].port_disable;
+ const bool was_port_disabled =
+ link_state[i].link_disabled;
+ const bool disable_port = is_port_disabled &&
+ !was_port_disabled;
+ const bool enable_port = !is_port_disabled &&
+ was_port_disabled;
+
+ if (!monitor_task_is_running[adapter_no]) /* stop quickly */
+ break;
+
+ /* Reading NIM sensors */
+ if (drv->nim_sensors[i] != NULL) {
+ nthw_spis_t *t_spi = new_sensors_t_spi(drv->fpga_info.mp_fpga);
+ if (t_spi) {
+ for (struct nim_sensor_group *ptr =
+ drv->nim_sensors[i];
+ ptr != NULL; ptr = ptr->next)
+ ptr->read(ptr, t_spi);
+ nthw_spis_delete(t_spi);
+ }
+ }
+
+ /* Has the administrative port state changed? */
+ assert(!(disable_port && enable_port));
+ if (disable_port) {
+ memset(&link_state[i], 0,
+ sizeof(link_state[i]));
+ link_state[i].link_disabled = true;
+ reported_link[i] = false;
+ /* Turn off laser and LED, etc. */
+ (void)create_nim(drv, fpga, i, false);
+ NT_LOG(DBG, ETHDEV, "%s: Port %i is disabled\n",
+ drv->mp_port_id_str[i], i);
+ continue;
+ }
+
+ if (enable_port) {
+ link_state[i].link_disabled = false;
+ NT_LOG(DBG, ETHDEV, "%s: Port %i is enabled\n",
+ drv->mp_port_id_str[i], i);
+ }
+
+ if (is_port_disabled)
+ continue;
+
+ if (link_info->port_action[i].port_lpbk_mode !=
+ last_lpbk_mode[i]) {
+ /* Loopback mode has changed. Do something */
+ if (!nim_is_present(&gpio_phy[i],
+ (uint8_t)i)) {
+ /*
+ * If there is no Nim present, we need to initialize the
+ * port anyway
+ */
+ port_init(drv, fpga, i);
+ }
+ NT_LOG(INF, ETHDEV,
+ "%s: Loopback mode changed=%u\n",
+ drv->mp_port_id_str[i],
+ link_info->port_action[i].port_lpbk_mode);
+ set_loopback(drv, &mac_pcs[i], i,
+ link_info->port_action[i].port_lpbk_mode,
+ last_lpbk_mode[i]);
+ if (link_info->port_action[i].port_lpbk_mode ==
+ 1)
+ link_state[i].link_up = true;
+ last_lpbk_mode[i] =
+ link_info->port_action[i].port_lpbk_mode;
+ continue;
+ }
+
+ (void)link_state_build(drv, &mac_pcs[i], &gpio_phy[i],
+ i, &new_link_state,
+ is_port_disabled);
+ if (!new_link_state.nim_present) {
+ if (link_state[i].nim_present) {
+ NT_LOG(INF, ETHDEV,
+ "%s: NIM module removed\n",
+ drv->mp_port_id_str[i]);
+ }
+ link_state[i] = new_link_state;
+ continue;
+ }
+
+ /* NIM module is present */
+ if (new_link_state.lh_nim_absent ||
+ !link_state[i].nim_present) {
+ sfp_nim_state_t new_state;
+
+ NT_LOG(DBG, ETHDEV, "%s: NIM module inserted\n",
+ drv->mp_port_id_str[i]);
+
+ if (port_init(drv, fpga, i)) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Failed to initialize NIM module\n",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
+ if (nim_state_build(&nim_ctx[i], &new_state)) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot read basic NIM data\n",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
+ assert(new_state.br); /* Cannot be zero if NIM is present */
+ NT_LOG(DBG, ETHDEV,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'\n",
+ drv->mp_port_id_str[i], nim_ctx->nim_id,
+ nim_id_to_text(nim_ctx->nim_id),
+ (unsigned int)new_state.br,
+ nim_ctx->vendor_name, nim_ctx->prod_no,
+ nim_ctx->serial_no);
+
+ (void)link_state_build(drv, &mac_pcs[i],
+ &gpio_phy[i], i,
+ &link_state[i],
+ is_port_disabled);
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: NIM module initialized\n",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
+ if (reported_link[i] != new_link_state.link_up) {
+ NT_LOG(INF, ETHDEV, "%s: link is %s\n",
+ drv->mp_port_id_str[i],
+ (new_link_state.link_up ? "up" :
+ "down"));
+ link_state[i].link_up = new_link_state.link_up;
+ reported_link[i] = new_link_state.link_up;
+ }
+ check_link_state(drv, &mac_pcs[i]);
+ } /* end-for */
+ if (monitor_task_is_running[adapter_no])
+ NT_OS_WAIT_USEC(5 * 100000U); /* 5 x 0.1s = 0.5s */
+ }
+
+NT4GA_LINK_100G_MON_EXIT:
+
+ NT_LOG(DBG, ETHDEV,
+ "%s: Stopped NT4GA 100 Gbps link monitoring thread.\n",
+ drv->mp_adapter_id_str);
+
+ return 0;
+}
+
+/*
+ * Userland NIM state machine
+ */
+static void *nt4ga_link_100g_mon(void *data)
+{
+ (void)common_ptp_nim_state_machine(data);
+
+ return NULL;
+}
+
+/*
+ * Initialize all ports
+ * The driver calls this function during initialization (of the driver).
+ */
+int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
+ nt_fpga_t *fpga)
+{
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ const int adapter_no = p_adapter_info->adapter_no;
+ const int nb_ports = fpga_info->n_phy_ports;
+ int res = 0;
+
+ NT_LOG(DBG, ETHDEV, "%s: Initializing ports\n",
+ p_adapter_info->mp_adapter_id_str);
+
+ /*
+ * Initialize global variables
+ */
+ assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+
+ if (res == 0 && !p_adapter_info->nt4ga_link.variables_initialized) {
+ nthw_mac_pcs_t *mac_pcs =
+ p_adapter_info->nt4ga_link.u.var100g.mac_pcs100g;
+ nim_i2c_ctx_t *nim_ctx =
+ p_adapter_info->nt4ga_link.u.var100g.nim_ctx;
+ nthw_gpio_phy_t *gpio_phy =
+ p_adapter_info->nt4ga_link.u.var100g.gpio_phy;
+ int i;
+
+ for (i = 0; i < nb_ports; i++) {
+ const uint8_t instance =
+ (uint8_t)(2U + i); /* 2 + adapter port number */
+ res = nthw_mac_pcs_init(&mac_pcs[i], fpga,
+ i /* int nInstance */);
+ if (res != 0)
+ break;
+ res = nthw_iic_init(&nim_ctx[i].hwiic, fpga, instance,
+ 8 /* timing */);
+ if (res != 0)
+ break;
+ nim_ctx[i].instance = instance;
+ nim_ctx[i].devaddr = 0x50; /* 0xA0 / 2 */
+ nim_ctx[i].regaddr = 0U;
+ res = nthw_gpio_phy_init(&gpio_phy[i], fpga,
+ 0 /* Only one instance */);
+ if (res != 0)
+ break;
+ }
+ if (res == 0)
+ p_adapter_info->nt4ga_link.variables_initialized = true;
+ }
+
+ /* Create state-machine thread */
+ if (res == 0) {
+ if (!monitor_task_is_running[adapter_no]) {
+ res = pthread_create(&monitor_tasks[adapter_no], NULL,
+ nt4ga_link_100g_mon, p_adapter_info);
+ }
+ }
+ return res;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_link_100g.h b/drivers/net/ntnic/adapter/nt4ga_link_100g.h
new file mode 100644
index 0000000000..803b3454b7
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_link_100g.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_LINK_100G_H_
+#define NT4GA_LINK_100G_H_
+
+#include "nthw_drv.h"
+
+int nt4ga_link_100g_ports_init(adapter_info_t *p_adapter_info, nt_fpga_t *p_fpga);
+
+#endif /* NT4GA_LINK_100G_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c
new file mode 100644
index 0000000000..07884e9219
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.c
@@ -0,0 +1,598 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nt_util.h"
+#include "nthw_drv.h"
+#include "nt4ga_adapter.h"
+#include "nt4ga_pci_ta_tg.h"
+#include "nthw_pci_ta.h"
+#include "nthw_pci_rd_tg.h"
+#include "nthw_pci_wr_tg.h"
+
+int nt4ga_pci_ta_tg_init(struct adapter_info_s *p_adapter_info)
+{
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ nt_fpga_t *p_fpga = fpga_info->mp_fpga;
+ nt4ga_pci_ta_tg_t *p = &p_adapter_info->nt4ga_pci_ta_tg;
+ int res;
+ int n_err_cnt = 0;
+
+ if (p) {
+ memset(p, 0, sizeof(nt4ga_pci_ta_tg_t));
+ } else {
+ NT_LOG(ERR, NTHW, "%s: %s: null ptr\n", p_adapter_id_str, __func__);
+ return -1;
+ }
+
+ assert(p_fpga);
+
+ p->mp_nthw_pci_rd_tg = nthw_pci_rd_tg_new();
+ assert(p->mp_nthw_pci_rd_tg);
+ res = nthw_pci_rd_tg_init(p->mp_nthw_pci_rd_tg, p_fpga, 0);
+ if (res) {
+ n_err_cnt++;
+ NT_LOG(WRN, NTHW, "%s: module PCI_RD_TG not found\n",
+ p_adapter_id_str);
+ }
+
+ p->mp_nthw_pci_wr_tg = nthw_pci_wr_tg_new();
+ assert(p->mp_nthw_pci_wr_tg);
+ res = nthw_pci_wr_tg_init(p->mp_nthw_pci_wr_tg, p_fpga, 0);
+ if (res) {
+ n_err_cnt++;
+ NT_LOG(WRN, NTHW, "%s: module PCI_WR_TG not found\n",
+ p_adapter_id_str);
+ }
+
+ p->mp_nthw_pci_ta = nthw_pci_ta_new();
+ assert(p->mp_nthw_pci_ta);
+ res = nthw_pci_ta_init(p->mp_nthw_pci_ta, p_fpga, 0);
+ if (res) {
+ n_err_cnt++;
+ NT_LOG(WRN, NTHW, "%s: module PCI_TA not found\n",
+ p_adapter_id_str);
+ }
+
+ return n_err_cnt;
+}
+
+static int nt4ga_pci_ta_tg_ta_write_control_enable(nt4ga_pci_ta_tg_t *p,
+ uint32_t enable)
+{
+ nthw_pci_ta_set_control_enable(p->mp_nthw_pci_ta, enable);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_length_error(nt4ga_pci_ta_tg_t *p, uint32_t *p_data)
+{
+ nthw_pci_ta_get_length_error(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_packet_bad(nt4ga_pci_ta_tg_t *p, uint32_t *p_data)
+{
+ nthw_pci_ta_get_packet_bad(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_packet_good(nt4ga_pci_ta_tg_t *p, uint32_t *p_data)
+{
+ nthw_pci_ta_get_packet_good(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_ta_read_payload_error(nt4ga_pci_ta_tg_t *p,
+ uint32_t *p_data)
+{
+ nthw_pci_ta_get_payload_error(p->mp_nthw_pci_ta, p_data);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_rd_tg_setup(nt4ga_pci_ta_tg_t *p, uint64_t iova,
+ int slot_addr, uint32_t req_size, bool wait,
+ bool wrap)
+{
+ const uint64_t n_phys_addr = (iova + (unsigned long)(slot_addr * req_size));
+
+ nthw_pci_rd_tg_set_ram_addr(p->mp_nthw_pci_rd_tg, slot_addr);
+ nthw_pci_rd_tg_set_phys_addr(p->mp_nthw_pci_rd_tg, n_phys_addr);
+ nthw_pci_rd_tg_set_ram_data(p->mp_nthw_pci_rd_tg, req_size, wait, wrap);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_rd_tg_run(nt4ga_pci_ta_tg_t *p, uint32_t num_iterations)
+{
+ nthw_pci_rd_tg_set_run(p->mp_nthw_pci_rd_tg, num_iterations);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_rd_tg_wait_ready(nt4ga_pci_ta_tg_t *p)
+{
+ int poll = 0;
+ uint32_t data = 0;
+
+ while (data == 0) {
+ /* NOTE: Deliberately start with a sleep - ensures that the FPGA pipe is empty */
+ NT_OS_WAIT_USEC(1000);
+ data = nthw_pci_rd_tg_get_ctrl_rdy(p->mp_nthw_pci_rd_tg);
+ poll++;
+ if (poll >= 1000) {
+ NT_LOG(ERR, NTHW,
+ "%s: FAILED waiting PCI RD TG ready: poll=%d\n",
+ __func__, poll);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_wr_tg_setup(nt4ga_pci_ta_tg_t *p, uint64_t iova,
+ int slot_addr, uint32_t req_size, bool wait,
+ bool wrap, bool inc)
+{
+ const uint64_t n_phys_addr = (iova + (unsigned long)(slot_addr * req_size));
+
+ nthw_pci_wr_tg_set_ram_addr(p->mp_nthw_pci_wr_tg, slot_addr);
+ nthw_pci_wr_tg_set_phys_addr(p->mp_nthw_pci_wr_tg, n_phys_addr);
+ nthw_pci_wr_tg_set_ram_data(p->mp_nthw_pci_wr_tg, req_size, wait, wrap, inc);
+
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_wr_tg_run(nt4ga_pci_ta_tg_t *p, uint32_t num_iterations)
+{
+ nthw_pci_wr_tg_set_run(p->mp_nthw_pci_wr_tg, num_iterations);
+ return 0;
+}
+
+static int nt4ga_pci_ta_tg_wr_tg_wait_ready(nt4ga_pci_ta_tg_t *p)
+{
+ int poll = 0;
+ uint32_t data = 0;
+
+ while (data == 0) {
+ /* NOTE: Deliberately start with a sleep - ensures that the FPGA pipe is empty */
+ NT_OS_WAIT_USEC(1000);
+ data = nthw_pci_wr_tg_get_ctrl_rdy(p->mp_nthw_pci_wr_tg);
+ poll++;
+ if (poll >= 1000) {
+ NT_LOG(ERR, NTHW,
+ "%s: FAILED waiting PCI WR TG ready: poll=%d\n",
+ __func__, poll);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int nt4ga_pci_ta_tg_measure_throughput_run(struct adapter_info_s *p_adapter_info,
+ struct nthw_hif_end_point_counters *pri,
+ struct nthw_hif_end_point_counters *sla)
+{
+ nt4ga_pci_ta_tg_t *p = &p_adapter_info->nt4ga_pci_ta_tg;
+
+ const int delay = pri->n_tg_delay;
+ const int pkt_size = pri->n_tg_pkt_size;
+ const int num_pkts = pri->n_tg_num_pkts;
+ const int n_direction = pri->n_tg_direction;
+ const uint8_t n_numa_node = (uint8_t)pri->n_numa_node;
+ const int dma_buf_size = (4 * 1024 * 1024);
+
+ const size_t align_size = ALIGN_SIZE(dma_buf_size);
+ uint32_t *mem_addr;
+ uint64_t iova;
+
+ int bo_error = 0;
+
+ nthw_hif *p_master_instance = p_adapter_info->fpga_info.mp_nthw_hif;
+ nthw_hif *p_slave_instance = NULL;
+
+ nthw_pcie3 *p_pci_master = p_adapter_info->fpga_info.mp_nthw_pcie3;
+ nthw_pcie3 *p_pci_slave = NULL;
+
+ assert(p_master_instance || p_pci_master);
+
+ struct nt_dma_s *p_dma;
+ /* FPGA needs a Page alignment (4K on Intel) */
+ p_dma = nt_dma_alloc(align_size, 0x1000, n_numa_node);
+ if (p_dma == NULL) {
+ NT_LOG(DBG, ETHDEV, "%s: vfio_dma_alloc failed\n", __func__);
+ return 0;
+ }
+ mem_addr = (uint32_t *)p_dma->addr;
+ iova = p_dma->iova;
+
+ NT_LOG(DBG, NTHW,
+ "%s: Running HIF bandwidth measurements on NUMA node %d\n",
+ __func__, n_numa_node);
+
+ bo_error = 0;
+ {
+ int wrap;
+
+ /* Stop any existing running test */
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0);
+
+ /* Prepare the HIF Traffic generator */
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 1);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ /*
+ * Ensure that the hostbuffer memory contain data that can be read -
+ * For this we will ask the FPGA to write data to it. The last wrap packet
+ * does not generate any data it only wraps (unlike the PCIe2 TG)
+ */
+ {
+ int pkt;
+
+ for (pkt = 0; pkt < num_pkts; pkt++) {
+ if (pkt >= (num_pkts - 1))
+ wrap = 1;
+
+ else
+ wrap = 0;
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_setup(p, iova,
+ pkt, pkt_size,
+ 0, wrap, 1);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_setup(p, iova,
+ pkt, pkt_size,
+ 0, wrap);
+ }
+ }
+
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 1);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ /* Start WR TG Write once */
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 1);
+ /* Wait until WR TG ready */
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ /* Verify that we have a packet */
+ {
+ int pkt;
+
+ for (pkt = 0; pkt < num_pkts; pkt++) {
+ uint32_t value = 0;
+ int poll;
+
+ for (poll = 8; poll < pkt_size;
+ poll += 4, value++) {
+ if (*(uint32_t *)((uint8_t *)mem_addr +
+ (pkt * pkt_size) +
+ poll) != value) {
+ NT_LOG(ERR, NTHW,
+ "HIF TG: Prepare failed. Data write failed: #%d.%d: %016X:%08X\n",
+ pkt, poll,
+ *(uint32_t *)((uint8_t *)
+ mem_addr +
+ (pkt *
+ pkt_size) +
+ poll),
+ value);
+
+ /*
+ * Break out of the verification loop on first
+ * Compare error
+ */
+ bo_error |= 1;
+ break;
+ }
+ }
+ }
+ }
+
+ switch (n_direction) {
+ case 1: /* Read only test */
+ nt4ga_pci_ta_tg_wr_tg_run(p, 0xffff);
+ break;
+ case 2: /* Write only test */
+ nt4ga_pci_ta_tg_rd_tg_run(p, 0xffff);
+ break;
+ case 3: /* Combined read/write test */
+ nt4ga_pci_ta_tg_wr_tg_run(p, 0xffff);
+ nt4ga_pci_ta_tg_rd_tg_run(p, 0xffff);
+ break;
+ default: /* stop tests */
+ nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ break;
+ }
+
+ do {
+ /* prep */
+ if (p_pci_master) {
+ nthw_pcie3_end_point_counters_sample_pre(p_pci_master,
+ pri);
+ }
+ if (p_pci_slave) {
+ nthw_pcie3_end_point_counters_sample_pre(p_pci_slave,
+ sla);
+ }
+
+ /* start measure */
+ if (p_master_instance)
+ nthw_hif_stat_req_enable(p_master_instance);
+ if (p_pci_master)
+ nthw_pcie3_stat_req_enable(p_pci_master);
+
+ if (p_slave_instance)
+ nthw_hif_stat_req_enable(p_slave_instance);
+ if (p_pci_slave)
+ nthw_pcie3_stat_req_enable(p_pci_slave);
+
+ /* Wait */
+ NT_OS_WAIT_USEC(delay);
+
+ /* Stop measure */
+ if (p_master_instance)
+ nthw_hif_stat_req_disable(p_master_instance);
+ if (p_pci_master)
+ nthw_pcie3_stat_req_disable(p_pci_master);
+
+ if (p_slave_instance)
+ nthw_hif_stat_req_disable(p_slave_instance);
+ if (p_pci_slave)
+ nthw_pcie3_stat_req_disable(p_pci_slave);
+
+ /* Post process master */
+ if (p_master_instance) {
+ nthw_hif_end_point_counters_sample(p_master_instance,
+ pri);
+ }
+
+ if (p_pci_master) {
+ nthw_pcie3_end_point_counters_sample_post(p_pci_master,
+ pri);
+ }
+
+ /* Post process slave */
+ if (p_slave_instance) {
+ nthw_hif_end_point_counters_sample(p_slave_instance,
+ sla);
+ }
+
+ if (p_pci_slave) {
+ nthw_pcie3_end_point_counters_sample_post(p_pci_slave,
+ sla);
+ }
+
+ {
+ /* Check for TA transmit errors */
+ uint32_t dw_good_pkts, dw_bad_pkts, dw_bad_length,
+ dw_bad_payload;
+ nt4ga_pci_ta_tg_ta_read_packet_good(p,
+ &dw_good_pkts);
+ nt4ga_pci_ta_tg_ta_read_packet_bad(p, &dw_bad_pkts);
+ nt4ga_pci_ta_tg_ta_read_length_error(p,
+ &dw_bad_length);
+ nt4ga_pci_ta_tg_ta_read_payload_error(p, &dw_bad_payload);
+
+ NT_LOG(DBG, NTHW,
+ "%s: NUMA node %u: HIF: TA: Good pkts, Bad pkts, Bad length, Bad payload\n",
+ __func__, n_numa_node);
+ NT_LOG(DBG, NTHW,
+ "%s: NUMA node %u: HIF: TA: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ __func__, n_numa_node, dw_good_pkts,
+ dw_bad_pkts, dw_bad_length, dw_bad_payload);
+
+ if (dw_bad_pkts | dw_bad_length | dw_bad_payload) {
+ bo_error |= 1;
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: error detected\n",
+ __func__, n_numa_node);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Good packets received: %u\n",
+ __func__, n_numa_node, dw_good_pkts);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Bad packets received : %u\n",
+ __func__, n_numa_node, dw_bad_pkts);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Bad length received : %u\n",
+ __func__, n_numa_node,
+ dw_bad_length);
+ NT_LOG(ERR, NTHW,
+ "%s: NUMA node %u: HIF: TA: Bad payload received : %u\n",
+ __func__, n_numa_node,
+ dw_bad_payload);
+ }
+ }
+
+ if (bo_error != 0)
+ break;
+
+ break; /* for now only loop once */
+
+ /*
+ * Only do "signalstop" looping if a specific numa node and direction is to
+ * be tested.
+ */
+ } while ((bo_error == 0) && (n_numa_node != UINT8_MAX) &&
+ (n_direction != -1));
+
+ /* Stop the test */
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0);
+
+ /* PCIe3 sanity checks */
+ {
+#if defined(DEBUG)
+ int do_loop = 1;
+#else
+ int do_loop = 0;
+#endif
+
+ while (do_loop) {
+ do_loop = 0;
+
+ if (p_master_instance) {
+ nthw_hif_stat_req_enable(p_master_instance);
+ NT_OS_WAIT_USEC(100);
+ nthw_hif_stat_req_disable(p_master_instance);
+ }
+
+ if (do_loop == 0)
+ break;
+
+ NT_LOG(DBG, NTHW,
+ "%s: WARNING this is wrong - wait again\n",
+ __func__);
+ NT_OS_WAIT_USEC(200 * 1000);
+ }
+ }
+ }
+
+ /* Stop the test */
+
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_wr_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_run(p, 0);
+ bo_error |= nt4ga_pci_ta_tg_rd_tg_wait_ready(p);
+
+ bo_error |= nt4ga_pci_ta_tg_ta_write_control_enable(p, 0);
+
+ nt_dma_free(p_dma);
+
+ return bo_error;
+}
+
+int nt4ga_pci_ta_tg_measure_throughput_main(struct adapter_info_s *p_adapter_info,
+ const uint8_t numa_node,
+ const int direction, const int n_pkt_size,
+ const int n_batch_count, const int n_delay)
+{
+ /* All numa nodes is indicated by UINT8_MAX */
+ const uint8_t numa_begin = (numa_node == UINT8_MAX ? 0 : numa_node);
+ const uint8_t numa_end = numa_begin;
+
+ /* sanity check direction param */
+ const int dir_begin = (direction <= 0 ? 1 : direction);
+ const int dir_end = (direction <= 0 ? 3 : direction);
+
+ int bo_error = 0;
+ struct nthw_hif_end_points eps;
+
+ if (n_delay == 0)
+ return -1;
+
+ NT_LOG(DBG, NTHW, "HIF adapter throughput:\n");
+
+ /* Only do "signalstop"-looping if a specific numa node is to be tested. */
+ {
+ uint8_t numa;
+
+ for (numa = numa_begin; numa <= numa_end; numa++) {
+ {
+ int by_loop;
+
+ for (by_loop = dir_begin; by_loop <= dir_end;
+ by_loop++) {
+ struct nthw_hif_end_point_counters *pri =
+ &eps.pri;
+ struct nthw_hif_end_point_counters *sla =
+ &eps.sla;
+
+ pri->n_numa_node = numa;
+ pri->n_tg_direction = by_loop;
+ pri->n_tg_pkt_size = (n_pkt_size > 0 ?
+ n_pkt_size :
+ TG_PKT_SIZE);
+ pri->n_tg_num_pkts =
+ (n_batch_count > 0 ?
+ n_batch_count :
+ TG_NUM_PACKETS);
+ pri->n_tg_delay = (n_delay > 0 ? n_delay :
+ TG_DELAY);
+ pri->cur_rx = 0;
+ pri->cur_tx = 0;
+ pri->n_ref_clk_cnt = -1;
+ pri->bo_error = 0;
+
+ sla->n_numa_node = numa;
+ sla->n_tg_direction = by_loop;
+ sla->n_tg_pkt_size = (n_pkt_size > 0 ?
+ n_pkt_size :
+ TG_PKT_SIZE);
+ sla->n_tg_num_pkts =
+ (n_batch_count > 0 ?
+ n_batch_count :
+ TG_NUM_PACKETS);
+ sla->n_tg_delay = (n_delay > 0 ? n_delay :
+ TG_DELAY);
+ sla->cur_rx = 0;
+ sla->cur_tx = 0;
+ pri->n_ref_clk_cnt = -1;
+ sla->bo_error = 0;
+
+ bo_error +=
+ nt4ga_pci_ta_tg_measure_throughput_run(p_adapter_info,
+ pri, sla);
+#if defined(DEBUG) && (1)
+ {
+ NT_LOG(DBG, NTHW,
+ "%s: @ %d: %d %d %d %d: %016lX %016lX : %6ld Mbps %6ld Mbps\n",
+ __func__, pri->n_numa_node,
+ pri->n_tg_direction,
+ pri->n_tg_num_pkts,
+ pri->n_tg_pkt_size,
+ pri->n_tg_delay,
+ pri->cur_rx, pri->cur_tx,
+ (pri->cur_rx * 8UL /
+ 1000000UL),
+ (pri->cur_tx * 8UL /
+ 1000000UL));
+ }
+ {
+ NT_LOG(DBG, NTHW,
+ "%s: @ %d: %d %d %d %d: %016lX %016lX : %6ld Mbps %6ld Mbps\n",
+ __func__, sla->n_numa_node,
+ sla->n_tg_direction,
+ sla->n_tg_num_pkts,
+ sla->n_tg_pkt_size,
+ sla->n_tg_delay,
+ sla->cur_rx, sla->cur_tx,
+ (sla->cur_rx * 8UL /
+ 1000000UL),
+ (sla->cur_tx * 8UL /
+ 1000000UL));
+ }
+#endif
+
+ if (pri->bo_error != 0 || sla->bo_error != 0)
+ bo_error++;
+ if (bo_error)
+ break;
+ }
+ }
+ }
+ }
+
+ if (bo_error != 0) {
+ NT_LOG(ERR, NTHW, "%s: error during bandwidth measurement\n",
+ __func__);
+ }
+
+ NT_LOG(DBG, NTHW, "HIF adapter throughput: done\n");
+
+ NT_LOG(DBG, NTHW, "%s: [%s:%u] done\n", __func__, __FILE__, __LINE__);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h
new file mode 100644
index 0000000000..8b46491f77
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_pci_ta_tg.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NT4GA_PCI_TA_TG_H_
+#define _NT4GA_PCI_TA_TG_H_
+
+#include <stdint.h>
+
+#define TA_TG_DBG_SHOW_SUMMARY (1)
+
+#define TG_NUM_PACKETS (8)
+#define TG_PKT_SIZE (2048 * 1)
+#define TG_AREA_SIZE (TG_NUM_PACKETS * TG_PKT_SIZE)
+
+#define TG_DELAY (200000) /* usec */
+
+/* Struct predefinitions */
+struct adapter_info_s;
+struct nthw_hif_end_point_counters;
+
+struct nt4ga_pci_ta_tg_s {
+ struct nthw_pci_rd_tg *mp_nthw_pci_rd_tg;
+ struct nthw_pci_wr_tg *mp_nthw_pci_wr_tg;
+ struct nthw_pci_ta *mp_nthw_pci_ta;
+};
+
+typedef struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg_t;
+typedef struct nt4ga_pci_ta_tg_s nt4ga_pci_ta_tg;
+
+int nt4ga_pci_ta_tg_init(struct adapter_info_s *p_adapter_info);
+
+int nt4ga_pci_ta_tg_measure_throughput_run(struct adapter_info_s *p_adapter_info,
+ struct nthw_hif_end_point_counters *pri,
+ struct nthw_hif_end_point_counters *sla);
+int nt4ga_pci_ta_tg_measure_throughput_main(struct adapter_info_s *p_adapter_info,
+ const uint8_t numa_node,
+ const int direction, const int n_pkt_size,
+ const int n_batch_count, const int n_delay);
+
+#endif /* _NT4GA_PCI_TA_TG_H_ */
diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.c b/drivers/net/ntnic/adapter/nt4ga_stat.c
new file mode 100644
index 0000000000..b61c73ea12
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_stat.c
@@ -0,0 +1,705 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nt_util.h"
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+#include "nt4ga_adapter.h"
+
+#define NO_FLAGS 0
+
+/* Inline timestamp format s pcap 32:32 bits. Convert to nsecs */
+static inline uint64_t timestamp2ns(uint64_t ts)
+{
+ return ((ts >> 32) * 1000000000) + (ts & 0xffffffff);
+}
+
+static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual);
+static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual);
+
+int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused,
+ nt4ga_stat_t *p_nt4ga_stat)
+{
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ if (p_nthw_stat->mb_is_vswitch) {
+ /*
+ * Set all bits in the DMA block timestamp since 9530-42-05 and other Vswitch FPGA
+ * images may only clear all bits in this memory location. TBV
+ * Consequently, last_timestamp must be constructed via a system call.
+ */
+ *p_nthw_stat->mp_timestamp = 0xFFFFFFFF;
+ p_nt4ga_stat->last_timestamp = NT_OS_GET_TIME_NS();
+ nt4ga_stat_collect_virt_v1_stats(p_nt4ga_stat,
+ p_nt4ga_stat->p_stat_dma_virtual);
+ } else {
+ p_nt4ga_stat->last_timestamp =
+ timestamp2ns(*p_nthw_stat->mp_timestamp);
+ nt4ga_stat_collect_cap_v1_stats(p_nt4ga_stat,
+ p_nt4ga_stat->p_stat_dma_virtual);
+ }
+ return 0;
+}
+
+int nt4ga_stat_init(struct adapter_info_s *p_adapter_info)
+{
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ nt_fpga_t *p_fpga = fpga_info->mp_fpga;
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+
+ if (p_nt4ga_stat) {
+ memset(p_nt4ga_stat, 0, sizeof(nt4ga_stat_t));
+ } else {
+ NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ {
+ nthw_stat_t *p_nthw_stat = nthw_stat_new();
+ nthw_rmc_t *p_nthw_rmc = nthw_rmc_new();
+
+ if (!p_nthw_stat) {
+ NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (!p_nthw_rmc) {
+ nthw_stat_delete(p_nthw_stat);
+
+ NT_LOG(ERR, ETHDEV, "%s: ERROR (%s:%d)", p_adapter_id_str,
+ __func__, __LINE__);
+ return -1;
+ }
+
+ p_nt4ga_stat->mp_nthw_stat = p_nthw_stat;
+ nthw_stat_init(p_nthw_stat, p_fpga, 0);
+
+ p_nt4ga_stat->mp_nthw_rmc = p_nthw_rmc;
+ nthw_rmc_init(p_nthw_rmc, p_fpga, 0);
+
+ p_nt4ga_stat->mn_rx_host_buffers = p_nthw_stat->m_nb_rx_host_buffers;
+ p_nt4ga_stat->mn_tx_host_buffers = p_nthw_stat->m_nb_tx_host_buffers;
+
+ p_nt4ga_stat->mn_rx_ports = p_nthw_stat->m_nb_rx_ports;
+ p_nt4ga_stat->mn_tx_ports = p_nthw_stat->m_nb_tx_ports;
+ }
+
+ return 0;
+}
+
+int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info)
+{
+ const int n_physical_adapter_no _unused = p_adapter_info->adapter_no;
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ nthw_rmc_t *p_nthw_rmc = p_nt4ga_stat->mp_nthw_rmc;
+
+ if (p_nthw_rmc)
+ nthw_rmc_block(p_nthw_rmc);
+
+ /* Allocate and map memory for fpga statistics */
+ {
+ uint32_t n_stat_size =
+ (uint32_t)(p_nthw_stat->m_nb_counters * sizeof(uint32_t) +
+ sizeof(p_nthw_stat->mp_timestamp));
+ struct nt_dma_s *p_dma;
+ int numa_node = p_adapter_info->fpga_info.numa_node;
+
+ /* FPGA needs a 16K alignment on Statistics */
+ p_dma = nt_dma_alloc(n_stat_size, 0x4000, numa_node);
+
+ if (!p_dma) {
+ NT_LOG(ERR, ETHDEV, "%s: pDma alloc failed\n",
+ __func__);
+ return -1;
+ }
+
+ NT_LOG(DBG, ETHDEV, "%s: %x @%d %p %" PRIX64 " %" PRIX64 "\n", __func__,
+ n_stat_size, numa_node, p_dma->addr, p_dma->iova);
+
+ NT_LOG(DBG, ETHDEV,
+ "DMA: Physical adapter %02ld, PA = 0x%016" PRIX64
+ " DMA = 0x%016" PRIX64 " size = 0x%" PRIX64 "\n",
+ n_physical_adapter_no, p_dma->iova, p_dma->addr, n_stat_size);
+
+ p_nt4ga_stat->p_stat_dma_virtual = (uint32_t *)p_dma->addr;
+ p_nt4ga_stat->n_stat_size = n_stat_size;
+ p_nt4ga_stat->p_stat_dma = p_dma;
+
+ memset(p_nt4ga_stat->p_stat_dma_virtual, 0xaa, n_stat_size);
+ nthw_stat_set_dma_address(p_nthw_stat, p_dma->iova,
+ p_nt4ga_stat->p_stat_dma_virtual);
+ }
+
+ if (p_nthw_rmc)
+ nthw_rmc_unblock(p_nthw_rmc, false);
+
+ p_nt4ga_stat->mp_stat_structs_color = calloc(p_nthw_stat->m_nb_color_counters,
+ sizeof(struct color_counters));
+ if (!p_nt4ga_stat->mp_stat_structs_color) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ p_nt4ga_stat->mp_stat_structs_hb =
+ calloc(p_nt4ga_stat->mn_rx_host_buffers + p_nt4ga_stat->mn_tx_host_buffers,
+ sizeof(struct host_buffer_counters));
+ if (!p_nt4ga_stat->mp_stat_structs_hb) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ /*
+ * Separate memory allocation for VSWITCH and Inline to appropriate port counter structures.
+ */
+ if (p_nthw_stat->mb_is_vswitch) {
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx =
+ calloc(p_nthw_stat->m_nb_rx_host_buffers,
+ sizeof(struct port_counters_vswitch_v1));
+ if (!p_nt4ga_stat->virt.mp_stat_structs_port_rx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx =
+ calloc(p_nthw_stat->m_nb_tx_host_buffers,
+ sizeof(struct port_counters_vswitch_v1));
+ if (!p_nt4ga_stat->virt.mp_stat_structs_port_tx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ p_nt4ga_stat->flm_stat_ver = 0;
+ p_nt4ga_stat->mp_stat_structs_flm = NULL;
+ } else { /* Inline */
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx =
+ calloc(NUM_ADAPTER_PORTS_MAX,
+ sizeof(struct port_counters_v2));
+ if (!p_nt4ga_stat->cap.mp_stat_structs_port_rx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx =
+ calloc(NUM_ADAPTER_PORTS_MAX,
+ sizeof(struct port_counters_v2));
+ if (!p_nt4ga_stat->cap.mp_stat_structs_port_tx) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ p_nt4ga_stat->flm_stat_ver = 0;
+
+ p_nt4ga_stat->mp_stat_structs_flm =
+ calloc(1, sizeof(struct flm_counters_v1));
+ if (!p_nt4ga_stat->mp_stat_structs_flm) {
+ NT_LOG(ERR, GENERAL, "Cannot allocate mem (%s:%d).\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ }
+
+ memset(p_nt4ga_stat->a_stat_structs_color_base, 0,
+ sizeof(struct color_counters) * NT_MAX_COLOR_FLOW_STATS);
+ p_nt4ga_stat->last_timestamp = 0;
+
+ nthw_stat_trigger(p_nthw_stat);
+
+ return 0;
+}
+
+int nt4ga_stat_stop(struct adapter_info_s *p_adapter_info)
+{
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+
+ if (p_nt4ga_stat->virt.mp_stat_structs_port_rx) {
+ free(p_nt4ga_stat->virt.mp_stat_structs_port_rx);
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx = NULL;
+ }
+ if (p_nt4ga_stat->cap.mp_stat_structs_port_rx) {
+ free(p_nt4ga_stat->cap.mp_stat_structs_port_rx);
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx = NULL;
+ }
+
+ if (p_nt4ga_stat->virt.mp_stat_structs_port_tx) {
+ free(p_nt4ga_stat->virt.mp_stat_structs_port_tx);
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx = NULL;
+ }
+ if (p_nt4ga_stat->cap.mp_stat_structs_port_tx) {
+ free(p_nt4ga_stat->cap.mp_stat_structs_port_tx);
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx = NULL;
+ }
+
+ if (p_nt4ga_stat->mp_stat_structs_color) {
+ free(p_nt4ga_stat->mp_stat_structs_color);
+ p_nt4ga_stat->mp_stat_structs_color = NULL;
+ }
+
+ if (p_nt4ga_stat->mp_stat_structs_hb) {
+ free(p_nt4ga_stat->mp_stat_structs_hb);
+ p_nt4ga_stat->mp_stat_structs_hb = NULL;
+ }
+
+ if (p_nt4ga_stat->mp_stat_structs_flm) {
+ free(p_nt4ga_stat->mp_stat_structs_flm);
+ p_nt4ga_stat->mp_stat_structs_flm = NULL;
+ }
+
+ if (p_nt4ga_stat->p_stat_dma) {
+ nt_dma_free(p_nt4ga_stat->p_stat_dma);
+ p_nt4ga_stat->p_stat_dma = NULL;
+ }
+
+ return 0;
+}
+
+int nt4ga_stat_dump(struct adapter_info_s *p_adapter_info, FILE *pfh)
+{
+ const char *const p_adapter_id_str = p_adapter_info->mp_adapter_id_str;
+ fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
+ nt4ga_stat_t *p_nt4ga_stat = &p_adapter_info->nt4ga_stat;
+ int i;
+
+ for (i = 0; i < fpga_info->n_phy_ports; i++) {
+ fprintf(pfh,
+ "%s: Intf %02d: Rx: %016" PRIX64 " %016" PRIX64
+ " %016" PRIX64 " Tx: %016" PRIX64 " %016" PRIX64
+ " %016" PRIX64 "\n",
+ p_adapter_id_str, i, p_nt4ga_stat->a_port_rx_packets_total[i],
+ p_nt4ga_stat->a_port_rx_octets_total[i],
+ p_nt4ga_stat->a_port_rx_drops_total[i],
+ p_nt4ga_stat->a_port_tx_packets_total[i],
+ p_nt4ga_stat->a_port_tx_octets_total[i],
+ p_nt4ga_stat->a_port_tx_drops_total[i]);
+ }
+
+ return 0;
+}
+
+/* Called with stat mutex locked */
+static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual)
+{
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ const int n_rx_ports = p_nt4ga_stat->mn_rx_ports;
+ const int n_tx_ports = p_nt4ga_stat->mn_tx_ports;
+ int c, h, p;
+
+ if (!p_nthw_stat || !p_nt4ga_stat)
+ return -1;
+
+ if (p_nthw_stat->mn_stat_layout_version != 6) {
+ NT_LOG(ERR, ETHDEV, "HW STA module version not supported");
+ return -1;
+ }
+
+ /* RX ports */
+ for (c = 0; c < p_nthw_stat->m_nb_color_counters / 2; c++) {
+ const unsigned int tcp_flags_bits = 6U;
+ const uint32_t val_mask_dma = 0xffffffffULL >> tcp_flags_bits;
+
+ p_nt4ga_stat->mp_stat_structs_color[c].color_packets +=
+ p_stat_dma_virtual[c * 2] & val_mask_dma;
+ p_nt4ga_stat->mp_stat_structs_color[c].tcp_flags |=
+ (uint8_t)(p_stat_dma_virtual[c * 2] >>
+ (32 - tcp_flags_bits));
+ p_nt4ga_stat->mp_stat_structs_color[c].color_bytes +=
+ p_stat_dma_virtual[c * 2 + 1];
+ }
+
+ /* Move to Host buffer counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_color_counters;
+
+ /* Host buffer counters */
+ for (h = 0; h < p_nthw_stat->m_nb_rx_host_buffers; h++) {
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_packets +=
+ p_stat_dma_virtual[h * 8];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_packets +=
+ p_stat_dma_virtual[h * 8 + 1];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_packets +=
+ p_stat_dma_virtual[h * 8 + 2];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_packets +=
+ p_stat_dma_virtual[h * 8 + 3];
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_bytes +=
+ p_stat_dma_virtual[h * 8 + 4];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 5];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_bytes +=
+ p_stat_dma_virtual[h * 8 + 6];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 7];
+ }
+
+ /* Move to Rx Port counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_rx_hb_counters;
+
+ /* RX ports */
+ for (p = 0; p < n_rx_ports; p++) {
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].qos_drop_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 3];
+ p_nt4ga_stat->virt.mp_stat_structs_port_rx[p].qos_drop_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 4];
+
+ /* Rx totals */
+ p_nt4ga_stat->a_port_rx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters];
+ p_nt4ga_stat->a_port_rx_packets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1];
+ p_nt4ga_stat->a_port_rx_drops_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2];
+ }
+
+ /* Move to Tx Port counters */
+ p_stat_dma_virtual += n_rx_ports * p_nthw_stat->m_nb_rx_port_counters;
+
+ /* TX ports */
+ for (p = 0; p < n_tx_ports; p++) {
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].qos_drop_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 3];
+ p_nt4ga_stat->virt.mp_stat_structs_port_tx[p].qos_drop_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 4];
+
+ /* Tx totals */
+ p_nt4ga_stat->a_port_tx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters];
+ p_nt4ga_stat->a_port_tx_packets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1];
+ p_nt4ga_stat->a_port_tx_drops_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2];
+ }
+
+ return 0;
+}
+
+/* Called with stat mutex locked */
+static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+ uint32_t *p_stat_dma_virtual)
+{
+ nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+
+ const int n_rx_ports = p_nt4ga_stat->mn_rx_ports;
+ const int n_tx_ports = p_nt4ga_stat->mn_tx_ports;
+ int c, h, p;
+
+ if (!p_nthw_stat || !p_nt4ga_stat)
+ return -1;
+
+ if (p_nthw_stat->mn_stat_layout_version != 6) {
+ NT_LOG(ERR, ETHDEV, "HW STA module version not supported");
+ return -1;
+ }
+
+ /* RX ports */
+ for (c = 0; c < p_nthw_stat->m_nb_color_counters / 2; c++) {
+ p_nt4ga_stat->mp_stat_structs_color[c].color_packets +=
+ p_stat_dma_virtual[c * 2];
+ p_nt4ga_stat->mp_stat_structs_color[c].color_bytes +=
+ p_stat_dma_virtual[c * 2 + 1];
+ }
+
+ /* Move to Host buffer counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_color_counters;
+
+ for (h = 0; h < p_nthw_stat->m_nb_rx_host_buffers; h++) {
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_packets +=
+ p_stat_dma_virtual[h * 8];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_packets +=
+ p_stat_dma_virtual[h * 8 + 1];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_packets +=
+ p_stat_dma_virtual[h * 8 + 2];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_packets +=
+ p_stat_dma_virtual[h * 8 + 3];
+ p_nt4ga_stat->mp_stat_structs_hb[h].flush_bytes +=
+ p_stat_dma_virtual[h * 8 + 4];
+ p_nt4ga_stat->mp_stat_structs_hb[h].drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 5];
+ p_nt4ga_stat->mp_stat_structs_hb[h].fwd_bytes +=
+ p_stat_dma_virtual[h * 8 + 6];
+ p_nt4ga_stat->mp_stat_structs_hb[h].dbs_drop_bytes +=
+ p_stat_dma_virtual[h * 8 + 7];
+ }
+
+ /* Move to Rx Port counters */
+ p_stat_dma_virtual += p_nthw_stat->m_nb_rx_hb_counters;
+
+ /* RX ports */
+ for (p = 0; p < n_rx_ports; p++) {
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 0];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].broadcast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 1];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].multicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 2];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].unicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 3];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_alignment +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 4];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_code_violation +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 5];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_crc +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 6];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].undersize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 7];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].oversize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 8];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].fragments +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 9];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].jabbers_not_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 10];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].jabbers_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 11];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_64_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 12];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_65_to_127_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 13];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_128_to_255_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 14];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_256_to_511_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 15];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_512_to_1023_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 16];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_1024_to_1518_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 17];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_1519_to_2047_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 18];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_2048_to_4095_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 19];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p]
+ .pkts_4096_to_8191_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 20];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_8192_to_max_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].mac_drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_lr +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 23];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].duplicate +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 24];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_ip_chksum_error +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 25];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_udp_chksum_error +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 26];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_tcp_chksum_error +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 27];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_giant_undersize +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 28];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_baby_giant +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 29];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_not_isl_vlan_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 30];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 31];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_vlan +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 32];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 33];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 34];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 35];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_vlan_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 36];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_isl_vlan_mpls +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 37];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_no_filter +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 38];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_dedup_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 39];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_filter_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 40];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_overflow +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 41];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts_dbs_drop +=
+ p_nthw_stat->m_dbs_present ?
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters +
+ 42] :
+ 0;
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_no_filter +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 43];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_dedup_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 44];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_filter_drop +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 45];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_overflow +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 46];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].octets_dbs_drop +=
+ p_nthw_stat->m_dbs_present ?
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters +
+ 47] :
+ 0;
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_first_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 48];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_first_not_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 49];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_mid_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 50];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_mid_not_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 51];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_last_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 52];
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].ipft_last_not_hit +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 53];
+
+ /* Rx totals */
+ uint64_t new_drop_events_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 38] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 39] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 40] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 41] +
+ (p_nthw_stat->m_dbs_present ?
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters +
+ 42] :
+ 0);
+
+ uint64_t new_packets_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 7] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 8] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 9] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 10] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 11] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 12] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 13] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 14] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 15] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 16] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 17] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 18] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 19] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 20] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].drop_events +=
+ new_drop_events_sum;
+ p_nt4ga_stat->cap.mp_stat_structs_port_rx[p].pkts += new_packets_sum;
+
+ p_nt4ga_stat->a_port_rx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 0];
+ p_nt4ga_stat->a_port_rx_packets_total[p] += new_packets_sum;
+ p_nt4ga_stat->a_port_rx_drops_total[p] += new_drop_events_sum;
+ }
+
+ /* Move to Tx Port counters */
+ p_stat_dma_virtual += n_rx_ports * p_nthw_stat->m_nb_rx_port_counters;
+
+ for (p = 0; p < n_tx_ports; p++) {
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 0];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].broadcast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 1];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].multicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 2];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].unicast_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 3];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_alignment +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 4];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_code_violation +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 5];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_crc +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 6];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].undersize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 7];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].oversize_pkts +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 8];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].fragments +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 9];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].jabbers_not_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 10];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].jabbers_truncated +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 11];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_64_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 12];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_65_to_127_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 13];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_128_to_255_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 14];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_256_to_511_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 15];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_512_to_1023_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 16];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_1024_to_1518_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 17];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_1519_to_2047_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 18];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_2048_to_4095_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 19];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p]
+ .pkts_4096_to_8191_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 20];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_8192_to_max_octets +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].mac_drop_events +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 22];
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts_lr +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 23];
+
+ /* Tx totals */
+ uint64_t new_drop_events_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_rx_port_counters + 22];
+
+ uint64_t new_packets_sum =
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 7] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 8] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 9] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 10] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 11] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 12] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 13] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 14] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 15] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 16] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 17] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 18] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 19] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 20] +
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 21];
+
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].drop_events +=
+ new_drop_events_sum;
+ p_nt4ga_stat->cap.mp_stat_structs_port_tx[p].pkts += new_packets_sum;
+
+ p_nt4ga_stat->a_port_tx_octets_total[p] +=
+ p_stat_dma_virtual[p * p_nthw_stat->m_nb_tx_port_counters + 0];
+ p_nt4ga_stat->a_port_tx_packets_total[p] += new_packets_sum;
+ p_nt4ga_stat->a_port_tx_drops_total[p] += new_drop_events_sum;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.h b/drivers/net/ntnic/adapter/nt4ga_stat.h
new file mode 100644
index 0000000000..4a1067200c
--- /dev/null
+++ b/drivers/net/ntnic/adapter/nt4ga_stat.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT4GA_STAT_H_
+#define NT4GA_STAT_H_
+
+#include "nt_util.h"
+#include "common_adapter_defs.h"
+
+#define NT_MAX_COLOR_FLOW_STATS 0x400
+
+struct color_counters {
+ uint64_t color_packets;
+ uint64_t color_bytes;
+ uint8_t tcp_flags;
+};
+
+struct host_buffer_counters {
+ uint64_t flush_packets;
+ uint64_t drop_packets;
+ uint64_t fwd_packets;
+ uint64_t dbs_drop_packets;
+ uint64_t flush_bytes;
+ uint64_t drop_bytes;
+ uint64_t fwd_bytes;
+ uint64_t dbs_drop_bytes;
+};
+
+struct port_counters_v2 {
+ /* Rx/Tx common port counters */
+ uint64_t drop_events;
+ uint64_t pkts;
+ /* FPGA counters */
+ uint64_t octets;
+ uint64_t broadcast_pkts;
+ uint64_t multicast_pkts;
+ uint64_t unicast_pkts;
+ uint64_t pkts_alignment;
+ uint64_t pkts_code_violation;
+ uint64_t pkts_crc;
+ uint64_t undersize_pkts;
+ uint64_t oversize_pkts;
+ uint64_t fragments;
+ uint64_t jabbers_not_truncated;
+ uint64_t jabbers_truncated;
+ uint64_t pkts_64_octets;
+ uint64_t pkts_65_to_127_octets;
+ uint64_t pkts_128_to_255_octets;
+ uint64_t pkts_256_to_511_octets;
+ uint64_t pkts_512_to_1023_octets;
+ uint64_t pkts_1024_to_1518_octets;
+ uint64_t pkts_1519_to_2047_octets;
+ uint64_t pkts_2048_to_4095_octets;
+ uint64_t pkts_4096_to_8191_octets;
+ uint64_t pkts_8192_to_max_octets;
+ uint64_t mac_drop_events;
+ uint64_t pkts_lr;
+ /* Rx only port counters */
+ uint64_t duplicate;
+ uint64_t pkts_ip_chksum_error;
+ uint64_t pkts_udp_chksum_error;
+ uint64_t pkts_tcp_chksum_error;
+ uint64_t pkts_giant_undersize;
+ uint64_t pkts_baby_giant;
+ uint64_t pkts_not_isl_vlan_mpls;
+ uint64_t pkts_isl;
+ uint64_t pkts_vlan;
+ uint64_t pkts_isl_vlan;
+ uint64_t pkts_mpls;
+ uint64_t pkts_isl_mpls;
+ uint64_t pkts_vlan_mpls;
+ uint64_t pkts_isl_vlan_mpls;
+ uint64_t pkts_no_filter;
+ uint64_t pkts_dedup_drop;
+ uint64_t pkts_filter_drop;
+ uint64_t pkts_overflow;
+ uint64_t pkts_dbs_drop;
+ uint64_t octets_no_filter;
+ uint64_t octets_dedup_drop;
+ uint64_t octets_filter_drop;
+ uint64_t octets_overflow;
+ uint64_t octets_dbs_drop;
+ uint64_t ipft_first_hit;
+ uint64_t ipft_first_not_hit;
+ uint64_t ipft_mid_hit;
+ uint64_t ipft_mid_not_hit;
+ uint64_t ipft_last_hit;
+ uint64_t ipft_last_not_hit;
+};
+
+struct port_counters_vswitch_v1 {
+ /* Rx/Tx common port counters */
+ uint64_t octets;
+ uint64_t pkts;
+ uint64_t drop_events;
+ uint64_t qos_drop_octets;
+ uint64_t qos_drop_pkts;
+};
+
+struct flm_counters_v1 {
+ /* FLM 0.17 */
+ uint64_t current;
+ uint64_t learn_done;
+ uint64_t learn_ignore;
+ uint64_t learn_fail;
+ uint64_t unlearn_done;
+ uint64_t unlearn_ignore;
+ uint64_t auto_unlearn_done;
+ uint64_t auto_unlearn_ignore;
+ uint64_t auto_unlearn_fail;
+ uint64_t timeout_unlearn_done;
+ uint64_t rel_done;
+ uint64_t rel_ignore;
+ /* FLM 0.20 */
+ uint64_t prb_done;
+ uint64_t prb_ignore;
+ uint64_t sta_done;
+ uint64_t inf_done;
+ uint64_t inf_skip;
+ uint64_t pck_hit;
+ uint64_t pck_miss;
+ uint64_t pck_unh;
+ uint64_t pck_dis;
+ uint64_t csh_hit;
+ uint64_t csh_miss;
+ uint64_t csh_unh;
+ uint64_t cuc_start;
+ uint64_t cuc_move;
+};
+
+struct nt4ga_stat_s {
+ nthw_stat_t *mp_nthw_stat;
+ nthw_rmc_t *mp_nthw_rmc;
+ struct nt_dma_s *p_stat_dma;
+ uint32_t *p_stat_dma_virtual;
+ uint32_t n_stat_size;
+
+ uint64_t last_timestamp;
+
+ int mn_rx_host_buffers;
+ int mn_tx_host_buffers;
+
+ int mn_rx_ports;
+ int mn_tx_ports;
+
+ struct color_counters *mp_stat_structs_color;
+ /* For calculating increments between stats polls */
+ struct color_counters a_stat_structs_color_base[NT_MAX_COLOR_FLOW_STATS];
+
+ union {
+ /*Port counters for VSWITCH/inline */
+ struct {
+ struct port_counters_vswitch_v1 *mp_stat_structs_port_rx;
+ struct port_counters_vswitch_v1 *mp_stat_structs_port_tx;
+ } virt;
+ struct {
+ struct port_counters_v2 *mp_stat_structs_port_rx;
+ struct port_counters_v2 *mp_stat_structs_port_tx;
+ } cap;
+ };
+
+ struct host_buffer_counters *mp_stat_structs_hb;
+
+ int flm_stat_ver;
+ struct flm_counters_v1 *mp_stat_structs_flm;
+
+ /* Rx/Tx totals: */
+ uint64_t n_totals_reset_timestamp; /* timestamp for last totals reset */
+
+ uint64_t a_port_rx_octets_total[NUM_ADAPTER_PORTS_MAX];
+ /* Base is for calculating increments between statistics reads */
+ uint64_t a_port_rx_octets_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_rx_packets_total[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_rx_packets_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_rx_drops_total[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_rx_drops_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_tx_octets_total[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_tx_octets_base[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_tx_packets_base[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_tx_packets_total[NUM_ADAPTER_PORTS_MAX];
+
+ uint64_t a_port_tx_drops_base[NUM_ADAPTER_PORTS_MAX];
+ uint64_t a_port_tx_drops_total[NUM_ADAPTER_PORTS_MAX];
+};
+
+typedef struct nt4ga_stat_s nt4ga_stat_t;
+
+int nt4ga_stat_init(struct adapter_info_s *p_adapter_info);
+int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info);
+int nt4ga_stat_stop(struct adapter_info_s *p_adapter_info);
+
+int nt4ga_stat_dump(struct adapter_info_s *p_adapter_info, FILE *pfh);
+
+int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info,
+ nt4ga_stat_t *p_nt4ga_stat);
+
+#endif /* NT4GA_STAT_H_ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 65064f44ab..383ff15390 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -9,22 +9,39 @@ cflags += [
# includes
includes = [
include_directories('.'),
+ include_directories('adapter'),
include_directories('include'),
+ include_directories('nim'),
include_directories('ntlog/include'),
include_directories('ntutil/include'),
include_directories('nthw'),
include_directories('nthw/core'),
include_directories('nthw/supported'),
+ include_directories('sensors'),
+ include_directories('sensors/avr_sensors'),
+ include_directories('sensors/board_sensors'),
+ include_directories('sensors/nim_sensors'),
+ include_directories('sensors/ntavr'),
]
# all sources
sources = files(
+ 'adapter/nt4ga_adapter.c',
+ 'adapter/nt4ga_link.c',
+ 'adapter/nt4ga_link_100g.c',
+ 'adapter/nt4ga_pci_ta_tg.c',
+ 'adapter/nt4ga_stat.c',
+ 'nim/i2c_nim.c',
+ 'nim/nt_link_speed.c',
+ 'nim/qsfp_sensors.c',
+ 'nim/sfp_sensors.c',
'nthw/core/nthw_clock_profiles.c',
'nthw/core/nthw_fpga.c',
'nthw/core/nthw_fpga_nt200a0x.c',
'nthw/core/nthw_fpga_rst.c',
'nthw/core/nthw_fpga_rst9563.c',
'nthw/core/nthw_fpga_rst_nt200a0x.c',
+ 'nthw/core/nthw_gmf.c',
'nthw/core/nthw_gpio_phy.c',
'nthw/core/nthw_hif.c',
'nthw/core/nthw_iic.c',
@@ -34,6 +51,7 @@ sources = files(
'nthw/core/nthw_pci_ta.c',
'nthw/core/nthw_pci_wr_tg.c',
'nthw/core/nthw_pcie3.c',
+ 'nthw/core/nthw_rmc.c',
'nthw/core/nthw_sdc.c',
'nthw/core/nthw_si5340.c',
'nthw/core/nthw_spi_v3.c',
@@ -49,6 +67,12 @@ sources = files(
'nthw/supported/nthw_fpga_9563_055_024_0000.c',
'ntlog/ntlog.c',
'ntutil/nt_util.c',
+ 'sensors/avr_sensors/avr_sensors.c',
+ 'sensors/board_sensors/board_sensors.c',
+ 'sensors/board_sensors/tempmon.c',
+ 'sensors/nim_sensors/nim_sensors.c',
+ 'sensors/ntavr/ntavr.c',
+ 'sensors/sensors.c',
)
if is_variable('default_cflags')
diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c
new file mode 100644
index 0000000000..55740e6de6
--- /dev/null
+++ b/drivers/net/ntnic/nim/i2c_nim.c
@@ -0,0 +1,1974 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_drv.h"
+#include "i2c_nim.h"
+#include "ntlog.h"
+#include "nt_util.h"
+
+#include "nim_sensors.h"
+#include "sfp_p_registers.h"
+#include "qsfp_registers.h"
+#include "sfp_sensors.h"
+#include "qsfp_sensors.h"
+
+#include <assert.h>
+#include <string.h> /* memcmp, memset */
+
+/*
+ * Nim functions
+ */
+#define QSFP_SUP_LEN_INFO_LIN_ADDR 142 /* 5bytes */
+#define QSFP_TRANSMITTER_TYPE_LIN_ADDR 147 /* 1byte */
+#define QSFP_CONTROL_STATUS_LIN_ADDR 86
+#define QSFP_SOFT_TX_ALL_DISABLE_BITS 0x0F
+#define QSFP_SPEC_COMPLIANCE_CODES_ADDR 131 /* 8 bytes */
+#define QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR 192 /* 1 byte */
+#define NIM_READ false
+#define NIM_WRITE true
+#define NIM_PAGE_SEL_REGISTER 127
+#define nim_i2c_0xa0 0xA0 /* Basic I2C address */
+#define QSFP_VENDOR_NAME_LIN_ADDR 148 /* 16bytes */
+#define QSFP_VENDOR_PN_LIN_ADDR 168 /* 16bytes */
+#define QSFP_VENDOR_SN_LIN_ADDR 196 /* 16bytes */
+#define QSFP_VENDOR_DATE_LIN_ADDR 212 /* 8bytes */
+#define QSFP_VENDOR_REV_LIN_ADDR 184 /* 2bytes */
+#define QSFP_DMI_OPTION_LIN_ADDR 220
+
+#define QSFP_EXTENDED_IDENTIFIER 129
+#define QSFP_POWER_CLASS_BITS_1_4 0xC0
+#define QSFP_POWER_CLASS_BITS_5_7 0x03
+
+static bool sfp_is_supported_tri_speed_pn(char *prod_no)
+{
+ static const char *const pn_trispeed_list[] = {
+ "FCMJ-8521-3", "FCLF-8521-3", "FCLF8521P2BTL", "EOLT-C12-02A",
+ "AMXP-24RJS", "ABCU-5710RZ", "ABCU-5740RZ", "FCLF8522P2BTL",
+ };
+
+ /* Determine if copper SFP is supported 3-speed type */
+ for (size_t i = 0; i < ARRAY_SIZE(pn_trispeed_list); i++)
+ if (strcmp(pn_trispeed_list[i], prod_no) == 0)
+ return true;
+
+ return false;
+}
+
+static bool page_addressing(nt_nim_identifier_t id)
+{
+ switch (id) {
+ case NT_NIM_SFP_SFP_PLUS:
+ return false;
+ case NT_NIM_XFP:
+ return true;
+ case NT_NIM_QSFP:
+ case NT_NIM_QSFP_PLUS:
+ case NT_NIM_QSFP28:
+ return true;
+ default:
+ NT_LOG(DBG, ETHDEV, "%s: Unknown NIM identifier %d\n", __func__,
+ id);
+ return false;
+ }
+}
+
+nt_nim_identifier_t translate_nimid(const nim_i2c_ctx_t *ctx)
+{
+ return (nt_nim_identifier_t)ctx->nim_id;
+}
+
+static int nim_read_write_i2c_data(nim_i2c_ctx_p ctx, bool do_write,
+ uint16_t lin_addr, uint8_t i2c_addr,
+ uint8_t reg_addr, uint8_t seq_cnt, uint8_t *p_data)
+{
+ /* Divide I2C_Addr by 2 because nthw_iic_read/writeData multiplies by 2 */
+ const uint8_t i2c_devaddr = i2c_addr / 2U;
+ (void)lin_addr; /* Unused */
+
+ if (do_write)
+ return nthw_iic_write_data(&ctx->hwiic, i2c_devaddr, reg_addr,
+ seq_cnt, p_data);
+ else
+ return nthw_iic_read_data(&ctx->hwiic, i2c_devaddr, reg_addr,
+ seq_cnt, p_data);
+}
+
+/*
+ * ------------------------------------------------------------------------------
+ * Selects a new page for page addressing. This is only relevant if the NIM
+ * supports this. Since page switching can take substantial time the current page
+ * select is read and subsequently only changed if necessary.
+ * Important:
+ * XFP Standard 8077, Ver 4.5, Page 61 states that:
+ * If the host attempts to write a table select value which is not supported in
+ * a particular module, the table select byte will revert to 01h.
+ * This can lead to some surprising result that some pages seems to be duplicated.
+ * ------------------------------------------------------------------------------
+ */
+
+static int nim_setup_page(nim_i2c_ctx_p ctx, uint8_t page_sel)
+{
+ uint8_t curr_page_sel;
+
+ /* Read the current page select value */
+ if (nim_read_write_i2c_data(ctx, NIM_READ, NIM_PAGE_SEL_REGISTER,
+ nim_i2c_0xa0, NIM_PAGE_SEL_REGISTER,
+ sizeof(curr_page_sel), &curr_page_sel) != 0)
+ return -1;
+
+ /* Only write new page select value if necessary */
+ if (page_sel != curr_page_sel) {
+ if (nim_read_write_i2c_data(ctx, NIM_WRITE, NIM_PAGE_SEL_REGISTER,
+ nim_i2c_0xa0, NIM_PAGE_SEL_REGISTER,
+ sizeof(page_sel), &page_sel) != 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int nim_nim_read_write_data_lin(nim_i2c_ctx_p ctx, bool m_page_addressing,
+ uint16_t lin_addr, uint16_t length,
+ uint8_t *p_data, bool do_write)
+{
+ uint16_t i;
+ uint8_t reg_addr; /* The actual register address in I2C device */
+ uint8_t i2c_addr;
+ int block_size = 128; /* Equal to size of MSA pages */
+ int seq_cnt;
+ int max_seq_cnt = 1;
+ int multi_byte = 1; /* One byte per I2C register is default */
+ const int m_port_no = ctx->instance - 2;
+
+ if (lin_addr >= SFP_PHY_LIN_ADDR) {
+ /*
+ * This represents an address space at I2C address 0xAC for SFP modules
+ * containing a PHY. (eg 1G Copper SFP). Each register is 16bit and is
+ * accessed MSByte first and this reading latches the LSByte that is
+ * subsequently read from the same address.
+ */
+ multi_byte = 2;
+ max_seq_cnt = 2;
+
+ /* Test for correct multibyte access */
+ if ((length % multi_byte) != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Uneven length (%d) for address range [0x%X..0x%X].",
+ m_port_no, __func__, length, SFP_PHY_LIN_ADDR,
+ SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG - 1);
+ return -1;
+ }
+
+ if (lin_addr + (length / 2) >
+ SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Access above address range [0x%X..0x%X].",
+ m_port_no, __func__, SFP_PHY_LIN_ADDR,
+ SFP_PHY_LIN_ADDR + SFP_PHY_LIN_RNG - 1);
+ return -1;
+ }
+ } else if (lin_addr + length > 128) {
+ /*
+ * Page addressing could be relevant since the last byte is outside the
+ * basic range so check if it is enabled
+ */
+ if (m_page_addressing) {
+ /* Crossing into the PHY address range is not allowed */
+ if (lin_addr + length > SFP_PHY_LIN_ADDR) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Access above paged address range [0..0x%X].",
+ m_port_no, __func__, SFP_PHY_LIN_ADDR);
+ return -1;
+ }
+ } else {
+ /* Access outside 0xA2 address range not allowed */
+ if (lin_addr + length > 512) {
+ NT_LOG(ERR, ETHDEV,
+ "Port %d: %s: Access above address range [0..511].",
+ m_port_no, __func__);
+ return -1;
+ }
+ }
+ }
+ /* No missing else here - all devices supports access to address [0..127] */
+
+ for (i = 0; i < length;) {
+ bool use_page_select = false;
+
+ /*
+ * Find out how much can be read from the current block in case of
+ * single byte access
+ */
+ if (multi_byte == 1)
+ max_seq_cnt = block_size - (lin_addr % block_size);
+
+ if (m_page_addressing) {
+ if (lin_addr >= 128) { /* Only page setup above this address */
+ use_page_select = true;
+
+ /* Map to [128..255] of 0xA0 device */
+ reg_addr = (uint8_t)(block_size +
+ (lin_addr % block_size));
+ } else {
+ reg_addr = (uint8_t)lin_addr;
+ }
+ i2c_addr = nim_i2c_0xa0; /* Base I2C address */
+ } else {
+ if (lin_addr >= SFP_PHY_LIN_ADDR) {
+ /* Map to address [0..31] of 0xAC device */
+ reg_addr = (uint8_t)(lin_addr - SFP_PHY_LIN_ADDR);
+ i2c_addr = nim_i2c_0xac;
+ } else if (lin_addr >= 256) {
+ /* Map to address [0..255] of 0xA2 device */
+ reg_addr = (uint8_t)(lin_addr - 256);
+ i2c_addr = nim_i2c_0xa2;
+ } else {
+ reg_addr = (uint8_t)lin_addr;
+ i2c_addr = nim_i2c_0xa0; /* Base I2C address */
+ }
+ }
+
+ /* Now actually do the reading/writing */
+ seq_cnt = length - i; /* Number of remaining bytes */
+
+ if (seq_cnt > max_seq_cnt)
+ seq_cnt = max_seq_cnt;
+
+ /*
+ * Read a number of bytes without explicitly specifying a new address.
+ * This can speed up I2C access since automatic incrementation of the
+ * I2C device internal address counter can be used. It also allows
+ * a HW implementation, that can deal with block access.
+ * Furthermore it also allows for access to data that must be accessed
+ * as 16bit words reading two bytes at each address eg PHYs.
+ */
+ if (use_page_select) {
+ if (nim_setup_page(ctx,
+ (uint8_t)((lin_addr / 128) - 1)) != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Cannot set up page for linear address %u\n",
+ __func__, lin_addr);
+ return -1;
+ }
+ }
+ if (nim_read_write_i2c_data(ctx, do_write, lin_addr, i2c_addr,
+ reg_addr, (uint8_t)seq_cnt,
+ p_data) != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Call to NIM_ReadWriteI2cData failed\n",
+ __func__);
+ return -1;
+ }
+
+ p_data += seq_cnt;
+ i = (uint16_t)(i + seq_cnt);
+ lin_addr = (uint16_t)(lin_addr + (seq_cnt / multi_byte));
+ }
+ return 0;
+}
+
+int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
+ void *data)
+{
+ return nim_nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id),
+ lin_addr, length, data, NIM_READ);
+}
+
+static int write_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
+ void *data)
+{
+ return nim_nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id),
+ lin_addr, length, data, NIM_WRITE);
+}
+
+/* Read and return a single byte */
+static uint8_t read_byte(nim_i2c_ctx_p ctx, uint16_t addr)
+{
+ uint8_t data;
+
+ read_data_lin(ctx, addr, sizeof(data), &data);
+ return data;
+}
+
+static int nim_read_id(nim_i2c_ctx_t *ctx)
+{
+ /* We are only reading the first byte so we don't care about pages here. */
+ const bool use_page_addressing = false;
+
+ if (nim_nim_read_write_data_lin(ctx, use_page_addressing,
+ NIM_IDENTIFIER_ADDR, sizeof(ctx->nim_id),
+ &ctx->nim_id, NIM_READ) != 0)
+ return -1;
+ return 0;
+}
+
+static int i2c_nim_common_construct(nim_i2c_ctx_p ctx)
+{
+ ctx->nim_id = 0;
+ int res = nim_read_id(ctx);
+
+ if (res) {
+ NT_LOG(ERR, PMD, "Can't read NIM id.");
+ return res;
+ }
+ memset(ctx->vendor_name, 0, sizeof(ctx->vendor_name));
+ memset(ctx->prod_no, 0, sizeof(ctx->prod_no));
+ memset(ctx->serial_no, 0, sizeof(ctx->serial_no));
+ memset(ctx->date, 0, sizeof(ctx->date));
+ memset(ctx->rev, 0, sizeof(ctx->rev));
+
+ ctx->content_valid = false;
+ memset(ctx->len_info, 0, sizeof(ctx->len_info));
+ ctx->pwr_level_req = 0;
+ ctx->pwr_level_cur = 0;
+ ctx->avg_pwr = false;
+ ctx->tx_disable = false;
+ ctx->lane_idx = -1;
+ ctx->lane_count = 1;
+ ctx->options = 0;
+ return 0;
+}
+
+static int nim_read_vendor_info(nim_i2c_ctx_p ctx, uint16_t addr,
+ uint8_t max_len, char *p_data);
+
+#define XSFP_READ_VENDOR_INFO(x) \
+ static void x##sfp_read_vendor_info(nim_i2c_ctx_t *ctx) \
+ { \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_NAME_LIN_ADDR, \
+ sizeof(ctx->vendor_name), \
+ ctx->vendor_name); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_PN_LIN_ADDR, \
+ sizeof(ctx->prod_no), ctx->prod_no); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_SN_LIN_ADDR, \
+ sizeof(ctx->serial_no), ctx->serial_no); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_DATE_LIN_ADDR, \
+ sizeof(ctx->date), ctx->date); \
+ nim_read_vendor_info(ctx, Q##SFP_VENDOR_REV_LIN_ADDR, \
+ (uint8_t)(sizeof(ctx->rev) - 2), \
+ ctx->rev); /*OBS Only two bytes*/ \
+ }
+
+XSFP_READ_VENDOR_INFO()
+XSFP_READ_VENDOR_INFO(q)
+
+static int sfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state)
+{
+ int res;
+
+ assert(ctx && state);
+ assert(ctx->nim_id != NT_NIM_UNKNOWN && "Nim is not initialized");
+
+ (void)memset(state, 0, sizeof(*state));
+
+ res = nthw_iic_read_data(&ctx->hwiic, ctx->devaddr, SFP_BIT_RATE_ADDR,
+ sizeof(state->br), &state->br);
+ return res;
+}
+
+static int qsfp_nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state)
+{
+ int res = 0; /* unused due to no readings from HW */
+
+ assert(ctx && state);
+ assert(ctx->nim_id != NT_NIM_UNKNOWN && "Nim is not initialized");
+
+ (void)memset(state, 0, sizeof(*state));
+
+ switch (ctx->nim_id) {
+ case 12U:
+ state->br = 10U; /* QSFP: 4 x 1G = 4G */
+ break;
+ case 13U:
+ state->br = 103U; /* QSFP+: 4 x 10G = 40G */
+ break;
+ case 17U:
+ state->br = 255U; /* QSFP28: 4 x 25G = 100G */
+ break;
+ default:
+ NT_LOG(INF, PMD,
+ "%s:%d nim_id = %u is not an QSFP/QSFP+/QSFP28 module\n",
+ __func__, __LINE__, ctx->nim_id);
+ res = -1;
+ }
+
+ return res;
+}
+
+int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state)
+{
+ if (translate_nimid(ctx) == NT_NIM_SFP_SFP_PLUS)
+ return sfp_nim_state_build(ctx, state);
+ else
+ return qsfp_nim_state_build(ctx, state);
+}
+
+const char *nim_id_to_text(uint8_t nim_id)
+{
+ switch (nim_id) {
+ case 0x0:
+ return "UNKNOWN";
+ case 0x1:
+ return "GBIC";
+ case 0x2:
+ return "FIXED";
+ case 0x3:
+ return "SFP/SFP+";
+ case 0x04:
+ return "300 pin XBI";
+ case 0x05:
+ return "XEN-PAK";
+ case 0x06:
+ return "XFP";
+ case 0x07:
+ return "XFF";
+ case 0x08:
+ return "XFP-E";
+ case 0x09:
+ return "XPAK";
+ case 0x0A:
+ return "X2";
+ case 0x0B:
+ return "DWDM";
+ case 0x0C:
+ return "QSFP";
+ case 0x0D:
+ return "QSFP+";
+ case 0x11:
+ return "QSFP28";
+ case 0x12:
+ return "CFP4";
+ default:
+ return "ILLEGAL!";
+ }
+}
+
+/*
+ * Read and check the validity of the NIM basic data.
+ * This will also preload the cache
+ */
+static void check_content_valid(nim_i2c_ctx_p ctx, uint16_t start_addr)
+{
+ uint32_t sum = 0;
+ uint8_t buf[96];
+
+ read_data_lin(ctx, start_addr, sizeof(buf), &buf[0]);
+
+ for (int i = 0; i < 63; i++)
+ sum += buf[i];
+
+ if ((sum & 0xFF) != buf[63]) {
+ ctx->content_valid = false;
+ } else {
+ sum = 0;
+
+ for (int i = 64; i < 95; i++)
+ sum += buf[i];
+
+ ctx->content_valid = ((sum & 0xFF) == buf[95]);
+ }
+ if (ctx->content_valid)
+ NT_LOG(DBG, NTHW, "NIM content validation passed");
+ else
+ NT_LOG(WRN, NTHW, "NIM content validation failed");
+}
+
+/*
+ * Set/reset Soft Rate__select bits (RS0 & RS1)
+ */
+static void nim_sfp_set_rate_sel_high(nim_i2c_ctx_p ctx, bool rx_rate_high,
+ bool tx_rate_high)
+{
+ const bool m_page_addressing = page_addressing(ctx->nim_id);
+ uint8_t data;
+
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_CONTROL_STATUS_LIN_ADDR, sizeof(data),
+ &data, NIM_READ);
+
+ if (rx_rate_high)
+ data |= SFP_SOFT_RATE0_BIT;
+ else
+ data &= (uint8_t)~(SFP_SOFT_RATE0_BIT);
+
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_CONTROL_STATUS_LIN_ADDR, sizeof(data),
+ &data, NIM_WRITE);
+
+ /* Read the Extended Status/Control and set/reset Soft RS1 bit */
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(data),
+ &data, NIM_READ);
+
+ if (tx_rate_high)
+ data |= SFP_SOFT_RATE1_BIT;
+ else
+ data &= (uint8_t)~(SFP_SOFT_RATE1_BIT);
+
+ nim_nim_read_write_data_lin(ctx, m_page_addressing,
+ SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(data),
+ &data, NIM_WRITE);
+}
+
+/*
+ * Some NIM modules requires some changes to a rate setting.
+ */
+static int nim_sfp_set_rate_select(nim_i2c_ctx_p ctx, nt_link_speed_t speed)
+{
+ if ((speed & (int)ctx->speed_mask) == 0) {
+ char buf[128];
+
+ NT_LOG(ERR, ETHDEV, "%s - Speed (%s) not within SpeedMask (%s)",
+ nt_translate_link_speed(speed),
+ nt_translate_link_speed_mask(ctx->speed_mask, buf,
+ sizeof(buf)));
+ return -1;
+ }
+
+ if (ctx->specific_u.sfp.dual_rate) {
+ uint64_t req_speed = nt_get_link_speed(speed);
+ uint64_t other_speed =
+ nt_get_link_speed((nt_link_speed_t)(ctx->speed_mask ^ (uint32_t)speed));
+ bool rate_high = req_speed > other_speed;
+ /*
+ * Do this both for 1/10 and 10/25. For Sfp28 it is not known if
+ * this is necessary but it is believed not to do any harm.
+ */
+ nim_sfp_set_rate_sel_high(ctx, rate_high, rate_high);
+ }
+ return 0;
+}
+
+/*
+ * Disable TX laser.
+ */
+int nim_sfp_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable)
+{
+ int res;
+ uint8_t value;
+ const bool pg_addr = page_addressing(ctx->nim_id);
+
+ res = nim_nim_read_write_data_lin(ctx, pg_addr, SFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_READ);
+ if (res != 0)
+ return res;
+
+ if (disable)
+ value |= SFP_SOFT_TX_DISABLE_BIT;
+ else
+ value &= (uint8_t)~SFP_SOFT_TX_DISABLE_BIT;
+
+ res = nim_nim_read_write_data_lin(ctx, pg_addr, SFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_WRITE);
+
+ return res;
+}
+
+/*
+ * Disable laser for specific lane or all lanes
+ */
+int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable,
+ int lane_idx)
+{
+ uint8_t value;
+ uint8_t mask;
+ const bool pg_addr = page_addressing(ctx->nim_id);
+
+ if (lane_idx < 0) /* If no lane is specified then all lanes */
+ mask = QSFP_SOFT_TX_ALL_DISABLE_BITS;
+ else
+ mask = (uint8_t)(1U << lane_idx);
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_READ) != 0)
+ return -1;
+
+ if (disable)
+ value |= mask;
+ else
+ value &= (uint8_t)~mask;
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_CONTROL_STATUS_LIN_ADDR,
+ sizeof(value), &value, NIM_WRITE) != 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * Read vendor information at a certain address. Any trailing whitespace is
+ * removed and a missing string termination in the NIM data is handled.
+ */
+static int nim_read_vendor_info(nim_i2c_ctx_p ctx, uint16_t addr,
+ uint8_t max_len, char *p_data)
+{
+ const bool pg_addr = page_addressing(ctx->nim_id);
+ int i;
+ /* Subtract "1" from maxLen that includes a terminating "0" */
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, addr, (uint8_t)(max_len - 1),
+ (uint8_t *)p_data, NIM_READ) != 0)
+ return -1;
+
+ /* Terminate at first found white space */
+ for (i = 0; i < max_len - 1; i++) {
+ if (*p_data == ' ' || *p_data == '\n' || *p_data == '\t' ||
+ *p_data == '\v' || *p_data == '\f' || *p_data == '\r') {
+ *p_data = '\0';
+ return 0;
+ }
+
+ p_data++;
+ }
+
+ /*
+ * Add line termination as the very last character, if it was missing in the
+ * NIM data
+ */
+ *p_data = '\0';
+ return 0;
+}
+
+/*
+ * Import length info in various units from NIM module data and convert to meters
+ */
+static void nim_import_len_info(nim_i2c_ctx_p ctx, uint8_t *p_nim_len_info,
+ uint16_t *p_nim_units)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->len_info); i++)
+ if (*(p_nim_len_info + i) == 255) {
+ ctx->len_info[i] = 65535;
+ } else {
+ uint32_t len = *(p_nim_len_info + i) * *(p_nim_units + i);
+
+ if (len > 65535)
+ ctx->len_info[i] = 65535;
+ else
+ ctx->len_info[i] = (uint16_t)len;
+ }
+}
+
+static int qsfpplus_read_basic_data(nim_i2c_ctx_t *ctx)
+{
+ const bool pg_addr = page_addressing(ctx->nim_id);
+ uint8_t options;
+ uint8_t value;
+ uint8_t nim_len_info[5];
+ uint16_t nim_units[5] = { 1000, 2, 1, 1,
+ 1
+ }; /* QSFP MSA units in meters */
+ const char *yes_no[2] _unused = { "No", "Yes" };
+
+ NT_LOG(DBG, ETHDEV, "Instance %d: NIM id: %s (%d)\n", ctx->instance,
+ nim_id_to_text(ctx->nim_id), ctx->nim_id);
+
+ /* Read DMI options */
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_DMI_OPTION_LIN_ADDR,
+ sizeof(options), &options, NIM_READ) != 0)
+ return -1;
+ ctx->avg_pwr = options & QSFP_DMI_AVG_PWR_BIT;
+ NT_LOG(DBG, ETHDEV,
+ "Instance %d: NIM options: (DMI: Yes, AvgPwr: %s)\n",
+ ctx->instance, yes_no[ctx->avg_pwr]);
+
+ qsfp_read_vendor_info(ctx);
+ NT_LOG(DBG, PMD,
+ "Instance %d: NIM info: (Vendor: %s, PN: %s, SN: %s, Date: %s, Rev: %s)\n",
+ ctx->instance, ctx->vendor_name, ctx->prod_no, ctx->serial_no,
+ ctx->date, ctx->rev);
+
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_SUP_LEN_INFO_LIN_ADDR,
+ sizeof(nim_len_info), nim_len_info,
+ NIM_READ) != 0)
+ return -1;
+
+ /*
+ * Returns supported length information in meters for various fibers as 5 indivi-
+ * dual values: [SM(9um), EBW(50um), MM(50um), MM(62.5um), Copper]
+ * If no length information is available for a certain entry, the returned value
+ * will be zero. This will be the case for SFP modules - EBW entry.
+ * If the MSBit is set the returned value in the lower 31 bits indicates that the
+ * supported length is greater than this.
+ */
+
+ nim_import_len_info(ctx, nim_len_info, nim_units);
+
+ /* Read required power level */
+ if (nim_nim_read_write_data_lin(ctx, pg_addr, QSFP_EXTENDED_IDENTIFIER,
+ sizeof(value), &value, NIM_READ) != 0)
+ return -1;
+
+ /*
+ * Get power class according to SFF-8636 Rev 2.7, Table 6-16, Page 43:
+ * If power class >= 5 setHighPower must be called for the module to be fully
+ * functional
+ */
+ if ((value & QSFP_POWER_CLASS_BITS_5_7) == 0) {
+ /* NIM in power class 1 - 4 */
+ ctx->pwr_level_req =
+ (uint8_t)(((value & QSFP_POWER_CLASS_BITS_1_4) >> 6) +
+ 1);
+ } else {
+ /* NIM in power class 5 - 7 */
+ ctx->pwr_level_req =
+ (uint8_t)((value & QSFP_POWER_CLASS_BITS_5_7) + 4);
+ }
+
+ return 0;
+}
+
+/*
+ * If true the user must actively select the desired rate. If false the module
+ * however can still support several rates without the user is required to select
+ * one of them. Supported rates must then be deduced from the product number.
+ * SFF-8636, Rev 2.10a:
+ * p40: 6.2.7 Rate Select
+ * p85: A.2 Rate Select
+ */
+static bool qsfp28_is_speed_selection_enabled(nim_i2c_ctx_p ctx)
+{
+ const uint8_t options_reg_addr = 195;
+ const uint8_t enh_options_reg_addr = 221;
+
+ uint8_t rate_select_ena = (read_byte(ctx, options_reg_addr) >> 5) &
+ 0x01; /* bit: 5 */
+
+ if (rate_select_ena == 0)
+ return false;
+
+ uint8_t rate_select_type = (read_byte(ctx, enh_options_reg_addr) >> 2) &
+ 0x03; /* bit 3..2 */
+
+ if (rate_select_type != 2) {
+ NT_LOG(DBG, NTHW, "NIM has unhandled rate select type (%d)",
+ rate_select_type);
+ return false;
+ }
+
+ return true; /* When true selectRate() can be used */
+}
+
+/*
+ * Select a speed that is supported for a multi rate module. The possible speed
+ * values must be obtained by setSpeedMask().
+ * Currently rate selection is assumed to be between 40Gb (10GBd) and 100G (25Gbd)
+ * The value in () are the baud rates for PAM-4 and are valid for extended rate
+ * select, version 2.
+ */
+static int qsfp28_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed)
+{
+ const uint8_t rx_rate_sel_addr = 87;
+ const uint8_t tx_rate_sel_addr = 88;
+
+ if (ctx->lane_idx < 0) {
+ /*
+ * All lanes together
+ * The condition below indicates that the module supports rate selection
+ */
+ if (ctx->speed_mask == (uint32_t)(NT_LINK_SPEED_40G | NT_LINK_SPEED_100G)) {
+ uint16_t data;
+
+ if (speed == NT_LINK_SPEED_100G) {
+ data = 0xAAAA;
+ } else if (speed == NT_LINK_SPEED_40G) {
+ data = 0x0000;
+ } else {
+ NT_LOG(ERR, NTHW, "Unhandled NIM speed (%s).",
+ nt_translate_link_speed(speed));
+ return -1;
+ }
+
+ /* Set speed for Rx and Tx on all lanes */
+ write_data_lin(ctx, rx_rate_sel_addr, sizeof(data), &data);
+ write_data_lin(ctx, tx_rate_sel_addr, sizeof(data), &data);
+ } else {
+ /* For ordinary modules only this speed is supported */
+ if (speed != NT_LINK_SPEED_100G) {
+ NT_LOG(ERR, NTHW,
+ "NIM cannot select this speed (%s).",
+ nt_translate_link_speed(speed));
+ return -1;
+ }
+ }
+ } else {
+ /*
+ * Individual lanes
+ * Currently we do not support QSFP28 modules that support rate selection when
+ * running on individual lanes but that might change in the future
+ */
+ if (speed != NT_LINK_SPEED_25G) {
+ NT_LOG(ERR, NTHW,
+ "NIM cannot select this lane speed (%s).",
+ nt_translate_link_speed(speed));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int nim_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed)
+{
+ if (translate_nimid(ctx) == NT_NIM_SFP_SFP_PLUS) {
+ return nim_sfp_set_rate_select(ctx, speed);
+ } else if (translate_nimid(ctx) == NT_NIM_QSFP28) {
+ if (qsfp28_is_speed_selection_enabled(ctx))
+ return qsfp28_set_link_speed(ctx, speed);
+
+ return 0; /* NIM picks up the speed automatically */
+ }
+ NT_LOG(ERR, ETHDEV,
+ "%s nim is not supported for adjustable link speed.",
+ nim_id_to_text(ctx->nim_id));
+ return -1;
+}
+
+/*
+ * Reads basic vendor and DMI information.
+ */
+static int sfp_read_basic_data(nim_i2c_ctx_p ctx)
+{
+ const char *yes_no[2] _unused = { "No", "Yes" };
+
+ check_content_valid(ctx, 0);
+ NT_LOG(DBG, PMD, "NIM id: %s (%d)", nim_id_to_text(ctx->nim_id),
+ ctx->nim_id);
+
+ /* Read DMI options */
+ uint8_t options;
+
+ read_data_lin(ctx, SFP_DMI_OPTION_LIN_ADDR, sizeof(options), &options);
+ ctx->avg_pwr = options & SFP_DMI_AVG_PWR_BIT;
+ ctx->dmi_supp = options & SFP_DMI_IMPL_BIT;
+ ctx->specific_u.sfp.ext_cal = options & SFP_DMI_EXT_CAL_BIT;
+ ctx->specific_u.sfp.addr_chg = options & SFP_DMI_ADDR_CHG_BIT;
+
+ if (ctx->dmi_supp) {
+ ctx->options |=
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ }
+
+ if (ctx->dmi_supp) {
+ NT_LOG(DBG, PMD,
+ "NIM options: (DMI: %s, AvgPwr: %s, ExtCal: %s, AddrChg: %s)",
+ yes_no[ctx->dmi_supp], yes_no[ctx->avg_pwr],
+ yes_no[ctx->specific_u.sfp.ext_cal],
+ yes_no[ctx->specific_u.sfp.addr_chg]);
+ } else {
+ NT_LOG(DBG, PMD, "NIM options: DMI not supported");
+ }
+ /* Read enhanced options */
+ read_data_lin(ctx, SFP_ENHANCED_OPTIONS_LIN_ADDR, sizeof(options),
+ &options);
+ ctx->tx_disable = options & SFP_SOFT_TX_DISABLE_IMPL_BIT;
+
+ if (ctx->tx_disable)
+ ctx->options |= (1 << NIM_OPTION_TX_DISABLE);
+
+ sfp_read_vendor_info(ctx);
+
+ uint8_t nim_len_info[5];
+
+ read_data_lin(ctx, SFP_SUP_LEN_INFO_LIN_ADDR, sizeof(nim_len_info),
+ nim_len_info);
+
+ /*
+ * Returns supported length information in meters for various fibers as 5 indivi-
+ * dual values: [SM(9um), EBW(50um), MM(50um), MM(62.5um), Copper]
+ * If no length information is available for a certain entry, the returned value
+ * will be zero. This will be the case for SFP modules - EBW entry.
+ * If the MSBit is set the returned value in the lower 31 bits indicates that the
+ * supported length is greater than this.
+ */
+
+ uint16_t nim_units[5] = { 1000, 100, 10, 10,
+ 1
+ }; /* SFP MSA units in meters */
+ nim_import_len_info(ctx, &nim_len_info[0], &nim_units[0]);
+
+ if (ctx->len_info[0] != 0 || ctx->len_info[1] != 0) {
+ /*
+ * Make sure that for SFP modules the supported length for SM fibers
+ * which is given in both km and 100m units is are equal to the greatest
+ * value.
+ * The following test will also be valid if NIM_LEN_MAX has been set!
+ */
+ if (ctx->len_info[1] > ctx->len_info[0])
+ ctx->len_info[0] = ctx->len_info[1];
+
+ ctx->len_info[1] = 0; /* EBW is not supported for SFP */
+ }
+
+ read_data_lin(ctx, SFP_OPTION0_LIN_ADDR, sizeof(options), &options);
+
+ if (options & SFP_POWER_LEVEL2_REQ_BIT)
+ ctx->pwr_level_req = 2;
+ else
+ ctx->pwr_level_req = 1;
+
+ ctx->pwr_level_cur = 1;
+
+ if (ctx->pwr_level_req == 2) {
+ /* Read the current power level status */
+ read_data_lin(ctx, SFP_EXT_CTRL_STAT0_LIN_ADDR, sizeof(options),
+ &options);
+
+ if (options & SFP_POWER_LEVEL2_GET_BIT)
+ ctx->pwr_level_cur = 2;
+ else
+ ctx->pwr_level_cur = 1;
+ }
+ return 0;
+}
+
+/*
+ * Read the vendor product number and from this determine which QSFP DMI options
+ * that are present. This list also covers QSFP28 modules.
+ * This function should be used if automatic detection does not work.
+ */
+static bool qsfpplus_get_qsfp_options_from_pn(nim_i2c_ctx_p ctx)
+{
+ if (strcmp(ctx->prod_no, "FTL410QE1C") == 0) {
+ /* FINISAR FTL410QE1C, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_TX_BIAS) | (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FTL410QE2C") == 0) {
+ /* FINISAR FTL410QE2C, QSFP+ */
+ ctx->options = (1 << NIM_OPTION_TEMP) |
+ (1 << NIM_OPTION_SUPPLY);
+ } else if (strcmp(ctx->prod_no, "FTL4C1QE1C") == 0) {
+ /* FINISAR FTL4C1QE1C, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-79E4Z") == 0) {
+ /*
+ * AFBR-79E4Z: The digital diagnostic accuracy is not guaranteed so only
+ * the mandatory temperature sensor is made available (although it will
+ * also be inaccurate)
+ */
+ /* AVAGO 79E4Z, QSFP+ */
+ ctx->options = (1 << NIM_OPTION_TEMP);
+ } else if (strcmp(ctx->prod_no, "AFBR-79E4Z-D") == 0) {
+ /* AVAGO 79E4Z-D, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-79EQDZ") == 0) {
+ /* AVAGO 79EQDZ, QSFP+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-79EBRZ") == 0) {
+ /*
+ * Avago RxOnly BiDi NIM
+ * No sensors available not even the normally mandatory temp sensor and this
+ * is ok since the temp sensor is not mandatory on active optical modules
+ */
+ /* SFF-8436_rev4.1, p67 */
+ ctx->options = (1 << NIM_OPTION_RX_ONLY);
+ } else if (strcmp(ctx->prod_no, "AFBR-79EBPZ-NU1") == 0) {
+ /*
+ * Avago RxTx BiDi NIM
+ * No sensors available not even the normally mandatory temp sensor and this
+ * is ok since the temp sensor is not mandatory on active optical modules
+ */
+ ctx->options = 0;
+ } else if (strcmp(ctx->prod_no, "AFBR-79EBPZ") == 0) {
+ /*
+ * Avago RxTx BiDi NIM
+ * No sensors available not even the normally mandatory temp sensor and this
+ * is ok since the temp sensor is not mandatory on active optical modules
+ */
+ ctx->options = 0;
+ } else if (strcmp(ctx->prod_no, "AFBR-89CDDZ") == 0) {
+ /* AVAGO 89CDDZ, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-89BDDZ") == 0) {
+ /* AVAGO 89BDDZ, QSFP28, BiDi */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "AFBR-89BRDZ") == 0) {
+ /*
+ * AVAGO 89BRDZ, QSFP28, BiDi, RxOnly
+ * but sensors have been set as above except for Tx sensors
+ */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_RX_ONLY);
+ /*
+ * According to mail correspondence AFBR-89BRDZ is a RxOnly version of
+ * AFBR-89BDDZ with lasers default off.
+ * The lasers can be turned on however but should probably not because the
+ * receivers might be degraded, and this is the cause for selling them as RxOnly.
+ */
+ } else if (strcmp(ctx->prod_no, "SQF1000L4LNGG01P") == 0) {
+ /* Sumitomo SQF1000L4LNGG01P, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1000L4LNGG01B") == 0) {
+ /* Sumitomo SQF1000L4LNGG01B, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1001L4LNGG01P") == 0) {
+ /* Sumitomo SQF1001L4LNGG01P, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1001L4LNGG01B") == 0) {
+ /* Sumitomo SQF1001L4LNGG01B, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "SQF1002L4LNGG01B") == 0) {
+ /* Sumitomo SQF1002L4LNGG01B, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FIM37700/171") == 0) {
+ /* Fujitsu FIM37700/171, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FIM37700/172") == 0) {
+ /* Fujitsu FIM37700/172, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "TR-FC85S-NVS") == 0) {
+ /* InnoLight TR-FC85S-NVS, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "TR-FC13L-NVS") == 0) {
+ /* InnoLight TR-FC13L-NVS, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FTLC9551REPM") == 0) {
+ /* Finisar FTLC9551REPM, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else if (strcmp(ctx->prod_no, "FTLC9558REPM") == 0) {
+ /* Finisar FTLC9558REPM, QSFP28 */
+ ctx->options =
+ (1 << NIM_OPTION_TEMP) | (1 << NIM_OPTION_SUPPLY) |
+ (1 << NIM_OPTION_RX_POWER) | (1 << NIM_OPTION_TX_BIAS) |
+ (1 << NIM_OPTION_TX_POWER);
+ } else {
+ /*
+ * DO NOTE: The temperature sensor is not mandatory on active/passive copper
+ * and active optical modules
+ */
+ ctx->options = (1 << NIM_OPTION_TEMP);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Try to figure out if a sensor is present by reading its value(s) and its limits.
+ * This is a highly impirical way that cannot be guaranteed to give the correct
+ * result but it was a wish not to be dependent on a PN table based solution.
+ */
+static void qsfpplus_find_qsfp_sensor_option(nim_i2c_ctx_p ctx,
+ uint16_t value_addr,
+ uint8_t lane_count,
+ uint16_t limit_addr, bool two_compl,
+ uint32_t sensor_option)
+{
+ uint8_t data[8];
+ int i, j;
+ int value;
+ int value_list[4];
+ int limit;
+ int limit_list[4];
+ bool present;
+
+ /* Read current value(s) */
+ read_data_lin(ctx, value_addr, (uint16_t)(lane_count * 2), data);
+
+ for (j = 0; j < lane_count; j++) {
+ value = 0;
+
+ for (i = 0; i < 2; i++) {
+ value = value << 8;
+ value += data[2 * j + i];
+ }
+
+ if (two_compl && value >= 0x8000)
+ value = value - 0x10000;
+
+ value_list[j] = value;
+ }
+
+ /* Read limits Warning high/low Alarm high/low 4 values each two bytes */
+ read_data_lin(ctx, limit_addr, 8, data);
+
+ for (j = 0; j < 4; j++) {
+ limit = 0;
+
+ for (i = 0; i < 2; i++) {
+ limit = limit << 8;
+ limit += data[2 * j + i];
+ }
+
+ if (two_compl && limit >= 0x8000)
+ limit = limit - 0x10000;
+
+ limit_list[j] = limit;
+ }
+
+ /* Find out if limits contradicts each other */
+ int alarm_high = limit_list[0];
+ int alarm_low = limit_list[1];
+ int warn_high = limit_list[2];
+ int warn_low = limit_list[3];
+
+ bool alarm_limits = false; /* Are they present - that is both not zero */
+ bool warn_limits = false;
+ bool limit_conflict = false;
+
+ if (alarm_high != 0 || alarm_low != 0) {
+ alarm_limits = true;
+
+ if (alarm_high <= alarm_low)
+ limit_conflict = true;
+ }
+
+ if (warn_high != 0 || warn_low != 0) {
+ warn_limits = true;
+
+ /* Warning limits must be least restrictive */
+ if (warn_high <= warn_low)
+ limit_conflict = true;
+ else if ((warn_high > alarm_high) || (warn_low < alarm_low))
+ limit_conflict = true;
+ }
+
+ /* Try to deduce if the sensor is present or not */
+ present = false;
+
+ if (limit_conflict) {
+ present = false;
+ } else if (warn_limits ||
+ alarm_limits) { /* Is one or both present and not contradictory */
+ present = true;
+ } else {
+ /*
+ * All limits are zero - look at the sensor value
+ * If one sensor is non-zero the sensor is set to be present
+ */
+ for (j = 0; j < lane_count; j++) {
+ if (value_list[j] != 0) {
+ present = true;
+ break;
+ }
+ }
+
+ /*
+ * If all limits and values are zero then present will be false here. In this
+ * case it is assumed that the sensor is not present:
+ * Experience indicates that for QSFP+ modules RxPwr will be non-zero even with
+ * no optical input. QSFP28 modules however can easily have RxPwr equal to zero
+ * with no optical input.
+ * For all investigated modules it was found that if RxPwr is implemented then
+ * the limits are also set. This is not always the case with TxBias and TxPwr
+ * but here the measured values will be non-zero when the laser is on what it
+ * will be just after initialization since it has no external hardware disable.
+ */
+ }
+
+ if (present)
+ ctx->options |= (1U << sensor_option);
+}
+
+/*
+ * Find active QSFP sensors.
+ */
+static void qsfpplus_get_qsfp_options_from_data(nim_i2c_ctx_p ctx)
+{
+ ctx->options = 0;
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TEMP_LIN_ADDR, 1,
+ QSFP_TEMP_THRESH_LIN_ADDR, true,
+ NIM_OPTION_TEMP);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_VOLT_LIN_ADDR, 1,
+ QSFP_VOLT_THRESH_LIN_ADDR, false,
+ NIM_OPTION_SUPPLY);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_RX_PWR_LIN_ADDR, 4,
+ QSFP_RX_PWR_THRESH_LIN_ADDR, false,
+ NIM_OPTION_RX_POWER);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TX_PWR_LIN_ADDR, 4,
+ QSFP_TX_PWR_THRESH_LIN_ADDR, false,
+ NIM_OPTION_TX_POWER);
+
+ qsfpplus_find_qsfp_sensor_option(ctx, QSFP_TX_BIAS_LIN_ADDR, 4,
+ QSFP_BIAS_THRESH_LIN_ADDR, false,
+ NIM_OPTION_TX_BIAS);
+}
+
+static void sfp_find_port_params(nim_i2c_ctx_p ctx)
+{
+ uint8_t data;
+ uint16_t bit_rate_nom;
+ uint8_t connector;
+ uint8_t gig_eth_comp;
+ uint8_t dmi_opt;
+ uint8_t fiber_chan_tx_tech;
+ unsigned int len_sm;
+ unsigned int len_mm_50um;
+ unsigned int len_mm_62_5um;
+
+ ctx->specific_u.sfp.sfp28 = false;
+
+ /* gigEthComp: */
+ static const uint8_t eth_1000_b_t = 1 << 3;
+ static const uint8_t eth_1000_b_sx = 1 << 0;
+ static const uint8_t eth_1000_b_lx = 1 << 1;
+
+ /* fiberChanTxTech: */
+ static const uint8_t cu_passive = 1 << 2;
+ static const uint8_t cu_active = 1 << 3;
+
+ /* dmiOpt: */
+ static const uint8_t dd_present = 1 << 6;
+
+ /* connector: */
+ static const uint8_t cu_pig_tail = 0x21;
+
+ ctx->port_type = NT_PORT_TYPE_SFP_NOT_RECOGNISED;
+
+ read_data_lin(ctx, 12, sizeof(data), &data);
+ bit_rate_nom = (uint16_t)(data * 100);
+
+ read_data_lin(ctx, 2, sizeof(connector), &connector);
+ read_data_lin(ctx, 6, sizeof(gig_eth_comp), &gig_eth_comp);
+ read_data_lin(ctx, 92, sizeof(dmi_opt), &dmi_opt);
+ read_data_lin(ctx, 8, sizeof(fiber_chan_tx_tech), &fiber_chan_tx_tech);
+
+ read_data_lin(ctx, 15, sizeof(data), &data);
+ len_sm = (unsigned int)data * 100; /* Unit is 100m */
+
+ read_data_lin(ctx, 16, sizeof(data), &data);
+ len_mm_50um = (unsigned int)data * 10; /* Unit is 10m */
+
+ read_data_lin(ctx, 17, sizeof(data), &data);
+ len_mm_62_5um = (unsigned int)data * 10; /* Unit is 10m */
+
+ /* First find out if it is a SFP or a SFP+ NIM */
+ if (bit_rate_nom == 0) {
+ /*
+ * A Nominal bit rate of zero indicates that it has not been defined and must
+ * be deduced from transceiver technology
+ */
+ ctx->specific_u.sfp.sfpplus = !(gig_eth_comp & eth_1000_b_t);
+ } else if (bit_rate_nom == 25500) {
+ /* SFF-8024 - 4.4 Extended Specification Compliance References */
+ read_data_lin(ctx, 36, sizeof(data), &data);
+
+ if (data == 0x02)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_SR;
+ else if (data == 0x03)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_LR;
+ else if (data == 0x0B)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_L;
+ else if (data == 0x0C)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_S;
+ else if (data == 0x0D)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_CR_CA_N;
+ else
+ ctx->port_type = NT_PORT_TYPE_SFP_28;
+
+ ctx->specific_u.sfp.sfp28 = true;
+ ctx->specific_u.sfp.sfpplus = true;
+
+ /*
+ * Whitelist of 25G transceivers known to also support 10G.
+ * There is no way to inquire about this capability.
+ */
+ if ((strcmp(ctx->prod_no, "TR-PZ85S-N00") == 0) ||
+ (strcmp(ctx->prod_no, "TR-PZ13L-N00") == 0) ||
+ (strcmp(ctx->prod_no, "FTLF8536P4BCV") == 0) ||
+ (strcmp(ctx->prod_no, "FTLF1436P4BCV") == 0)) {
+ ctx->specific_u.sfp.dual_rate = true;
+
+ /* Change the port type for dual rate modules */
+ if (ctx->port_type == NT_PORT_TYPE_SFP_28_SR)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_SR_DR;
+ else if (ctx->port_type == NT_PORT_TYPE_SFP_28_LR)
+ ctx->port_type = NT_PORT_TYPE_SFP_28_LR_DR;
+ }
+
+ return;
+ }
+ ctx->specific_u.sfp.sfpplus = (bit_rate_nom >= 10000);
+ /* Then find sub-types of each */
+ if (ctx->specific_u.sfp.sfpplus) {
+ if (fiber_chan_tx_tech & cu_active) {
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC;
+ } else if (fiber_chan_tx_tech & cu_passive) {
+ if (connector == cu_pig_tail)
+ ctx->port_type =
+ NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC;
+ else
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS_CU;
+ } else {
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS;
+ }
+ if (gig_eth_comp & (eth_1000_b_sx | eth_1000_b_lx)) {
+ ctx->port_type = NT_PORT_TYPE_SFP_PLUS_DUAL_RATE;
+ ctx->specific_u.sfp.dual_rate = true;
+ }
+
+ read_data_lin(ctx, 65, sizeof(data), &data);
+ /* Test hard RATE_SELECT bit */
+ ctx->specific_u.sfp.hw_rate_sel = ((data & (1 << 5)) != 0);
+
+ read_data_lin(ctx, 93, sizeof(data), &data);
+ /* Test soft RATE_SELECT bit */
+ ctx->specific_u.sfp.sw_rate_sel = ((data & (1 << 3)) != 0);
+ } else { /* SFP */
+ /* 100M */
+ if (bit_rate_nom != 0 && bit_rate_nom < 1000) {
+ ctx->port_type = NT_PORT_TYPE_SFP_FX;
+ /* 1G */
+ } else {
+ ctx->specific_u.sfp.cu_type = false;
+ if (gig_eth_comp & eth_1000_b_sx) {
+ ctx->port_type = NT_PORT_TYPE_SFP_SX;
+ } else if (gig_eth_comp & eth_1000_b_lx) {
+ ctx->port_type = NT_PORT_TYPE_SFP_LX;
+ } else if (gig_eth_comp & eth_1000_b_t) {
+ ctx->specific_u.sfp.tri_speed =
+ sfp_is_supported_tri_speed_pn(ctx->prod_no);
+
+ if (ctx->specific_u.sfp.tri_speed) {
+ ctx->port_type =
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED;
+ } else {
+ ctx->port_type = NT_PORT_TYPE_SFP_CU;
+ }
+ ctx->specific_u.sfp.cu_type = true;
+ } else {
+ /*
+ * Not all modules report their ethernet compliance correctly so use
+ * length indicators
+ */
+ if (len_sm > 0)
+ ctx->port_type = NT_PORT_TYPE_SFP_LX;
+ else if ((len_mm_50um > 0) || (len_mm_62_5um > 0))
+ ctx->port_type = NT_PORT_TYPE_SFP_SX;
+ }
+
+ /* Add Diagnostic Data suffix if necessary */
+ if (dmi_opt & dd_present) {
+ if (ctx->port_type == NT_PORT_TYPE_SFP_SX)
+ ctx->port_type = NT_PORT_TYPE_SFP_SX_DD;
+ else if (ctx->port_type == NT_PORT_TYPE_SFP_LX)
+ ctx->port_type = NT_PORT_TYPE_SFP_LX_DD;
+ else if (ctx->port_type == NT_PORT_TYPE_SFP_CU)
+ ctx->port_type = NT_PORT_TYPE_SFP_CU_DD;
+ else if (ctx->port_type ==
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED)
+ ctx->port_type =
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED_DD;
+ }
+ }
+ }
+}
+
+
+static void sfp_set_speed_mask(nim_i2c_ctx_p ctx)
+{
+ if (ctx->specific_u.sfp.sfp28) {
+ ctx->speed_mask = NT_LINK_SPEED_25G; /* Default for SFP28 */
+ if (ctx->specific_u.sfp.dual_rate)
+ ctx->speed_mask |= NT_LINK_SPEED_10G;
+ } else if (ctx->specific_u.sfp.sfpplus) {
+ ctx->speed_mask = NT_LINK_SPEED_10G; /* Default for SFP+ */
+ if (ctx->specific_u.sfp.dual_rate)
+ ctx->speed_mask |= NT_LINK_SPEED_1G;
+ if (ctx->port_type == NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC)
+ ctx->speed_mask |= NT_LINK_SPEED_1G;
+ if (ctx->port_type == NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC)
+ ctx->speed_mask |= NT_LINK_SPEED_1G;
+ } else { /* SFP */
+ if (ctx->port_type == NT_PORT_TYPE_SFP_FX) {
+ ctx->speed_mask = NT_LINK_SPEED_100M;
+ } else {
+ ctx->speed_mask = NT_LINK_SPEED_1G; /* Default for SFP */
+ if (ctx->specific_u.sfp.dual_rate ||
+ ctx->specific_u.sfp.tri_speed)
+ ctx->speed_mask |= NT_LINK_SPEED_100M;
+ if (ctx->specific_u.sfp.tri_speed)
+ ctx->speed_mask |= NT_LINK_SPEED_10M;
+ }
+ }
+ if (ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_L ||
+ ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_S ||
+ ctx->port_type == NT_PORT_TYPE_SFP_28_CR_CA_N) {
+ /* Enable multiple speed setting for SFP28 DAC cables */
+ ctx->speed_mask = (NT_LINK_SPEED_25G | NT_LINK_SPEED_10G |
+ NT_LINK_SPEED_1G);
+ }
+}
+
+static void qsfp28_find_port_params(nim_i2c_ctx_p ctx)
+{
+ uint8_t fiber_chan_speed;
+
+ /* Table 6-17 SFF-8636 */
+ read_data_lin(ctx, QSFP_SPEC_COMPLIANCE_CODES_ADDR, 1, &fiber_chan_speed);
+
+ if (fiber_chan_speed & (1 << 7)) {
+ /* SFF-8024, Rev 4.7, Table 4-4 */
+ uint8_t extended_specification_compliance_code = 0;
+
+ read_data_lin(ctx, QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR, 1,
+ &extended_specification_compliance_code);
+
+ switch (extended_specification_compliance_code) {
+ case 0x02:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_SR4;
+ break;
+ case 0x03:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_LR4;
+ break;
+ case 0x0B:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_L;
+ break;
+ case 0x0C:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_S;
+ break;
+ case 0x0D:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_CR_CA_N;
+ break;
+ case 0x25:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_DR;
+ break;
+ case 0x26:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_FR;
+ break;
+ case 0x27:
+ ctx->port_type = NT_PORT_TYPE_QSFP28_LR;
+ break;
+ default:
+ ctx->port_type = NT_PORT_TYPE_QSFP28;
+ }
+ } else {
+ ctx->port_type = NT_PORT_TYPE_QSFP28;
+ }
+}
+
+/*
+ * If true the user must actively select the desired rate. If false the module
+ * however can still support several rates without the user is required to select
+ * one of them. Supported rates must then be deduced from the product number.
+ * SFF-8636, Rev 2.10a:
+ * p40: 6.2.7 Rate Select
+ * p85: A.2 Rate Select
+ */
+static bool qsfp28_is_rate_selection_enabled(nim_i2c_ctx_p ctx)
+{
+ const uint8_t ext_rate_select_compl_reg_addr = 141;
+ const uint8_t options_reg_addr = 195;
+ const uint8_t enh_options_reg_addr = 221;
+
+ uint8_t rate_select_ena = (read_byte(ctx, options_reg_addr) >> 5) &
+ 0x01; /* bit: 5 */
+
+ if (rate_select_ena == 0)
+ return false;
+
+ uint8_t rate_select_type = (read_byte(ctx, enh_options_reg_addr) >> 2) &
+ 0x03; /* bit 3..2 */
+
+ if (rate_select_type != 2) {
+ NT_LOG(DBG, PMD, "NIM has unhandled rate select type (%d)",
+ rate_select_type);
+ return false;
+ }
+
+ uint8_t ext_rate_select_ver = read_byte(ctx, ext_rate_select_compl_reg_addr) &
+ 0x03; /* bit 1..0 */
+
+ if (ext_rate_select_ver != 0x02) {
+ NT_LOG(DBG, PMD,
+ "NIM has unhandled extended rate select version (%d)",
+ ext_rate_select_ver);
+ return false;
+ }
+
+ return true; /* When true selectRate() can be used */
+}
+
+static void qsfp28_set_speed_mask(nim_i2c_ctx_p ctx)
+{
+ if (ctx->port_type == NT_PORT_TYPE_QSFP28_FR ||
+ ctx->port_type == NT_PORT_TYPE_QSFP28_DR ||
+ ctx->port_type == NT_PORT_TYPE_QSFP28_LR) {
+ if (ctx->lane_idx < 0)
+ ctx->speed_mask = NT_LINK_SPEED_100G;
+ else
+ ctx->speed_mask =
+ 0; /* PAM-4 modules can only run on all lanes together */
+ } else {
+ if (ctx->lane_idx < 0)
+ ctx->speed_mask = NT_LINK_SPEED_100G;
+ else
+ ctx->speed_mask = NT_LINK_SPEED_25G;
+
+ if (qsfp28_is_rate_selection_enabled(ctx)) {
+ /*
+ * It is assumed that if the module supports dual rates then the other rate
+ * is 10G per lane or 40G for all lanes.
+ */
+ if (ctx->lane_idx < 0)
+ ctx->speed_mask |= NT_LINK_SPEED_40G;
+ else
+ ctx->speed_mask = NT_LINK_SPEED_10G;
+ }
+ }
+}
+
+static void qsfpplus_find_port_params(nim_i2c_ctx_p ctx)
+{
+ uint8_t device_tech;
+
+ read_data_lin(ctx, QSFP_TRANSMITTER_TYPE_LIN_ADDR, sizeof(device_tech),
+ &device_tech);
+
+ switch (device_tech & 0xF0) {
+ case 0xA0: /* Copper cable unequalized */
+ case 0xB0: /* Copper cable passive equalized */
+ ctx->port_type = NT_PORT_TYPE_QSFP_PASSIVE_DAC;
+ break;
+ case 0xC0: /* Copper cable, near and far end limiting active equalizers */
+ case 0xD0: /* Copper cable, far end limiting active equalizers */
+ case 0xE0: /* Copper cable, near end limiting active equalizers */
+ case 0xF0: /* Copper cable, linear active equalizers */
+ ctx->port_type = NT_PORT_TYPE_QSFP_ACTIVE_DAC;
+ break;
+ default: /* Optical */
+ ctx->port_type = NT_PORT_TYPE_QSFP_PLUS;
+ break;
+ }
+}
+
+static void qsfpplus_set_speed_mask(nim_i2c_ctx_p ctx)
+{
+ ctx->speed_mask = (ctx->lane_idx < 0) ? NT_LINK_SPEED_40G :
+ (NT_LINK_SPEED_10G);
+}
+
+static int sfp_preinit(nim_i2c_ctx_p ctx)
+{
+ int res = sfp_read_basic_data(ctx);
+
+ if (!res) {
+ sfp_find_port_params(ctx);
+ sfp_set_speed_mask(ctx);
+ }
+ return res;
+}
+
+static void qsfpplus_construct(nim_i2c_ctx_p ctx, int8_t lane_idx)
+{
+ assert(lane_idx < 4);
+ ctx->specific_u.qsfp.qsfp28 = false;
+ ctx->lane_idx = lane_idx;
+ ctx->lane_count = 4;
+}
+
+static int qsfpplus_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx)
+{
+ qsfpplus_construct(ctx, lane_idx);
+ int res = qsfpplus_read_basic_data(ctx);
+
+ if (!res) {
+ qsfpplus_find_port_params(ctx);
+ /*
+ * If not on the known modules list try to figure out which sensors that are present
+ */
+ if (!qsfpplus_get_qsfp_options_from_pn(ctx)) {
+ NT_LOG(DBG, NTHW,
+ "NIM options not known in advance - trying to detect");
+ qsfpplus_get_qsfp_options_from_data(ctx);
+ }
+
+ /*
+ * Read if TX_DISABLE has been implemented
+ * For passive optical modules this is required while it for copper and active
+ * optical modules is optional. Under all circumstances register 195.4 will
+ * indicate, if TX_DISABLE has been implemented in register 86.0-3
+ */
+ uint8_t value;
+
+ read_data_lin(ctx, QSFP_OPTION3_LIN_ADDR, sizeof(value), &value);
+
+ ctx->tx_disable = (value & QSFP_OPTION3_TX_DISABLE_BIT) != 0;
+
+ if (ctx->tx_disable)
+ ctx->options |= (1 << NIM_OPTION_TX_DISABLE);
+
+ /*
+ * Previously - considering AFBR-89BRDZ - code tried to establish if a module was
+ * RxOnly by testing the state of the lasers after reset. Lasers were for this
+ * module default disabled.
+ * However that code did not work for GigaLight, GQS-MPO400-SR4C so it was
+ * decided that this option should not be detected automatically but from PN
+ */
+ ctx->specific_u.qsfp.rx_only =
+ (ctx->options & (1 << NIM_OPTION_RX_ONLY)) != 0;
+ qsfpplus_set_speed_mask(ctx);
+ }
+ return res;
+}
+
+static void qsfp28_wait_for_ready_after_reset(nim_i2c_ctx_p ctx)
+{
+ uint8_t data;
+ bool init_complete_flag_present = false;
+
+ /*
+ * Revision compliance
+ * 7: SFF-8636 Rev 2.5, 2.6 and 2.7
+ * 8: SFF-8636 Rev 2.8, 2.9 and 2.10
+ */
+ read_data_lin(ctx, 1,
+ sizeof(ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance),
+ &ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance);
+ NT_LOG(DBG, NTHW, "NIM RevCompliance = %d",
+ ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance);
+
+ /* Wait if lane_idx == -1 (all lanes are used) or lane_idx == 0 (the first lane) */
+ if (ctx->lane_idx > 0)
+ return;
+
+ if (ctx->specific_u.qsfp.specific_u.qsfp28.rev_compliance >= 7) {
+ /* Check if init complete flag is implemented */
+ read_data_lin(ctx, 221, sizeof(data), &data);
+ init_complete_flag_present = (data & (1 << 4)) != 0;
+ }
+
+ NT_LOG(DBG, NTHW, "NIM InitCompleteFlagPresent = %d",
+ init_complete_flag_present);
+
+ /*
+ * If the init complete flag is not present then wait 500ms that together with 500ms
+ * after reset (in the adapter code) should be enough to read data from upper pages
+ * that otherwise would not be ready. Especially BiDi modules AFBR-89BDDZ have been
+ * prone to this when trying to read sensor options using getQsfpOptionsFromData()
+ * Probably because access to the paged address space is required.
+ */
+ if (!init_complete_flag_present) {
+ NT_OS_WAIT_USEC(500000);
+ return;
+ }
+
+ /* Otherwise wait for the init complete flag to be set */
+ int count = 0;
+
+ while (true) {
+ if (count > 10) { /* 1 s timeout */
+ NT_LOG(WRN, NTHW, "Timeout waiting for module ready");
+ break;
+ }
+
+ read_data_lin(ctx, 6, sizeof(data), &data);
+
+ if (data & 0x01) {
+ NT_LOG(DBG, NTHW, "Module ready after %dms",
+ count * 100);
+ break;
+ }
+
+ NT_OS_WAIT_USEC(100000); /* 100 ms */
+ count++;
+ }
+}
+
+static void qsfp28_get_fec_options(nim_i2c_ctx_p ctx)
+{
+ const char *const nim_list[] = {
+ "AFBR-89BDDZ", /* Avago BiDi */
+ "AFBR-89BRDZ", /* Avago BiDi, RxOnly */
+ "FTLC4352RKPL", /* Finisar QSFP28-LR */
+ "FTLC4352RHPL", /* Finisar QSFP28-DR */
+ "FTLC4352RJPL", /* Finisar QSFP28-FR */
+ "SFBR-89BDDZ-CS4", /* Foxconn, QSFP28 100G/40G BiDi */
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(nim_list); i++) {
+ if (ctx->prod_no == nim_list[i]) {
+ ctx->options |= (1 << NIM_OPTION_MEDIA_SIDE_FEC);
+ ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena =
+ true;
+ NT_LOG(DBG, NTHW, "Found FEC info via PN list");
+ return;
+ }
+ }
+
+ /*
+ * For modules not in the list find FEC info via registers
+ * Read if the module has controllable FEC
+ * SFF-8636, Rev 2.10a TABLE 6-28 Equalizer, Emphasis, Amplitude and Timing)
+ * (Page 03h, Bytes 224-229)
+ */
+ uint8_t data;
+ uint16_t addr = 227 + 3 * 128;
+
+ read_data_lin(ctx, addr, sizeof(data), &data);
+
+ /* Check if the module has FEC support that can be controlled */
+ ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl =
+ (data & (1 << 6)) != 0;
+ ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl =
+ (data & (1 << 7)) != 0;
+
+ if (ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl)
+ ctx->options |= (1 << NIM_OPTION_MEDIA_SIDE_FEC);
+
+ if (ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl)
+ ctx->options |= (1 << NIM_OPTION_HOST_SIDE_FEC);
+}
+
+static int qsfp28_preinit(nim_i2c_ctx_p ctx, int8_t lane_idx)
+{
+ int res = qsfpplus_preinit(ctx, lane_idx);
+
+ if (!res) {
+ qsfp28_wait_for_ready_after_reset(ctx);
+ memset(&ctx->specific_u.qsfp.specific_u.qsfp28, 0,
+ sizeof(ctx->specific_u.qsfp.specific_u.qsfp28));
+ ctx->specific_u.qsfp.qsfp28 = true;
+ qsfp28_find_port_params(ctx);
+ qsfp28_get_fec_options(ctx);
+ qsfp28_set_speed_mask(ctx);
+ }
+ return res;
+}
+
+static void sfp_nim_add_all_sensors(uint8_t m_port_no, nim_i2c_ctx_t *ctx,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt)
+{
+ struct nim_sensor_group *sensor = NULL;
+ *nim_sensors_cnt = 0;
+
+ if (ctx == NULL || nim_sensors_ptr == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ /*
+ * If the user has not provided a name for the temperature sensor then apply
+ * one automatically
+ */
+ if (strlen(sfp_sensors_level0[0].name) == 0) {
+ if (ctx->specific_u.sfp.sfp28) {
+ rte_strscpy(sfp_sensors_level0[0].name, "SFP28",
+ sizeof(sfp_sensors_level0[0].name));
+ } else if (ctx->specific_u.sfp.sfpplus) {
+ rte_strscpy(sfp_sensors_level0[0].name, "SFP+",
+ sizeof(sfp_sensors_level0[0].name));
+ } else {
+ rte_strscpy(sfp_sensors_level0[0].name, "SFP",
+ sizeof(sfp_sensors_level0[0].name));
+ }
+ }
+
+ /* allocate temperature sensor */
+ nim_sensors_ptr[m_port_no] = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level0[0]);
+ sensor = nim_sensors_ptr[m_port_no];
+ sensor->read = &nim_read_sfp_temp;
+ (*nim_sensors_cnt)++;
+
+ /* voltage */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[0]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_voltage;
+ (*nim_sensors_cnt)++;
+
+ /* bias current */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[1]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_bias_current;
+ (*nim_sensors_cnt)++;
+
+ /* tx power */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[2]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_tx_power;
+ (*nim_sensors_cnt)++;
+
+ /* rx power */
+ sensor->next = allocate_nim_sensor_group(m_port_no,
+ ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &sfp_sensors_level1[3]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_sfp_rx_power;
+ (*nim_sensors_cnt)++;
+}
+
+static void
+qsfp_plus_nim_add_all_sensors(uint8_t m_port_no, nim_i2c_ctx_t *ctx,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt)
+{
+ struct nim_sensor_group *sensor = NULL;
+
+ if (ctx == NULL || nim_sensors_ptr == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ /*
+ * If the user has not provided a name for the temperature sensor then apply
+ * one automatically
+ */
+ if (strlen(qsfp_sensor_level0[0].name) == 0) {
+ if (ctx->specific_u.qsfp.qsfp28)
+ rte_strscpy(qsfp_sensor_level0[0].name, "QSFP28",
+ sizeof(qsfp_sensor_level0[0].name));
+ else
+ rte_strscpy(qsfp_sensor_level0[0].name, "QSFP+",
+ sizeof(qsfp_sensor_level0[0].name));
+ }
+
+ /* temperature sensor */
+ nim_sensors_ptr[m_port_no] = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_PORT,
+ &qsfp_sensor_level0[0]);
+ sensor = nim_sensors_ptr[m_port_no];
+ sensor->read = &nim_read_qsfp_temp;
+ (*nim_sensors_cnt)++;
+
+ /* voltage */
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[0]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_voltage;
+ (*nim_sensors_cnt)++;
+
+ /* bias current sensors */
+ for (uint8_t i = 1; i < 5; i++) {
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[i]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_bias_current;
+ (*nim_sensors_cnt)++;
+ }
+
+ /* tx power */
+ for (uint8_t i = 5; i < 9; i++) {
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[i]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_tx_power;
+ (*nim_sensors_cnt)++;
+ }
+
+ /* rx power */
+ for (uint8_t i = 9; i < 13; i++) {
+ sensor->next = allocate_nim_sensor_group(m_port_no, ctx,
+ NT_SENSOR_SOURCE_LEVEL1_PORT,
+ &qsfp_sensor_level1[i]);
+ sensor = sensor->next;
+ sensor->read = &nim_read_qsfp_rx_power;
+ (*nim_sensors_cnt)++;
+ }
+}
+
+struct nim_sensor_group *
+allocate_nim_sensor_group(uint8_t port, struct nim_i2c_ctx *ctx,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *sd)
+{
+ struct nim_sensor_group *sg = malloc(sizeof(struct nim_sensor_group));
+
+ if (sg == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__);
+ return NULL;
+ }
+ sg->sensor = allocate_sensor_by_description(port, ssrc, sd);
+ sg->ctx = ctx;
+ sg->next = NULL;
+ return sg;
+}
+
+int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra, uint8_t port,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt)
+{
+ int res = i2c_nim_common_construct(ctx);
+
+ switch (translate_nimid(ctx)) {
+ case NT_NIM_SFP_SFP_PLUS:
+ sfp_preinit(ctx);
+ sfp_nim_add_all_sensors(port, ctx, nim_sensors_ptr,
+ nim_sensors_cnt);
+ break;
+ case NT_NIM_QSFP_PLUS:
+ qsfpplus_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1);
+ qsfp_plus_nim_add_all_sensors(port, ctx, nim_sensors_ptr,
+ nim_sensors_cnt);
+ break;
+ case NT_NIM_QSFP28:
+ qsfp28_preinit(ctx, extra ? *(int8_t *)extra : (int8_t)-1);
+ qsfp_plus_nim_add_all_sensors(port, ctx, nim_sensors_ptr,
+ nim_sensors_cnt);
+ break;
+ default:
+ res = 1;
+ NT_LOG(ERR, NTHW, "NIM type %s is not supported.\n",
+ nim_id_to_text(ctx->nim_id));
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nim/i2c_nim.h b/drivers/net/ntnic/nim/i2c_nim.h
new file mode 100644
index 0000000000..f664e6b7ee
--- /dev/null
+++ b/drivers/net/ntnic/nim/i2c_nim.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef I2C_NIM_H_
+#define I2C_NIM_H_
+
+#include "nthw_drv.h"
+#include "nim_defines.h"
+#include "nt_link_speed.h"
+
+#include "sensors.h"
+
+typedef struct sfp_nim_state {
+ uint8_t br; /* bit rate, units of 100 MBits/sec */
+} sfp_nim_state_t, *sfp_nim_state_p;
+
+typedef struct nim_i2c_ctx {
+ nthw_iic_t hwiic; /* depends on *Fpga_t, instance number, and cycle time */
+ uint8_t instance;
+ uint8_t devaddr;
+ uint8_t regaddr;
+ uint8_t nim_id;
+ nt_port_type_t port_type;
+
+ char vendor_name[17];
+ char prod_no[17];
+ char serial_no[17];
+ char date[9];
+ char rev[5];
+ bool avg_pwr;
+ bool content_valid;
+ uint8_t pwr_level_req;
+ uint8_t pwr_level_cur;
+ uint16_t len_info[5];
+ uint32_t speed_mask; /* Speeds supported by the NIM */
+ int8_t lane_idx; /* Is this associated with a single lane or all lanes (-1) */
+ uint8_t lane_count;
+ uint32_t options;
+ bool tx_disable;
+ bool dmi_supp;
+
+ union {
+ struct {
+ bool sfp28;
+ bool sfpplus;
+ bool dual_rate;
+ bool hw_rate_sel;
+ bool sw_rate_sel;
+ bool cu_type;
+ bool tri_speed;
+ bool ext_cal;
+ bool addr_chg;
+ } sfp;
+
+ struct {
+ bool rx_only;
+ bool qsfp28;
+ union {
+ struct {
+ uint8_t rev_compliance;
+ bool media_side_fec_ctrl;
+ bool host_side_fec_ctrl;
+ bool media_side_fec_ena;
+ bool host_side_fec_ena;
+ } qsfp28;
+ } specific_u;
+ } qsfp;
+
+ } specific_u;
+} nim_i2c_ctx_t, *nim_i2c_ctx_p;
+
+struct nim_sensor_group {
+ struct nt_adapter_sensor *sensor;
+ void (*read)(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+ struct nim_i2c_ctx *ctx;
+ struct nim_sensor_group *next;
+};
+
+struct nim_sensor_group *
+allocate_nim_sensor_group(uint8_t port, struct nim_i2c_ctx *ctx,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *sd);
+
+/*
+ * Utility functions
+ */
+
+nt_nim_identifier_t translate_nimid(const nim_i2c_ctx_t *ctx);
+
+/*
+ * Builds an nim state for the port implied by `ctx`, returns zero
+ * if successful, and non-zero otherwise. SFP and QSFP nims are supported
+ */
+int nim_state_build(nim_i2c_ctx_t *ctx, sfp_nim_state_t *state);
+
+/*
+ * Returns a type name such as "SFP/SFP+" for a given NIM type identifier,
+ * or the string "ILLEGAL!".
+ */
+const char *nim_id_to_text(uint8_t nim_id);
+
+int nim_sfp_nim_set_tx_laser_disable(nim_i2c_ctx_p ctx, bool disable);
+
+int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_t *ctx, bool disable,
+ int lane_idx);
+
+int nim_set_link_speed(nim_i2c_ctx_p ctx, nt_link_speed_t speed);
+
+/*
+ * This function tries to classify NIM based on it's ID and some register reads
+ * and collects information into ctx structure. The @extra parameter could contain
+ * the initialization argument for specific type of NIMS.
+ */
+int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra, uint8_t port,
+ struct nim_sensor_group **nim_sensors_ptr,
+ uint16_t *nim_sensors_cnt);
+
+int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
+ void *data);
+
+#endif /* I2C_NIM_H_ */
diff --git a/drivers/net/ntnic/nim/nim_defines.h b/drivers/net/ntnic/nim/nim_defines.h
new file mode 100644
index 0000000000..da3567d073
--- /dev/null
+++ b/drivers/net/ntnic/nim/nim_defines.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NIM_DEFINES_H_
+#define NIM_DEFINES_H_
+
+#define NIM_IDENTIFIER_ADDR 0 /* 1 byte */
+
+#define SFP_BIT_RATE_ADDR 12 /* 1 byte */
+#define SFP_VENDOR_NAME_ADDR 20 /* 16bytes */
+#define SFP_VENDOR_PN_ADDR 40 /* 16bytes */
+#define SFP_VENDOR_REV_ADDR 56 /* 4bytes */
+#define SFP_VENDOR_SN_ADDR 68 /* 16bytes */
+#define SFP_VENDOR_DATE_ADDR 84 /* 8bytes */
+
+#define SFP_CONTROL_STATUS_LIN_ADDR (110U + 256U) /* 0xA2 */
+#define SFP_SOFT_TX_DISABLE_BIT (1U << 6)
+
+#define QSFP_EXTENDED_IDENTIFIER 129
+#define QSFP_SUP_LEN_INFO_ADDR 142 /* 5bytes */
+#define QSFP_TRANSMITTER_TYPE_ADDR 147 /* 1byte */
+#define QSFP_VENDOR_NAME_ADDR 148 /* 16bytes */
+#define QSFP_VENDOR_PN_ADDR 168 /* 16bytes */
+#define QSFP_VENDOR_REV_ADDR 184 /* 2bytes */
+#define QSFP_VENDOR_SN_ADDR 196 /* 16bytes */
+#define QSFP_VENDOR_DATE_ADDR 212 /* 8bytes */
+
+/* I2C addresses */
+#define nim_i2c_0xa0 0xA0 /* Basic I2C address */
+#define nim_i2c_0xa2 0xA2 /* Diagnostic monitoring */
+#define nim_i2c_0xac 0xAC /* Address of integrated PHY */
+
+typedef enum {
+ NIM_OPTION_TEMP = 0,
+ NIM_OPTION_SUPPLY,
+ NIM_OPTION_RX_POWER,
+ NIM_OPTION_TX_BIAS,
+ NIM_OPTION_TX_POWER,
+ NIM_OPTION_TX_DISABLE,
+ /* Indicates that the module should be checked for the two next FEC types */
+ NIM_OPTION_FEC,
+ NIM_OPTION_MEDIA_SIDE_FEC,
+ NIM_OPTION_HOST_SIDE_FEC,
+ NIM_OPTION_RX_ONLY
+} nim_option_t;
+
+enum nt_nim_identifier_e {
+ NT_NIM_UNKNOWN = 0x00, /* Nim type is unknown */
+ NT_NIM_GBIC = 0x01, /* Nim type = GBIC */
+ NT_NIM_FIXED = 0x02, /* Nim type = FIXED */
+ NT_NIM_SFP_SFP_PLUS = 0x03, /* Nim type = SFP/SFP+ */
+ NT_NIM_300_PIN_XBI = 0x04, /* Nim type = 300 pin XBI */
+ NT_NIM_XEN_PAK = 0x05, /* Nim type = XEN-PAK */
+ NT_NIM_XFP = 0x06, /* Nim type = XFP */
+ NT_NIM_XFF = 0x07, /* Nim type = XFF */
+ NT_NIM_XFP_E = 0x08, /* Nim type = XFP-E */
+ NT_NIM_XPAK = 0x09, /* Nim type = XPAK */
+ NT_NIM_X2 = 0x0A, /* Nim type = X2 */
+ NT_NIM_DWDM = 0x0B, /* Nim type = DWDM */
+ NT_NIM_QSFP = 0x0C, /* Nim type = QSFP */
+ NT_NIM_QSFP_PLUS = 0x0D, /* Nim type = QSFP+ */
+ NT_NIM_QSFP28 = 0x11, /* Nim type = QSFP28 */
+ NT_NIM_CFP4 = 0x12, /* Nim type = CFP4 */
+};
+
+typedef enum nt_nim_identifier_e nt_nim_identifier_t;
+
+/*
+ * Port types
+ * The use of all non-generic XX_NOT_PRESENT is deprecated - use
+ * NT_PORT_TYPE_NIM_NOT_PRESENT instead
+ */
+enum nt_port_type_e {
+ NT_PORT_TYPE_NOT_AVAILABLE =
+ 0, /* The NIM/port type is not available (unknown) */
+ NT_PORT_TYPE_NOT_RECOGNISED, /* The NIM/port type not recognized */
+ NT_PORT_TYPE_RJ45, /* RJ45 type */
+ NT_PORT_TYPE_SFP_NOT_PRESENT, /* SFP type but slot is empty */
+ NT_PORT_TYPE_SFP_SX, /* SFP SX */
+ NT_PORT_TYPE_SFP_SX_DD, /* SFP SX digital diagnostic */
+ NT_PORT_TYPE_SFP_LX, /* SFP LX */
+ NT_PORT_TYPE_SFP_LX_DD, /* SFP LX digital diagnostic */
+ NT_PORT_TYPE_SFP_ZX, /* SFP ZX */
+ NT_PORT_TYPE_SFP_ZX_DD, /* SFP ZX digital diagnostic */
+ NT_PORT_TYPE_SFP_CU, /* SFP copper */
+ NT_PORT_TYPE_SFP_CU_DD, /* SFP copper digital diagnostic */
+ NT_PORT_TYPE_SFP_NOT_RECOGNISED, /* SFP unknown */
+ NT_PORT_TYPE_XFP, /* XFP */
+ NT_PORT_TYPE_XPAK, /* XPAK */
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED, /* SFP copper tri-speed */
+ NT_PORT_TYPE_SFP_CU_TRI_SPEED_DD, /* SFP copper tri-speed digital diagnostic */
+ NT_PORT_TYPE_SFP_PLUS, /* SFP+ type */
+ NT_PORT_TYPE_SFP_PLUS_NOT_PRESENT, /* SFP+ type but slot is empty */
+ NT_PORT_TYPE_XFP_NOT_PRESENT, /* XFP type but slot is empty */
+ NT_PORT_TYPE_QSFP_PLUS_NOT_PRESENT, /* QSFP type but slot is empty */
+ NT_PORT_TYPE_QSFP_PLUS, /* QSFP type */
+ NT_PORT_TYPE_SFP_PLUS_PASSIVE_DAC, /* SFP+ Passive DAC */
+ NT_PORT_TYPE_SFP_PLUS_ACTIVE_DAC, /* SFP+ Active DAC */
+ NT_PORT_TYPE_CFP4, /* CFP4 type */
+ NT_PORT_TYPE_CFP4_LR4 = NT_PORT_TYPE_CFP4, /* CFP4 100G, LR4 type */
+ NT_PORT_TYPE_CFP4_NOT_PRESENT, /* CFP4 type but slot is empty */
+ NT_PORT_TYPE_INITIALIZE, /* The port type is not fully established yet */
+ NT_PORT_TYPE_NIM_NOT_PRESENT, /* Generic "Not present" */
+ NT_PORT_TYPE_HCB, /* Test mode: Host Compliance Board */
+ NT_PORT_TYPE_NOT_SUPPORTED, /* The NIM type is not supported in this context */
+ NT_PORT_TYPE_SFP_PLUS_DUAL_RATE, /* SFP+ supports 1G/10G */
+ NT_PORT_TYPE_CFP4_SR4, /* CFP4 100G, SR4 type */
+ NT_PORT_TYPE_QSFP28_NOT_PRESENT, /* QSFP28 type but slot is empty */
+ NT_PORT_TYPE_QSFP28, /* QSFP28 type */
+ NT_PORT_TYPE_QSFP28_SR4, /* QSFP28-SR4 type */
+ NT_PORT_TYPE_QSFP28_LR4, /* QSFP28-LR4 type */
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ NT_PORT_TYPE_QSFP_PLUS_4X10,
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ NT_PORT_TYPE_QSFP_PASSIVE_DAC_4X10,
+ NT_PORT_TYPE_QSFP_PASSIVE_DAC =
+ NT_PORT_TYPE_QSFP_PASSIVE_DAC_4X10, /* QSFP passive DAC type */
+ /* Deprecated. The port type should not mention speed eg 4x10 or 1x40 */
+ NT_PORT_TYPE_QSFP_ACTIVE_DAC_4X10,
+ NT_PORT_TYPE_QSFP_ACTIVE_DAC =
+ NT_PORT_TYPE_QSFP_ACTIVE_DAC_4X10, /* QSFP active DAC type */
+ NT_PORT_TYPE_SFP_28, /* SFP28 type */
+ NT_PORT_TYPE_SFP_28_SR, /* SFP28-SR type */
+ NT_PORT_TYPE_SFP_28_LR, /* SFP28-LR type */
+ NT_PORT_TYPE_SFP_28_CR_CA_L, /* SFP28-CR-CA-L type */
+ NT_PORT_TYPE_SFP_28_CR_CA_S, /* SFP28-CR-CA-S type */
+ NT_PORT_TYPE_SFP_28_CR_CA_N, /* SFP28-CR-CA-N type */
+ NT_PORT_TYPE_QSFP28_CR_CA_L, /* QSFP28-CR-CA-L type */
+ NT_PORT_TYPE_QSFP28_CR_CA_S, /* QSFP28-CR-CA-S type */
+ NT_PORT_TYPE_QSFP28_CR_CA_N, /* QSFP28-CR-CA-N type */
+ NT_PORT_TYPE_SFP_28_SR_DR, /* SFP28-SR-DR type */
+ NT_PORT_TYPE_SFP_28_LR_DR, /* SFP28-LR-DR type */
+ NT_PORT_TYPE_SFP_FX, /* SFP FX */
+ NT_PORT_TYPE_SFP_PLUS_CU, /* SFP+ CU type */
+ /* QSFP28-FR type. Uses PAM4 modulation on one lane only */
+ NT_PORT_TYPE_QSFP28_FR,
+ /* QSFP28-DR type. Uses PAM4 modulation on one lane only */
+ NT_PORT_TYPE_QSFP28_DR,
+ /* QSFP28-LR type. Uses PAM4 modulation on one lane only */
+ NT_PORT_TYPE_QSFP28_LR,
+};
+
+typedef enum nt_port_type_e nt_port_type_t, *nt_port_type_p;
+
+#endif /* NIM_DEFINES_H_ */
diff --git a/drivers/net/ntnic/nim/nt_link_speed.c b/drivers/net/ntnic/nim/nt_link_speed.c
new file mode 100644
index 0000000000..35c75f5e56
--- /dev/null
+++ b/drivers/net/ntnic/nim/nt_link_speed.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "nt_link_speed.h"
+
+const char *nt_translate_link_speed(nt_link_speed_t link_speed)
+{
+ switch (link_speed) {
+ case NT_LINK_SPEED_UNKNOWN:
+ return "NotAvail";
+ case NT_LINK_SPEED_10M:
+ return "10M";
+ case NT_LINK_SPEED_100M:
+ return "100M";
+ case NT_LINK_SPEED_1G:
+ return "1G";
+ case NT_LINK_SPEED_10G:
+ return "10G";
+ case NT_LINK_SPEED_25G:
+ return "25G";
+ case NT_LINK_SPEED_40G:
+ return "40G";
+ case NT_LINK_SPEED_50G:
+ return "50G";
+ case NT_LINK_SPEED_100G:
+ return "100G";
+ default:
+ /* DEBUG assert: remind developer that a switch/case entry is needed here.... */
+ assert(false);
+ return "Unhandled";
+ }
+}
+
+uint64_t nt_get_link_speed(nt_link_speed_t e_link_speed)
+{
+ uint64_t n_link_speed = 0ULL;
+
+ switch (e_link_speed) {
+ case NT_LINK_SPEED_UNKNOWN:
+ n_link_speed = 0UL;
+ break;
+ case NT_LINK_SPEED_10M:
+ n_link_speed = (10ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_100M:
+ n_link_speed = (100ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_1G:
+ n_link_speed = (1ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_10G:
+ n_link_speed = (10ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_25G:
+ n_link_speed = (25ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_40G:
+ n_link_speed = (40ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_50G:
+ n_link_speed = (50ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ case NT_LINK_SPEED_100G:
+ n_link_speed = (100ULL * 1000ULL * 1000ULL * 1000ULL);
+ break;
+ default:
+ /* DEBUG assert: remind developer that a switch/case entry is needed here.... */
+ assert(false);
+ n_link_speed = 0UL;
+ break;
+ }
+ return n_link_speed;
+}
+
+const char *nt_translate_link_speed_mask(uint32_t link_speed_mask, char *buffer,
+ uint32_t length)
+{
+ size_t len = 0;
+
+ buffer[0] = 0;
+
+ for (int i = 0; i < 32; i++) {
+ if ((1U << i) & link_speed_mask) {
+ len = strlen(buffer);
+
+ if (len > 0) {
+ if ((length - len - 1) > 2) {
+ strncat(buffer, ", ", length);
+ len = strlen(buffer);
+ }
+ }
+
+ if (len < (length - 1))
+ strncat(buffer, nt_translate_link_speed(1 << i),
+ length);
+ }
+ }
+
+ return buffer;
+}
diff --git a/drivers/net/ntnic/nim/nt_link_speed.h b/drivers/net/ntnic/nim/nt_link_speed.h
new file mode 100644
index 0000000000..969e3fb867
--- /dev/null
+++ b/drivers/net/ntnic/nim/nt_link_speed.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NT_LINK_SPEED_H_
+#define NT_LINK_SPEED_H_
+
+#include <stdint.h>
+
+/*
+ * Link speed.
+ * Note this is a bitmask.
+ */
+enum nt_link_speed_e {
+ NT_LINK_SPEED_UNKNOWN = 0,
+ NT_LINK_SPEED_10M = 0x01, /* 10 Mbps */
+ NT_LINK_SPEED_100M = 0x02, /* 100 Mbps */
+ NT_LINK_SPEED_1G = 0x04, /* 1 Gbps (Autoneg only) */
+ NT_LINK_SPEED_10G = 0x08, /* 10 Gbps (Autoneg only) */
+ NT_LINK_SPEED_40G = 0x10, /* 40 Gbps (Autoneg only) */
+ NT_LINK_SPEED_100G = 0x20, /* 100 Gbps (Autoneg only) */
+ NT_LINK_SPEED_50G = 0x40, /* 50 Gbps (Autoneg only) */
+ NT_LINK_SPEED_25G = 0x80, /* 25 Gbps (Autoneg only) */
+ NT_LINK_SPEED_END /* always keep this entry as the last in enum */
+};
+
+typedef enum nt_link_speed_e nt_link_speed_t;
+
+const char *nt_translate_link_speed(nt_link_speed_t link_speed);
+const char *nt_translate_link_speed_mask(uint32_t link_speed_mask, char *buffer,
+ uint32_t length);
+uint64_t nt_get_link_speed(nt_link_speed_t e_link_speed);
+
+#endif /* NT_LINK_SPEED_H_ */
diff --git a/drivers/net/ntnic/nim/qsfp_registers.h b/drivers/net/ntnic/nim/qsfp_registers.h
new file mode 100644
index 0000000000..366dcbf06e
--- /dev/null
+++ b/drivers/net/ntnic/nim/qsfp_registers.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _QSFP_REGISTERS_H
+#define _QSFP_REGISTERS_H
+
+/*
+ * QSFP Registers
+ */
+#define QSFP_INT_STATUS_RX_LOS_ADDR 3
+#define QSFP_TEMP_LIN_ADDR 22
+#define QSFP_VOLT_LIN_ADDR 26
+#define QSFP_RX_PWR_LIN_ADDR 34 /* uint16_t [0..3] */
+#define QSFP_TX_BIAS_LIN_ADDR 42 /* uint16_t [0..3] */
+#define QSFP_TX_PWR_LIN_ADDR 50 /* uint16_t [0..3] */
+
+#define QSFP_CONTROL_STATUS_LIN_ADDR 86
+#define QSFP_SOFT_TX_ALL_DISABLE_BITS 0x0F
+
+#define QSFP_EXTENDED_IDENTIFIER 129
+#define QSFP_POWER_CLASS_BITS_1_4 0xC0
+#define QSFP_POWER_CLASS_BITS_5_7 0x03
+
+#define QSFP_SUP_LEN_INFO_LIN_ADDR 142 /* 5bytes */
+#define QSFP_TRANSMITTER_TYPE_LIN_ADDR 147 /* 1byte */
+#define QSFP_VENDOR_NAME_LIN_ADDR 148 /* 16bytes */
+#define QSFP_VENDOR_PN_LIN_ADDR 168 /* 16bytes */
+#define QSFP_VENDOR_SN_LIN_ADDR 196 /* 16bytes */
+#define QSFP_VENDOR_DATE_LIN_ADDR 212 /* 8bytes */
+#define QSFP_VENDOR_REV_LIN_ADDR 184 /* 2bytes */
+
+#define QSFP_SPEC_COMPLIANCE_CODES_ADDR 131 /* 8 bytes */
+#define QSFP_EXT_SPEC_COMPLIANCE_CODES_ADDR 192 /* 1 byte */
+
+#define QSFP_OPTION3_LIN_ADDR 195
+#define QSFP_OPTION3_TX_DISABLE_BIT (1 << 4)
+
+#define QSFP_DMI_OPTION_LIN_ADDR 220
+#define QSFP_DMI_AVG_PWR_BIT (1 << 3)
+
+#define QSFP_TEMP_THRESH_LIN_ADDR (128 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_VOLT_THRESH_LIN_ADDR (144 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_RX_PWR_THRESH_LIN_ADDR (176 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_BIAS_THRESH_LIN_ADDR (184 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define QSFP_TX_PWR_THRESH_LIN_ADDR (192 + (3 * 128)) /* Page 3 */
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#endif /* _QSFP_REGISTERS_H */
diff --git a/drivers/net/ntnic/nim/qsfp_sensors.c b/drivers/net/ntnic/nim/qsfp_sensors.c
new file mode 100644
index 0000000000..8264f8fb62
--- /dev/null
+++ b/drivers/net/ntnic/nim/qsfp_sensors.c
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdbool.h>
+
+#include "qsfp_sensors.h"
+
+#include "ntlog.h"
+#include "qsfp_registers.h"
+
+static bool qsfp_plus_nim_get_sensor(nim_i2c_ctx_p ctx, uint16_t addr,
+ nim_option_t nim_option, uint8_t count,
+ uint16_t *p_lane_values)
+{
+ (void)nim_option;
+
+ read_data_lin(ctx, addr, (uint16_t)(sizeof(uint16_t) * count),
+ p_lane_values);
+
+ for (int i = 0; i < count; i++) {
+ *p_lane_values = (*p_lane_values); /* Swap to little endian */
+
+#ifdef NIM_DMI_TEST_VALUE
+ if (nim_option == NIM_OPTION_RX_POWER)
+ *p_lane_values = (uint16_t)NIM_DMI_RX_PWR_TEST_VALUE;
+ else
+ *p_lane_values = (uint16_t)NIM_DMI_TEST_VALUE;
+#endif
+
+ p_lane_values++;
+ }
+
+ return true;
+}
+
+/*
+ * Read NIM temperature
+ */
+static bool qsfp_plus_nim_get_temperature(nim_i2c_ctx_p ctx, int16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TEMP_LIN_ADDR, NIM_OPTION_TEMP,
+ 1, (uint16_t *)p_value);
+}
+
+/*
+ * Read NIM supply voltage
+ */
+static bool qsfp_plus_nim_get_supply_voltage(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_VOLT_LIN_ADDR,
+ NIM_OPTION_SUPPLY, 1, p_value);
+}
+
+/*
+ * Read NIM bias current for four lanes
+ */
+static bool qsfp_plus_nim_get_tx_bias_current(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_BIAS_LIN_ADDR,
+ NIM_OPTION_TX_BIAS, 4, p_value);
+}
+
+/*
+ * Read NIM TX optical power for four lanes
+ */
+static bool qsfp_plus_nim_get_tx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_PWR_LIN_ADDR,
+ NIM_OPTION_TX_POWER, 4, p_value);
+}
+
+/*
+ * Read NIM RX optical power for four lanes
+ */
+static bool qsfp_plus_nim_get_rx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return qsfp_plus_nim_get_sensor(ctx, QSFP_TX_PWR_LIN_ADDR,
+ NIM_OPTION_RX_POWER, 4, p_value);
+}
+
+void nim_read_qsfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ int16_t res;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (qsfp_plus_nim_get_temperature(sg->ctx, &res))
+ update_sensor_value(sg->sensor, (int)(res * 10 / 256));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_qsfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t res;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (qsfp_plus_nim_get_supply_voltage(sg->ctx, &res))
+ update_sensor_value(sg->sensor, (int)((res) / 10));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_qsfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp[4] = { 0 };
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ bool res = qsfp_plus_nim_get_tx_bias_current(sg->ctx, temp);
+
+ if (res) {
+ for (uint8_t i = 0; i < sg->ctx->lane_count; i++)
+ update_sensor_value(sg->sensor, (int)temp[i] * 2);
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
+
+void nim_read_qsfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp[4] = { 0 };
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ bool res = qsfp_plus_nim_get_tx_power(sg->ctx, temp);
+
+ if (res) {
+ for (uint8_t i = 0; i < sg->ctx->lane_count; i++)
+ update_sensor_value(sg->sensor, (int)temp[i]);
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
+
+void nim_read_qsfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp[4] = { 0 };
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ bool res = qsfp_plus_nim_get_rx_power(sg->ctx, temp);
+
+ if (res) {
+ for (uint8_t i = 0; i < sg->ctx->lane_count; i++)
+ update_sensor_value(sg->sensor, (int)temp[i]);
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
diff --git a/drivers/net/ntnic/nim/qsfp_sensors.h b/drivers/net/ntnic/nim/qsfp_sensors.h
new file mode 100644
index 0000000000..de64b978cb
--- /dev/null
+++ b/drivers/net/ntnic/nim/qsfp_sensors.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _QSFP_H
+#define _QSFP_H
+
+#include "sensors.h"
+#include "i2c_nim.h"
+
+/* Read functions */
+void nim_read_qsfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_qsfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+
+#endif /* _QSFP_H */
diff --git a/drivers/net/ntnic/nim/sfp_p_registers.h b/drivers/net/ntnic/nim/sfp_p_registers.h
new file mode 100644
index 0000000000..a0fbe2afd7
--- /dev/null
+++ b/drivers/net/ntnic/nim/sfp_p_registers.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SFP_P_REG_H
+#define _SFP_P_REG_H
+
+/*
+ * SFP/SFP+ Registers
+ */
+#define SFP_GB_ETH_COMP_CODES_LIN_ADDR 6
+#define SFP_GB_ETH_COMP_1000BASET_BIT (1 << 3)
+#define SFP_GB_ETH_COMP_1000BASECX_BIT (1 << 2)
+#define SFP_GB_ETH_COMP_1000BASELX_BIT (1 << 1)
+#define SFP_GB_ETH_COMP_1000BASESX_BIT (1 << 0)
+
+#define SFP_FIBER_CHAN_TRANS_TECH_LIN_ADDR 8
+#define SFP_FIBER_CHAN_TRANS_TECH_ACTIVE_CU_BIT (1 << 3)
+#define SFP_FIBER_CHAN_TRANS_TECH_PASSIVE_CU_BIT (1 << 2)
+
+#define SFP_FIBER_CHAN_TRANS_MEDIA_LIN_ADDR 9
+#define SFP_FIBER_CHAN_TRANS_MEDIA_MM62_BIT (1 << 3)
+#define SFP_FIBER_CHAN_TRANS_MEDIA_MM50_BIT (1 << 2)
+#define SFP_FIBER_CHAN_TRANS_MEDIA_SM_BIT (1 << 0)
+
+#define SFP_CU_LINK_LEN_LIN_ADDR 18 /* 1byte */
+#define SFP_SUP_LEN_INFO_LIN_ADDR 14 /* 5bytes */
+#define SFP_CU_LINK_LEN_LIN_ADDR 18 /* 1byte */
+#define SFP_VENDOR_NAME_LIN_ADDR 20 /* 16bytes */
+#define SFP_VENDOR_PN_LIN_ADDR 40 /* 16bytes */
+#define SFP_VENDOR_REV_LIN_ADDR 56 /* 4bytes */
+#define SFP_VENDOR_SN_LIN_ADDR 68 /* 16bytes */
+#define SFP_VENDOR_DATE_LIN_ADDR 84 /* 8bytes */
+
+/* The following field is only relevant to SFP+ and is marked as reserved for SFP */
+#define SFP_OPTION0_LIN_ADDR 64
+#define SFP_POWER_LEVEL2_REQ_BIT (1 << 1)
+
+#define SFP_DMI_OPTION_LIN_ADDR (92)
+#define SFP_DMI_IMPL_BIT (1 << 6)
+#define SFP_DMI_EXT_CAL_BIT (1 << 4)
+#define SFP_DMI_AVG_PWR_BIT (1 << 3)
+#define SFP_DMI_ADDR_CHG_BIT (1 << 2)
+
+#define SFP_ENHANCED_OPTIONS_LIN_ADDR (93)
+#define SFP_SOFT_TX_FAULT_IMPL_BIT (1 << 5)
+#define SFP_SOFT_TX_DISABLE_IMPL_BIT (1 << 6)
+
+#define SFP_SFF8472_COMPLIANCE_LIN_ADDR 94
+
+#define SFP_TEMP_THRESH_LIN_ADDR (0 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_VOLT_THRESH_LIN_ADDR (8 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_TX_BIAS_THRESH_LIN_ADDR (16 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_TX_PWR_THRESH_LIN_ADDR (24 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+#define SFP_RX_PWR_THRESH_LIN_ADDR (32 + 256)
+/* 8bytes: HighAlarm, LowAlarm, HighWarn, LowWarn each 2 bytes */
+
+/* Calibration data addresses */
+#define SFP_RX_PWR_COEFF_LIN_ADDR (56 + 256) /* 5 x 32bit float values */
+
+#define SFP_TX_BIAS_SLOPE_LIN_ADDR (76 + 256)
+#define SFP_TX_BIAS_OFFSET_LIN_ADDR (78 + 256)
+
+#define SFP_TX_PWR_SLOPE_LIN_ADDR (80 + 256)
+#define SFP_TX_PWR_OFFSET_LIN_ADDR (82 + 256)
+
+#define SFP_TEMP_SLOPE_LIN_ADDR (84 + 256)
+#define SFP_TEMP_OFFSET_LIN_ADDR (86 + 256)
+
+#define SFP_VOLT_SLOPE_LIN_ADDR (88 + 256)
+#define SFP_VOLT_OFFSET_LIN_ADDR (90 + 256)
+
+/* Live data */
+#define SFP_TEMP_LIN_ADDR (96 + 256)
+#define SFP_VOLT_LIN_ADDR (98 + 256)
+#define SFP_TX_BIAS_LIN_ADDR (100 + 256)
+#define SFP_TX_PWR_LIN_ADDR (102 + 256)
+#define SFP_RX_PWR_LIN_ADDR (104 + 256)
+
+#define SFP_SOFT_RATE0_BIT (1 << 3)
+#define SFP_TX_FAULT_SET_BIT (1 << 2)
+
+#define SFP_EXT_CTRL_STAT0_LIN_ADDR (118 + 256) /* 0xA2 area */
+#define SFP_SOFT_RATE1_BIT (1 << 3)
+#define SFP_POWER_LEVEL2_GET_BIT (1 << 1) /* For reading the actual level */
+#define SFP_POWER_LEVEL2_SET_BIT (1 << 0) /* For setting the wanted level */
+
+/* PHY addresses */
+#define SFP_PHY_LIN_ADDR (12 * 128)
+#define SFP_PHY_LIN_RNG 32 /* 16bit words */
+
+#endif /* _SFP_P_REG_H */
diff --git a/drivers/net/ntnic/nim/sfp_sensors.c b/drivers/net/ntnic/nim/sfp_sensors.c
new file mode 100644
index 0000000000..766d6feaf3
--- /dev/null
+++ b/drivers/net/ntnic/nim/sfp_sensors.c
@@ -0,0 +1,288 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <arpa/inet.h>
+#include <stdbool.h>
+
+#include "ntlog.h"
+#include "sfp_sensors.h"
+
+#include "sfp_p_registers.h"
+
+/*
+ * Return calibrated data from an SFP module.
+ * It is first investigated if external calibration is to be used and if it is
+ * calibration data is retrieved. The function can only be used when calibration
+ * consists of a slope and offset factor. After function return p_data will point
+ * to 16bit data that can be either signed or unsigned.
+ */
+static bool sfp_nim_get_dmi_data(uint16_t data_addr, uint16_t slope_addr,
+ uint16_t offset_addr, void *p_value,
+ bool signed_data, nim_i2c_ctx_p ctx)
+{
+ int32_t value;
+ uint16_t slope = 1;
+ int16_t offset = 0;
+
+ if (!ctx->dmi_supp)
+ return false;
+
+ /* Read data in big endian format */
+ read_data_lin(ctx, data_addr, 2, p_value);
+ *(uint16_t *)p_value =
+ htons(*(uint16_t *)p_value); /* Swap to little endian */
+
+ /*
+ * Inject test value which can be both signed and unsigned but handle
+ * here as unsigned
+ */
+#ifdef NIM_DMI_TEST_VALUE
+ *(uint16_t *)p_value = (uint16_t)NIM_DMI_TEST_VALUE;
+#endif
+
+#if defined(NIM_DMI_TEST_SLOPE) || defined(NIM_DMI_TEST_OFFSET)
+ ctx->specific_u.sfp.ext_cal = true;
+#endif
+
+ if (ctx->specific_u.sfp.ext_cal) {
+ /* External calibration is needed */
+ read_data_lin(ctx, slope_addr, sizeof(slope), &slope);
+ read_data_lin(ctx, offset_addr, sizeof(offset), &offset);
+
+ /* Swap calibration to little endian */
+ slope = htons(slope);
+ offset = htons(offset);
+
+#ifdef NIM_DMI_TEST_SLOPE
+ slope = NIM_DMI_TEST_SLOPE;
+#endif
+
+#ifdef NIM_DMI_TEST_OFFSET
+ offset = NIM_DMI_TEST_OFFSET; /* 0x0140 equals 1.25 */
+#endif
+
+ if (signed_data) {
+ value = *(int16_t *)p_value * slope / 256 + offset;
+
+ if (value > INT16_MAX)
+ value = INT16_MAX;
+ else if (value < INT16_MIN)
+ value = INT16_MIN;
+
+ *(int16_t *)p_value = (int16_t)value;
+ } else {
+ value = *(uint16_t *)p_value * slope / 256 + offset;
+
+ if (value > UINT16_MAX)
+ value = UINT16_MAX;
+ else if (value < 0)
+ value = 0;
+
+ *(uint16_t *)p_value = (uint16_t)value;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Read NIM temperature
+ */
+static bool sfp_nim_get_temperature(nim_i2c_ctx_p ctx, int16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_TEMP_LIN_ADDR, SFP_TEMP_SLOPE_LIN_ADDR,
+ SFP_TEMP_OFFSET_LIN_ADDR, p_value, true, ctx);
+}
+
+/*
+ * Read NIM supply voltage
+ */
+static bool sfp_nim_get_supply_voltage(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_VOLT_LIN_ADDR, SFP_VOLT_SLOPE_LIN_ADDR,
+ SFP_VOLT_OFFSET_LIN_ADDR, p_value, false, ctx);
+}
+
+/*
+ * Read NIM bias current
+ */
+static bool sfp_nim_get_tx_bias_current(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_TX_BIAS_LIN_ADDR,
+ SFP_TX_BIAS_SLOPE_LIN_ADDR,
+ SFP_TX_BIAS_OFFSET_LIN_ADDR, p_value, false,
+ ctx);
+}
+
+/*
+ * Read NIM TX optical power
+ */
+static bool sfp_nim_get_tx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_dmi_data(SFP_TX_PWR_LIN_ADDR,
+ SFP_TX_PWR_SLOPE_LIN_ADDR,
+ SFP_TX_PWR_OFFSET_LIN_ADDR, p_value, false,
+ ctx);
+}
+
+/*
+ * Return the SFP received power in units of 0.1uW from DMI data.
+ * If external calibration is necessary, the calibration data is retrieved and
+ * the calibration is carried out.
+ */
+static bool sfp_nim_get_calibrated_rx_power(nim_i2c_ctx_p ctx, uint16_t addr,
+ uint16_t *p_value)
+{
+ float rx_pwr_cal[5];
+ float power_raised;
+ float rx_power;
+
+ /* Read data in big endian format */
+ read_data_lin(ctx, addr, sizeof(*p_value), p_value);
+ *(uint16_t *)p_value =
+ htons(*(uint16_t *)p_value); /* Swap to little endian */
+
+#ifdef NIM_DMI_RX_PWR_TEST_VALUE
+ *p_value = NIM_DMI_RX_PWR_TEST_VALUE;
+#endif
+
+#ifdef NIM_DMI_RX_PWR_CAL_DATA
+ ctx->specific_u.sfp.ext_cal = true;
+#endif
+
+ if (ctx->specific_u.sfp.ext_cal) {
+ /* Read calibration data in big endian format */
+ read_data_lin(ctx, SFP_RX_PWR_COEFF_LIN_ADDR, sizeof(rx_pwr_cal),
+ rx_pwr_cal);
+
+ for (int i = 0; i < 5; i++) {
+ uint32_t *p_val = (uint32_t *)&rx_pwr_cal[i];
+ *p_val = ntohl(*p_val); /* 32 bit swap */
+ }
+
+#ifdef NIM_DMI_RX_PWR_CAL_DATA
+ /* Testdata for verification */
+ NIM_DMI_RX_PWR_CAL_DATA
+#endif
+
+ /*
+ * If SFP module specifies external calibration - use calibration data
+ * according to the polynomial correction formula
+ * RxPwrCal = Coeff0 + Coeff1 * RxPwr + Coeff2 * RxPwr^2 +
+ * Coeff3 * RxPwr^3 + Coeff4 * RxPwr^4
+ */
+ power_raised = 1.0;
+ rx_power = rx_pwr_cal[4]; /* Coeff0 */
+
+ for (int i = 3; i >= 0; i--) {
+ power_raised *= (float)*p_value;
+ rx_power += rx_pwr_cal[i] * power_raised;
+ }
+
+ /* Check out for out of range */
+ if (rx_power > 65535)
+ return false;
+
+ if (rx_power < 0)
+ *p_value = 0;
+ else
+ *p_value = (uint16_t)rx_power;
+ }
+
+ return true;
+}
+
+/*
+ * Read RX optical power if it exists
+ */
+static bool sfp_nim_get_rx_power(nim_i2c_ctx_p ctx, uint16_t *p_value)
+{
+ return sfp_nim_get_calibrated_rx_power(ctx, SFP_RX_PWR_LIN_ADDR, p_value);
+}
+
+void nim_read_sfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ int16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_temperature(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)(temp * 10 / 256));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_sfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_supply_voltage(sg->ctx, &temp)) {
+ update_sensor_value(sg->sensor,
+ (int)(temp / 10)); /* Unit: 100uV -> 1mV */
+ } else {
+ update_sensor_value(sg->sensor, -1);
+ }
+}
+
+void nim_read_sfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_tx_bias_current(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)(temp * 2));
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_sfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_tx_power(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)temp);
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
+
+void nim_read_sfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint16_t temp;
+ (void)t_spi;
+
+ if (sg == NULL || sg->ctx == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+
+ if (sfp_nim_get_rx_power(sg->ctx, &temp))
+ update_sensor_value(sg->sensor, (int)temp);
+
+ else
+ update_sensor_value(sg->sensor, -1);
+}
diff --git a/drivers/net/ntnic/nim/sfp_sensors.h b/drivers/net/ntnic/nim/sfp_sensors.h
new file mode 100644
index 0000000000..ab56027dc8
--- /dev/null
+++ b/drivers/net/ntnic/nim/sfp_sensors.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SFP_H
+#define _SFP_H
+
+#include "sensors.h"
+#include "i2c_nim.h"
+
+/* Read functions */
+void nim_read_sfp_temp(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_voltage(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_bias_current(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_tx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+void nim_read_sfp_rx_power(struct nim_sensor_group *sg, nthw_spis_t *t_spi);
+
+#endif /* _SFP_H */
diff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
index efdcc222a8..bd7cd2a27c 100644
--- a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c
@@ -5,5 +5,12 @@
#include "nthw_clock_profiles.h"
/* Clock profile for NT200A02 2x40G, 2x100G */
-const int n_data_si5340_nt200a02_u23_v5;
-const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;
+#define si5340_revd_register_t type_si5340_nt200a02_u23_v5
+#define si5340_revd_registers data_si5340_nt200a02_u23_v5
+#include "nthw_nt200a02_u23_si5340_v5.h"
+const int n_data_si5340_nt200a02_u23_v5 = SI5340_REVD_REG_CONFIG_NUM_REGS;
+const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5 =
+ (const clk_profile_data_fmt2_t *)&data_si5340_nt200a02_u23_v5[0];
+#undef si5340_revd_registers
+#undef si5340_revd_register_t
+#undef SI5340_REVD_REG_CONFIG_HEADER /*Disable the include once protection */
diff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h
index 798a95d5cf..025b6b61cc 100644
--- a/drivers/net/ntnic/nthw/core/nthw_core.h
+++ b/drivers/net/ntnic/nthw/core/nthw_core.h
@@ -16,9 +16,11 @@
#include "nthw_pci_ta.h"
#include "nthw_iic.h"
+#include "nthw_gmf.h"
#include "nthw_gpio_phy.h"
#include "nthw_mac_pcs.h"
#include "nthw_mac_pcs_xxv.h"
+#include "nthw_rmc.h"
#include "nthw_sdc.h"
#include "nthw_spim.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.c b/drivers/net/ntnic/nthw/core/nthw_gmf.c
new file mode 100644
index 0000000000..fe63c461e5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gmf.c
@@ -0,0 +1,290 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <limits.h>
+#include <math.h>
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_gmf.h"
+
+nthw_gmf_t *nthw_gmf_new(void)
+{
+ nthw_gmf_t *p = malloc(sizeof(nthw_gmf_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_gmf_t));
+ return p;
+}
+
+void nthw_gmf_delete(nthw_gmf_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_gmf_t));
+ free(p);
+ }
+}
+
+int nthw_gmf_init(nthw_gmf_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ nt_module_t *mod = fpga_query_module(p_fpga, MOD_GMF, n_instance);
+
+ if (p == NULL)
+ return mod == NULL ? -1 : 0;
+
+ if (mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: GMF %d: no such instance\n",
+ p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_gmf = mod;
+
+ p->mp_ctrl = module_get_register(p->mp_mod_gmf, GMF_CTRL);
+ p->mp_ctrl_enable = register_get_field(p->mp_ctrl, GMF_CTRL_ENABLE);
+ p->mp_ctrl_ifg_enable = register_get_field(p->mp_ctrl, GMF_CTRL_IFG_ENABLE);
+ p->mp_ctrl_ifg_auto_adjust_enable =
+ register_get_field(p->mp_ctrl, GMF_CTRL_IFG_AUTO_ADJUST_ENABLE);
+
+ p->mp_speed = module_get_register(p->mp_mod_gmf, GMF_SPEED);
+ p->mp_speed_ifg_speed = register_get_field(p->mp_speed, GMF_SPEED_IFG_SPEED);
+
+ p->mp_ifg_clock_delta =
+ module_get_register(p->mp_mod_gmf, GMF_IFG_SET_CLOCK_DELTA);
+ p->mp_ifg_clock_delta_delta =
+ register_get_field(p->mp_ifg_clock_delta, GMF_IFG_SET_CLOCK_DELTA_DELTA);
+
+ p->mp_ifg_max_adjust_slack =
+ module_get_register(p->mp_mod_gmf, GMF_IFG_MAX_ADJUST_SLACK);
+ p->mp_ifg_max_adjust_slack_slack =
+ register_get_field(p->mp_ifg_max_adjust_slack, GMF_IFG_MAX_ADJUST_SLACK_SLACK);
+
+ p->mp_debug_lane_marker =
+ module_get_register(p->mp_mod_gmf, GMF_DEBUG_LANE_MARKER);
+ p->mp_debug_lane_marker_compensation =
+ register_get_field(p->mp_debug_lane_marker, GMF_DEBUG_LANE_MARKER_COMPENSATION);
+
+ p->mp_stat_sticky = module_get_register(p->mp_mod_gmf, GMF_STAT_STICKY);
+ p->mp_stat_sticky_data_underflowed =
+ register_get_field(p->mp_stat_sticky, GMF_STAT_STICKY_DATA_UNDERFLOWED);
+ p->mp_stat_sticky_ifg_adjusted =
+ register_get_field(p->mp_stat_sticky, GMF_STAT_STICKY_IFG_ADJUSTED);
+
+ p->mn_param_gmf_ifg_speed_mul =
+ fpga_get_product_param(p_fpga, NT_GMF_IFG_SPEED_MUL, 1);
+ p->mn_param_gmf_ifg_speed_div =
+ fpga_get_product_param(p_fpga, NT_GMF_IFG_SPEED_DIV, 1);
+
+ p->m_administrative_block = false;
+
+ p->mp_stat_next_pkt = module_query_register(p->mp_mod_gmf, GMF_STAT_NEXT_PKT);
+ if (p->mp_stat_next_pkt) {
+ p->mp_stat_next_pkt_ns =
+ register_query_field(p->mp_stat_next_pkt,
+ GMF_STAT_NEXT_PKT_NS);
+ } else {
+ p->mp_stat_next_pkt_ns = NULL;
+ }
+ p->mp_stat_max_delayed_pkt =
+ module_query_register(p->mp_mod_gmf, GMF_STAT_MAX_DELAYED_PKT);
+ if (p->mp_stat_max_delayed_pkt) {
+ p->mp_stat_max_delayed_pkt_ns =
+ register_query_field(p->mp_stat_max_delayed_pkt,
+ GMF_STAT_MAX_DELAYED_PKT_NS);
+ } else {
+ p->mp_stat_max_delayed_pkt_ns = NULL;
+ }
+ p->mp_ctrl_ifg_tx_now_always =
+ register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_NOW_ALWAYS);
+ p->mp_ctrl_ifg_tx_on_ts_always =
+ register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_ON_TS_ALWAYS);
+
+ p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock =
+ register_query_field(p->mp_ctrl, GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK);
+
+ p->mp_ifg_clock_delta_adjust =
+ module_query_register(p->mp_mod_gmf, GMF_IFG_SET_CLOCK_DELTA_ADJUST);
+ if (p->mp_ifg_clock_delta_adjust) {
+ p->mp_ifg_clock_delta_adjust_delta =
+ register_query_field(p->mp_ifg_clock_delta_adjust,
+ GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA);
+ } else {
+ p->mp_ifg_clock_delta_adjust_delta = NULL;
+ }
+ return 0;
+}
+
+void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable)
+{
+ if (!p->m_administrative_block)
+ field_set_val_flush32(p->mp_ctrl_enable, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_ifg_enable(nthw_gmf_t *p, bool enable)
+{
+ field_set_val_flush32(p->mp_ctrl_ifg_enable, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_tx_now_always_enable(nthw_gmf_t *p, bool enable)
+{
+ if (p->mp_ctrl_ifg_tx_now_always)
+ field_set_val_flush32(p->mp_ctrl_ifg_tx_now_always, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_tx_on_ts_always_enable(nthw_gmf_t *p, bool enable)
+{
+ if (p->mp_ctrl_ifg_tx_on_ts_always)
+ field_set_val_flush32(p->mp_ctrl_ifg_tx_on_ts_always, enable ? 1 : 0);
+}
+
+void nthw_gmf_set_tx_on_ts_adjust_on_set_clock(nthw_gmf_t *p, bool enable)
+{
+ if (p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock) {
+ field_set_val_flush32(p->mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock,
+ enable ? 1 : 0);
+ }
+}
+
+void nthw_gmf_set_ifg_auto_adjust_enable(nthw_gmf_t *p, bool enable)
+{
+ field_set_val_flush32(p->mp_ctrl_ifg_auto_adjust_enable, enable);
+}
+
+int nthw_gmf_set_ifg_speed_raw(nthw_gmf_t *p, uint64_t n_speed_val)
+{
+ if (n_speed_val <=
+ (1ULL << (field_get_bit_width(p->mp_speed_ifg_speed) - 1))) {
+ field_set_val(p->mp_speed_ifg_speed, (uint32_t *)&n_speed_val,
+ (field_get_bit_width(p->mp_speed_ifg_speed) <= 32 ? 1 :
+ 2));
+ field_flush_register(p->mp_speed_ifg_speed);
+ return 0;
+ }
+ return -1;
+}
+
+int nthw_gmf_get_ifg_speed_bit_width(nthw_gmf_t *p)
+{
+ const int n_bit_width = field_get_bit_width(p->mp_speed_ifg_speed);
+
+ assert(n_bit_width >=
+ 22); /* Sanity check: GMF ver 1.2 is bw 22 - GMF ver 1.3 is bw 64 */
+ return n_bit_width;
+}
+
+int nthw_gmf_set_ifg_speed_bits(nthw_gmf_t *p, const uint64_t n_rate_limit_bits,
+ const uint64_t n_link_speed)
+{
+ const int n_bit_width = (nthw_gmf_get_ifg_speed_bit_width(p) / 2);
+ const double f_adj_rate =
+ ((double)((((double)n_rate_limit_bits) / (double)n_link_speed) *
+ p->mn_param_gmf_ifg_speed_mul) /
+ p->mn_param_gmf_ifg_speed_div);
+ const double f_speed = ((1UL / f_adj_rate) - 1) * exp2(n_bit_width);
+ uint64_t n_speed_val = (uint64_t)round(f_speed);
+
+ return nthw_gmf_set_ifg_speed_raw(p, n_speed_val);
+}
+
+int nthw_gmf_set_ifg_speed_percent(nthw_gmf_t *p, const double f_rate_limit_percent)
+{
+ uint64_t n_speed_val;
+
+ if (f_rate_limit_percent == 0.0 || f_rate_limit_percent == 100.0) {
+ n_speed_val = 0;
+ } else if (f_rate_limit_percent <= 99) {
+ const int n_bit_width = (nthw_gmf_get_ifg_speed_bit_width(p) / 2);
+ const double f_adj_rate =
+ ((double)(f_rate_limit_percent *
+ (double)p->mn_param_gmf_ifg_speed_mul) /
+ p->mn_param_gmf_ifg_speed_div / 100);
+ const double f_speed = ((1UL / f_adj_rate) - 1) * exp2(n_bit_width);
+
+ n_speed_val = (uint64_t)f_speed;
+ } else {
+ return -1;
+ }
+
+ return nthw_gmf_set_ifg_speed_raw(p, n_speed_val);
+}
+
+void nthw_gmf_set_delta(nthw_gmf_t *p, uint64_t delta)
+{
+ field_set_val(p->mp_ifg_clock_delta_delta, (uint32_t *)&delta, 2);
+ field_flush_register(p->mp_ifg_clock_delta_delta);
+}
+
+void nthw_gmf_set_delta_adjust(nthw_gmf_t *p, uint64_t delta_adjust)
+{
+ if (p->mp_ifg_clock_delta_adjust) {
+ field_set_val(p->mp_ifg_clock_delta_adjust_delta,
+ (uint32_t *)&delta_adjust, 2);
+ field_flush_register(p->mp_ifg_clock_delta_adjust_delta);
+ }
+}
+
+void nthw_gmf_set_slack(nthw_gmf_t *p, uint64_t slack)
+{
+ field_set_val(p->mp_ifg_max_adjust_slack_slack, (uint32_t *)&slack, 2);
+ field_flush_register(p->mp_ifg_max_adjust_slack_slack);
+}
+
+void nthw_gmf_set_compensation(nthw_gmf_t *p, uint32_t compensation)
+{
+ field_set_val_flush32(p->mp_debug_lane_marker_compensation, compensation);
+}
+
+uint32_t nthw_gmf_get_status_sticky(nthw_gmf_t *p)
+{
+ uint32_t status = 0;
+
+ register_update(p->mp_stat_sticky);
+
+ if (field_get_val32(p->mp_stat_sticky_data_underflowed))
+ status |= GMF_STATUS_MASK_DATA_UNDERFLOWED;
+ if (field_get_val32(p->mp_stat_sticky_ifg_adjusted))
+ status |= GMF_STATUS_MASK_IFG_ADJUSTED;
+
+ return status;
+}
+
+void nthw_gmf_set_status_sticky(nthw_gmf_t *p, uint32_t status)
+{
+ if (status & GMF_STATUS_MASK_DATA_UNDERFLOWED)
+ field_set_flush(p->mp_stat_sticky_data_underflowed);
+ if (status & GMF_STATUS_MASK_IFG_ADJUSTED)
+ field_set_flush(p->mp_stat_sticky_ifg_adjusted);
+}
+
+uint64_t nthw_gmf_get_stat_next_pkt_ns(nthw_gmf_t *p)
+{
+ uint64_t value = ULONG_MAX;
+
+ if (p->mp_stat_next_pkt) {
+ register_update(p->mp_stat_next_pkt);
+ field_get_val(p->mp_stat_next_pkt_ns, (uint32_t *)&value, 2);
+ }
+ return value;
+}
+
+uint64_t nthw_gmf_get_stat_max_pk_delayedt_ns(nthw_gmf_t *p)
+{
+ uint64_t value = ULONG_MAX;
+
+ if (p->mp_stat_max_delayed_pkt) {
+ register_update(p->mp_stat_max_delayed_pkt);
+ field_get_val(p->mp_stat_max_delayed_pkt_ns, (uint32_t *)&value, 2);
+ }
+ return value;
+}
+
+void nthw_gmf_administrative_block(nthw_gmf_t *p)
+{
+ nthw_gmf_set_enable(p, false);
+ p->m_administrative_block = true;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.h b/drivers/net/ntnic/nthw/core/nthw_gmf.h
new file mode 100644
index 0000000000..aec1342be7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gmf.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_GMF_H__
+#define __NTHW_GMF_H__
+
+enum gmf_status_mask {
+ GMF_STATUS_MASK_DATA_UNDERFLOWED = 1,
+ GMF_STATUS_MASK_IFG_ADJUSTED
+};
+
+struct nthw_gmf {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_gmf;
+ int mn_instance;
+ /* */
+
+ nt_register_t *mp_ctrl;
+ nt_field_t *mp_ctrl_enable;
+ nt_field_t *mp_ctrl_ifg_enable;
+ nt_field_t *mp_ctrl_ifg_tx_now_always;
+ nt_field_t *mp_ctrl_ifg_tx_on_ts_always;
+ nt_field_t *mp_ctrl_ifg_tx_on_ts_adjust_on_set_clock;
+ nt_field_t *mp_ctrl_ifg_auto_adjust_enable;
+
+ nt_register_t *mp_speed;
+ nt_field_t *mp_speed_ifg_speed;
+
+ nt_register_t *mp_ifg_clock_delta;
+ nt_field_t *mp_ifg_clock_delta_delta;
+
+ nt_register_t *mp_ifg_clock_delta_adjust;
+ nt_field_t *mp_ifg_clock_delta_adjust_delta;
+
+ nt_register_t *mp_ifg_max_adjust_slack;
+ nt_field_t *mp_ifg_max_adjust_slack_slack;
+
+ nt_register_t *mp_debug_lane_marker;
+ nt_field_t *mp_debug_lane_marker_compensation;
+
+ nt_register_t *mp_stat_sticky;
+ nt_field_t *mp_stat_sticky_data_underflowed;
+ nt_field_t *mp_stat_sticky_ifg_adjusted;
+
+ nt_register_t *mp_stat_next_pkt;
+ nt_field_t *mp_stat_next_pkt_ns;
+
+ nt_register_t *mp_stat_max_delayed_pkt;
+ nt_field_t *mp_stat_max_delayed_pkt_ns;
+
+ int mn_param_gmf_ifg_speed_mul;
+ int mn_param_gmf_ifg_speed_div;
+
+ bool m_administrative_block; /* Used to enforce license expiry */
+};
+
+typedef struct nthw_gmf nthw_gmf_t;
+typedef struct nthw_gmf nthw_gmf;
+
+nthw_gmf_t *nthw_gmf_new(void);
+void nthw_gmf_delete(nthw_gmf_t *p);
+int nthw_gmf_init(nthw_gmf_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_ifg_enable(nthw_gmf_t *p, bool enable);
+
+void nthw_gmf_set_tx_now_always_enable(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_tx_on_ts_always_enable(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_tx_on_ts_adjust_on_set_clock(nthw_gmf_t *p, bool enable);
+void nthw_gmf_set_ifg_auto_adjust_enable(nthw_gmf_t *p, bool enable);
+
+int nthw_gmf_get_ifg_speed_bit_width(nthw_gmf_t *p);
+
+int nthw_gmf_set_ifg_speed_raw(nthw_gmf_t *p, uint64_t n_speed_val);
+int nthw_gmf_set_ifg_speed_bits(nthw_gmf_t *p, const uint64_t n_rate_limit_bits,
+ const uint64_t n_link_speed);
+int nthw_gmf_set_ifg_speed_percent(nthw_gmf_t *p, const double f_rate_limit_percent);
+
+void nthw_gmf_set_delta(nthw_gmf_t *p, uint64_t delta);
+void nthw_gmf_set_delta_adjust(nthw_gmf_t *p, uint64_t delta_adjust);
+void nthw_gmf_set_slack(nthw_gmf_t *p, uint64_t slack);
+void nthw_gmf_set_compensation(nthw_gmf_t *p, uint32_t compensation);
+
+uint32_t nthw_gmf_get_status_sticky(nthw_gmf_t *p);
+void nthw_gmf_set_status_sticky(nthw_gmf_t *p, uint32_t status);
+
+uint64_t nthw_gmf_get_stat_next_pkt_ns(nthw_gmf_t *p);
+uint64_t nthw_gmf_get_stat_max_pk_delayedt_ns(nthw_gmf_t *p);
+
+void nthw_gmf_administrative_block(nthw_gmf_t *p); /* Used to enforce license expiry blocking */
+
+#endif /* __NTHW_GMF_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h b/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h
new file mode 100644
index 0000000000..f063a1048a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_nt200a02_u23_si5340_v5.h
@@ -0,0 +1,344 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef SI5340_REVD_REG_CONFIG_HEADER
+#define SI5340_REVD_REG_CONFIG_HEADER
+
+#define SI5340_REVD_REG_CONFIG_NUM_REGS 326
+
+typedef struct {
+ unsigned int address; /* 16-bit register address */
+ unsigned char value; /* 8-bit register data */
+} si5340_revd_register_t;
+
+si5340_revd_register_t const si5340_revd_registers[SI5340_REVD_REG_CONFIG_NUM_REGS] = {
+ { 0x0B24, 0xC0 },
+ { 0x0B25, 0x00 },
+ { 0x0502, 0x01 },
+ { 0x0505, 0x03 },
+ { 0x0957, 0x17 },
+ { 0x0B4E, 0x1A },
+ { 0x0006, 0x00 },
+ { 0x0007, 0x00 },
+ { 0x0008, 0x00 },
+ { 0x000B, 0x74 },
+ { 0x0017, 0xF0 },
+ { 0x0018, 0xFF },
+ { 0x0021, 0x0F },
+ { 0x0022, 0x00 },
+ { 0x002B, 0x0A },
+ { 0x002C, 0x20 },
+ { 0x002D, 0x00 },
+ { 0x002E, 0x00 },
+ { 0x002F, 0x00 },
+ { 0x0030, 0x00 },
+ { 0x0031, 0x00 },
+ { 0x0032, 0x00 },
+ { 0x0033, 0x00 },
+ { 0x0034, 0x00 },
+ { 0x0035, 0x00 },
+ { 0x0036, 0x00 },
+ { 0x0037, 0x00 },
+ { 0x0038, 0x00 },
+ { 0x0039, 0x00 },
+ { 0x003A, 0x00 },
+ { 0x003B, 0x00 },
+ { 0x003C, 0x00 },
+ { 0x003D, 0x00 },
+ { 0x0041, 0x00 },
+ { 0x0042, 0x00 },
+ { 0x0043, 0x00 },
+ { 0x0044, 0x00 },
+ { 0x009E, 0x00 },
+ { 0x0102, 0x01 },
+ { 0x0112, 0x02 },
+ { 0x0113, 0x09 },
+ { 0x0114, 0x3E },
+ { 0x0115, 0x19 },
+ { 0x0117, 0x06 },
+ { 0x0118, 0x09 },
+ { 0x0119, 0x3E },
+ { 0x011A, 0x18 },
+ { 0x0126, 0x06 },
+ { 0x0127, 0x09 },
+ { 0x0128, 0x3E },
+ { 0x0129, 0x18 },
+ { 0x012B, 0x06 },
+ { 0x012C, 0x09 },
+ { 0x012D, 0x3E },
+ { 0x012E, 0x1A },
+ { 0x013F, 0x00 },
+ { 0x0140, 0x00 },
+ { 0x0141, 0x40 },
+ { 0x0206, 0x00 },
+ { 0x0208, 0x00 },
+ { 0x0209, 0x00 },
+ { 0x020A, 0x00 },
+ { 0x020B, 0x00 },
+ { 0x020C, 0x00 },
+ { 0x020D, 0x00 },
+ { 0x020E, 0x00 },
+ { 0x020F, 0x00 },
+ { 0x0210, 0x00 },
+ { 0x0211, 0x00 },
+ { 0x0212, 0x00 },
+ { 0x0213, 0x00 },
+ { 0x0214, 0x00 },
+ { 0x0215, 0x00 },
+ { 0x0216, 0x00 },
+ { 0x0217, 0x00 },
+ { 0x0218, 0x00 },
+ { 0x0219, 0x00 },
+ { 0x021A, 0x00 },
+ { 0x021B, 0x00 },
+ { 0x021C, 0x00 },
+ { 0x021D, 0x00 },
+ { 0x021E, 0x00 },
+ { 0x021F, 0x00 },
+ { 0x0220, 0x00 },
+ { 0x0221, 0x00 },
+ { 0x0222, 0x00 },
+ { 0x0223, 0x00 },
+ { 0x0224, 0x00 },
+ { 0x0225, 0x00 },
+ { 0x0226, 0x00 },
+ { 0x0227, 0x00 },
+ { 0x0228, 0x00 },
+ { 0x0229, 0x00 },
+ { 0x022A, 0x00 },
+ { 0x022B, 0x00 },
+ { 0x022C, 0x00 },
+ { 0x022D, 0x00 },
+ { 0x022E, 0x00 },
+ { 0x022F, 0x00 },
+ { 0x0235, 0x00 },
+ { 0x0236, 0x00 },
+ { 0x0237, 0x00 },
+ { 0x0238, 0xA6 },
+ { 0x0239, 0x8B },
+ { 0x023A, 0x00 },
+ { 0x023B, 0x00 },
+ { 0x023C, 0x00 },
+ { 0x023D, 0x00 },
+ { 0x023E, 0x80 },
+ { 0x0250, 0x03 },
+ { 0x0251, 0x00 },
+ { 0x0252, 0x00 },
+ { 0x0253, 0x00 },
+ { 0x0254, 0x00 },
+ { 0x0255, 0x00 },
+ { 0x025C, 0x00 },
+ { 0x025D, 0x00 },
+ { 0x025E, 0x00 },
+ { 0x025F, 0x00 },
+ { 0x0260, 0x00 },
+ { 0x0261, 0x00 },
+ { 0x026B, 0x30 },
+ { 0x026C, 0x35 },
+ { 0x026D, 0x00 },
+ { 0x026E, 0x00 },
+ { 0x026F, 0x00 },
+ { 0x0270, 0x00 },
+ { 0x0271, 0x00 },
+ { 0x0272, 0x00 },
+ { 0x0302, 0x00 },
+ { 0x0303, 0x00 },
+ { 0x0304, 0x00 },
+ { 0x0305, 0x00 },
+ { 0x0306, 0x0D },
+ { 0x0307, 0x00 },
+ { 0x0308, 0x00 },
+ { 0x0309, 0x00 },
+ { 0x030A, 0x00 },
+ { 0x030B, 0x80 },
+ { 0x030C, 0x00 },
+ { 0x030D, 0x00 },
+ { 0x030E, 0x00 },
+ { 0x030F, 0x00 },
+ { 0x0310, 0x61 },
+ { 0x0311, 0x08 },
+ { 0x0312, 0x00 },
+ { 0x0313, 0x00 },
+ { 0x0314, 0x00 },
+ { 0x0315, 0x00 },
+ { 0x0316, 0x80 },
+ { 0x0317, 0x00 },
+ { 0x0318, 0x00 },
+ { 0x0319, 0x00 },
+ { 0x031A, 0x00 },
+ { 0x031B, 0xD0 },
+ { 0x031C, 0x1A },
+ { 0x031D, 0x00 },
+ { 0x031E, 0x00 },
+ { 0x031F, 0x00 },
+ { 0x0320, 0x00 },
+ { 0x0321, 0xA0 },
+ { 0x0322, 0x00 },
+ { 0x0323, 0x00 },
+ { 0x0324, 0x00 },
+ { 0x0325, 0x00 },
+ { 0x0326, 0x00 },
+ { 0x0327, 0x00 },
+ { 0x0328, 0x00 },
+ { 0x0329, 0x00 },
+ { 0x032A, 0x00 },
+ { 0x032B, 0x00 },
+ { 0x032C, 0x00 },
+ { 0x032D, 0x00 },
+ { 0x0338, 0x00 },
+ { 0x0339, 0x1F },
+ { 0x033B, 0x00 },
+ { 0x033C, 0x00 },
+ { 0x033D, 0x00 },
+ { 0x033E, 0x00 },
+ { 0x033F, 0x00 },
+ { 0x0340, 0x00 },
+ { 0x0341, 0x00 },
+ { 0x0342, 0x00 },
+ { 0x0343, 0x00 },
+ { 0x0344, 0x00 },
+ { 0x0345, 0x00 },
+ { 0x0346, 0x00 },
+ { 0x0347, 0x00 },
+ { 0x0348, 0x00 },
+ { 0x0349, 0x00 },
+ { 0x034A, 0x00 },
+ { 0x034B, 0x00 },
+ { 0x034C, 0x00 },
+ { 0x034D, 0x00 },
+ { 0x034E, 0x00 },
+ { 0x034F, 0x00 },
+ { 0x0350, 0x00 },
+ { 0x0351, 0x00 },
+ { 0x0352, 0x00 },
+ { 0x0359, 0x00 },
+ { 0x035A, 0x00 },
+ { 0x035B, 0x00 },
+ { 0x035C, 0x00 },
+ { 0x035D, 0x00 },
+ { 0x035E, 0x00 },
+ { 0x035F, 0x00 },
+ { 0x0360, 0x00 },
+ { 0x0802, 0x00 },
+ { 0x0803, 0x00 },
+ { 0x0804, 0x00 },
+ { 0x0805, 0x00 },
+ { 0x0806, 0x00 },
+ { 0x0807, 0x00 },
+ { 0x0808, 0x00 },
+ { 0x0809, 0x00 },
+ { 0x080A, 0x00 },
+ { 0x080B, 0x00 },
+ { 0x080C, 0x00 },
+ { 0x080D, 0x00 },
+ { 0x080E, 0x00 },
+ { 0x080F, 0x00 },
+ { 0x0810, 0x00 },
+ { 0x0811, 0x00 },
+ { 0x0812, 0x00 },
+ { 0x0813, 0x00 },
+ { 0x0814, 0x00 },
+ { 0x0815, 0x00 },
+ { 0x0816, 0x00 },
+ { 0x0817, 0x00 },
+ { 0x0818, 0x00 },
+ { 0x0819, 0x00 },
+ { 0x081A, 0x00 },
+ { 0x081B, 0x00 },
+ { 0x081C, 0x00 },
+ { 0x081D, 0x00 },
+ { 0x081E, 0x00 },
+ { 0x081F, 0x00 },
+ { 0x0820, 0x00 },
+ { 0x0821, 0x00 },
+ { 0x0822, 0x00 },
+ { 0x0823, 0x00 },
+ { 0x0824, 0x00 },
+ { 0x0825, 0x00 },
+ { 0x0826, 0x00 },
+ { 0x0827, 0x00 },
+ { 0x0828, 0x00 },
+ { 0x0829, 0x00 },
+ { 0x082A, 0x00 },
+ { 0x082B, 0x00 },
+ { 0x082C, 0x00 },
+ { 0x082D, 0x00 },
+ { 0x082E, 0x00 },
+ { 0x082F, 0x00 },
+ { 0x0830, 0x00 },
+ { 0x0831, 0x00 },
+ { 0x0832, 0x00 },
+ { 0x0833, 0x00 },
+ { 0x0834, 0x00 },
+ { 0x0835, 0x00 },
+ { 0x0836, 0x00 },
+ { 0x0837, 0x00 },
+ { 0x0838, 0x00 },
+ { 0x0839, 0x00 },
+ { 0x083A, 0x00 },
+ { 0x083B, 0x00 },
+ { 0x083C, 0x00 },
+ { 0x083D, 0x00 },
+ { 0x083E, 0x00 },
+ { 0x083F, 0x00 },
+ { 0x0840, 0x00 },
+ { 0x0841, 0x00 },
+ { 0x0842, 0x00 },
+ { 0x0843, 0x00 },
+ { 0x0844, 0x00 },
+ { 0x0845, 0x00 },
+ { 0x0846, 0x00 },
+ { 0x0847, 0x00 },
+ { 0x0848, 0x00 },
+ { 0x0849, 0x00 },
+ { 0x084A, 0x00 },
+ { 0x084B, 0x00 },
+ { 0x084C, 0x00 },
+ { 0x084D, 0x00 },
+ { 0x084E, 0x00 },
+ { 0x084F, 0x00 },
+ { 0x0850, 0x00 },
+ { 0x0851, 0x00 },
+ { 0x0852, 0x00 },
+ { 0x0853, 0x00 },
+ { 0x0854, 0x00 },
+ { 0x0855, 0x00 },
+ { 0x0856, 0x00 },
+ { 0x0857, 0x00 },
+ { 0x0858, 0x00 },
+ { 0x0859, 0x00 },
+ { 0x085A, 0x00 },
+ { 0x085B, 0x00 },
+ { 0x085C, 0x00 },
+ { 0x085D, 0x00 },
+ { 0x085E, 0x00 },
+ { 0x085F, 0x00 },
+ { 0x0860, 0x00 },
+ { 0x0861, 0x00 },
+ { 0x090E, 0x02 },
+ { 0x091C, 0x04 },
+ { 0x0943, 0x00 },
+ { 0x0949, 0x00 },
+ { 0x094A, 0x00 },
+ { 0x094E, 0x49 },
+ { 0x094F, 0x02 },
+ { 0x095E, 0x00 },
+ { 0x0A02, 0x00 },
+ { 0x0A03, 0x07 },
+ { 0x0A04, 0x01 },
+ { 0x0A05, 0x07 },
+ { 0x0A14, 0x00 },
+ { 0x0A1A, 0x00 },
+ { 0x0A20, 0x00 },
+ { 0x0A26, 0x00 },
+ { 0x0B44, 0x0F },
+ { 0x0B4A, 0x08 },
+ { 0x0B57, 0x0E },
+ { 0x0B58, 0x01 },
+ { 0x001C, 0x01 },
+ { 0x0B24, 0xC3 },
+ { 0x0B25, 0x02 },
+};
+
+#endif /* SI5340_REVD_REG_CONFIG_HEADER */
diff --git a/drivers/net/ntnic/nthw/core/nthw_rmc.c b/drivers/net/ntnic/nthw/core/nthw_rmc.c
new file mode 100644
index 0000000000..c4c6779ce0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_rmc.c
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_rmc.h"
+
+nthw_rmc_t *nthw_rmc_new(void)
+{
+ nthw_rmc_t *p = malloc(sizeof(nthw_rmc_t));
+
+ if (p)
+ memset(p, 0, sizeof(nthw_rmc_t));
+ return p;
+}
+
+void nthw_rmc_delete(nthw_rmc_t *p)
+{
+ if (p) {
+ memset(p, 0, sizeof(nthw_rmc_t));
+ free(p);
+ }
+}
+
+int nthw_rmc_init(nthw_rmc_t *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RMC, n_instance);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RMC %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->mn_instance = n_instance;
+ p->mp_mod_rmc = p_mod;
+
+ /* Params */
+ p->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH;
+ p->mn_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS,
+ fpga_get_product_param(p_fpga, NT_PORTS, 0));
+ p->mn_nims = fpga_get_product_param(p_fpga, NT_NIMS, 0);
+ p->mb_administrative_block = false;
+
+ NT_LOG(DBG, NTHW, "%s: RMC %d: vswitch=%d\n", p_adapter_id_str,
+ p->mn_instance, p->mb_is_vswitch);
+
+ p->mp_reg_ctrl = module_get_register(p->mp_mod_rmc, RMC_CTRL);
+
+ p->mp_fld_ctrl_block_stat_drop =
+ register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_STATT);
+ p->mp_fld_ctrl_block_keep_alive =
+ register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_KEEPA);
+ p->mp_fld_ctrl_block_mac_port =
+ register_get_field(p->mp_reg_ctrl, RMC_CTRL_BLOCK_MAC_PORT);
+
+ p->mp_reg_status = module_query_register(p->mp_mod_rmc, RMC_STATUS);
+ if (p->mp_reg_status) {
+ p->mp_fld_sf_ram_of =
+ register_get_field(p->mp_reg_status, RMC_STATUS_SF_RAM_OF);
+ p->mp_fld_descr_fifo_of =
+ register_get_field(p->mp_reg_status, RMC_STATUS_DESCR_FIFO_OF);
+ }
+
+ p->mp_reg_dbg = module_query_register(p->mp_mod_rmc, RMC_DBG);
+ if (p->mp_reg_dbg) {
+ p->mp_fld_dbg_merge =
+ register_get_field(p->mp_reg_dbg, RMC_DBG_MERGE);
+ }
+
+ p->mp_reg_mac_if = module_query_register(p->mp_mod_rmc, RMC_MAC_IF);
+ if (p->mp_reg_mac_if) {
+ p->mp_fld_mac_if_err =
+ register_get_field(p->mp_reg_mac_if, RMC_MAC_IF_ERR);
+ }
+ return 0;
+}
+
+uint32_t nthw_rmc_get_mac_block(nthw_rmc_t *p)
+{
+ return field_get_updated(p->mp_fld_ctrl_block_mac_port);
+}
+
+uint32_t nthw_rmc_get_status_sf_ram_of(nthw_rmc_t *p)
+{
+ return (p->mp_reg_status) ? field_get_updated(p->mp_fld_sf_ram_of) :
+ 0xffffffff;
+}
+
+uint32_t nthw_rmc_get_status_descr_fifo_of(nthw_rmc_t *p)
+{
+ return (p->mp_reg_status) ? field_get_updated(p->mp_fld_descr_fifo_of) :
+ 0xffffffff;
+}
+
+uint32_t nthw_rmc_get_dbg_merge(nthw_rmc_t *p)
+{
+ return (p->mp_reg_dbg) ? field_get_updated(p->mp_fld_dbg_merge) : 0xffffffff;
+}
+
+uint32_t nthw_rmc_get_mac_if_err(nthw_rmc_t *p)
+{
+ return (p->mp_reg_mac_if) ? field_get_updated(p->mp_fld_mac_if_err) :
+ 0xffffffff;
+}
+
+void nthw_rmc_set_mac_block(nthw_rmc_t *p, uint32_t mask)
+{
+ field_set_val_flush32(p->mp_fld_ctrl_block_mac_port, mask);
+}
+
+void nthw_rmc_block(nthw_rmc_t *p)
+{
+ /* BLOCK_STATT(0)=1 BLOCK_KEEPA(1)=1 BLOCK_MAC_PORT(8:11)=~0 */
+ if (!p->mb_administrative_block) {
+ field_set_flush(p->mp_fld_ctrl_block_stat_drop);
+ field_set_flush(p->mp_fld_ctrl_block_keep_alive);
+ field_set_flush(p->mp_fld_ctrl_block_mac_port);
+ }
+}
+
+void nthw_rmc_unblock(nthw_rmc_t *p, bool b_is_slave)
+{
+ uint32_t n_block_mask = ~0U << (b_is_slave ? p->mn_nims : p->mn_ports);
+
+ if (p->mb_is_vswitch) {
+ /*
+ * VSWITCH: NFV: block bits: phy_nim_ports(2) + rtd_ports(4) +
+ * roa_recirculate_port(1)
+ */
+ n_block_mask = 1 << (2 + 4); /* block only ROA recirculate */
+ }
+
+ /* BLOCK_STATT(0)=0 BLOCK_KEEPA(1)=0 BLOCK_MAC_PORT(8:11)=0 */
+ if (!p->mb_administrative_block) {
+ field_clr_flush(p->mp_fld_ctrl_block_stat_drop);
+ field_clr_flush(p->mp_fld_ctrl_block_keep_alive);
+ field_set_val_flush32(p->mp_fld_ctrl_block_mac_port, n_block_mask);
+ }
+}
+
+void nthw_rmc_administrative_block(nthw_rmc_t *p)
+{
+ /* block all MAC ports */
+ field_set_flush(p->mp_fld_ctrl_block_mac_port);
+ p->mb_administrative_block = true;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_rmc.h b/drivers/net/ntnic/nthw/core/nthw_rmc.h
new file mode 100644
index 0000000000..b40f0a0994
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_rmc.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_RMC_H_
+#define NTHW_RMC_H_
+
+struct nthw_rmc {
+ nt_fpga_t *mp_fpga;
+ nt_module_t *mp_mod_rmc;
+ int mn_instance;
+
+ int mn_ports;
+ int mn_nims;
+ bool mb_is_vswitch;
+
+ bool mb_administrative_block;
+
+ /* RMC CTRL register */
+ nt_register_t *mp_reg_ctrl;
+ nt_field_t *mp_fld_ctrl_block_stat_drop;
+ nt_field_t *mp_fld_ctrl_block_keep_alive;
+ nt_field_t *mp_fld_ctrl_block_mac_port;
+
+ /* RMC Status register */
+ nt_register_t *mp_reg_status;
+ nt_field_t *mp_fld_sf_ram_of;
+ nt_field_t *mp_fld_descr_fifo_of;
+
+ /* RMC DBG register */
+ nt_register_t *mp_reg_dbg;
+ nt_field_t *mp_fld_dbg_merge;
+
+ /* RMC MAC_IF register */
+ nt_register_t *mp_reg_mac_if;
+ nt_field_t *mp_fld_mac_if_err;
+};
+
+typedef struct nthw_rmc nthw_rmc_t;
+typedef struct nthw_rmc nthw_rmc;
+
+nthw_rmc_t *nthw_rmc_new(void);
+void nthw_rmc_delete(nthw_rmc_t *p);
+int nthw_rmc_init(nthw_rmc_t *p, nt_fpga_t *p_fpga, int n_instance);
+
+uint32_t nthw_rmc_get_mac_block(nthw_rmc_t *p);
+void nthw_rmc_set_mac_block(nthw_rmc_t *p, uint32_t mask);
+void nthw_rmc_block(nthw_rmc_t *p);
+void nthw_rmc_unblock(nthw_rmc_t *p, bool b_is_slave);
+void nthw_rmc_administrative_block(nthw_rmc_t *p);
+
+uint32_t nthw_rmc_get_status_sf_ram_of(nthw_rmc_t *p);
+uint32_t nthw_rmc_get_status_descr_fifo_of(nthw_rmc_t *p);
+uint32_t nthw_rmc_get_dbg_merge(nthw_rmc_t *p);
+uint32_t nthw_rmc_get_mac_if_err(nthw_rmc_t *p);
+
+#endif /* NTHW_RMC_H_ */
diff --git a/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c
new file mode 100644
index 0000000000..bf120ccb39
--- /dev/null
+++ b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.c
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "avr_sensors.h"
+#include "ntlog.h"
+
+#define MAX_ADAPTERS 2
+
+uint8_t s_fpga_indexes[MAX_ADAPTERS] = { 0 }; /* _NTSD_MAX_NUM_ADAPTERS_ */
+static uint8_t get_fpga_idx(unsigned int adapter_no);
+
+/*
+ * This function setups monitoring of AVR sensors
+ */
+static uint8_t _avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no,
+ const char *p_name,
+ enum sensor_mon_device avr_dev,
+ uint8_t avr_dev_reg, enum sensor_mon_endian end,
+ enum sensor_mon_sign si, uint16_t mask)
+{
+ uint8_t fpga_idx = get_fpga_idx(m_adapter_no);
+ struct sensor_mon_setup16 avr_sensor_setup;
+
+ /* Setup monitoring in AVR placing results in FPGA */
+ avr_sensor_setup.setup_cnt = 1;
+ avr_sensor_setup.setup_data[0].fpga_idx = fpga_idx;
+ avr_sensor_setup.setup_data[0].device = avr_dev;
+ avr_sensor_setup.setup_data[0].device_register = avr_dev_reg;
+ avr_sensor_setup.setup_data[0].format = (uint16_t)(end | si << 2);
+
+ avr_sensor_setup.setup_data[0].mask = mask;
+ avr_sensor_setup.setup_data[0].pos =
+ 0; /* So far for all sensors in table */
+
+ /*
+ * At first it is the task of ntservice to test limit_low and limit_high on all
+ * board sensors. Later the test is going to be carried out by the AVR
+ */
+ if (si == SENSOR_MON_SIGNED) {
+ avr_sensor_setup.setup_data[0].int16.limit_low =
+ SENSOR_MON_INT16_NAN;
+ avr_sensor_setup.setup_data[0].int16.limit_high =
+ SENSOR_MON_INT16_NAN;
+ } else {
+ avr_sensor_setup.setup_data[0].uint16.limit_low =
+ SENSOR_MON_UINT16_NAN;
+ avr_sensor_setup.setup_data[0].uint16.limit_high =
+ SENSOR_MON_UINT16_NAN;
+ }
+
+ int result = nt_avr_sensor_mon_setup(&avr_sensor_setup, s_spi);
+
+ if (result)
+ NT_LOG(ERR, ETHDEV, "%s: sensor initialization error\n", p_name);
+
+ return fpga_idx;
+}
+
+static void avr_read(struct nt_sensor_group *sg, nthw_spis_t *t_spi)
+{
+ uint32_t p_sensor_result;
+
+ if (sg == NULL || sg->sensor == NULL)
+ return;
+
+ sensor_read(t_spi, sg->sensor->fpga_idx, &p_sensor_result);
+ update_sensor_value(sg->sensor, sg->conv_func(p_sensor_result));
+}
+
+struct nt_sensor_group *
+avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum sensor_mon_device avr_dev,
+ uint8_t avr_dev_reg, enum sensor_mon_endian end,
+ enum sensor_mon_sign si, int (*conv_func)(uint32_t),
+ uint16_t mask)
+{
+ struct nt_sensor_group *sg = malloc(sizeof(struct nt_sensor_group));
+
+ if (sg == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__);
+ return NULL;
+ }
+ init_sensor_group(sg);
+ sg->sensor = allocate_sensor(m_adapter_no, p_name, ssrc, type, index,
+ NT_SENSOR_DISABLE_ALARM, si);
+ sg->sensor->fpga_idx = _avr_sensor_init(s_spi, m_adapter_no, p_name, avr_dev,
+ avr_dev_reg, end, si, mask);
+ sg->read = &avr_read;
+ sg->conv_func = conv_func;
+ sg->monitor = NULL;
+ sg->next = NULL;
+ return sg;
+}
+
+static uint8_t get_fpga_idx(unsigned int adapter_no)
+{
+ uint8_t tmp = s_fpga_indexes[adapter_no];
+
+ s_fpga_indexes[adapter_no] = (uint8_t)(tmp + 1);
+
+ return tmp;
+}
diff --git a/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h
new file mode 100644
index 0000000000..b8c37a12cb
--- /dev/null
+++ b/drivers/net/ntnic/sensors/avr_sensors/avr_sensors.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _AVR_SENSORS_H
+#define _AVR_SENSORS_H
+
+#include <stdint.h>
+
+#include "sensors.h"
+#include "avr_intf.h"
+#include "ntavr.h"
+
+struct nt_sensor_group *
+avr_sensor_init(nthw_spi_v3_t *s_spi, uint8_t m_adapter_no, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum sensor_mon_device avr_dev,
+ uint8_t avr_dev_reg, enum sensor_mon_endian end,
+ enum sensor_mon_sign si, int (*conv_func)(uint32_t),
+ uint16_t mask);
+
+#endif /* _AVR_SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/board_sensors/board_sensors.c b/drivers/net/ntnic/sensors/board_sensors/board_sensors.c
new file mode 100644
index 0000000000..8e52379df8
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/board_sensors.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stddef.h>
+#include <math.h>
+
+#include "tempmon.h"
+#include "board_sensors.h"
+#include "ntlog.h"
+
+static void fpga_temperature_sensor_read(struct nt_sensor_group *sg,
+ nthw_spis_t *t_spi)
+{
+ int temp = 0;
+ (void)t_spi;
+ if (sg == NULL || sg->sensor == NULL) {
+ NT_LOG(ERR, ETHDEV, "failed to read FPGA temperature\n");
+ return;
+ }
+ struct nt_fpga_sensor_monitor *temp_monitor = sg->monitor;
+ uint32_t val = field_get_updated(temp_monitor->fields[0]);
+
+ temp = (val * 20159 - 44752896) / 16384;
+
+ update_sensor_value(sg->sensor, temp);
+}
+
+struct nt_sensor_group *fpga_temperature_sensor_init(uint8_t adapter_no,
+ unsigned int sensor_idx,
+ nt_fpga_t *p_fpga)
+{
+ struct nt_sensor_group *sg = malloc(sizeof(struct nt_sensor_group));
+
+ if (sg == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor group is NULL", __func__);
+ return NULL;
+ }
+ init_sensor_group(sg);
+ sg->monitor = tempmon_new();
+ tempmon_init(sg->monitor, p_fpga);
+ sg->sensor =
+ allocate_sensor(adapter_no, "FPGA", NT_SENSOR_SOURCE_ADAPTER,
+ NT_SENSOR_TYPE_TEMPERATURE, sensor_idx,
+ NT_SENSOR_DISABLE_ALARM, SENSOR_MON_UNSIGNED);
+ sg->read = &fpga_temperature_sensor_read;
+ return sg;
+}
diff --git a/drivers/net/ntnic/sensors/board_sensors/board_sensors.h b/drivers/net/ntnic/sensors/board_sensors/board_sensors.h
new file mode 100644
index 0000000000..a7f75b7ae4
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/board_sensors.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _BOARD_SENSORS_H
+#define _BOARD_SENSORS_H
+
+#include <stdint.h>
+
+#include "sensors.h"
+
+#include "nthw_fpga_model.h"
+
+struct nt_sensor_group *fpga_temperature_sensor_init(uint8_t adapter_no,
+ unsigned int sensor_idx,
+ nt_fpga_t *p_fpga);
+
+#endif /* _BOARD_SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/board_sensors/tempmon.c b/drivers/net/ntnic/sensors/board_sensors/tempmon.c
new file mode 100644
index 0000000000..2cd3709205
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/tempmon.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "tempmon.h"
+#include "ntlog.h"
+#include "nthw_register.h"
+
+struct nt_fpga_sensor_monitor *tempmon_new(void)
+{
+ struct nt_fpga_sensor_monitor *temp =
+ malloc(sizeof(struct nt_fpga_sensor_monitor));
+ if (temp == NULL)
+ NT_LOG(ERR, ETHDEV, "%s: monitor is NULL\n", __func__);
+ return temp;
+}
+
+void tempmon_init(struct nt_fpga_sensor_monitor *t, nt_fpga_t *p_fpga)
+{
+ if (t == NULL || p_fpga == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: bad argument(s)\n", __func__);
+ return;
+ }
+ /* fetch initialized module */
+ t->fpga = p_fpga;
+ t->mod = nthw_get_module(t->fpga, MOD_TEMPMON, 0);
+ if (t->mod == NULL)
+ NT_LOG(ERR, ETHDEV, "module is NULL\n");
+ /* fetch register */
+ t->reg = module_get_register(t->mod, TEMPMON_STAT);
+ if (t->reg == NULL)
+ NT_LOG(ERR, ETHDEV, "register is NULL\n");
+ /* fetch fields */
+ t->fields = malloc(sizeof(nt_field_t *));
+ if (t->fields == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: field is NULL", __func__);
+ return;
+ }
+ t->fields[0] = register_get_field(t->reg, TEMPMON_STAT_TEMP);
+ if (t->fields[0] == NULL)
+ NT_LOG(ERR, ETHDEV, "field is NULL\n");
+}
diff --git a/drivers/net/ntnic/sensors/board_sensors/tempmon.h b/drivers/net/ntnic/sensors/board_sensors/tempmon.h
new file mode 100644
index 0000000000..6f2017b714
--- /dev/null
+++ b/drivers/net/ntnic/sensors/board_sensors/tempmon.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _TEMPMON_H
+#define _TEMPMON_H
+
+#include "nthw_fpga_model.h"
+#include <stdlib.h>
+
+#include "sensors.h"
+
+struct nt_fpga_sensor_monitor *tempmon_new(void);
+void tempmon_init(struct nt_fpga_sensor_monitor *t, nt_fpga_t *p_fpga);
+
+#endif /* _TEMPMON_H */
diff --git a/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c
new file mode 100644
index 0000000000..e130855a35
--- /dev/null
+++ b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.c
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <arpa/inet.h>
+
+#include "nim_sensors.h"
+#include "ntlog.h"
+
+#define TEMP NT_SENSOR_TYPE_TEMPERATURE
+#define VOLT NT_SENSOR_TYPE_VOLTAGE
+#define CURR NT_SENSOR_TYPE_CURRENT
+#define PWR NT_SENSOR_TYPE_POWER
+
+#define SNA NT_SENSOR_SUBTYPE_NA
+#define AVG NT_SENSOR_SUBTYPE_POWER_AVERAGE
+
+#define ENA NT_SENSOR_ENABLE_ALARM
+#define DIA NT_SENSOR_DISABLE_ALARM
+
+/*
+ * Sensors for SFP/SFP+/SFP28. The name of the level 0 temperature sensor is
+ * empty and will then be set automatically
+ */
+struct nt_adapter_sensor_description sfp_sensors_level0[1] = {
+ { TEMP, SNA, NT_SENSOR_SFP_TEMP, DIA, "" },
+};
+
+struct nt_adapter_sensor_description sfp_sensors_level1[4] = {
+ { VOLT, SNA, NT_SENSOR_SFP_SUPPLY, DIA, "Supply" },
+ { CURR, SNA, NT_SENSOR_SFP_TX_BIAS, DIA, "Tx Bias" },
+ { PWR, AVG, NT_SENSOR_SFP_TX_POWER, DIA, "Tx" },
+ { PWR, AVG, NT_SENSOR_SFP_RX_POWER, DIA, "Rx" }
+};
+
+struct nt_adapter_sensor_description qsfp_sensor_level0[1] = {
+ { TEMP, SNA, NT_SENSOR_QSFP_TEMP, DIA, "" },
+};
+
+struct nt_adapter_sensor_description qsfp_sensor_level1[13] = {
+ { VOLT, SNA, NT_SENSOR_QSFP_SUPPLY, DIA, "Supply" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS1, DIA, "Tx Bias 1" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS2, DIA, "Tx Bias 2" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS3, DIA, "Tx Bias 3" },
+ { CURR, SNA, NT_SENSOR_QSFP_TX_BIAS4, DIA, "Tx Bias 4" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER1, DIA, "Tx 1" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER2, DIA, "Tx 2" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER3, DIA, "Tx 3" },
+ { PWR, AVG, NT_SENSOR_QSFP_TX_POWER4, DIA, "Tx 4" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER1, DIA, "Rx 1" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER2, DIA, "Rx 2" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER3, DIA, "Rx 3" },
+ { PWR, AVG, NT_SENSOR_QSFP_RX_POWER4, DIA, "Rx 4" }
+};
diff --git a/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h
new file mode 100644
index 0000000000..c68c9aa924
--- /dev/null
+++ b/drivers/net/ntnic/sensors/nim_sensors/nim_sensors.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NIM_SENSORS_H
+#define _NIM_SENSORS_H
+
+#include <stdint.h>
+#include <string.h>
+#include "sensors.h"
+
+#define XFP_TEMP_LIN_ADDR 96
+
+extern struct nt_adapter_sensor_description sfp_sensors_level0[1];
+extern struct nt_adapter_sensor_description sfp_sensors_level1[4];
+extern struct nt_adapter_sensor_description qsfp_sensor_level0[1];
+extern struct nt_adapter_sensor_description qsfp_sensor_level1[13];
+
+#endif /* _NIM_SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/ntavr/avr_intf.h b/drivers/net/ntnic/sensors/ntavr/avr_intf.h
new file mode 100644
index 0000000000..feeec6e13a
--- /dev/null
+++ b/drivers/net/ntnic/sensors/ntavr/avr_intf.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _AVR_INTF
+#define _AVR_INTF
+
+#include <stdint.h>
+
+#define SENSOR_MON_UINT16_NAN 0xFFFF /* Most positive number used as NaN */
+#define SENSOR_MON_INT16_NAN \
+ ((int16_t)0x8000) /* Most negative number used as NaN */
+
+/*
+ * Specify the nature of the raw data. AVR and ntservice must use this
+ * information when comparing or converting to native format which is little endian
+ */
+enum sensor_mon_endian { SENSOR_MON_LITTLE_ENDIAN, SENSOR_MON_BIG_ENDIAN };
+
+enum sensor_mon_sign {
+ SENSOR_MON_UNSIGNED,
+ SENSOR_MON_SIGNED, /* 2's complement */
+};
+
+/* Define sensor devices */
+enum sensor_mon_device {
+ SENSOR_MON_PSU_EXAR_7724_0 = 0, /* NT40E3, NT100E3 */
+ SENSOR_MON_PSU_EXAR_7724_1, /* NT40E3, NT100E3 */
+ SENSOR_MON_PSU_LTM_4676_0, /* na NT100E3, page-0 */
+ SENSOR_MON_PSU_LTM_4676_1, /* na NT100E3, page-0 */
+ SENSOR_MON_INA219_1, /* NT40E3, NT100E3 */
+ SENSOR_MON_INA219_2, /* NT40E3, NT100E3 */
+ SENSOR_MON_MAX6642, /* NT40E3, NT100E3 */
+ SENSOR_MON_DS1775, /* NT40E3, NT100E3 */
+ SENSOR_MON_FAN, /* NT40E3, NT100E3 */
+ SENSOR_MON_AVR, /* NT40E3, NT100E3 */
+ SENSOR_MON_PEX8734, /* na NT100E3 */
+ SENSOR_MON_RATE_COUNT, /* NT40E3, NT100E3 */
+ SENSOR_MON_PSU_LTM_4676_0_1, /* na NT100E3, page-1 */
+ SENSOR_MON_PSU_LTM_4676_1_1, /* na NT100E3, page-1 */
+ SENSOR_MON_MP2886A, /* na, na, NT200A02, */
+ SENSOR_MON_PSU_EM2260_1, /* na, na, na, na, NT200D01^M */
+ SENSOR_MON_PSU_EM2120_2, /* na, na, na, na, NT200D01^M */
+ SENSOR_MON_MP2886A_PSU_1, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8869S_PSU_2, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8645PGVT_PSU_3, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8645PGVT_PSU_4, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8869S_PSU_5, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_MP8869S_PSU_6, /* na, na, na, NT200A02, na, NT50B01, */
+ SENSOR_MON_DEVICE_COUNT
+};
+
+#pragma pack(1)
+struct sensor_mon_setup_data16 {
+ uint8_t fpga_idx; /* Destination of results */
+ uint8_t device; /* Device to monitor */
+ uint8_t device_register; /* Sensor within device */
+ uint16_t mask; /* Indicates active bits */
+ uint8_t pos; /* Position of first active bit */
+ uint16_t format; /* b0,1:sensor_mon_endian_t endian */
+ /* b2,3:sensor_mon_sign_t sign */
+ union {
+ struct {
+ int16_t limit_low; /* Signed alarm limit low */
+ int16_t limit_high; /* Signed alarm limit high */
+ } int16;
+
+ struct {
+ uint16_t limit_low; /* Unsigned alarm limit low */
+ uint16_t limit_high; /* Unsigned alarm limit high */
+ } uint16;
+ };
+};
+
+#pragma pack()
+struct sensor_mon_setup16 {
+ uint8_t setup_cnt; /* Number of entries in setup_data */
+ struct sensor_mon_setup_data16 setup_data[40];
+};
+
+/* Define sensor monitoring control */
+enum sensor_mon_control {
+ SENSOR_MON_CTRL_STOP = 0, /* Stop sensor monitoring */
+ SENSOR_MON_CTRL_RUN = 1, /* Start sensor monitoring */
+ SENSOR_MON_CTRL_REM_ALL_SENSORS =
+ 2, /* Stop and remove all sensor monitoring setup */
+};
+
+#endif /* _AVR_INTF */
diff --git a/drivers/net/ntnic/sensors/ntavr/ntavr.c b/drivers/net/ntnic/sensors/ntavr/ntavr.c
new file mode 100644
index 0000000000..6d8c3042b1
--- /dev/null
+++ b/drivers/net/ntnic/sensors/ntavr/ntavr.c
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntavr.h"
+#include "ntlog.h"
+
+static int txrx(nthw_spi_v3_t *s_spi, enum avr_opcodes opcode, size_t txsz,
+ uint16_t *tx, size_t *rxsz, uint16_t *rx)
+{
+ int res = 1;
+ struct tx_rx_buf m_tx = { .size = (uint16_t)txsz, .p_buf = tx };
+ struct tx_rx_buf m_rx = { .size = (uint16_t)*rxsz, .p_buf = rx };
+
+ res = nthw_spi_v3_transfer(s_spi, opcode, &m_tx, &m_rx);
+ if (res) {
+ NT_LOG(ERR, ETHDEV, "%s transfer failed - %i", __func__, res);
+ return res;
+ }
+
+ if (rxsz != NULL)
+ *rxsz = m_rx.size;
+
+ return res;
+}
+
+uint32_t sensor_read(nthw_spis_t *t_spi, uint8_t fpga_idx,
+ uint32_t *p_sensor_result)
+{
+ return nthw_spis_read_sensor(t_spi, fpga_idx, p_sensor_result);
+}
+
+int nt_avr_sensor_mon_setup(struct sensor_mon_setup16 *p_setup, nthw_spi_v3_t *s_spi)
+{
+ int error;
+ size_t tx_size;
+ size_t rx_size = 0;
+
+ tx_size = sizeof(struct sensor_mon_setup16) - sizeof(p_setup->setup_data);
+ tx_size += sizeof(p_setup->setup_data[0]) * p_setup->setup_cnt;
+
+ error = txrx(s_spi, AVR_OP_SENSOR_MON_SETUP, tx_size, (uint16_t *)p_setup,
+ &rx_size, NULL);
+
+ if (error) {
+ NT_LOG(ERR, ETHDEV, "%s failed\n", __func__);
+ return error;
+ }
+
+ if (rx_size != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Returned data: Expected size = 0, Actual = %zu",
+ __func__, rx_size);
+ return 1;
+ }
+ return 0;
+}
+
+int nt_avr_sensor_mon_ctrl(nthw_spi_v3_t *s_spi, enum sensor_mon_control ctrl)
+{
+ int error;
+ size_t rx_size = 0;
+
+ error = txrx(s_spi, AVR_OP_SENSOR_MON_CONTROL, sizeof(ctrl),
+ (uint16_t *)(&ctrl), &rx_size, NULL);
+
+ if (error != 0)
+ return error;
+
+ if (rx_size != 0) {
+ NT_LOG(ERR, ETHDEV,
+ "%s: Returned data: Expected size = 0, Actual = %zu",
+ __func__, rx_size);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/sensors/ntavr/ntavr.h b/drivers/net/ntnic/sensors/ntavr/ntavr.h
new file mode 100644
index 0000000000..b7a7aeb908
--- /dev/null
+++ b/drivers/net/ntnic/sensors/ntavr/ntavr.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _NTAVR_H
+#define _NTAVR_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "avr_intf.h"
+#include "nthw_drv.h"
+#include "nthw_spi_v3.h"
+
+/*
+ * @internal
+ * @brief AVR Device Enum
+ *
+ * Global names for identifying an AVR device for Generation2 adapters
+ */
+enum ntavr_device {
+ NTAVR_MAINBOARD, /* Mainboard AVR device */
+ NTAVR_FRONTBOARD /* Frontboard AVR device */
+};
+
+int nt_avr_sensor_mon_setup(struct sensor_mon_setup16 *p_setup,
+ nthw_spi_v3_t *s_spi);
+int nt_avr_sensor_mon_ctrl(nthw_spi_v3_t *s_spi, enum sensor_mon_control ctrl);
+uint32_t sensor_read(nthw_spis_t *t_spi, uint8_t fpga_idx,
+ uint32_t *p_sensor_result);
+
+#endif /* _NTAVR_H */
diff --git a/drivers/net/ntnic/sensors/sensor_types.h b/drivers/net/ntnic/sensors/sensor_types.h
new file mode 100644
index 0000000000..bac4e925f9
--- /dev/null
+++ b/drivers/net/ntnic/sensors/sensor_types.h
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SENSOR_TYPES_H
+#define _SENSOR_TYPES_H
+
+/*
+ * Sensor types
+ */
+enum nt_sensor_type_e {
+ NT_SENSOR_TYPE_UNKNOWN = 0,
+ NT_SENSOR_TYPE_TEMPERATURE = 1, /* Unit: 0.1 degree Celsius */
+ NT_SENSOR_TYPE_VOLTAGE = 2, /* Unit: 1 mV */
+ NT_SENSOR_TYPE_CURRENT = 3, /* Unit: 1 uA */
+ NT_SENSOR_TYPE_POWER = 4, /* Unit: 0.1 uW */
+ NT_SENSOR_TYPE_FAN = 5, /* Unit: 1 RPM (Revolutions Per Minute) */
+ NT_SENSOR_TYPE_HIGH_POWER = 6, /* Unit: 1 mW */
+ NT_SENSOR_TYPE_NUMBER = 7,
+};
+
+/*
+ * Generic SFP/SFP+/SFP28 sensors
+ *
+ * These sensors should be used instead of all adapter specific SFP sensors
+ * that have been deprecated..
+ */
+enum nt_sensors_sfp {
+ NT_SENSOR_SFP_TEMP,
+ NT_SENSOR_SFP_SUPPLY,
+ NT_SENSOR_SFP_TX_BIAS,
+ NT_SENSOR_SFP_TX_POWER,
+ NT_SENSOR_SFP_RX_POWER,
+};
+
+/*
+ * Generic QSFP/QSFP+/QSFP28 sensors
+ *
+ * These sensors should be used instead of all adapter specific QSFP sensors
+ * that have been deprecated..
+ */
+enum nt_sensors_qsfp {
+ NT_SENSOR_QSFP_TEMP,
+ NT_SENSOR_QSFP_SUPPLY,
+ NT_SENSOR_QSFP_TX_BIAS1,
+ NT_SENSOR_QSFP_TX_BIAS2,
+ NT_SENSOR_QSFP_TX_BIAS3,
+ NT_SENSOR_QSFP_TX_BIAS4,
+ NT_SENSOR_QSFP_TX_POWER1,
+ NT_SENSOR_QSFP_TX_POWER2,
+ NT_SENSOR_QSFP_TX_POWER3,
+ NT_SENSOR_QSFP_TX_POWER4,
+ NT_SENSOR_QSFP_RX_POWER1,
+ NT_SENSOR_QSFP_RX_POWER2,
+ NT_SENSOR_QSFP_RX_POWER3,
+ NT_SENSOR_QSFP_RX_POWER4,
+};
+
+typedef enum nt_sensor_type_e nt_sensor_type_t;
+
+/*
+ * Sensor subtypes
+ */
+enum nt_sensor_sub_type_e {
+ NT_SENSOR_SUBTYPE_NA = 0,
+ /*
+ * Subtype for NT_SENSOR_TYPE_POWER type on optical modules (optical modulation
+ * amplitude measured)
+ */
+ NT_SENSOR_SUBTYPE_POWER_OMA,
+ /* Subtype for NT_SENSOR_TYPE_POWER type on optical modules (average power measured) */
+ NT_SENSOR_SUBTYPE_POWER_AVERAGE,
+ /* Subtype for NT_SENSOR_TYPE_HIGH_POWER type on adapters (total power consumption) */
+ NT_SENSOR_SUBTYPE_POWER_TOTAL
+};
+
+typedef enum nt_sensor_sub_type_e nt_sensor_sub_type_t;
+
+/*
+ * Sensor source
+ */
+enum nt_sensor_source_e {
+ NT_SENSOR_SOURCE_UNKNOWN = 0x00, /* Unknown source */
+ /*
+ * Sensors located in a port. These are primary sensors - usually NIM temperature. Presence
+ * depends on adapter and NIM type.
+ */
+ NT_SENSOR_SOURCE_PORT =
+ 0x01,
+ /*
+ * Level 1 sensors located in a port. These are secondary sensors - usually NIM supply
+ * voltage, Tx bias and Rx/Tx optical power. Presence depends on adapter and NIM type.
+ */
+ NT_SENSOR_SOURCE_LEVEL1_PORT =
+ 0x02,
+#ifndef DOXYGEN_INTERNAL_ONLY
+ NT_SENSOR_SOURCE_LEVEL2_PORT =
+ 0x04, /* Level 2 sensors located in a port */
+#endif
+ NT_SENSOR_SOURCE_ADAPTER = 0x08, /* Sensors mounted on the adapter */
+ NT_SENSOR_SOURCE_LEVEL1_ADAPTER =
+ 0x10, /* Level 1 sensors mounted on the adapter */
+#ifndef DOXYGEN_INTERNAL_ONLY
+ NT_SENSOR_SOURCE_LEVEL2_ADAPTER =
+ 0x20, /* Level 2 sensors mounted on the adapter */
+#endif
+};
+
+/*
+ * Sensor state
+ */
+enum nt_sensor_state_e {
+ NT_SENSOR_STATE_UNKNOWN = 0, /* Unknown state */
+ NT_SENSOR_STATE_INITIALIZING = 1, /* The sensor is initializing */
+ NT_SENSOR_STATE_NORMAL = 2, /* Sensor values are within range */
+ NT_SENSOR_STATE_ALARM = 3, /* Sensor values are out of range */
+ NT_SENSOR_STATE_NOT_PRESENT =
+ 4 /* The sensor is not present, for example, SFP without diagnostics */
+};
+
+typedef enum nt_sensor_state_e nt_sensor_state_t;
+
+/*
+ * Sensor value
+ */
+#define NT_SENSOR_NAN \
+ (0x80000000) /* Indicates that sensor value or sensor limit is not valid (Not a Number) */
+
+/*
+ * Master/Slave
+ */
+enum nt_bonding_type_e {
+ NT_BONDING_UNKNOWN, /* Unknown bonding type */
+ NT_BONDING_MASTER, /* Adapter is master in the bonding */
+ NT_BONDING_SLAVE, /* Adapter is slave in the bonding */
+ NT_BONDING_PEER /* Adapter is bonded, but relationship is symmetric */
+};
+
+enum nt_sensors_e {
+ /* Public sensors (Level 0) */
+ NT_SENSOR_FPGA_TEMP, /* FPGA temperature sensor */
+};
+
+/*
+ * Adapter types
+ */
+enum nt_adapter_type_e {
+ NT_ADAPTER_TYPE_UNKNOWN = 0, /* Unknown adapter type */
+ NT_ADAPTER_TYPE_NT4E, /* NT4E network adapter */
+ NT_ADAPTER_TYPE_NT20E, /* NT20E network adapter */
+ NT_ADAPTER_TYPE_NT4E_STD, /* NT4E-STD network adapter */
+ NT_ADAPTER_TYPE_NT4E_PORT, /* NTPORT4E expansion adapter */
+ NT_ADAPTER_TYPE_NTBPE, /* NTBPE bypass adapter */
+ NT_ADAPTER_TYPE_NT20E2, /* NT20E2 network adapter */
+ NT_ADAPTER_TYPE_RESERVED1, /* Reserved */
+ NT_ADAPTER_TYPE_RESERVED2, /* Reserved */
+ NT_ADAPTER_TYPE_NT40E2_1, /* NT40E2-1 network adapter */
+ NT_ADAPTER_TYPE_NT40E2_4, /* NT40E2-4 network adapter */
+ NT_ADAPTER_TYPE_NT4E2_4T_BP, /* NT4E2-4T-BP bypass network adapter */
+ NT_ADAPTER_TYPE_NT4E2_4_PTP, /* NT4E2-4 PTP network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT20E2_PTP, /* NT20E2 PTP network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT40E3_4_PTP, /* NT40E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT100E3_1_PTP, /* NT100E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT20E3_2_PTP, /* NT20E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT80E3_2_PTP, /* NT80E3 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT200E3_2, /* NT200E3 network adapter */
+ NT_ADAPTER_TYPE_NT200A01, /* NT200A01 network adapter */
+ NT_ADAPTER_TYPE_NT200A01_2X100 =
+ NT_ADAPTER_TYPE_NT200A01, /* NT200A01 2 x 100 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT40A01_4X1, /* NT40A01_4X1 network adapter with IEEE1588 */
+ NT_ADAPTER_TYPE_NT200A01_2X40, /* NT200A01 2 x 40 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT80E3_2_PTP_8X10, /* NT80E3 8 x 10 Gbps network adapter with IEEE1588 */
+ /* */
+ NT_ADAPTER_TYPE_INTEL_A10_4X10, /* Intel PAC A10 GX 4 x 10 Gbps network adapter */
+ NT_ADAPTER_TYPE_INTEL_A10_1X40, /* Intel PAC A10 GX 1 x 40 Gbps network adapter */
+ /* */
+ NT_ADAPTER_TYPE_NT200A01_8X10, /* NT200A01 8 x 10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X100, /* NT200A02 2 x 100 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X40, /* NT200A02 2 x 40 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A01_2X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT200A01_2X10_25 =
+ NT_ADAPTER_TYPE_NT200A01_2X25, /* NT200A01 2 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT200A02_2X10_25 =
+ NT_ADAPTER_TYPE_NT200A02_2X25, /* NT200A02 2 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_4X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT200A02_4X10_25 =
+ NT_ADAPTER_TYPE_NT200A02_4X25, /* NT200A02 4 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_8X10, /* NT200A02 8 x 10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT50B01_2X25, /* Deprecated */
+ NT_ADAPTER_TYPE_NT50B01_2X10_25 =
+ NT_ADAPTER_TYPE_NT50B01_2X25, /* NT50B01 2 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT200A02_2X1_10, /* NT200A02 2 x 1/10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT100A01_4X1_10, /* NT100A01 4 x 1/10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT100A01_4X10_25, /* NT100A01 4 x 10/25 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT50B01_2X1_10, /* NT50B01 2 x 1/10 Gbps network adapter */
+ NT_ADAPTER_TYPE_NT40A11_4X1_10, /* NT40A11 4 x 1/10 Gbps network adapter */
+#ifndef DOXYGEN_INTERNAL_ONLY
+ NT_ADAPTER_TYPE_ML605 = 10000, /* NT20E2 eval board */
+#endif
+ NT_ADAPTER_TYPE_4GARCH_HAMOA =
+ (1U
+ << 29), /* Bit to mark to adapters as a 4GArch Hamoa adapter */
+ NT_ADAPTER_TYPE_4GARCH =
+ (1U << 30), /* Bit to mark to adapters as a 4GArch adapter */
+ /* NOTE: do *NOT* add normal adapters after the group bit mark enums */
+};
+
+/* The NT200E3 adapter sensor id's */
+typedef enum nt_sensors_adapter_nt200_e3_e {
+ /* Public sensors (Level 0) */
+ NT_SENSOR_NT200E3_FPGA_TEMP, /* FPGA temperature sensor */
+ NT_SENSOR_NT200E3_FAN_SPEED, /* FAN speed sensor */
+ /* MCU (Micro Controller Unit) temperature sensor located inside enclosure below FAN */
+ NT_SENSOR_NT200E3_MCU_TEMP,
+ NT_SENSOR_NT200E3_PSU0_TEMP, /* Power supply 0 temperature sensor */
+ NT_SENSOR_NT200E3_PSU1_TEMP, /* Power supply 1 temperature sensor */
+ NT_SENSOR_NT200E3_PCB_TEMP, /* PCB temperature sensor */
+
+ /* Diagnostic sensors (Level 1) */
+ /* Total power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_NT200E3_POWER,
+ /* FPGA power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_FPGA_POWER,
+ /* DDR4 RAM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_DDR4_POWER,
+ /* NIM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200E3_NIM_POWER,
+
+ NT_SENSOR_NT200E3_L1_MAX, /* Number of NT200E3 level 0,1 board sensors */
+} nt_sensors_adapter_nt200_e3_t;
+
+/*
+ * The following sensors are deprecated - generic types should be used instead
+ * The NIM temperature sensor must be the one with the lowest sensor_index
+ * (enum value) in order to be shown by the monitoring tool in port mode
+ */
+enum nt_sensors_port_nt200_e3_2_e {
+ /* Public sensors */
+ NT_SENSOR_NT200E3_NIM, /* QSFP28 temperature sensor */
+
+ /* Diagnostic sensors (Level 1) */
+ NT_SENSOR_NT200E3_SUPPLY, /* QSFP28 supply voltage sensor */
+ NT_SENSOR_NT200E3_TX_BIAS1, /* QSFP28 TX bias line 0 current sensor */
+ NT_SENSOR_NT200E3_TX_BIAS2, /* QSFP28 TX bias line 1 current sensor */
+ NT_SENSOR_NT200E3_TX_BIAS3, /* QSFP28 TX bias line 2 current sensor */
+ NT_SENSOR_NT200E3_TX_BIAS4, /* QSFP28 TX bias line 3 current sensor */
+ NT_SENSOR_NT200E3_RX1, /* QSFP28 RX line 0 power sensor */
+ NT_SENSOR_NT200E3_RX2, /* QSFP28 RX line 1 power sensor */
+ NT_SENSOR_NT200E3_RX3, /* QSFP28 RX line 2 power sensor */
+ NT_SENSOR_NT200E3_RX4, /* QSFP28 RX line 3 power sensor */
+ NT_SENSOR_NT200E3_TX1, /* QSFP28 TX line 0 power sensor */
+ NT_SENSOR_NT200E3_TX2, /* QSFP28 TX line 1 power sensor */
+ NT_SENSOR_NT200E3_TX3, /* QSFP28 TX line 2 power sensor */
+ NT_SENSOR_NT200E3_TX4, /* QSFP28 TX line 3 power sensor */
+ NT_SENSOR_NT200E3_PORT_MAX, /* Number of NT200E3 port sensors */
+};
+
+#endif
diff --git a/drivers/net/ntnic/sensors/sensors.c b/drivers/net/ntnic/sensors/sensors.c
new file mode 100644
index 0000000000..2a85843196
--- /dev/null
+++ b/drivers/net/ntnic/sensors/sensors.c
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "sensors.h"
+#include "ntlog.h"
+
+void sensor_deinit(struct nt_sensor_group *sg)
+{
+ if (sg) {
+ if (sg->sensor)
+ free(sg->sensor);
+ if (sg->monitor)
+ free(sg->monitor);
+ free(sg);
+ }
+}
+
+struct nt_adapter_sensor *
+allocate_sensor(uint8_t adapter_or_port_index, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum nt_sensor_event_alarm_e event_alarm,
+ enum sensor_mon_sign si)
+{
+ struct nt_adapter_sensor *sensor =
+ (struct nt_adapter_sensor *)malloc(sizeof(struct nt_adapter_sensor));
+ if (sensor == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor is NULL", __func__);
+ return NULL;
+ }
+
+ sensor->alarm = event_alarm;
+ sensor->m_enable_alarm = true;
+ sensor->m_intf_no = 0xFF;
+ sensor->m_adapter_no = 0xFF;
+ sensor->si = si;
+
+ sensor->info.source = ssrc;
+ sensor->info.source_index = adapter_or_port_index;
+ sensor->info.sensor_index = index;
+ sensor->info.type = type;
+ sensor->info.sub_type = NT_SENSOR_SUBTYPE_NA;
+ sensor->info.state = NT_SENSOR_STATE_INITIALIZING;
+ sensor->info.value = NT_SENSOR_NAN;
+ sensor->info.value_lowest = NT_SENSOR_NAN;
+ sensor->info.value_highest = NT_SENSOR_NAN;
+ memset(sensor->info.name, 0, NT_INFO_SENSOR_NAME);
+ memcpy(sensor->info.name, p_name,
+ (strlen(p_name) > NT_INFO_SENSOR_NAME) ? NT_INFO_SENSOR_NAME :
+ strlen(p_name));
+ sensor->info.name[NT_INFO_SENSOR_NAME] = '\0';
+
+ return sensor;
+}
+
+void update_sensor_value(struct nt_adapter_sensor *sensor, int32_t value)
+{
+ if (sensor == NULL)
+ return;
+ sensor->info.value = value;
+ if (sensor->info.value_highest < value ||
+ (unsigned int)sensor->info.value_highest == NT_SENSOR_NAN)
+ sensor->info.value_highest = value;
+ if (sensor->info.value_lowest > value ||
+ (unsigned int)sensor->info.value_lowest == NT_SENSOR_NAN)
+ sensor->info.value_lowest = value;
+}
+
+struct nt_adapter_sensor *
+allocate_sensor_by_description(uint8_t adapter_or_port_index,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *descr)
+{
+ struct nt_adapter_sensor *sensor =
+ (struct nt_adapter_sensor *)malloc(sizeof(struct nt_adapter_sensor));
+ if (sensor == NULL) {
+ NT_LOG(ERR, ETHDEV, "%s: sensor is NULL", __func__);
+ return NULL;
+ }
+
+ sensor->alarm = descr->event_alarm;
+ sensor->m_enable_alarm = true;
+ sensor->m_intf_no = 0xFF;
+ sensor->m_adapter_no = 0xFF;
+ sensor->si = SENSOR_MON_UNSIGNED;
+
+ sensor->info.source_index = adapter_or_port_index;
+ sensor->info.source = ssrc;
+ sensor->info.type = descr->type;
+ sensor->info.sensor_index = descr->index;
+ memset(sensor->info.name, 0, NT_INFO_SENSOR_NAME);
+ memcpy(sensor->info.name, descr->name,
+ (strlen(descr->name) > NT_INFO_SENSOR_NAME) ?
+ NT_INFO_SENSOR_NAME :
+ strlen(descr->name));
+ sensor->info.name[NT_INFO_SENSOR_NAME] = '\0';
+
+ return sensor;
+}
+
+void init_sensor_group(struct nt_sensor_group *sg)
+{
+ /* Set all pointers to NULL */
+ sg->sensor = NULL;
+ sg->monitor = NULL;
+ sg->next = NULL;
+ sg->read = NULL;
+ sg->conv_func = NULL;
+}
+
+/* Getters */
+int32_t get_value(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.value;
+};
+
+int32_t get_lowest(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.value_lowest;
+};
+
+int32_t get_highest(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.value_highest;
+};
+
+char *get_name(struct nt_sensor_group *sg)
+{
+ return sg->sensor->info.name;
+};
+
+/* Conversion functions */
+int null_signed(uint32_t p_sensor_result)
+{
+ return (int16_t)p_sensor_result;
+}
+
+int null_unsigned(uint32_t p_sensor_result)
+{
+ return (uint16_t)p_sensor_result;
+}
+
+/*
+ * ******************************************************************************
+ * For EXAR7724: Convert a read Vch value to Napatech internal representation
+ * Doc: Vout = ReadVal * 0.015 (PRESCALE is accounted for)
+ * ******************************************************************************
+ */
+int exar7724_vch(uint32_t p_sensor_result)
+{
+ return p_sensor_result * 15; /* NT unit: 1mV */
+}
+
+/*
+ * ******************************************************************************
+ * For EXAR7724: Convert a read Vin value to Napatech internal representation
+ * Doc: Vout = ReadVal * 0.0125
+ * ******************************************************************************
+ */
+int exar7724_vin(uint32_t p_sensor_result)
+{
+ return (p_sensor_result * 25) / 2; /* NT unit: 1mV */
+}
+
+/*
+ * ******************************************************************************
+ * For EXAR7724: Convert a read Tj value to Napatech internal representation
+ * Doc: Temp (in Kelvin) = (((ReadVal * 10mV) - 600mV) / (2mV/K)) + 300K =
+ * = ReadVal * 5K
+ * ******************************************************************************
+ */
+int exar7724_tj(uint32_t p_sensor_result)
+{
+ /*
+ * A value of 2730 is used instead of 2732 which is more correct but since
+ * the temperature step is 5 degrees it is more natural to show these steps
+ */
+ return p_sensor_result * 50 - 2730; /* NT unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * Conversion function for Linear Tecnology Linear_5s_11s format.
+ * The functions returns Y * 2**N, where N = b[15:11] is a 5-bit two's complement
+ * integer and Y = b[10:0] is an 11-bit two's complement integer.
+ * The multiplier value is used for scaling to Napatech units.
+ * ******************************************************************************
+ */
+static int conv5s_11s(uint16_t value, int multiplier)
+{
+ int n, y;
+
+ y = value & 0x07FF;
+
+ if (value & 0x0400)
+ y -= 0x0800; /* The MSBit is a sign bit */
+
+ n = (value >> 11) & 0x1F;
+
+ if (n & 0x10)
+ n -= 0x20; /* The MSBit is a sign bit */
+
+ y *= multiplier;
+
+ if (n > 0)
+ y *= (1 << n);
+
+ else if (n < 0)
+ y /= (1 << (-n));
+
+ return y;
+}
+
+/*
+ * ******************************************************************************
+ * Temperature conversion from Linear_5s_11s format.
+ * ******************************************************************************
+ */
+int ltm4676_tj(uint32_t p_sensor_result)
+{
+ return (uint16_t)conv5s_11s(p_sensor_result, 10); /* NT unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * For MP2886a: Convert a read Tj value to Napatech internal representation
+ * ******************************************************************************
+ */
+int mp2886a_tj(uint32_t p_sensor_result)
+{
+ /*
+ * MPS-2886p: READ_TEMPERATURE (register 0x8Dh)
+ * READ_TEMPERATURE is a 2-byte, unsigned integer.
+ */
+ return (uint16_t)p_sensor_result; /* NT unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * For MAX6642: Convert a read temperature value to Napatech internal representation
+ * ******************************************************************************
+ */
+int max6642_t(uint32_t p_sensor_result)
+{
+ if ((p_sensor_result >> 8) == 0xFF)
+ return NT_SENSOR_NAN;
+
+ /* The six lower bits are not used */
+ return (int)(((p_sensor_result >> 6) * 5) /
+ 2); /* NT unit: 0.25 deg, Native unit: 0.1C */
+}
+
+/*
+ * ******************************************************************************
+ * For DS1775: Convert a read temperature value to Napatech internal representation
+ * ******************************************************************************
+ */
+int ds1775_t(uint32_t p_sensor_result)
+{
+ return (p_sensor_result * 10) /
+ 256; /* NT unit: 0.1 deg, Native unit: 1/256 C */
+}
+
+/*
+ * ******************************************************************************
+ * For FAN: Convert a tick count to RPM
+ * NT unit: RPM, Native unit: 2 ticks/revolution
+ * ******************************************************************************
+ */
+int fan(uint32_t p_sensor_result)
+{
+ return (p_sensor_result * 60U / 4);
+}
diff --git a/drivers/net/ntnic/sensors/sensors.h b/drivers/net/ntnic/sensors/sensors.h
new file mode 100644
index 0000000000..1424b8bc83
--- /dev/null
+++ b/drivers/net/ntnic/sensors/sensors.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _SENSORS_H
+#define _SENSORS_H
+
+#include "sensor_types.h"
+#include "stream_info.h"
+#include "nthw_platform_drv.h"
+#include "nthw_drv.h"
+#include "nthw_spi_v3.h"
+#include "nthw_fpga_model.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "avr_intf.h"
+
+enum nt_sensor_event_alarm_e {
+ NT_SENSOR_ENABLE_ALARM,
+ NT_SENSOR_LOG_ALARM,
+ NT_SENSOR_DISABLE_ALARM,
+};
+
+/*
+ * Sensor Class types
+ */
+enum nt_sensor_class_e {
+ NT_SENSOR_CLASS_FPGA =
+ 0, /* Class for FPGA based sensors e.g FPGA temperature */
+ NT_SENSOR_CLASS_MCU =
+ 1, /* Class for MCU based sensors e.g MCU temperature */
+ NT_SENSOR_CLASS_PSU =
+ 2, /* Class for PSU based sensors e.g PSU temperature */
+ NT_SENSOR_CLASS_PCB =
+ 3, /* Class for PCB based sensors e.g PCB temperature */
+ NT_SENSOR_CLASS_NIM =
+ 4, /* Class for NIM based sensors e.g NIM temperature */
+ NT_SENSOR_CLASS_ANY = 5, /* Class for ANY sensors e.g any sensors */
+};
+
+typedef enum nt_sensor_class_e nt_sensor_class_t;
+
+/*
+ * Port of the sensor class
+ */
+struct nt_adapter_sensor {
+ uint8_t m_adapter_no;
+ uint8_t m_intf_no;
+ uint8_t fpga_idx; /* for AVR sensors */
+ enum sensor_mon_sign si;
+ struct nt_info_sensor_s info;
+ enum nt_sensor_event_alarm_e alarm;
+ bool m_enable_alarm;
+};
+
+struct nt_fpga_sensor_monitor {
+ nt_fpga_t *fpga;
+ nt_module_t *mod;
+
+ nt_register_t *reg;
+ nt_field_t **fields;
+ uint8_t fields_num;
+};
+
+/*
+ * Sensor description.
+ * Describe the static behavior of the sensor.
+ */
+struct nt_adapter_sensor_description {
+ enum nt_sensor_type_e type; /* Sensor type. */
+ enum nt_sensor_sub_type_e sub_type; /* Sensor subtype (if any applicable) */
+ unsigned int index; /* Sensor group index. */
+ enum nt_sensor_event_alarm_e event_alarm; /* Enable/Disable event alarm */
+ char name[20]; /* Sensor name. */
+};
+
+struct nt_sensor_group {
+ struct nt_adapter_sensor *sensor;
+ struct nt_fpga_sensor_monitor *monitor;
+ void (*read)(struct nt_sensor_group *sg, nthw_spis_t *t_spi);
+
+ /* conv params are needed to call current conversion functions */
+ int (*conv_func)(uint32_t p_sensor_result);
+ /* i2c interface for NIM sensors */
+
+ struct nt_sensor_group *next;
+};
+
+void init_sensor_group(struct nt_sensor_group *sg);
+
+void update_sensor_value(struct nt_adapter_sensor *sensor, int32_t value);
+
+void sensor_deinit(struct nt_sensor_group *sg);
+
+/* getters */
+int32_t get_value(struct nt_sensor_group *sg);
+int32_t get_lowest(struct nt_sensor_group *sg);
+int32_t get_highest(struct nt_sensor_group *sg);
+char *get_name(struct nt_sensor_group *sg);
+
+struct nt_adapter_sensor *
+allocate_sensor(uint8_t adapter_or_port_index, const char *p_name,
+ enum nt_sensor_source_e ssrc, enum nt_sensor_type_e type,
+ unsigned int index, enum nt_sensor_event_alarm_e event_alarm,
+ enum sensor_mon_sign si);
+struct nt_adapter_sensor *
+allocate_sensor_by_description(uint8_t adapter_or_port_index,
+ enum nt_sensor_source_e ssrc,
+ struct nt_adapter_sensor_description *descr);
+
+/* conversion functions */
+int null_signed(uint32_t p_sensor_result);
+int null_unsigned(uint32_t p_sensor_result);
+int exar7724_tj(uint32_t p_sensor_result);
+int max6642_t(uint32_t p_sensor_result);
+int ds1775_t(uint32_t p_sensor_result);
+int ltm4676_tj(uint32_t p_sensor_result);
+int exar7724_vch(uint32_t p_sensor_result);
+int exar7724_vin(uint32_t p_sensor_result);
+int mp2886a_tj(uint32_t p_sensor_result);
+int fan(uint32_t p_sensor_result);
+
+#endif /* _SENSORS_H */
diff --git a/drivers/net/ntnic/sensors/stream_info.h b/drivers/net/ntnic/sensors/stream_info.h
new file mode 100644
index 0000000000..b94231fd8b
--- /dev/null
+++ b/drivers/net/ntnic/sensors/stream_info.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _STREAM_INFO_H
+#define _STREAM_INFO_H
+
+#include "sensor_types.h"
+
+#include <stdint.h>
+
+/*
+ * This structure will return the sensor specific information
+ *
+ * The units used for the fields: value, value_lowest, value_highest, limit_low and
+ * limit_high depend on the type field. See @ref nt_sensor_type_e.
+ *
+ * For the limit_low and limit_high fields the following applies:\n
+ * If the sensor is located in a NIM (Network Interface Module), the limits are read
+ * from the NIM module via the DMI (Diagnostic Monitoring Interface) from the alarm
+ * and warning thresholds section, and the units are changed to internal representation.
+ * Only the alarm thresholds are used and are read only once during initialization.
+ * The limits cannot be changed.
+ *
+ * The value field is updated internally on a regular basis and is also based on a
+ * value read from the NIM which is also changed to internal representation.
+ *
+ * Not all NIM types support DMI data, and its presence must be determined by reading an
+ * option flag. In general, a NIM can read out: temperature, supply voltage,
+ * TX bias, TX optical power and RX optical power but not all NIM types support all
+ * 5 values.
+ *
+ * If external calibration is used (most NIM use internal calibration), both the
+ * current value and the threshold values are subjected to the specified calibration
+ * along with the change to internal calibration.
+ */
+#define NT_INFO_SENSOR_NAME 50
+struct nt_info_sensor_s {
+ enum nt_sensor_source_e
+ source; /* The source of the sensor (port or adapter on which the sensor resides) */
+ /*
+ * The source index - the adapter number for adapter sensors and port number for port
+ * sensors
+ */
+ uint32_t source_index;
+ /*
+ * The sensor index within the source index (sensor number on the adapter or sensor number
+ * on the port)
+ */
+ uint32_t sensor_index;
+ enum nt_sensor_type_e type; /* The sensor type */
+ enum nt_sensor_sub_type_e sub_type; /* The sensor subtype (if applicable) */
+ enum nt_sensor_state_e state; /* The current state (normal or alarm) */
+ int32_t value; /* The current value */
+ int32_t value_lowest; /* The lowest value registered */
+ int32_t value_highest; /* The highest value registered */
+ char name[NT_INFO_SENSOR_NAME + 1]; /* The sensor name */
+ enum nt_adapter_type_e
+ adapter_type; /* The adapter type where the sensor resides */
+};
+
+/* The NT200A02 adapter sensor id's */
+enum nt_sensors_adapter_nt200a02_e {
+ /* Public sensors (Level 0) */
+ NT_SENSOR_NT200A02_FPGA_TEMP, /* FPGA temperature sensor */
+ NT_SENSOR_NT200A02_FAN_SPEED, /* FAN speed sensor */
+
+ NT_SENSOR_NT200A02_MCU_TEMP,
+ NT_SENSOR_NT200A02_PSU0_TEMP, /* Power supply 0 temperature sensor */
+ NT_SENSOR_NT200A02_PSU1_TEMP, /* Power supply 1 temperature sensor */
+ NT_SENSOR_NT200A02_PCB_TEMP, /* PCB temperature sensor */
+
+ /* Diagnostic sensors (Level 1) */
+ /* Total power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_NT200A02_POWER,
+ /* FPGA power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_FPGA_POWER,
+ /* DDR4 RAM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_DDR4_POWER,
+ /* NIM power consumption (calculated value) - does not generate alarms */
+ NT_SENSOR_NT200A02_NIM_POWER,
+
+ NT_SENSOR_NT200A02_L1_MAX, /* Number of NT200A01 level 0,1 board sensors */
+};
+
+#endif
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH v2 4/8] net/ntnic: adds flow related FPGA functionality
2023-08-17 14:43 ` [PATCH v2 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 2/8] net/ntnic: adds core registers and fpga functionality Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 3/8] net/ntnic: adds NT200A02 adapter support Mykola Kostenok
@ 2023-08-17 14:43 ` Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 5/8] net/ntnic: adds FPGA abstraction layer Mykola Kostenok
` (4 subsequent siblings)
7 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-17 14:43 UTC (permalink / raw)
To: dev, mko-plv; +Cc: ckm
From: Christian Koue Muf <ckm@napatech.com>
The PMD will control the registers used for flow programming,
and this commit adds support for this.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
v2:
* Fixed compilation with Fedora 38
---
drivers/net/ntnic/meson.build | 21 +
.../ntnic/nthw/flow_filter/flow_nthw_cat.c | 1107 ++++++++++++++++
.../ntnic/nthw/flow_filter/flow_nthw_cat.h | 372 ++++++
.../ntnic/nthw/flow_filter/flow_nthw_csu.c | 146 +++
.../ntnic/nthw/flow_filter/flow_nthw_csu.h | 42 +
.../ntnic/nthw/flow_filter/flow_nthw_flm.c | 1140 +++++++++++++++++
.../ntnic/nthw/flow_filter/flow_nthw_flm.h | 422 ++++++
.../ntnic/nthw/flow_filter/flow_nthw_hfu.c | 293 +++++
.../ntnic/nthw/flow_filter/flow_nthw_hfu.h | 100 ++
.../ntnic/nthw/flow_filter/flow_nthw_hsh.c | 254 ++++
.../ntnic/nthw/flow_filter/flow_nthw_hsh.h | 81 ++
.../ntnic/nthw/flow_filter/flow_nthw_hst.c | 202 +++
.../ntnic/nthw/flow_filter/flow_nthw_hst.h | 72 ++
.../ntnic/nthw/flow_filter/flow_nthw_ifr.c | 93 ++
.../ntnic/nthw/flow_filter/flow_nthw_ifr.h | 39 +
.../ntnic/nthw/flow_filter/flow_nthw_info.c | 341 +++++
.../ntnic/nthw/flow_filter/flow_nthw_info.h | 104 ++
.../ntnic/nthw/flow_filter/flow_nthw_ioa.c | 234 ++++
.../ntnic/nthw/flow_filter/flow_nthw_ioa.h | 80 ++
.../net/ntnic/nthw/flow_filter/flow_nthw_km.c | 685 ++++++++++
.../net/ntnic/nthw/flow_filter/flow_nthw_km.h | 224 ++++
.../ntnic/nthw/flow_filter/flow_nthw_pdb.c | 230 ++++
.../ntnic/nthw/flow_filter/flow_nthw_pdb.h | 84 ++
.../ntnic/nthw/flow_filter/flow_nthw_qsl.c | 355 +++++
.../ntnic/nthw/flow_filter/flow_nthw_qsl.h | 121 ++
.../ntnic/nthw/flow_filter/flow_nthw_rmc.c | 112 ++
.../ntnic/nthw/flow_filter/flow_nthw_rmc.h | 40 +
.../ntnic/nthw/flow_filter/flow_nthw_roa.c | 294 +++++
.../ntnic/nthw/flow_filter/flow_nthw_roa.h | 109 ++
.../ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c | 132 ++
.../ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h | 53 +
.../ntnic/nthw/flow_filter/flow_nthw_slc.c | 109 ++
.../ntnic/nthw/flow_filter/flow_nthw_slc.h | 46 +
.../ntnic/nthw/flow_filter/flow_nthw_slc_lr.c | 109 ++
.../ntnic/nthw/flow_filter/flow_nthw_slc_lr.h | 46 +
.../ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c | 394 ++++++
.../ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h | 72 ++
.../ntnic/nthw/flow_filter/flow_nthw_tx_ins.c | 96 ++
.../ntnic/nthw/flow_filter/flow_nthw_tx_ins.h | 42 +
.../ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c | 165 +++
.../ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h | 70 +
41 files changed, 8731 insertions(+)
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 383ff15390..c184d5d4b5 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -17,6 +17,7 @@ includes = [
include_directories('nthw'),
include_directories('nthw/core'),
include_directories('nthw/supported'),
+ include_directories('nthw/flow_filter'),
include_directories('sensors'),
include_directories('sensors/avr_sensors'),
include_directories('sensors/board_sensors'),
@@ -58,6 +59,26 @@ sources = files(
'nthw/core/nthw_spim.c',
'nthw/core/nthw_spis.c',
'nthw/core/nthw_tsm.c',
+ 'nthw/flow_filter/flow_nthw_cat.c',
+ 'nthw/flow_filter/flow_nthw_csu.c',
+ 'nthw/flow_filter/flow_nthw_flm.c',
+ 'nthw/flow_filter/flow_nthw_hfu.c',
+ 'nthw/flow_filter/flow_nthw_hsh.c',
+ 'nthw/flow_filter/flow_nthw_hst.c',
+ 'nthw/flow_filter/flow_nthw_ifr.c',
+ 'nthw/flow_filter/flow_nthw_info.c',
+ 'nthw/flow_filter/flow_nthw_ioa.c',
+ 'nthw/flow_filter/flow_nthw_km.c',
+ 'nthw/flow_filter/flow_nthw_pdb.c',
+ 'nthw/flow_filter/flow_nthw_qsl.c',
+ 'nthw/flow_filter/flow_nthw_rmc.c',
+ 'nthw/flow_filter/flow_nthw_roa.c',
+ 'nthw/flow_filter/flow_nthw_rpp_lr.c',
+ 'nthw/flow_filter/flow_nthw_slc.c',
+ 'nthw/flow_filter/flow_nthw_slc_lr.c',
+ 'nthw/flow_filter/flow_nthw_tx_cpy.c',
+ 'nthw/flow_filter/flow_nthw_tx_ins.c',
+ 'nthw/flow_filter/flow_nthw_tx_rpl.c',
'nthw/nthw_fpga_model.c',
'nthw/nthw_dbs.c',
'nthw/nthw_epp.c',
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c
new file mode 100644
index 0000000000..91376363c1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.c
@@ -0,0 +1,1107 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_cat.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+struct cat_nthw *cat_nthw_new(void)
+{
+ struct cat_nthw *p = malloc(sizeof(struct cat_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void cat_nthw_delete(struct cat_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+void cat_nthw_set_debug_mode(struct cat_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_cat, n_debug_mode);
+}
+
+int cat_nthw_init(struct cat_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_CAT, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Cat %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_cat = p_mod;
+
+ p->m_km_if_cnt = fpga_get_product_param(p->mp_fpga, NT_CAT_KM_IF_CNT, -1);
+
+ /* CFN */
+ p->mp_cfn_ctrl = module_get_register(p->m_cat, CAT_CFN_CTRL);
+ p->mp_cfn_addr = register_get_field(p->mp_cfn_ctrl, CAT_CFN_CTRL_ADR);
+ p->mp_cfn_cnt = register_get_field(p->mp_cfn_ctrl, CAT_CFN_CTRL_CNT);
+ p->mp_cfn_data = module_get_register(p->m_cat, CAT_CFN_DATA);
+ p->mp_cfn_data_enable =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ENABLE);
+ p->mp_cfn_data_inv = register_get_field(p->mp_cfn_data, CAT_CFN_DATA_INV);
+ p->mp_cfn_data_ptc_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_INV);
+ p->mp_cfn_data_ptc_isl =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_ISL);
+ p->mp_cfn_data_ptc_mac =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_MAC);
+ p->mp_cfn_data_ptc_l2 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L2);
+ p->mp_cfn_data_ptc_vn_tag =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_VNTAG);
+ p->mp_cfn_data_ptc_vlan =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_VLAN);
+ p->mp_cfn_data_ptc_mpls =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_MPLS);
+ p->mp_cfn_data_ptc_l3 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L3);
+ p->mp_cfn_data_ptc_frag =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_FRAG);
+ p->mp_cfn_data_ptc_ip_prot =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_IP_PROT);
+ p->mp_cfn_data_ptc_l4 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_L4);
+ p->mp_cfn_data_ptc_tunnel =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TUNNEL);
+ p->mp_cfn_data_ptc_tnl_l2 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L2);
+ p->mp_cfn_data_ptc_tnl_vlan =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_VLAN);
+ p->mp_cfn_data_ptc_tnl_mpls =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_MPLS);
+ p->mp_cfn_data_ptc_tnl_l3 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L3);
+ p->mp_cfn_data_ptc_tnl_frag =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_FRAG);
+ p->mp_cfn_data_ptc_tnl_ip_prot =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_IP_PROT);
+ p->mp_cfn_data_ptc_tnl_l4 =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_TNL_L4);
+ p->mp_cfn_data_err_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_INV);
+ p->mp_cfn_data_err_cv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_CV);
+ p->mp_cfn_data_err_fcs =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_FCS);
+ p->mp_cfn_data_err_trunc =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TRUNC);
+ p->mp_cfn_data_mac_port =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_MAC_PORT);
+ p->mp_cfn_data_pm_cmp =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_CMP);
+ p->mp_cfn_data_pm_dct =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_DCT);
+ p->mp_cfn_data_pm_ext_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_EXT_INV);
+ p->mp_cfn_data_pm_cmb =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_CMB);
+ p->mp_cfn_data_pm_and_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_AND_INV);
+ p->mp_cfn_data_pm_or_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_OR_INV);
+ p->mp_cfn_data_pm_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_PM_INV);
+ p->mp_cfn_data_lc = register_get_field(p->mp_cfn_data, CAT_CFN_DATA_LC);
+ p->mp_cfn_data_lc_inv =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_LC_INV);
+
+ if (p->m_km_if_cnt == -1) {
+ p->mp_cfn_data_km0_or =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_KM_OR);
+ } else {
+ p->mp_cfn_data_km0_or =
+ register_get_field(p->mp_cfn_data, CAT_CFN_DATA_KM0_OR);
+ p->mp_cfn_data_km1_or =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_KM1_OR);
+ }
+
+ if (p->m_km_if_cnt < 0) {
+ /* KCE */
+ p->mp_kce_ctrl[0] = module_get_register(p->m_cat, CAT_KCE_CTRL);
+ p->mp_kce_addr[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE_CTRL_ADR);
+ p->mp_kce_cnt[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE_CTRL_CNT);
+ p->mp_kce_data[0] = module_get_register(p->m_cat, CAT_KCE_DATA);
+ p->mp_kce_data_enable[0] =
+ register_get_field(p->mp_kce_data[0], CAT_KCE_DATA_ENABLE);
+ /* KCS */
+ p->mp_kcs_ctrl[0] = module_get_register(p->m_cat, CAT_KCS_CTRL);
+ p->mp_kcs_addr[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS_CTRL_ADR);
+ p->mp_kcs_cnt[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS_CTRL_CNT);
+ p->mp_kcs_data[0] = module_get_register(p->m_cat, CAT_KCS_DATA);
+ p->mp_kcs_data_category[0] =
+ register_get_field(p->mp_kcs_data[0], CAT_KCS_DATA_CATEGORY);
+ /* FTE */
+ p->mp_fte_ctrl[0] = module_get_register(p->m_cat, CAT_FTE_CTRL);
+ p->mp_fte_addr[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE_CTRL_ADR);
+ p->mp_fte_cnt[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE_CTRL_CNT);
+ p->mp_fte_data[0] = module_get_register(p->m_cat, CAT_FTE_DATA);
+ p->mp_fte_data_enable[0] =
+ register_get_field(p->mp_fte_data[0], CAT_FTE_DATA_ENABLE);
+ } else {
+ /* KCE 0 */
+ p->mp_kce_ctrl[0] = module_get_register(p->m_cat, CAT_KCE0_CTRL);
+ p->mp_kce_addr[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE0_CTRL_ADR);
+ p->mp_kce_cnt[0] =
+ register_get_field(p->mp_kce_ctrl[0], CAT_KCE0_CTRL_CNT);
+ p->mp_kce_data[0] = module_get_register(p->m_cat, CAT_KCE0_DATA);
+ p->mp_kce_data_enable[0] = register_get_field(p->mp_kce_data[0],
+ CAT_KCE0_DATA_ENABLE);
+ /* KCS 0 */
+ p->mp_kcs_ctrl[0] = module_get_register(p->m_cat, CAT_KCS0_CTRL);
+ p->mp_kcs_addr[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS0_CTRL_ADR);
+ p->mp_kcs_cnt[0] =
+ register_get_field(p->mp_kcs_ctrl[0], CAT_KCS0_CTRL_CNT);
+ p->mp_kcs_data[0] = module_get_register(p->m_cat, CAT_KCS0_DATA);
+ p->mp_kcs_data_category[0] =
+ register_get_field(p->mp_kcs_data[0], CAT_KCS0_DATA_CATEGORY);
+ /* FTE 0 */
+ p->mp_fte_ctrl[0] = module_get_register(p->m_cat, CAT_FTE0_CTRL);
+ p->mp_fte_addr[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE0_CTRL_ADR);
+ p->mp_fte_cnt[0] =
+ register_get_field(p->mp_fte_ctrl[0], CAT_FTE0_CTRL_CNT);
+ p->mp_fte_data[0] = module_get_register(p->m_cat, CAT_FTE0_DATA);
+ p->mp_fte_data_enable[0] = register_get_field(p->mp_fte_data[0],
+ CAT_FTE0_DATA_ENABLE);
+ /* KCE 1 */
+ p->mp_kce_ctrl[1] = module_get_register(p->m_cat, CAT_KCE1_CTRL);
+ p->mp_kce_addr[1] =
+ register_get_field(p->mp_kce_ctrl[1], CAT_KCE1_CTRL_ADR);
+ p->mp_kce_cnt[1] =
+ register_get_field(p->mp_kce_ctrl[1], CAT_KCE1_CTRL_CNT);
+ p->mp_kce_data[1] = module_get_register(p->m_cat, CAT_KCE1_DATA);
+ p->mp_kce_data_enable[1] = register_get_field(p->mp_kce_data[1],
+ CAT_KCE1_DATA_ENABLE);
+ /* KCS 1 */
+ p->mp_kcs_ctrl[1] = module_get_register(p->m_cat, CAT_KCS1_CTRL);
+ p->mp_kcs_addr[1] =
+ register_get_field(p->mp_kcs_ctrl[1], CAT_KCS1_CTRL_ADR);
+ p->mp_kcs_cnt[1] =
+ register_get_field(p->mp_kcs_ctrl[1], CAT_KCS1_CTRL_CNT);
+ p->mp_kcs_data[1] = module_get_register(p->m_cat, CAT_KCS1_DATA);
+ p->mp_kcs_data_category[1] =
+ register_get_field(p->mp_kcs_data[1], CAT_KCS1_DATA_CATEGORY);
+ /* FTE 1 */
+ p->mp_fte_ctrl[1] = module_get_register(p->m_cat, CAT_FTE1_CTRL);
+ p->mp_fte_addr[1] =
+ register_get_field(p->mp_fte_ctrl[1], CAT_FTE1_CTRL_ADR);
+ p->mp_fte_cnt[1] =
+ register_get_field(p->mp_fte_ctrl[1], CAT_FTE1_CTRL_CNT);
+ p->mp_fte_data[1] = module_get_register(p->m_cat, CAT_FTE1_DATA);
+ p->mp_fte_data_enable[1] = register_get_field(p->mp_fte_data[1],
+ CAT_FTE1_DATA_ENABLE);
+ }
+
+ /* CTE */
+ p->mp_cte_ctrl = module_get_register(p->m_cat, CAT_CTE_CTRL);
+ p->mp_cte_addr = register_get_field(p->mp_cte_ctrl, CAT_CTE_CTRL_ADR);
+ p->mp_cte_cnt = register_get_field(p->mp_cte_ctrl, CAT_CTE_CTRL_CNT);
+ p->mp_cte_data = module_get_register(p->m_cat, CAT_CTE_DATA);
+ p->mp_cte_data_col =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_COL_ENABLE);
+ p->mp_cte_data_cor =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_COR_ENABLE);
+ p->mp_cte_data_hsh =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_HSH_ENABLE);
+ p->mp_cte_data_qsl =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_QSL_ENABLE);
+ p->mp_cte_data_ipf =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_IPF_ENABLE);
+ p->mp_cte_data_slc =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_SLC_ENABLE);
+ p->mp_cte_data_pdb =
+ register_get_field(p->mp_cte_data, CAT_CTE_DATA_PDB_ENABLE);
+ p->mp_cte_data_msk =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_MSK_ENABLE);
+ p->mp_cte_data_hst =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_HST_ENABLE);
+ p->mp_cte_data_epp =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_EPP_ENABLE);
+ p->mp_cte_data_tpe =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_TPE_ENABLE);
+ p->mp_cte_data_rrb =
+ register_query_field(p->mp_cte_data, CAT_CTE_DATA_RRB_ENABLE);
+ /* CTS */
+ p->mp_cts_ctrl = module_get_register(p->m_cat, CAT_CTS_CTRL);
+ p->mp_cts_addr = register_get_field(p->mp_cts_ctrl, CAT_CTS_CTRL_ADR);
+ p->mp_cts_cnt = register_get_field(p->mp_cts_ctrl, CAT_CTS_CTRL_CNT);
+ p->mp_cts_data = module_get_register(p->m_cat, CAT_CTS_DATA);
+ p->mp_cts_data_cat_a = register_get_field(p->mp_cts_data, CAT_CTS_DATA_CAT_A);
+ p->mp_cts_data_cat_b = register_get_field(p->mp_cts_data, CAT_CTS_DATA_CAT_B);
+ /* COT */
+ p->mp_cot_ctrl = module_get_register(p->m_cat, CAT_COT_CTRL);
+ p->mp_cot_addr = register_get_field(p->mp_cot_ctrl, CAT_COT_CTRL_ADR);
+ p->mp_cot_cnt = register_get_field(p->mp_cot_ctrl, CAT_COT_CTRL_CNT);
+ p->mp_cot_data = module_get_register(p->m_cat, CAT_COT_DATA);
+ p->mp_cot_data_color = register_get_field(p->mp_cot_data, CAT_COT_DATA_COLOR);
+ p->mp_cot_data_km = register_get_field(p->mp_cot_data, CAT_COT_DATA_KM);
+ p->mp_cot_data_nfv_sb =
+ register_query_field(p->mp_cot_data, CAT_COT_DATA_NFV_SB);
+ /* CCT */
+ p->mp_cct_ctrl = module_get_register(p->m_cat, CAT_CCT_CTRL);
+ p->mp_cct_addr = register_get_field(p->mp_cct_ctrl, CAT_CCT_CTRL_ADR);
+ p->mp_cct_cnt = register_get_field(p->mp_cct_ctrl, CAT_CCT_CTRL_CNT);
+ p->mp_cct_data = module_get_register(p->m_cat, CAT_CCT_DATA);
+ p->mp_cct_data_color = register_get_field(p->mp_cct_data, CAT_CCT_DATA_COLOR);
+ p->mp_cct_data_km = register_get_field(p->mp_cct_data, CAT_CCT_DATA_KM);
+ /* EXO */
+ p->mp_exo_ctrl = module_get_register(p->m_cat, CAT_EXO_CTRL);
+ p->mp_exo_addr = register_get_field(p->mp_exo_ctrl, CAT_EXO_CTRL_ADR);
+ p->mp_exo_cnt = register_get_field(p->mp_exo_ctrl, CAT_EXO_CTRL_CNT);
+ p->mp_exo_data = module_get_register(p->m_cat, CAT_EXO_DATA);
+ p->mp_exo_data_dyn = register_get_field(p->mp_exo_data, CAT_EXO_DATA_DYN);
+ p->mp_exo_data_ofs = register_get_field(p->mp_exo_data, CAT_EXO_DATA_OFS);
+ /* RCK */
+ p->mp_rck_ctrl = module_get_register(p->m_cat, CAT_RCK_CTRL);
+ p->mp_rck_addr = register_get_field(p->mp_rck_ctrl, CAT_RCK_CTRL_ADR);
+ p->mp_rck_cnt = register_get_field(p->mp_rck_ctrl, CAT_RCK_CTRL_CNT);
+ p->mp_rck_data = module_get_register(p->m_cat, CAT_RCK_DATA);
+ /* LEN */
+ p->mp_len_ctrl = module_get_register(p->m_cat, CAT_LEN_CTRL);
+ p->mp_len_addr = register_get_field(p->mp_len_ctrl, CAT_LEN_CTRL_ADR);
+ p->mp_len_cnt = register_get_field(p->mp_len_ctrl, CAT_LEN_CTRL_CNT);
+ p->mp_len_data = module_get_register(p->m_cat, CAT_LEN_DATA);
+ p->mp_len_data_lower = register_get_field(p->mp_len_data, CAT_LEN_DATA_LOWER);
+ p->mp_len_data_upper = register_get_field(p->mp_len_data, CAT_LEN_DATA_UPPER);
+ p->mp_len_data_dyn1 = register_get_field(p->mp_len_data, CAT_LEN_DATA_DYN1);
+ p->mp_len_data_dyn2 = register_get_field(p->mp_len_data, CAT_LEN_DATA_DYN2);
+ p->mp_len_data_inv = register_get_field(p->mp_len_data, CAT_LEN_DATA_INV);
+
+ p->mp_cfn_data_ptc_cfp =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_PTC_CFP);
+ p->mp_cfn_data_err_l3_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_L3_CS);
+ p->mp_cfn_data_err_l4_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_L4_CS);
+ p->mp_cfn_data_err_tnl_l3_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_L3_CS);
+ p->mp_cfn_data_err_tnl_l4_cs =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_L4_CS);
+ p->mp_cfn_data_err_ttl_exp =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TTL_EXP);
+ p->mp_cfn_data_err_tnl_ttl_exp =
+ register_query_field(p->mp_cfn_data, CAT_CFN_DATA_ERR_TNL_TTL_EXP);
+
+ p->mp_kcc_ctrl = module_query_register(p->m_cat, CAT_KCC_CTRL);
+ if (p->mp_kcc_ctrl != NULL) {
+ p->mp_kcc_addr =
+ register_query_field(p->mp_kcc_ctrl, CAT_KCC_CTRL_ADR);
+ p->mp_kcc_cnt =
+ register_query_field(p->mp_kcc_ctrl, CAT_KCC_CTRL_CNT);
+ }
+ p->mp_kcc_data = module_query_register(p->m_cat, CAT_KCC_DATA);
+ if (p->mp_kcc_data != NULL) {
+ p->mp_kcc_data_key =
+ register_query_field(p->mp_kcc_data, CAT_KCC_DATA_KEY);
+ p->mp_kcc_data_category =
+ register_query_field(p->mp_kcc_data, CAT_KCC_DATA_CATEGORY);
+ p->mp_kcc_data_id =
+ register_query_field(p->mp_kcc_data, CAT_KCC_DATA_ID);
+ }
+
+ p->mp_cce_ctrl = module_query_register(p->m_cat, CAT_CCE_CTRL);
+ if (p->mp_cce_ctrl != NULL) {
+ p->mp_cce_addr =
+ register_query_field(p->mp_cce_ctrl, CAT_CCE_CTRL_ADR);
+ p->mp_cce_cnt =
+ register_query_field(p->mp_cce_ctrl, CAT_CCE_CTRL_CNT);
+ }
+ p->mp_cce_data = module_query_register(p->m_cat, CAT_CCE_DATA);
+ if (p->mp_cce_data != NULL) {
+ p->mp_cce_data_imm =
+ register_query_field(p->mp_cce_data, CAT_CCE_DATA_IMM);
+ p->mp_cce_data_ind =
+ register_query_field(p->mp_cce_data, CAT_CCE_DATA_IND);
+ }
+
+ p->mp_ccs_ctrl = module_query_register(p->m_cat, CAT_CCS_CTRL);
+ if (p->mp_ccs_ctrl != NULL) {
+ p->mp_ccs_addr =
+ register_query_field(p->mp_ccs_ctrl, CAT_CCS_CTRL_ADR);
+ p->mp_ccs_cnt =
+ register_query_field(p->mp_ccs_ctrl, CAT_CCS_CTRL_CNT);
+ }
+ p->mp_ccs_data = module_query_register(p->m_cat, CAT_CCS_DATA);
+ if (p->mp_ccs_data != NULL) {
+ p->mp_ccs_data_cor_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_COR_EN);
+ p->mp_ccs_data_cor =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_COR);
+ p->mp_ccs_data_hsh_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HSH_EN);
+ p->mp_ccs_data_hsh =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HSH);
+ p->mp_ccs_data_qsl_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_QSL_EN);
+ p->mp_ccs_data_qsl =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_QSL);
+ p->mp_ccs_data_ipf_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_IPF_EN);
+ p->mp_ccs_data_ipf =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_IPF);
+ p->mp_ccs_data_slc_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SLC_EN);
+ p->mp_ccs_data_slc =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SLC);
+ p->mp_ccs_data_pdb_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_PDB_EN);
+ p->mp_ccs_data_pdb =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_PDB);
+ p->mp_ccs_data_msk_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_MSK_EN);
+ p->mp_ccs_data_msk =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_MSK);
+ p->mp_ccs_data_hst_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HST_EN);
+ p->mp_ccs_data_hst =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_HST);
+ p->mp_ccs_data_epp_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_EPP_EN);
+ p->mp_ccs_data_epp =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_EPP);
+ p->mp_ccs_data_tpe_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_TPE_EN);
+ p->mp_ccs_data_tpe =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_TPE);
+ p->mp_ccs_data_rrb_en =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_RRB_EN);
+ p->mp_ccs_data_rrb =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_RRB);
+ p->mp_ccs_data_sb0_type =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB0_TYPE);
+ p->mp_ccs_data_sb0_data =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB0_DATA);
+ p->mp_ccs_data_sb1_type =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB1_TYPE);
+ p->mp_ccs_data_sb1_data =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB1_DATA);
+ p->mp_ccs_data_sb2_type =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB2_TYPE);
+ p->mp_ccs_data_sb2_data =
+ register_query_field(p->mp_ccs_data, CAT_CCS_DATA_SB2_DATA);
+ }
+
+ return 0;
+}
+
+/* CFN */
+void cat_nthw_cfn_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_addr, val);
+}
+
+void r(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_cnt, val);
+}
+
+void cat_nthw_cfn_enable(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_enable, val);
+}
+
+void cat_nthw_cfn_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_inv, val);
+}
+
+void cat_nthw_cfn_ptc_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_inv, val);
+}
+
+void cat_nthw_cfn_ptc_isl(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_isl, val);
+}
+
+void cat_nthw_cfn_ptc_mac(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_mac, val);
+}
+
+void cat_nthw_cfn_ptc_l2(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_l2, val);
+}
+
+void cat_nthw_cfn_ptc_vn_tag(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_vn_tag, val);
+}
+
+void cat_nthw_cfn_ptc_vlan(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_vlan, val);
+}
+
+void cat_nthw_cfn_ptc_mpls(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_mpls, val);
+}
+
+void cat_nthw_cfn_ptc_l3(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_l3, val);
+}
+
+void cat_nthw_cfn_ptc_frag(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_frag, val);
+}
+
+void cat_nthw_cfn_ptc_ip_prot(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_ip_prot, val);
+}
+
+void cat_nthw_cfn_ptc_l4(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_l4, val);
+}
+
+void cat_nthw_cfn_ptc_tunnel(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tunnel, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_l2(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_l2, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_vlan(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_vlan, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_mpls(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_mpls, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_l3(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_l3, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_frag(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_frag, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_ip_prot(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_ip_prot, val);
+}
+
+void cat_nthw_cfn_ptc_tnl_l4(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_ptc_tnl_l4, val);
+}
+
+void cat_nthw_cfn_ptc_cfp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_ptc_cfp);
+ field_set_val32(p->mp_cfn_data_ptc_cfp, val);
+}
+
+void cat_nthw_cfn_err_l3_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_l3_cs);
+ field_set_val32(p->mp_cfn_data_err_l3_cs, val);
+}
+
+void cat_nthw_cfn_err_l4_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_l4_cs);
+ field_set_val32(p->mp_cfn_data_err_l4_cs, val);
+}
+
+void cat_nthw_cfn_err_tnl_l3_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_tnl_l3_cs);
+ field_set_val32(p->mp_cfn_data_err_tnl_l3_cs, val);
+}
+
+void cat_nthw_cfn_err_tnl_l4_cs(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_tnl_l4_cs);
+ field_set_val32(p->mp_cfn_data_err_tnl_l4_cs, val);
+}
+
+void cat_nthw_cfn_err_ttl_exp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_ttl_exp);
+ field_set_val32(p->mp_cfn_data_err_ttl_exp, val);
+}
+
+void cat_nthw_cfn_err_tnl_ttl_exp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_err_tnl_ttl_exp);
+ field_set_val32(p->mp_cfn_data_err_tnl_ttl_exp, val);
+}
+
+void cat_nthw_cfn_err_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_inv, val);
+}
+
+void cat_nthw_cfn_err_cv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_cv, val);
+}
+
+void cat_nthw_cfn_err_fcs(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_fcs, val);
+}
+
+void cat_nthw_cfn_err_trunc(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_err_trunc, val);
+}
+
+void cat_nthw_cfn_mac_port(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_mac_port, val);
+}
+
+void cat_nthw_cfn_pm_cmp(const struct cat_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_cfn_data_pm_cmp, val, p->mp_cfn_data_pm_cmp->mn_words);
+}
+
+void cat_nthw_cfn_pm_dct(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_dct, val);
+}
+
+void cat_nthw_cfn_pm_ext_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_ext_inv, val);
+}
+
+void cat_nthw_cfn_pm_cmb(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_cmb, val);
+}
+
+void cat_nthw_cfn_pm_and_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_and_inv, val);
+}
+
+void cat_nthw_cfn_pm_or_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_or_inv, val);
+}
+
+void cat_nthw_cfn_pm_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_pm_inv, val);
+}
+
+void cat_nthw_cfn_lc(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_lc, val);
+}
+
+void cat_nthw_cfn_lc_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_lc_inv, val);
+}
+
+void cat_nthw_cfn_km0_or(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cfn_data_km0_or, val);
+}
+
+void cat_nthw_cfn_km1_or(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cfn_data_km1_or);
+ field_set_val32(p->mp_cfn_data_km1_or, val);
+}
+
+void cat_nthw_cfn_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cfn_ctrl, 1);
+ register_flush(p->mp_cfn_data, 1);
+}
+
+void cat_nthw_kce_select(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kce_addr[index], val);
+}
+
+void cat_nthw_kce_cnt(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kce_cnt[index], val);
+}
+
+void cat_nthw_kce_enable(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kce_data_enable[index], val);
+}
+
+void cat_nthw_kce_flush(const struct cat_nthw *p, int index)
+{
+ register_flush(p->mp_kce_ctrl[index], 1);
+ register_flush(p->mp_kce_data[index], 1);
+}
+
+void cat_nthw_kcs_select(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kcs_addr[index], val);
+}
+
+void cat_nthw_kcs_cnt(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kcs_cnt[index], val);
+}
+
+void cat_nthw_kcs_category(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_kcs_data_category[index], val);
+}
+
+void cat_nthw_kcs_flush(const struct cat_nthw *p, int index)
+{
+ register_flush(p->mp_kcs_ctrl[index], 1);
+ register_flush(p->mp_kcs_data[index], 1);
+}
+
+void cat_nthw_fte_select(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_fte_addr[index], val);
+}
+
+void cat_nthw_fte_cnt(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_fte_cnt[index], val);
+}
+
+void cat_nthw_fte_enable(const struct cat_nthw *p, int index, uint32_t val)
+{
+ field_set_val32(p->mp_fte_data_enable[index], val);
+}
+
+void cat_nthw_fte_flush(const struct cat_nthw *p, int index)
+{
+ register_flush(p->mp_fte_ctrl[index], 1);
+ register_flush(p->mp_fte_data[index], 1);
+}
+
+void cat_nthw_cte_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_addr, val);
+}
+
+void cat_nthw_cte_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_cnt, val);
+}
+
+void cat_nthw_cte_enable_col(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_col, val);
+}
+
+void cat_nthw_cte_enable_cor(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_cor, val);
+}
+
+void cat_nthw_cte_enable_hsh(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_hsh, val);
+}
+
+void cat_nthw_cte_enable_qsl(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_qsl, val);
+}
+
+void cat_nthw_cte_enable_ipf(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_ipf, val);
+}
+
+void cat_nthw_cte_enable_slc(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_slc, val);
+}
+
+void cat_nthw_cte_enable_pdb(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cte_data_pdb, val);
+}
+
+void cat_nthw_cte_enable_msk(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_msk);
+ field_set_val32(p->mp_cte_data_msk, val);
+}
+
+void cat_nthw_cte_enable_hst(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_hst);
+ field_set_val32(p->mp_cte_data_hst, val);
+}
+
+void cat_nthw_cte_enable_epp(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_epp);
+ field_set_val32(p->mp_cte_data_epp, val);
+}
+
+void cat_nthw_cte_enable_tpe(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_tpe);
+ field_set_val32(p->mp_cte_data_tpe, val);
+}
+
+void cat_nthw_cte_enable_rrb(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cte_data_rrb);
+ field_set_val32(p->mp_cte_data_rrb, val);
+}
+
+void cat_nthw_cte_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cte_ctrl, 1);
+ register_flush(p->mp_cte_data, 1);
+}
+
+void cat_nthw_cts_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_addr, val);
+}
+
+void cat_nthw_cts_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_cnt, val);
+}
+
+void cat_nthw_cts_cat_a(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_data_cat_a, val);
+}
+
+void cat_nthw_cts_cat_b(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cts_data_cat_b, val);
+}
+
+void cat_nthw_cts_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cts_ctrl, 1);
+ register_flush(p->mp_cts_data, 1);
+}
+
+void cat_nthw_cot_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_addr, val);
+}
+
+void cat_nthw_cot_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_cnt, val);
+}
+
+void cat_nthw_cot_color(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_data_color, val);
+}
+
+void cat_nthw_cot_km(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cot_data_km, val);
+}
+
+void cat_nthw_cot_nfv_sb(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cot_data_nfv_sb);
+ field_set_val32(p->mp_cot_data_nfv_sb, val);
+}
+
+void cat_nthw_cot_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cot_ctrl, 1);
+ register_flush(p->mp_cot_data, 1);
+}
+
+void cat_nthw_cct_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_addr, val);
+}
+
+void cat_nthw_cct_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_cnt, val);
+}
+
+void cat_nthw_cct_color(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_data_color, val);
+}
+
+void cat_nthw_cct_km(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cct_data_km, val);
+}
+
+void cat_nthw_cct_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_cct_ctrl, 1);
+ register_flush(p->mp_cct_data, 1);
+}
+
+void cat_nthw_exo_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_exo_addr, val);
+}
+
+void cat_nthw_exo_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_exo_cnt, val);
+}
+
+void cat_nthw_exo_dyn(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_exo_data_dyn, val);
+}
+
+void cat_nthw_exo_ofs(const struct cat_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_exo_data_ofs, val);
+}
+
+void cat_nthw_exo_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_exo_ctrl, 1);
+ register_flush(p->mp_exo_data, 1);
+}
+
+void cat_nthw_rck_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rck_addr, val);
+}
+
+void cat_nthw_rck_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rck_cnt, val);
+}
+
+void cat_nthw_rck_data(const struct cat_nthw *p, uint32_t val)
+{
+ register_set_val(p->mp_rck_data, &val, 1);
+ register_make_dirty(p->mp_rck_data);
+}
+
+void cat_nthw_rck_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_rck_ctrl, 1);
+ register_flush(p->mp_rck_data, 1);
+}
+
+void cat_nthw_len_select(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_addr, val);
+}
+
+void cat_nthw_len_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_cnt, val);
+}
+
+void cat_nthw_len_lower(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_lower, val);
+}
+
+void cat_nthw_len_upper(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_upper, val);
+}
+
+void cat_nthw_len_dyn1(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_dyn1, val);
+}
+
+void cat_nthw_len_dyn2(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_dyn2, val);
+}
+
+void cat_nthw_len_inv(const struct cat_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_len_data_inv, val);
+}
+
+void cat_nthw_len_flush(const struct cat_nthw *p)
+{
+ register_flush(p->mp_len_ctrl, 1);
+ register_flush(p->mp_len_data, 1);
+}
+
+void cat_nthw_kcc_select(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_addr);
+ field_set_val32(p->mp_kcc_addr, val);
+}
+
+void cat_nthw_kcc_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_cnt);
+ field_set_val32(p->mp_kcc_cnt, val);
+}
+
+void cat_nthw_kcc_key(const struct cat_nthw *p, uint32_t *val)
+{
+ assert(p->mp_kcc_data_key);
+ field_set_val(p->mp_kcc_data_key, val, 2);
+}
+
+void cat_nthw_kcc_category(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_data_category);
+ field_set_val32(p->mp_kcc_data_category, val);
+}
+
+void cat_nthw_kcc_id(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_kcc_data_id);
+ field_set_val32(p->mp_kcc_data_id, val);
+}
+
+void cat_nthw_kcc_flush(const struct cat_nthw *p)
+{
+ assert(p->mp_kcc_ctrl);
+ assert(p->mp_kcc_data);
+ register_flush(p->mp_kcc_ctrl, 1);
+ register_flush(p->mp_kcc_data, 1);
+}
+
+void cat_nthw_cce_select(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_addr);
+ field_set_val32(p->mp_cce_addr, val);
+}
+
+void cat_nthw_cce_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_cnt);
+ field_set_val32(p->mp_cce_cnt, val);
+}
+
+void cat_nthw_cce_data_imm(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_data_imm);
+ field_set_val32(p->mp_cce_data_imm, val);
+}
+
+void cat_nthw_cce_data_ind(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_cce_data_ind);
+ field_set_val32(p->mp_cce_data_ind, val);
+}
+
+void cat_nthw_cce_flush(const struct cat_nthw *p)
+{
+ assert(p->mp_cce_ctrl);
+ assert(p->mp_cce_data);
+ register_flush(p->mp_cce_ctrl, 1);
+ register_flush(p->mp_cce_data, 1);
+}
+
+void cat_nthw_ccs_select(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_ccs_addr);
+ field_set_val32(p->mp_ccs_addr, val);
+}
+
+void cat_nthw_ccs_cnt(const struct cat_nthw *p, uint32_t val)
+{
+ assert(p->mp_ccs_cnt);
+ field_set_val32(p->mp_ccs_cnt, val);
+}
+
+#define CATNTHW_CCS_SET(name) \
+ void cat_nthw_ccs_data_##name(const struct cat_nthw *p, uint32_t val) \
+ { \
+ assert(p->mp_ccs_data_##name); \
+ field_set_val32(p->mp_ccs_data_##name, val); \
+ }
+
+CATNTHW_CCS_SET(cor_en);
+CATNTHW_CCS_SET(cor);
+CATNTHW_CCS_SET(hsh_en);
+CATNTHW_CCS_SET(hsh);
+CATNTHW_CCS_SET(qsl_en);
+CATNTHW_CCS_SET(qsl);
+CATNTHW_CCS_SET(ipf_en);
+CATNTHW_CCS_SET(ipf);
+CATNTHW_CCS_SET(slc_en);
+CATNTHW_CCS_SET(slc);
+CATNTHW_CCS_SET(pdb_en);
+CATNTHW_CCS_SET(pdb);
+CATNTHW_CCS_SET(msk_en);
+CATNTHW_CCS_SET(msk);
+CATNTHW_CCS_SET(hst_en);
+CATNTHW_CCS_SET(hst);
+CATNTHW_CCS_SET(epp_en);
+CATNTHW_CCS_SET(epp);
+CATNTHW_CCS_SET(tpe_en);
+CATNTHW_CCS_SET(tpe);
+CATNTHW_CCS_SET(rrb_en);
+CATNTHW_CCS_SET(rrb);
+CATNTHW_CCS_SET(sb0_type);
+CATNTHW_CCS_SET(sb0_data);
+CATNTHW_CCS_SET(sb1_type);
+CATNTHW_CCS_SET(sb1_data);
+CATNTHW_CCS_SET(sb2_type);
+CATNTHW_CCS_SET(sb2_data);
+
+void cat_nthw_ccs_flush(const struct cat_nthw *p)
+{
+ assert(p->mp_ccs_ctrl);
+ assert(p->mp_ccs_data);
+ register_flush(p->mp_ccs_ctrl, 1);
+ register_flush(p->mp_ccs_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h
new file mode 100644
index 0000000000..41ac891a93
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_cat.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_CAT_H__
+#define __FLOW_NTHW_CAT_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct cat_nthw;
+
+typedef struct cat_nthw cat_nthw_t;
+
+struct cat_nthw *cat_nthw_new(void);
+void cat_nthw_delete(struct cat_nthw *p);
+int cat_nthw_init(struct cat_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int cat_nthw_setup(struct cat_nthw *p, int n_idx, int n_idx_cnt);
+void cat_nthw_set_debug_mode(struct cat_nthw *p, unsigned int n_debug_mode);
+
+/* CFN */
+void cat_nthw_cfn_select(const struct cat_nthw *p, uint32_t val);
+void r(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_enable(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_isl(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_cfp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_mac(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_l2(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_vn_tag(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_vlan(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_mpls(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_l3(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_frag(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_ip_prot(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_l4(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tunnel(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_l2(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_vlan(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_mpls(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_l3(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_frag(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_ip_prot(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_ptc_tnl_l4(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_cv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_fcs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_trunc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_l3_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_l4_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_tnl_l3_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_tnl_l4_cs(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_ttl_exp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_err_tnl_ttl_exp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_mac_port(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_cmp(const struct cat_nthw *p, const uint32_t *val);
+void cat_nthw_cfn_pm_dct(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_ext_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_cmb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_and_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_or_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_pm_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_lc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_lc_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_km0_or(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_km1_or(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cfn_flush(const struct cat_nthw *p);
+/* KCE 0/1 */
+void cat_nthw_kce_select(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kce_cnt(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kce_enable(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kce_flush(const struct cat_nthw *p, int index);
+/* KCS 0/1 */
+void cat_nthw_kcs_select(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kcs_cnt(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kcs_category(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_kcs_flush(const struct cat_nthw *p, int index);
+/* FTE 0/1 */
+void cat_nthw_fte_select(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_fte_cnt(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_fte_enable(const struct cat_nthw *p, int index, uint32_t val);
+void cat_nthw_fte_flush(const struct cat_nthw *p, int index);
+/* CTE */
+void cat_nthw_cte_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_col(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_cor(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_hsh(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_qsl(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_ipf(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_slc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_pdb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_msk(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_hst(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_epp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_tpe(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_enable_rrb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cte_flush(const struct cat_nthw *p);
+/* CTS */
+void cat_nthw_cts_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cts_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cts_flush(const struct cat_nthw *p);
+void cat_nthw_cts_cat_a(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cts_cat_b(const struct cat_nthw *p, uint32_t val);
+/* COT */
+void cat_nthw_cot_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_color(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_km(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_nfv_sb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cot_flush(const struct cat_nthw *p);
+/* CCT */
+void cat_nthw_cct_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_color(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_km(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cct_flush(const struct cat_nthw *p);
+/* EXO */
+void cat_nthw_exo_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_exo_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_exo_dyn(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_exo_ofs(const struct cat_nthw *p, int32_t val);
+void cat_nthw_exo_flush(const struct cat_nthw *p);
+/* RCK */
+void cat_nthw_rck_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_rck_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_rck_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_rck_flush(const struct cat_nthw *p);
+/* LEN */
+void cat_nthw_len_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_lower(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_upper(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_dyn1(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_dyn2(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_inv(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_len_flush(const struct cat_nthw *p);
+/* KCC */
+void cat_nthw_kcc_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_key(const struct cat_nthw *p, uint32_t *val);
+void cat_nthw_kcc_category(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_id(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_kcc_flush(const struct cat_nthw *p);
+/* CCE */
+void cat_nthw_cce_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_data_imm(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_data_ind(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_cce_flush(const struct cat_nthw *p);
+/* CCS */
+void cat_nthw_ccs_select(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_cnt(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_cor_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_cor(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hsh_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hsh(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_qsl_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_qsl(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_ipf_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_ipf(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_slc_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_slc(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_pdb_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_pdb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_msk_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_msk(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hst_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_hst(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_epp_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_epp(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_tpe_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_tpe(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_rrb_en(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_rrb(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb0_type(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb0_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb1_type(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb1_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb2_type(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_data_sb2_data(const struct cat_nthw *p, uint32_t val);
+void cat_nthw_ccs_flush(const struct cat_nthw *p);
+
+struct cat_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+ nt_module_t *m_cat;
+ int m_km_if_cnt;
+
+ nt_register_t *mp_cfn_ctrl;
+ nt_field_t *mp_cfn_addr;
+ nt_field_t *mp_cfn_cnt;
+ nt_register_t *mp_cfn_data;
+ nt_field_t *mp_cfn_data_enable;
+ nt_field_t *mp_cfn_data_inv;
+ nt_field_t *mp_cfn_data_ptc_inv;
+ nt_field_t *mp_cfn_data_ptc_isl;
+ nt_field_t *mp_cfn_data_ptc_cfp;
+ nt_field_t *mp_cfn_data_ptc_mac;
+ nt_field_t *mp_cfn_data_ptc_l2;
+ nt_field_t *mp_cfn_data_ptc_vn_tag;
+ nt_field_t *mp_cfn_data_ptc_vlan;
+ nt_field_t *mp_cfn_data_ptc_mpls;
+ nt_field_t *mp_cfn_data_ptc_l3;
+ nt_field_t *mp_cfn_data_ptc_frag;
+ nt_field_t *mp_cfn_data_ptc_ip_prot;
+ nt_field_t *mp_cfn_data_ptc_l4;
+ nt_field_t *mp_cfn_data_ptc_tunnel;
+ nt_field_t *mp_cfn_data_ptc_tnl_l2;
+ nt_field_t *mp_cfn_data_ptc_tnl_vlan;
+ nt_field_t *mp_cfn_data_ptc_tnl_mpls;
+ nt_field_t *mp_cfn_data_ptc_tnl_l3;
+ nt_field_t *mp_cfn_data_ptc_tnl_frag;
+ nt_field_t *mp_cfn_data_ptc_tnl_ip_prot;
+ nt_field_t *mp_cfn_data_ptc_tnl_l4;
+ nt_field_t *mp_cfn_data_err_inv;
+ nt_field_t *mp_cfn_data_err_cv;
+ nt_field_t *mp_cfn_data_err_fcs;
+ nt_field_t *mp_cfn_data_err_trunc;
+ nt_field_t *mp_cfn_data_err_l3_cs;
+ nt_field_t *mp_cfn_data_err_l4_cs;
+ nt_field_t *mp_cfn_data_err_tnl_l3_cs;
+ nt_field_t *mp_cfn_data_err_tnl_l4_cs;
+ nt_field_t *mp_cfn_data_err_ttl_exp;
+ nt_field_t *mp_cfn_data_err_tnl_ttl_exp;
+ nt_field_t *mp_cfn_data_mac_port;
+ nt_field_t *mp_cfn_data_pm_cmp;
+ nt_field_t *mp_cfn_data_pm_dct;
+ nt_field_t *mp_cfn_data_pm_ext_inv;
+ nt_field_t *mp_cfn_data_pm_cmb;
+ nt_field_t *mp_cfn_data_pm_and_inv;
+ nt_field_t *mp_cfn_data_pm_or_inv;
+ nt_field_t *mp_cfn_data_pm_inv;
+ nt_field_t *mp_cfn_data_lc;
+ nt_field_t *mp_cfn_data_lc_inv;
+ nt_field_t *mp_cfn_data_km0_or;
+ nt_field_t *mp_cfn_data_km1_or;
+
+ nt_register_t *mp_kce_ctrl[2];
+ nt_field_t *mp_kce_addr[2];
+ nt_field_t *mp_kce_cnt[2];
+ nt_register_t *mp_kce_data[2];
+ nt_field_t *mp_kce_data_enable[2];
+
+ nt_register_t *mp_kcs_ctrl[2];
+ nt_field_t *mp_kcs_addr[2];
+ nt_field_t *mp_kcs_cnt[2];
+ nt_register_t *mp_kcs_data[2];
+ nt_field_t *mp_kcs_data_category[2];
+
+ nt_register_t *mp_fte_ctrl[2];
+ nt_field_t *mp_fte_addr[2];
+ nt_field_t *mp_fte_cnt[2];
+ nt_register_t *mp_fte_data[2];
+ nt_field_t *mp_fte_data_enable[2];
+
+ nt_register_t *mp_cte_ctrl;
+ nt_field_t *mp_cte_addr;
+ nt_field_t *mp_cte_cnt;
+ nt_register_t *mp_cte_data;
+ nt_field_t *mp_cte_data_col;
+ nt_field_t *mp_cte_data_cor;
+ nt_field_t *mp_cte_data_hsh;
+ nt_field_t *mp_cte_data_qsl;
+ nt_field_t *mp_cte_data_ipf;
+ nt_field_t *mp_cte_data_slc;
+ nt_field_t *mp_cte_data_pdb;
+ nt_field_t *mp_cte_data_msk;
+ nt_field_t *mp_cte_data_hst;
+ nt_field_t *mp_cte_data_epp;
+ nt_field_t *mp_cte_data_tpe;
+ nt_field_t *mp_cte_data_rrb;
+
+ nt_register_t *mp_cts_ctrl;
+ nt_field_t *mp_cts_addr;
+ nt_field_t *mp_cts_cnt;
+ nt_register_t *mp_cts_data;
+ nt_field_t *mp_cts_data_cat_a;
+ nt_field_t *mp_cts_data_cat_b;
+
+ nt_register_t *mp_cot_ctrl;
+ nt_field_t *mp_cot_addr;
+ nt_field_t *mp_cot_cnt;
+ nt_register_t *mp_cot_data;
+ nt_field_t *mp_cot_data_color;
+ nt_field_t *mp_cot_data_km;
+ nt_field_t *mp_cot_data_nfv_sb;
+
+ nt_register_t *mp_cct_ctrl;
+ nt_field_t *mp_cct_addr;
+ nt_field_t *mp_cct_cnt;
+ nt_register_t *mp_cct_data;
+ nt_field_t *mp_cct_data_color;
+ nt_field_t *mp_cct_data_km;
+
+ nt_register_t *mp_exo_ctrl;
+ nt_field_t *mp_exo_addr;
+ nt_field_t *mp_exo_cnt;
+ nt_register_t *mp_exo_data;
+ nt_field_t *mp_exo_data_dyn;
+ nt_field_t *mp_exo_data_ofs;
+
+ nt_register_t *mp_rck_ctrl;
+ nt_field_t *mp_rck_addr;
+ nt_field_t *mp_rck_cnt;
+ nt_register_t *mp_rck_data;
+
+ nt_register_t *mp_len_ctrl;
+ nt_field_t *mp_len_addr;
+ nt_field_t *mp_len_cnt;
+ nt_register_t *mp_len_data;
+ nt_field_t *mp_len_data_lower;
+ nt_field_t *mp_len_data_upper;
+ nt_field_t *mp_len_data_dyn1;
+ nt_field_t *mp_len_data_dyn2;
+ nt_field_t *mp_len_data_inv;
+ nt_register_t *mp_kcc_ctrl;
+ nt_field_t *mp_kcc_addr;
+ nt_field_t *mp_kcc_cnt;
+
+ nt_register_t *mp_kcc_data;
+ nt_field_t *mp_kcc_data_key;
+ nt_field_t *mp_kcc_data_category;
+ nt_field_t *mp_kcc_data_id;
+
+ nt_register_t *mp_cce_ctrl;
+ nt_field_t *mp_cce_addr;
+ nt_field_t *mp_cce_cnt;
+
+ nt_register_t *mp_cce_data;
+ nt_field_t *mp_cce_data_imm;
+ nt_field_t *mp_cce_data_ind;
+
+ nt_register_t *mp_ccs_ctrl;
+ nt_field_t *mp_ccs_addr;
+ nt_field_t *mp_ccs_cnt;
+
+ nt_register_t *mp_ccs_data;
+ nt_field_t *mp_ccs_data_cor_en;
+ nt_field_t *mp_ccs_data_cor;
+
+ nt_field_t *mp_ccs_data_hsh_en;
+ nt_field_t *mp_ccs_data_hsh;
+ nt_field_t *mp_ccs_data_qsl_en;
+ nt_field_t *mp_ccs_data_qsl;
+ nt_field_t *mp_ccs_data_ipf_en;
+ nt_field_t *mp_ccs_data_ipf;
+ nt_field_t *mp_ccs_data_slc_en;
+ nt_field_t *mp_ccs_data_slc;
+ nt_field_t *mp_ccs_data_pdb_en;
+ nt_field_t *mp_ccs_data_pdb;
+ nt_field_t *mp_ccs_data_msk_en;
+ nt_field_t *mp_ccs_data_msk;
+ nt_field_t *mp_ccs_data_hst_en;
+ nt_field_t *mp_ccs_data_hst;
+ nt_field_t *mp_ccs_data_epp_en;
+ nt_field_t *mp_ccs_data_epp;
+ nt_field_t *mp_ccs_data_tpe_en;
+ nt_field_t *mp_ccs_data_tpe;
+ nt_field_t *mp_ccs_data_rrb_en;
+ nt_field_t *mp_ccs_data_rrb;
+ nt_field_t *mp_ccs_data_sb0_type;
+ nt_field_t *mp_ccs_data_sb0_data;
+ nt_field_t *mp_ccs_data_sb1_type;
+ nt_field_t *mp_ccs_data_sb1_data;
+ nt_field_t *mp_ccs_data_sb2_type;
+ nt_field_t *mp_ccs_data_sb2_data;
+};
+
+#endif /* __FLOW_NTHW_CAT_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c
new file mode 100644
index 0000000000..5a7f90ad69
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.c
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_csu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void csu_nthw_set_debug_mode(struct csu_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_csu, n_debug_mode);
+}
+
+struct csu_nthw *csu_nthw_new(void)
+{
+ struct csu_nthw *p = malloc(sizeof(struct csu_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void csu_nthw_delete(struct csu_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int csu_nthw_init(struct csu_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_CSU, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Csu %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_csu = p_mod;
+
+ p->mp_rcp_ctrl = module_get_register(p->m_csu, CSU_RCP_CTRL);
+ p->mp_rcp_ctrl_adr = register_get_field(p->mp_rcp_ctrl, CSU_RCP_CTRL_ADR);
+ p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, CSU_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_csu, CSU_RCP_DATA);
+ p->mp_rcp_data_ol3_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_OL3_CMD);
+ p->mp_rcp_data_ol4_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_OL4_CMD);
+ p->mp_rcp_data_il3_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_IL3_CMD);
+ p->mp_rcp_data_il4_cmd =
+ register_get_field(p->mp_rcp_data, CSU_RCP_DATA_IL4_CMD);
+
+ return 0;
+}
+
+void csu_nthw_rcp_select(const struct csu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_adr, val);
+}
+
+void csu_nthw_rcp_cnt(const struct csu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_cnt, val);
+}
+
+void csu_nthw_rcp_outer_l3_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L3 calc method for outer layer3.
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_ol3_cmd, val);
+}
+
+void csu_nthw_rcp_outer_l4_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L4 calc method for outer layer4.
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ * 4: Set UDP checksum value of ZERO for both IPv4/IPv6, set good checksum for TCP.
+ * 5: Set UDP checksum value of ZERO for IPv4, set good checksum for TCP.
+ * 6: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4/IPv6 and UDP,
+ * otherwise GOOD checksum.
+ * 7: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4 and UDP, otherwise
+ * GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_ol4_cmd, val);
+}
+
+void csu_nthw_rcp_inner_l3_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L3 calc method for inner layer3 (tunneled).
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_il3_cmd, val);
+}
+
+void csu_nthw_rcp_inner_l4_cmd(const struct csu_nthw *p, uint32_t val)
+{
+ /*
+ * Select L4 calc method for inner layer4 (tunneled).
+ * 0: Do not touch checksum field.
+ * 1: Check, but do not touch checksum field.
+ * 2: Insert checksum header value for BAD checksum.
+ * 3: Insert checksum header value for GOOD checksum.
+ * 4: Set UDP checksum value of ZERO for both IPv4/IPv6, set good checksum for TCP.
+ * 5: Set UDP checksum value of ZERO for IPv4, set good checksum for TCP.
+ * 6: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4/IPv6 and UDP,
+ * otherwise GOOD checksum.
+ * 7: Set UDP checksum value of ZERO for outer tunnel when tunnel is IPv4 and UDP, otherwise
+ * GOOD checksum.
+ */
+ field_set_val32(p->mp_rcp_data_il4_cmd, val);
+}
+
+void csu_nthw_rcp_flush(const struct csu_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h
new file mode 100644
index 0000000000..6cb0e1f781
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_csu.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_NTHW_CSU_H_
+#define _FLOW_NTHW_CSU_H_
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct csu_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_csu;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_ctrl_adr;
+ nt_field_t *mp_rcp_ctrl_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_ol3_cmd;
+ nt_field_t *mp_rcp_data_ol4_cmd;
+ nt_field_t *mp_rcp_data_il3_cmd;
+ nt_field_t *mp_rcp_data_il4_cmd;
+};
+
+struct csu_nthw *csu_nthw_new(void);
+void csu_nthw_delete(struct csu_nthw *p);
+int csu_nthw_init(struct csu_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int csu_nthw_setup(struct csu_nthw *p, int n_idx, int n_idx_cnt);
+void csu_nthw_set_debug_mode(struct csu_nthw *p, unsigned int n_debug_mode);
+
+void csu_nthw_rcp_select(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_cnt(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_outer_l3_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_outer_l4_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_inner_l3_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_inner_l4_cmd(const struct csu_nthw *p, uint32_t val);
+void csu_nthw_rcp_flush(const struct csu_nthw *p);
+
+#endif /* _FLOW_NTHW_CSU_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c
new file mode 100644
index 0000000000..4549898cc1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.c
@@ -0,0 +1,1140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_rac.h"
+
+#include "flow_nthw_flm.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+struct flm_nthw *flm_nthw_new(void)
+{
+ struct flm_nthw *p = malloc(sizeof(struct flm_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void flm_nthw_delete(struct flm_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+void flm_nthw_set_debug_mode(struct flm_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_flm, n_debug_mode);
+}
+
+int flm_nthw_init(struct flm_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_FLM, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Flm %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_rac = p_fpga->p_fpga_info->mp_nthw_rac;
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_flm = p_mod;
+
+ p->mp_control = module_get_register(p->m_flm, FLM_CONTROL);
+ p->mp_control_enable =
+ register_get_field(p->mp_control, FLM_CONTROL_ENABLE);
+ p->mp_control_init = register_get_field(p->mp_control, FLM_CONTROL_INIT);
+ p->mp_control_lds = register_get_field(p->mp_control, FLM_CONTROL_LDS);
+ p->mp_control_lfs = register_get_field(p->mp_control, FLM_CONTROL_LFS);
+ p->mp_control_lis = register_get_field(p->mp_control, FLM_CONTROL_LIS);
+ p->mp_control_uds = register_get_field(p->mp_control, FLM_CONTROL_UDS);
+ p->mp_control_uis = register_get_field(p->mp_control, FLM_CONTROL_UIS);
+ p->mp_control_rds = register_get_field(p->mp_control, FLM_CONTROL_RDS);
+ p->mp_control_ris = register_get_field(p->mp_control, FLM_CONTROL_RIS);
+ p->mp_control_pds = register_query_field(p->mp_control, FLM_CONTROL_PDS);
+ p->mp_control_pis = register_query_field(p->mp_control, FLM_CONTROL_PIS);
+ p->mp_control_crcwr = register_get_field(p->mp_control, FLM_CONTROL_CRCWR);
+ p->mp_control_crcrd = register_get_field(p->mp_control, FLM_CONTROL_CRCRD);
+ p->mp_control_rbl = register_get_field(p->mp_control, FLM_CONTROL_RBL);
+ p->mp_control_eab = register_get_field(p->mp_control, FLM_CONTROL_EAB);
+ p->mp_control_split_sdram_usage =
+ register_get_field(p->mp_control, FLM_CONTROL_SPLIT_SDRAM_USAGE);
+
+ p->mp_status = module_get_register(p->m_flm, FLM_STATUS);
+ p->mp_status_calibdone =
+ register_get_field(p->mp_status, FLM_STATUS_CALIBDONE);
+ p->mp_status_initdone =
+ register_get_field(p->mp_status, FLM_STATUS_INITDONE);
+ p->mp_status_idle = register_get_field(p->mp_status, FLM_STATUS_IDLE);
+ p->mp_status_critical =
+ register_get_field(p->mp_status, FLM_STATUS_CRITICAL);
+ p->mp_status_panic = register_get_field(p->mp_status, FLM_STATUS_PANIC);
+ p->mp_status_crcerr = register_get_field(p->mp_status, FLM_STATUS_CRCERR);
+ p->mp_status_eft_bp = register_get_field(p->mp_status, FLM_STATUS_EFT_BP);
+
+ p->mp_timeout = module_get_register(p->m_flm, FLM_TIMEOUT);
+ p->mp_timeout_t = register_get_field(p->mp_timeout, FLM_TIMEOUT_T);
+
+ p->mp_scrub = module_get_register(p->m_flm, FLM_SCRUB);
+ p->mp_scrub_i = register_get_field(p->mp_scrub, FLM_SCRUB_I);
+
+ p->mp_load_bin = module_get_register(p->m_flm, FLM_LOAD_BIN);
+ p->mp_load_bin_bin = register_get_field(p->mp_load_bin, FLM_LOAD_BIN_BIN);
+
+ p->mp_load_pps = module_get_register(p->m_flm, FLM_LOAD_PPS);
+ p->mp_load_pps_pps = register_get_field(p->mp_load_pps, FLM_LOAD_PPS_PPS);
+
+ p->mp_load_lps = module_get_register(p->m_flm, FLM_LOAD_LPS);
+ p->mp_load_lps_lps = register_get_field(p->mp_load_lps, FLM_LOAD_LPS_LPS);
+
+ p->mp_load_aps = module_get_register(p->m_flm, FLM_LOAD_APS);
+ p->mp_load_aps_aps = register_get_field(p->mp_load_aps, FLM_LOAD_APS_APS);
+
+ p->mp_prio = module_get_register(p->m_flm, FLM_PRIO);
+ p->mp_prio_limit0 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT0);
+ p->mp_prio_ft0 = register_get_field(p->mp_prio, FLM_PRIO_FT0);
+ p->mp_prio_limit1 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT1);
+ p->mp_prio_ft1 = register_get_field(p->mp_prio, FLM_PRIO_FT1);
+ p->mp_prio_limit2 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT2);
+ p->mp_prio_ft2 = register_get_field(p->mp_prio, FLM_PRIO_FT2);
+ p->mp_prio_limit3 = register_get_field(p->mp_prio, FLM_PRIO_LIMIT3);
+ p->mp_prio_ft3 = register_get_field(p->mp_prio, FLM_PRIO_FT3);
+
+ p->mp_pst_ctrl = module_get_register(p->m_flm, FLM_PST_CTRL);
+ p->mp_pst_ctrl_adr = register_get_field(p->mp_pst_ctrl, FLM_PST_CTRL_ADR);
+ p->mp_pst_ctrl_cnt = register_get_field(p->mp_pst_ctrl, FLM_PST_CTRL_CNT);
+ p->mp_pst_data = module_get_register(p->m_flm, FLM_PST_DATA);
+ p->mp_pst_data_bp = register_get_field(p->mp_pst_data, FLM_PST_DATA_BP);
+ p->mp_pst_data_pp = register_get_field(p->mp_pst_data, FLM_PST_DATA_PP);
+ p->mp_pst_data_tp = register_get_field(p->mp_pst_data, FLM_PST_DATA_TP);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_flm, FLM_RCP_CTRL);
+ p->mp_rcp_ctrl_adr = register_get_field(p->mp_rcp_ctrl, FLM_RCP_CTRL_ADR);
+ p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, FLM_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_flm, FLM_RCP_DATA);
+ p->mp_rcp_data_lookup =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_LOOKUP);
+ p->mp_rcp_data_qw0_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_DYN);
+ p->mp_rcp_data_qw0_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_OFS);
+ p->mp_rcp_data_qw0_sel =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW0_SEL);
+ p->mp_rcp_data_qw4_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW4_DYN);
+ p->mp_rcp_data_qw4_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_QW4_OFS);
+ p->mp_rcp_data_sw8_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_DYN);
+ p->mp_rcp_data_sw8_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_OFS);
+ p->mp_rcp_data_sw8_sel =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW8_SEL);
+ p->mp_rcp_data_sw9_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW9_DYN);
+ p->mp_rcp_data_sw9_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_SW9_OFS);
+ p->mp_rcp_data_mask = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_MASK);
+ p->mp_rcp_data_kid = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_KID);
+ p->mp_rcp_data_opn = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_OPN);
+ p->mp_rcp_data_ipn = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_IPN);
+ p->mp_rcp_data_byt_dyn =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_BYT_DYN);
+ p->mp_rcp_data_byt_ofs =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_BYT_OFS);
+ p->mp_rcp_data_txplm = register_get_field(p->mp_rcp_data, FLM_RCP_DATA_TXPLM);
+ p->mp_rcp_data_auto_ipv4_mask =
+ register_get_field(p->mp_rcp_data, FLM_RCP_DATA_AUTO_IPV4_MASK);
+
+ p->mp_buf_ctrl = module_get_register(p->m_flm, FLM_BUF_CTRL);
+
+ p->mp_lrn_data = module_get_register(p->m_flm, FLM_LRN_DATA);
+ p->mp_inf_data = module_get_register(p->m_flm, FLM_INF_DATA);
+ p->mp_sta_data = module_get_register(p->m_flm, FLM_STA_DATA);
+
+ p->mp_stat_lrn_done = module_get_register(p->m_flm, FLM_STAT_LRN_DONE);
+ p->mp_stat_lrn_done_cnt =
+ register_get_field(p->mp_stat_lrn_done, FLM_STAT_LRN_DONE_CNT);
+
+ p->mp_stat_lrn_ignore = module_get_register(p->m_flm, FLM_STAT_LRN_IGNORE);
+ p->mp_stat_lrn_ignore_cnt =
+ register_get_field(p->mp_stat_lrn_ignore, FLM_STAT_LRN_IGNORE_CNT);
+
+ p->mp_stat_lrn_fail = module_get_register(p->m_flm, FLM_STAT_LRN_FAIL);
+ p->mp_stat_lrn_fail_cnt =
+ register_get_field(p->mp_stat_lrn_fail, FLM_STAT_LRN_FAIL_CNT);
+
+ p->mp_stat_unl_done = module_get_register(p->m_flm, FLM_STAT_UNL_DONE);
+ p->mp_stat_unl_done_cnt =
+ register_get_field(p->mp_stat_unl_done, FLM_STAT_UNL_DONE_CNT);
+
+ p->mp_stat_unl_ignore = module_get_register(p->m_flm, FLM_STAT_UNL_IGNORE);
+ p->mp_stat_unl_ignore_cnt =
+ register_get_field(p->mp_stat_unl_ignore, FLM_STAT_UNL_IGNORE_CNT);
+
+ p->mp_stat_prb_done = module_query_register(p->m_flm, FLM_STAT_PRB_DONE);
+ p->mp_stat_prb_done_cnt =
+ register_query_field(p->mp_stat_prb_done, FLM_STAT_PRB_DONE_CNT);
+
+ p->mp_stat_prb_ignore = module_query_register(p->m_flm, FLM_STAT_PRB_IGNORE);
+ p->mp_stat_prb_ignore_cnt = register_query_field(p->mp_stat_prb_ignore,
+ FLM_STAT_PRB_IGNORE_CNT);
+
+ p->mp_stat_rel_done = module_get_register(p->m_flm, FLM_STAT_REL_DONE);
+ p->mp_stat_rel_done_cnt =
+ register_get_field(p->mp_stat_rel_done, FLM_STAT_REL_DONE_CNT);
+
+ p->mp_stat_rel_ignore = module_get_register(p->m_flm, FLM_STAT_REL_IGNORE);
+ p->mp_stat_rel_ignore_cnt =
+ register_get_field(p->mp_stat_rel_ignore, FLM_STAT_REL_IGNORE_CNT);
+
+ p->mp_stat_aul_done = module_get_register(p->m_flm, FLM_STAT_AUL_DONE);
+ p->mp_stat_aul_done_cnt =
+ register_get_field(p->mp_stat_aul_done, FLM_STAT_AUL_DONE_CNT);
+
+ p->mp_stat_aul_ignore = module_get_register(p->m_flm, FLM_STAT_AUL_IGNORE);
+ p->mp_stat_aul_ignore_cnt =
+ register_get_field(p->mp_stat_aul_ignore, FLM_STAT_AUL_IGNORE_CNT);
+
+ p->mp_stat_aul_fail = module_get_register(p->m_flm, FLM_STAT_AUL_FAIL);
+ p->mp_stat_aul_fail_cnt =
+ register_get_field(p->mp_stat_aul_fail, FLM_STAT_AUL_FAIL_CNT);
+
+ p->mp_stat_tul_done = module_get_register(p->m_flm, FLM_STAT_TUL_DONE);
+ p->mp_stat_tul_done_cnt =
+ register_get_field(p->mp_stat_tul_done, FLM_STAT_TUL_DONE_CNT);
+
+ p->mp_stat_flows = module_get_register(p->m_flm, FLM_STAT_FLOWS);
+ p->mp_stat_flows_cnt =
+ register_get_field(p->mp_stat_flows, FLM_STAT_FLOWS_CNT);
+
+ p->mp_stat_sta_done = module_query_register(p->m_flm, FLM_STAT_STA_DONE);
+ p->mp_stat_sta_done_cnt =
+ register_query_field(p->mp_stat_sta_done, FLM_STAT_STA_DONE_CNT);
+
+ p->mp_stat_inf_done = module_query_register(p->m_flm, FLM_STAT_INF_DONE);
+ p->mp_stat_inf_done_cnt =
+ register_query_field(p->mp_stat_inf_done, FLM_STAT_INF_DONE_CNT);
+
+ p->mp_stat_inf_skip = module_query_register(p->m_flm, FLM_STAT_INF_SKIP);
+ p->mp_stat_inf_skip_cnt =
+ register_query_field(p->mp_stat_inf_skip, FLM_STAT_INF_SKIP_CNT);
+
+ p->mp_stat_pck_hit = module_query_register(p->m_flm, FLM_STAT_PCK_HIT);
+ p->mp_stat_pck_hit_cnt =
+ register_query_field(p->mp_stat_pck_hit, FLM_STAT_PCK_HIT_CNT);
+
+ p->mp_stat_pck_miss = module_query_register(p->m_flm, FLM_STAT_PCK_MISS);
+ p->mp_stat_pck_miss_cnt =
+ register_query_field(p->mp_stat_pck_miss, FLM_STAT_PCK_MISS_CNT);
+
+ p->mp_stat_pck_unh = module_query_register(p->m_flm, FLM_STAT_PCK_UNH);
+ p->mp_stat_pck_unh_cnt =
+ register_query_field(p->mp_stat_pck_unh, FLM_STAT_PCK_UNH_CNT);
+
+ p->mp_stat_pck_dis = module_query_register(p->m_flm, FLM_STAT_PCK_DIS);
+ p->mp_stat_pck_dis_cnt =
+ register_query_field(p->mp_stat_pck_dis, FLM_STAT_PCK_DIS_CNT);
+
+ p->mp_stat_csh_hit = module_query_register(p->m_flm, FLM_STAT_CSH_HIT);
+ p->mp_stat_csh_hit_cnt =
+ register_query_field(p->mp_stat_csh_hit, FLM_STAT_CSH_HIT_CNT);
+
+ p->mp_stat_csh_miss = module_query_register(p->m_flm, FLM_STAT_CSH_MISS);
+ p->mp_stat_csh_miss_cnt =
+ register_query_field(p->mp_stat_csh_miss, FLM_STAT_CSH_MISS_CNT);
+
+ p->mp_stat_csh_unh = module_query_register(p->m_flm, FLM_STAT_CSH_UNH);
+ p->mp_stat_csh_unh_cnt =
+ register_query_field(p->mp_stat_csh_unh, FLM_STAT_CSH_UNH_CNT);
+
+ p->mp_stat_cuc_start = module_query_register(p->m_flm, FLM_STAT_CUC_START);
+ p->mp_stat_cuc_start_cnt =
+ register_query_field(p->mp_stat_cuc_start, FLM_STAT_CUC_START_CNT);
+
+ p->mp_stat_cuc_move = module_query_register(p->m_flm, FLM_STAT_CUC_MOVE);
+ p->mp_stat_cuc_move_cnt =
+ register_query_field(p->mp_stat_cuc_move, FLM_STAT_CUC_MOVE_CNT);
+
+ return 0;
+}
+
+void flm_nthw_control_enable(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_enable, val);
+}
+
+void flm_nthw_control_init(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_init, val);
+}
+
+void flm_nthw_control_lds(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_lds, val);
+}
+
+void flm_nthw_control_lfs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_lfs, val);
+}
+
+void flm_nthw_control_lis(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_lis, val);
+}
+
+void flm_nthw_control_uds(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_uds, val);
+}
+
+void flm_nthw_control_uis(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_uis, val);
+}
+
+void flm_nthw_control_rds(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_rds, val);
+}
+
+void flm_nthw_control_ris(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_ris, val);
+}
+
+void flm_nthw_control_pds(const struct flm_nthw *p, uint32_t val)
+{
+ assert(p->mp_control_pds);
+ field_set_val32(p->mp_control_pds, val);
+}
+
+void flm_nthw_control_pis(const struct flm_nthw *p, uint32_t val)
+{
+ assert(p->mp_control_pis);
+ field_set_val32(p->mp_control_pis, val);
+}
+
+void flm_nthw_control_crcwr(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_crcwr, val);
+}
+
+void flm_nthw_control_crcrd(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_crcrd, val);
+}
+
+void flm_nthw_control_rbl(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_rbl, val);
+}
+
+void flm_nthw_control_eab(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_eab, val);
+}
+
+void flm_nthw_control_split_sdram_usage(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_control_split_sdram_usage, val);
+}
+
+void flm_nthw_control_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_control, 1);
+}
+
+void flm_nthw_status_calibdone(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_calibdone);
+}
+
+void flm_nthw_status_initdone(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_initdone);
+}
+
+void flm_nthw_status_idle(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_idle);
+}
+
+void flm_nthw_status_critical(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_critical);
+
+ else
+ field_set_val32(p->mp_status_critical, *val);
+}
+
+void flm_nthw_status_panic(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_panic);
+
+ else
+ field_set_val32(p->mp_status_panic, *val);
+}
+
+void flm_nthw_status_crcerr(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_crcerr);
+
+ else
+ field_set_val32(p->mp_status_crcerr, *val);
+}
+
+void flm_nthw_status_eft_bp(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_status_eft_bp);
+}
+
+void flm_nthw_status_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_status, 1);
+}
+
+void flm_nthw_status_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_status);
+}
+
+void flm_nthw_timeout_t(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_timeout_t, val);
+}
+
+void flm_nthw_timeout_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_timeout, 1);
+}
+
+void flm_nthw_scrub_i(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_scrub_i, val);
+}
+
+void flm_nthw_scrub_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_scrub, 1);
+}
+
+void flm_nthw_load_bin(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_bin_bin, val);
+}
+
+void flm_nthw_load_bin_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_bin, 1);
+}
+
+void flm_nthw_load_pps(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_pps_pps, val);
+}
+
+void flm_nthw_load_pps_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_pps, 1);
+}
+
+void flm_nthw_load_lps(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_lps_lps, val);
+}
+
+void flm_nthw_load_lps_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_lps, 1);
+}
+
+void flm_nthw_load_aps(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_load_aps_aps, val);
+}
+
+void flm_nthw_load_aps_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_load_aps, 1);
+}
+
+void flm_nthw_prio_limit0(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit0, val);
+}
+
+void flm_nthw_prio_ft0(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft0, val);
+}
+
+void flm_nthw_prio_limit1(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit1, val);
+}
+
+void flm_nthw_prio_ft1(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft1, val);
+}
+
+void flm_nthw_prio_limit2(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit2, val);
+}
+
+void flm_nthw_prio_ft2(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft2, val);
+}
+
+void flm_nthw_prio_limit3(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_limit3, val);
+}
+
+void flm_nthw_prio_ft3(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_prio_ft3, val);
+}
+
+void flm_nthw_prio_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_prio, 1);
+}
+
+void flm_nthw_pst_select(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_ctrl_adr, val);
+}
+
+void flm_nthw_pst_cnt(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_ctrl_cnt, val);
+}
+
+void flm_nthw_pst_bp(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_data_bp, val);
+}
+
+void flm_nthw_pst_pp(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_data_pp, val);
+}
+
+void flm_nthw_pst_tp(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_pst_data_tp, val);
+}
+
+void flm_nthw_pst_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_pst_ctrl, 1);
+ register_flush(p->mp_pst_data, 1);
+}
+
+void flm_nthw_rcp_select(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_adr, val);
+}
+
+void flm_nthw_rcp_cnt(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_cnt, val);
+}
+
+void flm_nthw_rcp_lookup(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_lookup, val);
+}
+
+void flm_nthw_rcp_qw0_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_dyn, val);
+}
+
+void flm_nthw_rcp_qw0_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_ofs, val);
+}
+
+void flm_nthw_rcp_qw0_sel(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_sel, val);
+}
+
+void flm_nthw_rcp_qw4_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_dyn, val);
+}
+
+void flm_nthw_rcp_qw4_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_ofs, val);
+}
+
+void flm_nthw_rcp_sw8_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw8_dyn, val);
+}
+
+void flm_nthw_rcp_sw8_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw8_ofs, val);
+}
+
+void flm_nthw_rcp_sw8_sel(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw8_sel, val);
+}
+
+void flm_nthw_rcp_sw9_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw9_dyn, val);
+}
+
+void flm_nthw_rcp_sw9_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw9_ofs, val);
+}
+
+void flm_nthw_rcp_mask(const struct flm_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask, val, 10);
+}
+
+void flm_nthw_rcp_kid(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_kid, val);
+}
+
+void flm_nthw_rcp_opn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_opn, val);
+}
+
+void flm_nthw_rcp_ipn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ipn, val);
+}
+
+void flm_nthw_rcp_byt_dyn(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_byt_dyn, val);
+}
+
+void flm_nthw_rcp_byt_ofs(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_byt_ofs, val);
+}
+
+void flm_nthw_rcp_txplm(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_txplm, val);
+}
+
+void flm_nthw_rcp_auto_ipv4_mask(const struct flm_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_auto_ipv4_mask, val);
+}
+
+void flm_nthw_rcp_flush(const struct flm_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+int flm_nthw_buf_ctrl_update(const struct flm_nthw *p, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr bc_buf;
+
+ ret = nthw_rac_rab_dma_begin(rac);
+ if (ret == 0) {
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+int flm_nthw_lrn_data_flush(const struct flm_nthw *p, const uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address = register_get_address(p->mp_lrn_data);
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr bc_buf;
+
+ if (nthw_rac_rab_dma_begin(rac) == 0) {
+ /* Announce the number of words to write to LRN_DATA */
+ uint32_t bufctrl_data[2];
+
+ bufctrl_data[0] = word_count;
+ bufctrl_data[1] = 0;
+ nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2,
+ bufctrl_data);
+ nthw_rac_rab_write32_dma(rac, address, bus_id, word_count, data);
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+int flm_nthw_inf_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address_infdata = register_get_address(p->mp_inf_data);
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr buf;
+ struct dma_buf_ptr bc_buf;
+
+ ret = nthw_rac_rab_dma_begin(rac);
+ if (ret == 0) {
+ /* Announce the number of words to read from INF_DATA */
+ uint32_t bufctrl_data[2];
+
+ bufctrl_data[0] = word_count << 16;
+ bufctrl_data[1] = 0;
+ nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2,
+ bufctrl_data);
+ nthw_rac_rab_read32_dma(rac, address_infdata, bus_id, word_count,
+ &buf);
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t mask = buf.size - 1;
+ uint32_t index = buf.index;
+
+ for (uint32_t i = 0; i < word_count; ++index, ++i)
+ data[i] = buf.base[index & mask];
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+int flm_nthw_sta_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail)
+{
+ int ret = -1;
+
+ struct nthw_rac *rac = (struct nthw_rac *)p->mp_rac;
+ uint32_t address_stadata = register_get_address(p->mp_sta_data);
+ uint32_t address_bufctrl = register_get_address(p->mp_buf_ctrl);
+ rab_bus_id_t bus_id = 1;
+ struct dma_buf_ptr buf;
+ struct dma_buf_ptr bc_buf;
+
+ ret = nthw_rac_rab_dma_begin(rac);
+ if (ret == 0) {
+ /* Announce the number of words to read from STA_DATA */
+ uint32_t bufctrl_data[2];
+
+ bufctrl_data[0] = 0;
+ bufctrl_data[1] = word_count;
+ nthw_rac_rab_write32_dma(rac, address_bufctrl, bus_id, 2,
+ bufctrl_data);
+ nthw_rac_rab_read32_dma(rac, address_stadata, bus_id, word_count,
+ &buf);
+ nthw_rac_rab_read32_dma(rac, address_bufctrl, bus_id, 2, &bc_buf);
+ ret = nthw_rac_rab_dma_commit(rac);
+ if (ret != 0)
+ return ret;
+
+ uint32_t mask = buf.size - 1;
+ uint32_t index = buf.index;
+
+ for (uint32_t i = 0; i < word_count; ++index, ++i)
+ data[i] = buf.base[index & mask];
+
+ uint32_t bc_mask = bc_buf.size - 1;
+ uint32_t bc_index = bc_buf.index;
+ *lrn_free = bc_buf.base[bc_index & bc_mask] & 0xffff;
+ *inf_avail = (bc_buf.base[bc_index & bc_mask] >> 16) & 0xffff;
+ *sta_avail = bc_buf.base[(bc_index + 1) & bc_mask] & 0xffff;
+ }
+
+ return ret;
+}
+
+void flm_nthw_stat_lrn_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_lrn_done_cnt);
+}
+
+void flm_nthw_stat_lrn_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_lrn_done);
+}
+
+void flm_nthw_stat_lrn_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_lrn_ignore_cnt);
+}
+
+void flm_nthw_stat_lrn_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_lrn_ignore);
+}
+
+void flm_nthw_stat_lrn_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_lrn_fail_cnt);
+}
+
+void flm_nthw_stat_lrn_fail_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_lrn_fail);
+}
+
+void flm_nthw_stat_unl_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_unl_done_cnt);
+}
+
+void flm_nthw_stat_unl_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_unl_done);
+}
+
+void flm_nthw_stat_unl_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_unl_ignore_cnt);
+}
+
+void flm_nthw_stat_unl_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_unl_ignore);
+}
+
+void flm_nthw_stat_prb_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_prb_done_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_prb_done_cnt);
+}
+
+void flm_nthw_stat_prb_done_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_prb_done);
+ register_update(p->mp_stat_prb_done);
+}
+
+void flm_nthw_stat_prb_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_prb_ignore_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_prb_ignore_cnt);
+}
+
+void flm_nthw_stat_prb_ignore_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_prb_ignore);
+ register_update(p->mp_stat_prb_ignore);
+}
+
+void flm_nthw_stat_rel_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_rel_done_cnt);
+}
+
+void flm_nthw_stat_rel_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_rel_done);
+}
+
+void flm_nthw_stat_rel_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_rel_ignore_cnt);
+}
+
+void flm_nthw_stat_rel_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_rel_ignore);
+}
+
+void flm_nthw_stat_aul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_aul_done_cnt);
+}
+
+void flm_nthw_stat_aul_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_aul_done);
+}
+
+void flm_nthw_stat_aul_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_aul_ignore_cnt);
+}
+
+void flm_nthw_stat_aul_ignore_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_aul_ignore);
+}
+
+void flm_nthw_stat_aul_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_aul_fail_cnt);
+}
+
+void flm_nthw_stat_aul_fail_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_aul_fail);
+}
+
+void flm_nthw_stat_tul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_tul_done_cnt);
+}
+
+void flm_nthw_stat_tul_done_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_tul_done);
+}
+
+void flm_nthw_stat_flows_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ if (get)
+ *val = field_get_val32(p->mp_stat_flows_cnt);
+}
+
+void flm_nthw_stat_flows_update(const struct flm_nthw *p)
+{
+ register_update(p->mp_stat_flows);
+}
+
+void flm_nthw_stat_sta_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_sta_done_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_sta_done_cnt);
+}
+
+void flm_nthw_stat_sta_done_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_sta_done);
+ register_update(p->mp_stat_sta_done);
+}
+
+void flm_nthw_stat_inf_done_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_inf_done_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_inf_done_cnt);
+}
+
+void flm_nthw_stat_inf_done_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_inf_done);
+ register_update(p->mp_stat_inf_done);
+}
+
+void flm_nthw_stat_inf_skip_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_inf_skip_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_inf_skip_cnt);
+}
+
+void flm_nthw_stat_inf_skip_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_inf_skip);
+ register_update(p->mp_stat_inf_skip);
+}
+
+void flm_nthw_stat_pck_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_hit_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_hit_cnt);
+}
+
+void flm_nthw_stat_pck_hit_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_hit);
+ register_update(p->mp_stat_pck_hit);
+}
+
+void flm_nthw_stat_pck_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_miss_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_miss_cnt);
+}
+
+void flm_nthw_stat_pck_miss_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_miss);
+ register_update(p->mp_stat_pck_miss);
+}
+
+void flm_nthw_stat_pck_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_unh_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_unh_cnt);
+}
+
+void flm_nthw_stat_pck_unh_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_unh);
+ register_update(p->mp_stat_pck_unh);
+}
+
+void flm_nthw_stat_pck_dis_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_pck_dis_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_pck_dis_cnt);
+}
+
+void flm_nthw_stat_pck_dis_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_pck_dis);
+ register_update(p->mp_stat_pck_dis);
+}
+
+void flm_nthw_stat_csh_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_csh_hit_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_csh_hit_cnt);
+}
+
+void flm_nthw_stat_csh_hit_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_csh_hit);
+ register_update(p->mp_stat_csh_hit);
+}
+
+void flm_nthw_stat_csh_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_csh_miss_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_csh_miss_cnt);
+}
+
+void flm_nthw_stat_csh_miss_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_csh_miss);
+ register_update(p->mp_stat_csh_miss);
+}
+
+void flm_nthw_stat_csh_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_csh_unh_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_csh_unh_cnt);
+}
+
+void flm_nthw_stat_csh_unh_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_csh_unh);
+ register_update(p->mp_stat_csh_unh);
+}
+
+void flm_nthw_stat_cuc_start_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_cuc_start_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_cuc_start_cnt);
+}
+
+void flm_nthw_stat_cuc_start_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_cuc_start);
+ register_update(p->mp_stat_cuc_start);
+}
+
+void flm_nthw_stat_cuc_move_cnt(const struct flm_nthw *p, uint32_t *val, int get)
+{
+ assert(p->mp_stat_cuc_move_cnt);
+ if (get)
+ *val = field_get_val32(p->mp_stat_cuc_move_cnt);
+}
+
+void flm_nthw_stat_cuc_move_update(const struct flm_nthw *p)
+{
+ assert(p->mp_stat_cuc_move);
+ register_update(p->mp_stat_cuc_move);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h
new file mode 100644
index 0000000000..4796d43940
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_flm.h
@@ -0,0 +1,422 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_FLM_H__
+#define __FLOW_NTHW_FLM_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct flm_nthw;
+
+typedef struct flm_nthw flm_nthw_t;
+
+struct flm_nthw *flm_nthw_new(void);
+void flm_nthw_delete(struct flm_nthw *p);
+int flm_nthw_init(struct flm_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+void flm_nthw_set_debug_mode(struct flm_nthw *p, unsigned int n_debug_mode);
+
+/* Control */
+void flm_nthw_control_enable(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_init(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_lds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_lfs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_lis(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_uds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_uis(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_rds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_ris(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_pds(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_pis(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_crcwr(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_crcrd(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_rbl(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_eab(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_split_sdram_usage(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_control_flush(const struct flm_nthw *p);
+
+/* Status */
+void flm_nthw_status_calibdone(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_initdone(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_idle(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_critical(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_panic(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_crcerr(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_eft_bp(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_status_flush(const struct flm_nthw *p);
+void flm_nthw_status_update(const struct flm_nthw *p);
+
+/* Timeout */
+void flm_nthw_timeout_t(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_timeout_flush(const struct flm_nthw *p);
+
+/* Scrub */
+void flm_nthw_scrub_i(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_scrub_flush(const struct flm_nthw *p);
+
+/* Load BIN */
+void flm_nthw_load_bin(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_bin_flush(const struct flm_nthw *p);
+
+/* Load PPS */
+void flm_nthw_load_pps(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_pps_flush(const struct flm_nthw *p);
+
+/* Load LPS */
+void flm_nthw_load_lps(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_lps_flush(const struct flm_nthw *p);
+
+/* Load APS */
+void flm_nthw_load_aps(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_load_aps_flush(const struct flm_nthw *p);
+
+/* Prio */
+void flm_nthw_prio_limit0(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft0(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_limit1(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft1(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_limit2(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft2(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_limit3(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_ft3(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_prio_flush(const struct flm_nthw *p);
+
+/* PST */
+void flm_nthw_pst_select(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_cnt(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_bp(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_pp(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_tp(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_pst_flush(const struct flm_nthw *p);
+
+/* RCP */
+void flm_nthw_rcp_select(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_cnt(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_lookup(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw0_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw0_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw0_sel(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw4_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_qw4_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw8_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw8_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw8_sel(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw9_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_sw9_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_mask(const struct flm_nthw *p, const uint32_t *val);
+void flm_nthw_rcp_kid(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_opn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_ipn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_byt_dyn(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_byt_ofs(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_txplm(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_auto_ipv4_mask(const struct flm_nthw *p, uint32_t val);
+void flm_nthw_rcp_flush(const struct flm_nthw *p);
+
+/* Buf Ctrl */
+int flm_nthw_buf_ctrl_update(const struct flm_nthw *p, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Lrn Data */
+int flm_nthw_lrn_data_flush(const struct flm_nthw *p, const uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Inf Data */
+int flm_nthw_inf_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Sta Data */
+int flm_nthw_sta_data_update(const struct flm_nthw *p, uint32_t *data,
+ uint32_t word_count, uint32_t *lrn_free,
+ uint32_t *inf_avail, uint32_t *sta_avail);
+
+/* Stat Lrn _done */
+void flm_nthw_stat_lrn_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_lrn_done_update(const struct flm_nthw *p);
+
+/* Stat Lrn Ignore */
+void flm_nthw_stat_lrn_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_lrn_ignore_update(const struct flm_nthw *p);
+
+/* Stat Lrn Fail */
+void flm_nthw_stat_lrn_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_lrn_fail_update(const struct flm_nthw *p);
+
+/* Stat Unl _done */
+void flm_nthw_stat_unl_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_unl_done_update(const struct flm_nthw *p);
+
+/* Stat Unl Ignore */
+void flm_nthw_stat_unl_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_unl_ignore_update(const struct flm_nthw *p);
+
+/* Stat Prb _done */
+void flm_nthw_stat_prb_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_prb_done_update(const struct flm_nthw *p);
+
+/* Stat Prb Ignore */
+void flm_nthw_stat_prb_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_prb_ignore_update(const struct flm_nthw *p);
+
+/* Stat Rel _done */
+void flm_nthw_stat_rel_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_rel_done_update(const struct flm_nthw *p);
+
+/* Stat Rel Ignore */
+void flm_nthw_stat_rel_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_rel_ignore_update(const struct flm_nthw *p);
+
+/* Stat Aul _done */
+void flm_nthw_stat_aul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_aul_done_update(const struct flm_nthw *p);
+
+/* Stat Aul Ignore */
+void flm_nthw_stat_aul_ignore_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_aul_ignore_update(const struct flm_nthw *p);
+
+/* Stat Aul Fail */
+void flm_nthw_stat_aul_fail_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_aul_fail_update(const struct flm_nthw *p);
+
+/* Stat Tul _done */
+void flm_nthw_stat_tul_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_tul_done_update(const struct flm_nthw *p);
+
+/* Stat Flows */
+void flm_nthw_stat_flows_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_flows_update(const struct flm_nthw *p);
+
+/* Stat Sta _done */
+void flm_nthw_stat_sta_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_sta_done_update(const struct flm_nthw *p);
+
+/* Stat Inf _done */
+void flm_nthw_stat_inf_done_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_inf_done_update(const struct flm_nthw *p);
+
+/* Stat Inf Skip */
+void flm_nthw_stat_inf_skip_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_inf_skip_update(const struct flm_nthw *p);
+
+/* Stat Pck Hit */
+void flm_nthw_stat_pck_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_hit_update(const struct flm_nthw *p);
+
+/* Stat Pck Miss */
+void flm_nthw_stat_pck_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_miss_update(const struct flm_nthw *p);
+
+/* Stat Pck Unh */
+void flm_nthw_stat_pck_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_unh_update(const struct flm_nthw *p);
+
+/* Stat Pck Dis */
+void flm_nthw_stat_pck_dis_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_pck_dis_update(const struct flm_nthw *p);
+
+/* Stat Csh Hit */
+void flm_nthw_stat_csh_hit_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_csh_hit_update(const struct flm_nthw *p);
+
+/* Stat Csh Miss */
+void flm_nthw_stat_csh_miss_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_csh_miss_update(const struct flm_nthw *p);
+
+/* Stat Csh Unh */
+void flm_nthw_stat_csh_unh_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_csh_unh_update(const struct flm_nthw *p);
+
+/* Stat Cuc Start */
+void flm_nthw_stat_cuc_start_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_cuc_start_update(const struct flm_nthw *p);
+
+/* Stat Cuc Move */
+void flm_nthw_stat_cuc_move_cnt(const struct flm_nthw *p, uint32_t *val, int get);
+void flm_nthw_stat_cuc_move_update(const struct flm_nthw *p);
+
+struct flm_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+ void *mp_rac;
+
+ nt_module_t *m_flm;
+
+ nt_register_t *mp_control;
+ nt_field_t *mp_control_enable;
+ nt_field_t *mp_control_init;
+ nt_field_t *mp_control_lds;
+ nt_field_t *mp_control_lfs;
+ nt_field_t *mp_control_lis;
+ nt_field_t *mp_control_uds;
+ nt_field_t *mp_control_uis;
+ nt_field_t *mp_control_rds;
+ nt_field_t *mp_control_ris;
+ nt_field_t *mp_control_pds;
+ nt_field_t *mp_control_pis;
+ nt_field_t *mp_control_crcwr;
+ nt_field_t *mp_control_crcrd;
+ nt_field_t *mp_control_rbl;
+ nt_field_t *mp_control_eab;
+ nt_field_t *mp_control_split_sdram_usage;
+
+ nt_register_t *mp_status;
+ nt_field_t *mp_status_calibdone;
+ nt_field_t *mp_status_initdone;
+ nt_field_t *mp_status_idle;
+ nt_field_t *mp_status_critical;
+ nt_field_t *mp_status_panic;
+ nt_field_t *mp_status_crcerr;
+ nt_field_t *mp_status_eft_bp;
+
+ nt_register_t *mp_timeout;
+ nt_field_t *mp_timeout_t;
+
+ nt_register_t *mp_scrub;
+ nt_field_t *mp_scrub_i;
+
+ nt_register_t *mp_load_bin;
+ nt_field_t *mp_load_bin_bin;
+
+ nt_register_t *mp_load_pps;
+ nt_field_t *mp_load_pps_pps;
+
+ nt_register_t *mp_load_lps;
+ nt_field_t *mp_load_lps_lps;
+
+ nt_register_t *mp_load_aps;
+ nt_field_t *mp_load_aps_aps;
+
+ nt_register_t *mp_prio;
+ nt_field_t *mp_prio_limit0;
+ nt_field_t *mp_prio_ft0;
+ nt_field_t *mp_prio_limit1;
+ nt_field_t *mp_prio_ft1;
+ nt_field_t *mp_prio_limit2;
+ nt_field_t *mp_prio_ft2;
+ nt_field_t *mp_prio_limit3;
+ nt_field_t *mp_prio_ft3;
+
+ nt_register_t *mp_pst_ctrl;
+ nt_field_t *mp_pst_ctrl_adr;
+ nt_field_t *mp_pst_ctrl_cnt;
+ nt_register_t *mp_pst_data;
+ nt_field_t *mp_pst_data_bp;
+ nt_field_t *mp_pst_data_pp;
+ nt_field_t *mp_pst_data_tp;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_ctrl_adr;
+ nt_field_t *mp_rcp_ctrl_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_lookup;
+ nt_field_t *mp_rcp_data_qw0_dyn;
+ nt_field_t *mp_rcp_data_qw0_ofs;
+ nt_field_t *mp_rcp_data_qw0_sel;
+ nt_field_t *mp_rcp_data_qw4_dyn;
+ nt_field_t *mp_rcp_data_qw4_ofs;
+ nt_field_t *mp_rcp_data_sw8_dyn;
+ nt_field_t *mp_rcp_data_sw8_ofs;
+ nt_field_t *mp_rcp_data_sw8_sel;
+ nt_field_t *mp_rcp_data_sw9_dyn;
+ nt_field_t *mp_rcp_data_sw9_ofs;
+ nt_field_t *mp_rcp_data_mask;
+ nt_field_t *mp_rcp_data_kid;
+ nt_field_t *mp_rcp_data_opn;
+ nt_field_t *mp_rcp_data_ipn;
+ nt_field_t *mp_rcp_data_byt_dyn;
+ nt_field_t *mp_rcp_data_byt_ofs;
+ nt_field_t *mp_rcp_data_txplm;
+ nt_field_t *mp_rcp_data_auto_ipv4_mask;
+
+ nt_register_t *mp_buf_ctrl;
+ nt_field_t *mp_buf_ctrl_lrn_free;
+ nt_field_t *mp_buf_ctrl_inf_avail;
+ nt_field_t *mp_buf_ctrl_sta_avail;
+
+ nt_register_t *mp_lrn_data;
+ nt_register_t *mp_inf_data;
+ nt_register_t *mp_sta_data;
+
+ nt_register_t *mp_stat_lrn_done;
+ nt_field_t *mp_stat_lrn_done_cnt;
+
+ nt_register_t *mp_stat_lrn_ignore;
+ nt_field_t *mp_stat_lrn_ignore_cnt;
+
+ nt_register_t *mp_stat_lrn_fail;
+ nt_field_t *mp_stat_lrn_fail_cnt;
+
+ nt_register_t *mp_stat_unl_done;
+ nt_field_t *mp_stat_unl_done_cnt;
+
+ nt_register_t *mp_stat_unl_ignore;
+ nt_field_t *mp_stat_unl_ignore_cnt;
+
+ nt_register_t *mp_stat_prb_done;
+ nt_field_t *mp_stat_prb_done_cnt;
+
+ nt_register_t *mp_stat_prb_ignore;
+ nt_field_t *mp_stat_prb_ignore_cnt;
+
+ nt_register_t *mp_stat_rel_done;
+ nt_field_t *mp_stat_rel_done_cnt;
+
+ nt_register_t *mp_stat_rel_ignore;
+ nt_field_t *mp_stat_rel_ignore_cnt;
+
+ nt_register_t *mp_stat_aul_done;
+ nt_field_t *mp_stat_aul_done_cnt;
+
+ nt_register_t *mp_stat_aul_ignore;
+ nt_field_t *mp_stat_aul_ignore_cnt;
+
+ nt_register_t *mp_stat_aul_fail;
+ nt_field_t *mp_stat_aul_fail_cnt;
+
+ nt_register_t *mp_stat_tul_done;
+ nt_field_t *mp_stat_tul_done_cnt;
+
+ nt_register_t *mp_stat_flows;
+ nt_field_t *mp_stat_flows_cnt;
+
+ nt_register_t *mp_stat_sta_done;
+ nt_field_t *mp_stat_sta_done_cnt;
+
+ nt_register_t *mp_stat_inf_done;
+ nt_field_t *mp_stat_inf_done_cnt;
+
+ nt_register_t *mp_stat_inf_skip;
+ nt_field_t *mp_stat_inf_skip_cnt;
+
+ nt_register_t *mp_stat_pck_hit;
+ nt_field_t *mp_stat_pck_hit_cnt;
+
+ nt_register_t *mp_stat_pck_miss;
+ nt_field_t *mp_stat_pck_miss_cnt;
+
+ nt_register_t *mp_stat_pck_unh;
+ nt_field_t *mp_stat_pck_unh_cnt;
+
+ nt_register_t *mp_stat_pck_dis;
+ nt_field_t *mp_stat_pck_dis_cnt;
+
+ nt_register_t *mp_stat_csh_hit;
+ nt_field_t *mp_stat_csh_hit_cnt;
+
+ nt_register_t *mp_stat_csh_miss;
+ nt_field_t *mp_stat_csh_miss_cnt;
+
+ nt_register_t *mp_stat_csh_unh;
+ nt_field_t *mp_stat_csh_unh_cnt;
+
+ nt_register_t *mp_stat_cuc_start;
+ nt_field_t *mp_stat_cuc_start_cnt;
+
+ nt_register_t *mp_stat_cuc_move;
+ nt_field_t *mp_stat_cuc_move_cnt;
+};
+
+#endif /* __FLOW_NTHW_FLM_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c
new file mode 100644
index 0000000000..b7fe7c5863
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.c
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_hfu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void hfu_nthw_set_debug_mode(struct hfu_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_hfu, n_debug_mode);
+}
+
+struct hfu_nthw *hfu_nthw_new(void)
+{
+ struct hfu_nthw *p = malloc(sizeof(struct hfu_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void hfu_nthw_delete(struct hfu_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int hfu_nthw_init(struct hfu_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HFU, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Hfu %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_hfu = fpga_query_module(p_fpga, MOD_HFU, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_hfu, HFU_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HFU_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HFU_RCP_CTRL_CNT);
+
+ p->mp_rcp_data = module_get_register(p->m_hfu, HFU_RCP_DATA);
+ p->mp_rcp_data_len_a_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_WR);
+ p->mp_rcp_data_len_a_ol4len =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_OL4LEN);
+ p->mp_rcp_data_len_a_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_POS_DYN);
+ p->mp_rcp_data_len_a_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_POS_OFS);
+ p->mp_rcp_data_len_a_add_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_ADD_DYN);
+ p->mp_rcp_data_len_a_add_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_ADD_OFS);
+ p->mp_rcp_data_len_a_sub_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_A_SUB_DYN);
+ p->mp_rcp_data_len_b_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_WR);
+ p->mp_rcp_data_len_b_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_POS_DYN);
+ p->mp_rcp_data_len_b_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_POS_OFS);
+ p->mp_rcp_data_len_b_add_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_ADD_DYN);
+ p->mp_rcp_data_len_b_add_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_ADD_OFS);
+ p->mp_rcp_data_len_b_sub_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_B_SUB_DYN);
+ p->mp_rcp_data_len_c_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_WR);
+ p->mp_rcp_data_len_c_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_POS_DYN);
+ p->mp_rcp_data_len_c_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_POS_OFS);
+ p->mp_rcp_data_len_c_add_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_ADD_DYN);
+ p->mp_rcp_data_len_c_add_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_ADD_OFS);
+ p->mp_rcp_data_len_c_sub_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_LEN_C_SUB_DYN);
+ p->mp_rcp_data_ttl_wr =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_WR);
+ p->mp_rcp_data_ttl_pos_dyn =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_POS_DYN);
+ p->mp_rcp_data_ttl_pos_ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TTL_POS_OFS);
+ p->mp_rcp_data_csinf = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_CSINF);
+ p->mp_rcp_data_l3prt = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L3PRT);
+ p->mp_rcp_data_l3frag =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L3FRAG);
+ p->mp_rcp_data_tunnel =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_TUNNEL);
+ p->mp_rcp_data_l4prt = register_get_field(p->mp_rcp_data, HFU_RCP_DATA_L4PRT);
+ p->mp_rcp_data_ol3ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_OL3OFS);
+ p->mp_rcp_data_ol4ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_OL4OFS);
+ p->mp_rcp_data_il3ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_IL3OFS);
+ p->mp_rcp_data_il4ofs =
+ register_get_field(p->mp_rcp_data, HFU_RCP_DATA_IL4OFS);
+
+ return 0;
+}
+
+void hfu_nthw_rcp_select(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void hfu_nthw_rcp_cnt(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void hfu_nthw_rcp_len_a_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_wr, val);
+}
+
+void hfu_nthw_rcp_len_a_ol4len(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_ol4len, val);
+}
+
+void hfu_nthw_rcp_len_a_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_len_a_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_len_a_add_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_add_dyn, val);
+}
+
+void hfu_nthw_rcp_len_a_add_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_add_ofs, val);
+}
+
+void hfu_nthw_rcp_len_a_sub_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_a_sub_dyn, val);
+}
+
+void hfu_nthw_rcp_len_b_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_wr, val);
+}
+
+void hfu_nthw_rcp_len_b_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_len_b_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_len_b_add_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_add_dyn, val);
+}
+
+void hfu_nthw_rcp_len_b_add_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_add_ofs, val);
+}
+
+void hfu_nthw_rcp_len_b_sub_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_b_sub_dyn, val);
+}
+
+void hfu_nthw_rcp_len_c_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_wr, val);
+}
+
+void hfu_nthw_rcp_len_c_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_len_c_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_len_c_add_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_add_dyn, val);
+}
+
+void hfu_nthw_rcp_len_c_add_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_add_ofs, val);
+}
+
+void hfu_nthw_rcp_len_c_sub_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len_c_sub_dyn, val);
+}
+
+void hfu_nthw_rcp_ttl_wr(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ttl_wr, val);
+}
+
+void hfu_nthw_rcp_ttl_pos_dyn(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ttl_pos_dyn, val);
+}
+
+void hfu_nthw_rcp_ttl_pos_ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ttl_pos_ofs, val);
+}
+
+void hfu_nthw_rcp_csinf(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_csinf, val);
+}
+
+void hfu_nthw_rcp_l3prt(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_l3prt, val);
+}
+
+void hfu_nthw_rcp_l3frag(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_l3frag, val);
+}
+
+void hfu_nthw_rcp_tunnel(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tunnel, val);
+}
+
+void hfu_nthw_rcp_l4prt(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_l4prt, val);
+}
+
+void hfu_nthw_rcp_ol3ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ol3ofs, val);
+}
+
+void hfu_nthw_rcp_ol4ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ol4ofs, val);
+}
+
+void hfu_nthw_rcp_il3ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_il3ofs, val);
+}
+
+void hfu_nthw_rcp_il4ofs(const struct hfu_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_il4ofs, val);
+}
+
+void hfu_nthw_rcp_flush(const struct hfu_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h
new file mode 100644
index 0000000000..ecba1a8822
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hfu.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_HFU_H__
+#define __FLOW_NTHW_HFU_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct hfu_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_hfu;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_len_a_wr;
+ nt_field_t *mp_rcp_data_len_a_ol4len;
+ nt_field_t *mp_rcp_data_len_a_pos_dyn;
+ nt_field_t *mp_rcp_data_len_a_pos_ofs;
+ nt_field_t *mp_rcp_data_len_a_add_dyn;
+ nt_field_t *mp_rcp_data_len_a_add_ofs;
+ nt_field_t *mp_rcp_data_len_a_sub_dyn;
+ nt_field_t *mp_rcp_data_len_b_wr;
+ nt_field_t *mp_rcp_data_len_b_pos_dyn;
+ nt_field_t *mp_rcp_data_len_b_pos_ofs;
+ nt_field_t *mp_rcp_data_len_b_add_dyn;
+ nt_field_t *mp_rcp_data_len_b_add_ofs;
+ nt_field_t *mp_rcp_data_len_b_sub_dyn;
+ nt_field_t *mp_rcp_data_len_c_wr;
+ nt_field_t *mp_rcp_data_len_c_pos_dyn;
+ nt_field_t *mp_rcp_data_len_c_pos_ofs;
+ nt_field_t *mp_rcp_data_len_c_add_dyn;
+ nt_field_t *mp_rcp_data_len_c_add_ofs;
+ nt_field_t *mp_rcp_data_len_c_sub_dyn;
+ nt_field_t *mp_rcp_data_ttl_wr;
+ nt_field_t *mp_rcp_data_ttl_pos_dyn;
+ nt_field_t *mp_rcp_data_ttl_pos_ofs;
+ nt_field_t *mp_rcp_data_csinf;
+ nt_field_t *mp_rcp_data_l3prt;
+ nt_field_t *mp_rcp_data_l3frag;
+ nt_field_t *mp_rcp_data_tunnel;
+ nt_field_t *mp_rcp_data_l4prt;
+ nt_field_t *mp_rcp_data_ol3ofs;
+ nt_field_t *mp_rcp_data_ol4ofs;
+ nt_field_t *mp_rcp_data_il3ofs;
+ nt_field_t *mp_rcp_data_il4ofs;
+};
+
+struct hfu_nthw *hfu_nthw_new(void);
+void hfu_nthw_delete(struct hfu_nthw *p);
+int hfu_nthw_init(struct hfu_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int hfu_nthw_setup(struct hfu_nthw *p, int n_idx, int n_idx_cnt);
+void hfu_nthw_set_debug_mode(struct hfu_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void hfu_nthw_rcp_select(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_cnt(const struct hfu_nthw *p, uint32_t val);
+
+void hfu_nthw_rcp_len_a_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_ol4len(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_add_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_add_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_a_sub_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_add_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_add_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_b_sub_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_add_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_add_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_len_c_sub_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ttl_wr(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ttl_pos_dyn(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ttl_pos_ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_csinf(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_l3prt(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_l3frag(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_tunnel(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_l4prt(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ol3ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_ol4ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_il3ofs(const struct hfu_nthw *p, uint32_t val);
+void hfu_nthw_rcp_il4ofs(const struct hfu_nthw *p, uint32_t val);
+
+void hfu_nthw_rcp_flush(const struct hfu_nthw *p);
+
+#endif /* __FLOW_NTHW_HFU_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c
new file mode 100644
index 0000000000..0dc6434e88
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.c
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_hsh.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void hsh_nthw_set_debug_mode(struct hsh_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_hsh, n_debug_mode);
+}
+
+struct hsh_nthw *hsh_nthw_new(void)
+{
+ struct hsh_nthw *p = malloc(sizeof(struct hsh_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void hsh_nthw_delete(struct hsh_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int hsh_nthw_init(struct hsh_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HSH, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Hsh %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_hsh = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_hsh, HSH_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HSH_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HSH_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_hsh, HSH_RCP_DATA);
+ p->mp_rcp_data_load_dist_type =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_LOAD_DIST_TYPE);
+ p->mp_rcp_data_mac_port_mask =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_MAC_PORT_MASK);
+ p->mp_rcp_data_sort = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_SORT);
+ p->mp_rcp_data_qw0_pe =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW0_PE);
+ p->mp_rcp_data_qw0_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW0_OFS);
+ p->mp_rcp_data_qw4_pe =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW4_PE);
+ p->mp_rcp_data_qw4_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_QW4_OFS);
+ p->mp_rcp_data_w8_pe = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_PE);
+ p->mp_rcp_data_w8_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_OFS);
+ p->mp_rcp_data_w8_sort =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W8_SORT);
+ p->mp_rcp_data_w9_pe = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_PE);
+ p->mp_rcp_data_w9_ofs =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_OFS);
+ p->mp_rcp_data_w9_sort =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_SORT);
+ p->mp_rcp_data_w9_p = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_W9_P);
+ p->mp_rcp_data_p_mask =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_P_MASK);
+ p->mp_rcp_data_word_mask =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_WORD_MASK);
+ p->mp_rcp_data_seed = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_SEED);
+ p->mp_rcp_data_tnl_p = register_get_field(p->mp_rcp_data, HSH_RCP_DATA_TNL_P);
+ p->mp_rcp_data_hsh_valid =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_HSH_VALID);
+ p->mp_rcp_data_hsh_type =
+ register_get_field(p->mp_rcp_data, HSH_RCP_DATA_HSH_TYPE);
+ p->mp_rcp_data_auto_ipv4_mask =
+ register_query_field(p->mp_rcp_data, HSH_RCP_DATA_AUTO_IPV4_MASK);
+
+ /* Init */
+ uint32_t val[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ field_set_val32(p->mp_rcp_addr, 0);
+ field_set_val32(p->mp_rcp_cnt, 1);
+
+ field_set_val32(p->mp_rcp_data_load_dist_type, 0);
+ field_set_val(p->mp_rcp_data_mac_port_mask, val,
+ p->mp_rcp_data_mac_port_mask->mn_words);
+ field_set_val32(p->mp_rcp_data_sort, 0);
+ field_set_val32(p->mp_rcp_data_qw0_pe, 0);
+ field_set_val32(p->mp_rcp_data_qw0_ofs, 0);
+ field_set_val32(p->mp_rcp_data_qw4_pe, 0);
+ field_set_val32(p->mp_rcp_data_qw4_ofs, 0);
+ field_set_val32(p->mp_rcp_data_w8_pe, 0);
+ field_set_val32(p->mp_rcp_data_w8_ofs, 0);
+ field_set_val32(p->mp_rcp_data_w8_sort, 0);
+ field_set_val32(p->mp_rcp_data_w9_pe, 0);
+ field_set_val32(p->mp_rcp_data_w9_ofs, 0);
+ field_set_val32(p->mp_rcp_data_w9_sort, 0);
+ field_set_val32(p->mp_rcp_data_w9_p, 0);
+ field_set_val(p->mp_rcp_data_word_mask, val, 10);
+ field_set_val32(p->mp_rcp_data_seed, 0);
+ field_set_val32(p->mp_rcp_data_tnl_p, 0);
+ field_set_val32(p->mp_rcp_data_hsh_valid, 0);
+ field_set_val32(p->mp_rcp_data_hsh_type, 31);
+
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+
+ return 0;
+}
+
+void hsh_nthw_rcp_select(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void hsh_nthw_rcp_cnt(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void hsh_nthw_rcp_load_dist_type(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_load_dist_type, val);
+}
+
+void hsh_nthw_rcp_mac_port_mask(const struct hsh_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mac_port_mask, val,
+ p->mp_rcp_data_mac_port_mask->mn_words);
+}
+
+void hsh_nthw_rcp_sort(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sort, val);
+}
+
+void hsh_nthw_rcp_qw0_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_pe, val);
+}
+
+void hsh_nthw_rcp_qw0_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_ofs, val);
+}
+
+void hsh_nthw_rcp_qw4_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_pe, val);
+}
+
+void hsh_nthw_rcp_qw4_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_ofs, val);
+}
+
+void hsh_nthw_rcp_w8_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w8_pe, val);
+}
+
+void hsh_nthw_rcp_w8_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w8_ofs, val);
+}
+
+void hsh_nthw_rcp_w8_sort(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w8_sort, val);
+}
+
+void hsh_nthw_rcp_w9_pe(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_pe, val);
+}
+
+void hsh_nthw_rcp_w9_ofs(const struct hsh_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_ofs, val);
+}
+
+void hsh_nthw_rcp_w9_sort(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_sort, val);
+}
+
+void hsh_nthw_rcp_w9_p(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_w9_p, val);
+}
+
+void hsh_nthw_rcp_p_mask(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_p_mask, val);
+}
+
+void hsh_nthw_rcp_word_mask(const struct hsh_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_word_mask, val, 10);
+}
+
+void hsh_nthw_rcp_seed(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_seed, val);
+}
+
+void hsh_nthw_rcp_tnl_p(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tnl_p, val);
+}
+
+void hsh_nthw_rcp_hsh_valid(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_hsh_valid, val);
+}
+
+void hsh_nthw_rcp_hsh_type(const struct hsh_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_hsh_type, val);
+}
+
+void hsh_nthw_rcp_auto_ipv4_mask(const struct hsh_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_auto_ipv4_mask)
+ field_set_val32(p->mp_rcp_data_auto_ipv4_mask, val);
+}
+
+void hsh_nthw_rcp_flush(const struct hsh_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h
new file mode 100644
index 0000000000..7cb7dbb743
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hsh.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_HSH_H__
+#define __FLOW_NTHW_HSH_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct hsh_nthw;
+
+typedef struct hsh_nthw hsh_nthw_t;
+
+struct hsh_nthw *hsh_nthw_new(void);
+void hsh_nthw_delete(struct hsh_nthw *p);
+int hsh_nthw_init(struct hsh_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int hsh_nthw_setup(struct hsh_nthw *p, int n_idx, int n_idx_cnt);
+void hsh_nthw_set_debug_mode(struct hsh_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void hsh_nthw_rcp_select(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_cnt(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_load_dist_type(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_mac_port_mask(const struct hsh_nthw *p, uint32_t *val);
+void hsh_nthw_rcp_sort(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_qw0_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_qw0_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_qw4_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_qw4_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_w8_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w8_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_w8_sort(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w9_pe(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w9_ofs(const struct hsh_nthw *p, int32_t val);
+void hsh_nthw_rcp_w9_sort(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_w9_p(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_p_mask(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_word_mask(const struct hsh_nthw *p, uint32_t *val);
+void hsh_nthw_rcp_seed(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_tnl_p(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_hsh_valid(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_hsh_type(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_auto_ipv4_mask(const struct hsh_nthw *p, uint32_t val);
+void hsh_nthw_rcp_flush(const struct hsh_nthw *p);
+
+struct hsh_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_hsh;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_load_dist_type;
+ nt_field_t *mp_rcp_data_mac_port_mask;
+ nt_field_t *mp_rcp_data_sort;
+ nt_field_t *mp_rcp_data_qw0_pe;
+ nt_field_t *mp_rcp_data_qw0_ofs;
+ nt_field_t *mp_rcp_data_qw4_pe;
+ nt_field_t *mp_rcp_data_qw4_ofs;
+ nt_field_t *mp_rcp_data_w8_pe;
+ nt_field_t *mp_rcp_data_w8_ofs;
+ nt_field_t *mp_rcp_data_w8_sort;
+ nt_field_t *mp_rcp_data_w9_pe;
+ nt_field_t *mp_rcp_data_w9_ofs;
+ nt_field_t *mp_rcp_data_w9_sort;
+ nt_field_t *mp_rcp_data_w9_p;
+ nt_field_t *mp_rcp_data_p_mask;
+ nt_field_t *mp_rcp_data_word_mask;
+ nt_field_t *mp_rcp_data_seed;
+ nt_field_t *mp_rcp_data_tnl_p;
+ nt_field_t *mp_rcp_data_hsh_valid;
+ nt_field_t *mp_rcp_data_hsh_type;
+ nt_field_t *mp_rcp_data_auto_ipv4_mask;
+};
+
+#endif /* __FLOW_NTHW_HSH_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c
new file mode 100644
index 0000000000..fc3dc443a2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.c
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_hst.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void hst_nthw_set_debug_mode(struct hst_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_hst, n_debug_mode);
+}
+
+struct hst_nthw *hst_nthw_new(void)
+{
+ struct hst_nthw *p = malloc(sizeof(struct hst_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void hst_nthw_delete(struct hst_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int hst_nthw_init(struct hst_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_HST, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Hst %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_hst = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_hst, HST_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, HST_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, HST_RCP_CTRL_CNT);
+
+ p->mp_rcp_data = module_get_register(p->m_hst, HST_RCP_DATA);
+ p->mp_rcp_data_strip_mode =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_STRIP_MODE);
+ p->mp_rcp_data_start_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_START_DYN);
+ p->mp_rcp_data_start_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_START_OFS);
+ p->mp_rcp_data_end_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_END_DYN);
+ p->mp_rcp_data_end_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_END_OFS);
+ p->mp_rcp_data_modif0_cmd =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_CMD);
+ p->mp_rcp_data_modif0_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_DYN);
+ p->mp_rcp_data_modif0_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_OFS);
+ p->mp_rcp_data_modif0_value =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF0_VALUE);
+ p->mp_rcp_data_modif1_cmd =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_CMD);
+ p->mp_rcp_data_modif1_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_DYN);
+ p->mp_rcp_data_modif1_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_OFS);
+ p->mp_rcp_data_modif1_value =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF1_VALUE);
+ p->mp_rcp_data_modif2_cmd =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_CMD);
+ p->mp_rcp_data_modif2_dyn =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_DYN);
+ p->mp_rcp_data_modif2_ofs =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_OFS);
+ p->mp_rcp_data_modif2_value =
+ register_get_field(p->mp_rcp_data, HST_RCP_DATA_MODIF2_VALUE);
+
+ return 0;
+}
+
+/* RCP */
+void hst_nthw_rcp_select(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void hst_nthw_rcp_cnt(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void hst_nthw_rcp_strip_mode(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_strip_mode, val);
+}
+
+void hst_nthw_rcp_start_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_start_dyn, val);
+}
+
+void hst_nthw_rcp_start_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_start_ofs, val);
+}
+
+void hst_nthw_rcp_end_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_end_dyn, val);
+}
+
+void hst_nthw_rcp_end_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_end_ofs, val);
+}
+
+void hst_nthw_rcp_modif0_cmd(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_cmd, val);
+}
+
+void hst_nthw_rcp_modif0_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_dyn, val);
+}
+
+void hst_nthw_rcp_modif0_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_ofs, val);
+}
+
+void hst_nthw_rcp_modif0_value(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif0_value, val);
+}
+
+void hst_nthw_rcp_modif1_cmd(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_cmd, val);
+}
+
+void hst_nthw_rcp_modif1_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_dyn, val);
+}
+
+void hst_nthw_rcp_modif1_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_ofs, val);
+}
+
+void hst_nthw_rcp_modif1_value(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif1_value, val);
+}
+
+void hst_nthw_rcp_modif2_cmd(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_cmd, val);
+}
+
+void hst_nthw_rcp_modif2_dyn(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_dyn, val);
+}
+
+void hst_nthw_rcp_modif2_ofs(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_ofs, val);
+}
+
+void hst_nthw_rcp_modif2_value(const struct hst_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_modif2_value, val);
+}
+
+void hst_nthw_rcp_flush(const struct hst_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h
new file mode 100644
index 0000000000..5bc7eb6e55
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_hst.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_HST_H__
+#define __FLOW_NTHW_HST_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct hst_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_hst;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_strip_mode;
+ nt_field_t *mp_rcp_data_start_dyn;
+ nt_field_t *mp_rcp_data_start_ofs;
+ nt_field_t *mp_rcp_data_end_dyn;
+ nt_field_t *mp_rcp_data_end_ofs;
+ nt_field_t *mp_rcp_data_modif0_cmd;
+ nt_field_t *mp_rcp_data_modif0_dyn;
+ nt_field_t *mp_rcp_data_modif0_ofs;
+ nt_field_t *mp_rcp_data_modif0_value;
+ nt_field_t *mp_rcp_data_modif1_cmd;
+ nt_field_t *mp_rcp_data_modif1_dyn;
+ nt_field_t *mp_rcp_data_modif1_ofs;
+ nt_field_t *mp_rcp_data_modif1_value;
+ nt_field_t *mp_rcp_data_modif2_cmd;
+ nt_field_t *mp_rcp_data_modif2_dyn;
+ nt_field_t *mp_rcp_data_modif2_ofs;
+ nt_field_t *mp_rcp_data_modif2_value;
+};
+
+typedef struct hst_nthw hst_nthw_t;
+
+struct hst_nthw *hst_nthw_new(void);
+void hst_nthw_delete(struct hst_nthw *p);
+int hst_nthw_init(struct hst_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int hst_nthw_setup(struct hst_nthw *p, int n_idx, int n_idx_cnt);
+void hst_nthw_set_debug_mode(struct hst_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void hst_nthw_rcp_select(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_cnt(const struct hst_nthw *p, uint32_t val);
+
+void hst_nthw_rcp_strip_mode(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_start_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_start_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_end_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_end_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_cmd(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif0_value(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_cmd(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif1_value(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_cmd(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_dyn(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_ofs(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_modif2_value(const struct hst_nthw *p, uint32_t val);
+void hst_nthw_rcp_flush(const struct hst_nthw *p);
+
+#endif /* __FLOW_NTHW_HST_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c
new file mode 100644
index 0000000000..0f51a36e57
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.c
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_ifr.h"
+
+void ifr_nthw_set_debug_mode(struct ifr_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_ifr, n_debug_mode);
+}
+
+struct ifr_nthw *ifr_nthw_new(void)
+{
+ struct ifr_nthw *p = malloc(sizeof(struct ifr_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void ifr_nthw_delete(struct ifr_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int ifr_nthw_init(struct ifr_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_IFR, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Ifr %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_ifr = fpga_query_module(p_fpga, MOD_IFR, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_ifr, IFR_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, IFR_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, IFR_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_ifr, IFR_RCP_DATA);
+ p->mp_rcp_data_en = register_get_field(p->mp_rcp_data, IFR_RCP_DATA_EN);
+ p->mp_rcp_data_mtu = register_get_field(p->mp_rcp_data, IFR_RCP_DATA_MTU);
+
+ return 0;
+}
+
+void ifr_nthw_rcp_select(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_addr);
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void ifr_nthw_rcp_cnt(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_cnt);
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void ifr_nthw_rcp_en(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_data_en);
+ field_set_val32(p->mp_rcp_data_en, val);
+}
+
+void ifr_nthw_rcp_mtu(const struct ifr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_data_en);
+ field_set_val32(p->mp_rcp_data_mtu, val);
+}
+
+void ifr_nthw_rcp_flush(const struct ifr_nthw *p)
+{
+ assert(p->mp_rcp_ctrl);
+ assert(p->mp_rcp_data);
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h
new file mode 100644
index 0000000000..626ca3d193
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ifr.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_IFR_H__
+#define __FLOW_NTHW_IFR_H__
+
+#include "nthw_fpga_model.h"
+
+struct ifr_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_ifr;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_en;
+ nt_field_t *mp_rcp_data_mtu;
+};
+
+struct ifr_nthw *ifr_nthw_new(void);
+void ifr_nthw_delete(struct ifr_nthw *p);
+int ifr_nthw_init(struct ifr_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int ifr_nthw_setup(struct ifr_nthw *p, int n_idx, int n_idx_cnt);
+void ifr_nthw_set_debug_mode(struct ifr_nthw *p, unsigned int n_debug_mode);
+
+/* IFR */
+void ifr_nthw_rcp_select(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_cnt(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_en(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_mtu(const struct ifr_nthw *p, uint32_t val);
+void ifr_nthw_rcp_flush(const struct ifr_nthw *p);
+
+#endif /* __FLOW_NTHW_IFR_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c
new file mode 100644
index 0000000000..27b55e3b7c
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.c
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga_model.h"
+
+#include "flow_nthw_info.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+static inline unsigned int clamp_one(unsigned int val)
+{
+ return val > 1 ? 1 : val;
+}
+
+struct info_nthw *info_nthw_new(void)
+{
+ struct info_nthw *p = malloc(sizeof(struct info_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void info_nthw_delete(struct info_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int info_nthw_init(struct info_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ assert(n_instance >= 0 && n_instance < 256);
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+
+ unsigned int km_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_KM_PRESENT, 0));
+ unsigned int kcc_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_CAT_KCC_PRESENT, 0));
+ unsigned int ioa_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0));
+ unsigned int roa_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_ROA_PRESENT, 0));
+ unsigned int dbs_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0));
+ unsigned int flm_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_FLM_PRESENT, 0));
+ unsigned int hst_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_HST_PRESENT, 0));
+
+ /* Modules for Tx Packet Edit function */
+ unsigned int hfu_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_HFU_PRESENT, 0));
+ unsigned int tx_cpy_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_TX_CPY_PRESENT, 0));
+ unsigned int tx_ins_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_TX_INS_PRESENT, 0));
+ unsigned int tx_rpl_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_TX_RPL_PRESENT, 0));
+ unsigned int csu_present =
+ clamp_one(fpga_get_product_param(p_fpga, NT_CSU_PRESENT, 0));
+ unsigned int tpe_present = (hfu_present && tx_cpy_present && tx_ins_present &&
+ tx_rpl_present && csu_present) ?
+ 1 :
+ 0;
+
+ p->n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0);
+ p->n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, 0);
+ p->n_ltx_avail = fpga_get_product_param(p_fpga, NT_LR_PRESENT, 0);
+ p->nb_cat_func = fpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0);
+ p->nb_categories = fpga_get_product_param(p_fpga, NT_CATEGORIES, 0);
+ p->nb_queues = fpga_get_product_param(p_fpga, NT_QUEUES, 0);
+ p->nb_flow_types = fpga_get_product_param(p_fpga, NT_KM_FLOW_TYPES, 0) *
+ clamp_one(km_present + flm_present);
+ p->nb_pm_ext = fpga_get_product_param(p_fpga, NT_CAT_N_EXT, 0);
+ p->nb_len = fpga_get_product_param(p_fpga, NT_CAT_N_LEN, 0);
+ p->nb_kcc_size =
+ fpga_get_product_param(p_fpga, NT_CAT_KCC_SIZE, 0) * kcc_present;
+ p->nb_kcc_banks =
+ fpga_get_product_param(p_fpga, NT_CAT_KCC_BANKS, 0) * kcc_present;
+ p->nb_km_categories =
+ fpga_get_product_param(p_fpga, NT_KM_CATEGORIES, 0) * km_present;
+ p->nb_km_cam_banks =
+ fpga_get_product_param(p_fpga, NT_KM_CAM_BANKS, 0) * km_present;
+ p->nb_km_cam_record_words =
+ fpga_get_product_param(p_fpga, NT_KM_CAM_REC_WORDS, 0) * km_present;
+ p->nb_km_cam_records =
+ fpga_get_product_param(p_fpga, NT_KM_CAM_RECORDS, 0) * km_present;
+ p->nb_km_tcam_banks =
+ fpga_get_product_param(p_fpga, NT_KM_TCAM_BANKS, 0) * km_present;
+ p->nb_km_tcam_bank_width =
+ fpga_get_product_param(p_fpga, NT_KM_TCAM_BANK_WIDTH, 0) *
+ km_present;
+ p->nb_flm_categories =
+ fpga_get_product_param(p_fpga, NT_FLM_CATEGORIES, 0) * flm_present;
+ p->nb_flm_size_mb = fpga_get_product_param(p_fpga, NT_FLM_SIZE_MB, 0);
+ p->nb_flm_entry_size = fpga_get_product_param(p_fpga, NT_FLM_ENTRY_SIZE, 0);
+ p->nb_flm_variant = fpga_get_product_param(p_fpga, NT_FLM_VARIANT, 0);
+ p->nb_flm_prios =
+ fpga_get_product_param(p_fpga, NT_FLM_PRIOS, 0) * flm_present;
+ p->nb_flm_pst_profiles =
+ fpga_get_product_param(p_fpga, NT_FLM_PST_PROFILES, 0) *
+ flm_present;
+ p->nb_hst_categories =
+ fpga_get_product_param(p_fpga, NT_HST_CATEGORIES, 0) * hst_present;
+ p->nb_qsl_categories = fpga_get_product_param(p_fpga, NT_QSL_CATEGORIES, 0);
+ p->nb_qsl_qst_entries = fpga_get_product_param(p_fpga, NT_QSL_QST_SIZE, 0);
+ p->nb_pdb_categories = fpga_get_product_param(p_fpga, NT_PDB_CATEGORIES, 0);
+ p->nb_ioa_categories =
+ fpga_get_product_param(p_fpga, NT_IOA_CATEGORIES, 0) * ioa_present;
+ p->nb_roa_categories =
+ fpga_get_product_param(p_fpga, NT_ROA_CATEGORIES, 0) * roa_present;
+ p->nb_dbs_categories =
+ RTE_MIN(fpga_get_product_param(p_fpga, NT_DBS_RX_QUEUES, 0),
+ fpga_get_product_param(p_fpga, NT_DBS_TX_QUEUES, 0)) *
+ dbs_present;
+ p->nb_cat_km_if_cnt = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_CNT,
+ km_present + flm_present);
+ p->m_cat_km_if_m0 = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_M0, -1);
+ p->m_cat_km_if_m1 = fpga_get_product_param(p_fpga, NT_CAT_KM_IF_M1, -1);
+ p->nb_tpe_categories =
+ fpga_get_product_param(p_fpga, NT_TPE_CATEGORIES, 0) * tpe_present;
+ p->nb_tx_cpy_writers =
+ fpga_get_product_param(p_fpga, NT_TX_CPY_WRITERS, 0) * tpe_present;
+ p->nb_tx_cpy_mask_mem =
+ fpga_get_product_param(p_fpga, NT_CPY_MASK_MEM, 0) * tpe_present;
+ p->nb_tx_rpl_depth =
+ fpga_get_product_param(p_fpga, NT_TX_RPL_DEPTH, 0) * tpe_present;
+ p->nb_tx_rpl_ext_categories =
+ fpga_get_product_param(p_fpga, NT_TX_RPL_EXT_CATEGORIES, 0) *
+ tpe_present;
+ p->nb_tpe_ifr_categories =
+ fpga_get_product_param(p_fpga, NT_TX_MTU_PROFILE_IFR, 0);
+ return 0;
+}
+
+unsigned int info_nthw_get_nb_phy_ports(const struct info_nthw *p)
+{
+ return p->n_phy_ports;
+}
+
+unsigned int info_nthw_get_nb_rx_ports(const struct info_nthw *p)
+{
+ return p->n_rx_ports;
+}
+
+unsigned int info_nthw_get_ltx_avail(const struct info_nthw *p)
+{
+ return p->n_ltx_avail;
+}
+
+unsigned int info_nthw_get_nb_categories(const struct info_nthw *p)
+{
+ return p->nb_categories;
+}
+
+unsigned int info_nthw_get_kcc_size(const struct info_nthw *p)
+{
+ return p->nb_kcc_size;
+}
+
+unsigned int info_nthw_get_kcc_banks(const struct info_nthw *p)
+{
+ return p->nb_kcc_banks;
+}
+
+unsigned int info_nthw_get_nb_queues(const struct info_nthw *p)
+{
+ return p->nb_queues;
+}
+
+unsigned int info_nthw_get_nb_cat_funcs(const struct info_nthw *p)
+{
+ return p->nb_cat_func;
+}
+
+unsigned int info_nthw_get_nb_km_flow_types(const struct info_nthw *p)
+{
+ return p->nb_flow_types;
+}
+
+unsigned int info_nthw_get_nb_pm_ext(const struct info_nthw *p)
+{
+ return p->nb_pm_ext;
+}
+
+unsigned int info_nthw_get_nb_len(const struct info_nthw *p)
+{
+ return p->nb_len;
+}
+
+unsigned int info_nthw_get_nb_km_categories(const struct info_nthw *p)
+{
+ return p->nb_km_categories;
+}
+
+unsigned int info_nthw_get_nb_km_cam_banks(const struct info_nthw *p)
+{
+ return p->nb_km_cam_banks;
+}
+
+unsigned int info_nthw_get_nb_km_cam_record_words(const struct info_nthw *p)
+{
+ return p->nb_km_cam_record_words;
+}
+
+unsigned int info_nthw_get_nb_km_cam_records(const struct info_nthw *p)
+{
+ return p->nb_km_cam_records;
+}
+
+unsigned int info_nthw_get_nb_km_tcam_banks(const struct info_nthw *p)
+{
+ return p->nb_km_tcam_banks;
+}
+
+unsigned int info_nthw_get_nb_km_tcam_bank_width(const struct info_nthw *p)
+{
+ return p->nb_km_tcam_bank_width;
+}
+
+unsigned int info_nthw_get_nb_flm_categories(const struct info_nthw *p)
+{
+ return p->nb_flm_categories;
+}
+
+unsigned int info_nthw_get_nb_flm_size_mb(const struct info_nthw *p)
+{
+ return p->nb_flm_size_mb;
+}
+
+unsigned int info_nthw_get_nb_flm_entry_size(const struct info_nthw *p)
+{
+ return p->nb_flm_entry_size;
+}
+
+unsigned int info_nthw_get_nb_flm_variant(const struct info_nthw *p)
+{
+ return p->nb_flm_variant;
+}
+
+unsigned int info_nthw_get_nb_flm_prios(const struct info_nthw *p)
+{
+ return p->nb_flm_prios;
+}
+
+unsigned int info_nthw_get_nb_flm_pst_profiles(const struct info_nthw *p)
+{
+ return p->nb_flm_pst_profiles;
+}
+
+unsigned int info_nthw_get_nb_hst_categories(const struct info_nthw *p)
+{
+ return p->nb_hst_categories;
+}
+
+unsigned int info_nthw_get_nb_qsl_categories(const struct info_nthw *p)
+{
+ return p->nb_qsl_categories;
+}
+
+unsigned int info_nthw_get_nb_qsl_qst_entries(const struct info_nthw *p)
+{
+ return p->nb_qsl_qst_entries;
+}
+
+unsigned int info_nthw_get_nb_pdb_categories(const struct info_nthw *p)
+{
+ return p->nb_pdb_categories;
+}
+
+unsigned int info_nthw_get_nb_ioa_categories(const struct info_nthw *p)
+{
+ return p->nb_ioa_categories;
+}
+
+unsigned int info_nthw_get_nb_roa_categories(const struct info_nthw *p)
+{
+ return p->nb_roa_categories;
+}
+
+unsigned int info_nthw_get_nb_dbs_categories(const struct info_nthw *p)
+{
+ return p->nb_dbs_categories;
+}
+
+unsigned int info_nthw_get_nb_cat_km_if_cnt(const struct info_nthw *p)
+{
+ return p->nb_cat_km_if_cnt;
+}
+
+unsigned int info_nthw_get_nb_cat_km_if_m0(const struct info_nthw *p)
+{
+ return p->m_cat_km_if_m0;
+}
+
+unsigned int info_nthw_get_nb_cat_km_if_m1(const struct info_nthw *p)
+{
+ return p->m_cat_km_if_m1;
+}
+
+unsigned int info_nthw_get_nb_tpe_categories(const struct info_nthw *p)
+{
+ return p->nb_tpe_categories;
+}
+
+unsigned int info_nthw_get_nb_tx_cpy_writers(const struct info_nthw *p)
+{
+ return p->nb_tx_cpy_writers;
+}
+
+unsigned int info_nthw_get_nb_tx_cpy_mask_mem(const struct info_nthw *p)
+{
+ return p->nb_tx_cpy_mask_mem;
+}
+
+unsigned int info_nthw_get_nb_tx_rpl_depth(const struct info_nthw *p)
+{
+ return p->nb_tx_rpl_depth;
+}
+
+unsigned int info_nthw_get_nb_tx_rpl_ext_categories(const struct info_nthw *p)
+{
+ return p->nb_tx_rpl_ext_categories;
+}
+
+unsigned int info_nthw_get_nb_tpe_ifr_categories(const struct info_nthw *p)
+{
+ return p->nb_tpe_ifr_categories;
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h
new file mode 100644
index 0000000000..c697ba84e9
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_info.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_INFO_H__
+#define __FLOW_NTHW_INFO_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct info_nthw;
+
+struct info_nthw *info_nthw_new(void);
+void info_nthw_delete(struct info_nthw *p);
+int info_nthw_init(struct info_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int info_nthw_setup(struct info_nthw *p, int n_idx, int n_idx_cnt);
+
+unsigned int info_nthw_get_nb_phy_ports(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_rx_ports(const struct info_nthw *p);
+unsigned int info_nthw_get_ltx_avail(const struct info_nthw *p);
+
+unsigned int info_nthw_get_nb_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_queues(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_funcs(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_flow_types(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_pm_ext(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_len(const struct info_nthw *p);
+unsigned int info_nthw_get_kcc_size(const struct info_nthw *p);
+unsigned int info_nthw_get_kcc_banks(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_cam_banks(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_cam_record_words(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_cam_records(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_tcam_banks(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_km_tcam_bank_width(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_size_mb(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_entry_size(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_variant(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_prios(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_flm_pst_profiles(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_hst_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_qsl_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_qsl_qst_entries(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_pdb_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_ioa_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_roa_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_dbs_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_km_if_cnt(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_km_if_m0(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_cat_km_if_m1(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tpe_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_cpy_writers(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_cpy_mask_mem(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_rpl_depth(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tx_rpl_ext_categories(const struct info_nthw *p);
+unsigned int info_nthw_get_nb_tpe_ifr_categories(const struct info_nthw *p);
+
+struct info_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+ unsigned int n_phy_ports;
+ unsigned int n_rx_ports;
+ unsigned int n_ltx_avail;
+ unsigned int nb_cat_func;
+ unsigned int nb_categories;
+ unsigned int nb_queues;
+ unsigned int nb_flow_types;
+ unsigned int nb_pm_ext;
+ unsigned int nb_len;
+ unsigned int nb_kcc_size;
+ unsigned int nb_kcc_banks;
+ unsigned int nb_km_categories;
+ unsigned int nb_km_cam_banks;
+ unsigned int nb_km_cam_record_words;
+ unsigned int nb_km_cam_records;
+ unsigned int nb_km_tcam_banks;
+ unsigned int nb_km_tcam_bank_width;
+ unsigned int nb_flm_categories;
+ unsigned int nb_flm_size_mb;
+ unsigned int nb_flm_entry_size;
+ unsigned int nb_flm_variant;
+ unsigned int nb_flm_prios;
+ unsigned int nb_flm_pst_profiles;
+ unsigned int nb_hst_categories;
+ unsigned int nb_qsl_categories;
+ unsigned int nb_qsl_qst_entries;
+ unsigned int nb_pdb_categories;
+ unsigned int nb_ioa_categories;
+ unsigned int nb_roa_categories;
+ unsigned int nb_dbs_categories;
+ unsigned int nb_cat_km_if_cnt;
+ unsigned int m_cat_km_if_m0;
+ unsigned int m_cat_km_if_m1;
+ unsigned int nb_tpe_categories;
+ unsigned int nb_tx_cpy_writers;
+ unsigned int nb_tx_cpy_mask_mem;
+ unsigned int nb_tx_rpl_depth;
+ unsigned int nb_tx_rpl_ext_categories;
+ unsigned int nb_tpe_ifr_categories;
+};
+
+#endif /* __FLOW_NTHW_INFO_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c
new file mode 100644
index 0000000000..a83d443f6f
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.c
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_ioa.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void ioa_nthw_set_debug_mode(struct ioa_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_ioa, n_debug_mode);
+}
+
+struct ioa_nthw *ioa_nthw_new(void)
+{
+ struct ioa_nthw *p = malloc(sizeof(struct ioa_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void ioa_nthw_delete(struct ioa_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int ioa_nthw_init(struct ioa_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_IOA, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Ioa %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_ioa = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_ioa, IOA_RECIPE_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, IOA_RECIPE_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, IOA_RECIPE_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_ioa, IOA_RECIPE_DATA);
+ p->mp_rcp_data_tunnel_pop =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_TUNNEL_POP);
+ p->mp_rcp_data_vlan_pop =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_POP);
+ p->mp_rcp_data_vlan_push =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_PUSH);
+ p->mp_rcp_data_vlan_vid =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_VID);
+ p->mp_rcp_data_vlan_dei =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_DEI);
+ p->mp_rcp_data_vlan_pcp =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_PCP);
+ p->mp_rcp_data_vlan_tpid_sel =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_VLAN_TPID_SEL);
+ p->mp_rcp_data_queue_override_en =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_QUEUE_OVERRIDE_EN);
+ p->mp_rcp_data_queue_id =
+ register_get_field(p->mp_rcp_data, IOA_RECIPE_DATA_QUEUE_ID);
+
+ /* Special Vlan Tpid */
+ p->mp_special = module_get_register(p->m_ioa, IOA_VLAN_TPID_SPECIAL);
+ p->mp_special_vlan_tpid_cust_tpid0 =
+ register_get_field(p->mp_special, IOA_VLAN_TPID_SPECIAL_CUSTTPID0);
+ p->mp_special_vlan_tpid_cust_tpid1 =
+ register_get_field(p->mp_special, IOA_VLAN_TPID_SPECIAL_CUSTTPID1);
+ {
+ /*
+ * This extension in IOA is a messy way FPGA have chosen to
+ * put control bits for EPP module in IOA. It is accepted as
+ * we are going towards exchange IOA and ROA modules later
+ * to get higher scalability in future.
+ */
+ p->mp_roa_epp_ctrl =
+ module_query_register(p->m_ioa, IOA_ROA_EPP_CTRL);
+ if (p->mp_roa_epp_ctrl) {
+ p->mp_roa_epp_addr =
+ register_get_field(p->mp_roa_epp_ctrl,
+ IOA_ROA_EPP_CTRL_ADR);
+ p->mp_roa_epp_cnt =
+ register_get_field(p->mp_roa_epp_ctrl,
+ IOA_ROA_EPP_CTRL_CNT);
+ } else {
+ p->mp_roa_epp_addr = NULL;
+ p->mp_roa_epp_cnt = NULL;
+ }
+
+ p->mp_roa_epp_data =
+ module_query_register(p->m_ioa, IOA_ROA_EPP_DATA);
+ if (p->mp_roa_epp_data) {
+ p->mp_roa_epp_data_push_tunnel =
+ register_get_field(p->mp_roa_epp_data,
+ IOA_ROA_EPP_DATA_PUSH_TUNNEL);
+ p->mp_roa_epp_data_tx_port =
+ register_get_field(p->mp_roa_epp_data,
+ IOA_ROA_EPP_DATA_TX_PORT);
+ } else {
+ p->mp_roa_epp_data_push_tunnel = NULL;
+ p->mp_roa_epp_data_tx_port = NULL;
+ }
+ }
+ return 0;
+}
+
+/* RCP */
+void ioa_nthw_rcp_select(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void ioa_nthw_rcp_cnt(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void ioa_nthw_rcp_tunnel_pop(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tunnel_pop, val);
+}
+
+void ioa_nthw_rcp_vlan_pop(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_pop, val);
+}
+
+void ioa_nthw_rcp_vlan_push(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_push, val);
+}
+
+void ioa_nthw_rcp_vlan_vid(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_vid, val);
+}
+
+void ioa_nthw_rcp_vlan_dei(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_dei, val);
+}
+
+void ioa_nthw_rcp_vlan_pcp(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_pcp, val);
+}
+
+void ioa_nthw_rcp_vlan_tpid_sel(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_vlan_tpid_sel, val);
+}
+
+void ioa_nthw_rcp_queue_override_en(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_queue_override_en, val);
+}
+
+void ioa_nthw_rcp_queue_id(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_queue_id, val);
+}
+
+void ioa_nthw_rcp_flush(const struct ioa_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+/* Vlan Tpid Special */
+void ioa_nthw_special_vlan_tpid_cust_tpid0(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_special_vlan_tpid_cust_tpid0, val);
+}
+
+void ioa_nthw_special_vlan_tpid_cust_tpid1(const struct ioa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_special_vlan_tpid_cust_tpid1, val);
+}
+
+void ioa_nthw_special_vlan_tpid_flush(const struct ioa_nthw *p)
+{
+ register_flush(p->mp_special, 1);
+}
+
+void ioa_nthw_roa_epp_select(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_addr)
+ field_set_val32(p->mp_roa_epp_addr, val);
+}
+
+void ioa_nthw_roa_epp_cnt(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_cnt)
+ field_set_val32(p->mp_roa_epp_cnt, val);
+}
+
+void ioa_nthw_roa_epp_push_tunnel(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_data_push_tunnel)
+ field_set_val32(p->mp_roa_epp_data_push_tunnel, val);
+}
+
+void ioa_nthw_roa_epp_tx_port(const struct ioa_nthw *p, uint32_t val)
+{
+ if (p->mp_roa_epp_data_tx_port)
+ field_set_val32(p->mp_roa_epp_data_tx_port, val);
+}
+
+void ioa_nthw_roa_epp_flush(const struct ioa_nthw *p)
+{
+ if (p->mp_roa_epp_ctrl)
+ register_flush(p->mp_roa_epp_ctrl, 1);
+ if (p->mp_roa_epp_data)
+ register_flush(p->mp_roa_epp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h
new file mode 100644
index 0000000000..8ab30d2d28
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_ioa.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_IOA_H__
+#define __FLOW_NTHW_IOA_H__
+
+#include "nthw_fpga_model.h"
+
+#include <stdint.h> /* uint32_t */
+
+struct ioa_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_ioa;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+
+ nt_field_t *mp_rcp_data_tunnel_pop;
+ nt_field_t *mp_rcp_data_vlan_pop;
+ nt_field_t *mp_rcp_data_vlan_push;
+ nt_field_t *mp_rcp_data_vlan_vid;
+ nt_field_t *mp_rcp_data_vlan_dei;
+ nt_field_t *mp_rcp_data_vlan_pcp;
+ nt_field_t *mp_rcp_data_vlan_tpid_sel;
+ nt_field_t *mp_rcp_data_queue_override_en;
+ nt_field_t *mp_rcp_data_queue_id;
+
+ nt_register_t *mp_special;
+ nt_field_t *mp_special_vlan_tpid_cust_tpid0;
+ nt_field_t *mp_special_vlan_tpid_cust_tpid1;
+
+ nt_register_t *mp_roa_epp_ctrl;
+ nt_field_t *mp_roa_epp_addr;
+ nt_field_t *mp_roa_epp_cnt;
+ nt_register_t *mp_roa_epp_data;
+ nt_field_t *mp_roa_epp_data_push_tunnel;
+ nt_field_t *mp_roa_epp_data_tx_port;
+};
+
+typedef struct ioa_nthw ioa_nthw_t;
+
+struct ioa_nthw *ioa_nthw_new(void);
+void ioa_nthw_delete(struct ioa_nthw *p);
+int ioa_nthw_init(struct ioa_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int ioa_nthw_setup(struct ioa_nthw *p, int n_idx, int n_idx_cnt);
+void ioa_nthw_set_debug_mode(struct ioa_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void ioa_nthw_rcp_select(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_cnt(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_tunnel_pop(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_pop(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_push(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_vid(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_dei(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_pcp(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_vlan_tpid_sel(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_queue_override_en(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_queue_id(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_rcp_flush(const struct ioa_nthw *p);
+
+/* Vlan Tpid Special */
+void ioa_nthw_special_vlan_tpid_cust_tpid0(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_special_vlan_tpid_cust_tpid1(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_special_vlan_tpid_flush(const struct ioa_nthw *p);
+
+/* EPP module */
+void ioa_nthw_roa_epp_select(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_cnt(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_push_tunnel(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_tx_port(const struct ioa_nthw *p, uint32_t val);
+void ioa_nthw_roa_epp_flush(const struct ioa_nthw *p);
+
+#endif /* __FLOW_NTHW_IOA_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c
new file mode 100644
index 0000000000..af54e14940
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.c
@@ -0,0 +1,685 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_km.h"
+
+#include <stdint.h>
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+#define CHECK_AND_SET_VALUE(_a, val) \
+ do { \
+ __typeof__(_a) (a) = (_a); \
+ if (a) { \
+ field_set_val32(a, val); \
+ } \
+ } while (0)
+
+void km_nthw_set_debug_mode(struct km_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_km, n_debug_mode);
+}
+
+struct km_nthw *km_nthw_new(void)
+{
+ struct km_nthw *p = malloc(sizeof(struct km_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void km_nthw_delete(struct km_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int km_nthw_init(struct km_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_KM, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Km %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_km = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_km, KM_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, KM_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, KM_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_km, KM_RCP_DATA);
+ p->mp_rcp_data_qw0_dyn =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_DYN);
+ p->mp_rcp_data_qw0_ofs =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_OFS);
+ p->mp_rcp_data_qw0_sel_a =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_SEL_A);
+ p->mp_rcp_data_qw0_sel_b =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW0_SEL_B);
+ p->mp_rcp_data_qw4_dyn =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_DYN);
+ p->mp_rcp_data_qw4_ofs =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_OFS);
+ p->mp_rcp_data_qw4_sel_a =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_SEL_A);
+ p->mp_rcp_data_qw4_sel_b =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_QW4_SEL_B);
+
+ p->mp_rcp_data_sw8_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_DYN);
+ p->mp_rcp_data_dw8_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_DYN);
+
+ p->mp_rcp_data_swx_ovs_sb =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SWX_OVS_SB);
+ p->mp_rcp_data_swx_cch =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SWX_CCH);
+ p->mp_rcp_data_swx_sel_a =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_SWX_SEL_A);
+ p->mp_rcp_data_swx_sel_b =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_SWX_SEL_B);
+ p->mp_rcp_data_mask_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_MASK_A);
+ p->mp_rcp_data_mask_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_MASK_B);
+ p->mp_rcp_data_dual = register_get_field(p->mp_rcp_data, KM_RCP_DATA_DUAL);
+ p->mp_rcp_data_paired =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_PAIRED);
+ p->mp_rcp_data_el_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_EL_A);
+ p->mp_rcp_data_el_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_EL_B);
+ p->mp_rcp_data_info_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_INFO_A);
+ p->mp_rcp_data_info_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_INFO_B);
+ p->mp_rcp_data_ftm_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_FTM_A);
+ p->mp_rcp_data_ftm_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_FTM_B);
+ p->mp_rcp_data_bank_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_BANK_A);
+ p->mp_rcp_data_bank_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_BANK_B);
+ p->mp_rcp_data_kl_a = register_get_field(p->mp_rcp_data, KM_RCP_DATA_KL_A);
+ p->mp_rcp_data_kl_b = register_get_field(p->mp_rcp_data, KM_RCP_DATA_KL_B);
+ p->mp_rcp_data_flow_set =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_FLOW_SET);
+ p->mp_rcp_data_keyway_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_KEYWAY_A);
+ p->mp_rcp_data_keyway_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_KEYWAY_B);
+ p->mp_rcp_data_synergy_mode =
+ register_get_field(p->mp_rcp_data, KM_RCP_DATA_SYNERGY_MODE);
+
+ /* CAM */
+ p->mp_cam_ctrl = module_get_register(p->m_km, KM_CAM_CTRL);
+ p->mp_cam_addr = register_get_field(p->mp_cam_ctrl, KM_CAM_CTRL_ADR);
+ p->mp_cam_cnt = register_get_field(p->mp_cam_ctrl, KM_CAM_CTRL_CNT);
+ p->mp_cam_data = module_get_register(p->m_km, KM_CAM_DATA);
+ p->mp_cam_data_w0 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W0);
+ p->mp_cam_data_w1 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W1);
+ p->mp_cam_data_w2 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W2);
+ p->mp_cam_data_w3 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W3);
+ p->mp_cam_data_w4 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W4);
+ p->mp_cam_data_w5 = register_get_field(p->mp_cam_data, KM_CAM_DATA_W5);
+ p->mp_cam_data_ft0 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT0);
+ p->mp_cam_data_ft1 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT1);
+ p->mp_cam_data_ft2 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT2);
+ p->mp_cam_data_ft3 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT3);
+ p->mp_cam_data_ft4 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT4);
+ p->mp_cam_data_ft5 = register_get_field(p->mp_cam_data, KM_CAM_DATA_FT5);
+ /* TCAM */
+ p->mp_tcam_ctrl = module_get_register(p->m_km, KM_TCAM_CTRL);
+ p->mp_tcam_addr = register_get_field(p->mp_tcam_ctrl, KM_TCAM_CTRL_ADR);
+ p->mp_tcam_cnt = register_get_field(p->mp_tcam_ctrl, KM_TCAM_CTRL_CNT);
+ p->mp_tcam_data = module_get_register(p->m_km, KM_TCAM_DATA);
+ p->mp_tcam_data_t = register_get_field(p->mp_tcam_data, KM_TCAM_DATA_T);
+ /* TCI */
+ p->mp_tci_ctrl = module_get_register(p->m_km, KM_TCI_CTRL);
+ p->mp_tci_addr = register_get_field(p->mp_tci_ctrl, KM_TCI_CTRL_ADR);
+ p->mp_tci_cnt = register_get_field(p->mp_tci_ctrl, KM_TCI_CTRL_CNT);
+ p->mp_tci_data = module_get_register(p->m_km, KM_TCI_DATA);
+ p->mp_tci_data_color = register_get_field(p->mp_tci_data, KM_TCI_DATA_COLOR);
+ p->mp_tci_data_ft = register_get_field(p->mp_tci_data, KM_TCI_DATA_FT);
+ /* TCQ */
+ p->mp_tcq_ctrl = module_get_register(p->m_km, KM_TCQ_CTRL);
+ p->mp_tcq_addr = register_get_field(p->mp_tcq_ctrl, KM_TCQ_CTRL_ADR);
+ p->mp_tcq_cnt = register_get_field(p->mp_tcq_ctrl, KM_TCQ_CTRL_CNT);
+ p->mp_tcq_data = module_get_register(p->m_km, KM_TCQ_DATA);
+ p->mp_tcq_data_bank_mask =
+ register_query_field(p->mp_tcq_data, KM_TCQ_DATA_BANK_MASK);
+ p->mp_tcq_data_qual = register_get_field(p->mp_tcq_data, KM_TCQ_DATA_QUAL);
+
+ p->mp_rcp_data_dw0_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW0_B_DYN);
+ p->mp_rcp_data_dw0_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW0_B_OFS);
+ p->mp_rcp_data_dw2_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW2_B_DYN);
+ p->mp_rcp_data_dw2_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW2_B_OFS);
+ p->mp_rcp_data_sw4_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW4_B_DYN);
+ p->mp_rcp_data_sw4_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW4_B_OFS);
+ p->mp_rcp_data_sw5_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW5_B_DYN);
+ p->mp_rcp_data_sw5_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW5_B_OFS);
+ if (!p->mp_rcp_data_dw0_b_dyn) {
+ /* old field defines */
+ p->mp_rcp_data_dw0_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW0_B_DYN);
+ p->mp_rcp_data_dw0_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW0_B_OFS);
+ p->mp_rcp_data_dw2_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW4_B_DYN);
+ p->mp_rcp_data_dw2_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_QW4_B_OFS);
+ p->mp_rcp_data_sw4_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_B_DYN);
+ p->mp_rcp_data_sw4_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_B_OFS);
+ p->mp_rcp_data_sw5_b_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_B_DYN);
+ p->mp_rcp_data_sw5_b_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_B_OFS);
+ }
+
+ /* v0.6+ */
+ if (p->mp_rcp_data_dw8_dyn) {
+ p->mp_rcp_data_dw8_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_OFS);
+ p->mp_rcp_data_dw8_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_SEL_A);
+ p->mp_rcp_data_dw8_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW8_SEL_B);
+ p->mp_rcp_data_dw10_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_DYN);
+ p->mp_rcp_data_dw10_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_OFS);
+ p->mp_rcp_data_dw10_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_SEL_A);
+ p->mp_rcp_data_dw10_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_DW10_SEL_B);
+ } else if (p->mp_rcp_data_sw8_dyn) {
+ p->mp_rcp_data_sw8_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_OFS);
+ p->mp_rcp_data_sw8_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_SEL_A);
+ p->mp_rcp_data_sw8_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW8_SEL_B);
+ p->mp_rcp_data_sw9_dyn =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_DYN);
+ p->mp_rcp_data_sw9_ofs =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_OFS);
+ p->mp_rcp_data_sw9_sel_a =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_SEL_A);
+ p->mp_rcp_data_sw9_sel_b =
+ register_query_field(p->mp_rcp_data, KM_RCP_DATA_SW9_SEL_B);
+ }
+
+ return 0;
+}
+
+/* RCP */
+void km_nthw_rcp_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+};
+
+void km_nthw_rcp_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+};
+
+void km_nthw_rcp_qw0_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_dyn, val);
+};
+
+void km_nthw_rcp_qw0_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_ofs, val);
+};
+
+void km_nthw_rcp_qw0_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_sel_a, val);
+};
+
+void km_nthw_rcp_qw0_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw0_sel_b, val);
+};
+
+void km_nthw_rcp_qw4_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_dyn, val);
+};
+
+void km_nthw_rcp_qw4_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_ofs, val);
+};
+
+void km_nthw_rcp_qw4_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_sel_a, val);
+};
+
+void km_nthw_rcp_qw4_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_qw4_sel_b, val);
+};
+
+void km_nthw_rcp_dw8_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_dyn, val);
+};
+
+void km_nthw_rcp_sw8_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_dyn, val);
+};
+
+void km_nthw_rcp_sw8_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_ofs, val);
+};
+
+void km_nthw_rcp_sw8_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_sel_a, val);
+};
+
+void km_nthw_rcp_sw8_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw8_sel_b, val);
+};
+
+void km_nthw_rcp_sw9_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_dyn, val);
+};
+
+void km_nthw_rcp_sw9_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_ofs, val);
+};
+
+void km_nthw_rcp_sw9_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_sel_a, val);
+};
+
+void km_nthw_rcp_sw9_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_sw9_sel_b, val);
+};
+
+void km_nthw_rcp_swx_ovs_sb(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_swx_ovs_sb, val);
+};
+
+void km_nthw_rcp_swx_cch(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_swx_cch, val);
+};
+
+void km_nthw_rcp_dw8_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_ofs, val);
+};
+
+void km_nthw_rcp_dw8_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_sel_a, val);
+};
+
+void km_nthw_rcp_dw8_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw8_sel_b, val);
+};
+
+void km_nthw_rcp_dw10_dyn(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_dyn, val);
+};
+
+void km_nthw_rcp_dw10_ofs(const struct km_nthw *p, int32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_ofs, val);
+};
+
+void km_nthw_rcp_dw10_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_sel_a, val);
+};
+
+void km_nthw_rcp_dw10_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_dw10_sel_b, val);
+};
+
+void km_nthw_rcp_swx_sel_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_swx_sel_a, val);
+};
+
+void km_nthw_rcp_swx_sel_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_swx_sel_b, val);
+};
+
+void km_nthw_rcp_mask_a(const struct km_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask_a, val, p->mp_rcp_data_mask_a->mn_words);
+};
+
+void km_nthw_rcp_mask_b(const struct km_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask_b, val, p->mp_rcp_data_mask_b->mn_words);
+};
+
+void km_nthw_rcp_mask_d_a(const struct km_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rcp_data_mask_a, val, p->mp_rcp_data_mask_a->mn_words);
+}; /* for DW8/DW10 from v6+ */
+
+void km_nthw_rcp_dual(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dual, val);
+};
+
+void km_nthw_rcp_paired(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_paired, val);
+};
+
+void km_nthw_rcp_el_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_el_a, val);
+};
+
+void km_nthw_rcp_el_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_el_b, val);
+};
+
+void km_nthw_rcp_info_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_info_a, val);
+};
+
+void km_nthw_rcp_info_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_info_b, val);
+};
+
+void km_nthw_rcp_ftm_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ftm_a, val);
+};
+
+void km_nthw_rcp_ftm_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ftm_b, val);
+};
+
+void km_nthw_rcp_bank_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_bank_a, val);
+};
+
+void km_nthw_rcp_bank_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_bank_b, val);
+};
+
+void km_nthw_rcp_kl_a(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_kl_a, val);
+};
+
+void km_nthw_rcp_kl_b(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_kl_b, val);
+};
+
+void km_nthw_rcp_flow_set(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_flow_set, val);
+};
+
+void km_nthw_rcp_keyway_a(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_keyway_a, val);
+};
+
+void km_nthw_rcp_keyway_b(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_rcp_data_keyway_b, val);
+};
+
+void km_nthw_rcp_synergy_mode(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_synergy_mode, val);
+};
+
+void km_nthw_rcp_dw0_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw0_b_dyn, val);
+};
+
+void km_nthw_rcp_dw0_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw0_b_ofs, val);
+};
+
+void km_nthw_rcp_dw2_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw2_b_dyn, val);
+};
+
+void km_nthw_rcp_dw2_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dw2_b_ofs, val);
+};
+
+void km_nthw_rcp_sw4_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw4_b_dyn, val);
+};
+
+void km_nthw_rcp_sw4_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw4_b_ofs, val);
+};
+
+void km_nthw_rcp_sw5_b_dyn(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw5_b_dyn, val);
+};
+
+void km_nthw_rcp_sw5_b_ofs(const struct km_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_sw5_b_ofs, val);
+};
+
+void km_nthw_rcp_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+};
+
+/* CAM */
+void km_nthw_cam_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_addr, val);
+};
+
+void km_nthw_cam_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_cnt, val);
+};
+
+void km_nthw_cam_w0(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w0, val);
+};
+
+void km_nthw_cam_w1(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w1, val);
+};
+
+void km_nthw_cam_w2(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w2, val);
+};
+
+void km_nthw_cam_w3(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w3, val);
+};
+
+void km_nthw_cam_w4(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w4, val);
+};
+
+void km_nthw_cam_w5(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_w5, val);
+};
+
+void km_nthw_cam_ft0(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft0, val);
+};
+
+void km_nthw_cam_ft1(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft1, val);
+};
+
+void km_nthw_cam_ft2(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft2, val);
+};
+
+void km_nthw_cam_ft3(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft3, val);
+};
+
+void km_nthw_cam_ft4(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft4, val);
+};
+
+void km_nthw_cam_ft5(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_cam_data_ft5, val);
+};
+
+void km_nthw_cam_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_cam_ctrl, 1);
+ register_flush(p->mp_cam_data, 1);
+};
+
+/* TCAM */
+void km_nthw_tcam_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcam_addr, val);
+};
+
+void km_nthw_tcam_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcam_cnt, val);
+};
+
+void km_nthw_tcam_t(const struct km_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_tcam_data_t, val, 3);
+};
+
+void km_nthw_tcam_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_tcam_ctrl, 1);
+ register_flush(p->mp_tcam_data, 1);
+};
+
+/* TCI */
+void km_nthw_tci_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_addr, val);
+};
+
+void km_nthw_tci_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_cnt, val);
+};
+
+void km_nthw_tci_color(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_data_color, val);
+};
+
+void km_nthw_tci_ft(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tci_data_ft, val);
+};
+
+void km_nthw_tci_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_tci_ctrl, 1);
+ register_flush(p->mp_tci_data, 1);
+};
+
+/* TCQ */
+void km_nthw_tcq_select(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcq_addr, val);
+};
+
+void km_nthw_tcq_cnt(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcq_cnt, val);
+};
+
+void km_nthw_tcq_bank_mask(const struct km_nthw *p, uint32_t val)
+{
+ CHECK_AND_SET_VALUE(p->mp_tcq_data_bank_mask, val);
+};
+
+void km_nthw_tcq_qual(const struct km_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tcq_data_qual, val);
+};
+
+void km_nthw_tcq_qual72(const struct km_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_tcq_data_qual, val, 3);
+}; /* to use in v4 */
+
+void km_nthw_tcq_flush(const struct km_nthw *p)
+{
+ register_flush(p->mp_tcq_ctrl, 1);
+ register_flush(p->mp_tcq_data, 1);
+};
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h
new file mode 100644
index 0000000000..61f9ed2ae4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_km.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_KM_H__
+#define __FLOW_NTHW_KM_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct km_nthw;
+
+typedef struct km_nthw km_nthw_t;
+
+struct km_nthw *km_nthw_new(void);
+void km_nthw_delete(struct km_nthw *p);
+int km_nthw_init(struct km_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int km_nthw_setup(struct km_nthw *p, int n_idx, int n_idx_cnt);
+void km_nthw_set_debug_mode(struct km_nthw *p, unsigned int n_debug_mode);
+
+/* RCP initial v3 */
+void km_nthw_rcp_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw0_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw0_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_qw0_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw0_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw4_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw4_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_qw4_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_qw4_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw8_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw8_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw8_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw8_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw9_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw9_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw9_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw9_sel_b(const struct km_nthw *p, uint32_t val);
+/* subst in v6 */
+void km_nthw_rcp_dw8_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw8_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_dw8_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw8_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw10_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw10_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_dw10_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw10_sel_b(const struct km_nthw *p, uint32_t val);
+
+void km_nthw_rcp_swx_ovs_sb(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_swx_cch(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_swx_sel_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_swx_sel_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_mask_a(const struct km_nthw *p, const uint32_t *val);
+void km_nthw_rcp_mask_d_a(const struct km_nthw *p, const uint32_t *val);
+void km_nthw_rcp_mask_b(const struct km_nthw *p, const uint32_t *val);
+void km_nthw_rcp_dual(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_paired(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_el_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_el_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_info_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_info_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_ftm_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_ftm_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_bank_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_bank_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_kl_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_kl_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_flow_set(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_keyway_a(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_keyway_b(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_synergy_mode(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw0_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw0_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_dw2_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_dw2_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw4_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw4_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_sw5_b_dyn(const struct km_nthw *p, uint32_t val);
+void km_nthw_rcp_sw5_b_ofs(const struct km_nthw *p, int32_t val);
+void km_nthw_rcp_flush(const struct km_nthw *p);
+/* CAM */
+void km_nthw_cam_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w0(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w1(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w2(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w3(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w4(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_w5(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft0(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft1(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft2(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft3(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft4(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_ft5(const struct km_nthw *p, uint32_t val);
+void km_nthw_cam_flush(const struct km_nthw *p);
+/* TCAM */
+void km_nthw_tcam_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcam_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcam_t(const struct km_nthw *p, uint32_t *val);
+void km_nthw_tcam_flush(const struct km_nthw *p);
+/* TCI */
+void km_nthw_tci_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_color(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_ft(const struct km_nthw *p, uint32_t val);
+void km_nthw_tci_flush(const struct km_nthw *p);
+/* TCQ */
+void km_nthw_tcq_select(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_cnt(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_bank_mask(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_qual(const struct km_nthw *p, uint32_t val);
+void km_nthw_tcq_qual72(const struct km_nthw *p, uint32_t *val);
+
+void km_nthw_tcq_flush(const struct km_nthw *p);
+
+struct km_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_km;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_qw0_dyn;
+ nt_field_t *mp_rcp_data_qw0_ofs;
+ nt_field_t *mp_rcp_data_qw0_sel_a;
+ nt_field_t *mp_rcp_data_qw0_sel_b;
+ nt_field_t *mp_rcp_data_qw4_dyn;
+ nt_field_t *mp_rcp_data_qw4_ofs;
+ nt_field_t *mp_rcp_data_qw4_sel_a;
+ nt_field_t *mp_rcp_data_qw4_sel_b;
+ nt_field_t *mp_rcp_data_sw8_dyn;
+ nt_field_t *mp_rcp_data_sw8_ofs;
+ nt_field_t *mp_rcp_data_sw8_sel_a;
+ nt_field_t *mp_rcp_data_sw8_sel_b;
+ nt_field_t *mp_rcp_data_sw9_dyn;
+ nt_field_t *mp_rcp_data_sw9_ofs;
+ nt_field_t *mp_rcp_data_sw9_sel_a;
+ nt_field_t *mp_rcp_data_sw9_sel_b;
+
+ nt_field_t *mp_rcp_data_dw8_dyn; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw8_ofs; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw8_sel_a; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw8_sel_b; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_dyn; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_ofs; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_sel_a; /* substituted Sw<x> from v6+ */
+ nt_field_t *mp_rcp_data_dw10_sel_b; /* substituted Sw<x> from v6+ */
+
+ nt_field_t *mp_rcp_data_swx_ovs_sb;
+ nt_field_t *mp_rcp_data_swx_cch;
+ nt_field_t *mp_rcp_data_swx_sel_a;
+ nt_field_t *mp_rcp_data_swx_sel_b;
+ nt_field_t *mp_rcp_data_mask_a;
+ nt_field_t *mp_rcp_data_mask_b;
+ nt_field_t *mp_rcp_data_dual;
+ nt_field_t *mp_rcp_data_paired;
+ nt_field_t *mp_rcp_data_el_a;
+ nt_field_t *mp_rcp_data_el_b;
+ nt_field_t *mp_rcp_data_info_a;
+ nt_field_t *mp_rcp_data_info_b;
+ nt_field_t *mp_rcp_data_ftm_a;
+ nt_field_t *mp_rcp_data_ftm_b;
+ nt_field_t *mp_rcp_data_bank_a;
+ nt_field_t *mp_rcp_data_bank_b;
+ nt_field_t *mp_rcp_data_kl_a;
+ nt_field_t *mp_rcp_data_kl_b;
+ nt_field_t *mp_rcp_data_flow_set;
+ nt_field_t *mp_rcp_data_keyway_a;
+ nt_field_t *mp_rcp_data_keyway_b;
+ nt_field_t *mp_rcp_data_synergy_mode;
+ nt_field_t *mp_rcp_data_dw0_b_dyn;
+ nt_field_t *mp_rcp_data_dw0_b_ofs;
+ nt_field_t *mp_rcp_data_dw2_b_dyn;
+ nt_field_t *mp_rcp_data_dw2_b_ofs;
+ nt_field_t *mp_rcp_data_sw4_b_dyn;
+ nt_field_t *mp_rcp_data_sw4_b_ofs;
+ nt_field_t *mp_rcp_data_sw5_b_dyn;
+ nt_field_t *mp_rcp_data_sw5_b_ofs;
+
+ nt_register_t *mp_cam_ctrl;
+ nt_field_t *mp_cam_addr;
+ nt_field_t *mp_cam_cnt;
+ nt_register_t *mp_cam_data;
+ nt_field_t *mp_cam_data_w0;
+ nt_field_t *mp_cam_data_w1;
+ nt_field_t *mp_cam_data_w2;
+ nt_field_t *mp_cam_data_w3;
+ nt_field_t *mp_cam_data_w4;
+ nt_field_t *mp_cam_data_w5;
+ nt_field_t *mp_cam_data_ft0;
+ nt_field_t *mp_cam_data_ft1;
+ nt_field_t *mp_cam_data_ft2;
+ nt_field_t *mp_cam_data_ft3;
+ nt_field_t *mp_cam_data_ft4;
+ nt_field_t *mp_cam_data_ft5;
+
+ nt_register_t *mp_tcam_ctrl;
+ nt_field_t *mp_tcam_addr;
+ nt_field_t *mp_tcam_cnt;
+ nt_register_t *mp_tcam_data;
+ nt_field_t *mp_tcam_data_t;
+
+ nt_register_t *mp_tci_ctrl;
+ nt_field_t *mp_tci_addr;
+ nt_field_t *mp_tci_cnt;
+ nt_register_t *mp_tci_data;
+ nt_field_t *mp_tci_data_color;
+ nt_field_t *mp_tci_data_ft;
+
+ nt_register_t *mp_tcq_ctrl;
+ nt_field_t *mp_tcq_addr;
+ nt_field_t *mp_tcq_cnt;
+ nt_register_t *mp_tcq_data;
+ nt_field_t *mp_tcq_data_bank_mask;
+ nt_field_t *mp_tcq_data_qual;
+};
+
+#endif /* __FLOW_NTHW_KM_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c
new file mode 100644
index 0000000000..e823a527bb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.c
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_pdb.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void pdb_nthw_set_debug_mode(struct pdb_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_pdb, n_debug_mode);
+}
+
+struct pdb_nthw *pdb_nthw_new(void)
+{
+ struct pdb_nthw *p = malloc(sizeof(struct pdb_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void pdb_nthw_delete(struct pdb_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int pdb_nthw_init(struct pdb_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_PDB, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Pdb %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_pdb = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_pdb, PDB_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, PDB_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, PDB_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_pdb, PDB_RCP_DATA);
+ p->mp_rcp_data_descriptor =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DESCRIPTOR);
+ p->mp_rcp_data_desc_len =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DESC_LEN);
+ p->mp_rcp_data_tx_port =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_PORT);
+ p->mp_rcp_data_tx_ignore =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_IGNORE);
+ p->mp_rcp_data_tx_now =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_TX_NOW);
+ p->mp_rcp_data_crc_overwrite =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_CRC_OVERWRITE);
+ p->mp_rcp_data_align = register_get_field(p->mp_rcp_data, PDB_RCP_DATA_ALIGN);
+ p->mp_rcp_data_ofs0_dyn =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS0_DYN);
+ p->mp_rcp_data_ofs0_rel =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS0_REL);
+ p->mp_rcp_data_ofs1_dyn =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS1_DYN);
+ p->mp_rcp_data_ofs1_rel =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS1_REL);
+ p->mp_rcp_data_ofs2_dyn =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS2_DYN);
+ p->mp_rcp_data_ofs2_rel =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_OFS2_REL);
+ p->mp_rcp_data_ip_prot_tnl =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_IP_PROT_TNL);
+ p->mp_rcp_data_ppc_hsh =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_PPC_HSH);
+ p->mp_rcp_data_duplicate_en =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DUPLICATE_EN);
+ p->mp_rcp_data_duplicate_bit =
+ register_get_field(p->mp_rcp_data, PDB_RCP_DATA_DUPLICATE_BIT);
+ p->mp_rcp_data_pcap_keep_fcs =
+ register_query_field(p->mp_rcp_data, PDB_RCP_DATA_PCAP_KEEP_FCS);
+ /* CONFIG */
+ p->mp_config = module_get_register(p->m_pdb, PDB_CONFIG);
+ p->mp_config_ts_format =
+ register_get_field(p->mp_config, PDB_CONFIG_TS_FORMAT);
+ p->mp_config_port_ofs =
+ register_get_field(p->mp_config, PDB_CONFIG_PORT_OFS);
+
+ return 0;
+}
+
+/* RCP */
+void pdb_nthw_rcp_select(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void pdb_nthw_rcp_cnt(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void pdb_nthw_rcp_descriptor(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_descriptor, val);
+}
+
+void pdb_nthw_rcp_desc_len(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_desc_len, val);
+}
+
+void pdb_nthw_rcp_tx_port(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tx_port, val);
+}
+
+void pdb_nthw_rcp_tx_ignore(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tx_ignore, val);
+}
+
+void pdb_nthw_rcp_tx_now(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tx_now, val);
+}
+
+void pdb_nthw_rcp_crc_overwrite(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_crc_overwrite, val);
+}
+
+void pdb_nthw_rcp_align(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_align, val);
+}
+
+void pdb_nthw_rcp_ofs0_dyn(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs0_dyn, val);
+}
+
+void pdb_nthw_rcp_ofs0_rel(const struct pdb_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs0_rel, val);
+}
+
+void pdb_nthw_rcp_ofs1_dyn(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs1_dyn, val);
+}
+
+void pdb_nthw_rcp_ofs1_rel(const struct pdb_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs1_rel, val);
+}
+
+void pdb_nthw_rcp_ofs2_dyn(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs2_dyn, val);
+}
+
+void pdb_nthw_rcp_ofs2_rel(const struct pdb_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs2_rel, val);
+}
+
+void pdb_nthw_rcp_ip_prot_tnl(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ip_prot_tnl, val);
+}
+
+void pdb_nthw_rcp_ppc_hsh(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ppc_hsh, val);
+}
+
+void pdb_nthw_rcp_duplicate_en(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_duplicate_en, val);
+}
+
+void pdb_nthw_rcp_duplicate_bit(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_duplicate_bit, val);
+}
+
+void pdb_nthw_rcp_data_pcap_keep_fcs(const struct pdb_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_pcap_keep_fcs)
+ field_set_val32(p->mp_rcp_data_pcap_keep_fcs, val);
+}
+
+void pdb_nthw_rcp_flush(const struct pdb_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+/* CONFIG */
+void pdb_nthw_config_ts_format(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_ts_format, val);
+}
+
+void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_port_ofs, val);
+}
+
+void pdb_nthw_config_flush(const struct pdb_nthw *p)
+{
+ register_flush(p->mp_config, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h
new file mode 100644
index 0000000000..aed050eca5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_pdb.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_PDB_H__
+#define __FLOW_NTHW_PDB_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct pdb_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_pdb;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_descriptor;
+ nt_field_t *mp_rcp_data_desc_len;
+ nt_field_t *mp_rcp_data_tx_port;
+ nt_field_t *mp_rcp_data_tx_ignore;
+ nt_field_t *mp_rcp_data_tx_now;
+ nt_field_t *mp_rcp_data_crc_overwrite;
+ nt_field_t *mp_rcp_data_align;
+ nt_field_t *mp_rcp_data_ofs0_dyn;
+ nt_field_t *mp_rcp_data_ofs0_rel;
+ nt_field_t *mp_rcp_data_ofs1_dyn;
+ nt_field_t *mp_rcp_data_ofs1_rel;
+ nt_field_t *mp_rcp_data_ofs2_dyn;
+ nt_field_t *mp_rcp_data_ofs2_rel;
+ nt_field_t *mp_rcp_data_ip_prot_tnl;
+ nt_field_t *mp_rcp_data_ppc_hsh;
+ nt_field_t *mp_rcp_data_duplicate_en;
+ nt_field_t *mp_rcp_data_duplicate_bit;
+ nt_field_t *mp_rcp_data_pcap_keep_fcs;
+
+ nt_register_t *mp_config;
+ nt_field_t *mp_config_ts_format;
+ nt_field_t *mp_config_port_ofs;
+};
+
+typedef struct pdb_nthw pdb_nthw_t;
+
+struct pdb_nthw *pdb_nthw_new(void);
+void pdb_nthw_delete(struct pdb_nthw *p);
+int pdb_nthw_init(struct pdb_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int pdb_nthw_setup(struct pdb_nthw *p, int n_idx, int n_idx_cnt);
+void pdb_nthw_set_debug_mode(struct pdb_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void pdb_nthw_rcp_select(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_cnt(const struct pdb_nthw *p, uint32_t val);
+
+void pdb_nthw_rcp_descriptor(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_desc_len(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_tx_port(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_tx_ignore(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_tx_now(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_crc_overwrite(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_align(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs0_dyn(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs0_rel(const struct pdb_nthw *p, int32_t val);
+void pdb_nthw_rcp_ofs1_dyn(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs1_rel(const struct pdb_nthw *p, int32_t val);
+void pdb_nthw_rcp_ofs2_dyn(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ofs2_rel(const struct pdb_nthw *p, int32_t val);
+void pdb_nthw_rcp_ip_prot_tnl(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_ppc_hsh(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_duplicate_en(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_duplicate_bit(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_data_pcap_keep_fcs(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_rcp_flush(const struct pdb_nthw *p);
+
+/* CONFIG */
+void pdb_nthw_config_ts_format(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_config_port_ofs(const struct pdb_nthw *p, uint32_t val);
+void pdb_nthw_config_flush(const struct pdb_nthw *p);
+
+#endif /* __FLOW_NTHW_PDB_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c
new file mode 100644
index 0000000000..6c13824df6
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.c
@@ -0,0 +1,355 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_qsl.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void qsl_nthw_set_debug_mode(struct qsl_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_qsl, n_debug_mode);
+}
+
+struct qsl_nthw *qsl_nthw_new(void)
+{
+ struct qsl_nthw *p = malloc(sizeof(struct qsl_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void qsl_nthw_delete(struct qsl_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int qsl_nthw_init(struct qsl_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_QSL, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: QSL %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_qsl = p_mod;
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_qsl, QSL_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, QSL_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, QSL_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_qsl, QSL_RCP_DATA);
+ p->mp_rcp_data_discard =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_DISCARD);
+ p->mp_rcp_data_drop = register_get_field(p->mp_rcp_data, QSL_RCP_DATA_DROP);
+ p->mp_rcp_data_tbl_lo =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_LO);
+ p->mp_rcp_data_tbl_hi =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_HI);
+ p->mp_rcp_data_tbl_idx =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_IDX);
+ p->mp_rcp_data_tbl_msk =
+ register_get_field(p->mp_rcp_data, QSL_RCP_DATA_TBL_MSK);
+ p->mp_rcp_data_cao = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_CAO);
+ p->mp_rcp_data_lr = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_LR);
+ p->mp_rcp_data_tsa = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_TSA);
+ p->mp_rcp_data_vli = register_query_field(p->mp_rcp_data, QSL_RCP_DATA_VLI);
+
+ /* QST */
+ p->mp_qst_ctrl = module_get_register(p->m_qsl, QSL_QST_CTRL);
+ p->mp_qst_addr = register_get_field(p->mp_qst_ctrl, QSL_QST_CTRL_ADR);
+ p->mp_qst_cnt = register_get_field(p->mp_qst_ctrl, QSL_QST_CTRL_CNT);
+ p->mp_qst_data = module_get_register(p->m_qsl, QSL_QST_DATA);
+ p->mp_qst_data_queue = register_get_field(p->mp_qst_data, QSL_QST_DATA_QUEUE);
+ p->mp_qst_data_en = register_query_field(p->mp_qst_data, QSL_QST_DATA_EN);
+ p->mp_qst_data_tx_port =
+ register_query_field(p->mp_qst_data, QSL_QST_DATA_TX_PORT);
+ p->mp_qst_data_lre = register_query_field(p->mp_qst_data, QSL_QST_DATA_LRE);
+ p->mp_qst_data_tci = register_query_field(p->mp_qst_data, QSL_QST_DATA_TCI);
+ p->mp_qst_data_ven = register_query_field(p->mp_qst_data, QSL_QST_DATA_VEN);
+ /* QEN */
+ p->mp_qen_ctrl = module_get_register(p->m_qsl, QSL_QEN_CTRL);
+ p->mp_qen_addr = register_get_field(p->mp_qen_ctrl, QSL_QEN_CTRL_ADR);
+ p->mp_qen_cnt = register_get_field(p->mp_qen_ctrl, QSL_QEN_CTRL_CNT);
+ p->mp_qen_data = module_get_register(p->m_qsl, QSL_QEN_DATA);
+ p->mp_qen_data_en = register_get_field(p->mp_qen_data, QSL_QEN_DATA_EN);
+ /* UNMQ */
+ p->mp_unmq_ctrl = module_get_register(p->m_qsl, QSL_UNMQ_CTRL);
+ p->mp_unmq_addr = register_get_field(p->mp_unmq_ctrl, QSL_UNMQ_CTRL_ADR);
+ p->mp_unmq_cnt = register_get_field(p->mp_unmq_ctrl, QSL_UNMQ_CTRL_CNT);
+ p->mp_unmq_data = module_get_register(p->m_qsl, QSL_UNMQ_DATA);
+ p->mp_unmq_data_dest_queue =
+ register_get_field(p->mp_unmq_data, QSL_UNMQ_DATA_DEST_QUEUE);
+ p->mp_unmq_data_en = register_get_field(p->mp_unmq_data, QSL_UNMQ_DATA_EN);
+
+ if (!p->mp_qst_data_en) {
+ /* changed name from EN to QEN in v0.7 */
+ p->mp_qst_data_en =
+ register_get_field(p->mp_qst_data, QSL_QST_DATA_QEN);
+ }
+
+ /* LTX - not there anymore from v0.7+ */
+ p->mp_ltx_ctrl = module_query_register(p->m_qsl, QSL_LTX_CTRL);
+ if (p->mp_ltx_ctrl) {
+ p->mp_ltx_addr =
+ register_get_field(p->mp_ltx_ctrl, QSL_LTX_CTRL_ADR);
+ p->mp_ltx_cnt = register_get_field(p->mp_ltx_ctrl, QSL_LTX_CTRL_CNT);
+ } else {
+ p->mp_ltx_addr = NULL;
+ p->mp_ltx_cnt = NULL;
+ }
+ p->mp_ltx_data = module_query_register(p->m_qsl, QSL_LTX_DATA);
+ if (p->mp_ltx_data) {
+ p->mp_ltx_data_lr =
+ register_get_field(p->mp_ltx_data, QSL_LTX_DATA_LR);
+ p->mp_ltx_data_tx_port =
+ register_get_field(p->mp_ltx_data, QSL_LTX_DATA_TX_PORT);
+ p->mp_ltx_data_tsa =
+ register_get_field(p->mp_ltx_data, QSL_LTX_DATA_TSA);
+ } else {
+ p->mp_ltx_data_lr = NULL;
+ p->mp_ltx_data_tx_port = NULL;
+ p->mp_ltx_data_tsa = NULL;
+ }
+ return 0;
+}
+
+int qsl_nthw_setup(struct qsl_nthw *p, int n_idx, int n_idx_cnt)
+{
+ (void)p;
+ (void)n_idx;
+ (void)n_idx_cnt;
+
+ return 0;
+}
+
+/* RCP */
+void qsl_nthw_rcp_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+};
+
+void qsl_nthw_rcp_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void qsl_nthw_rcp_discard(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_discard, val);
+}
+
+void qsl_nthw_rcp_drop(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_drop, val);
+}
+
+void qsl_nthw_rcp_tbl_lo(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tbl_lo, val);
+}
+
+void qsl_nthw_rcp_tbl_hi(const struct qsl_nthw *p, uint32_t val)
+
+{
+ field_set_val32(p->mp_rcp_data_tbl_hi, val);
+}
+
+void qsl_nthw_rcp_tbl_idx(const struct qsl_nthw *p, uint32_t val)
+
+{
+ field_set_val32(p->mp_rcp_data_tbl_idx, val);
+}
+
+void qsl_nthw_rcp_tbl_msk(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tbl_msk, val);
+}
+
+void qsl_nthw_rcp_cao(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_cao)
+ field_set_val32(p->mp_rcp_data_cao, val);
+}
+
+void qsl_nthw_rcp_lr(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_lr)
+ field_set_val32(p->mp_rcp_data_lr, val);
+}
+
+void qsl_nthw_rcp_tsa(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_tsa)
+ field_set_val32(p->mp_rcp_data_tsa, val);
+}
+
+void qsl_nthw_rcp_vli(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_rcp_data_vli)
+ field_set_val32(p->mp_rcp_data_vli, val);
+}
+
+void qsl_nthw_rcp_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+/* LTX */
+void qsl_nthw_ltx_select(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_addr)
+ field_set_val32(p->mp_ltx_addr, val);
+}
+
+void qsl_nthw_ltx_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_addr)
+ field_set_val32(p->mp_ltx_cnt, val);
+}
+
+void qsl_nthw_ltx_lr(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_data_lr)
+ field_set_val32(p->mp_ltx_data_lr, val);
+}
+
+void qsl_nthw_ltx_tx_port(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_data_tx_port)
+ field_set_val32(p->mp_ltx_data_tx_port, val);
+}
+
+void qsl_nthw_ltx_tsa(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_ltx_data_tsa)
+ field_set_val32(p->mp_ltx_data_tsa, val);
+};
+
+void qsl_nthw_ltx_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_ltx_ctrl, 1);
+ register_flush(p->mp_ltx_data, 1);
+}
+
+/* QST */
+void qsl_nthw_qst_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_addr, val);
+}
+
+void qsl_nthw_qst_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_cnt, val);
+}
+
+void qsl_nthw_qst_queue(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_data_queue, val);
+}
+
+void qsl_nthw_qst_en(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qst_data_en, val);
+}
+
+void qsl_nthw_qst_tx_port(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_tx_port)
+ field_set_val32(p->mp_qst_data_tx_port, val);
+}
+
+void qsl_nthw_qst_lre(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_lre)
+ field_set_val32(p->mp_qst_data_lre, val);
+}
+
+void qsl_nthw_qst_tci(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_tci)
+ field_set_val32(p->mp_qst_data_tci, val);
+}
+
+void qsl_nthw_qst_ven(const struct qsl_nthw *p, uint32_t val)
+{
+ if (p->mp_qst_data_ven)
+ field_set_val32(p->mp_qst_data_ven, val);
+}
+
+void qsl_nthw_qst_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_qst_ctrl, 1);
+ register_flush(p->mp_qst_data, 1);
+}
+
+/* QEN */
+void qsl_nthw_qen_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qen_addr, val);
+}
+
+void qsl_nthw_qen_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qen_cnt, val);
+}
+
+void qsl_nthw_qen_en(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_qen_data_en, val);
+}
+
+void qsl_nthw_qen_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_qen_ctrl, 1);
+ register_flush(p->mp_qen_data, 1);
+}
+
+/* UNMQ */
+void qsl_nthw_unmq_select(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_addr, val);
+}
+
+void qsl_nthw_unmq_cnt(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_cnt, val);
+}
+
+void qsl_nthw_unmq_dest_queue(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_data_dest_queue, val);
+}
+
+void qsl_nthw_unmq_en(const struct qsl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_unmq_data_en, val);
+}
+
+void qsl_nthw_unmq_flush(const struct qsl_nthw *p)
+{
+ register_flush(p->mp_unmq_ctrl, 1);
+ register_flush(p->mp_unmq_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h
new file mode 100644
index 0000000000..eeebbcf1c4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_qsl.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_QSL_H__
+#define __FLOW_NTHW_QSL_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct qsl_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_qsl;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_discard;
+ nt_field_t *mp_rcp_data_drop;
+ nt_field_t *mp_rcp_data_tbl_lo;
+ nt_field_t *mp_rcp_data_tbl_hi;
+ nt_field_t *mp_rcp_data_tbl_idx;
+ nt_field_t *mp_rcp_data_tbl_msk;
+ nt_field_t *mp_rcp_data_cao;
+ nt_field_t *mp_rcp_data_lr;
+ nt_field_t *mp_rcp_data_tsa;
+ nt_field_t *mp_rcp_data_vli;
+
+ nt_register_t *mp_ltx_ctrl;
+ nt_field_t *mp_ltx_addr;
+ nt_field_t *mp_ltx_cnt;
+ nt_register_t *mp_ltx_data;
+ nt_field_t *mp_ltx_data_lr;
+ nt_field_t *mp_ltx_data_tx_port;
+ nt_field_t *mp_ltx_data_tsa;
+
+ nt_register_t *mp_qst_ctrl;
+ nt_field_t *mp_qst_addr;
+ nt_field_t *mp_qst_cnt;
+ nt_register_t *mp_qst_data;
+ nt_field_t *mp_qst_data_queue;
+ nt_field_t *mp_qst_data_en;
+ nt_field_t *mp_qst_data_tx_port;
+ nt_field_t *mp_qst_data_lre;
+ nt_field_t *mp_qst_data_tci;
+ nt_field_t *mp_qst_data_ven;
+
+ nt_register_t *mp_qen_ctrl;
+ nt_field_t *mp_qen_addr;
+ nt_field_t *mp_qen_cnt;
+ nt_register_t *mp_qen_data;
+ nt_field_t *mp_qen_data_en;
+
+ nt_register_t *mp_unmq_ctrl;
+ nt_field_t *mp_unmq_addr;
+ nt_field_t *mp_unmq_cnt;
+ nt_register_t *mp_unmq_data;
+ nt_field_t *mp_unmq_data_dest_queue;
+ nt_field_t *mp_unmq_data_en;
+};
+
+typedef struct qsl_nthw qsl_nthw_t;
+
+struct qsl_nthw *qsl_nthw_new(void);
+void qsl_nthw_delete(struct qsl_nthw *p);
+int qsl_nthw_init(struct qsl_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int qsl_nthw_setup(struct qsl_nthw *p, int n_idx, int n_idx_cnt);
+void qsl_nthw_set_debug_mode(struct qsl_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void qsl_nthw_rcp_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_discard(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_drop(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_lo(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_hi(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_idx(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tbl_msk(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_cao(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_lr(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_tsa(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_vli(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_rcp_flush(const struct qsl_nthw *p);
+
+/* LTX */
+void qsl_nthw_ltx_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_lr(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_tx_port(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_tsa(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_ltx_flush(const struct qsl_nthw *p);
+
+/* QST */
+void qsl_nthw_qst_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_queue(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_en(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_tx_port(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_lre(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_tci(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_ven(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qst_flush(const struct qsl_nthw *p);
+
+/* QEN */
+void qsl_nthw_qen_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qen_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qen_en(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_qen_flush(const struct qsl_nthw *p);
+
+/* UNMQ */
+void qsl_nthw_unmq_select(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_cnt(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_dest_queue(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_en(const struct qsl_nthw *p, uint32_t val);
+void qsl_nthw_unmq_flush(const struct qsl_nthw *p);
+
+#endif /* __FLOW_NTHW_QSL_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c
new file mode 100644
index 0000000000..8f519b7728
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_rmc.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void rmc_nthw_set_debug_mode(struct rmc_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_rmc, n_debug_mode);
+}
+
+struct rmc_nthw *rmc_nthw_new(void)
+{
+ struct rmc_nthw *p = malloc(sizeof(struct rmc_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void rmc_nthw_delete(struct rmc_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int rmc_nthw_init(struct rmc_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RMC, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RMC %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_rmc = p_mod;
+
+ /* CTRL */
+ p->mp_ctrl = module_get_register(p->m_rmc, RMC_CTRL);
+ p->mp_ctrl_block_statt =
+ register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_STATT);
+ p->mp_ctrl_block_keep_a =
+ register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_KEEPA);
+ p->mp_ctrl_block_rpp_slice =
+ register_query_field(p->mp_ctrl, RMC_CTRL_BLOCK_RPP_SLICE);
+ p->mp_ctrl_block_mac_port =
+ register_get_field(p->mp_ctrl, RMC_CTRL_BLOCK_MAC_PORT);
+ p->mp_ctrl_lag_phy_odd_even =
+ register_get_field(p->mp_ctrl, RMC_CTRL_LAG_PHY_ODD_EVEN);
+ return 0;
+}
+
+int rmc_nthw_setup(struct rmc_nthw *p, int n_idx, int n_idx_cnt)
+{
+ (void)p;
+ (void)n_idx;
+ (void)n_idx_cnt;
+
+ return 0;
+}
+
+/* CTRL */
+void rmc_nthw_ctrl_block_statt(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_block_statt, val);
+}
+
+void rmc_nthw_ctrl_block_keep_a(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_block_keep_a, val);
+}
+
+void rmc_nthw_ctrl_block_rpp_slice(const struct rmc_nthw *p, uint32_t val)
+{
+ if (p->mp_ctrl_block_rpp_slice)
+ field_set_val32(p->mp_ctrl_block_rpp_slice, val);
+}
+
+void rmc_nthw_ctrl_block_mac_port(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_block_mac_port, val);
+}
+
+void rmc_nthw_ctrl_lag_phy_odd_even(const struct rmc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ctrl_lag_phy_odd_even, val);
+}
+
+void rmc_nthw_ctrl_flush(const struct rmc_nthw *p)
+{
+ register_flush(p->mp_ctrl, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h
new file mode 100644
index 0000000000..57d5776002
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rmc.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_RMC_H__
+#define __FLOW_NTHW_RMC_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct rmc_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_rmc;
+
+ nt_register_t *mp_ctrl;
+ nt_field_t *mp_ctrl_block_statt;
+ nt_field_t *mp_ctrl_block_keep_a;
+ nt_field_t *mp_ctrl_block_rpp_slice;
+ nt_field_t *mp_ctrl_block_mac_port;
+ nt_field_t *mp_ctrl_lag_phy_odd_even;
+};
+
+struct rmc_nthw *rmc_nthw_new(void);
+void rmc_nthw_delete(struct rmc_nthw *p);
+int rmc_nthw_init(struct rmc_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int rmc_nthw_setup(struct rmc_nthw *p, int n_idx, int n_idx_cnt);
+void rmc_nthw_set_debug_mode(struct rmc_nthw *p, unsigned int n_debug_mode);
+
+/* CTRL */
+void rmc_nthw_ctrl_block_statt(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_block_keep_a(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_block_rpp_slice(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_block_mac_port(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_lag_phy_odd_even(const struct rmc_nthw *p, uint32_t val);
+void rmc_nthw_ctrl_flush(const struct rmc_nthw *p);
+
+#endif /* __FLOW_NTHW_RMC_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c
new file mode 100644
index 0000000000..934778f426
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.c
@@ -0,0 +1,294 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_roa.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void roa_nthw_set_debug_mode(struct roa_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_roa, n_debug_mode);
+}
+
+struct roa_nthw *roa_nthw_new(void)
+{
+ struct roa_nthw *p = malloc(sizeof(struct roa_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void roa_nthw_delete(struct roa_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int roa_nthw_init(struct roa_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_ROA, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: ROA %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_roa = p_mod;
+
+ /* TUN HDR */
+ p->mp_tun_hdr_ctrl = module_get_register(p->m_roa, ROA_TUNHDR_CTRL);
+ p->mp_tun_hdr_addr =
+ register_get_field(p->mp_tun_hdr_ctrl, ROA_TUNHDR_CTRL_ADR);
+ p->mp_tun_hdr_cnt =
+ register_get_field(p->mp_tun_hdr_ctrl, ROA_TUNHDR_CTRL_CNT);
+ p->mp_tun_hdr_data = module_get_register(p->m_roa, ROA_TUNHDR_DATA);
+ p->mp_tun_hdr_data_tunnel_hdr =
+ register_get_field(p->mp_tun_hdr_data, ROA_TUNHDR_DATA_TUNNEL_HDR);
+ /* TUN CFG */
+ p->mp_tun_cfg_ctrl = module_get_register(p->m_roa, ROA_TUNCFG_CTRL);
+ p->mp_tun_cfg_addr =
+ register_get_field(p->mp_tun_cfg_ctrl, ROA_TUNCFG_CTRL_ADR);
+ p->mp_tun_cfg_cnt =
+ register_get_field(p->mp_tun_cfg_ctrl, ROA_TUNCFG_CTRL_CNT);
+ p->mp_tun_cfg_data = module_get_register(p->m_roa, ROA_TUNCFG_DATA);
+ p->mp_tun_cfg_data_tun_len =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_LEN);
+ p->mp_tun_cfg_data_tun_type =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_TYPE);
+ p->mp_tun_cfg_data_tun_vlan =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_VLAN);
+ p->mp_tun_cfg_data_ip_type =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IP_TYPE);
+ p->mp_tun_cfg_data_ipcs_upd =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPCS_UPD);
+ p->mp_tun_cfg_data_ipcs_precalc =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPCS_PRECALC);
+ p->mp_tun_cfg_data_iptl_upd =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPTL_UPD);
+ p->mp_tun_cfg_data_iptl_precalc =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_IPTL_PRECALC);
+ p->mp_tun_cfg_data_vxlan_udp_len_upd =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TUN_VXLAN_UDP_LEN_UPD);
+ p->mp_tun_cfg_data_tx_lag_ix =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_TX_LAG_IX);
+ p->mp_tun_cfg_data_recirculate =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRCULATE);
+ p->mp_tun_cfg_data_push_tunnel =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_PUSH_TUNNEL);
+ p->mp_tun_cfg_data_recirc_port =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRC_PORT);
+ p->mp_tun_cfg_data_recirc_bypass =
+ register_get_field(p->mp_tun_cfg_data, ROA_TUNCFG_DATA_RECIRC_BYPASS);
+ /* CONFIG */
+ p->mp_config = module_get_register(p->m_roa, ROA_CONFIG);
+ p->mp_config_fwd_recirculate =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_RECIRCULATE);
+ p->mp_config_fwd_normal_pcks =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_NORMAL_PCKS);
+ p->mp_config_fwd_tx_port0 =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_TXPORT0);
+ p->mp_config_fwd_tx_port1 =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_TXPORT1);
+ p->mp_config_fwd_cell_builder_pcks =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_CELLBUILDER_PCKS);
+ p->mp_config_fwd_non_normal_pcks =
+ register_get_field(p->mp_config, ROA_CONFIG_FWD_NON_NORMAL_PCKS);
+ /* LAG */
+ p->mp_lag_cfg_ctrl = module_get_register(p->m_roa, ROA_LAGCFG_CTRL);
+ p->mp_lag_cfg_addr =
+ register_get_field(p->mp_lag_cfg_ctrl, ROA_LAGCFG_CTRL_ADR);
+ p->mp_lag_cfg_cnt =
+ register_get_field(p->mp_lag_cfg_ctrl, ROA_LAGCFG_CTRL_CNT);
+ p->mp_lag_cfg_data = module_get_register(p->m_roa, ROA_LAGCFG_DATA);
+ p->mp_lag_cfg_data_tx_phy_port =
+ register_get_field(p->mp_lag_cfg_data, ROA_LAGCFG_DATA_TXPHY_PORT);
+
+ return 0;
+}
+
+/* TUN HDR */
+void roa_nthw_tun_hdr_select(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_hdr_addr, val);
+}
+
+void roa_nthw_tun_hdr_cnt(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_hdr_cnt, val);
+}
+
+void roa_nthw_tun_hdr_tunnel_hdr(const struct roa_nthw *p, uint32_t *val)
+{
+ field_set_val(p->mp_tun_hdr_data_tunnel_hdr, val, 4);
+}
+
+void roa_nthw_tun_hdr_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_tun_hdr_ctrl, 1);
+ register_flush(p->mp_tun_hdr_data, 1);
+}
+
+/* TUN CFG */
+void roa_nthw_tun_cfg_select(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_addr, val);
+}
+
+void roa_nthw_tun_cfg_cnt(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_cnt, val);
+}
+
+void roa_nthw_tun_cfg_tun_len(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tun_len, val);
+}
+
+void roa_nthw_tun_cfg_tun_type(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tun_type, val);
+}
+
+void roa_nthw_tun_cfg_tun_vlan(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tun_vlan, val);
+}
+
+void roa_nthw_tun_cfg_ip_type(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_ip_type, val);
+}
+
+void roa_nthw_tun_cfg_ipcs_upd(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_ipcs_upd, val);
+}
+
+void roa_nthw_tun_cfg_ipcs_precalc(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_ipcs_precalc, val);
+}
+
+void roa_nthw_tun_cfg_iptl_upd(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_iptl_upd, val);
+}
+
+void roa_nthw_tun_cfg_iptl_precalc(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_iptl_precalc, val);
+}
+
+void roa_nthw_tun_cfg_vxlan_udp_len_upd(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_vxlan_udp_len_upd, val);
+}
+
+void roa_nthw_tun_cfg_tx_lag_ix(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_tx_lag_ix, val);
+};
+
+void roa_nthw_tun_cfg_recirculate(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_recirculate, val);
+}
+
+void roa_nthw_tun_cfg_push_tunnel(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_push_tunnel, val);
+}
+
+void roa_nthw_tun_cfg_recirc_port(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_recirc_port, val);
+}
+
+void roa_nthw_tun_cfg_recirc_bypass(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_tun_cfg_data_recirc_bypass, val);
+}
+
+void roa_nthw_tun_cfg_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_tun_cfg_ctrl, 1);
+ register_flush(p->mp_tun_cfg_data, 1);
+}
+
+/* ROA CONFIG */
+void roa_nthw_config_fwd_recirculate(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_recirculate, val);
+}
+
+void roa_nthw_config_fwd_normal_pcks(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_normal_pcks, val);
+}
+
+void roa_nthw_config_fwd_tx_port0(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_tx_port0, val);
+}
+
+void roa_nthw_config_fwd_tx_port1(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_tx_port1, val);
+}
+
+void roa_nthw_config_fwd_cell_builder_pcks(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_cell_builder_pcks, val);
+}
+
+void roa_nthw_config_fwd_non_normal_pcks(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_config_fwd_non_normal_pcks, val);
+}
+
+void roa_nthw_config_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_config, 1);
+}
+
+/* LAG */
+void roa_nthw_lag_cfg_select(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_lag_cfg_addr, val);
+}
+
+void roa_nthw_lag_cfg_cnt(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_lag_cfg_cnt, val);
+}
+
+void roa_nthw_lag_cfg_tx_phy_port(const struct roa_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_lag_cfg_data_tx_phy_port, val);
+}
+
+void roa_nthw_lag_cfg_flush(const struct roa_nthw *p)
+{
+ register_flush(p->mp_lag_cfg_ctrl, 1);
+ register_flush(p->mp_lag_cfg_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h
new file mode 100644
index 0000000000..9398ef5ae9
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_roa.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_ROA_H__
+#define __FLOW_NTHW_ROA_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct roa_nthw;
+
+typedef struct roa_nthw roa_nthw_t;
+
+struct roa_nthw *roa_nthw_new(void);
+void roa_nthw_delete(struct roa_nthw *p);
+int roa_nthw_init(struct roa_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int roa_nthw_setup(struct roa_nthw *p, int n_idx, int n_idx_cnt);
+void roa_nthw_set_debug_mode(struct roa_nthw *p, unsigned int n_debug_mode);
+
+/* TUN HDR */
+void roa_nthw_tun_hdr_select(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_hdr_cnt(const struct roa_nthw *p, uint32_t val);
+
+void roa_nthw_tun_hdr_tunnel_hdr(const struct roa_nthw *p, uint32_t *val);
+void roa_nthw_tun_hdr_flush(const struct roa_nthw *p);
+
+/* TUN CFG */
+void roa_nthw_tun_cfg_select(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_cnt(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tun_len(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tun_type(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tun_vlan(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_ip_type(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_ipcs_upd(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_ipcs_precalc(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_iptl_upd(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_iptl_precalc(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_vxlan_udp_len_upd(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_tx_lag_ix(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_recirculate(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_push_tunnel(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_recirc_port(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_recirc_bypass(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_tun_cfg_flush(const struct roa_nthw *p);
+
+/* ROA CONFIG */
+void roa_nthw_config_fwd_recirculate(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_normal_pcks(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_tx_port0(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_tx_port1(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_cell_builder_pcks(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_fwd_non_normal_pcks(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_config_flush(const struct roa_nthw *p);
+
+/* LAG */
+void roa_nthw_lag_cfg_select(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_lag_cfg_cnt(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_lag_cfg_tx_phy_port(const struct roa_nthw *p, uint32_t val);
+void roa_nthw_lag_cfg_flush(const struct roa_nthw *p);
+
+struct roa_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_roa;
+
+ nt_register_t *mp_tun_hdr_ctrl;
+ nt_field_t *mp_tun_hdr_addr;
+ nt_field_t *mp_tun_hdr_cnt;
+ nt_register_t *mp_tun_hdr_data;
+ nt_field_t *mp_tun_hdr_data_tunnel_hdr;
+
+ nt_register_t *mp_tun_cfg_ctrl;
+ nt_field_t *mp_tun_cfg_addr;
+ nt_field_t *mp_tun_cfg_cnt;
+ nt_register_t *mp_tun_cfg_data;
+ nt_field_t *mp_tun_cfg_data_tun_len;
+ nt_field_t *mp_tun_cfg_data_tun_type;
+ nt_field_t *mp_tun_cfg_data_tun_vlan;
+ nt_field_t *mp_tun_cfg_data_ip_type;
+ nt_field_t *mp_tun_cfg_data_ipcs_upd;
+ nt_field_t *mp_tun_cfg_data_ipcs_precalc;
+ nt_field_t *mp_tun_cfg_data_iptl_upd;
+ nt_field_t *mp_tun_cfg_data_iptl_precalc;
+ nt_field_t *mp_tun_cfg_data_vxlan_udp_len_upd;
+ nt_field_t *mp_tun_cfg_data_tx_lag_ix;
+ nt_field_t *mp_tun_cfg_data_recirculate;
+ nt_field_t *mp_tun_cfg_data_push_tunnel;
+ nt_field_t *mp_tun_cfg_data_recirc_port;
+ nt_field_t *mp_tun_cfg_data_recirc_bypass;
+
+ nt_register_t *mp_config;
+ nt_field_t *mp_config_fwd_recirculate;
+ nt_field_t *mp_config_fwd_normal_pcks;
+ nt_field_t *mp_config_fwd_tx_port0;
+ nt_field_t *mp_config_fwd_tx_port1;
+ nt_field_t *mp_config_fwd_cell_builder_pcks;
+ nt_field_t *mp_config_fwd_non_normal_pcks;
+
+ nt_register_t *mp_lag_cfg_ctrl;
+ nt_field_t *mp_lag_cfg_addr;
+ nt_field_t *mp_lag_cfg_cnt;
+ nt_register_t *mp_lag_cfg_data;
+ nt_field_t *mp_lag_cfg_data_tx_phy_port;
+};
+
+#endif /* __FLOW_NTHW_ROA_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c
new file mode 100644
index 0000000000..2ce3ce6cf8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_rpp_lr.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void rpp_lr_nthw_set_debug_mode(struct rpp_lr_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_rpp_lr, n_debug_mode);
+}
+
+struct rpp_lr_nthw *rpp_lr_nthw_new(void)
+{
+ struct rpp_lr_nthw *p = malloc(sizeof(struct rpp_lr_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void rpp_lr_nthw_delete(struct rpp_lr_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int rpp_lr_nthw_init(struct rpp_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_RPP_LR, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: RppLr %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_rpp_lr = fpga_query_module(p_fpga, MOD_RPP_LR, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_rpp_lr, RPP_LR_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, RPP_LR_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, RPP_LR_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_rpp_lr, RPP_LR_RCP_DATA);
+ p->mp_rcp_data_exp = register_get_field(p->mp_rcp_data, RPP_LR_RCP_DATA_EXP);
+
+ p->mp_ifr_rcp_ctrl = module_query_register(p->m_rpp_lr, RPP_LR_IFR_RCP_CTRL);
+ p->mp_ifr_rcp_addr =
+ register_query_field(p->mp_ifr_rcp_ctrl, RPP_LR_IFR_RCP_CTRL_ADR);
+ p->mp_ifr_rcp_cnt =
+ register_query_field(p->mp_ifr_rcp_ctrl, RPP_LR_IFR_RCP_CTRL_CNT);
+ p->mp_ifr_rcp_data = module_query_register(p->m_rpp_lr, RPP_LR_IFR_RCP_DATA);
+ p->mp_ifr_rcp_data_en =
+ register_query_field(p->mp_ifr_rcp_data, RPP_LR_IFR_RCP_DATA_EN);
+ p->mp_ifr_rcp_data_mtu =
+ register_query_field(p->mp_ifr_rcp_data, RPP_LR_IFR_RCP_DATA_MTU);
+
+ return 0;
+}
+
+void rpp_lr_nthw_rcp_select(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_addr);
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void rpp_lr_nthw_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_cnt);
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void rpp_lr_nthw_rcp_exp(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_rcp_data_exp);
+ field_set_val32(p->mp_rcp_data_exp, val);
+}
+
+void rpp_lr_nthw_rcp_flush(const struct rpp_lr_nthw *p)
+{
+ assert(p->mp_rcp_ctrl);
+ assert(p->mp_rcp_data);
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+void rpp_lr_nthw_ifr_rcp_select(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_addr);
+ field_set_val32(p->mp_ifr_rcp_addr, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_cnt);
+ field_set_val32(p->mp_ifr_rcp_cnt, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_en(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_data_en);
+ field_set_val32(p->mp_ifr_rcp_data_en, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_mtu(const struct rpp_lr_nthw *p, uint32_t val)
+{
+ assert(p->mp_ifr_rcp_data_mtu);
+ field_set_val32(p->mp_ifr_rcp_data_mtu, val);
+}
+
+void rpp_lr_nthw_ifr_rcp_flush(const struct rpp_lr_nthw *p)
+{
+ assert(p->mp_ifr_rcp_ctrl);
+ assert(p->mp_ifr_rcp_data);
+ register_flush(p->mp_ifr_rcp_ctrl, 1);
+ register_flush(p->mp_ifr_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h
new file mode 100644
index 0000000000..e442c9d8d2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_rpp_lr.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_RPP_LR_H__
+#define __FLOW_NTHW_RPP_LR_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct rpp_lr_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_rpp_lr;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_exp;
+
+ nt_register_t *mp_ifr_rcp_ctrl;
+ nt_field_t *mp_ifr_rcp_addr;
+ nt_field_t *mp_ifr_rcp_cnt;
+
+ nt_register_t *mp_ifr_rcp_data;
+ nt_field_t *mp_ifr_rcp_data_en;
+ nt_field_t *mp_ifr_rcp_data_mtu;
+};
+
+struct rpp_lr_nthw *rpp_lr_nthw_new(void);
+void rpp_lr_nthw_delete(struct rpp_lr_nthw *p);
+int rpp_lr_nthw_init(struct rpp_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int rpp_lr_nthw_setup(struct rpp_lr_nthw *p, int n_idx, int n_idx_cnt);
+void rpp_lr_nthw_set_debug_mode(struct rpp_lr_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void rpp_lr_nthw_rcp_select(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_rcp_exp(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_rcp_flush(const struct rpp_lr_nthw *p);
+
+/* RCP IFR */
+void rpp_lr_nthw_ifr_rcp_select(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_cnt(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_en(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_mtu(const struct rpp_lr_nthw *p, uint32_t val);
+void rpp_lr_nthw_ifr_rcp_flush(const struct rpp_lr_nthw *p);
+
+#endif /* __FLOW_NTHW_RPP_LR_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c
new file mode 100644
index 0000000000..a409e68869
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_slc.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void slc_nthw_set_debug_mode(struct slc_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_slc, n_debug_mode);
+}
+
+struct slc_nthw *slc_nthw_new(void)
+{
+ struct slc_nthw *p = malloc(sizeof(struct slc_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void slc_nthw_delete(struct slc_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int slc_nthw_init(struct slc_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_SLC, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Slc %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_slc = fpga_query_module(p_fpga, MOD_SLC, n_instance);
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_slc, SLC_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_slc, SLC_RCP_DATA);
+ p->mp_rcp_data_tail_slc_en =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_SLC_EN);
+ p->mp_rcp_data_tail_dyn =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_DYN);
+ p->mp_rcp_data_tail_ofs =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_OFS);
+ p->mp_rcp_data_pcap = register_get_field(p->mp_rcp_data, SLC_RCP_DATA_PCAP);
+
+ return 0;
+}
+
+/* RCP */
+void slc_nthw_rcp_select(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void slc_nthw_rcp_cnt(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void slc_nthw_rcp_tail_slc_en(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_slc_en, val);
+}
+
+void slc_nthw_rcp_tail_dyn(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_dyn, val);
+}
+
+void slc_nthw_rcp_tail_ofs(const struct slc_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_ofs, val);
+}
+
+void slc_nthw_rcp_pcap(const struct slc_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_pcap, val);
+}
+
+void slc_nthw_rcp_flush(const struct slc_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h
new file mode 100644
index 0000000000..e0f58e27e4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_SLC_H__
+#define __FLOW_NTHW_SLC_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct slc_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_slc;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+
+ nt_field_t *mp_rcp_data_tail_slc_en;
+ nt_field_t *mp_rcp_data_tail_dyn;
+ nt_field_t *mp_rcp_data_tail_ofs;
+ nt_field_t *mp_rcp_data_pcap;
+};
+
+typedef struct slc_nthw slc_nthw_t;
+
+struct slc_nthw *slc_nthw_new(void);
+void slc_nthw_delete(struct slc_nthw *p);
+int slc_nthw_init(struct slc_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int slc_nthw_setup(struct slc_nthw *p, int n_idx, int n_idx_cnt);
+void slc_nthw_set_debug_mode(struct slc_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void slc_nthw_rcp_select(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_cnt(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_tail_slc_en(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_tail_dyn(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_tail_ofs(const struct slc_nthw *p, int32_t val);
+void slc_nthw_rcp_pcap(const struct slc_nthw *p, uint32_t val);
+void slc_nthw_rcp_flush(const struct slc_nthw *p);
+
+#endif /* __FLOW_NTHW_SLC_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c
new file mode 100644
index 0000000000..f106974bdd
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_slc_lr.h"
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memset */
+
+void slc_lr_nthw_set_debug_mode(struct slc_lr_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_slc_lr, n_debug_mode);
+}
+
+struct slc_lr_nthw *slc_lr_nthw_new(void)
+{
+ struct slc_lr_nthw *p = malloc(sizeof(struct slc_lr_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+
+ return p;
+}
+
+void slc_lr_nthw_delete(struct slc_lr_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int slc_lr_nthw_init(struct slc_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_SLC_LR, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: Slc %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_slc_lr = fpga_query_module(p_fpga, MOD_SLC_LR, n_instance);
+
+ /* RCP */
+ p->mp_rcp_ctrl = module_get_register(p->m_slc_lr, SLC_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, SLC_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_slc_lr, SLC_RCP_DATA);
+ p->mp_rcp_data_tail_slc_en =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_SLC_EN);
+ p->mp_rcp_data_tail_dyn =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_DYN);
+ p->mp_rcp_data_tail_ofs =
+ register_get_field(p->mp_rcp_data, SLC_RCP_DATA_TAIL_OFS);
+ p->mp_rcp_data_pcap = register_get_field(p->mp_rcp_data, SLC_RCP_DATA_PCAP);
+
+ return 0;
+}
+
+/* RCP */
+void slc_lr_nthw_rcp_select(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void slc_lr_nthw_rcp_cnt(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void slc_lr_nthw_rcp_tail_slc_en(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_slc_en, val);
+}
+
+void slc_lr_nthw_rcp_tail_dyn(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_dyn, val);
+}
+
+void slc_lr_nthw_rcp_tail_ofs(const struct slc_lr_nthw *p, int32_t val)
+{
+ field_set_val32(p->mp_rcp_data_tail_ofs, val);
+}
+
+void slc_lr_nthw_rcp_pcap(const struct slc_lr_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_pcap, val);
+}
+
+void slc_lr_nthw_rcp_flush(const struct slc_lr_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h
new file mode 100644
index 0000000000..533f2efbeb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_slc_lr.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_SLC_LR_H__
+#define __FLOW_NTHW_SLC_LR_H__
+
+#include <stdint.h> /* uint32_t */
+#include "nthw_fpga_model.h"
+
+struct slc_lr_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_slc_lr;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+ nt_register_t *mp_rcp_data;
+
+ nt_field_t *mp_rcp_data_tail_slc_en;
+ nt_field_t *mp_rcp_data_tail_dyn;
+ nt_field_t *mp_rcp_data_tail_ofs;
+ nt_field_t *mp_rcp_data_pcap;
+};
+
+typedef struct slc_lr_nthw slc_lr_nthw_t;
+
+struct slc_lr_nthw *slc_lr_nthw_new(void);
+void slc_lr_nthw_delete(struct slc_lr_nthw *p);
+int slc_lr_nthw_init(struct slc_lr_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int slc_lr_nthw_setup(struct slc_lr_nthw *p, int n_idx, int n_idx_cnt);
+void slc_lr_nthw_set_debug_mode(struct slc_lr_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void slc_lr_nthw_rcp_select(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_cnt(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_tail_slc_en(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_tail_dyn(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_tail_ofs(const struct slc_lr_nthw *p, int32_t val);
+void slc_lr_nthw_rcp_pcap(const struct slc_lr_nthw *p, uint32_t val);
+void slc_lr_nthw_rcp_flush(const struct slc_lr_nthw *p);
+
+#endif /* __FLOW_NTHW_SLC_LR_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c
new file mode 100644
index 0000000000..4d28d8cc3d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.c
@@ -0,0 +1,394 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_tx_cpy.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void tx_cpy_nthw_set_debug_mode(struct tx_cpy_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_tx_cpy, n_debug_mode);
+}
+
+struct tx_cpy_nthw *tx_cpy_nthw_new(void)
+{
+ struct tx_cpy_nthw *p = malloc(sizeof(struct tx_cpy_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void tx_cpy_nthw_delete(struct tx_cpy_nthw *p)
+{
+ if (p) {
+ free(p->m_writers);
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int tx_cpy_nthw_init(struct tx_cpy_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_CPY, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TxCpy %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_tx_cpy = fpga_query_module(p_fpga, MOD_TX_CPY, n_instance);
+
+ const int writers_cnt =
+ fpga_get_product_param(p->mp_fpga, NT_TX_CPY_WRITERS, 0);
+ if (writers_cnt < 1)
+ return -1;
+
+ p->m_writers_cnt = (unsigned int)writers_cnt;
+ p->m_writers = calloc(p->m_writers_cnt, sizeof(struct tx_cpy_writers_s));
+ if (p->m_writers == NULL)
+ return -1;
+
+ const int variant =
+ fpga_get_product_param(p->mp_fpga, NT_TX_CPY_VARIANT, 0);
+
+ switch (p->m_writers_cnt) {
+ default:
+ case 6:
+ p->m_writers[5].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_CTRL);
+ p->m_writers[5].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[5].mp_writer_ctrl,
+ CPY_WRITER5_CTRL_ADR);
+ p->m_writers[5].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[5].mp_writer_ctrl,
+ CPY_WRITER5_CTRL_CNT);
+ p->m_writers[5].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_DATA);
+ p->m_writers[5].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_READER_SELECT);
+ p->m_writers[5].mp_writer_data_dyn =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_DYN);
+ p->m_writers[5].mp_writer_data_ofs =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_OFS);
+ p->m_writers[5].mp_writer_data_len =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[5].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[5].mp_writer_data,
+ CPY_WRITER5_DATA_MASK_POINTER);
+ p->m_writers[5].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_MASK_CTRL);
+ p->m_writers[5].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[5].mp_writer_mask_ctrl,
+ CPY_WRITER5_MASK_CTRL_ADR);
+ p->m_writers[5].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[5].mp_writer_mask_ctrl,
+ CPY_WRITER5_MASK_CTRL_CNT);
+ p->m_writers[5].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER5_MASK_DATA);
+ p->m_writers[5].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[5].mp_writer_mask_data,
+ CPY_WRITER5_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 5:
+ p->m_writers[4].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_CTRL);
+ p->m_writers[4].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[4].mp_writer_ctrl, CPY_WRITER4_CTRL_ADR);
+ p->m_writers[4].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[4].mp_writer_ctrl, CPY_WRITER4_CTRL_CNT);
+ p->m_writers[4].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_DATA);
+ p->m_writers[4].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[4].mp_writer_data,
+ CPY_WRITER4_DATA_READER_SELECT);
+ p->m_writers[4].mp_writer_data_dyn =
+ register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_DYN);
+ p->m_writers[4].mp_writer_data_ofs =
+ register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_OFS);
+ p->m_writers[4].mp_writer_data_len =
+ register_get_field(p->m_writers[4].mp_writer_data, CPY_WRITER4_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[4].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[4].mp_writer_data,
+ CPY_WRITER4_DATA_MASK_POINTER);
+ p->m_writers[4].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_MASK_CTRL);
+ p->m_writers[4].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[4].mp_writer_mask_ctrl,
+ CPY_WRITER4_MASK_CTRL_ADR);
+ p->m_writers[4].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[4].mp_writer_mask_ctrl,
+ CPY_WRITER4_MASK_CTRL_CNT);
+ p->m_writers[4].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER4_MASK_DATA);
+ p->m_writers[4].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[4].mp_writer_mask_data,
+ CPY_WRITER4_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 4:
+ p->m_writers[3].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_CTRL);
+ p->m_writers[3].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[3].mp_writer_ctrl, CPY_WRITER3_CTRL_ADR);
+ p->m_writers[3].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[3].mp_writer_ctrl, CPY_WRITER3_CTRL_CNT);
+ p->m_writers[3].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_DATA);
+ p->m_writers[3].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[3].mp_writer_data,
+ CPY_WRITER3_DATA_READER_SELECT);
+ p->m_writers[3].mp_writer_data_dyn =
+ register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_DYN);
+ p->m_writers[3].mp_writer_data_ofs =
+ register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_OFS);
+ p->m_writers[3].mp_writer_data_len =
+ register_get_field(p->m_writers[3].mp_writer_data, CPY_WRITER3_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[3].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[3].mp_writer_data,
+ CPY_WRITER3_DATA_MASK_POINTER);
+ p->m_writers[3].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_MASK_CTRL);
+ p->m_writers[3].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[3].mp_writer_mask_ctrl,
+ CPY_WRITER3_MASK_CTRL_ADR);
+ p->m_writers[3].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[3].mp_writer_mask_ctrl,
+ CPY_WRITER3_MASK_CTRL_CNT);
+ p->m_writers[3].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER3_MASK_DATA);
+ p->m_writers[3].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[3].mp_writer_mask_data,
+ CPY_WRITER3_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 3:
+ p->m_writers[2].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_CTRL);
+ p->m_writers[2].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[2].mp_writer_ctrl, CPY_WRITER2_CTRL_ADR);
+ p->m_writers[2].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[2].mp_writer_ctrl, CPY_WRITER2_CTRL_CNT);
+ p->m_writers[2].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_DATA);
+ p->m_writers[2].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[2].mp_writer_data,
+ CPY_WRITER2_DATA_READER_SELECT);
+ p->m_writers[2].mp_writer_data_dyn =
+ register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_DYN);
+ p->m_writers[2].mp_writer_data_ofs =
+ register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_OFS);
+ p->m_writers[2].mp_writer_data_len =
+ register_get_field(p->m_writers[2].mp_writer_data, CPY_WRITER2_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[2].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[2].mp_writer_data,
+ CPY_WRITER2_DATA_MASK_POINTER);
+ p->m_writers[2].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_MASK_CTRL);
+ p->m_writers[2].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[2].mp_writer_mask_ctrl,
+ CPY_WRITER2_MASK_CTRL_ADR);
+ p->m_writers[2].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[2].mp_writer_mask_ctrl,
+ CPY_WRITER2_MASK_CTRL_CNT);
+ p->m_writers[2].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER2_MASK_DATA);
+ p->m_writers[2].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[2].mp_writer_mask_data,
+ CPY_WRITER2_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 2:
+ p->m_writers[1].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_CTRL);
+ p->m_writers[1].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[1].mp_writer_ctrl, CPY_WRITER1_CTRL_ADR);
+ p->m_writers[1].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[1].mp_writer_ctrl, CPY_WRITER1_CTRL_CNT);
+ p->m_writers[1].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_DATA);
+ p->m_writers[1].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[1].mp_writer_data,
+ CPY_WRITER1_DATA_READER_SELECT);
+ p->m_writers[1].mp_writer_data_dyn =
+ register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_DYN);
+ p->m_writers[1].mp_writer_data_ofs =
+ register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_OFS);
+ p->m_writers[1].mp_writer_data_len =
+ register_get_field(p->m_writers[1].mp_writer_data, CPY_WRITER1_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[1].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[1].mp_writer_data,
+ CPY_WRITER1_DATA_MASK_POINTER);
+ p->m_writers[1].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_MASK_CTRL);
+ p->m_writers[1].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[1].mp_writer_mask_ctrl,
+ CPY_WRITER1_MASK_CTRL_ADR);
+ p->m_writers[1].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[1].mp_writer_mask_ctrl,
+ CPY_WRITER1_MASK_CTRL_CNT);
+ p->m_writers[1].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER1_MASK_DATA);
+ p->m_writers[1].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[1].mp_writer_mask_data,
+ CPY_WRITER1_MASK_DATA_BYTE_MASK);
+ }
+ /* Fallthrough */
+ case 1:
+ p->m_writers[0].mp_writer_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_CTRL);
+ p->m_writers[0].mp_writer_ctrl_addr =
+ register_get_field(p->m_writers[0].mp_writer_ctrl, CPY_WRITER0_CTRL_ADR);
+ p->m_writers[0].mp_writer_ctrl_cnt =
+ register_get_field(p->m_writers[0].mp_writer_ctrl, CPY_WRITER0_CTRL_CNT);
+ p->m_writers[0].mp_writer_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_DATA);
+ p->m_writers[0].mp_writer_data_reader_select =
+ register_get_field(p->m_writers[0].mp_writer_data,
+ CPY_WRITER0_DATA_READER_SELECT);
+ p->m_writers[0].mp_writer_data_dyn =
+ register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_DYN);
+ p->m_writers[0].mp_writer_data_ofs =
+ register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_OFS);
+ p->m_writers[0].mp_writer_data_len =
+ register_get_field(p->m_writers[0].mp_writer_data, CPY_WRITER0_DATA_LEN);
+ if (variant != 0) {
+ p->m_writers[0].mp_writer_data_mask_pointer =
+ register_get_field(p->m_writers[0].mp_writer_data,
+ CPY_WRITER0_DATA_MASK_POINTER);
+ p->m_writers[0].mp_writer_mask_ctrl =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_MASK_CTRL);
+ p->m_writers[0].mp_writer_mask_ctrl_addr =
+ register_get_field(p->m_writers[0].mp_writer_mask_ctrl,
+ CPY_WRITER0_MASK_CTRL_ADR);
+ p->m_writers[0].mp_writer_mask_ctrl_cnt =
+ register_get_field(p->m_writers[0].mp_writer_mask_ctrl,
+ CPY_WRITER0_MASK_CTRL_CNT);
+ p->m_writers[0].mp_writer_mask_data =
+ module_get_register(p->m_tx_cpy, CPY_WRITER0_MASK_DATA);
+ p->m_writers[0].mp_writer_mask_data_byte_mask =
+ register_get_field(p->m_writers[0].mp_writer_mask_data,
+ CPY_WRITER0_MASK_DATA_BYTE_MASK);
+ }
+ break;
+ case 0:
+ return -1;
+ }
+
+ return 0;
+}
+
+void tx_cpy_nthw_writer_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_ctrl_addr, val);
+}
+
+void tx_cpy_nthw_writer_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_ctrl_cnt, val);
+}
+
+void tx_cpy_nthw_writer_reader_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_reader_select, val);
+}
+
+void tx_cpy_nthw_writer_dyn(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_dyn, val);
+}
+
+void tx_cpy_nthw_writer_ofs(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_ofs, val);
+}
+
+void tx_cpy_nthw_writer_len(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_data_len, val);
+}
+
+void tx_cpy_nthw_writer_mask_pointer(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_data_mask_pointer);
+ field_set_val32(p->m_writers[index].mp_writer_data_mask_pointer, val);
+}
+
+void tx_cpy_nthw_writer_flush(const struct tx_cpy_nthw *p, unsigned int index)
+{
+ assert(index < p->m_writers_cnt);
+ register_flush(p->m_writers[index].mp_writer_ctrl, 1);
+ register_flush(p->m_writers[index].mp_writer_data, 1);
+}
+
+void tx_cpy_nthw_writer_mask_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_ctrl_addr);
+ field_set_val32(p->m_writers[index].mp_writer_mask_ctrl_addr, val);
+}
+
+void tx_cpy_nthw_writer_mask_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_ctrl_cnt);
+ field_set_val32(p->m_writers[index].mp_writer_mask_ctrl_cnt, val);
+}
+
+void tx_cpy_nthw_writer_mask(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_data_byte_mask);
+ field_set_val32(p->m_writers[index].mp_writer_mask_data_byte_mask, val);
+}
+
+void tx_cpy_nthw_writer_mask_flush(const struct tx_cpy_nthw *p, unsigned int index)
+{
+ assert(index < p->m_writers_cnt);
+ assert(p->m_writers[index].mp_writer_mask_ctrl);
+ assert(p->m_writers[index].mp_writer_mask_data);
+ register_flush(p->m_writers[index].mp_writer_mask_ctrl, 1);
+ register_flush(p->m_writers[index].mp_writer_mask_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h
new file mode 100644
index 0000000000..f97983b29a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_cpy.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_TX_CPY_H__
+#define __FLOW_NTHW_TX_CPY_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct tx_cpy_writers_s {
+ nt_register_t *mp_writer_ctrl;
+ nt_field_t *mp_writer_ctrl_addr;
+ nt_field_t *mp_writer_ctrl_cnt;
+
+ nt_register_t *mp_writer_data;
+ nt_field_t *mp_writer_data_reader_select;
+ nt_field_t *mp_writer_data_dyn;
+ nt_field_t *mp_writer_data_ofs;
+ nt_field_t *mp_writer_data_len;
+ nt_field_t *mp_writer_data_mask_pointer;
+
+ nt_register_t *mp_writer_mask_ctrl;
+ nt_field_t *mp_writer_mask_ctrl_addr;
+ nt_field_t *mp_writer_mask_ctrl_cnt;
+
+ nt_register_t *mp_writer_mask_data;
+ nt_field_t *mp_writer_mask_data_byte_mask;
+};
+
+struct tx_cpy_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_tx_cpy;
+
+ unsigned int m_writers_cnt;
+ struct tx_cpy_writers_s *m_writers;
+};
+
+struct tx_cpy_nthw *tx_cpy_nthw_new(void);
+void tx_cpy_nthw_delete(struct tx_cpy_nthw *p);
+int tx_cpy_nthw_init(struct tx_cpy_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int tx_cpy_nthw_setup(struct tx_cpy_nthw *p, int n_idx, int n_idx_cnt);
+void tx_cpy_nthw_set_debug_mode(struct tx_cpy_nthw *p, unsigned int n_debug_mode);
+
+void tx_cpy_nthw_writer_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_reader_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_dyn(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_ofs(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_len(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask_pointer(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_flush(const struct tx_cpy_nthw *p, unsigned int index);
+
+void tx_cpy_nthw_writer_mask_select(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask_cnt(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask(const struct tx_cpy_nthw *p, unsigned int index,
+ uint32_t val);
+void tx_cpy_nthw_writer_mask_flush(const struct tx_cpy_nthw *p, unsigned int index);
+
+#endif /* __FLOW_NTHW_TX_CPY_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c
new file mode 100644
index 0000000000..998c3613ee
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.c
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_tx_ins.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void tx_ins_nthw_set_debug_mode(struct tx_ins_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_tx_ins, n_debug_mode);
+}
+
+struct tx_ins_nthw *tx_ins_nthw_new(void)
+{
+ struct tx_ins_nthw *p = malloc(sizeof(struct tx_ins_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void tx_ins_nthw_delete(struct tx_ins_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int tx_ins_nthw_init(struct tx_ins_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_INS, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TxIns %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_tx_ins = fpga_query_module(p_fpga, MOD_TX_INS, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_tx_ins, INS_RCP_CTRL);
+ p->mp_rcp_addr = register_get_field(p->mp_rcp_ctrl, INS_RCP_CTRL_ADR);
+ p->mp_rcp_cnt = register_get_field(p->mp_rcp_ctrl, INS_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_tx_ins, INS_RCP_DATA);
+ p->mp_rcp_data_dyn = register_get_field(p->mp_rcp_data, INS_RCP_DATA_DYN);
+ p->mp_rcp_data_ofs = register_get_field(p->mp_rcp_data, INS_RCP_DATA_OFS);
+ p->mp_rcp_data_len = register_get_field(p->mp_rcp_data, INS_RCP_DATA_LEN);
+
+ return 0;
+}
+
+void tx_ins_nthw_rcp_select(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_addr, val);
+}
+
+void tx_ins_nthw_rcp_cnt(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_cnt, val);
+}
+
+void tx_ins_nthw_rcp_dyn(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dyn, val);
+}
+
+void tx_ins_nthw_rcp_ofs(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs, val);
+}
+
+void tx_ins_nthw_rcp_len(const struct tx_ins_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len, val);
+}
+
+void tx_ins_nthw_rcp_flush(const struct tx_ins_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h
new file mode 100644
index 0000000000..813bd30c62
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_ins.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_TX_INS_H__
+#define __FLOW_NTHW_TX_INS_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct tx_ins_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_tx_ins;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_addr;
+ nt_field_t *mp_rcp_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_dyn;
+ nt_field_t *mp_rcp_data_ofs;
+ nt_field_t *mp_rcp_data_len;
+};
+
+struct tx_ins_nthw *tx_ins_nthw_new(void);
+void tx_ins_nthw_delete(struct tx_ins_nthw *p);
+int tx_ins_nthw_init(struct tx_ins_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int tx_ins_nthw_setup(struct tx_ins_nthw *p, int n_idx, int n_idx_cnt);
+void tx_ins_nthw_set_debug_mode(struct tx_ins_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void tx_ins_nthw_rcp_select(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_cnt(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_dyn(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_ofs(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_len(const struct tx_ins_nthw *p, uint32_t val);
+void tx_ins_nthw_rcp_flush(const struct tx_ins_nthw *p);
+
+#endif /* __FLOW_NTHW_TX_INS_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c
new file mode 100644
index 0000000000..5e7e26f74d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "flow_nthw_tx_rpl.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void tx_rpl_nthw_set_debug_mode(struct tx_rpl_nthw *p, unsigned int n_debug_mode)
+{
+ module_set_debug_mode(p->m_tx_rpl, n_debug_mode);
+}
+
+struct tx_rpl_nthw *tx_rpl_nthw_new(void)
+{
+ struct tx_rpl_nthw *p = malloc(sizeof(struct tx_rpl_nthw));
+
+ if (p)
+ (void)memset(p, 0, sizeof(*p));
+ return p;
+}
+
+void tx_rpl_nthw_delete(struct tx_rpl_nthw *p)
+{
+ if (p) {
+ (void)memset(p, 0, sizeof(*p));
+ free(p);
+ }
+}
+
+int tx_rpl_nthw_init(struct tx_rpl_nthw *p, nt_fpga_t *p_fpga, int n_instance)
+{
+ const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+ nt_module_t *p_mod = fpga_query_module(p_fpga, MOD_TX_RPL, n_instance);
+
+ assert(n_instance >= 0 && n_instance < 256);
+
+ if (p == NULL)
+ return p_mod == NULL ? -1 : 0;
+
+ if (p_mod == NULL) {
+ NT_LOG(ERR, NTHW, "%s: TxRpl %d: no such instance\n",
+ p_adapter_id_str, n_instance);
+ return -1;
+ }
+
+ p->mp_fpga = p_fpga;
+ p->m_physical_adapter_no = (uint8_t)n_instance;
+ p->m_tx_rpl = fpga_query_module(p_fpga, MOD_TX_RPL, n_instance);
+
+ p->mp_rcp_ctrl = module_get_register(p->m_tx_rpl, RPL_RCP_CTRL);
+ p->mp_rcp_ctrl_addr = register_get_field(p->mp_rcp_ctrl, RPL_RCP_CTRL_ADR);
+ p->mp_rcp_ctrl_cnt = register_get_field(p->mp_rcp_ctrl, RPL_RCP_CTRL_CNT);
+ p->mp_rcp_data = module_get_register(p->m_tx_rpl, RPL_RCP_DATA);
+ p->mp_rcp_data_dyn = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_DYN);
+ p->mp_rcp_data_ofs = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_OFS);
+ p->mp_rcp_data_len = register_get_field(p->mp_rcp_data, RPL_RCP_DATA_LEN);
+ p->mp_rcp_data_rpl_ptr =
+ register_get_field(p->mp_rcp_data, RPL_RCP_DATA_RPL_PTR);
+ p->mp_rcp_data_ext_prio =
+ register_get_field(p->mp_rcp_data, RPL_RCP_DATA_EXT_PRIO);
+
+ p->mp_ext_ctrl = module_get_register(p->m_tx_rpl, RPL_EXT_CTRL);
+ p->mp_ext_ctrl_addr = register_get_field(p->mp_ext_ctrl, RPL_EXT_CTRL_ADR);
+ p->mp_ext_ctrl_cnt = register_get_field(p->mp_ext_ctrl, RPL_EXT_CTRL_CNT);
+ p->mp_ext_data = module_get_register(p->m_tx_rpl, RPL_EXT_DATA);
+ p->mp_ext_data_rpl_ptr =
+ register_get_field(p->mp_ext_data, RPL_EXT_DATA_RPL_PTR);
+
+ p->mp_rpl_ctrl = module_get_register(p->m_tx_rpl, RPL_RPL_CTRL);
+ p->mp_rpl_ctrl_addr = register_get_field(p->mp_rpl_ctrl, RPL_RPL_CTRL_ADR);
+ p->mp_rpl_ctrl_cnt = register_get_field(p->mp_rpl_ctrl, RPL_RPL_CTRL_CNT);
+ p->mp_rpl_data = module_get_register(p->m_tx_rpl, RPL_RPL_DATA);
+ p->mp_rpl_data_value = register_get_field(p->mp_rpl_data, RPL_RPL_DATA_VALUE);
+
+ return 0;
+}
+
+void tx_rpl_nthw_rcp_select(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_addr, val);
+}
+
+void tx_rpl_nthw_rcp_cnt(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_ctrl_cnt, val);
+}
+
+void tx_rpl_nthw_rcp_dyn(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_dyn, val);
+}
+
+void tx_rpl_nthw_rcp_ofs(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ofs, val);
+}
+
+void tx_rpl_nthw_rcp_len(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_len, val);
+}
+
+void tx_rpl_nthw_rcp_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_rpl_ptr, val);
+}
+
+void tx_rpl_nthw_rcp_ext_prio(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rcp_data_ext_prio, val);
+}
+
+void tx_rpl_nthw_rcp_flush(const struct tx_rpl_nthw *p)
+{
+ register_flush(p->mp_rcp_ctrl, 1);
+ register_flush(p->mp_rcp_data, 1);
+}
+
+void tx_rpl_nthw_ext_select(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ext_ctrl_addr, val);
+}
+
+void tx_rpl_nthw_ext_cnt(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ext_ctrl_cnt, val);
+}
+
+void tx_rpl_nthw_ext_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_ext_data_rpl_ptr, val);
+}
+
+void tx_rpl_nthw_ext_flush(const struct tx_rpl_nthw *p)
+{
+ register_flush(p->mp_ext_ctrl, 1);
+ register_flush(p->mp_ext_data, 1);
+}
+
+void tx_rpl_nthw_rpl_select(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rpl_ctrl_addr, val);
+}
+
+void tx_rpl_nthw_rpl_cnt(const struct tx_rpl_nthw *p, uint32_t val)
+{
+ field_set_val32(p->mp_rpl_ctrl_cnt, val);
+}
+
+void tx_rpl_nthw_rpl_value(const struct tx_rpl_nthw *p, const uint32_t *val)
+{
+ field_set_val(p->mp_rpl_data_value, val, 4);
+}
+
+void tx_rpl_nthw_rpl_flush(const struct tx_rpl_nthw *p)
+{
+ register_flush(p->mp_rpl_ctrl, 1);
+ register_flush(p->mp_rpl_data, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h
new file mode 100644
index 0000000000..e5f724361b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_filter/flow_nthw_tx_rpl.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_NTHW_TX_RPL_H__
+#define __FLOW_NTHW_TX_RPL_H__
+
+#include <stdint.h>
+#include "nthw_fpga_model.h"
+
+struct tx_rpl_nthw {
+ uint8_t m_physical_adapter_no;
+ nt_fpga_t *mp_fpga;
+
+ nt_module_t *m_tx_rpl;
+
+ nt_register_t *mp_rcp_ctrl;
+ nt_field_t *mp_rcp_ctrl_addr;
+ nt_field_t *mp_rcp_ctrl_cnt;
+
+ nt_register_t *mp_rcp_data;
+ nt_field_t *mp_rcp_data_dyn;
+ nt_field_t *mp_rcp_data_ofs;
+ nt_field_t *mp_rcp_data_len;
+ nt_field_t *mp_rcp_data_rpl_ptr;
+ nt_field_t *mp_rcp_data_ext_prio;
+
+ nt_register_t *mp_ext_ctrl;
+ nt_field_t *mp_ext_ctrl_addr;
+ nt_field_t *mp_ext_ctrl_cnt;
+
+ nt_register_t *mp_ext_data;
+ nt_field_t *mp_ext_data_rpl_ptr;
+
+ nt_register_t *mp_rpl_ctrl;
+ nt_field_t *mp_rpl_ctrl_addr;
+ nt_field_t *mp_rpl_ctrl_cnt;
+
+ nt_register_t *mp_rpl_data;
+ nt_field_t *mp_rpl_data_value;
+};
+
+struct tx_rpl_nthw *tx_rpl_nthw_new(void);
+void tx_rpl_nthw_delete(struct tx_rpl_nthw *p);
+int tx_rpl_nthw_init(struct tx_rpl_nthw *p, nt_fpga_t *p_fpga, int n_instance);
+
+int tx_rpl_nthw_setup(struct tx_rpl_nthw *p, int n_idx, int n_idx_cnt);
+void tx_rpl_nthw_set_debug_mode(struct tx_rpl_nthw *p, unsigned int n_debug_mode);
+
+/* RCP */
+void tx_rpl_nthw_rcp_select(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_cnt(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_dyn(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_ofs(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_len(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_ext_prio(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rcp_flush(const struct tx_rpl_nthw *p);
+
+void tx_rpl_nthw_ext_select(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_ext_cnt(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_ext_rpl_ptr(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_ext_flush(const struct tx_rpl_nthw *p);
+
+void tx_rpl_nthw_rpl_select(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rpl_cnt(const struct tx_rpl_nthw *p, uint32_t val);
+void tx_rpl_nthw_rpl_value(const struct tx_rpl_nthw *p, const uint32_t *val);
+void tx_rpl_nthw_rpl_flush(const struct tx_rpl_nthw *p);
+
+#endif /* __FLOW_NTHW_TX_RPL_H__ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH v2 5/8] net/ntnic: adds FPGA abstraction layer
2023-08-17 14:43 ` [PATCH v2 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (2 preceding siblings ...)
2023-08-17 14:43 ` [PATCH v2 4/8] net/ntnic: adds flow related FPGA functionality Mykola Kostenok
@ 2023-08-17 14:43 ` Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 6/8] net/ntnic: adds flow logic Mykola Kostenok
` (3 subsequent siblings)
7 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-17 14:43 UTC (permalink / raw)
To: dev, mko-plv; +Cc: ckm
From: Christian Koue Muf <ckm@napatech.com>
The FPGA abstraction layer limits the need to rewrite flow logic
when new FPGA modules are created.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
v2:
* Fixed compilation with Fedora 38
* Fixed WARNING:TYPO_SPELLING
---
drivers/net/ntnic/meson.build | 21 +
.../ntnic/nthw/flow_api/flow_api_actions.c | 205 ++
.../ntnic/nthw/flow_api/flow_api_actions.h | 284 +++
.../ntnic/nthw/flow_api/flow_api_backend.c | 182 ++
.../ntnic/nthw/flow_api/flow_api_backend.h | 1818 +++++++++++++++++
.../net/ntnic/nthw/flow_api/flow_api_engine.h | 475 +++++
.../ntnic/nthw/flow_api/flow_api_nic_setup.h | 32 +
.../nthw/flow_api/flow_engine/flow_group.c | 125 ++
.../nthw/flow_api/flow_engine/flow_hasher.c | 213 ++
.../nthw/flow_api/flow_engine/flow_hasher.h | 20 +
.../nthw/flow_api/flow_engine/flow_kcc.c | 434 ++++
.../ntnic/nthw/flow_api/flow_engine/flow_km.c | 1434 +++++++++++++
.../nthw/flow_api/flow_engine/flow_tunnel.c | 787 +++++++
.../ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c | 1789 ++++++++++++++++
.../nthw/flow_api/hw_mod/hw_mod_cat_v18.h | 138 ++
.../nthw/flow_api/hw_mod/hw_mod_cat_v21.h | 88 +
.../nthw/flow_api/hw_mod/hw_mod_cat_v22.h | 83 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c | 1099 ++++++++++
.../nthw/flow_api/hw_mod/hw_mod_flm_v17.h | 274 +++
.../nthw/flow_api/hw_mod/hw_mod_flm_v20.h | 102 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c | 195 ++
.../nthw/flow_api/hw_mod/hw_mod_hsh_v5.h | 36 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c | 178 ++
.../nthw/flow_api/hw_mod/hw_mod_hst_v2.h | 32 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c | 271 +++
.../nthw/flow_api/hw_mod/hw_mod_ioa_v4.h | 36 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_km.c | 629 ++++++
.../ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h | 93 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c | 219 ++
.../nthw/flow_api/hw_mod/hw_mod_pdb_v9.h | 39 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c | 348 ++++
.../nthw/flow_api/hw_mod/hw_mod_qsl_v7.h | 45 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c | 112 +
.../nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h | 20 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c | 358 ++++
.../nthw/flow_api/hw_mod/hw_mod_roa_v6.h | 49 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c | 132 ++
.../nthw/flow_api/hw_mod/hw_mod_slc_lr.c | 132 ++
.../nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h | 19 +
.../nthw/flow_api/hw_mod/hw_mod_slc_v1.h | 19 +
.../ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c | 983 +++++++++
.../nthw/flow_api/hw_mod/hw_mod_tpe_v1.h | 103 +
.../nthw/flow_api/hw_mod/hw_mod_tpe_v2.h | 37 +
.../nthw/flow_api/stream_binary_flow_api.h | 697 +++++++
44 files changed, 14385 insertions(+)
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_actions.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_backend.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_engine.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index c184d5d4b5..387481bb4a 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -17,6 +17,7 @@ includes = [
include_directories('nthw'),
include_directories('nthw/core'),
include_directories('nthw/supported'),
+ include_directories('nthw/flow_api'),
include_directories('nthw/flow_filter'),
include_directories('sensors'),
include_directories('sensors/avr_sensors'),
@@ -59,6 +60,26 @@ sources = files(
'nthw/core/nthw_spim.c',
'nthw/core/nthw_spis.c',
'nthw/core/nthw_tsm.c',
+ 'nthw/flow_api/flow_api_actions.c',
+ 'nthw/flow_api/flow_api_backend.c',
+ 'nthw/flow_api/flow_engine/flow_group.c',
+ 'nthw/flow_api/flow_engine/flow_hasher.c',
+ 'nthw/flow_api/flow_engine/flow_kcc.c',
+ 'nthw/flow_api/flow_engine/flow_km.c',
+ 'nthw/flow_api/flow_engine/flow_tunnel.c',
+ 'nthw/flow_api/hw_mod/hw_mod_cat.c',
+ 'nthw/flow_api/hw_mod/hw_mod_flm.c',
+ 'nthw/flow_api/hw_mod/hw_mod_hsh.c',
+ 'nthw/flow_api/hw_mod/hw_mod_hst.c',
+ 'nthw/flow_api/hw_mod/hw_mod_ioa.c',
+ 'nthw/flow_api/hw_mod/hw_mod_km.c',
+ 'nthw/flow_api/hw_mod/hw_mod_pdb.c',
+ 'nthw/flow_api/hw_mod/hw_mod_qsl.c',
+ 'nthw/flow_api/hw_mod/hw_mod_rmc.c',
+ 'nthw/flow_api/hw_mod/hw_mod_roa.c',
+ 'nthw/flow_api/hw_mod/hw_mod_slc.c',
+ 'nthw/flow_api/hw_mod/hw_mod_slc_lr.c',
+ 'nthw/flow_api/hw_mod/hw_mod_tpe.c',
'nthw/flow_filter/flow_nthw_cat.c',
'nthw/flow_filter/flow_nthw_csu.c',
'nthw/flow_filter/flow_nthw_flm.c',
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c
new file mode 100644
index 0000000000..945ab7d743
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.c
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+
+#include "ntlog.h"
+
+#include "stream_binary_flow_api.h"
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index,
+ struct tunnel_header_s *tun)
+{
+ int err = 0;
+ int num_writes = (tun->ip_version == 4) ? 4 : 8;
+
+ /*
+ * Write 4 * 4 words = 64 bytes (IPv4) or 8 * 4 words = 128 bytes (IPv6)
+ */
+ for (int i = 0; (i < num_writes) && !err; i++) {
+ for (int ii = 0; (ii < 4) && !err; ii++) {
+ /* must write each 4 words backwards! */
+ err |= hw_mod_roa_tunhdr_set(be, HW_ROA_TUNHDR,
+ index, i * 4 + ii,
+ ntohl(tun->d.hdr32[(i + 1) * 4 - ii - 1]));
+ }
+ }
+
+ return err;
+}
+
+int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions)
+{
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PRESET_ALL, index, 0);
+ /*
+ * If tunnel header specified
+ */
+ int tun_len = get_roa_tunhdr_len(color_actions);
+
+ if (tun_len) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_LEN, index,
+ tun_len);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TUN_TYPE, index,
+ roa_get_tun_type(color_actions));
+
+ /* set the total tunnel IP header length */
+ if (get_roa_tun_ip_type(color_actions) == 1) {
+ /* IPv6 */
+ if ((size_t)tun_len > (sizeof(struct flow_elem_eth) +
+ sizeof(struct flow_elem_ipv6))) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD, index, 1);
+ /* tunnel header length excludes the IPv6 header itself */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index,
+ (uint32_t)(tun_len -
+ (sizeof(struct flow_elem_eth) +
+ sizeof(struct flow_elem_ipv6))));
+ }
+ } else {
+ /* IPv4 */
+ if ((size_t)tun_len > sizeof(struct flow_elem_eth)) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_UPD,
+ index, 1);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPTL_PRECALC, index,
+ (uint32_t)(tun_len -
+ sizeof(struct flow_elem_eth)));
+ }
+ }
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IP_TYPE, index,
+ get_roa_tun_ip_type(color_actions));
+
+ if (get_roa_tun_ip_type(color_actions) == 1) {
+ /* IPv6 - Do not update the IP checksum in the tunnel header */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD, index,
+ 0);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC,
+ index, 0);
+ } else {
+ /* IPv4 */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_UPD,
+ index, 1);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_IPCS_PRECALC,
+ index,
+ get_roa_tun_ip_csum(color_actions));
+ }
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD,
+ index, 1);
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_PUSH_TUNNEL, index, 1);
+ }
+
+ /* bypass must be > 0 or recirculate_port >= 0 - bypass wins */
+ uint8_t recirculate_bypass = roa_get_recirc_bypass_port(color_actions);
+
+ if (recirculate_bypass) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index,
+ recirculate_bypass);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE, index, 1);
+
+ } else {
+ int32_t recirculate_port = roa_get_recirc_port(color_actions);
+
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS, index,
+ 255);
+
+ if (recirculate_port >= 0) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_PORT,
+ index, recirculate_port);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE,
+ index, 1);
+ }
+ }
+
+ uint8_t tx = roa_get_tx(color_actions);
+
+ if (tx) {
+ if (tx == DESTINATION_TX_PHY0) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,
+ index, ROA_TX_PHY0);
+ } else if (tx == DESTINATION_TX_PHY1) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,
+ index, ROA_TX_PHY1);
+ } else if (tx == (DESTINATION_TX_PHY0 | DESTINATION_TX_PHY1)) {
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_TX_LAG_IX,
+ index, ROA_TX_PHY0);
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRC_BYPASS,
+ index, 0x81); /* port 1 - only port left */
+ hw_mod_roa_tuncfg_set(be, HW_ROA_TUNCFG_RECIRCULATE,
+ index, 1);
+
+ } else {
+ return -1; /* ERR */
+ }
+ }
+
+ /*
+ * Special IOA memory that contains ROA information - bad FPGA design
+ */
+ if (tx || tun_len) {
+ if (be->ioa.ver > 3 && tun_len &&
+ get_roa_tun_ip_type(color_actions) == 1) {
+ /* IPv6 VxLAN tunnel. Select EPP recipe 2 */
+ hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL,
+ index, 2);
+ } else {
+ /* IPv4 VxLAN tunnel or no tunnel (select recipe 1 or 0) */
+ hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_PUSH_TUNNEL,
+ index, !!tun_len);
+ }
+ hw_mod_ioa_roa_epp_set(be, HW_IOA_ROA_EPP_TX_PORT, index, tx);
+ }
+
+ return 0;
+}
+
+int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions)
+{
+ if (color_actions & ioa_set_vxlan_pop(0)) {
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_TUNNEL_POP, index, 1);
+ NT_LOG(DBG, FILTER, "Pop outer Tunnel (Vxlan)\n");
+ }
+
+ if (color_actions & ioa_set_vlan_pop(0)) {
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_POP, index, 1);
+ NT_LOG(DBG, FILTER, "Pop outer Vlan\n");
+ }
+
+ int tpid_sel = ioa_get_tpid_sel(color_actions);
+
+ if (color_actions & ioa_set_vlan_push(0, 0)) {
+ uint16_t tci = ioa_get_vlan_tci(color_actions);
+
+ NT_LOG(DBG, FILTER, "Push Vlan with TPID/TCI %04x/%04x\n",
+ tpid_sel ? 0x88a8 : 0x8100, tci);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_VID, index,
+ tci & 0x0FFF);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_DEI, index,
+ (tci >> 12) & 0x1);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PCP, index,
+ (tci >> 13) & 0x7);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_PUSH, index, 1);
+ }
+
+ int queue = ioa_get_queue(color_actions);
+
+ if (queue >= 0) {
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_OVERRIDE_EN, index, 1);
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_QUEUE_ID, index, queue);
+ }
+
+ hw_mod_ioa_rcp_set(be, HW_IOA_RCP_VLAN_TPID_SEL, index, tpid_sel);
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h
new file mode 100644
index 0000000000..400066e817
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_actions.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_ACTIONS_H_
+#define _FLOW_ACTIONS_H_
+
+struct flow_api_backend_s;
+struct tunnel_header_s;
+
+#define MAX_COLOR_FLOW_STATS 0x400
+
+#define ROA_RECIRC_BYPASS_PHY_OFFSET 0x80
+#define MAX_REPLICATION_PORTS 2
+
+enum {
+ DESTINATION_TX_NONE = 0,
+ DESTINATION_TX_PHY0 = 1,
+ DESTINATION_TX_PHY1 = 2
+};
+
+enum { TUN_IPV4 = 0, TUN_IPV6 };
+
+enum {
+ VLAN_TPID_802_1Q = 0,
+ VLAN_TPID_802_1AD,
+ VLAN_TPID_CUSTOM_0,
+ VLAN_TPID_CUSTOM_1
+};
+
+enum { ROA_TX_NO_RETRANSMIT = 0, ROA_TX_PHY0, ROA_TX_PHY1, ROA_TX_RESERVED };
+
+/*
+ * before version 6 of QSL
+ */
+#if (MAX_COLOR_FLOW_STATS == 0x4000)
+#define MAX_HW_FLOW_STATS_OLD 0x3fff
+
+#else
+#if (MAX_COLOR_FLOW_STATS == 0x400)
+#define MAX_HW_FLOW_STATS_OLD 0x03ff
+#else
+#error *** Unsupported number of color statistics counter ***
+#endif
+#endif
+
+/*
+ * OLD behavior substituted from 4.1+
+ *
+ * 13:0 Mark (color) 16384 flow stats
+ * 21:14 IOA index 256 entries
+ * 29:22 ROA index 256 entries
+ * 31:30 1 to indicate this layout
+ * or
+ * 9:0 Mark (color) 1024 flow stats
+ * 19:10 IOA index 1024 entries
+ * 29:20 ROA index 1024 entries
+ * 31:30 0 to indicate this layout
+ */
+static inline uint32_t set_color_action_old(uint32_t color, uint32_t ioa_rcp,
+ uint32_t roa_rcp)
+{
+#if (MAX_COLOR_FLOW_STATS == 0x400)
+ uint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) |
+ ((ioa_rcp & 0x3ff) << 10) |
+ ((roa_rcp & 0x3ff) << 20) | (0 << 30);
+#else
+ uint32_t color_action = (color & MAX_HW_FLOW_STATS_OLD) |
+ ((ioa_rcp & 0xff) << 14) |
+ ((roa_rcp & 0xff) << 22) | (1 << 30);
+#endif
+ return color_action;
+}
+
+#define BITMASK(a, b) ((1U << ((a) - (b) + 1)) - 1)
+
+/*
+ * 9:0 Mark (color) 1024 flow stats
+ * 17:10 IOA index 256 entries
+ * 25:18 ROA index 256 entries
+ * 30:26 QSL and HSH 32 recipes indexable
+ * 31:31 CAO implicitly when color_action is set
+ */
+#define FLOW_MARK_MASK BITMASK(9, 0)
+#define IOA_RCP_MASK BITMASK(17, 10)
+#define ROA_RCP_MASK BITMASK(25, 18)
+#define QSL_HSH_MASK BITMASK(30, 26)
+
+static inline uint32_t set_color_action(uint32_t mark, uint32_t ioa_rcp,
+ uint32_t roa_rcp, uint32_t qsl_hsh)
+{
+ uint32_t color_action = (mark & FLOW_MARK_MASK) |
+ ((ioa_rcp & IOA_RCP_MASK) << 10) |
+ ((roa_rcp & ROA_RCP_MASK) << 18) |
+ ((qsl_hsh & QSL_HSH_MASK) << 26) | (1 << 31);
+ return color_action;
+}
+
+/*
+ * This is a bitmask representation in SW for
+ * roa config settings. It is mostly done for
+ * effective cache matching
+ *
+ * ROA config bit offs bits
+ * ----------------------------
+ * recirc port 7:0 8 -> uses hbx > 0
+ * recirc bypass 15:8 8 -> uses hbx > 0 if set, will override
+ * tunnel type 19:16 4
+ * tx port 23:20 4 -> txport + 1
+ * tun_ip_type 24:24 1
+ * recirculate 25:25 1 -> recirculate port set
+ * tunhdr_len 33:26 8 -> tunnel header length - 0 if none
+ * ip_csum_prec 49:34 16 -> tunnel ip header checksum pre-calculated
+ * new_recirc_port 50:50 1 -> indication of a new port for recirculate has been allocated.
+ * Needs default queue
+ */
+
+static inline uint64_t set_roa_new_recirc_port(uint64_t actions)
+{
+ actions |= 1ULL << 50;
+ return actions;
+}
+
+static inline uint8_t get_roa_new_recirc_port(uint64_t actions)
+{
+ return (uint8_t)((actions >> 50) & 1);
+}
+
+static inline uint64_t set_roa_tun_ip_type(uint64_t actions, uint8_t ip_type)
+{
+ actions |= (uint64_t)(ip_type & 1) << 24;
+ return actions;
+}
+
+static inline uint8_t get_roa_tun_ip_type(uint64_t actions)
+{
+ return (uint8_t)((actions >> 24) & 1);
+}
+
+static inline uint64_t set_roa_tun_ip_csum(uint64_t actions, uint16_t csum)
+{
+ actions |= (uint64_t)csum << 34;
+ return actions;
+}
+
+static inline uint16_t get_roa_tun_ip_csum(uint64_t actions)
+{
+ return (uint16_t)((actions >> 34) & 0xffff);
+}
+
+static inline uint64_t set_roa_tunhdr_len(uint64_t actions, uint8_t length)
+{
+ actions |= (uint64_t)length << 26;
+ return actions;
+}
+
+static inline uint8_t get_roa_tunhdr_len(uint64_t actions)
+{
+ return (uint8_t)((actions >> 26) & 0xff);
+}
+
+static inline uint64_t set_roa_tx(uint64_t actions, uint8_t txport)
+{
+ actions |= ((txport + ROA_TX_PHY0) & 0x0f) << 20;
+ return actions;
+}
+
+static inline uint8_t roa_get_tx(uint64_t actions)
+{
+ return (actions >> 20) & 0x0f;
+}
+
+static inline uint64_t set_roa_tun_type(uint64_t actions, uint8_t type)
+{
+ actions |= (type & 0x0f) << 16;
+ return actions;
+}
+
+static inline uint8_t roa_get_tun_type(uint64_t actions)
+{
+ return (actions >> 16) & 0x0f;
+}
+
+static inline uint64_t set_roa_recirculate(uint64_t actions, uint8_t port)
+{
+ actions |= (1ULL << 25) | port;
+ return actions;
+}
+
+static inline int32_t roa_get_recirc_port(uint64_t actions)
+{
+ if (!((1ULL << 25) & actions))
+ return -1;
+ return (actions & 0xff);
+}
+
+static inline uint64_t set_roa_recirc_bypass(uint64_t actions, uint8_t port)
+{
+ actions |= ((uint64_t)port & 0xff) << 8;
+ return actions;
+}
+
+static inline uint8_t roa_get_recirc_bypass_port(uint64_t actions)
+{
+ return ((actions >> 8) & 0xff);
+}
+
+/*
+ * This is a bitmask representation in SW for
+ * ioa action settings. It is mostly done for
+ * effective cache matching
+ *
+ * IOA action bit offs bits
+ * --------------------------------
+ * tci 15:0 16
+ * queue 23:16 8 uses hbx
+ * tpid select 27:24 4
+ * pop vxlan 28 1
+ * pop vlan 29 1
+ * push vlan 30 1
+ * queue override 31 1
+ */
+
+static inline uint64_t ioa_set_queue(uint64_t actions, uint8_t hb)
+{
+ actions |= (1 << 31) | ((uint64_t)hb << 16);
+ return actions;
+}
+
+static inline int ioa_get_queue(uint64_t actions)
+{
+ if (!(actions & (1 << 31)))
+ return -1;
+ return ((actions >> 16) & 0xff);
+}
+
+static inline uint64_t ioa_set_vxlan_pop(uint64_t actions)
+{
+ actions |= 1 << 28;
+ return actions;
+}
+
+static inline uint64_t ioa_set_vlan_pop(uint64_t actions)
+{
+ actions |= 1 << 29;
+ return actions;
+}
+
+static inline uint64_t ioa_set_vlan_push_qinq(uint64_t actions)
+{
+ actions |= (VLAN_TPID_802_1AD & 0x0f) << 24;
+ return actions;
+}
+
+static inline uint8_t ioa_get_tpid_sel(uint64_t actions)
+{
+ return (uint8_t)((actions >> 24) & 0x0f);
+}
+
+static inline uint64_t ioa_set_vlan_push(uint64_t actions, uint16_t tci)
+{
+ actions |= (1 << 30) | tci;
+ return actions;
+}
+
+static inline uint64_t ioa_set_vlan_pcp(uint64_t actions, uint8_t pcp)
+{
+ actions |= (1 << 30) | ((uint16_t)(pcp & 7) << 13);
+ return actions;
+}
+
+static inline uint16_t ioa_get_vlan_tci(uint64_t actions)
+{
+ return (uint16_t)(actions & 0xffff);
+}
+
+int flow_actions_create_roa_tunhdr(struct flow_api_backend_s *be, int index,
+ struct tunnel_header_s *tun);
+int flow_actions_create_roa_tuncfg(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions);
+int flow_actions_create_ioa_config(struct flow_api_backend_s *be, int index,
+ uint64_t color_actions);
+
+#endif /* _FLOW_ACTIONS_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c
new file mode 100644
index 0000000000..f4d71acb51
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.c
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+
+#include "flow_api_backend.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct {
+ const char *name;
+ int (*allocate)(struct flow_api_backend_s *be);
+ void (*free)(struct flow_api_backend_s *be);
+ int (*reset)(struct flow_api_backend_s *be);
+ bool (*present)(struct flow_api_backend_s *be);
+} module[] = {
+ { "CAT", hw_mod_cat_alloc, hw_mod_cat_free, hw_mod_cat_reset,
+ hw_mod_cat_present
+ },
+ { "KM", hw_mod_km_alloc, hw_mod_km_free, hw_mod_km_reset,
+ hw_mod_km_present
+ },
+ { "FLM", hw_mod_flm_alloc, hw_mod_flm_free, hw_mod_flm_reset,
+ hw_mod_flm_present
+ },
+ { "HSH", hw_mod_hsh_alloc, hw_mod_hsh_free, hw_mod_hsh_reset,
+ hw_mod_hsh_present
+ },
+ { "HST", hw_mod_hst_alloc, hw_mod_hst_free, hw_mod_hst_reset,
+ hw_mod_hst_present
+ },
+ { "QSL", hw_mod_qsl_alloc, hw_mod_qsl_free, hw_mod_qsl_reset,
+ hw_mod_qsl_present
+ },
+ { "SLC", hw_mod_slc_alloc, hw_mod_slc_free, hw_mod_slc_reset,
+ hw_mod_slc_present
+ },
+ { "SLC LR", hw_mod_slc_lr_alloc, hw_mod_slc_lr_free,
+ hw_mod_slc_lr_reset, hw_mod_slc_lr_present
+ },
+ { "PDB", hw_mod_pdb_alloc, hw_mod_pdb_free, hw_mod_pdb_reset,
+ hw_mod_pdb_present
+ },
+ { "IOA", hw_mod_ioa_alloc, hw_mod_ioa_free, hw_mod_ioa_reset,
+ hw_mod_ioa_present
+ },
+ { "ROA", hw_mod_roa_alloc, hw_mod_roa_free, hw_mod_roa_reset,
+ hw_mod_roa_present
+ },
+ { "RMC", hw_mod_rmc_alloc, hw_mod_rmc_free, hw_mod_rmc_reset,
+ hw_mod_rmc_present
+ },
+ { "TPE", hw_mod_tpe_alloc, hw_mod_tpe_free, hw_mod_tpe_reset,
+ hw_mod_tpe_present
+ },
+};
+
+#define MOD_COUNT (ARRAY_SIZE(module))
+
+void *callocate_mod(struct common_func_s *mod, int sets, ...)
+{
+#define MAX_SETS 38
+ void *base = NULL;
+ void **plist[MAX_SETS];
+ int len[MAX_SETS];
+ int offs[MAX_SETS];
+ unsigned int total_bytes = 0;
+ int cnt, elem_size;
+
+ assert(sets <= MAX_SETS);
+ assert(sets > 0);
+
+ va_list args;
+
+ va_start(args, sets);
+
+ for (int i = 0; i < sets; i++) {
+ plist[i] = va_arg(args, void *);
+ cnt = va_arg(args, int);
+ elem_size = va_arg(args, int);
+ offs[i] = EXTRA_INDEXES * elem_size;
+ len[i] = offs[i] + cnt * elem_size;
+ total_bytes += len[i];
+ }
+ base = calloc(1, total_bytes);
+ if (base) {
+ char *p_b = (char *)base;
+
+ for (int i = 0; i < sets; i++) {
+ (*plist[i]) = (void *)((char *)p_b + offs[i]);
+ p_b += len[i];
+ }
+ } else {
+ NT_LOG(ERR, FILTER, "ERROR: module memory allocation failed\n");
+ }
+
+ va_end(args);
+
+ mod->base = base;
+ mod->allocated_size = total_bytes;
+
+ return base;
+}
+
+void zero_module_cache(struct common_func_s *mod)
+{
+ memset(mod->base, 0, mod->allocated_size);
+}
+
+int flow_api_backend_init(struct flow_api_backend_s *dev,
+ const struct flow_api_backend_ops *iface,
+ void *be_dev)
+{
+ assert(dev);
+ dev->iface = iface;
+ dev->be_dev = be_dev;
+ dev->num_phy_ports = iface->get_nb_phy_port(be_dev);
+ dev->num_rx_ports = iface->get_nb_rx_port(be_dev);
+ dev->max_categories = iface->get_nb_categories(be_dev);
+ dev->max_queues = iface->get_nb_queues(be_dev);
+
+ NT_LOG(DBG, FILTER,
+ "*************** FLOW REGISTER MODULES AND INITIALIZE - SET ALL TO DEFAULT *****************\n");
+ /*
+ * Create Cache and SW, version independent, NIC module representation
+ */
+ for (unsigned int mod = 0; mod < MOD_COUNT; mod++) {
+ if (!module[mod].present(dev))
+ continue;
+ if (module[mod].allocate(dev) == 0 &&
+ module[mod].reset(dev) == 0) {
+ /* OK */
+ continue;
+ } else {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Initialization of NIC module failed : [ %s ]\n",
+ module[mod].name);
+ flow_api_backend_done(dev);
+ NT_LOG(ERR, FILTER,
+ "*************** Failed to create Binary Flow API *******************\n");
+ NT_LOG(ERR, FILTER,
+ "******** ERROR ERROR: Binary Flow API will not be available ********\n");
+ NT_LOG(ERR, FILTER,
+ "********************************************************************\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int flow_api_backend_reset(struct flow_api_backend_s *dev)
+{
+ assert(dev);
+
+ for (unsigned int mod = 0; mod < MOD_COUNT; mod++) {
+ if (module[mod].reset(dev) == 0) {
+ /* OK */
+ continue;
+ } else {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Resetting NIC module failed : [ %s ]\n",
+ module[mod].name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int flow_api_backend_done(struct flow_api_backend_s *dev)
+{
+ for (unsigned int mod = 0; mod < MOD_COUNT; mod++)
+ module[mod].free(dev);
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h
new file mode 100644
index 0000000000..c3386adea9
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_backend.h
@@ -0,0 +1,1818 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_API_BACKEND_H__
+#define __FLOW_API_BACKEND_H__
+
+/*
+ * Flow API
+ * Direct access to NIC HW module memory and register fields in a
+ * module version independent representation
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "ntlog.h"
+
+/* supported module versions */
+#include "../flow_api/hw_mod/hw_mod_km_v7.h"
+#include "flow_api/hw_mod/hw_mod_cat_v18.h"
+#include "flow_api/hw_mod/hw_mod_cat_v21.h"
+#include "flow_api/hw_mod/hw_mod_cat_v22.h"
+#include "flow_api/hw_mod/hw_mod_flm_v17.h"
+#include "flow_api/hw_mod/hw_mod_flm_v20.h"
+#include "flow_api/hw_mod/hw_mod_hst_v2.h"
+#include "flow_api/hw_mod/hw_mod_km_v7.h"
+#include "flow_api/hw_mod/hw_mod_qsl_v7.h"
+#include "flow_api/hw_mod/hw_mod_pdb_v9.h"
+#include "flow_api/hw_mod/hw_mod_slc_v1.h"
+#include "flow_api/hw_mod/hw_mod_slc_lr_v2.h"
+#include "flow_api/hw_mod/hw_mod_roa_v6.h"
+#include "flow_api/hw_mod/hw_mod_hsh_v5.h"
+#include "flow_api/hw_mod/hw_mod_ioa_v4.h"
+#include "flow_api/hw_mod/hw_mod_rmc_v1_3.h"
+#include "flow_api/hw_mod/hw_mod_tpe_v1.h"
+#include "flow_api/hw_mod/hw_mod_tpe_v2.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_PHYS_ADAPTERS 8
+
+#define VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
+#define VER_MINOR(ver) ((ver) & 0xffff)
+
+struct flow_api_backend_s;
+struct common_func_s;
+
+#define CAST_COMMON(mod) ((struct common_func_s *)(mod))
+
+void *callocate_mod(struct common_func_s *mod, int sets, ...);
+void zero_module_cache(struct common_func_s *mod);
+
+#define ZERO_MOD_CACHE(mod) (zero_module_cache(CAST_COMMON(mod)))
+
+#define ALL_ENTRIES -1000
+#define ALL_BANK_ENTRIES -1001
+
+static inline int error_index_too_large(const char *func)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Index too large\n", func);
+ return -2;
+}
+
+static inline int error_word_off_too_large(const char *func)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Word offset too large\n", func);
+ return -3;
+}
+
+static inline int error_unsup_ver(const char *func, const char *mod, int ver)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Unsupported NIC module: %s ver %i.%i\n",
+ func, mod, VER_MAJOR(ver), VER_MINOR(ver));
+ return -4;
+}
+
+static inline int error_unsup_field(const char *func)
+{
+ NT_LOG(INF, FILTER, "ERROR:%s: Unsupported field in NIC module\n",
+ func);
+ return -5;
+}
+
+static inline int error_resource_count(const char *func, const char *resource,
+ const char *mod, int ver)
+{
+ NT_LOG(INF, FILTER,
+ "ERROR:%s: Insufficient resource [ %s ] : NIC module:"
+ "%s ver %i.%i\n",
+ func, resource, mod, VER_MAJOR(ver), VER_MINOR(ver));
+ return -4;
+}
+
+#define NOT_FOUND 0xffffffff
+
+enum { EXTRA_INDEXES };
+#define COPY_INDEX (EXTRA_INDEX_COPY - EXTRA_INDEXES)
+
+static inline void get_set(uint32_t *cached_val, uint32_t *val, int get)
+{
+ if (get)
+ *val = *cached_val;
+ else
+ *cached_val = *val;
+}
+
+static inline void get_set_signed(int32_t *cached_val, uint32_t *val, int get)
+{
+ if (get)
+ *val = (uint32_t)*cached_val;
+ else
+ *cached_val = (int32_t)*val;
+}
+
+static inline int find_equal_index(void *be_module_reg,
+ unsigned int type_size, unsigned int idx, unsigned int start,
+ unsigned int nb_elements, uint32_t *value, int get, const char *func)
+{
+ unsigned int i;
+ if (!get)
+ return error_unsup_field(func);
+ *value = NOT_FOUND;
+ if (start >= nb_elements)
+ return error_index_too_large(func);
+ for (i = start; i < nb_elements; i++) {
+ if (idx == i)
+ continue;
+ if (memcmp((uint8_t *)be_module_reg + idx * type_size,
+ (uint8_t *)be_module_reg + i * type_size,
+ type_size) == 0) {
+ *value = i;
+ break;
+ }
+ }
+ return 0;
+}
+
+static inline int do_compare_indexes(void *be_module_reg,
+ unsigned int type_size, unsigned int idx, unsigned int cmp_idx,
+ unsigned int nb_elements, int get, const char *func)
+{
+ if (!get)
+ return error_unsup_field(func);
+ if (cmp_idx >= nb_elements)
+ return error_index_too_large(func);
+ if (idx != cmp_idx &&
+ (memcmp((uint8_t *)be_module_reg + idx * type_size,
+ (uint8_t *)be_module_reg + cmp_idx * type_size,
+ type_size) == 0))
+ return 1;
+ return 0;
+}
+
+static inline int is_non_zero(const void *addr, size_t n)
+{
+ size_t i = 0;
+ const uint8_t *p = (const uint8_t *)addr;
+
+ for (i = 0; i < n; i++) {
+ if (p[i] != 0)
+ return 1;
+ }
+ return 0;
+}
+
+static inline int is_all_bits_set(const void *addr, size_t n)
+{
+ size_t i = 0;
+ const uint8_t *p = (const uint8_t *)addr;
+
+ for (i = 0; i < n; i++) {
+ if (p[i] != 0xff)
+ return 0;
+ }
+ return 1;
+}
+
+enum cte_index_e {
+ CT_COL = 0,
+ CT_COR = 1,
+ CT_HSH = 2,
+ CT_QSL = 3,
+ CT_IPF = 4,
+ CT_SLC = 5,
+ CT_PDB = 6,
+ CT_MSK = 7,
+ CT_HST = 8,
+ CT_EPP = 9,
+ CT_TPE = 10,
+ CT_RRB = 11,
+ CT_CNT
+};
+
+/* Sideband info bit indicator */
+#define SWX_INFO (1 << 6)
+
+enum frame_offs_e {
+ DYN_SOF = 0,
+ DYN_L2 = 1,
+ DYN_FIRST_VLAN = 2,
+ DYN_MPLS = 3,
+ DYN_L3 = 4,
+ DYN_ID_IPV4_6 = 5,
+ DYN_FINAL_IP_DST = 6,
+ DYN_L4 = 7,
+ DYN_L4_PAYLOAD = 8,
+ DYN_TUN_PAYLOAD = 9,
+ DYN_TUN_L2 = 10,
+ DYN_TUN_VLAN = 11,
+ DYN_TUN_MPLS = 12,
+ DYN_TUN_L3 = 13,
+ DYN_TUN_ID_IPV4_6 = 14,
+ DYN_TUN_FINAL_IP_DST = 15,
+ DYN_TUN_L4 = 16,
+ DYN_TUN_L4_PAYLOAD = 17,
+ DYN_EOF = 18,
+ DYN_L3_PAYLOAD_END = 19,
+ DYN_TUN_L3_PAYLOAD_END = 20,
+ SB_VNI = SWX_INFO | 1,
+ SB_MAC_PORT = SWX_INFO | 2,
+ SB_KCC_ID = SWX_INFO | 3
+};
+
+enum km_flm_if_select_e { KM_FLM_IF_FIRST = 0, KM_FLM_IF_SECOND = 1 };
+
+enum {
+ QW0_SEL_EXCLUDE = 0,
+ QW0_SEL_FIRST32 = 1,
+ QW0_SEL_SECOND32 = 2,
+ QW0_SEL_FIRST64 = 3,
+ QW0_SEL_ALL128 = 4,
+};
+
+enum {
+ QW4_SEL_EXCLUDE = 0,
+ QW4_SEL_FIRST32 = 1,
+ QW4_SEL_FIRST64 = 2,
+ QW4_SEL_ALL128 = 3,
+};
+
+enum {
+ SW8_SEL_EXCLUDE = 0,
+ SW8_SEL_FIRST16 = 1,
+ SW8_SEL_SECOND16 = 2,
+ SW8_SEL_ALL32 = 3,
+};
+
+enum {
+ DW8_SEL_EXCLUDE = 0,
+ DW8_SEL_FIRST16 = 1,
+ DW8_SEL_SECOND16 = 2,
+ DW8_SEL_FIRST32 = 3,
+ DW8_SEL_FIRST32_SWAP16 = 4,
+ DW8_SEL_ALL64 = 5,
+};
+
+enum {
+ SW9_SEL_EXCLUDE = 0,
+ SW9_SEL_FIRST16 = 1,
+ SW9_SEL_ALL32 = 2,
+};
+
+enum {
+ DW10_SEL_EXCLUDE = 0,
+ DW10_SEL_FIRST16 = 1,
+ DW10_SEL_FIRST32 = 2,
+ DW10_SEL_ALL64 = 3,
+};
+
+enum {
+ SWX_SEL_EXCLUDE = 0,
+ SWX_SEL_ALL32 = 1,
+};
+
+enum {
+ PROT_OTHER = 0,
+ PROT_L2_ETH2 = 1,
+ PROT_L2_SNAP = 2,
+ PROT_L2_LLC = 3,
+ PROT_L2_RAW = 4,
+ PROT_L2_PPPOE_D = 5,
+ PROT_L2_PPOE_S = 6
+};
+
+enum { PROT_L3_IPV4 = 1, PROT_L3_IPV6 = 2 };
+
+enum { PROT_L4_TCP = 1, PROT_L4_UDP = 2, PROT_L4_SCTP = 3, PROT_L4_ICMP = 4 };
+
+enum {
+ PROT_TUN_IP_IN_IP = 1,
+ PROT_TUN_ETHER_IP = 2,
+ PROT_TUN_GREV0 = 3,
+ PROT_TUN_GREV1 = 4,
+ PROT_TUN_GTPV0U = 5,
+ PROT_TUN_GTPV1U = 6,
+ PROT_TUN_GTPV1C = 7,
+ PROT_TUN_GTPV2C = 8,
+ PROT_TUN_VXLAN = 9,
+ PROT_TUN_PSEUDO_WIRE = 10
+};
+
+enum { PROT_TUN_L2_OTHER = 0, PROT_TUN_L2_ETH2 = 1 };
+
+enum { PROT_TUN_L3_OTHER = 0, PROT_TUN_L3_IPV4 = 1, PROT_TUN_L3_IPV6 = 2 };
+
+enum {
+ PROT_TUN_L4_OTHER = 0,
+ PROT_TUN_L4_TCP = 1,
+ PROT_TUN_L4_UDP = 2,
+ PROT_TUN_L4_SCTP = 3,
+ PROT_TUN_L4_ICMP = 4
+};
+
+enum {
+ IP_FRAG_NOT_A_FRAG = 0,
+ IP_FRAG_FIRST = 1,
+ IP_FRAG_MIDDLE = 2,
+ IP_FRAG_LAST = 3
+};
+
+enum {
+ HASH_HASH_NONE = 0,
+ HASH_USER_DEFINED = 1,
+ HASH_LAST_MPLS_LABEL = 2,
+ HASH_ALL_MPLS_LABELS = 3,
+ HASH_2TUPLE = 4,
+ HASH_2TUPLESORTED = 5,
+ HASH_LAST_VLAN_ID = 6,
+ HASH_ALL_VLAN_IDS = 7,
+ HASH_5TUPLE = 8,
+ HASH_5TUPLESORTED = 9,
+ HASH_3TUPLE_GRE_V0 = 10,
+ HASH_3TUPLE_GRE_V0_SORTED = 11,
+ HASH_5TUPLE_SCTP = 12,
+ HASH_5TUPLE_SCTP_SORTED = 13,
+ HASH_3TUPLE_GTP_V0 = 14,
+ HASH_3TUPLE_GTP_V0_SORTED = 15,
+ HASH_3TUPLE_GTP_V1V2 = 16,
+ HASH_3TUPLE_GTP_V1V2_SORTED = 17,
+ HASH_HASHINNER_2TUPLE = 18,
+ HASH_HASHINNER_2TUPLESORTED = 19,
+ HASH_HASHINNER_5TUPLE = 20,
+ HASH_HASHINNER_5TUPLESORTED = 21,
+ HASH_KM = 30,
+ HASH_ROUND_ROBIN = 31,
+ HASH_OUTER_DST_IP = 32,
+ HASH_INNER_SRC_IP = 33,
+};
+
+enum {
+ CPY_SELECT_DSCP_IPV4 = 0,
+ CPY_SELECT_DSCP_IPV6 = 1,
+ CPY_SELECT_RQI_QFI = 2,
+ CPY_SELECT_IPV4 = 3,
+ CPY_SELECT_PORT = 4,
+ CPY_SELECT_TEID = 5,
+};
+
+#define RCK_CML(_comp_) (1 << ((_comp_) * 4))
+#define RCK_CMU(_comp_) (1 << ((_comp_) * 4 + 1))
+#define RCK_SEL(_comp_) (1 << ((_comp_) * 4 + 2))
+#define RCK_SEU(_comp_) (1 << ((_comp_) * 4 + 3))
+
+#define RCK_EXT(x) (((uint32_t)(x) << 6))
+
+#define FIELD_START_INDEX 100
+
+#define COMMON_FUNC_INFO_S \
+ int ver; \
+ void *base; \
+ unsigned int allocated_size; \
+ int debug
+
+struct common_func_s {
+ COMMON_FUNC_INFO_S;
+};
+
+struct cat_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_cat_funcs;
+ uint32_t nb_flow_types;
+ uint32_t nb_pm_ext;
+ uint32_t nb_len;
+ uint32_t kcc_size;
+ uint32_t cts_num;
+ uint32_t kcc_banks;
+ uint32_t kcc_id_bit_size;
+ uint32_t kcc_records;
+ uint32_t km_if_count;
+ int32_t km_if_m0;
+ int32_t km_if_m1;
+
+ union {
+ struct hw_mod_cat_v18_s v18;
+ struct hw_mod_cat_v21_s v21;
+ struct hw_mod_cat_v22_s v22;
+ };
+};
+
+enum hw_cat_e {
+ /*
+ * functions initial CAT v18
+ */
+ /* 00 */ HW_CAT_CFN_SET_ALL_DEFAULTS = 0,
+ /* 01 */ HW_CAT_CFN_PRESET_ALL,
+ /* 02 */ HW_CAT_CFN_COMPARE,
+ /* 03 */ HW_CAT_CFN_FIND,
+ /* 04 */ HW_CAT_CFN_COPY_FROM,
+ /* 05 */ HW_CAT_COT_PRESET_ALL,
+ /* 06 */ HW_CAT_COT_COMPARE,
+ /* 07 */ HW_CAT_COT_FIND,
+ /* fields */
+ /* 00 */ HW_CAT_CFN_ENABLE = FIELD_START_INDEX,
+ /* 01 */ HW_CAT_CFN_INV,
+ /* 02 */ HW_CAT_CFN_PTC_INV,
+ /* 03 */ HW_CAT_CFN_PTC_ISL,
+ /* 04 */ HW_CAT_CFN_PTC_CFP,
+ /* 05 */ HW_CAT_CFN_PTC_MAC,
+ /* 06 */ HW_CAT_CFN_PTC_L2,
+ /* 07 */ HW_CAT_CFN_PTC_VNTAG,
+ /* 08 */ HW_CAT_CFN_PTC_VLAN,
+ /* 09 */ HW_CAT_CFN_PTC_MPLS,
+ /* 10 */ HW_CAT_CFN_PTC_L3,
+ /* 11 */ HW_CAT_CFN_PTC_FRAG,
+ /* 12 */ HW_CAT_CFN_PTC_IP_PROT,
+ /* 13 */ HW_CAT_CFN_PTC_L4,
+ /* 14 */ HW_CAT_CFN_PTC_TUNNEL,
+ /* 15 */ HW_CAT_CFN_PTC_TNL_L2,
+ /* 16 */ HW_CAT_CFN_PTC_TNL_VLAN,
+ /* 17 */ HW_CAT_CFN_PTC_TNL_MPLS,
+ /* 18 */ HW_CAT_CFN_PTC_TNL_L3,
+ /* 19 */ HW_CAT_CFN_PTC_TNL_FRAG,
+ /* 20 */ HW_CAT_CFN_PTC_TNL_IP_PROT,
+ /* 21 */ HW_CAT_CFN_PTC_TNL_L4,
+ /* 22 */ HW_CAT_CFN_ERR_INV,
+ /* 23 */ HW_CAT_CFN_ERR_CV,
+ /* 24 */ HW_CAT_CFN_ERR_FCS,
+ /* 25 */ HW_CAT_CFN_ERR_TRUNC,
+ /* 26 */ HW_CAT_CFN_ERR_L3_CS,
+ /* 27 */ HW_CAT_CFN_ERR_L4_CS,
+ /* 28 */ HW_CAT_CFN_MAC_PORT,
+ /* 29 */ HW_CAT_CFN_PM_CMP,
+ /* 30 */ HW_CAT_CFN_PM_DCT,
+ /* 31 */ HW_CAT_CFN_PM_EXT_INV,
+ /* 32 */ HW_CAT_CFN_PM_CMB,
+ /* 33 */ HW_CAT_CFN_PM_AND_INV,
+ /* 34 */ HW_CAT_CFN_PM_OR_INV,
+ /* 35 */ HW_CAT_CFN_PM_INV,
+ /* 36 */ HW_CAT_CFN_LC,
+ /* 37 */ HW_CAT_CFN_LC_INV,
+ /* 38 */ HW_CAT_CFN_KM0_OR,
+ /* 39 */ HW_CAT_CFN_KM1_OR,
+ /* 40 */ HW_CAT_KCE_ENABLE_BM,
+ /* 41 */ HW_CAT_KCS_CATEGORY,
+ /* 42 */ HW_CAT_FTE_ENABLE_BM,
+ /* 43 */ HW_CAT_CTE_ENABLE_BM,
+ /* 44 */ HW_CAT_CTS_CAT_A,
+ /* 45 */ HW_CAT_CTS_CAT_B,
+ /* 46 */ HW_CAT_COT_COLOR,
+ /* 47 */ HW_CAT_COT_KM,
+ /* 48 */ HW_CAT_CCT_COLOR,
+ /* 49 */ HW_CAT_CCT_KM,
+ /* 50 */ HW_CAT_KCC_KEY,
+ /* 51 */ HW_CAT_KCC_CATEGORY,
+ /* 52 */ HW_CAT_KCC_ID,
+ /* 53 */ HW_CAT_EXO_DYN,
+ /* 54 */ HW_CAT_EXO_OFS,
+ /* 55 */ HW_CAT_RCK_DATA,
+ /* 56 */ HW_CAT_LEN_LOWER,
+ /* 57 */ HW_CAT_LEN_UPPER,
+ /* 58 */ HW_CAT_LEN_DYN1,
+ /* 59 */ HW_CAT_LEN_DYN2,
+ /* 60 */ HW_CAT_LEN_INV,
+ /* 61 */ HW_CAT_CFN_ERR_TNL_L3_CS,
+ /* 62 */ HW_CAT_CFN_ERR_TNL_L4_CS,
+ /* 63 */ HW_CAT_CFN_ERR_TTL_EXP,
+ /* 64 */ HW_CAT_CFN_ERR_TNL_TTL_EXP,
+
+ /* 65 */ HW_CAT_CCE_IMM,
+ /* 66 */ HW_CAT_CCE_IND,
+ /* 67 */ HW_CAT_CCS_COR_EN,
+ /* 68 */ HW_CAT_CCS_COR,
+ /* 69 */ HW_CAT_CCS_HSH_EN,
+ /* 70 */ HW_CAT_CCS_HSH,
+ /* 71 */ HW_CAT_CCS_QSL_EN,
+ /* 72 */ HW_CAT_CCS_QSL,
+ /* 73 */ HW_CAT_CCS_IPF_EN,
+ /* 74 */ HW_CAT_CCS_IPF,
+ /* 75 */ HW_CAT_CCS_SLC_EN,
+ /* 76 */ HW_CAT_CCS_SLC,
+ /* 77 */ HW_CAT_CCS_PDB_EN,
+ /* 78 */ HW_CAT_CCS_PDB,
+ /* 79 */ HW_CAT_CCS_MSK_EN,
+ /* 80 */ HW_CAT_CCS_MSK,
+ /* 81 */ HW_CAT_CCS_HST_EN,
+ /* 82 */ HW_CAT_CCS_HST,
+ /* 83 */ HW_CAT_CCS_EPP_EN,
+ /* 84 */ HW_CAT_CCS_EPP,
+ /* 85 */ HW_CAT_CCS_TPE_EN,
+ /* 86 */ HW_CAT_CCS_TPE,
+ /* 87 */ HW_CAT_CCS_RRB_EN,
+ /* 88 */ HW_CAT_CCS_RRB,
+ /* 89 */ HW_CAT_CCS_SB0_TYPE,
+ /* 90 */ HW_CAT_CCS_SB0_DATA,
+ /* 91 */ HW_CAT_CCS_SB1_TYPE,
+ /* 92 */ HW_CAT_CCS_SB1_DATA,
+ /* 93 */ HW_CAT_CCS_SB2_TYPE,
+ /* 94 */ HW_CAT_CCS_SB2_DATA,
+
+};
+
+bool hw_mod_cat_present(struct flow_api_backend_s *be);
+int hw_mod_cat_alloc(struct flow_api_backend_s *be);
+void hw_mod_cat_free(struct flow_api_backend_s *be);
+int hw_mod_cat_reset(struct flow_api_backend_s *be);
+int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value);
+int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value);
+/* KCE/KCS/FTE KM */
+int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+/* KCE/KCS/FTE FLM */
+int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count);
+int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value);
+int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value);
+
+int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value);
+int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value);
+
+int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+/* added in v22 */
+int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value);
+int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value);
+
+struct km_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_categories;
+ uint32_t nb_cam_banks;
+ uint32_t nb_cam_record_words;
+ uint32_t nb_cam_records;
+ uint32_t nb_tcam_banks;
+ uint32_t nb_tcam_bank_width;
+ /* not read from backend, but rather set using version */
+ uint32_t nb_km_rcp_mask_a_word_size;
+ uint32_t nb_km_rcp_mask_b_word_size;
+ union {
+ struct hw_mod_km_v7_s v7;
+ };
+};
+
+enum hw_km_e {
+ /* functions */
+ HW_KM_RCP_PRESET_ALL = 0,
+ HW_KM_CAM_PRESET_ALL,
+ /* to sync and reset hw with cache - force write all entries in a bank */
+ HW_KM_TCAM_BANK_RESET,
+ /* fields */
+ HW_KM_RCP_QW0_DYN = FIELD_START_INDEX,
+ HW_KM_RCP_QW0_OFS,
+ HW_KM_RCP_QW0_SEL_A,
+ HW_KM_RCP_QW0_SEL_B,
+ HW_KM_RCP_QW4_DYN,
+ HW_KM_RCP_QW4_OFS,
+ HW_KM_RCP_QW4_SEL_A,
+ HW_KM_RCP_QW4_SEL_B,
+ HW_KM_RCP_DW8_DYN,
+ HW_KM_RCP_DW8_OFS,
+ HW_KM_RCP_DW8_SEL_A,
+ HW_KM_RCP_DW8_SEL_B,
+ HW_KM_RCP_DW10_DYN,
+ HW_KM_RCP_DW10_OFS,
+ HW_KM_RCP_DW10_SEL_A,
+ HW_KM_RCP_DW10_SEL_B,
+ HW_KM_RCP_SWX_CCH,
+ HW_KM_RCP_SWX_SEL_A,
+ HW_KM_RCP_SWX_SEL_B,
+ HW_KM_RCP_MASK_A,
+ HW_KM_RCP_MASK_B,
+ HW_KM_RCP_DUAL,
+ HW_KM_RCP_PAIRED,
+ HW_KM_RCP_EL_A,
+ HW_KM_RCP_EL_B,
+ HW_KM_RCP_INFO_A,
+ HW_KM_RCP_INFO_B,
+ HW_KM_RCP_FTM_A,
+ HW_KM_RCP_FTM_B,
+ HW_KM_RCP_BANK_A,
+ HW_KM_RCP_BANK_B,
+ HW_KM_RCP_KL_A,
+ HW_KM_RCP_KL_B,
+ HW_KM_RCP_KEYWAY_A,
+ HW_KM_RCP_KEYWAY_B,
+ HW_KM_RCP_SYNERGY_MODE,
+ HW_KM_RCP_DW0_B_DYN,
+ HW_KM_RCP_DW0_B_OFS,
+ HW_KM_RCP_DW2_B_DYN,
+ HW_KM_RCP_DW2_B_OFS,
+ HW_KM_RCP_SW4_B_DYN,
+ HW_KM_RCP_SW4_B_OFS,
+ HW_KM_RCP_SW5_B_DYN,
+ HW_KM_RCP_SW5_B_OFS,
+ HW_KM_CAM_W0,
+ HW_KM_CAM_W1,
+ HW_KM_CAM_W2,
+ HW_KM_CAM_W3,
+ HW_KM_CAM_W4,
+ HW_KM_CAM_W5,
+ HW_KM_CAM_FT0,
+ HW_KM_CAM_FT1,
+ HW_KM_CAM_FT2,
+ HW_KM_CAM_FT3,
+ HW_KM_CAM_FT4,
+ HW_KM_CAM_FT5,
+ HW_KM_TCAM_T,
+ HW_KM_TCI_COLOR,
+ HW_KM_TCI_FT,
+ HW_KM_TCQ_BANK_MASK,
+ HW_KM_TCQ_QUAL
+};
+
+bool hw_mod_km_present(struct flow_api_backend_s *be);
+int hw_mod_km_alloc(struct flow_api_backend_s *be);
+void hw_mod_km_free(struct flow_api_backend_s *be);
+int hw_mod_km_reset(struct flow_api_backend_s *be);
+int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t value);
+int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t *value);
+int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count);
+int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value);
+int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank,
+ int count);
+int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set);
+int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set);
+int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count);
+int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value);
+int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count);
+int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value);
+
+struct hst_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_hst_rcp_categories;
+ union {
+ struct hw_mod_hst_v2_s v2;
+ };
+};
+
+enum hw_hst_e {
+ /* functions */
+ HW_HST_RCP_PRESET_ALL = 0,
+ HW_HST_RCP_FIND,
+ HW_HST_RCP_COMPARE,
+ /* Control fields */
+ HW_HST_RCP_STRIP_MODE = FIELD_START_INDEX,
+ HW_HST_RCP_START_DYN,
+ HW_HST_RCP_START_OFS,
+ HW_HST_RCP_END_DYN,
+ HW_HST_RCP_END_OFS,
+ HW_HST_RCP_MODIF0_CMD,
+ HW_HST_RCP_MODIF0_DYN,
+ HW_HST_RCP_MODIF0_OFS,
+ HW_HST_RCP_MODIF0_VALUE,
+ HW_HST_RCP_MODIF1_CMD,
+ HW_HST_RCP_MODIF1_DYN,
+ HW_HST_RCP_MODIF1_OFS,
+ HW_HST_RCP_MODIF1_VALUE,
+ HW_HST_RCP_MODIF2_CMD,
+ HW_HST_RCP_MODIF2_DYN,
+ HW_HST_RCP_MODIF2_OFS,
+ HW_HST_RCP_MODIF2_VALUE,
+
+};
+
+bool hw_mod_hst_present(struct flow_api_backend_s *be);
+int hw_mod_hst_alloc(struct flow_api_backend_s *be);
+void hw_mod_hst_free(struct flow_api_backend_s *be);
+int hw_mod_hst_reset(struct flow_api_backend_s *be);
+
+int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t value);
+int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t *value);
+
+struct flm_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_categories;
+ uint32_t nb_size_mb;
+ uint32_t nb_entry_size;
+ uint32_t nb_variant;
+ uint32_t nb_prios;
+ uint32_t nb_pst_profiles;
+ union {
+ struct hw_mod_flm_v17_s v17;
+ struct hw_mod_flm_v20_s v20;
+ };
+};
+
+enum hw_flm_e {
+ /* functions */
+ HW_FLM_CONTROL_PRESET_ALL = 0,
+ HW_FLM_RCP_PRESET_ALL,
+ HW_FLM_FLOW_LRN_DATA_V17,
+ HW_FLM_FLOW_INF_DATA_V17,
+ HW_FLM_FLOW_STA_DATA_V17,
+ /* Control fields */
+ HW_FLM_CONTROL_ENABLE = FIELD_START_INDEX,
+ HW_FLM_CONTROL_INIT,
+ HW_FLM_CONTROL_LDS,
+ HW_FLM_CONTROL_LFS,
+ HW_FLM_CONTROL_LIS,
+ HW_FLM_CONTROL_UDS,
+ HW_FLM_CONTROL_UIS,
+ HW_FLM_CONTROL_RDS,
+ HW_FLM_CONTROL_RIS,
+ HW_FLM_CONTROL_PDS,
+ HW_FLM_CONTROL_PIS,
+ HW_FLM_CONTROL_CRCWR,
+ HW_FLM_CONTROL_CRCRD,
+ HW_FLM_CONTROL_RBL,
+ HW_FLM_CONTROL_EAB,
+ HW_FLM_CONTROL_SPLIT_SDRAM_USAGE,
+ HW_FLM_STATUS_CALIBDONE,
+ HW_FLM_STATUS_INITDONE,
+ HW_FLM_STATUS_IDLE,
+ HW_FLM_STATUS_CRITICAL,
+ HW_FLM_STATUS_PANIC,
+ HW_FLM_STATUS_CRCERR,
+ HW_FLM_STATUS_EFT_BP,
+ HW_FLM_TIMEOUT_T,
+ HW_FLM_SCRUB_I,
+ HW_FLM_LOAD_BIN,
+ HW_FLM_LOAD_PPS,
+ HW_FLM_LOAD_LPS,
+ HW_FLM_LOAD_APS,
+ HW_FLM_PRIO_LIMIT0,
+ HW_FLM_PRIO_FT0,
+ HW_FLM_PRIO_LIMIT1,
+ HW_FLM_PRIO_FT1,
+ HW_FLM_PRIO_LIMIT2,
+ HW_FLM_PRIO_FT2,
+ HW_FLM_PRIO_LIMIT3,
+ HW_FLM_PRIO_FT3,
+ HW_FLM_PST_PRESET_ALL,
+ HW_FLM_PST_BP,
+ HW_FLM_PST_PP,
+ HW_FLM_PST_TP,
+ HW_FLM_RCP_LOOKUP,
+ HW_FLM_RCP_QW0_DYN,
+ HW_FLM_RCP_QW0_OFS,
+ HW_FLM_RCP_QW0_SEL,
+ HW_FLM_RCP_QW4_DYN,
+ HW_FLM_RCP_QW4_OFS,
+ HW_FLM_RCP_SW8_DYN,
+ HW_FLM_RCP_SW8_OFS,
+ HW_FLM_RCP_SW8_SEL,
+ HW_FLM_RCP_SW9_DYN,
+ HW_FLM_RCP_SW9_OFS,
+ HW_FLM_RCP_MASK,
+ HW_FLM_RCP_KID,
+ HW_FLM_RCP_OPN,
+ HW_FLM_RCP_IPN,
+ HW_FLM_RCP_BYT_DYN,
+ HW_FLM_RCP_BYT_OFS,
+ HW_FLM_RCP_TXPLM,
+ HW_FLM_RCP_AUTO_IPV4_MASK,
+ HW_FLM_BUF_CTRL_LRN_FREE,
+ HW_FLM_BUF_CTRL_INF_AVAIL,
+ HW_FLM_BUF_CTRL_STA_AVAIL,
+ HW_FLM_STAT_LRN_DONE,
+ HW_FLM_STAT_LRN_IGNORE,
+ HW_FLM_STAT_LRN_FAIL,
+ HW_FLM_STAT_UNL_DONE,
+ HW_FLM_STAT_UNL_IGNORE,
+ HW_FLM_STAT_REL_DONE,
+ HW_FLM_STAT_REL_IGNORE,
+ HW_FLM_STAT_PRB_DONE,
+ HW_FLM_STAT_PRB_IGNORE,
+ HW_FLM_STAT_AUL_DONE,
+ HW_FLM_STAT_AUL_IGNORE,
+ HW_FLM_STAT_AUL_FAIL,
+ HW_FLM_STAT_TUL_DONE,
+ HW_FLM_STAT_FLOWS,
+ HW_FLM_STAT_STA_DONE, /* module ver 0.20 */
+ HW_FLM_STAT_INF_DONE, /* module ver 0.20 */
+ HW_FLM_STAT_INF_SKIP, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_HIT, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_MISS, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_UNH, /* module ver 0.20 */
+ HW_FLM_STAT_PCK_DIS, /* module ver 0.20 */
+ HW_FLM_STAT_CSH_HIT, /* module ver 0.20 */
+ HW_FLM_STAT_CSH_MISS, /* module ver 0.20 */
+ HW_FLM_STAT_CSH_UNH, /* module ver 0.20 */
+ HW_FLM_STAT_CUC_START, /* module ver 0.20 */
+ HW_FLM_STAT_CUC_MOVE, /* module ver 0.20 */
+};
+
+bool hw_mod_flm_present(struct flow_api_backend_s *be);
+int hw_mod_flm_alloc(struct flow_api_backend_s *be);
+void hw_mod_flm_free(struct flow_api_backend_s *be);
+int hw_mod_flm_reset(struct flow_api_backend_s *be);
+
+int hw_mod_flm_control_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_status_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_status_update(struct flow_api_backend_s *be);
+int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_prio_flush(struct flow_api_backend_s *be);
+int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value);
+int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value);
+int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value);
+
+int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value);
+int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value);
+int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value);
+
+int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be);
+int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_stat_update(struct flow_api_backend_s *be);
+int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value);
+
+int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be,
+ enum hw_flm_e field, const uint32_t *value);
+int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ uint32_t word_cnt);
+int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value);
+
+struct hsh_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp;
+ union {
+ struct hw_mod_hsh_v5_s v5;
+ };
+};
+
+enum hw_hsh_e {
+ /* functions */
+ HW_HSH_RCP_PRESET_ALL = 0,
+ HW_HSH_RCP_COMPARE,
+ HW_HSH_RCP_FIND,
+ /* fields */
+ HW_HSH_RCP_LOAD_DIST_TYPE = FIELD_START_INDEX,
+ HW_HSH_RCP_MAC_PORT_MASK,
+ HW_HSH_RCP_SORT,
+ HW_HSH_RCP_QW0_PE,
+ HW_HSH_RCP_QW0_OFS,
+ HW_HSH_RCP_QW4_PE,
+ HW_HSH_RCP_QW4_OFS,
+ HW_HSH_RCP_W8_PE,
+ HW_HSH_RCP_W8_OFS,
+ HW_HSH_RCP_W8_SORT,
+ HW_HSH_RCP_W9_PE,
+ HW_HSH_RCP_W9_OFS,
+ HW_HSH_RCP_W9_SORT,
+ HW_HSH_RCP_W9_P,
+ HW_HSH_RCP_P_MASK,
+ HW_HSH_RCP_WORD_MASK,
+ HW_HSH_RCP_SEED,
+ HW_HSH_RCP_TNL_P,
+ HW_HSH_RCP_HSH_VALID,
+ HW_HSH_RCP_HSH_TYPE,
+ HW_HSH_RCP_AUTO_IPV4_MASK
+
+};
+
+bool hw_mod_hsh_present(struct flow_api_backend_s *be);
+int hw_mod_hsh_alloc(struct flow_api_backend_s *be);
+void hw_mod_hsh_free(struct flow_api_backend_s *be);
+int hw_mod_hsh_reset(struct flow_api_backend_s *be);
+int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t value);
+int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value);
+
+struct qsl_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp_categories;
+ uint32_t nb_qst_entries;
+ union {
+ struct hw_mod_qsl_v7_s v7;
+ };
+};
+
+enum hw_qsl_e {
+ /* functions */
+ HW_QSL_RCP_PRESET_ALL = 0,
+ HW_QSL_RCP_COMPARE,
+ HW_QSL_RCP_FIND,
+ HW_QSL_QST_PRESET_ALL,
+ /* fields */
+ HW_QSL_RCP_DISCARD = FIELD_START_INDEX,
+ HW_QSL_RCP_DROP,
+ HW_QSL_RCP_TBL_LO,
+ HW_QSL_RCP_TBL_HI,
+ HW_QSL_RCP_TBL_IDX,
+ HW_QSL_RCP_TBL_MSK,
+ HW_QSL_RCP_LR,
+ HW_QSL_RCP_TSA,
+ HW_QSL_RCP_VLI,
+ HW_QSL_QST_QUEUE,
+ HW_QSL_QST_EN, /* Alias: HW_QSL_QST_QEN */
+ HW_QSL_QST_TX_PORT,
+ HW_QSL_QST_LRE,
+ HW_QSL_QST_TCI,
+ HW_QSL_QST_VEN,
+ HW_QSL_QEN_EN,
+ HW_QSL_UNMQ_DEST_QUEUE,
+ HW_QSL_UNMQ_EN,
+
+};
+
+bool hw_mod_qsl_present(struct flow_api_backend_s *be);
+int hw_mod_qsl_alloc(struct flow_api_backend_s *be);
+void hw_mod_qsl_free(struct flow_api_backend_s *be);
+int hw_mod_qsl_reset(struct flow_api_backend_s *be);
+int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value);
+
+struct slc_func_s {
+ COMMON_FUNC_INFO_S;
+ union {
+ struct hw_mod_slc_v1_s v1;
+ };
+};
+
+enum hw_slc_e {
+ /* functions */
+ HW_SLC_RCP_PRESET_ALL = 0,
+ HW_SLC_RCP_COMPARE,
+ HW_SLC_RCP_FIND,
+ /* fields */
+ HW_SLC_RCP_SLC_EN = FIELD_START_INDEX,
+ HW_SLC_RCP_DYN,
+ HW_SLC_RCP_OFS,
+ HW_SLC_RCP_PCAP
+};
+
+bool hw_mod_slc_present(struct flow_api_backend_s *be);
+int hw_mod_slc_alloc(struct flow_api_backend_s *be);
+void hw_mod_slc_free(struct flow_api_backend_s *be);
+int hw_mod_slc_reset(struct flow_api_backend_s *be);
+int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t *value);
+
+struct slc_lr_func_s {
+ COMMON_FUNC_INFO_S;
+ union {
+ struct hw_mod_slc_lr_v2_s v2;
+ };
+};
+
+enum hw_slc_lr_e {
+ /* functions */
+ HW_SLC_LR_RCP_PRESET_ALL = 0,
+ HW_SLC_LR_RCP_COMPARE,
+ HW_SLC_LR_RCP_FIND,
+ /* fields */
+ HW_SLC_LR_RCP_SLC_EN = FIELD_START_INDEX,
+ HW_SLC_LR_RCP_DYN,
+ HW_SLC_LR_RCP_OFS,
+ HW_SLC_LR_RCP_PCAP
+};
+
+bool hw_mod_slc_lr_present(struct flow_api_backend_s *be);
+int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be);
+void hw_mod_slc_lr_free(struct flow_api_backend_s *be);
+int hw_mod_slc_lr_reset(struct flow_api_backend_s *be);
+int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t *value);
+
+struct pdb_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_pdb_rcp_categories;
+
+ union {
+ struct hw_mod_pdb_v9_s v9;
+ };
+};
+
+enum hw_pdb_e {
+ /* functions */
+ HW_PDB_RCP_PRESET_ALL = 0,
+ HW_PDB_RCP_COMPARE,
+ HW_PDB_RCP_FIND,
+ /* fields */
+ HW_PDB_RCP_DESCRIPTOR = FIELD_START_INDEX,
+ HW_PDB_RCP_DESC_LEN,
+ HW_PDB_RCP_TX_PORT,
+ HW_PDB_RCP_TX_IGNORE,
+ HW_PDB_RCP_TX_NOW,
+ HW_PDB_RCP_CRC_OVERWRITE,
+ HW_PDB_RCP_ALIGN,
+ HW_PDB_RCP_OFS0_DYN,
+ HW_PDB_RCP_OFS0_REL,
+ HW_PDB_RCP_OFS1_DYN,
+ HW_PDB_RCP_OFS1_REL,
+ HW_PDB_RCP_OFS2_DYN,
+ HW_PDB_RCP_OFS2_REL,
+ HW_PDB_RCP_IP_PROT_TNL,
+ HW_PDB_RCP_PPC_HSH,
+ HW_PDB_RCP_DUPLICATE_EN,
+ HW_PDB_RCP_DUPLICATE_BIT,
+ HW_PDB_RCP_PCAP_KEEP_FCS,
+ HW_PDB_CONFIG_TS_FORMAT,
+ HW_PDB_CONFIG_PORT_OFS,
+};
+
+bool hw_mod_pdb_present(struct flow_api_backend_s *be);
+int hw_mod_pdb_alloc(struct flow_api_backend_s *be);
+void hw_mod_pdb_free(struct flow_api_backend_s *be);
+int hw_mod_pdb_reset(struct flow_api_backend_s *be);
+int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_pdb_config_flush(struct flow_api_backend_s *be);
+int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t value);
+
+struct ioa_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp_categories;
+ uint32_t nb_roa_epp_entries;
+ union {
+ struct hw_mod_ioa_v4_s v4;
+ };
+};
+
+enum hw_ioa_e {
+ /* functions */
+ HW_IOA_RCP_PRESET_ALL = 0,
+ HW_IOA_RCP_COMPARE,
+ HW_IOA_RCP_FIND,
+ HW_IOA_ROA_EPP_PRESET_ALL,
+ HW_IOA_ROA_EPP_COMPARE,
+ HW_IOA_ROA_EPP_FIND,
+ /* fields */
+ HW_IOA_RCP_TUNNEL_POP = FIELD_START_INDEX,
+ HW_IOA_RCP_VLAN_POP,
+ HW_IOA_RCP_VLAN_PUSH,
+ HW_IOA_RCP_VLAN_VID,
+ HW_IOA_RCP_VLAN_DEI,
+ HW_IOA_RCP_VLAN_PCP,
+ HW_IOA_RCP_VLAN_TPID_SEL,
+ HW_IOA_RCP_QUEUE_OVERRIDE_EN,
+ HW_IOA_RCP_QUEUE_ID,
+ HW_IOA_CONFIG_CUST_TPID_0,
+ HW_IOA_CONFIG_CUST_TPID_1,
+ HW_IOA_ROA_EPP_PUSH_TUNNEL,
+ HW_IOA_ROA_EPP_TX_PORT,
+};
+
+bool hw_mod_ioa_present(struct flow_api_backend_s *be);
+int hw_mod_ioa_alloc(struct flow_api_backend_s *be);
+void hw_mod_ioa_free(struct flow_api_backend_s *be);
+int hw_mod_ioa_reset(struct flow_api_backend_s *be);
+int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_ioa_config_flush(struct flow_api_backend_s *be);
+int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t value);
+
+int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+
+struct roa_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_tun_categories;
+ uint32_t nb_lag_entries;
+ union {
+ struct hw_mod_roa_v6_s v6;
+ };
+};
+
+enum hw_roa_e {
+ /* functions */
+ HW_ROA_TUNHDR_COMPARE = 0,
+ HW_ROA_TUNCFG_PRESET_ALL,
+ HW_ROA_TUNCFG_COMPARE,
+ HW_ROA_TUNCFG_FIND,
+ /* fields */
+ HW_ROA_TUNHDR = FIELD_START_INDEX,
+ HW_ROA_TUNCFG_TUN_LEN,
+ HW_ROA_TUNCFG_TUN_TYPE,
+ HW_ROA_TUNCFG_TUN_VLAN,
+ HW_ROA_TUNCFG_IP_TYPE,
+ HW_ROA_TUNCFG_IPCS_UPD,
+ HW_ROA_TUNCFG_IPCS_PRECALC,
+ HW_ROA_TUNCFG_IPTL_UPD,
+ HW_ROA_TUNCFG_IPTL_PRECALC,
+ HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD,
+ HW_ROA_TUNCFG_TX_LAG_IX,
+ HW_ROA_TUNCFG_RECIRCULATE,
+ HW_ROA_TUNCFG_PUSH_TUNNEL,
+ HW_ROA_TUNCFG_RECIRC_PORT,
+ HW_ROA_TUNCFG_RECIRC_BYPASS,
+ HW_ROA_CONFIG_FWD_RECIRCULATE,
+ HW_ROA_CONFIG_FWD_NORMAL_PCKS,
+ HW_ROA_CONFIG_FWD_TXPORT0,
+ HW_ROA_CONFIG_FWD_TXPORT1,
+ HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS,
+ HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS,
+ HW_ROA_LAGCFG_TXPHY_PORT,
+ HW_ROA_IGS_PKT_DROP,
+ HW_ROA_IGS_BYTE_DROP,
+ HW_ROA_RCC_PKT_DROP,
+ HW_ROA_RCC_BYTE_DROP,
+};
+
+bool hw_mod_roa_present(struct flow_api_backend_s *be);
+int hw_mod_roa_alloc(struct flow_api_backend_s *be);
+void hw_mod_roa_free(struct flow_api_backend_s *be);
+int hw_mod_roa_reset(struct flow_api_backend_s *be);
+int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t value);
+int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value);
+int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_roa_config_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value);
+int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value);
+int hw_mod_roa_igs_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_igs_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_igs_pkt_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_igs_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_igs_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_igs_byte_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_rcc_pkt_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_rcc_pkt_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_rcc_pkt_flush(struct flow_api_backend_s *be);
+int hw_mod_roa_rcc_byte_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value);
+int hw_mod_roa_rcc_byte_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value);
+int hw_mod_roa_rcc_byte_flush(struct flow_api_backend_s *be);
+
+struct rmc_func_s {
+ COMMON_FUNC_INFO_S;
+ union {
+ struct hw_mod_rmc_v1_3_s v1_3;
+ };
+};
+
+enum hw_rmc_e {
+ HW_RMC_BLOCK_STATT = FIELD_START_INDEX,
+ HW_RMC_BLOCK_KEEPA,
+ HW_RMC_BLOCK_RPP_SLICE,
+ HW_RMC_BLOCK_MAC_PORT,
+ HW_RMC_LAG_PHY_ODD_EVEN,
+};
+
+bool hw_mod_rmc_present(struct flow_api_backend_s *be);
+int hw_mod_rmc_alloc(struct flow_api_backend_s *be);
+void hw_mod_rmc_free(struct flow_api_backend_s *be);
+int hw_mod_rmc_reset(struct flow_api_backend_s *be);
+int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t value);
+int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t *value);
+int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be);
+
+struct tpe_func_s {
+ COMMON_FUNC_INFO_S;
+ uint32_t nb_rcp_categories;
+ uint32_t nb_ifr_categories;
+ uint32_t nb_cpy_writers;
+ uint32_t nb_rpl_depth;
+ uint32_t nb_rpl_ext_categories;
+ union {
+ struct hw_mod_tpe_v1_s v1;
+ struct hw_mod_tpe_v2_s v2;
+ };
+};
+
+enum hw_tpe_e {
+ /* functions */
+ HW_TPE_PRESET_ALL = 0,
+ HW_TPE_FIND,
+ HW_TPE_COMPARE,
+ /* Control fields */
+ HW_TPE_RPP_RCP_EXP = FIELD_START_INDEX,
+ HW_TPE_IFR_RCP_EN,
+ HW_TPE_IFR_RCP_MTU,
+ HW_TPE_INS_RCP_DYN,
+ HW_TPE_INS_RCP_OFS,
+ HW_TPE_INS_RCP_LEN,
+ HW_TPE_RPL_RCP_DYN,
+ HW_TPE_RPL_RCP_OFS,
+ HW_TPE_RPL_RCP_LEN,
+ HW_TPE_RPL_RCP_RPL_PTR,
+ HW_TPE_RPL_RCP_EXT_PRIO,
+ HW_TPE_RPL_EXT_RPL_PTR,
+ HW_TPE_RPL_EXT_META_RPL_LEN, /* SW only */
+ HW_TPE_RPL_RPL_VALUE,
+ HW_TPE_CPY_RCP_READER_SELECT,
+ HW_TPE_CPY_RCP_DYN,
+ HW_TPE_CPY_RCP_OFS,
+ HW_TPE_CPY_RCP_LEN,
+ HW_TPE_HFU_RCP_LEN_A_WR,
+ HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN,
+ HW_TPE_HFU_RCP_LEN_A_POS_DYN,
+ HW_TPE_HFU_RCP_LEN_A_POS_OFS,
+ HW_TPE_HFU_RCP_LEN_A_ADD_DYN,
+ HW_TPE_HFU_RCP_LEN_A_ADD_OFS,
+ HW_TPE_HFU_RCP_LEN_A_SUB_DYN,
+ HW_TPE_HFU_RCP_LEN_B_WR,
+ HW_TPE_HFU_RCP_LEN_B_POS_DYN,
+ HW_TPE_HFU_RCP_LEN_B_POS_OFS,
+ HW_TPE_HFU_RCP_LEN_B_ADD_DYN,
+ HW_TPE_HFU_RCP_LEN_B_ADD_OFS,
+ HW_TPE_HFU_RCP_LEN_B_SUB_DYN,
+ HW_TPE_HFU_RCP_LEN_C_WR,
+ HW_TPE_HFU_RCP_LEN_C_POS_DYN,
+ HW_TPE_HFU_RCP_LEN_C_POS_OFS,
+ HW_TPE_HFU_RCP_LEN_C_ADD_DYN,
+ HW_TPE_HFU_RCP_LEN_C_ADD_OFS,
+ HW_TPE_HFU_RCP_LEN_C_SUB_DYN,
+ HW_TPE_HFU_RCP_TTL_WR,
+ HW_TPE_HFU_RCP_TTL_POS_DYN,
+ HW_TPE_HFU_RCP_TTL_POS_OFS,
+ HW_TPE_HFU_RCP_CS_INF,
+ HW_TPE_HFU_RCP_L3_PRT,
+ HW_TPE_HFU_RCP_L3_FRAG,
+ HW_TPE_HFU_RCP_TUNNEL,
+ HW_TPE_HFU_RCP_L4_PRT,
+ HW_TPE_HFU_RCP_OUTER_L3_OFS,
+ HW_TPE_HFU_RCP_OUTER_L4_OFS,
+ HW_TPE_HFU_RCP_INNER_L3_OFS,
+ HW_TPE_HFU_RCP_INNER_L4_OFS,
+ HW_TPE_CSU_RCP_OUTER_L3_CMD,
+ HW_TPE_CSU_RCP_OUTER_L4_CMD,
+ HW_TPE_CSU_RCP_INNER_L3_CMD,
+ HW_TPE_CSU_RCP_INNER_L4_CMD,
+};
+
+bool hw_mod_tpe_present(struct flow_api_backend_s *be);
+int hw_mod_tpe_alloc(struct flow_api_backend_s *be);
+void hw_mod_tpe_free(struct flow_api_backend_s *be);
+int hw_mod_tpe_reset(struct flow_api_backend_s *be);
+
+int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t value);
+int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t *value);
+
+int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count);
+int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value);
+int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value);
+
+enum debug_mode_e {
+ FLOW_BACKEND_DEBUG_MODE_NONE = 0x0000,
+ FLOW_BACKEND_DEBUG_MODE_WRITE = 0x0001
+};
+
+struct flow_api_backend_ops {
+ int version;
+ int (*set_debug_mode)(void *dev, enum debug_mode_e mode);
+ int (*get_nb_phy_port)(void *dev);
+ int (*get_nb_rx_port)(void *dev);
+ int (*get_ltx_avail)(void *dev);
+ int (*get_nb_cat_funcs)(void *dev);
+ int (*get_nb_categories)(void *dev);
+ int (*get_nb_cat_km_if_cnt)(void *dev);
+ int (*get_nb_cat_km_if_m0)(void *dev);
+ int (*get_nb_cat_km_if_m1)(void *dev);
+
+ int (*get_nb_queues)(void *dev);
+ int (*get_nb_km_flow_types)(void *dev);
+ int (*get_nb_pm_ext)(void *dev);
+ int (*get_nb_len)(void *dev);
+ int (*get_kcc_size)(void *dev);
+ int (*get_kcc_banks)(void *dev);
+ int (*get_nb_km_categories)(void *dev);
+ int (*get_nb_km_cam_banks)(void *dev);
+ int (*get_nb_km_cam_record_words)(void *dev);
+ int (*get_nb_km_cam_records)(void *dev);
+ int (*get_nb_km_tcam_banks)(void *dev);
+ int (*get_nb_km_tcam_bank_width)(void *dev);
+ int (*get_nb_flm_categories)(void *dev);
+ int (*get_nb_flm_size_mb)(void *dev);
+ int (*get_nb_flm_entry_size)(void *dev);
+ int (*get_nb_flm_variant)(void *dev);
+ int (*get_nb_flm_prios)(void *dev);
+ int (*get_nb_flm_pst_profiles)(void *dev);
+ int (*get_nb_hst_categories)(void *dev);
+ int (*get_nb_qsl_categories)(void *dev);
+ int (*get_nb_qsl_qst_entries)(void *dev);
+ int (*get_nb_pdb_categories)(void *dev);
+ int (*get_nb_ioa_categories)(void *dev);
+ int (*get_nb_roa_categories)(void *dev);
+ int (*get_nb_tpe_categories)(void *dev);
+ int (*get_nb_tx_cpy_writers)(void *dev);
+ int (*get_nb_tx_cpy_mask_mem)(void *dev);
+ int (*get_nb_tx_rpl_depth)(void *dev);
+ int (*get_nb_tx_rpl_ext_categories)(void *dev);
+ int (*get_nb_tpe_ifr_categories)(void *dev);
+
+ int (*alloc_rx_queue)(void *dev, int queue_id);
+ int (*free_rx_queue)(void *dev, int hw_queue);
+
+ /* CAT */
+ bool (*get_cat_present)(void *dev);
+ uint32_t (*get_cat_version)(void *dev);
+ int (*cat_cfn_flush)(void *dev, const struct cat_func_s *cat,
+ int cat_func, int cnt);
+ int (*cat_kce_flush)(void *dev, const struct cat_func_s *cat,
+ int km_if_idx, int index, int cnt);
+ int (*cat_kcs_flush)(void *dev, const struct cat_func_s *cat,
+ int km_if_idx, int cat_func, int cnt);
+ int (*cat_fte_flush)(void *dev, const struct cat_func_s *cat,
+ int km_if_idx, int index, int cnt);
+ int (*cat_cte_flush)(void *dev, const struct cat_func_s *cat,
+ int cat_func, int cnt);
+ int (*cat_cts_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_cot_flush)(void *dev, const struct cat_func_s *cat,
+ int cat_func, int cnt);
+ int (*cat_cct_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_exo_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_rck_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_len_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_kcc_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_cce_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+ int (*cat_ccs_flush)(void *dev, const struct cat_func_s *cat, int index,
+ int cnt);
+
+ /* KM */
+ bool (*get_km_present)(void *dev);
+ uint32_t (*get_km_version)(void *dev);
+ int (*km_rcp_flush)(void *dev, const struct km_func_s *km, int category,
+ int cnt);
+ int (*km_cam_flush)(void *dev, const struct km_func_s *km, int bank,
+ int record, int cnt);
+ int (*km_tcam_flush)(void *dev, const struct km_func_s *km, int bank,
+ int byte, int value, int cnt);
+ int (*km_tci_flush)(void *dev, const struct km_func_s *km, int bank,
+ int record, int cnt);
+ int (*km_tcq_flush)(void *dev, const struct km_func_s *km, int bank,
+ int record, int cnt);
+
+ /* FLM */
+ bool (*get_flm_present)(void *dev);
+ uint32_t (*get_flm_version)(void *dev);
+ int (*flm_control_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_status_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_status_update)(void *dev, const struct flm_func_s *flm);
+ int (*flm_timeout_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_scrub_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_bin_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_pps_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_lps_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_load_aps_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_prio_flush)(void *dev, const struct flm_func_s *flm);
+ int (*flm_pst_flush)(void *dev, const struct flm_func_s *flm, int index,
+ int cnt);
+ int (*flm_rcp_flush)(void *dev, const struct flm_func_s *flm, int index,
+ int cnt);
+ int (*flm_buf_ctrl_update)(void *dev, const struct flm_func_s *flm);
+ int (*flm_stat_update)(void *dev, const struct flm_func_s *flm);
+ int (*flm_lrn_data_flush)(void *be_dev, const struct flm_func_s *flm,
+ const uint32_t *lrn_data, uint32_t size);
+ int (*flm_inf_data_update)(void *be_dev, const struct flm_func_s *flm,
+ uint32_t *lrn_data, uint32_t size);
+ int (*flm_sta_data_update)(void *be_dev, const struct flm_func_s *flm,
+ uint32_t *lrn_data, uint32_t size);
+
+ /* HSH */
+ bool (*get_hsh_present)(void *dev);
+ uint32_t (*get_hsh_version)(void *dev);
+ int (*hsh_rcp_flush)(void *dev, const struct hsh_func_s *hsh,
+ int category, int cnt);
+
+ /* HST */
+ bool (*get_hst_present)(void *dev);
+ uint32_t (*get_hst_version)(void *dev);
+ int (*hst_rcp_flush)(void *dev, const struct hst_func_s *hst,
+ int category, int cnt);
+
+ /* QSL */
+ bool (*get_qsl_present)(void *dev);
+ uint32_t (*get_qsl_version)(void *dev);
+ int (*qsl_rcp_flush)(void *dev, const struct qsl_func_s *qsl,
+ int category, int cnt);
+ int (*qsl_qst_flush)(void *dev, const struct qsl_func_s *qsl, int entry,
+ int cnt);
+ int (*qsl_qen_flush)(void *dev, const struct qsl_func_s *qsl, int entry,
+ int cnt);
+ int (*qsl_unmq_flush)(void *dev, const struct qsl_func_s *qsl,
+ int entry, int cnt);
+
+ /* SLC */
+ bool (*get_slc_present)(void *dev);
+ uint32_t (*get_slc_version)(void *dev);
+ int (*slc_rcp_flush)(void *dev, const struct slc_func_s *slc,
+ int category, int cnt);
+
+ /* SLC LR */
+ bool (*get_slc_lr_present)(void *dev);
+ uint32_t (*get_slc_lr_version)(void *dev);
+ int (*slc_lr_rcp_flush)(void *dev, const struct slc_lr_func_s *slc_lr,
+ int category, int cnt);
+
+ /* PDB */
+ bool (*get_pdb_present)(void *dev);
+ uint32_t (*get_pdb_version)(void *dev);
+ int (*pdb_rcp_flush)(void *dev, const struct pdb_func_s *pdb,
+ int category, int cnt);
+ int (*pdb_config_flush)(void *dev, const struct pdb_func_s *pdb);
+
+ /* IOA */
+ bool (*get_ioa_present)(void *dev);
+ uint32_t (*get_ioa_version)(void *dev);
+ int (*ioa_rcp_flush)(void *dev, const struct ioa_func_s *ioa, int index,
+ int cnt);
+ int (*ioa_special_tpid_flush)(void *dev, const struct ioa_func_s *ioa);
+ int (*ioa_roa_epp_flush)(void *dev, const struct ioa_func_s *ioa,
+ int index, int cnt);
+
+ /* ROA */
+ bool (*get_roa_present)(void *dev);
+ uint32_t (*get_roa_version)(void *dev);
+ int (*roa_tunhdr_flush)(void *dev, const struct roa_func_s *roa,
+ int index, int cnt);
+ int (*roa_tuncfg_flush)(void *dev, const struct roa_func_s *roa,
+ int index, int cnt);
+ int (*roa_config_flush)(void *dev, const struct roa_func_s *roa);
+ int (*roa_lagcfg_flush)(void *dev, const struct roa_func_s *roa,
+ int index, int cnt);
+
+ /* RMC */
+ bool (*get_rmc_present)(void *dev);
+ uint32_t (*get_rmc_version)(void *dev);
+ int (*rmc_ctrl_flush)(void *dev, const struct rmc_func_s *rmc);
+
+ /* TPE */
+ bool (*get_tpe_present)(void *dev);
+ uint32_t (*get_tpe_version)(void *dev);
+ int (*tpe_rpp_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpp_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_ifr_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_ins_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpl_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpl_ext_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_rpl_rpl_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_cpy_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_hfu_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+ int (*tpe_csu_rcp_flush)(void *dev, const struct tpe_func_s *tpe,
+ int index, int cnt);
+};
+
+struct flow_api_backend_s {
+ void *be_dev;
+ const struct flow_api_backend_ops *iface;
+
+ /* flow filter FPGA modules */
+ struct cat_func_s cat;
+ struct km_func_s km;
+ struct flm_func_s flm;
+ struct hsh_func_s hsh;
+ struct hst_func_s hst;
+ struct qsl_func_s qsl;
+ struct slc_func_s slc;
+ struct slc_lr_func_s slc_lr;
+ struct pdb_func_s pdb;
+ struct ioa_func_s ioa;
+ struct roa_func_s roa;
+ struct rmc_func_s rmc;
+ struct tpe_func_s tpe;
+
+ /* NIC attributes */
+ unsigned int num_phy_ports;
+ unsigned int num_rx_ports;
+
+ /* flow filter resource capacities */
+ unsigned int max_categories;
+ unsigned int max_queues;
+};
+
+int flow_api_backend_init(struct flow_api_backend_s *dev,
+ const struct flow_api_backend_ops *iface,
+ void *be_dev);
+int flow_api_backend_reset(struct flow_api_backend_s *dev);
+int flow_api_backend_done(struct flow_api_backend_s *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FLOW_API_BACKEND_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h
new file mode 100644
index 0000000000..bee12b71f7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_engine.h
@@ -0,0 +1,475 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_API_ENGINE_H_
+#define _FLOW_API_ENGINE_H_
+
+#include <stdint.h>
+#include "stream_binary_flow_api.h"
+
+struct flow_elem;
+/*
+ * ****************************************************
+ * Resource management
+ * ****************************************************
+ */
+#define BIT_CONTAINER_8_ALIGN(x) (((x) + 7) / 8)
+
+/*
+ * Resource management
+ * These are free resources in FPGA
+ * Other FPGA memory lists are linked to one of these
+ * and will implicitly follow them
+ */
+enum res_type_e {
+ RES_QUEUE,
+ RES_CAT_CFN,
+ RES_CAT_COT,
+ RES_CAT_EXO,
+ RES_CAT_LEN,
+ RES_KM_FLOW_TYPE,
+ RES_KM_CATEGORY,
+ RES_HSH_RCP,
+ RES_PDB_RCP,
+ RES_QSL_RCP,
+ RES_QSL_QST,
+ RES_SLC_RCP,
+ RES_IOA_RCP,
+ RES_ROA_RCP,
+ RES_FLM_FLOW_TYPE,
+ RES_FLM_RCP,
+ RES_HST_RCP,
+ RES_TPE_RCP,
+ RES_TPE_EXT,
+ RES_TPE_RPL,
+ RES_COUNT,
+ RES_INVALID
+};
+
+/*
+ * ****************************************************
+ * Flow NIC offload management
+ * ****************************************************
+ */
+#define MAX_OUTPUT_DEST (128)
+#define NB_QSL_QEN_ADDR 32
+
+#define INVALID_FLOW_STAT_ID 0xffffffff
+
+#define MAX_WORD_NUM 24
+#define MAX_BANKS 6
+
+#define MAX_TCAM_START_OFFSETS 4
+
+#define MAX_TAG_INDEX 8
+
+#define MAX_FLM_MTRS_SUPPORTED 4
+#define MAX_CPY_WRITERS_SUPPORTED 8
+
+/*
+ * 128 128 32 32 32
+ * Have | QW0 || QW4 || SW8 || SW9 | SWX in FPGA
+ *
+ * Each word may start at any offset, though
+ * they are combined in chronological order, with all enabled to
+ * build the extracted match data, thus that is how the match key
+ * must be build
+ *
+ */
+enum extractor_e {
+ KM_USE_EXTRACTOR_UNDEF,
+ KM_USE_EXTRACTOR_QWORD,
+ KM_USE_EXTRACTOR_SWORD,
+};
+
+struct match_elem_s {
+ enum extractor_e extr;
+ int masked_for_tcam; /* if potentially selected for TCAM */
+ uint32_t e_word[4];
+ uint32_t e_mask[4];
+
+ int extr_start_offs_id;
+ int8_t rel_offs;
+ uint32_t word_len;
+};
+
+enum cam_tech_use_e { KM_CAM, KM_TCAM, KM_SYNERGY };
+
+#define MAX_MATCH_FIELDS 16
+
+struct km_flow_def_s {
+ struct flow_api_backend_s *be;
+
+ /* For keeping track of identical entries */
+ struct km_flow_def_s *reference;
+ struct km_flow_def_s *root;
+
+ /* For collect flow elements and sorting */
+ struct match_elem_s match[MAX_MATCH_FIELDS];
+ struct match_elem_s *match_map[MAX_MATCH_FIELDS];
+ int num_ftype_elem;
+
+ /* Finally formatted CAM/TCAM entry */
+ enum cam_tech_use_e target;
+ uint32_t entry_word[MAX_WORD_NUM];
+ uint32_t entry_mask[MAX_WORD_NUM];
+ int key_word_size;
+
+ /* TCAM calculated possible bank start offsets */
+ int start_offsets[MAX_TCAM_START_OFFSETS];
+ int num_start_offsets;
+
+ /* Flow information */
+
+ /*
+ * HW input port ID needed for compare. In port must be identical on flow
+ * types
+ */
+ uint32_t port_id;
+ uint32_t info; /* used for color (actions) */
+ int info_set;
+ int flow_type; /* 0 is illegal and used as unset */
+ int flushed_to_target; /* if this km entry has been finally programmed into NIC hw */
+
+ /* CAM specific bank management */
+ int cam_paired;
+ int record_indexes[MAX_BANKS];
+ int bank_used;
+ uint32_t *cuckoo_moves; /* for CAM statistics only */
+ struct cam_distrib_s *cam_dist;
+ struct hasher_s *hsh;
+
+ /* TCAM specific bank management */
+ struct tcam_distrib_s *tcam_dist;
+ int tcam_start_bank;
+ int tcam_record;
+};
+
+/*
+ * KCC-CAM
+ */
+struct kcc_key_s {
+ uint64_t sb_data : 32;
+ uint64_t sb_type : 8;
+ uint64_t cat_cfn : 8;
+ uint64_t port : 16;
+};
+
+#define KCC_ID_INVALID 0xffffffff
+
+struct kcc_flow_def_s {
+ struct flow_api_backend_s *be;
+ union {
+ uint64_t key64;
+ uint32_t key32[2];
+ struct kcc_key_s key;
+ };
+ uint32_t km_category;
+ uint32_t id;
+
+ uint8_t *kcc_unique_ids;
+
+ int flushed_to_target;
+ int record_indexes[MAX_BANKS];
+ int bank_used;
+ uint32_t *cuckoo_moves; /* for CAM statistics only */
+ struct kcc_cam_distrib_s *cam_dist;
+ struct hasher_s *hsh;
+};
+
+/*
+ * Tunnel encapsulation header definition
+ */
+enum { TUN_TYPE_VXLAN = 0, TUN_TYPE_NVGRE = 1 };
+
+#define MAX_TUN_HDR_SIZE 128
+
+struct tunnel_header_s {
+ union {
+ uint8_t hdr8[MAX_TUN_HDR_SIZE];
+ uint32_t hdr32[(MAX_TUN_HDR_SIZE + 3) / 4];
+ } d;
+ uint32_t user_port_id;
+ uint8_t len;
+
+ uint8_t nb_vlans;
+
+ uint8_t ip_version; /* 4: v4, 6: v6 */
+ uint16_t ip_csum_precalc;
+
+ uint8_t new_outer;
+ uint8_t l2_len;
+ uint8_t l3_len;
+ uint8_t l4_len;
+};
+
+enum port_type_e {
+ PORT_NONE, /* not defined or drop */
+ PORT_INTERNAL, /* no queues attached */
+ PORT_PHY, /* MAC phy output queue */
+ PORT_VIRT, /* Memory queues to Host */
+};
+
+enum special_partial_match_e {
+ SPCIAL_MATCH_NONE,
+ SPECIAL_MATCH_LACP,
+};
+
+#define PORT_ID_NONE 0xffffffff
+
+struct output_s {
+ uint32_t owning_port_id; /* the port who owns this output destination */
+ enum port_type_e type;
+ int id; /* depending on port type: queue ID or physical port id or not used */
+ int active; /* activated */
+};
+
+struct nic_flow_def {
+ /*
+ * Frame Decoder match info collected
+ */
+ int l2_prot;
+ int l3_prot;
+ int l4_prot;
+ int tunnel_prot;
+ int tunnel_l3_prot;
+ int tunnel_l4_prot;
+ int vlans;
+ int fragmentation;
+ /*
+ * Additional meta data for various functions
+ */
+ int in_port_override;
+ int l4_dst_port;
+ /*
+ * Output destination info collection
+ */
+ struct output_s dst_id[MAX_OUTPUT_DEST]; /* define the output to use */
+ /* total number of available queues defined for all outputs - i.e. number of dst_id's */
+ int dst_num_avail;
+
+ /*
+ * To identify high priority match with mark for special SW processing (non-OVS)
+ */
+ enum special_partial_match_e special_match;
+
+ /*
+ * Mark or Action info collection
+ */
+ uint32_t mark;
+ uint64_t roa_actions;
+ uint64_t ioa_actions;
+
+ uint32_t jump_to_group;
+
+ uint32_t mtr_ids[MAX_FLM_MTRS_SUPPORTED];
+
+ int full_offload;
+ /*
+ * Action push tunnel
+ */
+ struct tunnel_header_s tun_hdr;
+
+ /*
+ * If DPDK RTE tunnel helper API used
+ * this holds the tunnel if used in flow
+ */
+ struct tunnel_s *tnl;
+
+ /*
+ * Header Stripper
+ */
+ int header_strip_start_dyn;
+ int header_strip_start_ofs;
+ int header_strip_end_dyn;
+ int header_strip_end_ofs;
+ int header_strip_removed_outer_ip;
+
+ /*
+ * Modify field
+ */
+ struct {
+ uint32_t select;
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+ uint32_t level;
+ union {
+ uint8_t value8[16];
+ uint16_t value16[8];
+ uint32_t value32[4];
+ };
+ } modify_field[MAX_CPY_WRITERS_SUPPORTED];
+
+ uint32_t modify_field_count;
+ uint8_t ttl_sub_enable;
+ uint8_t ttl_sub_ipv4;
+ uint8_t ttl_sub_outer;
+
+ /*
+ * Key Matcher flow definitions
+ */
+ struct km_flow_def_s km;
+
+ /*
+ * Key Matcher Category CAM
+ */
+ struct kcc_flow_def_s *kcc;
+ int kcc_referenced;
+
+ /*
+ * TX fragmentation IFR/RPP_LR MTU recipe
+ */
+ uint8_t flm_mtu_fragmentation_recipe;
+};
+
+enum flow_handle_type {
+ FLOW_HANDLE_TYPE_FLOW,
+ FLOW_HANDLE_TYPE_FLM,
+};
+
+struct flow_handle {
+ enum flow_handle_type type;
+
+ struct flow_eth_dev *dev;
+ struct flow_handle *next;
+ struct flow_handle *prev;
+
+ union {
+ struct {
+ /*
+ * 1st step conversion and validation of flow
+ * verified and converted flow match + actions structure
+ */
+ struct nic_flow_def *fd;
+ /*
+ * 2nd step NIC HW resource allocation and configuration
+ * NIC resource management structures
+ */
+ struct {
+ int index; /* allocation index into NIC raw resource table */
+ /* number of contiguous allocations needed for this resource */
+ int count;
+ /*
+ * This resource if not initially created by this flow, but reused
+ * by it
+ */
+ int referenced;
+ } resource[RES_COUNT];
+ int flushed;
+
+ uint32_t flow_stat_id;
+ uint32_t color;
+ int cao_enabled;
+ uint32_t cte;
+
+ uint32_t port_id; /* MAC port ID or override of virtual in_port */
+ uint32_t flm_ref_count;
+ uint8_t flm_group_index;
+ uint8_t flm_ft_index;
+ };
+
+ struct {
+ uint32_t flm_data[10];
+ uint8_t flm_prot;
+ uint8_t flm_kid;
+ uint8_t flm_prio;
+
+ uint16_t flm_rpl_ext_ptr;
+ uint32_t flm_nat_ipv4;
+ uint16_t flm_nat_port;
+ uint8_t flm_dscp;
+ uint32_t flm_teid;
+ uint8_t flm_rqi;
+ uint8_t flm_qfi;
+
+ uint8_t flm_mtu_fragmentation_recipe;
+
+ struct flow_handle *flm_owner;
+ };
+ };
+};
+
+void km_attach_ndev_resource_management(struct km_flow_def_s *km,
+ void **handle);
+void km_free_ndev_resource_management(void **handle);
+
+int km_get_cam_population_level(void *cam_dist, uint32_t *cam_elem,
+ uint32_t *cuckoo_moves);
+
+int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4],
+ uint32_t e_mask[4], uint32_t word_len,
+ enum frame_offs_e start, int8_t offset);
+
+int km_key_create(struct km_flow_def_s *km, uint32_t port_id);
+/*
+ * Compares 2 KM key definitions after first collect validate and optimization.
+ * km is compared against an existing km1.
+ * if identical, km1 flow_type is returned
+ */
+int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1);
+
+void km_set_info(struct km_flow_def_s *km, int on);
+int km_rcp_set(struct km_flow_def_s *km, int index);
+
+int km_refer_data_match_entry(struct km_flow_def_s *km,
+ struct km_flow_def_s *km1);
+int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color);
+int km_clear_data_match_entry(struct km_flow_def_s *km);
+
+void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc,
+ void **handle);
+void kcc_free_ndev_resource_management(void **handle);
+int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc);
+void kcc_free_unique_id(struct kcc_flow_def_s *kcc);
+int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1);
+int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category);
+
+int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc);
+int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid);
+int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni);
+int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port);
+int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn);
+uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc);
+
+int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc);
+int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc);
+int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc);
+
+/*
+ * Group management
+ */
+int flow_group_handle_create(void **handle, uint32_t group_count);
+int flow_group_handle_destroy(void **handle);
+
+int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in,
+ uint32_t *group_out);
+int flow_group_translate_release(void *handle, uint32_t translated_group);
+
+/*
+ * Actions management
+ */
+uint8_t flow_tunnel_alloc_virt_port(void);
+uint8_t flow_tunnel_free_virt_port(uint8_t virt_port);
+struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx,
+ uint32_t *vni);
+int tunnel_release(struct tunnel_s *tnl);
+uint8_t get_tunnel_vport(struct tunnel_s *rtnl);
+void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id);
+int tunnel_get_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,
+ uint8_t vport);
+
+int is_virtual_port(uint8_t virt_port);
+int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be,
+ struct nic_flow_def *fd,
+ const struct flow_elem *elem);
+
+/*
+ * statistics
+ */
+uint32_t flow_actions_create_flow_stat_id(uint32_t *stat_map, uint32_t mark);
+void flow_actions_delete_flow_stat_id(uint32_t *stat_map,
+ uint32_t flow_stat_id);
+
+#endif /* _FLOW_API_ENGINE_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h
new file mode 100644
index 0000000000..c4db0f4c5c
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api_nic_setup.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __FLOW_API_NIC_SETUP_H__
+#define __FLOW_API_NIC_SETUP_H__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct flow_api_backend_ops; /* Operation list for common FPGA module API for backend */
+struct flow_nic_dev; /* adapter device */
+
+/*
+ * Flow capable NIC backend - creating flow api instance for adapter nr (backend)
+ */
+struct flow_nic_dev *flow_api_create(uint8_t adapter_no,
+ const struct flow_api_backend_ops *be_if,
+ void *be_dev);
+int flow_api_done(struct flow_nic_dev *dev);
+void *flow_api_get_be_dev(struct flow_nic_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FLOW_API_NIC_SETUP_H__ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c
new file mode 100644
index 0000000000..9b6e5484a0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_group.c
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define OWNER_ID_COUNT 256
+
+struct group_lookup_entry_s {
+ uint64_t ref_counter;
+ uint32_t *reverse_lookup;
+};
+
+struct group_handle_s {
+ uint32_t group_count;
+
+ uint32_t *translation_table;
+
+ struct group_lookup_entry_s *lookup_entries;
+};
+
+int flow_group_handle_create(void **handle, uint32_t group_count)
+{
+ struct group_handle_s *group_handle;
+
+ *handle = calloc(1, sizeof(struct group_handle_s));
+ group_handle = *handle;
+
+ group_handle->group_count = group_count;
+ group_handle->translation_table = calloc((uint32_t)(group_count * OWNER_ID_COUNT),
+ sizeof(uint32_t));
+ group_handle->lookup_entries =
+ calloc(group_count, sizeof(struct group_lookup_entry_s));
+
+ return *handle != NULL ? 0 : -1;
+}
+
+int flow_group_handle_destroy(void **handle)
+{
+ if (*handle) {
+ struct group_handle_s *group_handle =
+ (struct group_handle_s *)*handle;
+
+ free(group_handle->translation_table);
+ free(group_handle->lookup_entries);
+
+ free(*handle);
+ *handle = NULL;
+ }
+
+ return 0;
+}
+
+int flow_group_translate_get(void *handle, uint8_t owner_id, uint32_t group_in,
+ uint32_t *group_out)
+{
+ struct group_handle_s *group_handle = (struct group_handle_s *)handle;
+ uint32_t *table_ptr;
+ uint32_t lookup;
+
+ if (group_handle == NULL || group_in >= group_handle->group_count)
+ return -1;
+
+ /* Don't translate group 0 */
+ if (group_in == 0) {
+ *group_out = 0;
+ return 0;
+ }
+
+ table_ptr = &group_handle->translation_table[owner_id * OWNER_ID_COUNT +
+ group_in];
+ lookup = *table_ptr;
+
+ if (lookup == 0) {
+ for (lookup = 1;
+ lookup < group_handle->group_count &&
+ group_handle->lookup_entries[lookup].ref_counter > 0;
+ ++lookup)
+ ;
+
+ if (lookup < group_handle->group_count) {
+ group_handle->lookup_entries[lookup].reverse_lookup =
+ table_ptr;
+ group_handle->lookup_entries[lookup].ref_counter += 1;
+
+ *table_ptr = lookup;
+ } else {
+ return -1;
+ }
+ } else {
+ group_handle->lookup_entries[lookup].ref_counter += 1;
+ }
+ *group_out = lookup;
+ return 0;
+}
+
+int flow_group_translate_release(void *handle, uint32_t translated_group)
+{
+ struct group_handle_s *group_handle = (struct group_handle_s *)handle;
+ struct group_lookup_entry_s *lookup;
+
+ if (group_handle == NULL ||
+ translated_group >= group_handle->group_count)
+ return -1;
+
+ /* Don't translate group 0 */
+ if (translated_group == 0)
+ return 0;
+
+ lookup = &group_handle->lookup_entries[translated_group];
+
+ if (lookup->reverse_lookup && lookup->ref_counter > 0) {
+ lookup->ref_counter -= 1;
+ if (lookup->ref_counter == 0) {
+ *lookup->reverse_lookup = 0;
+ lookup->reverse_lookup = NULL;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c
new file mode 100644
index 0000000000..6982129e17
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.c
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "flow_hasher.h"
+
+#include <math.h>
+
+/* #define TESTING */
+
+#ifdef TESTING
+#include <stdio.h>
+int hash_test(struct hasher_s *hsh, int banks, int record_bw);
+#endif
+
+static uint32_t shuffle(uint32_t x)
+{
+ return (((x & 0x00000002) << 29) | ((x & 0xAAAAAAA8) >> 3) |
+ ((x & 0x15555555) << 3) | ((x & 0x40000000) >> 29));
+}
+
+static uint32_t ror_inv(uint32_t x, const int s)
+{
+ return ((x >> s) | ((~x) << (32 - s)));
+}
+
+static uint32_t combine(uint32_t x, uint32_t y)
+{
+ uint32_t x1 = ror_inv(x, 15);
+ uint32_t x2 = ror_inv(x, 13);
+ uint32_t y1 = ror_inv(y, 3);
+ uint32_t y2 = ror_inv(y, 27);
+
+ return (x ^ y ^
+ ((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) |
+ (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) |
+ (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2)));
+}
+
+static uint32_t mix(uint32_t x, uint32_t y)
+{
+ return shuffle(combine(x, y));
+}
+
+static uint64_t ror_inv3(uint64_t x)
+{
+ const uint64_t m = 0xE0000000E0000000ULL;
+
+ return (((x >> 3) | m) ^ ((x << 29) & m));
+}
+
+static uint64_t ror_inv13(uint64_t x)
+{
+ const uint64_t m = 0xFFF80000FFF80000ULL;
+
+ return (((x >> 13) | m) ^ ((x << 19) & m));
+}
+
+static uint64_t ror_inv15(uint64_t x)
+{
+ const uint64_t m = 0xFFFE0000FFFE0000ULL;
+
+ return (((x >> 15) | m) ^ ((x << 17) & m));
+}
+
+static uint64_t ror_inv27(uint64_t x)
+{
+ const uint64_t m = 0xFFFFFFE0FFFFFFE0ULL;
+
+ return (((x >> 27) | m) ^ ((x << 5) & m));
+}
+
+static uint64_t shuffle64(uint64_t x)
+{
+ return (((x & 0x0000000200000002) << 29) |
+ ((x & 0xAAAAAAA8AAAAAAA8) >> 3) |
+ ((x & 0x1555555515555555) << 3) |
+ ((x & 0x4000000040000000) >> 29));
+}
+
+static uint64_t pair(uint32_t x, uint32_t y)
+{
+ return (((uint64_t)x << 32) | y);
+}
+
+static uint64_t combine64(uint64_t x, uint64_t y)
+{
+ uint64_t x1 = ror_inv15(x);
+ uint64_t x2 = ror_inv13(x);
+ uint64_t y1 = ror_inv3(y);
+ uint64_t y2 = ror_inv27(y);
+
+ return (x ^ y ^
+ ((x1 & y1 & ~x2 & ~y2) | (x1 & ~y1 & x2 & ~y2) |
+ (x1 & ~y1 & ~x2 & y2) | (~x1 & y1 & x2 & ~y2) |
+ (~x1 & y1 & ~x2 & y2) | (~x1 & ~y1 & x2 & y2)));
+}
+
+static uint64_t mix64(uint64_t x, uint64_t y)
+{
+ return shuffle64(combine64(x, y));
+}
+
+static uint32_t calc16(const uint32_t key[16])
+{
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Layer 0 */
+ /* \./ \./ \./ \./ \./ \./ \./ \./ */
+ /* 0 1 2 3 4 5 6 7 Layer 1 */
+ /* \__.__/ \__.__/ \__.__/ \__.__/ */
+ /* 0 1 2 3 Layer 2 */
+ /* \______.______/ \______.______/ */
+ /* 0 1 Layer 3 */
+ /* \______________.______________/ */
+ /* 0 Layer 4 */
+ /* / \ */
+ /* \./ */
+ /* 0 Layer 5 */
+ /* / \ */
+ /* \./ Layer 6 */
+ /* value */
+
+ uint64_t z;
+ uint32_t x;
+
+ z = mix64(mix64(mix64(pair(key[0], key[8]), pair(key[1], key[9])),
+ mix64(pair(key[2], key[10]), pair(key[3], key[11]))),
+ mix64(mix64(pair(key[4], key[12]), pair(key[5], key[13])),
+ mix64(pair(key[6], key[14]), pair(key[7], key[15]))));
+
+ x = mix((uint32_t)(z >> 32), (uint32_t)z);
+ x = mix(x, ror_inv(x, 17));
+ x = combine(x, ror_inv(x, 17));
+
+ return x;
+}
+
+uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result)
+{
+ uint64_t val;
+ uint32_t res;
+
+ val = calc16(key);
+ res = (uint32_t)val;
+
+ if (hsh->cam_bw > 32)
+ val = (val << (hsh->cam_bw - 32)) ^ val;
+
+ for (int i = 0; i < hsh->banks; i++) {
+ result[i] = (unsigned int)(val & hsh->cam_records_bw_mask);
+ val = val >> hsh->cam_records_bw;
+ }
+ return res;
+}
+
+int init_hasher(struct hasher_s *hsh, int banks, int nb_records)
+{
+ hsh->banks = banks;
+ hsh->cam_records_bw = (int)(log2(nb_records - 1) + 1);
+ hsh->cam_records_bw_mask = (1U << hsh->cam_records_bw) - 1;
+ hsh->cam_bw = hsh->banks * hsh->cam_records_bw;
+
+#ifdef TESTING
+ int res = hash_test(hsh, _banks, (int)log2(nb_records - 1) + 1);
+
+ if (res)
+ printf("ERROR: testing hasher\n");
+#endif
+
+ return 0;
+}
+
+#ifdef TESTING
+int hash_test(struct hasher_s *hsh, int banks, int record_bw)
+{
+ int res = 0;
+ int val[10], resval[10];
+ uint32_t bits = 0;
+
+ uint32_t inval[16] = { 0xaaaabbbb, 0xccccdddd, 0xeeeeffff, 0x88881111 };
+ const uint32_t result = 0xACECAE65;
+
+ for (int i = 0; i < 16; i++)
+ printf("%08x,", inval[i]);
+ printf("\nbanks %i, records bit width: %i\n", banks, record_bw);
+
+ uint32_t ret = gethash(hsh, inval, val);
+
+ printf("Return VAL = %08X == %08X\n", ret, result);
+ res += (ret != result) ? 1 : 0;
+
+ int shft = (banks * record_bw) - 32;
+ int mask = (1 << record_bw) - 1;
+
+ if (shft > 0) {
+ bits = (ret >> (32 - shft));
+ ret ^= ret << shft;
+ }
+
+ resval[0] = ret & mask;
+ ret >>= record_bw;
+ resval[1] = ret & mask;
+ ret >>= record_bw;
+ resval[2] = ret & mask;
+ resval[2] |= (bits << (record_bw - shft));
+
+ for (int i = 0; i < 3; i++) {
+ printf("HASH %i: %i == %i\n", i, val[i], resval[i]);
+ res += (val[i] != resval[i]) ? 1 : 0;
+ }
+
+ return res;
+}
+#endif
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h
new file mode 100644
index 0000000000..6365a396d2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_hasher.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_HASHER_H_
+#define _FLOW_HASHER_H_
+
+#include <stdint.h>
+
+struct hasher_s {
+ int banks;
+ int cam_records_bw;
+ uint32_t cam_records_bw_mask;
+ int cam_bw;
+};
+
+int init_hasher(struct hasher_s *hsh, int banks, int nb_records);
+uint32_t gethash(struct hasher_s *hsh, const uint32_t key[16], int *result);
+
+#endif /* _FLOW_HASHER_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c
new file mode 100644
index 0000000000..ddf1742588
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_kcc.c
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+#include "flow_hasher.h"
+
+/*
+ * KCC-CAM structures and defines
+ */
+struct kcc_cam_distrib_s {
+ struct kcc_flow_def_s *kcc_owner;
+ int ref_cnt;
+};
+
+#define BE_CAM_KCC_DIST_IDX(bnk) \
+ ({ \
+ int _temp_bnk = (bnk); \
+ (_temp_bnk * kcc->be->cat.kcc_records + kcc->record_indexes[_temp_bnk]); \
+ })
+
+
+#define BE_CAM_ENTRIES \
+ (kcc->be->cat.kcc_size * sizeof(struct kcc_cam_distrib_s))
+#define BE_UNIQUE_IDS_SIZE ((1U << kcc->be->cat.kcc_id_bit_size) / 8)
+
+#define KCC_CUCKOO_MOVE_MAX_DEPTH 8
+static int kcc_cam_addr_reserved_stack[KCC_CUCKOO_MOVE_MAX_DEPTH];
+
+void kcc_attach_ndev_resource_management(struct kcc_flow_def_s *kcc,
+ void **handle)
+{
+ /*
+ * KCC entries occupied in CAM - to manage the cuckoo shuffling
+ * and manage CAM population and usage
+ */
+ if (!*handle) {
+ *handle = calloc(1, BE_CAM_ENTRIES + sizeof(uint32_t) +
+ BE_UNIQUE_IDS_SIZE +
+ sizeof(struct hasher_s));
+ NT_LOG(DBG, FILTER,
+ "Allocate NIC DEV KCC-CAM record manager\n");
+ }
+ kcc->cam_dist = (struct kcc_cam_distrib_s *)*handle;
+ kcc->cuckoo_moves =
+ (uint32_t *)((char *)kcc->cam_dist + BE_CAM_ENTRIES);
+ kcc->kcc_unique_ids = (uint8_t *)((char *)kcc->cam_dist +
+ BE_CAM_ENTRIES + sizeof(uint32_t));
+
+ kcc->hsh = (struct hasher_s *)((char *)kcc->kcc_unique_ids +
+ BE_UNIQUE_IDS_SIZE);
+ init_hasher(kcc->hsh, kcc->be->cat.kcc_banks, kcc->be->cat.kcc_records);
+}
+
+void kcc_free_ndev_resource_management(void **handle)
+{
+ if (*handle) {
+ free(*handle);
+ NT_LOG(DBG, FILTER, "Free NIC DEV KCC-CAM record manager\n");
+ }
+ *handle = NULL;
+}
+
+/*
+ * Key for KCC CAM
+ */
+int kcc_key_add_no_sideband(struct kcc_flow_def_s *kcc)
+{
+ kcc->key.sb_data = 0xffffffff;
+ kcc->key.sb_type = 0;
+ return 0;
+}
+
+int kcc_key_add_vlan(struct kcc_flow_def_s *kcc, uint16_t tpid, uint16_t vid)
+{
+ kcc->key.sb_data = ((uint32_t)tpid << 16) | (vid & 0x0fff);
+ kcc->key.sb_type = 1;
+ return 0;
+}
+
+int kcc_key_add_vxlan(struct kcc_flow_def_s *kcc, uint32_t vni)
+{
+ kcc->key.sb_data = (vni & 0x00ffffff) | 0x02000000;
+ kcc->key.sb_type = 2;
+ return 0;
+}
+
+int kcc_key_add_port(struct kcc_flow_def_s *kcc, uint16_t port)
+{
+ kcc->key.port = port;
+ return 0;
+}
+
+int kcc_key_add_cat_cfn(struct kcc_flow_def_s *kcc, uint8_t cat_cfn)
+{
+ kcc->key.cat_cfn = cat_cfn;
+ return 0;
+}
+
+uint8_t kcc_key_get_cat_cfn(struct kcc_flow_def_s *kcc)
+{
+ return kcc->key.cat_cfn;
+}
+
+/*
+ * other settings for KCC CAM
+ */
+int kcc_add_km_category(struct kcc_flow_def_s *kcc, uint32_t category)
+{
+ kcc->km_category = category;
+ return 0;
+}
+
+int kcc_alloc_unique_id(struct kcc_flow_def_s *kcc)
+{
+ uint32_t i, ii;
+ /* search a free unique ID in allocation bitmap */
+ for (i = 0; i < BE_UNIQUE_IDS_SIZE; i++)
+ if (kcc->kcc_unique_ids[i] != 0xff)
+ break;
+
+ if (i == BE_UNIQUE_IDS_SIZE)
+ return -1;
+
+ for (ii = 0; ii < 8; ii++) {
+ if ((kcc->kcc_unique_ids[i] & (uint8_t)(1U << ii)) == 0) {
+ kcc->kcc_unique_ids[i] =
+ (uint8_t)(kcc->kcc_unique_ids[i] |
+ (uint8_t)(1U << ii));
+ kcc->id = (uint16_t)(i * 8 + ii);
+ NT_LOG(DBG, FILTER, "Allocate new KCC ID : %i\n",
+ kcc->id);
+ return (int)kcc->id;
+ }
+ }
+ return -1;
+}
+
+void kcc_free_unique_id(struct kcc_flow_def_s *kcc)
+{
+ if (kcc->id == KCC_ID_INVALID)
+ return;
+
+ uint32_t idx = kcc->id >> 3;
+ uint8_t shft = (uint8_t)(kcc->id & 7);
+
+ assert(idx < BE_UNIQUE_IDS_SIZE);
+ if (idx < BE_UNIQUE_IDS_SIZE) {
+ assert(kcc->kcc_unique_ids[idx] & (uint8_t)(1 << shft));
+ kcc->kcc_unique_ids[idx] &= (uint8_t)~(1 << shft);
+ NT_LOG(DBG, FILTER, "Free KCC ID : %i\n", kcc->id);
+ kcc->id = KCC_ID_INVALID;
+ }
+}
+
+int kcc_key_compare(struct kcc_flow_def_s *kcc, struct kcc_flow_def_s *kcc1)
+{
+ if (kcc->key64 == kcc1->key64)
+ return 1;
+ return 0;
+}
+
+static int kcc_cam_populate(struct kcc_flow_def_s *kcc, int bank)
+{
+ int res;
+ int idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank];
+
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0,
+ kcc->key32[0]);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1,
+ kcc->key32[1]);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0,
+ kcc->km_category);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, kcc->id);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_flush(kcc->be, idx, 1);
+
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = kcc;
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 1;
+ return res;
+}
+
+static int kcc_cam_reset_entry(struct kcc_flow_def_s *kcc, int bank)
+{
+ int res = 0;
+ int idx = bank * kcc->be->cat.kcc_records + kcc->record_indexes[bank];
+
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 0, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_KEY, idx, 1, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_CATEGORY, idx, 0, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_set(kcc->be, HW_CAT_KCC_ID, idx, 0, 0);
+ if (res)
+ return -1;
+ res = hw_mod_cat_kcc_flush(kcc->be, idx, 1);
+
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner = NULL;
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].ref_cnt = 0;
+
+ kcc->key64 = 0UL;
+ kcc->km_category = 0;
+ /* "kcc->id" holds an allocated unique id, so cleared/freed later */
+ return res;
+}
+
+static int kcc_move_cuckoo_index(struct kcc_flow_def_s *kcc)
+{
+ assert(kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)].kcc_owner);
+
+ for (uint32_t bank = 0; bank < kcc->be->cat.kcc_banks; bank++) {
+ /* It will not select itself */
+ if (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(bank)].kcc_owner ==
+ NULL) {
+ /*
+ * Populate in new position
+ */
+ int res = kcc_cam_populate(kcc, bank);
+
+ if (res) {
+ NT_LOG(DBG, FILTER,
+ "Error: failed to write to KM CAM in cuckoo move\n");
+ return 0;
+ }
+
+ /*
+ * Reset/free entry in old bank
+ * HW flushes are really not needed, the old addresses are always taken over
+ * by the caller If you change this code in future updates, this may no
+ * longer be true then!
+ */
+ kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)]
+ .kcc_owner = NULL;
+ NT_LOG(DBG, FILTER,
+ "KCC Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\n",
+ kcc->bank_used, bank,
+ BE_CAM_KCC_DIST_IDX(kcc->bank_used),
+ BE_CAM_KCC_DIST_IDX(bank));
+
+ kcc->bank_used = bank;
+ (*kcc->cuckoo_moves)++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int kcc_move_cuckoo_index_level(struct kcc_flow_def_s *kcc_parent,
+ int bank_idx, int levels,
+ int cam_adr_list_len)
+{
+ struct kcc_flow_def_s *kcc = kcc_parent->cam_dist[bank_idx].kcc_owner;
+
+ assert(levels <= KCC_CUCKOO_MOVE_MAX_DEPTH);
+
+ if (kcc_move_cuckoo_index(kcc))
+ return 1;
+ if (levels <= 1)
+ return 0;
+
+ assert(cam_adr_list_len < KCC_CUCKOO_MOVE_MAX_DEPTH);
+
+ kcc_cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx;
+
+ for (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++) {
+ int reserved = 0;
+ int new_idx = BE_CAM_KCC_DIST_IDX(i);
+
+ for (int i_reserved = 0; i_reserved < cam_adr_list_len;
+ i_reserved++) {
+ if (kcc_cam_addr_reserved_stack[i_reserved] ==
+ new_idx) {
+ reserved = 1;
+ break;
+ }
+ }
+ if (reserved)
+ continue;
+
+ int res = kcc_move_cuckoo_index_level(kcc, new_idx, levels - 1,
+ cam_adr_list_len);
+ if (res) {
+ if (kcc_move_cuckoo_index(kcc))
+ return 1;
+
+ else
+ assert(0);
+ }
+ }
+
+ return 0;
+}
+
+static uint32_t kcc_hsh_key[16];
+
+static int kcc_write_data_to_cam(struct kcc_flow_def_s *kcc)
+{
+ int res = 0;
+ int val[MAX_BANKS];
+
+ kcc_hsh_key[0] = kcc->key32[1];
+ kcc_hsh_key[1] = kcc->key32[0];
+ NT_LOG(DBG, FILTER, "TEMP TEMP TEMP");
+ NT_LOG(DBG, FILTER, "Hash key[0] %08x", kcc_hsh_key[0]);
+ NT_LOG(DBG, FILTER, "Hash key[1] %08x", kcc_hsh_key[1]);
+ NT_LOG(DBG, FILTER, "TEMP TEMP TEMP - swapped");
+
+ /* 2-15 never changed - remains zero */
+
+ gethash(kcc->hsh, kcc_hsh_key, val);
+
+ for (uint32_t i = 0; i < kcc->be->cat.kcc_banks; i++)
+ kcc->record_indexes[i] = val[i];
+ NT_LOG(DBG, FILTER, "KCC HASH [%03X, %03X, %03X]\n",
+ kcc->record_indexes[0], kcc->record_indexes[1],
+ kcc->record_indexes[2]);
+
+ int bank = -1;
+ /*
+ * first step, see if any of the banks are free
+ */
+ for (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks; i_bank++) {
+ if (kcc->cam_dist[BE_CAM_KCC_DIST_IDX(i_bank)].kcc_owner ==
+ NULL) {
+ bank = i_bank;
+ break;
+ }
+ }
+
+ if (bank < 0) {
+ /*
+ * Second step - cuckoo move existing flows if possible
+ */
+ for (uint32_t i_bank = 0; i_bank < kcc->be->cat.kcc_banks;
+ i_bank++) {
+ if (kcc_move_cuckoo_index_level(kcc,
+ BE_CAM_KCC_DIST_IDX(i_bank),
+ 4, 0)) {
+ bank = i_bank;
+ break;
+ }
+ }
+
+ if (bank < 0)
+ return -1;
+ }
+
+ /* populate CAM */
+ NT_LOG(DBG, FILTER, "KCC Bank = %i (addr %04X)\n", bank,
+ BE_CAM_KCC_DIST_IDX(bank));
+ res = kcc_cam_populate(kcc, bank);
+ if (res == 0) {
+ kcc->flushed_to_target = 1;
+ kcc->bank_used = bank;
+ } else {
+ NT_LOG(DBG, FILTER, "KCC CAM populate failed\n");
+ }
+ return res;
+}
+
+int kcc_write_data_match_entry(struct kcc_flow_def_s *kcc)
+{
+ int res = -1;
+
+ NT_LOG(DBG, FILTER,
+ "KCC Write Data entry. Create New Key: %016lx, KM category %i, id %i\n",
+ kcc->key64, kcc->km_category, kcc->id);
+ res = kcc_write_data_to_cam(kcc);
+ return res;
+}
+
+static int kcc_clear_data_match_entry(struct kcc_flow_def_s *kcc)
+{
+ int res = 0;
+
+ if (kcc->flushed_to_target) {
+ res = kcc_cam_reset_entry(kcc, kcc->bank_used);
+ kcc->flushed_to_target = 0;
+ kcc->bank_used = 0;
+ }
+ return res;
+}
+
+int kcc_key_ref_count_add(struct kcc_flow_def_s *kcc)
+{
+ assert(kcc->bank_used >= 0 &&
+ kcc->bank_used < (int)kcc->be->cat.kcc_banks);
+
+ struct kcc_cam_distrib_s *cam_entry =
+ &kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)];
+
+ NT_LOG(DBG, FILTER,
+ "KCC ADD Ref existing Key: %016lx, KM category %i, id %i (new ref count %i)\n",
+ kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt + 1);
+ return ++cam_entry->ref_cnt;
+}
+
+int kcc_key_ref_count_dec(struct kcc_flow_def_s *kcc)
+{
+ if (kcc->bank_used < 0 || kcc->bank_used >= (int)kcc->be->cat.kcc_banks)
+ return -1;
+
+ struct kcc_cam_distrib_s *cam_entry =
+ &kcc->cam_dist[BE_CAM_KCC_DIST_IDX(kcc->bank_used)];
+
+ if (cam_entry->ref_cnt) {
+ if (--cam_entry->ref_cnt == 0) {
+ kcc_clear_data_match_entry(kcc);
+ NT_LOG(DBG, FILTER,
+ "KCC DEC Ref on Key became zero - Delete\n");
+ }
+ }
+
+ NT_LOG(DBG, FILTER,
+ "KCC DEC Ref on Key: %016lx, KM category %i, id %i (new ref count %i)\n",
+ kcc->key64, kcc->km_category, kcc->id, cam_entry->ref_cnt);
+ return cam_entry->ref_cnt;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c
new file mode 100644
index 0000000000..560be9f7d3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_km.c
@@ -0,0 +1,1434 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+#include "flow_hasher.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct cam_match_masks_s {
+ uint32_t word_len;
+ uint32_t key_mask[4];
+} cam_masks[] = {
+ { 4,
+ { 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff
+ }
+ }, /* IP6_SRC, IP6_DST */
+ { 4,
+ { 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffff0000
+ }
+ }, /* DMAC,SMAC,ethtype */
+ { 4,
+ { 0xffffffff, 0xffff0000, 0x00000000,
+ 0xffff0000
+ }
+ }, /* DMAC,ethtype */
+ { 4,
+ { 0x00000000, 0x0000ffff, 0xffffffff,
+ 0xffff0000
+ }
+ }, /* SMAC,ethtype */
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000 } }, /* ETH_128 */
+ { 2,
+ { 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000
+ }
+ }, /* IP4_COMBINED */
+ { 1, { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 } },
+ /*
+ * ETH_TYPE, IP4_TTL_PROTO, IP4_SRC, IP4_DST, IP6_FLOW_TC,
+ * IP6_NEXT_HDR_HOP, TP_PORT_COMBINED, SIDEBAND_VNI
+ */
+ { 1,
+ { 0xffff0000, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* IP4_IHL_TOS, TP_PORT_SRC32_OR_ICMP, TCP_CTRL */
+ { 1,
+ { 0x0000ffff, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* TP_PORT_DST32 */
+ { 1,
+ { 0x00030000, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* IPv4 TOS mask bits used often by OVS */
+ { 1,
+ { 0x00300000, 0x00000000, 0x00000000,
+ 0x00000000
+ }
+ }, /* IPv6 TOS mask bits used often by OVS */
+};
+
+#define NUM_CAM_MASKS (ARRAY_SIZE(cam_masks))
+
+/*
+ * CAM structures and defines
+ */
+struct cam_distrib_s {
+ struct km_flow_def_s *km_owner;
+};
+
+#define CAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_cam_records + (rec))
+#define CAM_KM_DIST_IDX(bnk) \
+ ({ \
+ int _temp_bnk = (bnk); \
+ CAM_DIST_IDX(_temp_bnk, km->record_indexes[_temp_bnk]); \
+ })
+
+#define CUCKOO_MOVE_MAX_DEPTH 8
+static int cam_addr_reserved_stack[CUCKOO_MOVE_MAX_DEPTH];
+
+/*
+ * TCAM structures and defines
+ */
+struct tcam_distrib_s {
+ struct km_flow_def_s *km_owner;
+};
+
+#define TCAM_DIST_IDX(bnk, rec) ((bnk) * km->be->km.nb_tcam_bank_width + (rec))
+
+static int tcam_find_mapping(struct km_flow_def_s *km);
+
+void km_attach_ndev_resource_management(struct km_flow_def_s *km, void **handle)
+{
+#define CAM_ENTRIES \
+ (km->be->km.nb_cam_banks * km->be->km.nb_cam_records * \
+ sizeof(struct cam_distrib_s))
+#define TCAM_ENTRIES \
+ (km->be->km.nb_tcam_bank_width * km->be->km.nb_tcam_banks * \
+ sizeof(struct tcam_distrib_s))
+ /*
+ * KM entries occupied in CAM - to manage the cuckoo shuffling
+ * and manage CAM population and usage
+ * KM entries occupied in TCAM - to manage population and usage
+ */
+ if (!*handle) {
+ *handle = calloc(1, (size_t)CAM_ENTRIES + sizeof(uint32_t) +
+ (size_t)TCAM_ENTRIES +
+ sizeof(struct hasher_s));
+ NT_LOG(DBG, FILTER,
+ "Allocate NIC DEV CAM and TCAM record manager\n");
+ }
+ km->cam_dist = (struct cam_distrib_s *)*handle;
+ km->cuckoo_moves = (uint32_t *)((char *)km->cam_dist + CAM_ENTRIES);
+ km->tcam_dist =
+ (struct tcam_distrib_s *)((char *)km->cam_dist + CAM_ENTRIES +
+ sizeof(uint32_t));
+
+ km->hsh = (struct hasher_s *)((char *)km->tcam_dist + TCAM_ENTRIES);
+ init_hasher(km->hsh, km->be->km.nb_cam_banks,
+ km->be->km.nb_cam_records);
+}
+
+void km_free_ndev_resource_management(void **handle)
+{
+ if (*handle) {
+ free(*handle);
+ NT_LOG(DBG, FILTER,
+ "Free NIC DEV CAM and TCAM record manager\n");
+ }
+ *handle = NULL;
+}
+
+int km_add_match_elem(struct km_flow_def_s *km, uint32_t e_word[4],
+ uint32_t e_mask[4], uint32_t word_len,
+ enum frame_offs_e start_id, int8_t offset)
+{
+#ifdef FLOW_DEBUG
+ char *s = ntlog_helper_str_alloc("MATCH: ");
+
+ for (unsigned int i = 0; i < word_len; i++)
+ ntlog_helper_str_add(s, "%08x, ", e_word[i]);
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_reset(s, "MASK : ");
+ for (unsigned int i = 0; i < word_len; i++)
+ ntlog_helper_str_add(s, "%08x, ", e_mask[i]);
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_free(s);
+#endif
+
+ /* valid word_len 1,2,4 */
+ if (word_len == 3) {
+ word_len = 4;
+ e_word[3] = 0;
+ e_mask[3] = 0;
+ }
+ if (word_len < 1 || word_len > 4) {
+ assert(0);
+ return -1;
+ }
+
+ for (unsigned int i = 0; i < word_len; i++) {
+ km->match[km->num_ftype_elem].e_word[i] = e_word[i];
+ km->match[km->num_ftype_elem].e_mask[i] = e_mask[i];
+ }
+
+ km->match[km->num_ftype_elem].word_len = word_len;
+ km->match[km->num_ftype_elem].rel_offs = offset;
+ km->match[km->num_ftype_elem].extr_start_offs_id = start_id;
+
+ /*
+ * Determine here if this flow may better be put into TCAM
+ * Otherwise it will go into CAM
+ * This is dependent on a cam_masks list defined above
+ */
+ km->match[km->num_ftype_elem].masked_for_tcam = 1;
+ for (unsigned int msk = 0; msk < NUM_CAM_MASKS; msk++) {
+ if (word_len == cam_masks[msk].word_len) {
+ int match = 1;
+
+ for (unsigned int wd = 0; wd < word_len; wd++) {
+ if (e_mask[wd] != cam_masks[msk].key_mask[wd]) {
+ match = 0;
+ break;
+ }
+ }
+ if (match) {
+ /* Can go into CAM */
+ km->match[km->num_ftype_elem].masked_for_tcam =
+ 0;
+ }
+ }
+ }
+
+ km->num_ftype_elem++;
+ return 0;
+}
+
+void km_set_info(struct km_flow_def_s *km, int on)
+{
+ km->info_set = !!on;
+}
+
+static int get_word(struct km_flow_def_s *km, uint32_t size, int marked[])
+{
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (!marked[i] &&
+ !(km->match[i].extr_start_offs_id & SWX_INFO) &&
+ km->match[i].word_len == size)
+ return i;
+ }
+ return -1;
+}
+
+#ifdef FLOW_DEBUG
+static const char *get_prot_offset_descr(int idx)
+{
+ switch (idx) {
+ case DYN_SOF:
+ return "SOF";
+ case DYN_L2:
+ return "L2 header";
+ case DYN_FIRST_VLAN:
+ return "First VLAN";
+ case DYN_MPLS:
+ return "First MPLS";
+ case DYN_L3:
+ return "L3 header";
+ case DYN_ID_IPV4_6:
+ return "ID field IPv4/6";
+ case DYN_FINAL_IP_DST:
+ return "Final IP dest";
+ case DYN_L4:
+ return "L4 header";
+ case DYN_L4_PAYLOAD:
+ return "L4 payload";
+ case DYN_TUN_PAYLOAD:
+ return "Tunnel payload";
+ case DYN_TUN_L2:
+ return "Tunnel L2 header";
+ case DYN_TUN_VLAN:
+ return "First tunneled VLAN";
+ case DYN_TUN_MPLS:
+ return "First tunneled MPLS";
+ case DYN_TUN_L3:
+ return "Tunnel L3 header";
+ case DYN_TUN_ID_IPV4_6:
+ return "Tunnel ID field IPv4/6";
+ case DYN_TUN_FINAL_IP_DST:
+ return "Tunnel final IP dest";
+ case DYN_TUN_L4:
+ return "Tunnel L4 header";
+ case DYN_TUN_L4_PAYLOAD:
+ return "Tunnel L4 payload";
+ case SB_VNI:
+ return "VNI";
+ case SB_MAC_PORT:
+ return "In Port";
+ case SB_KCC_ID:
+ return "KCC ID";
+ default:
+ break;
+ }
+ return "<unknown>";
+}
+#endif
+
+#define MAX_QWORDS 2
+#define MAX_SWORDS 2
+
+int km_key_create(struct km_flow_def_s *km, uint32_t port_id)
+{
+ /*
+ * Create combined extractor mappings
+ * if key fields may be changed to cover un-mappable otherwise?
+ * split into cam and tcam and use synergy mode when available
+ *
+ */
+ int match_marked[MAX_MATCH_FIELDS];
+ int idx = 0;
+ int next = 0;
+ int m_idx;
+ int size;
+
+ memset(match_marked, 0, sizeof(match_marked));
+
+ /* build QWords */
+ for (int qwords = 0; qwords < MAX_QWORDS; qwords++) {
+ size = 4;
+ m_idx = get_word(km, size, match_marked);
+ if (m_idx < 0) {
+ size = 2;
+ m_idx = get_word(km, size, match_marked);
+
+ if (m_idx < 0) {
+ size = 1;
+ m_idx = get_word(km, 1, match_marked);
+ }
+ }
+ if (m_idx < 0) {
+ /* no more defined */
+ break;
+ }
+
+ match_marked[m_idx] = 1;
+
+ /* build match map list and set final extractor to use */
+ km->match_map[next] = &km->match[m_idx];
+ km->match[m_idx].extr = KM_USE_EXTRACTOR_QWORD;
+
+ /* build final entry words and mask array */
+ for (int i = 0; i < size; i++) {
+ km->entry_word[idx + i] = km->match[m_idx].e_word[i];
+ km->entry_mask[idx + i] = km->match[m_idx].e_mask[i];
+ }
+
+ idx += size;
+ next++;
+ }
+
+ m_idx = get_word(km, 4, match_marked);
+ if (m_idx >= 0) {
+ /* cannot match more QWords */
+ return -1;
+ }
+
+ /*
+ * On km v6+ we have DWORDs here instead. However, we only use them as SWORDs for now
+ * No match would be able to exploit these as DWORDs because of maximum length of 12 words
+ * in CAM
+ * The last 2 words are taken by KCC-ID/SWX and Color. You could have one or none QWORDs
+ * where then both these DWORDs were possible in 10 words, but we don't have such use case
+ * built in yet
+ */
+ /* build SWords */
+ for (int swords = 0; swords < MAX_SWORDS; swords++) {
+ m_idx = get_word(km, 1, match_marked);
+ if (m_idx < 0) {
+ /* no more defined */
+ break;
+ }
+
+ match_marked[m_idx] = 1;
+ /* build match map list and set final extractor to use */
+ km->match_map[next] = &km->match[m_idx];
+ km->match[m_idx].extr = KM_USE_EXTRACTOR_SWORD;
+
+ /* build final entry words and mask array */
+ km->entry_word[idx] = km->match[m_idx].e_word[0];
+ km->entry_mask[idx] = km->match[m_idx].e_mask[0];
+ idx++;
+ next++;
+ }
+
+ /*
+ * Make sure we took them all
+ */
+ m_idx = get_word(km, 1, match_marked);
+ if (m_idx >= 0) {
+ /* cannot match more SWords */
+ return -1;
+ }
+
+ /*
+ * Handle SWX words specially
+ */
+ int swx_found = 0;
+
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (km->match[i].extr_start_offs_id & SWX_INFO) {
+ km->match_map[next] = &km->match[i];
+ km->match[i].extr = KM_USE_EXTRACTOR_SWORD;
+ /* build final entry words and mask array */
+ km->entry_word[idx] = km->match[i].e_word[0];
+ km->entry_mask[idx] = km->match[i].e_mask[0];
+ idx++;
+ next++;
+ swx_found = 1;
+ }
+ }
+
+ assert(next == km->num_ftype_elem);
+
+ km->key_word_size = idx;
+ km->port_id = port_id;
+
+ km->target = KM_CAM;
+ /*
+ * Finally decide if we want to put this match->action into the TCAM
+ * When SWX word used we need to put it into CAM always, no matter what mask pattern
+ * Later, when synergy mode is applied, we can do a split
+ */
+ if (!swx_found && km->key_word_size <= 6) {
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (km->match_map[i]->masked_for_tcam) {
+ /* At least one */
+ km->target = KM_TCAM;
+ }
+ }
+ }
+
+ NT_LOG(DBG, FILTER, "This flow goes into %s\n",
+ (km->target == KM_TCAM) ? "TCAM" : "CAM");
+
+ if (km->target == KM_TCAM) {
+ if (km->key_word_size > 10) {
+ /* do not support SWX in TCAM */
+ return -1;
+ }
+ /*
+ * adjust for unsupported key word size in TCAM
+ */
+ if ((km->key_word_size == 5 || km->key_word_size == 7 ||
+ km->key_word_size == 9)) {
+ km->entry_mask[km->key_word_size] = 0;
+ km->key_word_size++;
+ }
+
+ /*
+ * 1. the fact that the length of a key cannot change among the same used banks
+ *
+ * calculate possible start indexes
+ * unfortunately restrictions in TCAM lookup
+ * makes it hard to handle key lengths larger than 6
+ * when other sizes should be possible too
+ */
+ switch (km->key_word_size) {
+ case 1:
+ for (int i = 0; i < 4; i++)
+ km->start_offsets[0] = 8 + i;
+ km->num_start_offsets = 4;
+ break;
+ case 2:
+ km->start_offsets[0] = 6;
+ km->num_start_offsets = 1;
+ break;
+ case 3:
+ km->start_offsets[0] = 0;
+ km->num_start_offsets = 1;
+ /* enlarge to 6 */
+ km->entry_mask[km->key_word_size++] = 0;
+ km->entry_mask[km->key_word_size++] = 0;
+ km->entry_mask[km->key_word_size++] = 0;
+ break;
+ case 4:
+ km->start_offsets[0] = 0;
+ km->num_start_offsets = 1;
+ /* enlarge to 6 */
+ km->entry_mask[km->key_word_size++] = 0;
+ km->entry_mask[km->key_word_size++] = 0;
+ break;
+ case 6:
+ km->start_offsets[0] = 0;
+ km->num_start_offsets = 1;
+ break;
+
+ default:
+ NT_LOG(DBG, FILTER,
+ "Final Key word size too large: %i\n",
+ km->key_word_size);
+ return -1;
+ }
+
+#ifdef FLOW_DEBUG
+ char *s = ntlog_helper_str_alloc("TCAM offs: ");
+
+ for (int i = 0; i < km->num_start_offsets; i++)
+ ntlog_helper_str_add(s, "%i,", km->start_offsets[i]);
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_free(s);
+#endif
+ }
+
+#ifdef FLOW_DEBUG
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ NT_LOG(DBG, FILTER,
+ "size %i -> Extr: %s, offset id: %s, rel offset: %i\n",
+ km->match_map[i]->word_len,
+ (km->match_map[i]->extr_start_offs_id & SWX_INFO) ?
+ "SIDEBAND" :
+ km->match_map[i]->extr == KM_USE_EXTRACTOR_SWORD ?
+ "SWORD" :
+ "QWORD",
+ get_prot_offset_descr(km->match_map[i]->extr_start_offs_id),
+ km->match_map[i]->rel_offs);
+ }
+ char *s = ntlog_helper_str_alloc("");
+
+ for (int i = 0; i < km->key_word_size; i++)
+ ntlog_helper_str_add(s, "%08x,", km->entry_word[i]);
+
+ NT_LOG(DBG, FILTER, "%s", s);
+
+ ntlog_helper_str_reset(s, "");
+ for (int i = 0; i < km->key_word_size; i++)
+ ntlog_helper_str_add(s, "%08x,", km->entry_mask[i]);
+
+ NT_LOG(DBG, FILTER, "%s", s);
+ ntlog_helper_str_free(s);
+#endif
+
+ return 0;
+}
+
+int km_key_compare(struct km_flow_def_s *km, struct km_flow_def_s *km1)
+{
+ if (km->target != km1->target ||
+ km->num_ftype_elem != km1->num_ftype_elem ||
+ km->key_word_size != km1->key_word_size ||
+ km->info_set != km1->info_set)
+ return 0;
+
+ /*
+ * before KCC-CAM:
+ * if port is added to match, then we can have different ports in CAT
+ * that reuses this flow type
+ */
+ int port_match_included = 0, kcc_swx_used = 0;
+
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ if (km->match[i].extr_start_offs_id == SB_MAC_PORT) {
+ port_match_included = 1;
+ break;
+ } else if (km->match_map[i]->extr_start_offs_id == SB_KCC_ID) {
+ kcc_swx_used = 1;
+ break;
+ }
+ }
+
+ /*
+ * If not using KCC and if port match is not included in CAM,
+ * we need to have same port_id to reuse
+ */
+ if (!kcc_swx_used && !port_match_included &&
+ km->port_id != km1->port_id)
+ return 0;
+
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ /* using same extractor types in same sequence */
+ if (km->match_map[i]->extr_start_offs_id != km1->match_map[i]->extr_start_offs_id ||
+ km->match_map[i]->rel_offs != km1->match_map[i]->rel_offs ||
+ km->match_map[i]->extr != km1->match_map[i]->extr ||
+ km->match_map[i]->word_len != km1->match_map[i]->word_len)
+ return 0;
+ }
+
+ if (km->target == KM_CAM) {
+ /* in CAM must exactly match on all masks */
+ for (int i = 0; i < km->key_word_size; i++) {
+ if (km->entry_mask[i] != km1->entry_mask[i])
+ return 0;
+ }
+
+ /* Would be set later if not reusing from km1 */
+ km->cam_paired = km1->cam_paired;
+ } else if (km->target == KM_TCAM) {
+ /*
+ * If TCAM, we must make sure Recipe Key Mask does not
+ * mask out enable bits in masks
+ * Note: it is important that km1 is the original creator
+ * of the KM Recipe, since it contains its true masks
+ */
+ for (int i = 0; i < km->key_word_size; i++) {
+ if ((km->entry_mask[i] & km1->entry_mask[i]) !=
+ km->entry_mask[i])
+ return 0;
+ }
+
+ km->tcam_start_bank = km1->tcam_start_bank;
+ km->tcam_record = -1; /* needs to be found later */
+ } else {
+ NT_LOG(DBG, FILTER,
+ "ERROR - KM target not defined or supported\n");
+ return 0;
+ }
+
+ /*
+ * Check for a flow clash. If already programmed return with -1
+ */
+ int double_match = 1;
+
+ for (int i = 0; i < km->key_word_size; i++) {
+ if ((km->entry_word[i] & km->entry_mask[i]) !=
+ (km1->entry_word[i] & km1->entry_mask[i])) {
+ double_match = 0;
+ break;
+ }
+ }
+
+ if (double_match)
+ return -1;
+
+ /*
+ * Note that TCAM and CAM may reuse same RCP and flow type
+ * when this happens, CAM entry wins on overlap
+ */
+
+ /* Use same KM Recipe and same flow type - return flow type */
+ return km1->flow_type;
+}
+
+int km_rcp_set(struct km_flow_def_s *km, int index)
+{
+ int qw = 0;
+ int sw = 0;
+ int swx = 0;
+
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_PRESET_ALL, index, 0, 0);
+
+ /* set extractor words, offs, contrib */
+ for (int i = 0; i < km->num_ftype_elem; i++) {
+ switch (km->match_map[i]->extr) {
+ case KM_USE_EXTRACTOR_SWORD:
+ if (km->match_map[i]->extr_start_offs_id & SWX_INFO) {
+ if (km->target == KM_CAM && swx == 0) {
+ /* SWX */
+ if (km->match_map[i]
+ ->extr_start_offs_id ==
+ SB_VNI) {
+ NT_LOG(DBG, FILTER,
+ "Set KM SWX sel A - VNI\n");
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_CCH,
+ index, 0, 1);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_SEL_A,
+ index, 0,
+ SWX_SEL_ALL32);
+ } else if (km->match_map[i]
+ ->extr_start_offs_id ==
+ SB_MAC_PORT) {
+ NT_LOG(DBG, FILTER,
+ "Set KM SWX sel A - PTC + MAC\n");
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_SEL_A,
+ index, 0,
+ SWX_SEL_ALL32);
+ } else if (km->match_map[i]
+ ->extr_start_offs_id ==
+ SB_KCC_ID) {
+ NT_LOG(DBG, FILTER,
+ "Set KM SWX sel A - KCC ID\n");
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_CCH,
+ index, 0, 1);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_SWX_SEL_A,
+ index, 0,
+ SWX_SEL_ALL32);
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ swx++;
+ } else {
+ if (sw == 0) {
+ /* DW8 */
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW8_DYN,
+ index, 0,
+ km->match_map[i]
+ ->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW8_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW8_SEL_A,
+ index, 0,
+ DW8_SEL_FIRST32);
+ NT_LOG(DBG, FILTER,
+ "Set KM DW8 sel A: dyn: %i, offs: %i\n",
+ km->match_map[i]
+ ->extr_start_offs_id,
+ km->match_map[i]->rel_offs);
+ } else if (sw == 1) {
+ /* DW10 */
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW10_DYN,
+ index, 0,
+ km->match_map[i]
+ ->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW10_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_DW10_SEL_A,
+ index, 0,
+ DW10_SEL_FIRST32);
+ NT_LOG(DBG, FILTER,
+ "Set KM DW10 sel A: dyn: %i, offs: %i\n",
+ km->match_map[i]
+ ->extr_start_offs_id,
+ km->match_map[i]->rel_offs);
+ } else {
+ return -1;
+ }
+ sw++;
+ }
+ break;
+
+ case KM_USE_EXTRACTOR_QWORD:
+ if (qw == 0) {
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_DYN,
+ index, 0,
+ km->match_map[i]->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ switch (km->match_map[i]->word_len) {
+ case 1:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_SEL_A,
+ index, 0,
+ QW0_SEL_FIRST32);
+ break;
+ case 2:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_SEL_A,
+ index, 0,
+ QW0_SEL_FIRST64);
+ break;
+ case 4:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW0_SEL_A,
+ index, 0,
+ QW0_SEL_ALL128);
+ break;
+ default:
+ return -1;
+ }
+ NT_LOG(DBG, FILTER,
+ "Set KM QW0 sel A: dyn: %i, offs: %i, size: %i\n",
+ km->match_map[i]->extr_start_offs_id,
+ km->match_map[i]->rel_offs,
+ km->match_map[i]->word_len);
+ } else if (qw == 1) {
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_DYN,
+ index, 0,
+ km->match_map[i]->extr_start_offs_id);
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_OFS,
+ index, 0,
+ km->match_map[i]->rel_offs);
+ switch (km->match_map[i]->word_len) {
+ case 1:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_SEL_A,
+ index, 0,
+ QW4_SEL_FIRST32);
+ break;
+ case 2:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_SEL_A,
+ index, 0,
+ QW4_SEL_FIRST64);
+ break;
+ case 4:
+ hw_mod_km_rcp_set(km->be,
+ HW_KM_RCP_QW4_SEL_A,
+ index, 0,
+ QW4_SEL_ALL128);
+ break;
+ default:
+ return -1;
+ }
+ NT_LOG(DBG, FILTER,
+ "Set KM QW4 sel A: dyn: %i, offs: %i, size: %i\n",
+ km->match_map[i]->extr_start_offs_id,
+ km->match_map[i]->rel_offs,
+ km->match_map[i]->word_len);
+ } else {
+ return -1;
+ }
+ qw++;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ /* set mask A */
+ for (int i = 0; i < km->key_word_size; i++) {
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_MASK_A, index,
+ (km->be->km.nb_km_rcp_mask_a_word_size - 1) -
+ i,
+ km->entry_mask[i]);
+ NT_LOG(DBG, FILTER, "Set KM mask A: %08x\n", km->entry_mask[i]);
+ }
+
+ if (km->target == KM_CAM) {
+ /* set info - Color */
+ if (km->info_set) {
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_INFO_A, index, 0,
+ 1);
+ NT_LOG(DBG, FILTER, "Set KM info A\n");
+ }
+ /* set key length A */
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_EL_A, index, 0,
+ km->key_word_size + !!km->info_set -
+ 1); /* select id is -1 */
+ /* set Flow Type for Key A */
+ NT_LOG(DBG, FILTER, "Set KM EL A: %i\n",
+ km->key_word_size + !!km->info_set - 1);
+
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_FTM_A, index, 0,
+ 1 << km->flow_type);
+
+ NT_LOG(DBG, FILTER, "Set KM FTM A - ft: %i\n", km->flow_type);
+
+ /* Set Paired - only on the CAM part though... */
+ if ((uint32_t)(km->key_word_size + !!km->info_set) >
+ km->be->km.nb_cam_record_words) {
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_PAIRED,
+ index, 0, 1);
+ NT_LOG(DBG, FILTER, "Set KM CAM Paired\n");
+ km->cam_paired = 1;
+ }
+ } else if (km->target == KM_TCAM) {
+ uint32_t bank_bm = 0;
+
+ if (tcam_find_mapping(km) < 0) {
+ /* failed mapping into TCAM */
+ NT_LOG(DBG, FILTER, "INFO: TCAM mapping flow failed\n");
+ return -1;
+ }
+
+ assert((uint32_t)(km->tcam_start_bank + km->key_word_size) <=
+ km->be->km.nb_tcam_banks);
+
+ for (int i = 0; i < km->key_word_size; i++) {
+ bank_bm |= (1 << (km->be->km.nb_tcam_banks - 1 -
+ (km->tcam_start_bank + i)));
+ }
+
+ /* Set BANK_A */
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_BANK_A, index, 0, bank_bm);
+ /* Set Kl_A */
+ hw_mod_km_rcp_set(km->be, HW_KM_RCP_KL_A, index, 0,
+ km->key_word_size - 1);
+
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int cam_populate(struct km_flow_def_s *km, int bank)
+{
+ int res = 0;
+ int cnt = km->key_word_size + !!km->info_set;
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,
+ km->record_indexes[bank],
+ km->entry_word[i]);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank,
+ km->record_indexes[bank],
+ km->flow_type);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = km;
+
+ if (cnt) {
+ assert(km->cam_paired);
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be,
+ HW_KM_CAM_W0 + i,
+ bank,
+ km->record_indexes[bank] + 1,
+ km->entry_word[km->be->km.nb_cam_record_words +
+ i]);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i,
+ bank,
+ km->record_indexes[bank] + 1,
+ km->flow_type);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = km;
+ }
+
+ res |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank],
+ km->cam_paired ? 2 : 1);
+
+ return res;
+}
+
+static int cam_reset_entry(struct km_flow_def_s *km, int bank)
+{
+ int res = 0;
+ int cnt = km->key_word_size + !!km->info_set;
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,
+ km->record_indexes[bank], 0);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i, bank,
+ km->record_indexes[bank], 0);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner = NULL;
+
+ if (cnt) {
+ assert(km->cam_paired);
+ for (uint32_t i = 0; i < km->be->km.nb_cam_record_words && cnt;
+ i++, cnt--) {
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_W0 + i, bank,
+ km->record_indexes[bank] + 1,
+ 0);
+ res |= hw_mod_km_cam_set(km->be, HW_KM_CAM_FT0 + i,
+ bank,
+ km->record_indexes[bank] + 1,
+ 0);
+ }
+ km->cam_dist[CAM_KM_DIST_IDX(bank) + 1].km_owner = NULL;
+ }
+ res |= hw_mod_km_cam_flush(km->be, bank, km->record_indexes[bank],
+ km->cam_paired ? 2 : 1);
+ return res;
+}
+
+static int move_cuckoo_index(struct km_flow_def_s *km)
+{
+ assert(km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner);
+
+ for (uint32_t bank = 0; bank < km->be->km.nb_cam_banks; bank++) {
+ /* It will not select itself */
+ if (km->cam_dist[CAM_KM_DIST_IDX(bank)].km_owner == NULL) {
+ if (km->cam_paired) {
+ if (km->cam_dist[CAM_KM_DIST_IDX(bank) + 1]
+ .km_owner != NULL)
+ continue;
+ }
+
+ /*
+ * Populate in new position
+ */
+ int res = cam_populate(km, bank);
+
+ if (res) {
+ NT_LOG(DBG, FILTER,
+ "Error: failed to write to KM CAM in cuckoo move\n");
+ return 0;
+ }
+
+ /*
+ * Reset/free entry in old bank
+ * HW flushes are really not needed, the old addresses are always taken over
+ * by the caller
+ * If you change this code in future updates, this may no longer be true
+ * then!
+ */
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner =
+ NULL;
+ if (km->cam_paired)
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1]
+ .km_owner = NULL;
+
+ NT_LOG(DBG, FILTER,
+ "KM Cuckoo hash moved from bank %i to bank %i (%04X => %04X)\n",
+ km->bank_used, bank,
+ CAM_KM_DIST_IDX(km->bank_used),
+ CAM_KM_DIST_IDX(bank));
+ km->bank_used = bank;
+ (*km->cuckoo_moves)++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int move_cuckoo_index_level(struct km_flow_def_s *km_parent,
+ int bank_idx, int levels,
+ int cam_adr_list_len)
+{
+ struct km_flow_def_s *km = km_parent->cam_dist[bank_idx].km_owner;
+
+ assert(levels <= CUCKOO_MOVE_MAX_DEPTH);
+
+ /*
+ * Only move if same pairness
+ * Can be extended later to handle both move of paired and single entries
+ */
+ if (!km || km_parent->cam_paired != km->cam_paired)
+ return 0;
+
+ if (move_cuckoo_index(km))
+ return 1;
+ if (levels <= 1)
+ return 0;
+
+ assert(cam_adr_list_len < CUCKOO_MOVE_MAX_DEPTH);
+
+ cam_addr_reserved_stack[cam_adr_list_len++] = bank_idx;
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) {
+ int reserved = 0;
+ int new_idx = CAM_KM_DIST_IDX(i);
+
+ for (int i_reserved = 0; i_reserved < cam_adr_list_len;
+ i_reserved++) {
+ if (cam_addr_reserved_stack[i_reserved] == new_idx) {
+ reserved = 1;
+ break;
+ }
+ }
+ if (reserved)
+ continue;
+
+ int res = move_cuckoo_index_level(km, new_idx, levels - 1,
+ cam_adr_list_len);
+ if (res) {
+ if (move_cuckoo_index(km))
+ return 1;
+
+ else
+ assert(0);
+ }
+ }
+
+ return 0;
+}
+
+static int km_write_data_to_cam(struct km_flow_def_s *km)
+{
+ int res = 0;
+ int val[MAX_BANKS];
+
+ assert(km->be->km.nb_cam_banks <= MAX_BANKS);
+ assert(km->cam_dist);
+
+ /* word list without info set */
+ gethash(km->hsh, km->entry_word, val);
+
+ for (uint32_t i = 0; i < km->be->km.nb_cam_banks; i++) {
+ /* if paired we start always on an even address - reset bit 0 */
+ km->record_indexes[i] = (km->cam_paired) ? val[i] & ~1 : val[i];
+ }
+ NT_LOG(DBG, FILTER, "KM HASH [%03X, %03X, %03X]\n",
+ km->record_indexes[0], km->record_indexes[1],
+ km->record_indexes[2]);
+
+ if (km->info_set) {
+ km->entry_word[km->key_word_size] =
+ km->info; /* finally set info */
+ }
+
+ int bank = -1;
+ /*
+ * first step, see if any of the banks are free
+ */
+ for (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks; i_bank++) {
+ if (km->cam_dist[CAM_KM_DIST_IDX(i_bank)].km_owner == NULL) {
+ if (km->cam_paired == 0 ||
+ (km->cam_dist[CAM_KM_DIST_IDX(i_bank) + 1]
+ .km_owner == NULL)) {
+ bank = i_bank;
+ break;
+ }
+ }
+ }
+
+ if (bank < 0) {
+ /*
+ * Second step - cuckoo move existing flows if possible
+ */
+ for (uint32_t i_bank = 0; i_bank < km->be->km.nb_cam_banks;
+ i_bank++) {
+ if (move_cuckoo_index_level(km, CAM_KM_DIST_IDX(i_bank),
+ 4, 0)) {
+ bank = i_bank;
+ break;
+ }
+ }
+ }
+ if (bank < 0)
+ return -1;
+
+ /* populate CAM */
+ NT_LOG(DBG, FILTER, "KM Bank = %i (addr %04X)\n", bank,
+ CAM_KM_DIST_IDX(bank));
+ res = cam_populate(km, bank);
+ if (res == 0) {
+ km->flushed_to_target = 1;
+ km->bank_used = bank;
+ }
+
+ return res;
+}
+
+/*
+ * TCAM
+ */
+static int tcam_find_free_record(struct km_flow_def_s *km, int start_bank)
+{
+ for (uint32_t rec = 0; rec < km->be->km.nb_tcam_bank_width; rec++) {
+ if (km->tcam_dist[TCAM_DIST_IDX(start_bank, rec)].km_owner ==
+ NULL) {
+ int pass = 1;
+
+ for (int ii = 1; ii < km->key_word_size; ii++) {
+ if (km->tcam_dist[TCAM_DIST_IDX(start_bank + ii,
+ rec)]
+ .km_owner != NULL) {
+ pass = 0;
+ break;
+ }
+ }
+ if (pass) {
+ km->tcam_record = rec;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int tcam_find_mapping(struct km_flow_def_s *km)
+{
+ /* Search record and start index for this flow */
+ for (int bs_idx = 0; bs_idx < km->num_start_offsets; bs_idx++) {
+ if (tcam_find_free_record(km, km->start_offsets[bs_idx])) {
+ km->tcam_start_bank = km->start_offsets[bs_idx];
+ NT_LOG(DBG, FILTER,
+ "Found space in TCAM start bank %i, record %i\n",
+ km->tcam_start_bank, km->tcam_record);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int tcam_write_word(struct km_flow_def_s *km, int bank, int record,
+ uint32_t word, uint32_t mask)
+{
+ int err = 0;
+ uint32_t all_recs[3];
+
+ int rec_val = record / 32;
+ int rec_bit_shft = record % 32;
+ uint32_t rec_bit = (1 << rec_bit_shft);
+
+ assert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3);
+
+ for (int byte = 0; byte < 4; byte++) {
+ uint8_t a = (uint8_t)((word >> (24 - (byte * 8))) & 0xff);
+ uint8_t a_m = (uint8_t)((mask >> (24 - (byte * 8))) & 0xff);
+ /* calculate important value bits */
+ a = a & a_m;
+
+#ifdef FLOW_DEBUG
+ if (a_m == 0) {
+ NT_LOG(DBG, FILTER,
+ "bank %i, byte %i, All values, rec_val %i rec bit %08x\n",
+ bank, byte, rec_val, rec_bit);
+ }
+#endif
+
+ for (int val = 0; val < 256; val++) {
+ err |= hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if ((val & a_m) == a) {
+ all_recs[rec_val] |= rec_bit;
+#ifdef FLOW_DEBUG
+ if (a_m) {
+ NT_LOG(DBG, FILTER,
+ "bank %i, byte %i, val %i(%02x), "
+ "rec_val %i rec bit %08x\n",
+ bank, byte, val, val, rec_val,
+ rec_bit);
+ }
+#endif
+ } else {
+ all_recs[rec_val] &= ~rec_bit;
+ }
+ err |= hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if (err)
+ break;
+ }
+ }
+ /* flush bank */
+ err |= hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES);
+ if (err == 0) {
+ assert(km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner ==
+ NULL);
+ km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = km;
+ }
+ return err;
+}
+
+static int km_write_data_to_tcam(struct km_flow_def_s *km)
+{
+ int err = 0;
+
+ if (km->tcam_record < 0) {
+ tcam_find_free_record(km, km->tcam_start_bank);
+ if (km->tcam_record < 0) {
+ NT_LOG(DBG, FILTER,
+ "FAILED to find space in TCAM for flow\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER,
+ "Reused RCP: Found space in TCAM start bank %i, record %i\n",
+ km->tcam_start_bank, km->tcam_record);
+ }
+
+ /* Write KM_TCI */
+ err |= hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank,
+ km->tcam_record, km->info);
+ err |= hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank,
+ km->tcam_record, km->flow_type);
+ err |= hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record,
+ 1);
+
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ for (int i = 0; i < km->key_word_size && !err; i++) {
+ err = tcam_write_word(km, km->tcam_start_bank + i,
+ km->tcam_record, km->entry_word[i],
+ km->entry_mask[i]);
+ }
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ if (err == 0)
+ km->flushed_to_target = 1;
+
+ return err;
+}
+
+static int tcam_reset_bank(struct km_flow_def_s *km, int bank, int record)
+{
+ int err = 0;
+ uint32_t all_recs[3];
+
+ int rec_val = record / 32;
+ int rec_bit_shft = record % 32;
+ uint32_t rec_bit = (1 << rec_bit_shft);
+
+ assert((km->be->km.nb_tcam_bank_width + 31) / 32 <= 3);
+
+ for (int byte = 0; byte < 4; byte++) {
+ for (int val = 0; val < 256; val++) {
+ err = hw_mod_km_tcam_get(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if (err)
+ break;
+ all_recs[rec_val] &= ~rec_bit;
+ err = hw_mod_km_tcam_set(km->be, HW_KM_TCAM_T, bank,
+ byte, val, all_recs);
+ if (err)
+ break;
+ }
+ }
+ if (err)
+ return err;
+
+ /* flush bank */
+ err = hw_mod_km_tcam_flush(km->be, bank, ALL_BANK_ENTRIES);
+ km->tcam_dist[TCAM_DIST_IDX(bank, record)].km_owner = NULL;
+
+ NT_LOG(DBG, FILTER, "Reset TCAM bank %i, rec_val %i rec bit %08x\n",
+ bank, rec_val, rec_bit);
+
+ return err;
+}
+
+static int tcam_reset_entry(struct km_flow_def_s *km)
+{
+ int err = 0;
+
+ if (km->tcam_start_bank < 0 || km->tcam_record < 0) {
+ NT_LOG(DBG, FILTER, "FAILED to find space in TCAM for flow\n");
+ return -1;
+ }
+
+ /* Write KM_TCI */
+ hw_mod_km_tci_set(km->be, HW_KM_TCI_COLOR, km->tcam_start_bank,
+ km->tcam_record, 0);
+ hw_mod_km_tci_set(km->be, HW_KM_TCI_FT, km->tcam_start_bank,
+ km->tcam_record, 0);
+ hw_mod_km_tci_flush(km->be, km->tcam_start_bank, km->tcam_record, 1);
+
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ for (int i = 0; i < km->key_word_size && !err; i++) {
+ err = tcam_reset_bank(km, km->tcam_start_bank + i,
+ km->tcam_record);
+ }
+#ifdef FLOW_DEBUG
+ km->be->iface->set_debug_mode(km->be->be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ return err;
+}
+
+int km_refer_data_match_entry(struct km_flow_def_s *km,
+ struct km_flow_def_s *km1)
+{
+ int res = 0;
+
+ km->root = km1->root ? km1->root : km1;
+ while (km1->reference)
+ km1 = km1->reference;
+ km1->reference = km;
+
+ km->info = km1->info;
+
+ switch (km->target) {
+ case KM_CAM:
+ km->cam_paired = km1->cam_paired;
+ km->bank_used = km1->bank_used;
+ km->flushed_to_target = km1->flushed_to_target;
+ break;
+ case KM_TCAM:
+ km->tcam_start_bank = km1->tcam_start_bank;
+ km->tcam_record = km1->tcam_record;
+ km->flushed_to_target = km1->flushed_to_target;
+ break;
+ case KM_SYNERGY:
+ default:
+ res = -1;
+ break;
+ }
+
+ return res;
+}
+
+int km_write_data_match_entry(struct km_flow_def_s *km, uint32_t color)
+{
+ int res = -1;
+
+ km->info = color;
+ NT_LOG(DBG, FILTER, "Write Data entry Color: %08x\n", color);
+
+ switch (km->target) {
+ case KM_CAM:
+ res = km_write_data_to_cam(km);
+ break;
+ case KM_TCAM:
+ res = km_write_data_to_tcam(km);
+ break;
+ case KM_SYNERGY:
+ default:
+ break;
+ }
+ return res;
+}
+
+int km_clear_data_match_entry(struct km_flow_def_s *km)
+{
+ int res = 0;
+
+ if (km->root) {
+ struct km_flow_def_s *km1 = km->root;
+
+ while (km1->reference != km)
+ km1 = km1->reference;
+
+ km1->reference = km->reference;
+
+ km->flushed_to_target = 0;
+ km->bank_used = 0;
+ } else if (km->reference) {
+ km->reference->root = NULL;
+
+ switch (km->target) {
+ case KM_CAM:
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used)].km_owner =
+ km->reference;
+ if (km->key_word_size + !!km->info_set > 1) {
+ assert(km->cam_paired);
+ km->cam_dist[CAM_KM_DIST_IDX(km->bank_used) + 1]
+ .km_owner = km->reference;
+ }
+ break;
+ case KM_TCAM:
+ for (int i = 0; i < km->key_word_size; i++) {
+ km->tcam_dist[TCAM_DIST_IDX(km->tcam_start_bank + i,
+ km->tcam_record)].km_owner = km->reference;
+ }
+ break;
+ case KM_SYNERGY:
+ default:
+ res = -1;
+ break;
+ }
+
+ km->flushed_to_target = 0;
+ km->bank_used = 0;
+ } else if (km->flushed_to_target) {
+ switch (km->target) {
+ case KM_CAM:
+ res = cam_reset_entry(km, km->bank_used);
+ break;
+ case KM_TCAM:
+ res = tcam_reset_entry(km);
+ break;
+ case KM_SYNERGY:
+ default:
+ res = -1;
+ break;
+ }
+ km->flushed_to_target = 0;
+ km->bank_used = 0;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c
new file mode 100644
index 0000000000..17717da8e2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_engine/flow_tunnel.c
@@ -0,0 +1,787 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+#include <stdio.h>
+#include "stream_binary_flow_api.h"
+
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+#define MAX_HW_VIRT_PORTS 127 /* 255 reserved */
+#define VIRTUAL_TUNNEL_PORT_OFFSET 72
+
+struct tunnel_s {
+ struct tunnel_cfg_s cfg;
+ struct tunnel_cfg_s cfg_mask;
+ uint32_t flow_stat_id;
+ uint8_t vport;
+ int refcnt;
+ struct tunnel_s *next; /* linked list of defined tunnels */
+};
+
+int is_virtual_port(uint8_t virt_port)
+{
+ return !!(virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET &&
+ virt_port < MAX_HW_VIRT_PORTS);
+}
+
+/*
+ * New function for use with OVS 2.17.2
+ */
+static struct tunnel_s *tunnels;
+
+static uint8_t vport[MAX_HW_VIRT_PORTS - VIRTUAL_TUNNEL_PORT_OFFSET + 1];
+
+uint8_t flow_tunnel_alloc_virt_port(void)
+{
+ for (uint8_t i = VIRTUAL_TUNNEL_PORT_OFFSET; i < MAX_HW_VIRT_PORTS;
+ i++) {
+ if (!vport[i - VIRTUAL_TUNNEL_PORT_OFFSET]) {
+ vport[i - VIRTUAL_TUNNEL_PORT_OFFSET] = 1;
+ return i;
+ }
+ }
+
+ /* no more virtual ports */
+ return 255;
+}
+
+uint8_t flow_tunnel_free_virt_port(uint8_t virt_port)
+{
+ if (virt_port >= VIRTUAL_TUNNEL_PORT_OFFSET &&
+ virt_port < MAX_HW_VIRT_PORTS) {
+ vport[virt_port - VIRTUAL_TUNNEL_PORT_OFFSET] = 0;
+ return 0;
+ }
+ return -1;
+}
+
+#define check(_v1, _v2, _msk1, _msk2) ({ \
+ __typeof__(_v1) (v1) = (_v1); \
+ __typeof__(_v2) (v2) = (_v2); \
+ __typeof__(_msk1) (msk1) = (_msk1); \
+ __typeof__(_msk2) (msk2) = (_msk2); \
+ (((v1) & (msk1) & (msk2)) == ((v2) & (msk1) & (msk2))); \
+})
+
+#define check_tun_v4_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({ \
+ __typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \
+ __typeof__(_tun_msk) (tun_msk) = (_tun_msk); \
+ __typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \
+ __typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \
+ (check((tun_cfg)->v4.src_ip, (tun1_cfg)->v4.src_ip, \
+ (tun_msk)->v4.src_ip, (tun1_msk)->v4.src_ip) && \
+ check((tun_cfg)->v4.dst_ip, (tun1_cfg)->v4.dst_ip, \
+ (tun_msk)->v4.dst_ip, (tun1_msk)->v4.dst_ip) && \
+ check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \
+ (tun1_msk)->s_port) && \
+ check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \
+ (tun1_msk)->d_port)); \
+})
+
+#define check_tun_v6_equal(_tun_cfg, _tun_msk, _tun1_cfg, _tun1_msk) ({ \
+ __typeof__(_tun_cfg) (tun_cfg) = (_tun_cfg); \
+ __typeof__(_tun_msk) (tun_msk) = (_tun_msk); \
+ __typeof__(_tun1_cfg) (tun1_cfg) = (_tun1_cfg); \
+ __typeof__(_tun1_msk) (tun1_msk) = (_tun1_msk); \
+ (check((tun_cfg)->v6_long.src_ip[0], (tun1_cfg)->v6_long.src_ip[0], \
+ (tun_msk)->v6_long.src_ip[0], (tun1_msk)->v6_long.src_ip[0]) && \
+ check((tun_cfg)->v6_long.src_ip[1], (tun1_cfg)->v6_long.src_ip[1], \
+ (tun_msk)->v6_long.src_ip[1], (tun1_msk)->v6_long.src_ip[1]) && \
+ check((tun_cfg)->v6_long.dst_ip[0], (tun1_cfg)->v6_long.dst_ip[0], \
+ (tun_msk)->v6_long.dst_ip[0], (tun1_msk)->v6_long.dst_ip[0]) && \
+ check((tun_cfg)->v6_long.dst_ip[1], (tun1_cfg)->v6_long.dst_ip[1], \
+ (tun_msk)->v6_long.dst_ip[1], (tun1_msk)->v6_long.dst_ip[1]) && \
+ check((tun_cfg)->s_port, (tun1_cfg)->s_port, (tun_msk)->s_port, \
+ (tun1_msk)->s_port) && \
+ check((tun_cfg)->d_port, (tun1_cfg)->d_port, (tun_msk)->d_port, \
+ (tun1_msk)->d_port)); \
+})
+
+static int check_tun_match(struct tunnel_s *tun,
+ const struct tunnel_cfg_s *tnlcfg,
+ const struct tunnel_cfg_s *tnlcfg_mask)
+{
+ if (tun->cfg.tun_type == tnlcfg->tun_type) {
+ if (tun->cfg.ipversion == 4) {
+ return check_tun_v4_equal(&tun->cfg, &tun->cfg_mask,
+ tnlcfg, tnlcfg_mask);
+ } else {
+ return check_tun_v6_equal(&tun->cfg, &tun->cfg_mask,
+ tnlcfg, tnlcfg_mask);
+ }
+ }
+ return 0;
+}
+
+static struct tunnel_s *tunnel_get(const struct tunnel_cfg_s *tnlcfg,
+ const struct tunnel_cfg_s *tnlcfg_mask,
+ int tun_set)
+{
+ struct tunnel_s *tun = tunnels;
+
+ while (tun) {
+ if (tun->flow_stat_id != (uint32_t)-1) {
+ /* This tun is already defined and set */
+ if (tun_set) {
+ /*
+ * A tunnel full match definition - search for duplicate
+ */
+ if (memcmp(&tun->cfg, tnlcfg,
+ sizeof(struct tunnel_cfg_s)) == 0 &&
+ memcmp(&tun->cfg_mask, tnlcfg_mask,
+ sizeof(struct tunnel_cfg_s)) == 0)
+ break;
+ } else {
+ /*
+ * A tunnel match search
+ */
+ if (check_tun_match(tun, tnlcfg, tnlcfg_mask))
+ break;
+ }
+
+ } else if (tun_set) {
+ /*
+ * Check if this is a pre-configured tunnel for this one to be set
+ * try match them
+ */
+ if (check_tun_match(tun, tnlcfg, tnlcfg_mask)) {
+ /*
+ * Change the tun into the defining one - flow_stat_id is set later
+ */
+ memcpy(&tun->cfg, tnlcfg,
+ sizeof(struct tunnel_cfg_s));
+ memcpy(&tun->cfg_mask, tnlcfg_mask,
+ sizeof(struct tunnel_cfg_s));
+
+ break;
+ }
+
+ } /* else ignore - both unset */
+ tun = tun->next;
+ }
+
+ /*
+ * If not found, create and add it to db
+ */
+ if (!tun) {
+ uint8_t vport = flow_tunnel_alloc_virt_port();
+
+ NT_LOG(DBG, FILTER, "Create NEW tunnel allocate vport %i\n",
+ vport);
+
+ if (vport < 0xff) {
+ tun = calloc(1, sizeof(struct tunnel_s));
+ memcpy(&tun->cfg, tnlcfg, sizeof(struct tunnel_cfg_s));
+ memcpy(&tun->cfg_mask, tnlcfg_mask,
+ sizeof(struct tunnel_cfg_s));
+
+ /* flow_stat_id is set later from flow code */
+ tun->flow_stat_id = (uint32_t)-1;
+ tun->vport = vport;
+ tun->refcnt = 1;
+
+ tun->next = tunnels;
+ tunnels = tun;
+ }
+ } else {
+ tun->refcnt++;
+ NT_LOG(DBG, FILTER, "Found tunnel has vport %i - ref %i\n",
+ tun->vport, tun->refcnt);
+ }
+
+ return tun;
+}
+
+int tunnel_release(struct tunnel_s *tnl)
+{
+ struct tunnel_s *tun = tunnels, *prev = NULL;
+
+ NT_LOG(DBG, FILTER, "release tunnel vport %i, ref cnt %i..\n",
+ tnl->vport, tnl->refcnt);
+ /* find tunnel in list */
+ while (tun) {
+ if (tun == tnl)
+ break;
+ prev = tun;
+ tun = tun->next;
+ }
+
+ if (!tun) {
+ NT_LOG(DBG, FILTER,
+ "ERROR: Tunnel not found in tunnel release!\n");
+ return -1;
+ }
+
+ /* if last ref, take out of list */
+ if (--tun->refcnt == 0) {
+ if (prev)
+ prev->next = tun->next;
+ else
+ tunnels = tun->next;
+ flow_tunnel_free_virt_port(tun->vport);
+
+ NT_LOG(DBG, FILTER,
+ "tunnel ref count == 0 remove tunnel vport %i\n",
+ tun->vport);
+ free(tun);
+ }
+
+ return 0;
+}
+
+struct tunnel_s *tunnel_parse(const struct flow_elem *elem, int *idx,
+ uint32_t *vni)
+{
+ int eidx = *idx;
+ struct tunnel_cfg_s tnlcfg;
+ struct tunnel_cfg_s tnlcfg_mask;
+ struct tunnel_s *rtnl = NULL;
+
+ if (elem) {
+ eidx++;
+ memset(&tnlcfg, 0, sizeof(struct tunnel_cfg_s));
+ int valid = 1;
+ enum flow_elem_type last_type = FLOW_ELEM_TYPE_END;
+
+ tnlcfg.d_port = 0xffff;
+ tnlcfg.tun_type = -1;
+
+ if (vni)
+ *vni = (uint32_t)-1;
+
+ while (elem[eidx].type != FLOW_ELEM_TYPE_END &&
+ elem[eidx].type >= last_type && valid) {
+ switch (elem[eidx].type) {
+ case FLOW_ELEM_TYPE_ANY:
+ case FLOW_ELEM_TYPE_ETH:
+ /* Ignore */
+ break;
+ case FLOW_ELEM_TYPE_IPV4: {
+ const struct flow_elem_ipv4 *ipv4 =
+ (const struct flow_elem_ipv4 *)elem[eidx]
+ .spec;
+ const struct flow_elem_ipv4 *ipv4_mask =
+ (const struct flow_elem_ipv4 *)elem[eidx]
+ .mask;
+
+ tnlcfg.v4.src_ip = ipv4->hdr.src_ip;
+ tnlcfg.v4.dst_ip = ipv4->hdr.dst_ip;
+ tnlcfg_mask.v4.src_ip = ipv4_mask->hdr.src_ip;
+ tnlcfg_mask.v4.dst_ip = ipv4_mask->hdr.dst_ip;
+
+ tnlcfg.ipversion = 4;
+ }
+ break;
+ case FLOW_ELEM_TYPE_IPV6: {
+ const struct flow_elem_ipv6 *ipv6 =
+ (const struct flow_elem_ipv6 *)elem[eidx]
+ .spec;
+ const struct flow_elem_ipv6 *ipv6_mask =
+ (const struct flow_elem_ipv6 *)elem[eidx]
+ .mask;
+
+ memcpy(tnlcfg.v6.src_ip, ipv6->hdr.src_addr,
+ sizeof(tnlcfg.v6.src_ip));
+ memcpy(tnlcfg.v6.dst_ip, ipv6->hdr.dst_addr,
+ sizeof(tnlcfg.v6.dst_ip));
+ memcpy(tnlcfg_mask.v6.src_ip,
+ ipv6_mask->hdr.src_addr,
+ sizeof(tnlcfg.v6.src_ip));
+ memcpy(tnlcfg_mask.v6.dst_ip,
+ ipv6_mask->hdr.dst_addr,
+ sizeof(tnlcfg.v6.dst_ip));
+
+ tnlcfg.ipversion = 6;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_UDP: {
+ const struct flow_elem_udp *udp =
+ (const struct flow_elem_udp *)elem[eidx]
+ .spec;
+ const struct flow_elem_udp *udp_mask =
+ (const struct flow_elem_udp *)elem[eidx]
+ .mask;
+
+ tnlcfg.s_port = udp->hdr.src_port;
+ tnlcfg.d_port = udp->hdr.dst_port;
+ tnlcfg_mask.s_port = udp_mask->hdr.src_port;
+ tnlcfg_mask.d_port = udp_mask->hdr.dst_port;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VXLAN: {
+ const struct flow_elem_vxlan *vxlan =
+ (const struct flow_elem_vxlan *)
+ elem[eidx]
+ .spec;
+ if (vni)
+ *vni = (uint32_t)(((uint32_t)
+ vxlan->vni[0]
+ << 16) |
+ ((uint32_t)
+ vxlan->vni[1]
+ << 8) |
+ ((uint32_t)vxlan
+ ->vni[2]));
+
+ tnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN;
+ }
+ break;
+ default:
+ valid = 0;
+ break;
+ }
+
+ last_type = elem[eidx].type;
+ eidx++;
+ }
+
+ /*
+ * vxlan ports : 4789 or 8472
+ */
+ if (tnlcfg.tun_type < 0 &&
+ (tnlcfg.d_port == 0xb512 || tnlcfg.d_port == 0x1821))
+ tnlcfg.tun_type = FLOW_ELEM_TYPE_VXLAN;
+
+ if (!valid || tnlcfg.ipversion == 0 || tnlcfg.tun_type < 0 ||
+ tnlcfg.d_port == 0xffff) {
+ NT_LOG(DBG, FILTER, "Invalid tunnel received\n");
+ return NULL;
+ }
+
+ /* search/add to DB */
+ rtnl = tunnel_get(&tnlcfg, &tnlcfg_mask,
+ vni ? 0 :
+ 1); /* if vni == NULL it is a tun set command */
+
+#ifdef FLOW_DEBUG
+ if (rtnl) {
+ if (vni)
+ NT_LOG(DBG, FILTER,
+ "MATCH A TUNNEL DEFINITION - PRESET "
+ "(PREALLOC VPORT) IF NOT FOUND:\n");
+ else
+ NT_LOG(DBG, FILTER,
+ "SET A TUNNEL DEFINITION:\n");
+ struct in_addr addr, mask;
+ char buf[64];
+
+ addr.s_addr = rtnl->cfg.v4.src_ip;
+ sprintf(buf, "%s", inet_ntoa(addr));
+ mask.s_addr = rtnl->cfg_mask.v4.src_ip;
+ NT_LOG(DBG, FILTER, " tun src IP: %s / %s\n", buf,
+ inet_ntoa(mask));
+ addr.s_addr = rtnl->cfg.v4.dst_ip;
+ sprintf(buf, "%s", inet_ntoa(addr));
+ mask.s_addr = rtnl->cfg_mask.v4.dst_ip;
+ NT_LOG(DBG, FILTER, " tun dst IP: %s / %s\n", buf,
+ inet_ntoa(mask));
+ NT_LOG(DBG, FILTER, " tun tp_src: %i / %04x\n",
+ htons(rtnl->cfg.s_port),
+ htons(rtnl->cfg_mask.s_port));
+ NT_LOG(DBG, FILTER, " tun tp_dst: %i / %04x\n",
+ htons(rtnl->cfg.d_port),
+ htons(rtnl->cfg_mask.d_port));
+ NT_LOG(DBG, FILTER, " tun ipver: %i\n",
+ rtnl->cfg.ipversion);
+ NT_LOG(DBG, FILTER, " tun flow_stat_id: %i\n",
+ rtnl->flow_stat_id);
+ NT_LOG(DBG, FILTER, " tun vport: %i\n",
+ rtnl->vport);
+ NT_LOG(DBG, FILTER, " tun refcnt: %i\n",
+ rtnl->refcnt);
+ }
+#endif
+
+ *idx = eidx; /* pointing to next or END */
+ }
+
+ return rtnl;
+}
+
+uint8_t get_tunnel_vport(struct tunnel_s *rtnl)
+{
+ return rtnl->vport;
+}
+
+void tunnel_set_flow_stat_id(struct tunnel_s *rtnl, uint32_t flow_stat_id)
+{
+ rtnl->flow_stat_id = flow_stat_id;
+}
+
+int tunnel_get_definition(struct tunnel_cfg_s *tuncfg, uint32_t flow_stat_id,
+ uint8_t vport)
+{
+ struct tunnel_s *tun = tunnels;
+
+ while (tun) {
+ if (tun->vport == vport && (flow_stat_id == tun->flow_stat_id ||
+ flow_stat_id == (uint32_t)-1)) {
+ memcpy(tuncfg, &tun->cfg, sizeof(struct tunnel_cfg_s));
+ return 0;
+ }
+ tun = tun->next;
+ }
+
+ return -1;
+}
+
+static be16_t ip_checksum_sum(const be16_t *data, unsigned int size,
+ be16_t seed)
+{
+ unsigned int sum = seed;
+ unsigned int idx;
+
+ for (idx = 0; idx < size / 2; idx++)
+ sum += (unsigned int)(data[idx]);
+ if (size & 1)
+ sum += (unsigned char)data[idx];
+ /* unfold */
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+ return (be16_t)sum;
+}
+
+static void copy_unmasked(uint8_t *result, const struct flow_elem *elem,
+ uint8_t size)
+{
+ for (uint8_t i = 0; i < size; i++)
+ result[i] = ((const uint8_t *)elem->spec)[i];
+}
+
+int flow_tunnel_create_vxlan_hdr(struct flow_api_backend_s *be,
+ struct nic_flow_def *fd,
+ const struct flow_elem *elem)
+{
+ uint32_t eidx = 0;
+ uint8_t size;
+ struct ipv4_hdr_s *tun_ipv4 = NULL;
+ uint16_t *tun_hdr_eth_type_p = NULL;
+
+ if (elem) {
+ while (elem[eidx].type != FLOW_ELEM_TYPE_END) {
+ switch (elem[eidx].type) {
+ case FLOW_ELEM_TYPE_ETH: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_ETH\n");
+ struct flow_elem_eth eth;
+
+ size = sizeof(struct flow_elem_eth);
+
+ copy_unmasked((uint8_t *)ð, &elem[eidx],
+ size);
+
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ ð, size);
+
+ /*
+ * Save a pointer to the tun header ethtype field
+ * (needed later in the IPv4 and IPv6 flow elem cases)
+ */
+ tun_hdr_eth_type_p =
+ (uint16_t *)&fd->tun_hdr.d
+ .hdr8[fd->tun_hdr.len + 12];
+
+#ifdef FLOW_DEBUG
+ NT_LOG(DBG, FILTER,
+ "dmac : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth.d_addr.addr_b[0],
+ eth.d_addr.addr_b[1],
+ eth.d_addr.addr_b[2],
+ eth.d_addr.addr_b[3],
+ eth.d_addr.addr_b[5],
+ eth.d_addr.addr_b[5]);
+ NT_LOG(DBG, FILTER,
+ "smac : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth.s_addr.addr_b[0],
+ eth.s_addr.addr_b[1],
+ eth.s_addr.addr_b[2],
+ eth.s_addr.addr_b[3],
+ eth.s_addr.addr_b[5],
+ eth.s_addr.addr_b[5]);
+ NT_LOG(DBG, FILTER, "type : %04x\n",
+ ntohs(eth.ether_type));
+#endif
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ }
+ break;
+ /* VLAN is not supported */
+
+ case FLOW_ELEM_TYPE_IPV4: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_IPV4\n");
+ struct flow_elem_ipv4 ipv4;
+
+ size = sizeof(struct flow_elem_ipv4);
+
+ copy_unmasked((uint8_t *)&ipv4, &elem[eidx],
+ size);
+
+ if (ipv4.hdr.version_ihl != 0x45)
+ ipv4.hdr.version_ihl = 0x45;
+
+ if (ipv4.hdr.ttl == 0)
+ ipv4.hdr.ttl = 64;
+
+ if (ipv4.hdr.next_proto_id !=
+ 17) /* must be UDP */
+ ipv4.hdr.next_proto_id = 17;
+
+ ipv4.hdr.frag_offset =
+ htons(1 << 14); /* DF flag */
+
+ size = sizeof(struct ipv4_hdr_s);
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &ipv4.hdr, size);
+
+ /* Set the tun header ethtype field to IPv4 (if empty) */
+ if (tun_hdr_eth_type_p &&
+ (*tun_hdr_eth_type_p == 0)) {
+ *tun_hdr_eth_type_p =
+ htons(0x0800); /* IPv4 */
+ }
+
+ tun_ipv4 = (struct ipv4_hdr_s *)&fd->tun_hdr.d
+ .hdr8[fd->tun_hdr.len];
+
+ NT_LOG(DBG, FILTER, "v_ihl : %02x\n",
+ tun_ipv4->version_ihl);
+ NT_LOG(DBG, FILTER, "tos : %02x\n",
+ tun_ipv4->tos);
+ NT_LOG(DBG, FILTER, "len : %d\n",
+ ntohs(tun_ipv4->length));
+ NT_LOG(DBG, FILTER, "id : %02x\n",
+ tun_ipv4->id);
+ NT_LOG(DBG, FILTER, "fl/frg : %04x\n",
+ ntohs(tun_ipv4->frag_offset));
+ NT_LOG(DBG, FILTER, "ttl : %02x\n",
+ tun_ipv4->ttl);
+ NT_LOG(DBG, FILTER, "prot : %02x\n",
+ tun_ipv4->next_proto_id);
+ NT_LOG(DBG, FILTER, "chksum : %04x\n",
+ ntohs(tun_ipv4->hdr_csum));
+ NT_LOG(DBG, FILTER, "src : %d.%d.%d.%d\n",
+ (tun_ipv4->src_ip & 0xff),
+ ((tun_ipv4->src_ip >> 8) & 0xff),
+ ((tun_ipv4->src_ip >> 16) & 0xff),
+ ((tun_ipv4->src_ip >> 24) & 0xff));
+ NT_LOG(DBG, FILTER, "dst : %d.%d.%d.%d\n",
+ (tun_ipv4->dst_ip & 0xff),
+ ((tun_ipv4->dst_ip >> 8) & 0xff),
+ ((tun_ipv4->dst_ip >> 16) & 0xff),
+ ((tun_ipv4->dst_ip >> 24) & 0xff));
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ fd->tun_hdr.ip_version = 4;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_IPV6: {
+ if (be->roa.ver < 6) {
+ NT_LOG(ERR, FILTER,
+ "Tunnel flow element type IPv6 requires ROA version 6 or higher (current version=%d)\n",
+ be->roa.ver);
+ return -1;
+ }
+
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_IPV6\n");
+ struct flow_elem_ipv6 ipv6;
+
+ size = sizeof(struct flow_elem_ipv6);
+
+ copy_unmasked((uint8_t *)&ipv6, &elem[eidx],
+ size);
+
+ /*
+ * Make sure the version field (the 4 most significant bits of
+ * "vtc_flow") is set to 6
+ */
+ if ((ipv6.hdr.vtc_flow & htonl(0x60000000)) ==
+ 0) {
+ ipv6.hdr.vtc_flow |= htonl(0x60000000); /* Version = 6 */
+ }
+
+ if (ipv6.hdr.proto != 17) /* must be UDP */
+ ipv6.hdr.proto = 17;
+
+ if (ipv6.hdr.hop_limits == 0)
+ ipv6.hdr.hop_limits = 64;
+
+ size = sizeof(struct ipv6_hdr_s);
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &ipv6.hdr, size);
+
+ /* Set the tun header ethtype field to IPv6 (if empty) */
+ if (tun_hdr_eth_type_p &&
+ (*tun_hdr_eth_type_p == 0)) {
+ *tun_hdr_eth_type_p =
+ htons(0x86DD); /* IPv6 */
+ }
+
+ NT_LOG(DBG, FILTER, "vtc_flow : %08x\n",
+ ntohl(ipv6.hdr.vtc_flow));
+ NT_LOG(DBG, FILTER, "payload_len : %04x\n",
+ ntohs(ipv6.hdr.payload_len));
+ NT_LOG(DBG, FILTER, "proto : %02x\n",
+ ipv6.hdr.proto);
+ NT_LOG(DBG, FILTER, "hop_limits : %02x\n",
+ ipv6.hdr.hop_limits);
+ NT_LOG(DBG, FILTER,
+ "src : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ ipv6.hdr.src_addr[0],
+ ipv6.hdr.src_addr[1],
+ ipv6.hdr.src_addr[2],
+ ipv6.hdr.src_addr[3],
+ ipv6.hdr.src_addr[4],
+ ipv6.hdr.src_addr[5],
+ ipv6.hdr.src_addr[6],
+ ipv6.hdr.src_addr[7],
+ ipv6.hdr.src_addr[8],
+ ipv6.hdr.src_addr[9],
+ ipv6.hdr.src_addr[10],
+ ipv6.hdr.src_addr[11],
+ ipv6.hdr.src_addr[12],
+ ipv6.hdr.src_addr[13],
+ ipv6.hdr.src_addr[14],
+ ipv6.hdr.src_addr[15]);
+ NT_LOG(DBG, FILTER,
+ "dst : %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ ipv6.hdr.dst_addr[0],
+ ipv6.hdr.dst_addr[1],
+ ipv6.hdr.dst_addr[2],
+ ipv6.hdr.dst_addr[3],
+ ipv6.hdr.dst_addr[4],
+ ipv6.hdr.dst_addr[5],
+ ipv6.hdr.dst_addr[6],
+ ipv6.hdr.dst_addr[7],
+ ipv6.hdr.dst_addr[8],
+ ipv6.hdr.dst_addr[9],
+ ipv6.hdr.dst_addr[10],
+ ipv6.hdr.dst_addr[11],
+ ipv6.hdr.dst_addr[12],
+ ipv6.hdr.dst_addr[13],
+ ipv6.hdr.dst_addr[14],
+ ipv6.hdr.dst_addr[15]);
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ fd->tun_hdr.ip_version = 6;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_UDP: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_UDP\n");
+ struct flow_elem_udp udp;
+
+ size = sizeof(struct flow_elem_udp);
+
+ copy_unmasked((uint8_t *)&udp, &elem[eidx],
+ size);
+
+ udp.hdr.cksum =
+ 0; /* set always the UDP checksum to 0 */
+
+ size = sizeof(struct udp_hdr_s);
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &udp.hdr, size);
+
+ NT_LOG(DBG, FILTER, "src p : %d\n",
+ ntohs(udp.hdr.src_port));
+ NT_LOG(DBG, FILTER, "dst p : %d\n",
+ ntohs(udp.hdr.dst_port));
+ NT_LOG(DBG, FILTER, "len : %d\n",
+ ntohs(udp.hdr.len));
+ NT_LOG(DBG, FILTER, "chksum : %04x\n",
+ ntohs(udp.hdr.cksum));
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VXLAN: {
+ struct flow_elem_vxlan vxlan_m;
+
+ size = sizeof(struct flow_elem_vxlan);
+
+ copy_unmasked((uint8_t *)&vxlan_m, &elem[eidx],
+ size);
+
+ vxlan_m.flags =
+ 0x08; /* set always I-flag - valid VNI */
+
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_VXLAN - vni %u\n",
+ (vxlan_m.vni[0] << 16) +
+ (vxlan_m.vni[1] << 8) +
+ vxlan_m.vni[2]);
+
+ memcpy(&fd->tun_hdr.d.hdr8[fd->tun_hdr.len],
+ &vxlan_m, size);
+
+ NT_LOG(DBG, FILTER, "flags : %02x\n",
+ vxlan_m.flags);
+ NT_LOG(DBG, FILTER, "vni : %d\n",
+ (vxlan_m.vni[0] << 16) +
+ (vxlan_m.vni[1] << 8) +
+ vxlan_m.vni[2]);
+
+ fd->tun_hdr.len =
+ (uint8_t)(fd->tun_hdr.len + size);
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_PORT_ID: {
+ const struct flow_elem_port_id *port =
+ (const struct flow_elem_port_id *)
+ elem[eidx]
+ .spec;
+ fd->tun_hdr.user_port_id = port->id;
+ }
+ break;
+
+ case FLOW_ELEM_TYPE_VOID: {
+ NT_LOG(DBG, FILTER,
+ "Tunnel: RTE_FLOW_ITEM_TYPE_VOID (ignoring)\n");
+ }
+ break;
+
+ default:
+ NT_LOG(INF, FILTER,
+ "unsupported Tunnel flow element type %u\n",
+ elem[eidx].type);
+ return -1;
+ }
+
+ eidx++;
+ }
+ }
+
+ if (tun_ipv4) {
+ tun_ipv4->hdr_csum = 0;
+ tun_ipv4->length = 0;
+ fd->tun_hdr.ip_csum_precalc = ntohs(ip_checksum_sum((const be16_t *)&fd->tun_hdr.d
+ .hdr8[14],
+ (unsigned int)sizeof(struct ipv4_hdr_s),
+ (be16_t)htons((uint16_t)(fd->tun_hdr.len - sizeof(struct flow_elem_eth)))));
+
+ NT_LOG(DBG, FILTER,
+ "chksum precalc: %04x, precalc hdr len %u\n",
+ fd->tun_hdr.ip_csum_precalc,
+ fd->tun_hdr.len - sizeof(struct flow_elem_eth));
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c
new file mode 100644
index 0000000000..5a62343718
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat.c
@@ -0,0 +1,1789 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "CAT"
+#define _VER_ be->cat.ver
+
+static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count);
+static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count);
+static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count);
+
+bool hw_mod_cat_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_cat_present(be->be_dev);
+}
+
+int hw_mod_cat_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_cat_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "CAT MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ int nb = be->iface->get_nb_cat_funcs(be->be_dev);
+
+ if (nb <= 0)
+ return error_resource_count(__func__, "cat_funcs", _MOD_, _VER_);
+ be->cat.nb_cat_funcs = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_flow_types(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "km_flow_types", _MOD_, _VER_);
+ be->cat.nb_flow_types = (uint32_t)nb;
+
+ nb = be->iface->get_nb_pm_ext(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "pm_ext", _MOD_, _VER_);
+ be->cat.nb_pm_ext = (uint32_t)nb;
+
+ nb = be->iface->get_nb_len(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "len", _MOD_, _VER_);
+ be->cat.nb_len = (uint32_t)nb;
+
+ nb = be->iface->get_kcc_size(be->be_dev);
+ if (nb < 0)
+ return error_resource_count(__func__, "kcc_size", _MOD_, _VER_);
+ be->cat.kcc_size = (uint32_t)nb;
+
+ nb = be->iface->get_kcc_banks(be->be_dev);
+ if (nb < 0)
+ return error_resource_count(__func__, "kcc_banks", _MOD_, _VER_);
+ be->cat.kcc_banks = (uint32_t)nb;
+
+ nb = be->iface->get_nb_cat_km_if_cnt(be->be_dev);
+ if (nb < 0)
+ return error_resource_count(__func__, "km_if_count", _MOD_, _VER_);
+ be->cat.km_if_count = (uint32_t)nb;
+
+ int idx = be->iface->get_nb_cat_km_if_m0(be->be_dev);
+
+ be->cat.km_if_m0 = idx;
+
+ idx = be->iface->get_nb_cat_km_if_m1(be->be_dev);
+ be->cat.km_if_m1 = idx;
+
+ if (be->cat.kcc_banks)
+ be->cat.kcc_records = be->cat.kcc_size / be->cat.kcc_banks;
+ else
+ be->cat.kcc_records = 0;
+
+ be->cat.kcc_id_bit_size = 10;
+
+ switch (_VER_) {
+ case 18:
+ be->cat.cts_num = 11;
+ if (!callocate_mod(CAST_COMMON(&be->cat), 12,
+ &be->cat.v18.cfn,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_cfn_s),
+ &be->cat.v18.kce,
+ (be->cat.nb_cat_funcs / 8),
+ sizeof(struct cat_v18_kce_s),
+ &be->cat.v18.kcs,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_kcs_s),
+ &be->cat.v18.fte,
+ (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 2,
+ sizeof(struct cat_v18_fte_s),
+ &be->cat.v18.cte,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_cte_s),
+ &be->cat.v18.cts,
+ be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),
+ sizeof(struct cat_v18_cts_s),
+ &be->cat.v18.cot,
+ be->max_categories,
+ sizeof(struct cat_v18_cot_s),
+ &be->cat.v18.cct,
+ be->max_categories * 4,
+ sizeof(struct cat_v18_cct_s),
+ &be->cat.v18.exo,
+ be->cat.nb_pm_ext,
+ sizeof(struct cat_v18_exo_s),
+ &be->cat.v18.rck,
+ be->cat.nb_pm_ext * 64,
+ sizeof(struct cat_v18_rck_s),
+ &be->cat.v18.len,
+ be->cat.nb_len,
+ sizeof(struct cat_v18_len_s),
+ &be->cat.v18.kcc_cam,
+ be->cat.kcc_size,
+ sizeof(struct cat_v18_kcc_s)))
+ return -1;
+
+ break;
+ /* end case 18 */
+ case 21:
+ be->cat.cts_num = 11;
+ if (!callocate_mod(CAST_COMMON(&be->cat), 12,
+ &be->cat.v21.cfn,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_cfn_s),
+ &be->cat.v21.kce,
+ (be->cat.nb_cat_funcs / 8),
+ sizeof(struct cat_v21_kce_s),
+ &be->cat.v21.kcs,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_kcs_s),
+ &be->cat.v21.fte,
+ (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4,
+ sizeof(struct cat_v21_fte_s),
+ &be->cat.v21.cte,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v18_cte_s),
+ &be->cat.v21.cts,
+ be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),
+ sizeof(struct cat_v18_cts_s),
+ &be->cat.v21.cot,
+ be->max_categories,
+ sizeof(struct cat_v18_cot_s),
+ &be->cat.v21.cct,
+ be->max_categories * 4,
+ sizeof(struct cat_v18_cct_s),
+ &be->cat.v21.exo,
+ be->cat.nb_pm_ext,
+ sizeof(struct cat_v18_exo_s),
+ &be->cat.v21.rck,
+ be->cat.nb_pm_ext * 64,
+ sizeof(struct cat_v18_rck_s),
+ &be->cat.v21.len,
+ be->cat.nb_len,
+ sizeof(struct cat_v18_len_s),
+ &be->cat.v21.kcc_cam,
+ be->cat.kcc_size,
+ sizeof(struct cat_v18_kcc_s)))
+ return -1;
+
+ break;
+ /* end case 21 */
+ case 22:
+ be->cat.cts_num = 12;
+ if (!callocate_mod(CAST_COMMON(&be->cat), 14,
+ &be->cat.v22.cfn,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_cfn_s),
+ &be->cat.v22.kce,
+ (be->cat.nb_cat_funcs / 8),
+ sizeof(struct cat_v21_kce_s),
+ &be->cat.v22.kcs,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v21_kcs_s),
+ &be->cat.v22.fte,
+ (be->cat.nb_cat_funcs / 8) * be->cat.nb_flow_types * 4,
+ sizeof(struct cat_v21_fte_s),
+ &be->cat.v22.cte,
+ be->cat.nb_cat_funcs,
+ sizeof(struct cat_v22_cte_s),
+ &be->cat.v22.cts,
+ be->cat.nb_cat_funcs * ((be->cat.cts_num + 1) / 2),
+ sizeof(struct cat_v18_cts_s),
+ &be->cat.v22.cot,
+ be->max_categories,
+ sizeof(struct cat_v18_cot_s),
+ &be->cat.v22.cct,
+ be->max_categories * 4,
+ sizeof(struct cat_v18_cct_s),
+ &be->cat.v22.exo,
+ be->cat.nb_pm_ext,
+ sizeof(struct cat_v18_exo_s),
+ &be->cat.v22.rck,
+ be->cat.nb_pm_ext * 64,
+ sizeof(struct cat_v18_rck_s),
+ &be->cat.v22.len,
+ be->cat.nb_len,
+ sizeof(struct cat_v18_len_s),
+ &be->cat.v22.kcc_cam,
+ be->cat.kcc_size,
+ sizeof(struct cat_v18_kcc_s),
+ &be->cat.v22.cce,
+ 4,
+ sizeof(struct cat_v22_cce_s),
+ &be->cat.v22.ccs,
+ 1024,
+ sizeof(struct cat_v22_ccs_s)))
+ return -1;
+
+ break;
+ /* end case 22 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_cat_free(struct flow_api_backend_s *be)
+{
+ if (be->cat.base) {
+ free(be->cat.base);
+ be->cat.base = NULL;
+ }
+}
+
+static int cfn_reset(struct flow_api_backend_s *be, int i)
+{
+ int err = hw_mod_cat_cfn_set(be, HW_CAT_CFN_PRESET_ALL, i, 0, 0);
+
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_ISL, i, 0,
+ 0xffffffff); /* accept both ISL or not ISL */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_CFP, i, 0,
+ 0xffffffff); /* accept both CFP or not CFP */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MAC, i, 0,
+ 0xffffffff); /* accept all MACs */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L2, i, 0,
+ 0xffffffff); /* accept all L2 prot */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VNTAG, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_VLAN, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_MPLS, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L3, i, 0,
+ 0xffffffff); /* accept all L3 prot */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_FRAG, i, 0,
+ 0xffffffff); /* accept all fragments */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_IP_PROT, i, 0,
+ 0xffffffff); /* IP prot check disabled */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_L4, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TUNNEL, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L2, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_VLAN, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_MPLS, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L3, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_FRAG, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_IP_PROT, i, 0,
+ 0xffffffff); /* inner IP prot check disabled */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PTC_TNL_L4, i, 0,
+ 0xffffffff); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_CV, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_FCS, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TRUNC, i, 0,
+ 0xffffffff); /* accept all truncations */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L3_CS, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_L4_CS, i, 0, 3); /* accept all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_PM_OR_INV, i, 0, 1); /* */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_LC_INV, i, 0, 1); /* */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_KM0_OR, i, 0,
+ 0xffffffff); /* or all */
+ if (_VER_ >= 21) {
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_KM1_OR, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L3_CS, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_L4_CS, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TTL_EXP, i, 0,
+ 0xffffffff); /* or all */
+ hw_mod_cat_cfn_set(be, HW_CAT_CFN_ERR_TNL_TTL_EXP, i, 0,
+ 0xffffffff); /* or all */
+ }
+ return err;
+}
+
+int hw_mod_cat_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->cat);
+
+ NT_LOG(DBG, FILTER, "INIT CAT CFN\n");
+ if (hw_mod_cat_cfn_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ if (_VER_ <= 18) {
+ NT_LOG(DBG, FILTER, "INIT CAT KCE\n");
+ if (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, 0, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT KCS\n");
+ if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, 0, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT FTE\n");
+ if (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, 0, 0,
+ ALL_ENTRIES))
+ return -1;
+ } else {
+ NT_LOG(DBG, FILTER, "INIT CAT KCE 0\n");
+ if (hw_mod_cat_kce_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,
+ 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT KCS 0\n");
+ if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,
+ 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT FTE 0\n");
+ if (hw_mod_cat_fte_flush(be, KM_FLM_IF_FIRST, be->cat.km_if_m0,
+ 0, ALL_ENTRIES))
+ return -1;
+
+ if (be->cat.km_if_count > 1) {
+ NT_LOG(DBG, FILTER, "INIT CAT KCE 1\n");
+ if (hw_mod_cat_kce_flush(be, KM_FLM_IF_SECOND,
+ be->cat.km_if_m1, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT KCS 1\n");
+ if (hw_mod_cat_kcs_flush(be, KM_FLM_IF_SECOND,
+ be->cat.km_if_m1, 0,
+ ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT FTE 1\n");
+ if (hw_mod_cat_fte_flush(be, KM_FLM_IF_SECOND,
+ be->cat.km_if_m1, 0,
+ ALL_ENTRIES))
+ return -1;
+ }
+ }
+
+ NT_LOG(DBG, FILTER, "INIT CAT CTE\n");
+ if (hw_mod_cat_cte_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT CTS\n");
+ if (hw_mod_cat_cts_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT COT\n");
+ if (hw_mod_cat_cot_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT CCT\n");
+ if (hw_mod_cat_cct_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT EXO\n");
+ if (hw_mod_cat_exo_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT RCK\n");
+ if (hw_mod_cat_rck_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ NT_LOG(DBG, FILTER, "INIT CAT LEN\n");
+ if (hw_mod_cat_len_flush(be, 0, ALL_ENTRIES))
+ return -1;
+
+ if (be->cat.kcc_size) {
+ NT_LOG(DBG, FILTER, "INIT CAT KCC\n");
+ if (hw_mod_cat_kcc_flush(be, 0, ALL_ENTRIES))
+ return -1;
+ }
+
+ if (_VER_ > 21) {
+ NT_LOG(DBG, FILTER, "INIT CAT CCE\n");
+ if (hw_mod_cat_cce_flush(be, 0, ALL_ENTRIES))
+ return -1;
+ NT_LOG(DBG, FILTER, "INIT CAT CCS\n");
+ if (hw_mod_cat_ccs_flush(be, 0, ALL_ENTRIES))
+ return -1;
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cfn_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ switch (count) {
+ case ALL_ENTRIES:
+ if (start_idx != 0)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx,
+ be->cat.nb_cat_funcs);
+
+ default:
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cfn_flush(be->be_dev, &be->cat, start_idx,
+ count);
+ }
+}
+
+static int hw_mod_cat_cfn_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, int word_off,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if ((unsigned int)index >= be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_CFN_SET_ALL_DEFAULTS:
+ if (get)
+ return error_unsup_field(__func__);
+ return cfn_reset(be, index);
+ case HW_CAT_CFN_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->cat.v18.cfn[index], (uint8_t)*value,
+ sizeof(struct cat_v18_cfn_s));
+ break;
+ case HW_CAT_CFN_COMPARE:
+ rv = do_compare_indexes(be->cat.v18.cfn,
+ sizeof(struct cat_v18_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_FIND:
+ rv = find_equal_index(be->cat.v18.cfn,
+ sizeof(struct cat_v18_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_ENABLE:
+ get_set(&be->cat.v18.cfn[index].enable, value, get);
+ break;
+ case HW_CAT_CFN_INV:
+ get_set(&be->cat.v18.cfn[index].inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_INV:
+ get_set(&be->cat.v18.cfn[index].ptc_inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_ISL:
+ get_set(&be->cat.v18.cfn[index].ptc_isl, value, get);
+ break;
+ case HW_CAT_CFN_PTC_CFP:
+ get_set(&be->cat.v18.cfn[index].ptc_cfp, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MAC:
+ get_set(&be->cat.v18.cfn[index].ptc_mac, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L2:
+ get_set(&be->cat.v18.cfn[index].ptc_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VNTAG:
+ get_set(&be->cat.v18.cfn[index].ptc_vntag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VLAN:
+ get_set(&be->cat.v18.cfn[index].ptc_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MPLS:
+ get_set(&be->cat.v18.cfn[index].ptc_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L3:
+ get_set(&be->cat.v18.cfn[index].ptc_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_FRAG:
+ get_set(&be->cat.v18.cfn[index].ptc_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_IP_PROT:
+ get_set(&be->cat.v18.cfn[index].ptc_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L4:
+ get_set(&be->cat.v18.cfn[index].ptc_l4, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TUNNEL:
+ get_set(&be->cat.v18.cfn[index].ptc_tunnel, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L2:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_VLAN:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_MPLS:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L3:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_FRAG:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_IP_PROT:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L4:
+ get_set(&be->cat.v18.cfn[index].ptc_tnl_l4, value, get);
+ break;
+ case HW_CAT_CFN_ERR_INV:
+ get_set(&be->cat.v18.cfn[index].err_inv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_CV:
+ get_set(&be->cat.v18.cfn[index].err_cv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_FCS:
+ get_set(&be->cat.v18.cfn[index].err_fcs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TRUNC:
+ get_set(&be->cat.v18.cfn[index].err_trunc, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L3_CS:
+ get_set(&be->cat.v18.cfn[index].err_l3_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L4_CS:
+ get_set(&be->cat.v18.cfn[index].err_l4_cs, value, get);
+ break;
+ case HW_CAT_CFN_MAC_PORT:
+ get_set(&be->cat.v18.cfn[index].mac_port, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMP:
+ if (word_off > 1)
+ return error_word_off_too_large(__func__);
+ get_set(&be->cat.v18.cfn[index].pm_cmp[word_off], value, get);
+ break;
+ case HW_CAT_CFN_PM_DCT:
+ get_set(&be->cat.v18.cfn[index].pm_dct, value, get);
+ break;
+ case HW_CAT_CFN_PM_EXT_INV:
+ get_set(&be->cat.v18.cfn[index].pm_ext_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMB:
+ get_set(&be->cat.v18.cfn[index].pm_cmb, value, get);
+ break;
+ case HW_CAT_CFN_PM_AND_INV:
+ get_set(&be->cat.v18.cfn[index].pm_and_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_OR_INV:
+ get_set(&be->cat.v18.cfn[index].pm_or_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_INV:
+ get_set(&be->cat.v18.cfn[index].pm_inv, value, get);
+ break;
+ case HW_CAT_CFN_LC:
+ get_set(&be->cat.v18.cfn[index].lc, value, get);
+ break;
+ case HW_CAT_CFN_LC_INV:
+ get_set(&be->cat.v18.cfn[index].lc_inv, value, get);
+ break;
+ case HW_CAT_CFN_KM0_OR:
+ get_set(&be->cat.v18.cfn[index].km_or, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CFN_SET_ALL_DEFAULTS:
+ if (get)
+ return error_unsup_field(__func__);
+ return cfn_reset(be, index);
+ case HW_CAT_CFN_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->cat.v21.cfn[index], (uint8_t)*value,
+ sizeof(struct cat_v21_cfn_s));
+ break;
+ case HW_CAT_CFN_COMPARE:
+ rv = do_compare_indexes(be->cat.v21.cfn,
+ sizeof(struct cat_v21_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_FIND:
+ rv = find_equal_index(be->cat.v21.cfn,
+ sizeof(struct cat_v21_cfn_s), index, word_off,
+ be->cat.nb_cat_funcs, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_CFN_COPY_FROM:
+ if (get)
+ return error_unsup_field(__func__);
+ memcpy(&be->cat.v21.cfn[index],
+ &be->cat.v21.cfn[*value],
+ sizeof(struct cat_v21_cfn_s));
+ break;
+ case HW_CAT_CFN_ENABLE:
+ get_set(&be->cat.v21.cfn[index].enable, value, get);
+ break;
+ case HW_CAT_CFN_INV:
+ get_set(&be->cat.v21.cfn[index].inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_INV:
+ get_set(&be->cat.v21.cfn[index].ptc_inv, value, get);
+ break;
+ case HW_CAT_CFN_PTC_ISL:
+ get_set(&be->cat.v21.cfn[index].ptc_isl, value, get);
+ break;
+ case HW_CAT_CFN_PTC_CFP:
+ get_set(&be->cat.v21.cfn[index].ptc_cfp, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MAC:
+ get_set(&be->cat.v21.cfn[index].ptc_mac, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L2:
+ get_set(&be->cat.v21.cfn[index].ptc_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VNTAG:
+ get_set(&be->cat.v21.cfn[index].ptc_vntag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_VLAN:
+ get_set(&be->cat.v21.cfn[index].ptc_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_MPLS:
+ get_set(&be->cat.v21.cfn[index].ptc_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L3:
+ get_set(&be->cat.v21.cfn[index].ptc_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_FRAG:
+ get_set(&be->cat.v21.cfn[index].ptc_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_IP_PROT:
+ get_set(&be->cat.v21.cfn[index].ptc_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_L4:
+ get_set(&be->cat.v21.cfn[index].ptc_l4, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TUNNEL:
+ get_set(&be->cat.v21.cfn[index].ptc_tunnel, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L2:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_l2, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_VLAN:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_vlan, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_MPLS:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_mpls, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L3:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_l3, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_FRAG:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_frag, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_IP_PROT:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_ip_prot, value, get);
+ break;
+ case HW_CAT_CFN_PTC_TNL_L4:
+ get_set(&be->cat.v21.cfn[index].ptc_tnl_l4, value, get);
+ break;
+ case HW_CAT_CFN_ERR_INV:
+ get_set(&be->cat.v21.cfn[index].err_inv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_CV:
+ get_set(&be->cat.v21.cfn[index].err_cv, value, get);
+ break;
+ case HW_CAT_CFN_ERR_FCS:
+ get_set(&be->cat.v21.cfn[index].err_fcs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TRUNC:
+ get_set(&be->cat.v21.cfn[index].err_trunc, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L3_CS:
+ get_set(&be->cat.v21.cfn[index].err_l3_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_L4_CS:
+ get_set(&be->cat.v21.cfn[index].err_l4_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TNL_L3_CS:
+ get_set(&be->cat.v21.cfn[index].err_tnl_l3_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TNL_L4_CS:
+ get_set(&be->cat.v21.cfn[index].err_tnl_l4_cs, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TTL_EXP:
+ get_set(&be->cat.v21.cfn[index].err_ttl_exp, value, get);
+ break;
+ case HW_CAT_CFN_ERR_TNL_TTL_EXP:
+ get_set(&be->cat.v21.cfn[index].err_tnl_ttl_exp, value, get);
+ break;
+ case HW_CAT_CFN_MAC_PORT:
+ get_set(&be->cat.v21.cfn[index].mac_port, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMP:
+ if (word_off > 1)
+ return error_word_off_too_large(__func__);
+ get_set(&be->cat.v21.cfn[index].pm_cmp[word_off], value, get);
+ break;
+ case HW_CAT_CFN_PM_DCT:
+ get_set(&be->cat.v21.cfn[index].pm_dct, value, get);
+ break;
+ case HW_CAT_CFN_PM_EXT_INV:
+ get_set(&be->cat.v21.cfn[index].pm_ext_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_CMB:
+ get_set(&be->cat.v21.cfn[index].pm_cmb, value, get);
+ break;
+ case HW_CAT_CFN_PM_AND_INV:
+ get_set(&be->cat.v21.cfn[index].pm_and_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_OR_INV:
+ get_set(&be->cat.v21.cfn[index].pm_or_inv, value, get);
+ break;
+ case HW_CAT_CFN_PM_INV:
+ get_set(&be->cat.v21.cfn[index].pm_inv, value, get);
+ break;
+ case HW_CAT_CFN_LC:
+ get_set(&be->cat.v21.cfn[index].lc, value, get);
+ break;
+ case HW_CAT_CFN_LC_INV:
+ get_set(&be->cat.v21.cfn[index].lc_inv, value, get);
+ break;
+ case HW_CAT_CFN_KM0_OR:
+ get_set(&be->cat.v21.cfn[index].km0_or, value, get);
+ break;
+ case HW_CAT_CFN_KM1_OR:
+ get_set(&be->cat.v21.cfn[index].km1_or, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_cat_cfn_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value)
+{
+ return hw_mod_cat_cfn_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_cat_cfn_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value)
+{
+ return hw_mod_cat_cfn_mod(be, field, index, word_off, value, 1);
+}
+
+static inline int
+find_km_flm_module_interface_index(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id)
+{
+ int km_if_idx;
+
+ if (_VER_ == 18) {
+ km_if_idx = 0;
+ } else {
+ if (if_num == KM_FLM_IF_SECOND) {
+ if (be->cat.km_if_m1 == km_if_id)
+ km_if_idx = 1;
+ else
+ return error_unsup_field(__func__);
+ } else {
+ if (be->cat.km_if_m0 == km_if_id)
+ km_if_idx = 0;
+ else if (be->cat.km_if_m1 == km_if_id)
+ km_if_idx = 1;
+ else
+ return error_unsup_field(__func__);
+ }
+ }
+ return km_if_idx;
+}
+
+/*
+ * KCE
+ */
+
+static int hw_mod_cat_kce_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count)
+{
+ /* writes 8 bits - one for each cfn - at a time */
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs / 8;
+ if ((unsigned int)(start_idx + count) > (be->cat.nb_cat_funcs / 8))
+ return error_index_too_large(__func__);
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ return be->iface->cat_kce_flush(be->be_dev, &be->cat, km_if_idx,
+ start_idx, count);
+}
+
+int hw_mod_cat_kce_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kce_flush(be, if_num, 0, start_idx, count);
+}
+
+int hw_mod_cat_kce_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kce_flush(be, if_num, 1, start_idx, count);
+}
+
+static int hw_mod_cat_kce_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int index, uint32_t *value, int get)
+{
+ if ((unsigned int)index >= (be->cat.nb_cat_funcs / 8))
+ return error_index_too_large(__func__);
+
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_KCE_ENABLE_BM:
+ get_set(&be->cat.v18.kce[index].enable_bm, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_KCE_ENABLE_BM:
+ get_set(&be->cat.v21.kce[index].enable_bm[km_if_idx],
+ value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_kce_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 0, index, &value, 0);
+}
+
+int hw_mod_cat_kce_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 0, index, value, 1);
+}
+
+int hw_mod_cat_kce_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 1, index, &value, 0);
+}
+
+int hw_mod_cat_kce_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kce_mod(be, field, if_num, 1, index, value, 1);
+}
+
+/*
+ * KCS
+ */
+static int hw_mod_cat_kcs_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ return be->iface->cat_kcs_flush(be->be_dev, &be->cat, km_if_idx,
+ start_idx, count);
+}
+
+int hw_mod_cat_kcs_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kcs_flush(be, if_num, 0, start_idx, count);
+}
+
+int hw_mod_cat_kcs_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_kcs_flush(be, if_num, 1, start_idx, count);
+}
+
+static int hw_mod_cat_kcs_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int index, uint32_t *value, int get)
+{
+ if ((unsigned int)index >= be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_KCS_CATEGORY:
+ get_set(&be->cat.v18.kcs[index].category, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_KCS_CATEGORY:
+ get_set(&be->cat.v21.kcs[index].category[km_if_idx],
+ value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_kcs_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 0, index, &value, 0);
+}
+
+int hw_mod_cat_kcs_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 0, index, value, 1);
+}
+
+int hw_mod_cat_kcs_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 1, index, &value, 0);
+}
+
+int hw_mod_cat_kcs_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_kcs_mod(be, field, if_num, 1, index, value, 1);
+}
+
+/*
+ * FTE
+ */
+static int hw_mod_cat_fte_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int start_idx, int count)
+{
+ const uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2;
+
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types *
+ key_cnt;
+ if ((unsigned int)(start_idx + count) >
+ (be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt))
+ return error_index_too_large(__func__);
+
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ return be->iface->cat_fte_flush(be->be_dev, &be->cat, km_if_idx,
+ start_idx, count);
+}
+
+int hw_mod_cat_fte_km_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_fte_flush(be, if_num, 0, start_idx, count);
+}
+
+int hw_mod_cat_fte_flm_flush(struct flow_api_backend_s *be,
+ enum km_flm_if_select_e if_num, int start_idx,
+ int count)
+{
+ return hw_mod_cat_fte_flush(be, if_num, 1, start_idx, count);
+}
+
+static int hw_mod_cat_fte_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int km_if_id,
+ int index, uint32_t *value, int get)
+{
+ const uint32_t key_cnt = (_VER_ >= 20) ? 4 : 2;
+
+ if ((unsigned int)index >=
+ (be->cat.nb_cat_funcs / 8 * be->cat.nb_flow_types * key_cnt))
+ return error_index_too_large(__func__);
+ /* find KM module */
+ int km_if_idx;
+
+ km_if_idx = find_km_flm_module_interface_index(be, if_num, km_if_id);
+ if (km_if_idx < 0)
+ return km_if_idx;
+
+ switch (_VER_) {
+ case 18:
+ switch (field) {
+ case HW_CAT_FTE_ENABLE_BM:
+ get_set(&be->cat.v18.fte[index].enable_bm, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18 */
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_FTE_ENABLE_BM:
+ get_set(&be->cat.v21.fte[index].enable_bm[km_if_idx],
+ value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_fte_km_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 0, index, &value, 0);
+}
+
+int hw_mod_cat_fte_km_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 0, index, value, 1);
+}
+
+int hw_mod_cat_fte_flm_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 1, index, &value, 0);
+}
+
+int hw_mod_cat_fte_flm_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ enum km_flm_if_select_e if_num, int index,
+ uint32_t *value)
+{
+ return hw_mod_cat_fte_mod(be, field, if_num, 1, index, value, 1);
+}
+
+int hw_mod_cat_cte_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cte_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cte_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_cat_funcs)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CTE_ENABLE_BM:
+ get_set(&be->cat.v18.cte[index].enable_bm, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cte_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cte_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cte_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cte_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cts_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ int addr_size = (_VER_ < 15) ? 8 : ((be->cat.cts_num + 1) / 2);
+
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs * addr_size;
+ if ((unsigned int)(start_idx + count) >
+ (be->cat.nb_cat_funcs * addr_size))
+ return error_index_too_large(__func__);
+ return be->iface->cat_cts_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cts_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ int addr_size = (be->cat.cts_num + 1) / 2;
+
+ if ((unsigned int)index >= (be->cat.nb_cat_funcs * addr_size))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CTS_CAT_A:
+ get_set(&be->cat.v18.cts[index].cat_a, value, get);
+ break;
+ case HW_CAT_CTS_CAT_B:
+ get_set(&be->cat.v18.cts[index].cat_b, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cts_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cts_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cts_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cts_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cot_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->max_categories;
+ if ((unsigned int)(start_idx + count) > be->max_categories)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cot_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cot_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ int rv = 0;
+ if ((unsigned int)index >= be->max_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_COT_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->cat.v18.cot[index], (uint8_t)*value,
+ sizeof(struct cat_v18_cot_s));
+ break;
+ case HW_CAT_COT_COMPARE:
+ rv = do_compare_indexes(be->cat.v18.cot,
+ sizeof(struct cat_v18_cot_s), index, *value,
+ be->max_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_COT_FIND:
+ rv = find_equal_index(be->cat.v18.cot,
+ sizeof(struct cat_v18_cot_s), index, *value,
+ be->max_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_CAT_COT_COLOR:
+ get_set(&be->cat.v18.cot[index].color, value, get);
+ break;
+ case HW_CAT_COT_KM:
+ get_set(&be->cat.v18.cot[index].km, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cot_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cot_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cot_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cot_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cct_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_cat_funcs * 4;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_cat_funcs * 4)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cct_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cct_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_cat_funcs * 4)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_CCT_COLOR:
+ get_set(&be->cat.v18.cct[index].color, value, get);
+ break;
+ case HW_CAT_CCT_KM:
+ get_set(&be->cat.v18.cct[index].km, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cct_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cct_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cct_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cct_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_kcc_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.kcc_size;
+ if ((unsigned int)(start_idx + count) > be->cat.kcc_size)
+ return error_index_too_large(__func__);
+ return be->iface->cat_kcc_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_kcc_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, int word_off,
+ uint32_t *value, int get)
+{
+ if ((unsigned int)index >= be->cat.kcc_size)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_KCC_KEY:
+ if (word_off > 1)
+ return error_word_off_too_large(__func__);
+ get_set(&be->cat.v18.kcc_cam[index].key[word_off], value,
+ get);
+ break;
+
+ case HW_CAT_KCC_CATEGORY:
+ get_set(&be->cat.v18.kcc_cam[index].category, value, get);
+ break;
+
+ case HW_CAT_KCC_ID:
+ get_set(&be->cat.v18.kcc_cam[index].id, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_kcc_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t value)
+{
+ return hw_mod_cat_kcc_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_cat_kcc_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, int word_off, uint32_t *value)
+{
+ return hw_mod_cat_kcc_mod(be, field, index, word_off, value, 1);
+}
+
+int hw_mod_cat_exo_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_pm_ext;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_pm_ext)
+ return error_index_too_large(__func__);
+ return be->iface->cat_exo_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_exo_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_pm_ext)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_EXO_DYN:
+ get_set(&be->cat.v18.exo[index].dyn, value, get);
+ break;
+ case HW_CAT_EXO_OFS:
+ get_set_signed(&be->cat.v18.exo[index].ofs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_exo_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_exo_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_exo_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_exo_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_rck_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_pm_ext * 64;
+ if ((unsigned int)(start_idx + count) > (be->cat.nb_pm_ext * 64))
+ return error_index_too_large(__func__);
+ return be->iface->cat_rck_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_rck_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= (be->cat.nb_pm_ext * 64))
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_RCK_DATA:
+ get_set(&be->cat.v18.rck[index].rck_data, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_rck_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_rck_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_rck_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_rck_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_len_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->cat.nb_len;
+ if ((unsigned int)(start_idx + count) > be->cat.nb_len)
+ return error_index_too_large(__func__);
+ return be->iface->cat_len_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_len_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_len)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 18:
+ case 21:
+ case 22:
+ switch (field) {
+ case HW_CAT_LEN_LOWER:
+ get_set(&be->cat.v18.len[index].lower, value, get);
+ break;
+ case HW_CAT_LEN_UPPER:
+ get_set(&be->cat.v18.len[index].upper, value, get);
+ break;
+ case HW_CAT_LEN_DYN1:
+ get_set(&be->cat.v18.len[index].dyn1, value, get);
+ break;
+ case HW_CAT_LEN_DYN2:
+ get_set(&be->cat.v18.len[index].dyn2, value, get);
+ break;
+ case HW_CAT_LEN_INV:
+ get_set(&be->cat.v18.len[index].inv, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 18/21/22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_len_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_len_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_len_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_len_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_cce_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = 4;
+ if ((unsigned int)(start_idx + count) > 4)
+ return error_index_too_large(__func__);
+ return be->iface->cat_cce_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_cce_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_len)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 22:
+ switch (field) {
+ case HW_CAT_CCE_IMM:
+ get_set(&be->cat.v22.cce[index].imm, value, get);
+ break;
+ case HW_CAT_CCE_IND:
+ get_set(&be->cat.v22.cce[index].ind, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_cce_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_cce_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_cce_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_cce_mod(be, field, index, value, 1);
+}
+
+int hw_mod_cat_ccs_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = 1024;
+ if ((unsigned int)(start_idx + count) > 1024)
+ return error_index_too_large(__func__);
+ return be->iface->cat_ccs_flush(be->be_dev, &be->cat, start_idx, count);
+}
+
+static int hw_mod_cat_ccs_mod(struct flow_api_backend_s *be,
+ enum hw_cat_e field, int index, uint32_t *value,
+ int get)
+{
+ if ((unsigned int)index >= be->cat.nb_len)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 22:
+ switch (field) {
+ case HW_CAT_CCS_COR_EN:
+ get_set(&be->cat.v22.ccs[index].cor_en, value, get);
+ break;
+ case HW_CAT_CCS_COR:
+ get_set(&be->cat.v22.ccs[index].cor, value, get);
+ break;
+ case HW_CAT_CCS_HSH_EN:
+ get_set(&be->cat.v22.ccs[index].hsh_en, value, get);
+ break;
+ case HW_CAT_CCS_HSH:
+ get_set(&be->cat.v22.ccs[index].hsh, value, get);
+ break;
+ case HW_CAT_CCS_QSL_EN:
+ get_set(&be->cat.v22.ccs[index].qsl_en, value, get);
+ break;
+ case HW_CAT_CCS_QSL:
+ get_set(&be->cat.v22.ccs[index].qsl, value, get);
+ break;
+ case HW_CAT_CCS_IPF_EN:
+ get_set(&be->cat.v22.ccs[index].ipf_en, value, get);
+ break;
+ case HW_CAT_CCS_IPF:
+ get_set(&be->cat.v22.ccs[index].ipf, value, get);
+ break;
+ case HW_CAT_CCS_SLC_EN:
+ get_set(&be->cat.v22.ccs[index].slc_en, value, get);
+ break;
+ case HW_CAT_CCS_SLC:
+ get_set(&be->cat.v22.ccs[index].slc, value, get);
+ break;
+ case HW_CAT_CCS_PDB_EN:
+ get_set(&be->cat.v22.ccs[index].pdb_en, value, get);
+ break;
+ case HW_CAT_CCS_PDB:
+ get_set(&be->cat.v22.ccs[index].pdb, value, get);
+ break;
+ case HW_CAT_CCS_MSK_EN:
+ get_set(&be->cat.v22.ccs[index].msk_en, value, get);
+ break;
+ case HW_CAT_CCS_MSK:
+ get_set(&be->cat.v22.ccs[index].msk, value, get);
+ break;
+ case HW_CAT_CCS_HST_EN:
+ get_set(&be->cat.v22.ccs[index].hst_en, value, get);
+ break;
+ case HW_CAT_CCS_HST:
+ get_set(&be->cat.v22.ccs[index].hst, value, get);
+ break;
+ case HW_CAT_CCS_EPP_EN:
+ get_set(&be->cat.v22.ccs[index].epp_en, value, get);
+ break;
+ case HW_CAT_CCS_EPP:
+ get_set(&be->cat.v22.ccs[index].epp, value, get);
+ break;
+ case HW_CAT_CCS_TPE_EN:
+ get_set(&be->cat.v22.ccs[index].tpe_en, value, get);
+ break;
+ case HW_CAT_CCS_TPE:
+ get_set(&be->cat.v22.ccs[index].tpe, value, get);
+ break;
+ case HW_CAT_CCS_RRB_EN:
+ get_set(&be->cat.v22.ccs[index].rrb_en, value, get);
+ break;
+ case HW_CAT_CCS_RRB:
+ get_set(&be->cat.v22.ccs[index].rrb, value, get);
+ break;
+ case HW_CAT_CCS_SB0_TYPE:
+ get_set(&be->cat.v22.ccs[index].sb0_type, value, get);
+ break;
+ case HW_CAT_CCS_SB0_DATA:
+ get_set(&be->cat.v22.ccs[index].sb0_data, value, get);
+ break;
+ case HW_CAT_CCS_SB1_TYPE:
+ get_set(&be->cat.v22.ccs[index].sb1_type, value, get);
+ break;
+ case HW_CAT_CCS_SB1_DATA:
+ get_set(&be->cat.v22.ccs[index].sb1_data, value, get);
+ break;
+ case HW_CAT_CCS_SB2_TYPE:
+ get_set(&be->cat.v22.ccs[index].sb2_type, value, get);
+ break;
+ case HW_CAT_CCS_SB2_DATA:
+ get_set(&be->cat.v22.ccs[index].sb2_data, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 22 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_cat_ccs_set(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_cat_ccs_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_cat_ccs_get(struct flow_api_backend_s *be, enum hw_cat_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_cat_ccs_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h
new file mode 100644
index 0000000000..3dc4a0aac7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v18.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_CAT_V18_H_
+#define _HW_MOD_CAT_V18_H_
+
+struct cat_v18_cfn_s {
+ uint32_t enable;
+ uint32_t inv;
+ /* protocol checks */
+ uint32_t ptc_inv;
+ uint32_t ptc_isl;
+ uint32_t ptc_cfp;
+ uint32_t ptc_mac;
+ uint32_t ptc_l2;
+ uint32_t ptc_vntag;
+ uint32_t ptc_vlan;
+ uint32_t ptc_mpls;
+ uint32_t ptc_l3;
+ uint32_t ptc_frag;
+ uint32_t ptc_ip_prot;
+ uint32_t ptc_l4;
+ uint32_t ptc_tunnel;
+ uint32_t ptc_tnl_l2;
+ uint32_t ptc_tnl_vlan;
+ uint32_t ptc_tnl_mpls;
+ uint32_t ptc_tnl_l3;
+ uint32_t ptc_tnl_frag;
+ uint32_t ptc_tnl_ip_prot;
+ uint32_t ptc_tnl_l4;
+ /* error checks */
+ uint32_t err_inv;
+ uint32_t err_cv;
+ uint32_t err_fcs;
+ uint32_t err_trunc;
+ uint32_t err_l3_cs;
+ uint32_t err_l4_cs;
+ /* in port */
+ uint32_t mac_port;
+ /* pattern matcher */
+ uint32_t pm_cmp[2];
+ uint32_t pm_dct;
+ uint32_t pm_ext_inv;
+ uint32_t pm_cmb;
+ uint32_t pm_and_inv;
+ uint32_t pm_or_inv;
+ uint32_t pm_inv;
+ uint32_t lc;
+ uint32_t lc_inv;
+ uint32_t km_or;
+};
+
+struct cat_v18_kce_s {
+ uint32_t enable_bm;
+};
+
+struct cat_v18_kcs_s {
+ uint32_t category;
+};
+
+struct cat_v18_fte_s {
+ uint32_t enable_bm;
+};
+
+struct cat_v18_cte_s {
+ union {
+ uint32_t enable_bm;
+ struct {
+ uint32_t col : 1;
+ uint32_t cor : 1;
+ uint32_t hsh : 1;
+ uint32_t qsl : 1;
+ uint32_t ipf : 1;
+ uint32_t slc : 1;
+ uint32_t pdb : 1;
+ uint32_t msk : 1;
+ uint32_t hst : 1;
+ uint32_t epp : 1;
+ uint32_t tpe : 1;
+ } b;
+ };
+};
+
+struct cat_v18_cts_s {
+ uint32_t cat_a;
+ uint32_t cat_b;
+};
+
+struct cat_v18_cot_s {
+ uint32_t color;
+ uint32_t km;
+};
+
+struct cat_v18_cct_s {
+ uint32_t color;
+ uint32_t km;
+};
+
+struct cat_v18_exo_s {
+ uint32_t dyn;
+ int32_t ofs;
+};
+
+struct cat_v18_rck_s {
+ uint32_t rck_data;
+};
+
+struct cat_v18_len_s {
+ uint32_t lower;
+ uint32_t upper;
+ uint32_t dyn1;
+ uint32_t dyn2;
+ uint32_t inv;
+};
+
+struct cat_v18_kcc_s {
+ uint32_t key[2];
+ uint32_t category;
+ uint32_t id;
+};
+
+struct hw_mod_cat_v18_s {
+ struct cat_v18_cfn_s *cfn;
+ struct cat_v18_kce_s *kce;
+ struct cat_v18_kcs_s *kcs;
+ struct cat_v18_fte_s *fte;
+ struct cat_v18_cte_s *cte;
+ struct cat_v18_cts_s *cts;
+ struct cat_v18_cot_s *cot;
+ struct cat_v18_cct_s *cct;
+ struct cat_v18_exo_s *exo;
+ struct cat_v18_rck_s *rck;
+ struct cat_v18_len_s *len;
+ struct cat_v18_kcc_s *kcc_cam;
+};
+
+#endif /* _HW_MOD_CAT_V18_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h
new file mode 100644
index 0000000000..fa69ec11f3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v21.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_CAT_V21_H_
+#define _HW_MOD_CAT_V21_H_
+
+#include "hw_mod_cat_v18.h"
+
+struct cat_v21_cfn_s {
+ uint32_t enable;
+ uint32_t inv;
+ /* protocol checks */
+ uint32_t ptc_inv;
+ uint32_t ptc_isl;
+ uint32_t ptc_cfp;
+ uint32_t ptc_mac;
+ uint32_t ptc_l2;
+ uint32_t ptc_vntag;
+ uint32_t ptc_vlan;
+ uint32_t ptc_mpls;
+ uint32_t ptc_l3;
+ uint32_t ptc_frag;
+ uint32_t ptc_ip_prot;
+ uint32_t ptc_l4;
+ uint32_t ptc_tunnel;
+ uint32_t ptc_tnl_l2;
+ uint32_t ptc_tnl_vlan;
+ uint32_t ptc_tnl_mpls;
+ uint32_t ptc_tnl_l3;
+ uint32_t ptc_tnl_frag;
+ uint32_t ptc_tnl_ip_prot;
+ uint32_t ptc_tnl_l4;
+ /* error checks */
+ uint32_t err_inv;
+ uint32_t err_cv;
+ uint32_t err_fcs;
+ uint32_t err_trunc;
+ uint32_t err_l3_cs;
+ uint32_t err_l4_cs;
+ uint32_t err_tnl_l3_cs;
+ uint32_t err_tnl_l4_cs;
+ uint32_t err_ttl_exp;
+ uint32_t err_tnl_ttl_exp;
+ /* in port */
+ uint32_t mac_port;
+ /* pattern matcher */
+ uint32_t pm_cmp[2];
+ uint32_t pm_dct;
+ uint32_t pm_ext_inv;
+ uint32_t pm_cmb;
+ uint32_t pm_and_inv;
+ uint32_t pm_or_inv;
+ uint32_t pm_inv;
+ uint32_t lc;
+ uint32_t lc_inv;
+ uint32_t km0_or;
+ uint32_t km1_or;
+};
+
+struct cat_v21_kce_s {
+ uint32_t enable_bm[2];
+};
+
+struct cat_v21_kcs_s {
+ uint32_t category[2];
+};
+
+struct cat_v21_fte_s {
+ uint32_t enable_bm[2];
+};
+
+struct hw_mod_cat_v21_s {
+ struct cat_v21_cfn_s *cfn;
+ struct cat_v21_kce_s *kce;
+ struct cat_v21_kcs_s *kcs;
+ struct cat_v21_fte_s *fte;
+ struct cat_v18_cte_s *cte;
+ struct cat_v18_cts_s *cts;
+ struct cat_v18_cot_s *cot;
+ struct cat_v18_cct_s *cct;
+ struct cat_v18_exo_s *exo;
+ struct cat_v18_rck_s *rck;
+ struct cat_v18_len_s *len;
+ struct cat_v18_kcc_s *kcc_cam;
+};
+
+#endif /* _HW_MOD_CAT_V21_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h
new file mode 100644
index 0000000000..fa7dc6f441
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_cat_v22.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_CAT_V22_H_
+#define _HW_MOD_CAT_V22_H_
+
+#include "hw_mod_cat_v21.h"
+
+struct cat_v22_cte_s {
+ union {
+ uint32_t enable_bm;
+ struct {
+ uint32_t col : 1;
+ uint32_t cor : 1;
+ uint32_t hsh : 1;
+ uint32_t qsl : 1;
+ uint32_t ipf : 1;
+ uint32_t slc : 1;
+ uint32_t pdb : 1;
+ uint32_t msk : 1;
+ uint32_t hst : 1;
+ uint32_t epp : 1;
+ uint32_t tpe : 1;
+ uint32_t rrb : 1;
+ } b;
+ };
+};
+
+struct cat_v22_cce_s {
+ uint32_t imm;
+ uint32_t ind;
+};
+
+struct cat_v22_ccs_s {
+ uint32_t cor_en;
+ uint32_t cor;
+ uint32_t hsh_en;
+ uint32_t hsh;
+ uint32_t qsl_en;
+ uint32_t qsl;
+ uint32_t ipf_en;
+ uint32_t ipf;
+ uint32_t slc_en;
+ uint32_t slc;
+ uint32_t pdb_en;
+ uint32_t pdb;
+ uint32_t msk_en;
+ uint32_t msk;
+ uint32_t hst_en;
+ uint32_t hst;
+ uint32_t epp_en;
+ uint32_t epp;
+ uint32_t tpe_en;
+ uint32_t tpe;
+ uint32_t rrb_en;
+ uint32_t rrb;
+ uint32_t sb0_type;
+ uint32_t sb0_data;
+ uint32_t sb1_type;
+ uint32_t sb1_data;
+ uint32_t sb2_type;
+ uint32_t sb2_data;
+};
+
+struct hw_mod_cat_v22_s {
+ struct cat_v21_cfn_s *cfn;
+ struct cat_v21_kce_s *kce; /* KCE 0/1 */
+ struct cat_v21_kcs_s *kcs; /* KCS 0/1 */
+ struct cat_v21_fte_s *fte; /* FTE 0/1 */
+ struct cat_v22_cte_s *cte;
+ struct cat_v18_cts_s *cts;
+ struct cat_v18_cot_s *cot;
+ struct cat_v18_cct_s *cct;
+ struct cat_v18_exo_s *exo;
+ struct cat_v18_rck_s *rck;
+ struct cat_v18_len_s *len;
+ struct cat_v18_kcc_s *kcc_cam;
+ struct cat_v22_cce_s *cce;
+ struct cat_v22_ccs_s *ccs;
+};
+
+#endif /* _HW_MOD_CAT_V22_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c
new file mode 100644
index 0000000000..404add5fe6
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm.c
@@ -0,0 +1,1099 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "FLM"
+#define _VER_ be->flm.ver
+
+bool hw_mod_flm_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_flm_present(be->be_dev);
+}
+
+int hw_mod_flm_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_flm_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "FLM MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_flm_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_categories", _MOD_, _VER_);
+ be->flm.nb_categories = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_size_mb(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_size_mb", _MOD_, _VER_);
+ be->flm.nb_size_mb = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_entry_size(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_entry_size", _MOD_, _VER_);
+ be->flm.nb_entry_size = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_variant(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_variant", _MOD_, _VER_);
+ be->flm.nb_variant = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_prios(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_prios", _MOD_, _VER_);
+ be->flm.nb_prios = (uint32_t)nb;
+
+ nb = be->iface->get_nb_flm_pst_profiles(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "flm_variant", _MOD_, _VER_);
+ be->flm.nb_pst_profiles = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 17:
+ if (!callocate_mod(CAST_COMMON(&be->flm), 26,
+ &be->flm.v17.control, 1,
+ sizeof(struct flm_v17_control_s),
+ &be->flm.v17.status, 1,
+ sizeof(struct flm_v17_status_s),
+ &be->flm.v17.timeout, 1,
+ sizeof(struct flm_v17_timeout_s),
+ &be->flm.v17.scrub, 1,
+ sizeof(struct flm_v17_scrub_s),
+ &be->flm.v17.load_bin, 1,
+ sizeof(struct flm_v17_load_bin_s),
+ &be->flm.v17.load_pps, 1,
+ sizeof(struct flm_v17_load_pps_s),
+ &be->flm.v17.load_lps, 1,
+ sizeof(struct flm_v17_load_lps_s),
+ &be->flm.v17.load_aps, 1,
+ sizeof(struct flm_v17_load_aps_s),
+ &be->flm.v17.prio, 1,
+ sizeof(struct flm_v17_prio_s),
+ &be->flm.v17.pst, be->flm.nb_pst_profiles,
+ sizeof(struct flm_v17_pst_s),
+ &be->flm.v17.rcp, be->flm.nb_categories,
+ sizeof(struct flm_v17_rcp_s),
+ &be->flm.v17.buf_ctrl, 1,
+ sizeof(struct flm_v17_buf_ctrl_s),
+ &be->flm.v17.lrn_done, 1,
+ sizeof(struct flm_v17_stat_lrn_done_s),
+ &be->flm.v17.lrn_ignore, 1,
+ sizeof(struct flm_v17_stat_lrn_ignore_s),
+ &be->flm.v17.lrn_fail, 1,
+ sizeof(struct flm_v17_stat_lrn_fail_s),
+ &be->flm.v17.unl_done, 1,
+ sizeof(struct flm_v17_stat_unl_done_s),
+ &be->flm.v17.unl_ignore, 1,
+ sizeof(struct flm_v17_stat_unl_ignore_s),
+ &be->flm.v17.rel_done, 1,
+ sizeof(struct flm_v17_stat_rel_done_s),
+ &be->flm.v17.rel_ignore, 1,
+ sizeof(struct flm_v17_stat_rel_ignore_s),
+ &be->flm.v17.aul_done, 1,
+ sizeof(struct flm_v17_stat_aul_done_s),
+ &be->flm.v17.aul_ignore, 1,
+ sizeof(struct flm_v17_stat_aul_ignore_s),
+ &be->flm.v17.aul_fail, 1,
+ sizeof(struct flm_v17_stat_aul_fail_s),
+ &be->flm.v17.tul_done, 1,
+ sizeof(struct flm_v17_stat_tul_done_s),
+ &be->flm.v17.flows, 1,
+ sizeof(struct flm_v17_stat_flows_s),
+ &be->flm.v17.prb_done, 1,
+ sizeof(struct flm_v17_stat_prb_done_s),
+ &be->flm.v17.prb_ignore, 1,
+ sizeof(struct flm_v17_stat_prb_ignore_s)))
+ return -1;
+ break;
+
+ case 20:
+ if (!callocate_mod(CAST_COMMON(&be->flm), 38,
+ &be->flm.v17.control, 1,
+ sizeof(struct flm_v17_control_s),
+ &be->flm.v17.status, 1,
+ sizeof(struct flm_v17_status_s),
+ &be->flm.v17.timeout, 1,
+ sizeof(struct flm_v17_timeout_s),
+ &be->flm.v17.scrub, 1,
+ sizeof(struct flm_v17_scrub_s),
+ &be->flm.v17.load_bin, 1,
+ sizeof(struct flm_v17_load_bin_s),
+ &be->flm.v17.load_pps, 1,
+ sizeof(struct flm_v17_load_pps_s),
+ &be->flm.v17.load_lps, 1,
+ sizeof(struct flm_v17_load_lps_s),
+ &be->flm.v17.load_aps, 1,
+ sizeof(struct flm_v17_load_aps_s),
+ &be->flm.v17.prio, 1,
+ sizeof(struct flm_v17_prio_s),
+ &be->flm.v17.pst, be->flm.nb_pst_profiles,
+ sizeof(struct flm_v17_pst_s),
+ &be->flm.v17.rcp, be->flm.nb_categories,
+ sizeof(struct flm_v17_rcp_s),
+ &be->flm.v17.buf_ctrl, 1,
+ sizeof(struct flm_v17_buf_ctrl_s),
+ &be->flm.v17.lrn_done, 1,
+ sizeof(struct flm_v17_stat_lrn_done_s),
+ &be->flm.v17.lrn_ignore, 1,
+ sizeof(struct flm_v17_stat_lrn_ignore_s),
+ &be->flm.v17.lrn_fail, 1,
+ sizeof(struct flm_v17_stat_lrn_fail_s),
+ &be->flm.v17.unl_done, 1,
+ sizeof(struct flm_v17_stat_unl_done_s),
+ &be->flm.v17.unl_ignore, 1,
+ sizeof(struct flm_v17_stat_unl_ignore_s),
+ &be->flm.v17.rel_done, 1,
+ sizeof(struct flm_v17_stat_rel_done_s),
+ &be->flm.v17.rel_ignore, 1,
+ sizeof(struct flm_v17_stat_rel_ignore_s),
+ &be->flm.v17.aul_done, 1,
+ sizeof(struct flm_v17_stat_aul_done_s),
+ &be->flm.v17.aul_ignore, 1,
+ sizeof(struct flm_v17_stat_aul_ignore_s),
+ &be->flm.v17.aul_fail, 1,
+ sizeof(struct flm_v17_stat_aul_fail_s),
+ &be->flm.v17.tul_done, 1,
+ sizeof(struct flm_v17_stat_tul_done_s),
+ &be->flm.v17.flows, 1,
+ sizeof(struct flm_v17_stat_flows_s),
+ &be->flm.v17.prb_done, 1,
+ sizeof(struct flm_v17_stat_prb_done_s),
+ &be->flm.v17.prb_ignore, 1,
+ sizeof(struct flm_v17_stat_prb_ignore_s),
+ &be->flm.v20.sta_done, 1,
+ sizeof(struct flm_v20_stat_sta_done_s),
+ &be->flm.v20.inf_done, 1,
+ sizeof(struct flm_v20_stat_inf_done_s),
+ &be->flm.v20.inf_skip, 1,
+ sizeof(struct flm_v20_stat_inf_skip_s),
+ &be->flm.v20.pck_hit, 1,
+ sizeof(struct flm_v20_stat_pck_hit_s),
+ &be->flm.v20.pck_miss, 1,
+ sizeof(struct flm_v20_stat_pck_miss_s),
+ &be->flm.v20.pck_unh, 1,
+ sizeof(struct flm_v20_stat_pck_unh_s),
+ &be->flm.v20.pck_dis, 1,
+ sizeof(struct flm_v20_stat_pck_dis_s),
+ &be->flm.v20.csh_hit, 1,
+ sizeof(struct flm_v20_stat_csh_hit_s),
+ &be->flm.v20.csh_miss, 1,
+ sizeof(struct flm_v20_stat_csh_miss_s),
+ &be->flm.v20.csh_unh, 1,
+ sizeof(struct flm_v20_stat_csh_unh_s),
+ &be->flm.v20.cuc_start, 1,
+ sizeof(struct flm_v20_stat_cuc_start_s),
+ &be->flm.v20.cuc_move, 1,
+ sizeof(struct flm_v20_stat_cuc_move_s)))
+ return -1;
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_flm_free(struct flow_api_backend_s *be)
+{
+ if (be->flm.base) {
+ free(be->flm.base);
+ be->flm.base = NULL;
+ }
+}
+
+int hw_mod_flm_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->flm);
+
+ NT_LOG(DBG, FILTER, "INIT FLM\n");
+ hw_mod_flm_control_set(be, HW_FLM_CONTROL_SPLIT_SDRAM_USAGE, 0x10);
+
+ hw_mod_flm_control_flush(be);
+ hw_mod_flm_timeout_flush(be);
+ hw_mod_flm_scrub_flush(be);
+ hw_mod_flm_rcp_flush(be, 0, ALL_ENTRIES);
+
+ return 0;
+}
+
+int hw_mod_flm_control_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_control_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_control_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_CONTROL_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(be->flm.v17.control, (uint8_t)*value,
+ sizeof(struct flm_v17_control_s));
+ break;
+ case HW_FLM_CONTROL_ENABLE:
+ get_set(&be->flm.v17.control->enable, value, get);
+ break;
+ case HW_FLM_CONTROL_INIT:
+ get_set(&be->flm.v17.control->init, value, get);
+ break;
+ case HW_FLM_CONTROL_LDS:
+ get_set(&be->flm.v17.control->lds, value, get);
+ break;
+ case HW_FLM_CONTROL_LFS:
+ get_set(&be->flm.v17.control->lfs, value, get);
+ break;
+ case HW_FLM_CONTROL_LIS:
+ get_set(&be->flm.v17.control->lis, value, get);
+ break;
+ case HW_FLM_CONTROL_UDS:
+ get_set(&be->flm.v17.control->uds, value, get);
+ break;
+ case HW_FLM_CONTROL_UIS:
+ get_set(&be->flm.v17.control->uis, value, get);
+ break;
+ case HW_FLM_CONTROL_RDS:
+ get_set(&be->flm.v17.control->rds, value, get);
+ break;
+ case HW_FLM_CONTROL_RIS:
+ get_set(&be->flm.v17.control->ris, value, get);
+ break;
+ case HW_FLM_CONTROL_PDS:
+ get_set(&be->flm.v17.control->pds, value, get);
+ break;
+ case HW_FLM_CONTROL_PIS:
+ get_set(&be->flm.v17.control->pis, value, get);
+ break;
+ case HW_FLM_CONTROL_CRCWR:
+ get_set(&be->flm.v17.control->crcwr, value, get);
+ break;
+ case HW_FLM_CONTROL_CRCRD:
+ get_set(&be->flm.v17.control->crcrd, value, get);
+ break;
+ case HW_FLM_CONTROL_RBL:
+ get_set(&be->flm.v17.control->rbl, value, get);
+ break;
+ case HW_FLM_CONTROL_EAB:
+ get_set(&be->flm.v17.control->eab, value, get);
+ break;
+ case HW_FLM_CONTROL_SPLIT_SDRAM_USAGE:
+ get_set(&be->flm.v17.control->split_sdram_usage, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_control_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_control_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_control_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_control_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_status_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_status_flush(be->be_dev, &be->flm);
+}
+
+int hw_mod_flm_status_update(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_status_update(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_status_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_STATUS_CALIBDONE:
+ get_set(&be->flm.v17.status->calibdone, value, get);
+ break;
+ case HW_FLM_STATUS_INITDONE:
+ get_set(&be->flm.v17.status->initdone, value, get);
+ break;
+ case HW_FLM_STATUS_IDLE:
+ get_set(&be->flm.v17.status->idle, value, get);
+ break;
+ case HW_FLM_STATUS_CRITICAL:
+ get_set(&be->flm.v17.status->critical, value, get);
+ break;
+ case HW_FLM_STATUS_PANIC:
+ get_set(&be->flm.v17.status->panic, value, get);
+ break;
+ case HW_FLM_STATUS_CRCERR:
+ get_set(&be->flm.v17.status->crcerr, value, get);
+ break;
+ case HW_FLM_STATUS_EFT_BP:
+ get_set(&be->flm.v17.status->eft_bp, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_status_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_status_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_status_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_status_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_timeout_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_timeout_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_timeout_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_TIMEOUT_T:
+ get_set(&be->flm.v17.timeout->t, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_timeout_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_timeout_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_timeout_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_timeout_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_scrub_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_scrub_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_scrub_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_SCRUB_I:
+ get_set(&be->flm.v17.scrub->i, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_scrub_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_scrub_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_scrub_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_scrub_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_bin_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_bin_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_bin_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_BIN:
+ get_set(&be->flm.v17.load_bin->bin, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_bin_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_bin_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_bin_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_bin_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_pps_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_pps_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_pps_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_PPS:
+ get_set(&be->flm.v17.load_pps->pps, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_pps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_pps_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_pps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_pps_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_lps_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_lps_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_lps_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_LPS:
+ get_set(&be->flm.v17.load_lps->lps, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_lps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_lps_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_lps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_lps_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_load_aps_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_load_aps_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_load_aps_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_LOAD_APS:
+ get_set(&be->flm.v17.load_aps->aps, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_load_aps_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_load_aps_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_load_aps_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_load_aps_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_prio_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_prio_flush(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_prio_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_PRIO_LIMIT0:
+ get_set(&be->flm.v17.prio->limit0, value, get);
+ break;
+ case HW_FLM_PRIO_FT0:
+ get_set(&be->flm.v17.prio->ft0, value, get);
+ break;
+ case HW_FLM_PRIO_LIMIT1:
+ get_set(&be->flm.v17.prio->limit1, value, get);
+ break;
+ case HW_FLM_PRIO_FT1:
+ get_set(&be->flm.v17.prio->ft1, value, get);
+ break;
+ case HW_FLM_PRIO_LIMIT2:
+ get_set(&be->flm.v17.prio->limit2, value, get);
+ break;
+ case HW_FLM_PRIO_FT2:
+ get_set(&be->flm.v17.prio->ft2, value, get);
+ break;
+ case HW_FLM_PRIO_LIMIT3:
+ get_set(&be->flm.v17.prio->limit3, value, get);
+ break;
+ case HW_FLM_PRIO_FT3:
+ get_set(&be->flm.v17.prio->ft3, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_prio_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t value)
+{
+ return hw_mod_flm_prio_mod(be, field, &value, 0);
+}
+
+int hw_mod_flm_prio_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_prio_mod(be, field, value, 1);
+}
+
+int hw_mod_flm_pst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->flm.nb_pst_profiles;
+ if ((unsigned int)(start_idx + count) > be->flm.nb_pst_profiles)
+ return error_index_too_large(__func__);
+ return be->iface->flm_pst_flush(be->be_dev, &be->flm, start_idx, count);
+}
+
+static int hw_mod_flm_pst_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, int index, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_PST_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->flm.v17.pst[index], (uint8_t)*value,
+ sizeof(struct flm_v17_pst_s));
+ break;
+ case HW_FLM_PST_BP:
+ get_set(&be->flm.v17.pst[index].bp, value, get);
+ break;
+ case HW_FLM_PST_PP:
+ get_set(&be->flm.v17.pst[index].pp, value, get);
+ break;
+ case HW_FLM_PST_TP:
+ get_set(&be->flm.v17.pst[index].tp, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_pst_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_flm_pst_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_flm_pst_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_flm_pst_mod(be, field, index, value, 1);
+}
+
+int hw_mod_flm_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->flm.nb_categories;
+ if ((unsigned int)(start_idx + count) > be->flm.nb_categories)
+ return error_index_too_large(__func__);
+ return be->iface->flm_rcp_flush(be->be_dev, &be->flm, start_idx, count);
+}
+
+static int hw_mod_flm_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_flm_e field, int index, uint32_t *value,
+ int get)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->flm.v17.rcp[index], (uint8_t)*value,
+ sizeof(struct flm_v17_rcp_s));
+ break;
+ case HW_FLM_RCP_LOOKUP:
+ get_set(&be->flm.v17.rcp[index].lookup, value, get);
+ break;
+ case HW_FLM_RCP_QW0_DYN:
+ get_set(&be->flm.v17.rcp[index].qw0_dyn, value, get);
+ break;
+ case HW_FLM_RCP_QW0_OFS:
+ get_set(&be->flm.v17.rcp[index].qw0_ofs, value, get);
+ break;
+ case HW_FLM_RCP_QW0_SEL:
+ get_set(&be->flm.v17.rcp[index].qw0_sel, value, get);
+ break;
+ case HW_FLM_RCP_QW4_DYN:
+ get_set(&be->flm.v17.rcp[index].qw4_dyn, value, get);
+ break;
+ case HW_FLM_RCP_QW4_OFS:
+ get_set(&be->flm.v17.rcp[index].qw4_ofs, value, get);
+ break;
+ case HW_FLM_RCP_SW8_DYN:
+ get_set(&be->flm.v17.rcp[index].sw8_dyn, value, get);
+ break;
+ case HW_FLM_RCP_SW8_OFS:
+ get_set(&be->flm.v17.rcp[index].sw8_ofs, value, get);
+ break;
+ case HW_FLM_RCP_SW8_SEL:
+ get_set(&be->flm.v17.rcp[index].sw8_sel, value, get);
+ break;
+ case HW_FLM_RCP_SW9_DYN:
+ get_set(&be->flm.v17.rcp[index].sw9_dyn, value, get);
+ break;
+ case HW_FLM_RCP_SW9_OFS:
+ get_set(&be->flm.v17.rcp[index].sw9_ofs, value, get);
+ break;
+ case HW_FLM_RCP_MASK:
+ if (get) {
+ memcpy(value, be->flm.v17.rcp[index].mask,
+ sizeof(((struct flm_v17_rcp_s *)0)
+ ->mask));
+ } else {
+ memcpy(be->flm.v17.rcp[index].mask, value,
+ sizeof(((struct flm_v17_rcp_s *)0)
+ ->mask));
+ }
+ break;
+ case HW_FLM_RCP_KID:
+ get_set(&be->flm.v17.rcp[index].kid, value, get);
+ break;
+ case HW_FLM_RCP_OPN:
+ get_set(&be->flm.v17.rcp[index].opn, value, get);
+ break;
+ case HW_FLM_RCP_IPN:
+ get_set(&be->flm.v17.rcp[index].ipn, value, get);
+ break;
+ case HW_FLM_RCP_BYT_DYN:
+ get_set(&be->flm.v17.rcp[index].byt_dyn, value, get);
+ break;
+ case HW_FLM_RCP_BYT_OFS:
+ get_set(&be->flm.v17.rcp[index].byt_ofs, value, get);
+ break;
+ case HW_FLM_RCP_TXPLM:
+ get_set(&be->flm.v17.rcp[index].txplm, value, get);
+ break;
+ case HW_FLM_RCP_AUTO_IPV4_MASK:
+ get_set(&be->flm.v17.rcp[index].auto_ipv4_mask, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_rcp_set_mask(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value)
+{
+ if (field != HW_FLM_RCP_MASK)
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ return hw_mod_flm_rcp_mod(be, field, index, value, 0);
+}
+
+int hw_mod_flm_rcp_set(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t value)
+{
+ if (field == HW_FLM_RCP_MASK)
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ return hw_mod_flm_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_flm_rcp_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_flm_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_flm_buf_ctrl_update(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_buf_ctrl_update(be->be_dev, &be->flm);
+}
+
+static int hw_mod_flm_buf_ctrl_mod_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value)
+{
+ int get = 1; /* Only get supported */
+
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_BUF_CTRL_LRN_FREE:
+ get_set(&be->flm.v17.buf_ctrl->lrn_free, value, get);
+ break;
+ case HW_FLM_BUF_CTRL_INF_AVAIL:
+ get_set(&be->flm.v17.buf_ctrl->inf_avail, value, get);
+ break;
+ case HW_FLM_BUF_CTRL_STA_AVAIL:
+ get_set(&be->flm.v17.buf_ctrl->sta_avail, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_buf_ctrl_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ return hw_mod_flm_buf_ctrl_mod_get(be, field, value);
+}
+
+int hw_mod_flm_stat_update(struct flow_api_backend_s *be)
+{
+ return be->iface->flm_stat_update(be->be_dev, &be->flm);
+}
+
+int hw_mod_flm_stat_get(struct flow_api_backend_s *be, enum hw_flm_e field,
+ uint32_t *value)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_STAT_LRN_DONE:
+ *value = be->flm.v17.lrn_done->cnt;
+ break;
+ case HW_FLM_STAT_LRN_IGNORE:
+ *value = be->flm.v17.lrn_ignore->cnt;
+ break;
+ case HW_FLM_STAT_LRN_FAIL:
+ *value = be->flm.v17.lrn_fail->cnt;
+ break;
+ case HW_FLM_STAT_UNL_DONE:
+ *value = be->flm.v17.unl_done->cnt;
+ break;
+ case HW_FLM_STAT_UNL_IGNORE:
+ *value = be->flm.v17.unl_ignore->cnt;
+ break;
+ case HW_FLM_STAT_REL_DONE:
+ *value = be->flm.v17.rel_done->cnt;
+ break;
+ case HW_FLM_STAT_REL_IGNORE:
+ *value = be->flm.v17.rel_ignore->cnt;
+ break;
+ case HW_FLM_STAT_PRB_DONE:
+ *value = be->flm.v17.prb_done->cnt;
+ break;
+ case HW_FLM_STAT_PRB_IGNORE:
+ *value = be->flm.v17.prb_ignore->cnt;
+ break;
+ case HW_FLM_STAT_AUL_DONE:
+ *value = be->flm.v17.aul_done->cnt;
+ break;
+ case HW_FLM_STAT_AUL_IGNORE:
+ *value = be->flm.v17.aul_ignore->cnt;
+ break;
+ case HW_FLM_STAT_AUL_FAIL:
+ *value = be->flm.v17.aul_fail->cnt;
+ break;
+ case HW_FLM_STAT_TUL_DONE:
+ *value = be->flm.v17.tul_done->cnt;
+ break;
+ case HW_FLM_STAT_FLOWS:
+ *value = be->flm.v17.flows->cnt;
+ break;
+
+ default: {
+ if (_VER_ < 18)
+ return error_unsup_field(__func__);
+
+ switch (field) {
+ case HW_FLM_STAT_STA_DONE:
+ *value = be->flm.v20.sta_done->cnt;
+ break;
+ case HW_FLM_STAT_INF_DONE:
+ *value = be->flm.v20.inf_done->cnt;
+ break;
+ case HW_FLM_STAT_INF_SKIP:
+ *value = be->flm.v20.inf_skip->cnt;
+ break;
+ case HW_FLM_STAT_PCK_HIT:
+ *value = be->flm.v20.pck_hit->cnt;
+ break;
+ case HW_FLM_STAT_PCK_MISS:
+ *value = be->flm.v20.pck_miss->cnt;
+ break;
+ case HW_FLM_STAT_PCK_UNH:
+ *value = be->flm.v20.pck_unh->cnt;
+ break;
+ case HW_FLM_STAT_PCK_DIS:
+ *value = be->flm.v20.pck_dis->cnt;
+ break;
+ case HW_FLM_STAT_CSH_HIT:
+ *value = be->flm.v20.csh_hit->cnt;
+ break;
+ case HW_FLM_STAT_CSH_MISS:
+ *value = be->flm.v20.csh_miss->cnt;
+ break;
+ case HW_FLM_STAT_CSH_UNH:
+ *value = be->flm.v20.csh_unh->cnt;
+ break;
+ case HW_FLM_STAT_CUC_START:
+ *value = be->flm.v20.cuc_start->cnt;
+ break;
+ case HW_FLM_STAT_CUC_MOVE:
+ *value = be->flm.v20.cuc_move->cnt;
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ }
+ break;
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_lrn_data_set_flush(struct flow_api_backend_s *be,
+ enum hw_flm_e field, const uint32_t *value)
+{
+ int ret = 0;
+
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_FLOW_LRN_DATA_V17:
+ ret = be->iface->flm_lrn_data_flush(be->be_dev,
+ &be->flm, value,
+ sizeof(struct flm_v17_lrn_data_s) /
+ sizeof(uint32_t));
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return ret;
+}
+
+int hw_mod_flm_inf_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value,
+ uint32_t word_cnt)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_FLOW_INF_DATA_V17:
+ be->iface->flm_inf_data_update(be->be_dev, &be->flm,
+ value, word_cnt);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_flm_sta_data_update_get(struct flow_api_backend_s *be,
+ enum hw_flm_e field, uint32_t *value)
+{
+ switch (_VER_) {
+ case 17:
+ case 20:
+ switch (field) {
+ case HW_FLM_FLOW_STA_DATA_V17:
+ be->iface->flm_sta_data_update(be->be_dev,
+ &be->flm, value,
+ sizeof(struct flm_v17_sta_data_s) /
+ sizeof(uint32_t));
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h
new file mode 100644
index 0000000000..311e39ba36
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v17.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_FLM_V17_H_
+#define _HW_MOD_FLM_V17_H_
+
+struct flm_v17_mbr_idx_overlay {
+ uint64_t a : 28;
+ uint64_t b : 28;
+ uint64_t pad : 4;
+};
+
+#define FLM_V17_MBR_ID1(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)(mbr_id_ptr))->a)
+#define FLM_V17_MBR_ID2(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)(mbr_id_ptr))->b)
+#define FLM_V17_MBR_ID3(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)((mbr_id_ptr) + 7))->a)
+#define FLM_V17_MBR_ID4(mbr_id_ptr) \
+ (((struct flm_v17_mbr_idx_overlay *)((mbr_id_ptr) + 7))->b)
+
+struct flm_v17_control_s {
+ uint32_t enable;
+ uint32_t init;
+ uint32_t lds;
+ uint32_t lfs;
+ uint32_t lis;
+ uint32_t uds;
+ uint32_t uis;
+ uint32_t rds;
+ uint32_t ris;
+ uint32_t pds;
+ uint32_t pis;
+ uint32_t crcwr;
+ uint32_t crcrd;
+ uint32_t rbl;
+ uint32_t eab;
+ uint32_t split_sdram_usage;
+};
+
+struct flm_v17_status_s {
+ uint32_t calibdone;
+ uint32_t initdone;
+ uint32_t idle;
+ uint32_t critical;
+ uint32_t panic;
+ uint32_t crcerr;
+ uint32_t eft_bp;
+};
+
+struct flm_v17_timeout_s {
+ uint32_t t;
+};
+
+struct flm_v17_scrub_s {
+ uint32_t i;
+};
+
+struct flm_v17_load_bin_s {
+ uint32_t bin;
+};
+
+struct flm_v17_load_pps_s {
+ uint32_t pps;
+};
+
+struct flm_v17_load_lps_s {
+ uint32_t lps;
+};
+
+struct flm_v17_load_aps_s {
+ uint32_t aps;
+};
+
+struct flm_v17_prio_s {
+ uint32_t limit0;
+ uint32_t ft0;
+ uint32_t limit1;
+ uint32_t ft1;
+ uint32_t limit2;
+ uint32_t ft2;
+ uint32_t limit3;
+ uint32_t ft3;
+};
+
+struct flm_v17_pst_s {
+ uint32_t bp;
+ uint32_t pp;
+ uint32_t tp;
+};
+
+struct flm_v17_rcp_s {
+ uint32_t lookup;
+ uint32_t qw0_dyn;
+ uint32_t qw0_ofs;
+ uint32_t qw0_sel;
+ uint32_t qw4_dyn;
+ uint32_t qw4_ofs;
+ uint32_t sw8_dyn;
+ uint32_t sw8_ofs;
+ uint32_t sw8_sel;
+ uint32_t sw9_dyn;
+ uint32_t sw9_ofs;
+ uint32_t mask[10];
+ uint32_t kid;
+ uint32_t opn;
+ uint32_t ipn;
+ uint32_t byt_dyn;
+ uint32_t byt_ofs;
+ uint32_t txplm;
+ uint32_t auto_ipv4_mask;
+};
+
+struct flm_v17_buf_ctrl_s {
+ uint32_t lrn_free;
+ uint32_t inf_avail;
+ uint32_t sta_avail;
+};
+
+#pragma pack(1)
+struct flm_v17_lrn_data_s {
+ uint32_t sw9; /* 31:0 (32) */
+ uint32_t sw8; /* 63:32 (32) */
+ uint32_t qw4[4]; /* 191:64 (128) */
+ uint32_t qw0[4]; /* 319:192 (128) */
+ uint8_t prot; /* 327:320 (8) */
+ uint8_t kid; /* 335:328 (8) */
+ uint32_t nat_ip; /* 367:336 (32) */
+ uint32_t teid; /* 399:368 (32) */
+ uint16_t nat_port; /* 415:400 (16) */
+ uint16_t rate; /* 431:416 (16) */
+ uint16_t size; /* 447:432 (16) */
+ uint32_t color; /* 479:448 (32) */
+ uint32_t adj; /* 511:480 (32) */
+ uint8_t id[9]; /* 583:512 (72) */
+ uint16_t fill : 12; /* 595:584 (12) */
+ uint16_t ft : 4; /* 599:596 (4) */
+ uint8_t ft_mbr : 4; /* 603:600 (4) */
+ uint8_t ft_miss : 4; /* 607:604 (5) */
+
+ /* 635:608, 663:636, 691:664, 719:692 (4 x 28) Get/set with macros FLM_V17_MBR_IDx */
+ uint8_t mbr_idx[14];
+ uint32_t vol_idx : 3; /* 722:720 (3) */
+ uint32_t stat_prof : 4; /* 726:723 (4) */
+ uint32_t prio : 2; /* 728:727 (2) */
+ uint32_t ent : 1; /* 729:729 (1) */
+ uint32_t op : 4; /* 733:730 (4) */
+ uint32_t dscp : 6; /* 739:734 (6) */
+ uint32_t qfi : 6; /* 745:740 (6) */
+ uint32_t rqi : 1; /* 746:746 (1) */
+ uint32_t nat_en : 1; /* 747:747 (1) */
+ uint32_t pad0 : 4; /* 751:748 (4) */
+ uint16_t pad1 : 15; /* 752:766 (15) */
+ uint16_t eor : 1; /* 767:767 (1) */
+};
+
+struct flm_v17_inf_data_s {
+ uint64_t bytes;
+ uint64_t packets;
+ uint64_t ts;
+ uint64_t id0; /* id0 and id1 results in a 72-bit int */
+ uint32_t id1 : 8;
+ uint32_t cause : 3;
+ uint32_t pad : 20;
+ uint32_t eor : 1;
+};
+
+struct flm_v17_sta_data_s {
+ uint64_t id0; /* id0 and id1 results in a 72-bit int */
+ uint32_t id1 : 8;
+ uint32_t lds : 1;
+ uint32_t lfs : 1;
+ uint32_t lis : 1;
+ uint32_t uds : 1;
+ uint32_t uis : 1;
+ uint32_t rds : 1;
+ uint32_t ris : 1;
+ uint32_t pds : 1;
+ uint32_t pis : 1;
+ uint32_t pad : 14;
+ uint32_t eor : 1;
+};
+
+#pragma pack()
+struct flm_v17_stat_lrn_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_lrn_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_lrn_fail_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_unl_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_unl_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_rel_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_rel_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_aul_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_aul_ignore_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_aul_fail_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_tul_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_flows_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_prb_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v17_stat_prb_ignore_s {
+ uint32_t cnt;
+};
+
+struct hw_mod_flm_v17_s {
+ struct flm_v17_control_s *control;
+ struct flm_v17_status_s *status;
+ struct flm_v17_timeout_s *timeout;
+ struct flm_v17_scrub_s *scrub;
+ struct flm_v17_load_bin_s *load_bin;
+ struct flm_v17_load_pps_s *load_pps;
+ struct flm_v17_load_lps_s *load_lps;
+ struct flm_v17_load_aps_s *load_aps;
+ struct flm_v17_prio_s *prio;
+ struct flm_v17_pst_s *pst;
+ struct flm_v17_rcp_s *rcp;
+ struct flm_v17_buf_ctrl_s *buf_ctrl;
+ /* lrn_data is not handled by struct */
+ /* inf_data is not handled by struct */
+ /* sta_data is not handled by struct */
+ struct flm_v17_stat_lrn_done_s *lrn_done;
+ struct flm_v17_stat_lrn_ignore_s *lrn_ignore;
+ struct flm_v17_stat_lrn_fail_s *lrn_fail;
+ struct flm_v17_stat_unl_done_s *unl_done;
+ struct flm_v17_stat_unl_ignore_s *unl_ignore;
+ struct flm_v17_stat_rel_done_s *rel_done;
+ struct flm_v17_stat_rel_ignore_s *rel_ignore;
+ struct flm_v17_stat_aul_done_s *aul_done;
+ struct flm_v17_stat_aul_ignore_s *aul_ignore;
+ struct flm_v17_stat_aul_fail_s *aul_fail;
+ struct flm_v17_stat_tul_done_s *tul_done;
+ struct flm_v17_stat_flows_s *flows;
+ struct flm_v17_stat_prb_done_s *prb_done;
+ struct flm_v17_stat_prb_ignore_s *prb_ignore;
+};
+
+#endif /* _HW_MOD_FLM_V17_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h
new file mode 100644
index 0000000000..e33d4353c3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_flm_v20.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_FLM_V20_H_
+#define _HW_MOD_FLM_V20_H_
+
+struct flm_v20_stat_sta_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_inf_done_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_inf_skip_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_hit_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_miss_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_unh_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_pck_dis_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_csh_hit_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_csh_miss_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_csh_unh_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_cuc_start_s {
+ uint32_t cnt;
+};
+
+struct flm_v20_stat_cuc_move_s {
+ uint32_t cnt;
+};
+
+struct hw_mod_flm_v20_s {
+ struct flm_v17_control_s *control;
+ struct flm_v17_status_s *status;
+ struct flm_v17_timeout_s *timeout;
+ struct flm_v17_scrub_s *scrub;
+ struct flm_v17_load_bin_s *load_bin;
+ struct flm_v17_load_pps_s *load_pps;
+ struct flm_v17_load_lps_s *load_lps;
+ struct flm_v17_load_aps_s *load_aps;
+ struct flm_v17_prio_s *prio;
+ struct flm_v17_pst_s *pst;
+ struct flm_v17_rcp_s *rcp;
+ struct flm_v17_buf_ctrl_s *buf_ctrl;
+ /*
+ * lrn_data is not handled by struct
+ * inf_data is not handled by struct
+ * sta_data is not handled by struct
+ */
+ struct flm_v17_stat_lrn_done_s *lrn_done;
+ struct flm_v17_stat_lrn_ignore_s *lrn_ignore;
+ struct flm_v17_stat_lrn_fail_s *lrn_fail;
+ struct flm_v17_stat_unl_done_s *unl_done;
+ struct flm_v17_stat_unl_ignore_s *unl_ignore;
+ struct flm_v17_stat_rel_done_s *rel_done;
+ struct flm_v17_stat_rel_ignore_s *rel_ignore;
+ struct flm_v17_stat_aul_done_s *aul_done;
+ struct flm_v17_stat_aul_ignore_s *aul_ignore;
+ struct flm_v17_stat_aul_fail_s *aul_fail;
+ struct flm_v17_stat_tul_done_s *tul_done;
+ struct flm_v17_stat_flows_s *flows;
+ struct flm_v17_stat_prb_done_s *prb_done;
+ struct flm_v17_stat_prb_ignore_s *prb_ignore;
+ struct flm_v20_stat_sta_done_s *sta_done;
+ struct flm_v20_stat_inf_done_s *inf_done;
+ struct flm_v20_stat_inf_skip_s *inf_skip;
+ struct flm_v20_stat_pck_hit_s *pck_hit;
+ struct flm_v20_stat_pck_miss_s *pck_miss;
+ struct flm_v20_stat_pck_unh_s *pck_unh;
+ struct flm_v20_stat_pck_dis_s *pck_dis;
+ struct flm_v20_stat_csh_hit_s *csh_hit;
+ struct flm_v20_stat_csh_miss_s *csh_miss;
+ struct flm_v20_stat_csh_unh_s *csh_unh;
+ struct flm_v20_stat_cuc_start_s *cuc_start;
+ struct flm_v20_stat_cuc_move_s *cuc_move;
+};
+
+#endif /* _HW_MOD_FLM_V20_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c
new file mode 100644
index 0000000000..1b8896d5c2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh.c
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "HSH"
+#define _VER_ be->hsh.ver
+
+#define HSH_RCP_ENTRIES_V4 16
+#define HSH_RCP_ENTRIES_V5 32
+#define HSH_RCP_MAC_PORT_MASK_SIZE 4
+#define HSH_RCP_WORD_MASK_SIZE 10
+
+bool hw_mod_hsh_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_hsh_present(be->be_dev);
+}
+
+int hw_mod_hsh_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_hsh_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "HSH MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 5:
+ be->hsh.nb_rcp = HSH_RCP_ENTRIES_V5;
+ if (!callocate_mod(CAST_COMMON(&be->hsh), 1,
+ &be->hsh.v5.rcp,
+ be->hsh.nb_rcp,
+ sizeof(struct hsh_v5_rcp_s)))
+ return -1;
+ break;
+ /* end case 5 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_hsh_free(struct flow_api_backend_s *be)
+{
+ if (be->hsh.base) {
+ free(be->hsh.base);
+ be->hsh.base = NULL;
+ }
+}
+
+int hw_mod_hsh_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->hsh);
+
+ NT_LOG(DBG, FILTER, "INIT HSH RCP\n");
+ return hw_mod_hsh_rcp_flush(be, 0, be->hsh.nb_rcp);
+}
+
+int hw_mod_hsh_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->hsh.nb_rcp;
+ if ((start_idx + count) > (int)be->hsh.nb_rcp)
+ return error_index_too_large(__func__);
+ return be->iface->hsh_rcp_flush(be->be_dev, &be->hsh, start_idx, count);
+}
+
+static int hw_mod_hsh_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_hsh_e field, uint32_t index,
+ uint32_t word_off, uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->hsh.nb_rcp)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 5:
+ switch (field) {
+ case HW_HSH_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->hsh.v5.rcp[index], (uint8_t)*value,
+ sizeof(struct hsh_v5_rcp_s));
+ break;
+ case HW_HSH_RCP_COMPARE:
+ rv = do_compare_indexes(be->hsh.v5.rcp,
+ sizeof(struct hsh_v5_rcp_s), index, word_off,
+ be->hsh.nb_rcp, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HSH_RCP_FIND:
+ rv = find_equal_index(be->hsh.v5.rcp,
+ sizeof(struct hsh_v5_rcp_s), index, word_off,
+ be->hsh.nb_rcp, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HSH_RCP_LOAD_DIST_TYPE:
+ get_set(&be->hsh.v5.rcp[index].load_dist_type, value, get);
+ break;
+ case HW_HSH_RCP_MAC_PORT_MASK:
+ if (word_off > HSH_RCP_MAC_PORT_MASK_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->hsh.v5.rcp[index].mac_port_mask[word_off],
+ value, get);
+ break;
+ case HW_HSH_RCP_SORT:
+ get_set(&be->hsh.v5.rcp[index].sort, value, get);
+ break;
+ case HW_HSH_RCP_QW0_PE:
+ get_set(&be->hsh.v5.rcp[index].qw0_pe, value, get);
+ break;
+ case HW_HSH_RCP_QW0_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].qw0_ofs, value, get);
+ break;
+ case HW_HSH_RCP_QW4_PE:
+ get_set(&be->hsh.v5.rcp[index].qw4_pe, value, get);
+ break;
+ case HW_HSH_RCP_QW4_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].qw4_ofs, value, get);
+ break;
+ case HW_HSH_RCP_W8_PE:
+ get_set(&be->hsh.v5.rcp[index].w8_pe, value, get);
+ break;
+ case HW_HSH_RCP_W8_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].w8_ofs, value, get);
+ break;
+ case HW_HSH_RCP_W8_SORT:
+ get_set(&be->hsh.v5.rcp[index].w8_sort, value, get);
+ break;
+ case HW_HSH_RCP_W9_PE:
+ get_set(&be->hsh.v5.rcp[index].w9_pe, value, get);
+ break;
+ case HW_HSH_RCP_W9_OFS:
+ get_set_signed(&be->hsh.v5.rcp[index].w9_ofs, value, get);
+ break;
+ case HW_HSH_RCP_W9_SORT:
+ get_set(&be->hsh.v5.rcp[index].w9_sort, value, get);
+ break;
+ case HW_HSH_RCP_W9_P:
+ get_set(&be->hsh.v5.rcp[index].w9_p, value, get);
+ break;
+ case HW_HSH_RCP_P_MASK:
+ get_set(&be->hsh.v5.rcp[index].p_mask, value, get);
+ break;
+ case HW_HSH_RCP_WORD_MASK:
+ if (word_off > HSH_RCP_WORD_MASK_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->hsh.v5.rcp[index].word_mask[word_off],
+ value, get);
+ break;
+ case HW_HSH_RCP_SEED:
+ get_set(&be->hsh.v5.rcp[index].seed, value, get);
+ break;
+ case HW_HSH_RCP_TNL_P:
+ get_set(&be->hsh.v5.rcp[index].tnl_p, value, get);
+ break;
+ case HW_HSH_RCP_HSH_VALID:
+ get_set(&be->hsh.v5.rcp[index].hsh_valid, value, get);
+ break;
+ case HW_HSH_RCP_HSH_TYPE:
+ get_set(&be->hsh.v5.rcp[index].hsh_type, value, get);
+ break;
+ case HW_HSH_RCP_AUTO_IPV4_MASK:
+ get_set(&be->hsh.v5.rcp[index].auto_ipv4_mask, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 5 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_hsh_rcp_set(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t value)
+{
+ return hw_mod_hsh_rcp_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_hsh_rcp_get(struct flow_api_backend_s *be, enum hw_hsh_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value)
+{
+ return hw_mod_hsh_rcp_mod(be, field, index, word_off, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h
new file mode 100644
index 0000000000..8588750ff0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hsh_v5.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_HSH_V5_H_
+#define _HW_MOD_HSH_V5_H_
+
+struct hsh_v5_rcp_s {
+ uint32_t load_dist_type;
+ uint32_t mac_port_mask[4];
+ uint32_t sort;
+ uint32_t qw0_pe;
+ int32_t qw0_ofs;
+ uint32_t qw4_pe;
+ int32_t qw4_ofs;
+ uint32_t w8_pe;
+ int32_t w8_ofs;
+ uint32_t w8_sort;
+ uint32_t w9_pe;
+ int32_t w9_ofs;
+ uint32_t w9_sort;
+ uint32_t w9_p;
+ uint32_t p_mask;
+ uint32_t word_mask[10];
+ uint32_t seed;
+ uint32_t tnl_p;
+ uint32_t hsh_valid;
+ uint32_t hsh_type;
+ uint32_t auto_ipv4_mask;
+};
+
+struct hw_mod_hsh_v5_s {
+ struct hsh_v5_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_HSH_V5_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c
new file mode 100644
index 0000000000..751c7b3ffe
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst.c
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "HST"
+#define _VER_ be->hst.ver
+
+bool hw_mod_hst_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_hst_present(be->be_dev);
+}
+
+int hw_mod_hst_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_hst_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "HST MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_hst_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "hst_categories", _MOD_, _VER_);
+ be->hst.nb_hst_rcp_categories = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 2:
+ if (!callocate_mod(CAST_COMMON(&be->hst), 1,
+ &be->hst.v2.rcp,
+ be->hst.nb_hst_rcp_categories,
+ sizeof(struct hst_v2_rcp_s)))
+ return -1;
+ break;
+ /* end case 2 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_hst_free(struct flow_api_backend_s *be)
+{
+ if (be->hst.base) {
+ free(be->hst.base);
+ be->hst.base = NULL;
+ }
+}
+
+int hw_mod_hst_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->hst);
+
+ NT_LOG(DBG, FILTER, "INIT HST RCP\n");
+ return hw_mod_hst_rcp_flush(be, 0, ALL_ENTRIES);
+}
+
+int hw_mod_hst_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->hst.nb_hst_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->hst.nb_hst_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->hst_rcp_flush(be->be_dev, &be->hst, start_idx, count);
+}
+
+static int hw_mod_hst_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_hst_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->hst.nb_hst_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_HST_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->hst.v2.rcp[index], (uint8_t)*value,
+ sizeof(struct hst_v2_rcp_s));
+ break;
+ case HW_HST_RCP_FIND:
+ find_equal_index(be->hst.v2.rcp,
+ sizeof(struct hst_v2_rcp_s), index, *value,
+ be->hst.nb_hst_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HST_RCP_COMPARE:
+ rv = do_compare_indexes(be->hst.v2.rcp,
+ sizeof(struct hst_v2_rcp_s), index, *value,
+ be->hst.nb_hst_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_HST_RCP_STRIP_MODE:
+ get_set(&be->hst.v2.rcp[index].strip_mode, value, get);
+ break;
+ case HW_HST_RCP_START_DYN:
+ get_set(&be->hst.v2.rcp[index].start_dyn, value, get);
+ break;
+ case HW_HST_RCP_START_OFS:
+ get_set(&be->hst.v2.rcp[index].start_ofs, value, get);
+ break;
+ case HW_HST_RCP_END_DYN:
+ get_set(&be->hst.v2.rcp[index].end_dyn, value, get);
+ break;
+ case HW_HST_RCP_END_OFS:
+ get_set(&be->hst.v2.rcp[index].end_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_CMD:
+ get_set(&be->hst.v2.rcp[index].modif0_cmd, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_DYN:
+ get_set(&be->hst.v2.rcp[index].modif0_dyn, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_OFS:
+ get_set(&be->hst.v2.rcp[index].modif0_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF0_VALUE:
+ get_set(&be->hst.v2.rcp[index].modif0_value, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_CMD:
+ get_set(&be->hst.v2.rcp[index].modif1_cmd, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_DYN:
+ get_set(&be->hst.v2.rcp[index].modif1_dyn, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_OFS:
+ get_set(&be->hst.v2.rcp[index].modif1_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF1_VALUE:
+ get_set(&be->hst.v2.rcp[index].modif1_value, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_CMD:
+ get_set(&be->hst.v2.rcp[index].modif2_cmd, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_DYN:
+ get_set(&be->hst.v2.rcp[index].modif2_dyn, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_OFS:
+ get_set(&be->hst.v2.rcp[index].modif2_ofs, value, get);
+ break;
+ case HW_HST_RCP_MODIF2_VALUE:
+ get_set(&be->hst.v2.rcp[index].modif2_value, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 2 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_hst_rcp_set(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_hst_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_hst_rcp_get(struct flow_api_backend_s *be, enum hw_hst_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_hst_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h
new file mode 100644
index 0000000000..230c70b56d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_hst_v2.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_HST_V2_H_
+#define _HW_MOD_HST_V2_H_
+
+struct hst_v2_rcp_s {
+ uint32_t strip_mode;
+ uint32_t start_dyn;
+ uint32_t start_ofs;
+ uint32_t end_dyn;
+ uint32_t end_ofs;
+ uint32_t modif0_cmd;
+ uint32_t modif0_dyn;
+ uint32_t modif0_ofs;
+ uint32_t modif0_value;
+ uint32_t modif1_cmd;
+ uint32_t modif1_dyn;
+ uint32_t modif1_ofs;
+ uint32_t modif1_value;
+ uint32_t modif2_cmd;
+ uint32_t modif2_dyn;
+ uint32_t modif2_ofs;
+ uint32_t modif2_value;
+};
+
+struct hw_mod_hst_v2_s {
+ struct hst_v2_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_HST_V2_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c
new file mode 100644
index 0000000000..c8e3593637
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa.c
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "IOA"
+#define _VER_ be->ioa.ver
+
+bool hw_mod_ioa_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_ioa_present(be->be_dev);
+}
+
+int hw_mod_ioa_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_ioa_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "IOA MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ int nb = be->iface->get_nb_ioa_categories(be->be_dev);
+
+ if (nb <= 0)
+ return error_resource_count(__func__, "ioa_categories", _MOD_, _VER_);
+ be->ioa.nb_rcp_categories = (uint32_t)nb;
+
+ /* NOTE: ROA number of categories are called here. FPGA uses a cross-indexing here - bad! */
+ nb = be->iface->get_nb_roa_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "roa_epp_entries", _MOD_, _VER_);
+ be->ioa.nb_roa_epp_entries = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 4:
+ if (!callocate_mod(CAST_COMMON(&be->ioa), 3,
+ &be->ioa.v4.rcp, be->ioa.nb_rcp_categories,
+ sizeof(struct ioa_v4_rcp_s),
+ &be->ioa.v4.tpid, 1,
+ sizeof(struct ioa_v4_special_tpid_s),
+ &be->ioa.v4.roa_epp, be->ioa.nb_roa_epp_entries,
+ sizeof(struct ioa_v4_roa_epp_s)))
+ return -1;
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_ioa_free(struct flow_api_backend_s *be)
+{
+ if (be->ioa.base) {
+ free(be->ioa.base);
+ be->ioa.base = NULL;
+ }
+}
+
+int hw_mod_ioa_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->ioa);
+
+ NT_LOG(DBG, FILTER, "INIT IOA RCP\n");
+ hw_mod_ioa_rcp_flush(be, 0, ALL_ENTRIES);
+ NT_LOG(DBG, FILTER, "INIT IOA SPECIAL TPID\n");
+ hw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_0, 0x8200);
+ hw_mod_ioa_config_set(be, HW_IOA_CONFIG_CUST_TPID_1, 0x8300);
+ hw_mod_ioa_config_flush(be);
+ NT_LOG(DBG, FILTER, "INIT IOA ROA EPP\n");
+ hw_mod_ioa_roa_epp_flush(be, 0, ALL_ENTRIES);
+ return 0;
+}
+
+int hw_mod_ioa_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->ioa.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->ioa.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->ioa_rcp_flush(be->be_dev, &be->ioa, start_idx, count);
+}
+
+static int hw_mod_ioa_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_ioa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->ioa.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 4:
+ switch (field) {
+ case HW_IOA_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->ioa.v4.rcp[index], (uint8_t)*value,
+ sizeof(struct ioa_v4_rcp_s));
+ break;
+ case HW_IOA_RCP_FIND:
+ rv = find_equal_index(be->ioa.v4.rcp,
+ sizeof(struct ioa_v4_rcp_s), index, *value,
+ be->ioa.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_RCP_COMPARE:
+ rv = do_compare_indexes(be->ioa.v4.rcp,
+ sizeof(struct ioa_v4_rcp_s), index, *value,
+ be->ioa.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_RCP_TUNNEL_POP:
+ get_set(&be->ioa.v4.rcp[index].tunnel_pop, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_POP:
+ get_set(&be->ioa.v4.rcp[index].vlan_pop, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_PUSH:
+ get_set(&be->ioa.v4.rcp[index].vlan_push, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_VID:
+ get_set(&be->ioa.v4.rcp[index].vlan_vid, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_DEI:
+ get_set(&be->ioa.v4.rcp[index].vlan_dei, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_PCP:
+ get_set(&be->ioa.v4.rcp[index].vlan_pcp, value, get);
+ break;
+ case HW_IOA_RCP_VLAN_TPID_SEL:
+ get_set(&be->ioa.v4.rcp[index].vlan_tpid_sel, value, get);
+ break;
+ case HW_IOA_RCP_QUEUE_OVERRIDE_EN:
+ get_set(&be->ioa.v4.rcp[index].queue_override_en, value, get);
+ break;
+ case HW_IOA_RCP_QUEUE_ID:
+ get_set(&be->ioa.v4.rcp[index].queue_id, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_ioa_rcp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_ioa_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_ioa_rcp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_ioa_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_ioa_config_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->ioa_special_tpid_flush(be->be_dev, &be->ioa);
+}
+
+int hw_mod_ioa_config_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t value)
+{
+ switch (_VER_) {
+ case 4:
+ switch (field) {
+ case HW_IOA_CONFIG_CUST_TPID_0:
+ be->ioa.v4.tpid->cust_tpid_0 = value;
+ break;
+ case HW_IOA_CONFIG_CUST_TPID_1:
+ be->ioa.v4.tpid->cust_tpid_1 = value;
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_ioa_roa_epp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->ioa.nb_roa_epp_entries;
+ if ((unsigned int)(start_idx + count) > be->ioa.nb_roa_epp_entries)
+ return error_index_too_large(__func__);
+ return be->iface->ioa_roa_epp_flush(be->be_dev, &be->ioa, start_idx,
+ count);
+}
+
+static int hw_mod_ioa_roa_epp_mod(struct flow_api_backend_s *be,
+ enum hw_ioa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->ioa.nb_roa_epp_entries)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 4:
+ switch (field) {
+ case HW_IOA_ROA_EPP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->ioa.v4.roa_epp[index], (uint8_t)*value,
+ sizeof(struct ioa_v4_roa_epp_s));
+ break;
+ case HW_IOA_ROA_EPP_FIND:
+ rv = find_equal_index(be->ioa.v4.roa_epp,
+ sizeof(struct ioa_v4_roa_epp_s), index, *value,
+ be->ioa.nb_roa_epp_entries, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_ROA_EPP_COMPARE:
+ rv = do_compare_indexes(be->ioa.v4.roa_epp,
+ sizeof(struct ioa_v4_roa_epp_s), index, *value,
+ be->ioa.nb_roa_epp_entries, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_IOA_ROA_EPP_PUSH_TUNNEL:
+ get_set(&be->ioa.v4.roa_epp[index].push_tunnel, value, get);
+ break;
+ case HW_IOA_ROA_EPP_TX_PORT:
+ get_set(&be->ioa.v4.roa_epp[index].tx_port, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 4 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_ioa_roa_epp_set(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_ioa_roa_epp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_ioa_roa_epp_get(struct flow_api_backend_s *be, enum hw_ioa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_ioa_roa_epp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h
new file mode 100644
index 0000000000..309b53ff76
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_ioa_v4.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_IOA_V4_H_
+#define _HW_MOD_IOA_V4_H_
+
+struct ioa_v4_rcp_s {
+ uint32_t tunnel_pop;
+ uint32_t vlan_pop;
+ uint32_t vlan_push;
+ uint32_t vlan_vid;
+ uint32_t vlan_dei;
+ uint32_t vlan_pcp;
+ uint32_t vlan_tpid_sel;
+ uint32_t queue_override_en;
+ uint32_t queue_id;
+};
+
+struct ioa_v4_special_tpid_s {
+ uint32_t cust_tpid_0;
+ uint32_t cust_tpid_1;
+};
+
+struct ioa_v4_roa_epp_s {
+ uint32_t push_tunnel;
+ uint32_t tx_port;
+};
+
+struct hw_mod_ioa_v4_s {
+ struct ioa_v4_rcp_s *rcp;
+ struct ioa_v4_special_tpid_s *tpid;
+ struct ioa_v4_roa_epp_s *roa_epp;
+};
+
+#endif /* _HW_MOD_IOA_V4_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c
new file mode 100644
index 0000000000..a91f0e0a7d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km.c
@@ -0,0 +1,629 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "KM"
+#define _VER_ be->km.ver
+
+#define KM_TCQ_ENTRIES 2048
+#define KM_RCP_MASK_A_SIZE 11
+#define KM_RCP_MASK_D_A_SIZE \
+ 12 /* Mask for double size word extractors for DW8/DW10 */
+#define KM_RCP_MASK_B_SIZE 6
+
+bool hw_mod_km_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_km_present(be->be_dev);
+}
+
+int hw_mod_km_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_km_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "KM MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_km_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "km_categories", _MOD_, _VER_);
+ be->km.nb_categories = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_cam_banks(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "cam_banks", _MOD_, _VER_);
+ be->km.nb_cam_banks = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_cam_records(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "cam_records", _MOD_, _VER_);
+ be->km.nb_cam_records = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_cam_record_words(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "cam_record_words", _MOD_, _VER_);
+ be->km.nb_cam_record_words = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_tcam_banks(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tcam_banks", _MOD_, _VER_);
+ be->km.nb_tcam_banks = (uint32_t)nb;
+
+ nb = be->iface->get_nb_km_tcam_bank_width(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tcam_bank_width", _MOD_, _VER_);
+ be->km.nb_tcam_bank_width = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 7:
+ be->km.nb_km_rcp_mask_a_word_size = 12;
+ be->km.nb_km_rcp_mask_b_word_size = 6;
+ if (!callocate_mod(CAST_COMMON(&be->km), 5,
+ &be->km.v7.rcp,
+ be->km.nb_categories,
+ sizeof(struct km_v7_rcp_s),
+ &be->km.v7.cam,
+ be->km.nb_cam_banks * be->km.nb_cam_records,
+ sizeof(struct km_v7_cam_s),
+ &be->km.v7.tcam,
+ be->km.nb_tcam_banks * 4 * 256,
+ sizeof(struct km_v7_tcam_s),
+ &be->km.v7.tci,
+ be->km.nb_tcam_banks * be->km.nb_tcam_bank_width,
+ sizeof(struct km_v7_tci_s),
+ &be->km.v7.tcq,
+ KM_TCQ_ENTRIES,
+ sizeof(struct km_v7_tcq_s)))
+ return -1;
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_km_free(struct flow_api_backend_s *be)
+{
+ if (be->km.base) {
+ free(be->km.base);
+ be->km.base = NULL;
+ }
+}
+
+int hw_mod_km_reset(struct flow_api_backend_s *be)
+{
+ uint32_t tcam_v_set[3] = { 0x00000000, 0x00000000, 0x00000000 };
+ /* int err = 0; */
+
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->km);
+
+ NT_LOG(DBG, FILTER, "INIT KM RCP\n");
+ hw_mod_km_rcp_flush(be, 0, ALL_ENTRIES);
+
+ /* init CAM - all zero */
+ NT_LOG(DBG, FILTER, "INIT KM CAM\n");
+ hw_mod_km_cam_flush(be, 0, 0, ALL_ENTRIES);
+
+ /* init TCAM - all zero */
+ NT_LOG(DBG, FILTER, "INIT KM TCAM\n");
+ for (unsigned int i = 0; i < be->km.nb_tcam_banks; i++) {
+ /*
+ * TCAM entries are cache controlled, thus need to hard reset initially to sync
+ * cache with HW
+ */
+ hw_mod_km_tcam_set(be, HW_KM_TCAM_BANK_RESET, i, 0, 0,
+ tcam_v_set);
+ }
+ hw_mod_km_tcam_flush(be, 0, ALL_ENTRIES);
+
+ /* init TCI - all zero */
+ NT_LOG(DBG, FILTER, "INIT KM TCI\n");
+ hw_mod_km_tci_flush(be, 0, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT KM TCQ\n");
+ for (unsigned int i = 0; i < be->km.nb_tcam_bank_width; i++)
+ hw_mod_km_tcq_flush(be, 0, i, be->km.nb_tcam_banks);
+
+ return 0;
+}
+
+int hw_mod_km_rcp_flush(struct flow_api_backend_s *be, int start_idx, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_categories;
+ if ((unsigned int)(start_idx + count) > be->km.nb_categories)
+ return error_index_too_large(__func__);
+ return be->iface->km_rcp_flush(be->be_dev, &be->km, start_idx, count);
+}
+
+static int hw_mod_km_rcp_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t *value, int get)
+{
+ if ((unsigned int)index >= be->km.nb_categories)
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->km.v7.rcp[index], (uint8_t)*value,
+ sizeof(struct km_v7_rcp_s));
+ break;
+ case HW_KM_RCP_QW0_DYN:
+ get_set(&be->km.v7.rcp[index].qw0_dyn, value, get);
+ break;
+ case HW_KM_RCP_QW0_OFS:
+ get_set_signed(&be->km.v7.rcp[index].qw0_ofs, value, get);
+ break;
+ case HW_KM_RCP_QW0_SEL_A:
+ get_set(&be->km.v7.rcp[index].qw0_sel_a, value, get);
+ break;
+ case HW_KM_RCP_QW0_SEL_B:
+ get_set(&be->km.v7.rcp[index].qw0_sel_b, value, get);
+ break;
+ case HW_KM_RCP_QW4_DYN:
+ get_set(&be->km.v7.rcp[index].qw4_dyn, value, get);
+ break;
+ case HW_KM_RCP_QW4_OFS:
+ get_set_signed(&be->km.v7.rcp[index].qw4_ofs, value, get);
+ break;
+ case HW_KM_RCP_QW4_SEL_A:
+ get_set(&be->km.v7.rcp[index].qw4_sel_a, value, get);
+ break;
+ case HW_KM_RCP_QW4_SEL_B:
+ get_set(&be->km.v7.rcp[index].qw4_sel_b, value, get);
+ break;
+ case HW_KM_RCP_DW8_DYN:
+ get_set(&be->km.v7.rcp[index].dw8_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW8_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw8_ofs, value, get);
+ break;
+ case HW_KM_RCP_DW8_SEL_A:
+ get_set(&be->km.v7.rcp[index].dw8_sel_a, value, get);
+ break;
+ case HW_KM_RCP_DW8_SEL_B:
+ get_set(&be->km.v7.rcp[index].dw8_sel_b, value, get);
+ break;
+ case HW_KM_RCP_DW10_DYN:
+ get_set(&be->km.v7.rcp[index].dw10_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW10_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw10_ofs, value, get);
+ break;
+ case HW_KM_RCP_DW10_SEL_A:
+ get_set(&be->km.v7.rcp[index].dw10_sel_a, value, get);
+ break;
+ case HW_KM_RCP_DW10_SEL_B:
+ get_set(&be->km.v7.rcp[index].dw10_sel_b, value, get);
+ break;
+ case HW_KM_RCP_SWX_CCH:
+ get_set(&be->km.v7.rcp[index].swx_cch, value, get);
+ break;
+ case HW_KM_RCP_SWX_SEL_A:
+ get_set(&be->km.v7.rcp[index].swx_sel_a, value, get);
+ break;
+ case HW_KM_RCP_SWX_SEL_B:
+ get_set(&be->km.v7.rcp[index].swx_sel_b, value, get);
+ break;
+ case HW_KM_RCP_MASK_A:
+ if (word_off > KM_RCP_MASK_D_A_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->km.v7.rcp[index].mask_d_a[word_off], value, get);
+ break;
+ case HW_KM_RCP_MASK_B:
+ if (word_off > KM_RCP_MASK_B_SIZE)
+ return error_word_off_too_large(__func__);
+ get_set(&be->km.v7.rcp[index].mask_b[word_off], value, get);
+ break;
+ case HW_KM_RCP_DUAL:
+ get_set(&be->km.v7.rcp[index].dual, value, get);
+ break;
+ case HW_KM_RCP_PAIRED:
+ get_set(&be->km.v7.rcp[index].paired, value, get);
+ break;
+ case HW_KM_RCP_EL_A:
+ get_set(&be->km.v7.rcp[index].el_a, value, get);
+ break;
+ case HW_KM_RCP_EL_B:
+ get_set(&be->km.v7.rcp[index].el_b, value, get);
+ break;
+ case HW_KM_RCP_INFO_A:
+ get_set(&be->km.v7.rcp[index].info_a, value, get);
+ break;
+ case HW_KM_RCP_INFO_B:
+ get_set(&be->km.v7.rcp[index].info_b, value, get);
+ break;
+ case HW_KM_RCP_FTM_A:
+ get_set(&be->km.v7.rcp[index].ftm_a, value, get);
+ break;
+ case HW_KM_RCP_FTM_B:
+ get_set(&be->km.v7.rcp[index].ftm_b, value, get);
+ break;
+ case HW_KM_RCP_BANK_A:
+ get_set(&be->km.v7.rcp[index].bank_a, value, get);
+ break;
+ case HW_KM_RCP_BANK_B:
+ get_set(&be->km.v7.rcp[index].bank_b, value, get);
+ break;
+ case HW_KM_RCP_KL_A:
+ get_set(&be->km.v7.rcp[index].kl_a, value, get);
+ break;
+ case HW_KM_RCP_KL_B:
+ get_set(&be->km.v7.rcp[index].kl_b, value, get);
+ break;
+ case HW_KM_RCP_KEYWAY_A:
+ get_set(&be->km.v7.rcp[index].keyway_a, value, get);
+ break;
+ case HW_KM_RCP_KEYWAY_B:
+ get_set(&be->km.v7.rcp[index].keyway_b, value, get);
+ break;
+ case HW_KM_RCP_SYNERGY_MODE:
+ get_set(&be->km.v7.rcp[index].synergy_mode, value, get);
+ break;
+ case HW_KM_RCP_DW0_B_DYN:
+ get_set(&be->km.v7.rcp[index].dw0_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW0_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw0_b_ofs, value, get);
+ break;
+ case HW_KM_RCP_DW2_B_DYN:
+ get_set(&be->km.v7.rcp[index].dw2_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_DW2_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].dw2_b_ofs, value, get);
+ break;
+ case HW_KM_RCP_SW4_B_DYN:
+ get_set(&be->km.v7.rcp[index].sw4_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_SW4_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].sw4_b_ofs, value, get);
+ break;
+ case HW_KM_RCP_SW5_B_DYN:
+ get_set(&be->km.v7.rcp[index].sw5_b_dyn, value, get);
+ break;
+ case HW_KM_RCP_SW5_B_OFS:
+ get_set_signed(&be->km.v7.rcp[index].sw5_b_ofs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_km_rcp_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t value)
+{
+ return hw_mod_km_rcp_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_km_rcp_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int index, int word_off, uint32_t *value)
+{
+ return hw_mod_km_rcp_mod(be, field, index, word_off, value, 1);
+}
+
+int hw_mod_km_cam_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_cam_records * be->km.nb_cam_banks;
+
+ unsigned int end =
+ start_bank * be->km.nb_cam_records + start_record + count;
+ if (end > (be->km.nb_cam_banks * be->km.nb_cam_records))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_cam_flush(be->be_dev, &be->km, start_bank,
+ start_record, count);
+}
+
+static int hw_mod_km_cam_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value, int get)
+{
+ if ((unsigned int)bank >= be->km.nb_cam_banks)
+ return error_index_too_large(__func__);
+ if ((unsigned int)record >= be->km.nb_cam_records)
+ return error_index_too_large(__func__);
+
+ unsigned int index = bank * be->km.nb_cam_records + record;
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_CAM_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->km.v7.cam[index], (uint8_t)*value,
+ sizeof(struct km_v7_cam_s));
+ break;
+ case HW_KM_CAM_W0:
+ get_set(&be->km.v7.cam[index].w0, value, get);
+ break;
+ case HW_KM_CAM_W1:
+ get_set(&be->km.v7.cam[index].w1, value, get);
+ break;
+ case HW_KM_CAM_W2:
+ get_set(&be->km.v7.cam[index].w2, value, get);
+ break;
+ case HW_KM_CAM_W3:
+ get_set(&be->km.v7.cam[index].w3, value, get);
+ break;
+ case HW_KM_CAM_W4:
+ get_set(&be->km.v7.cam[index].w4, value, get);
+ break;
+ case HW_KM_CAM_W5:
+ get_set(&be->km.v7.cam[index].w5, value, get);
+ break;
+ case HW_KM_CAM_FT0:
+ get_set(&be->km.v7.cam[index].ft0, value, get);
+ break;
+ case HW_KM_CAM_FT1:
+ get_set(&be->km.v7.cam[index].ft1, value, get);
+ break;
+ case HW_KM_CAM_FT2:
+ get_set(&be->km.v7.cam[index].ft2, value, get);
+ break;
+ case HW_KM_CAM_FT3:
+ get_set(&be->km.v7.cam[index].ft3, value, get);
+ break;
+ case HW_KM_CAM_FT4:
+ get_set(&be->km.v7.cam[index].ft4, value, get);
+ break;
+ case HW_KM_CAM_FT5:
+ get_set(&be->km.v7.cam[index].ft5, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_cam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value)
+{
+ return hw_mod_km_cam_mod(be, field, bank, record, &value, 0);
+}
+
+int hw_mod_km_cam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_cam_mod(be, field, bank, record, value, 1);
+}
+
+int hw_mod_km_tcam_flush(struct flow_api_backend_s *be, int start_bank,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_tcam_banks * 4 * 256;
+ else if (count == ALL_BANK_ENTRIES)
+ count = 4 * 256;
+
+ unsigned int end = start_bank * 4 * 256 + count;
+
+ if (end > (be->km.nb_tcam_banks * 4 * 256))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_tcam_flush(be->be_dev, &be->km, start_bank, 0, 0,
+ count);
+}
+
+static int hw_mod_km_tcam_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val,
+ uint32_t *value_set, int get)
+{
+ unsigned int start_index = bank * 4 * 256 + (int)byte * 256 + byte_val;
+
+ if (start_index >= (be->km.nb_tcam_banks * 4 * 256))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_TCAM_BANK_RESET:
+ if (get)
+ return error_unsup_field(__func__);
+ {
+ int start_idx = bank * 4 * 256;
+
+ for (int i = 0; i < 4 * 256; i++) {
+ be->km.v7.tcam[start_idx + i].t[0] =
+ value_set[0];
+ be->km.v7.tcam[start_idx + i].t[1] =
+ value_set[1];
+ be->km.v7.tcam[start_idx + i].t[2] =
+ value_set[2];
+ be->km.v7.tcam[start_idx + i].dirty = 1;
+ }
+ }
+ break;
+ case HW_KM_TCAM_T: {
+ int index = bank * 4 * 256 + byte * 256 + byte_val;
+
+ if (get) {
+ value_set[0] = be->km.v7.tcam[index].t[0];
+ value_set[1] = be->km.v7.tcam[index].t[1];
+ value_set[2] = be->km.v7.tcam[index].t[2];
+ } else {
+ /* only change if any bits has to be changed */
+ if (be->km.v7.tcam[index].t[0] !=
+ value_set[0] ||
+ be->km.v7.tcam[index].t[1] !=
+ value_set[1] ||
+ be->km.v7.tcam[index].t[2] !=
+ value_set[2]) {
+ be->km.v7.tcam[index].t[0] =
+ value_set[0];
+ be->km.v7.tcam[index].t[1] =
+ value_set[1];
+ be->km.v7.tcam[index].t[2] =
+ value_set[2];
+ be->km.v7.tcam[index].dirty = 1;
+ }
+ }
+ }
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_tcam_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set)
+{
+ return hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set,
+ 0);
+}
+
+int hw_mod_km_tcam_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int byte, int byte_val, uint32_t *value_set)
+{
+ return hw_mod_km_tcam_mod(be, field, bank, byte, byte_val, value_set,
+ 1);
+}
+
+int hw_mod_km_tci_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width;
+
+ unsigned int end = (int)start_bank * be->km.nb_tcam_bank_width +
+ start_record + count;
+
+ if (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_tci_flush(be->be_dev, &be->km, start_bank,
+ start_record, count);
+}
+
+static int hw_mod_km_tci_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value, int get)
+{
+ unsigned int index = bank * be->km.nb_tcam_bank_width + record;
+
+ if (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_TCI_COLOR:
+ get_set(&be->km.v7.tci[index].color, value, get);
+ break;
+ case HW_KM_TCI_FT:
+ get_set(&be->km.v7.tci[index].ft, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_tci_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t value)
+{
+ return hw_mod_km_tci_mod(be, field, bank, record, &value, 0);
+}
+
+int hw_mod_km_tci_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_tci_mod(be, field, bank, record, value, 1);
+}
+
+int hw_mod_km_tcq_flush(struct flow_api_backend_s *be, int start_bank,
+ int start_record, int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->km.nb_tcam_banks * be->km.nb_tcam_bank_width;
+
+ unsigned int end = (int)start_bank * be->km.nb_tcam_bank_width +
+ start_record + count;
+
+ if (end > (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ return be->iface->km_tcq_flush(be->be_dev, &be->km, start_bank,
+ start_record, count);
+}
+
+static int hw_mod_km_tcq_mod(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value, int get)
+{
+ unsigned int index = bank * be->km.nb_tcam_bank_width + record;
+
+ if (index >= (be->km.nb_tcam_banks * be->km.nb_tcam_bank_width))
+ return error_index_too_large(__func__);
+
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_KM_TCQ_BANK_MASK:
+ get_set(&be->km.v7.tcq[index].bank_mask, value, get);
+ break;
+ case HW_KM_TCQ_QUAL:
+ get_set(&be->km.v7.tcq[index].qual, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+int hw_mod_km_tcq_set(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_tcq_mod(be, field, bank, record, value, 0);
+}
+
+int hw_mod_km_tcq_get(struct flow_api_backend_s *be, enum hw_km_e field,
+ int bank, int record, uint32_t *value)
+{
+ return hw_mod_km_tcq_mod(be, field, bank, record, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h
new file mode 100644
index 0000000000..798a175609
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_km_v7.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_KM_V7_H_
+#define _HW_MOD_KM_V7_H_
+
+struct km_v7_rcp_s {
+ uint32_t qw0_dyn;
+ int32_t qw0_ofs;
+ uint32_t qw0_sel_a;
+ uint32_t qw0_sel_b;
+ uint32_t qw4_dyn;
+ int32_t qw4_ofs;
+ uint32_t qw4_sel_a;
+ uint32_t qw4_sel_b;
+ uint32_t dw8_dyn;
+ int32_t dw8_ofs;
+ uint32_t dw8_sel_a;
+ uint32_t dw8_sel_b;
+ uint32_t dw10_dyn;
+ int32_t dw10_ofs;
+ uint32_t dw10_sel_a;
+ uint32_t dw10_sel_b;
+ uint32_t swx_cch;
+ uint32_t swx_sel_a;
+ uint32_t swx_sel_b;
+ uint32_t mask_d_a[12];
+ uint32_t mask_b[6];
+ uint32_t dual;
+ uint32_t paired;
+ uint32_t el_a;
+ uint32_t el_b;
+ uint32_t info_a;
+ uint32_t info_b;
+ uint32_t ftm_a;
+ uint32_t ftm_b;
+ uint32_t bank_a;
+ uint32_t bank_b;
+ uint32_t kl_a;
+ uint32_t kl_b;
+ uint32_t keyway_a;
+ uint32_t keyway_b;
+ uint32_t synergy_mode;
+ uint32_t dw0_b_dyn;
+ int32_t dw0_b_ofs;
+ uint32_t dw2_b_dyn;
+ int32_t dw2_b_ofs;
+ uint32_t sw4_b_dyn;
+ int32_t sw4_b_ofs;
+ uint32_t sw5_b_dyn;
+ int32_t sw5_b_ofs;
+};
+
+struct km_v7_cam_s {
+ uint32_t w0;
+ uint32_t w1;
+ uint32_t w2;
+ uint32_t w3;
+ uint32_t w4;
+ uint32_t w5;
+ uint32_t ft0;
+ uint32_t ft1;
+ uint32_t ft2;
+ uint32_t ft3;
+ uint32_t ft4;
+ uint32_t ft5;
+};
+
+struct km_v7_tcam_s {
+ uint32_t t[3];
+ uint32_t dirty;
+};
+
+struct km_v7_tci_s {
+ uint32_t color;
+ uint32_t ft;
+};
+
+struct km_v7_tcq_s {
+ uint32_t bank_mask;
+ uint32_t qual;
+};
+
+struct hw_mod_km_v7_s {
+ struct km_v7_rcp_s *rcp;
+ struct km_v7_cam_s *cam;
+ struct km_v7_tcam_s *tcam;
+ struct km_v7_tci_s *tci;
+ struct km_v7_tcq_s *tcq;
+};
+
+#endif /* _HW_MOD_KM_V7_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c
new file mode 100644
index 0000000000..8d0d70cae2
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb.c
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "PDB"
+#define _VER_ be->pdb.ver
+
+bool hw_mod_pdb_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_pdb_present(be->be_dev);
+}
+
+int hw_mod_pdb_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_pdb_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "PDB MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_pdb_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "pdb_categories", _MOD_, _VER_);
+ be->pdb.nb_pdb_rcp_categories = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 9:
+ if (!callocate_mod(CAST_COMMON(&be->pdb), 2,
+ &be->pdb.v9.rcp,
+ be->pdb.nb_pdb_rcp_categories,
+ sizeof(struct pdb_v9_rcp_s),
+ &be->pdb.v9.config,
+ 1,
+ sizeof(struct pdb_v9_config_s)))
+ return -1;
+ break;
+ /* end case 9 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_pdb_free(struct flow_api_backend_s *be)
+{
+ if (be->pdb.base) {
+ free(be->pdb.base);
+ be->pdb.base = NULL;
+ }
+}
+
+int hw_mod_pdb_reset(struct flow_api_backend_s *be)
+{
+ int err = 0;
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->pdb);
+
+ NT_LOG(DBG, FILTER, "INIT PDB RCP\n");
+ err |= hw_mod_pdb_rcp_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT PDB CONFIG\n");
+ err |= hw_mod_pdb_config_flush(be);
+ return err;
+}
+
+int hw_mod_pdb_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->pdb.nb_pdb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->pdb.nb_pdb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->pdb_rcp_flush(be->be_dev, &be->pdb, start_idx, count);
+}
+
+static int hw_mod_pdb_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_pdb_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->pdb.nb_pdb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 9:
+ switch (field) {
+ case HW_PDB_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->pdb.v9.rcp[index], (uint8_t)*value,
+ sizeof(struct pdb_v9_rcp_s));
+ break;
+ case HW_PDB_RCP_FIND:
+ rv = find_equal_index(be->pdb.v9.rcp,
+ sizeof(struct pdb_v9_rcp_s), index, *value,
+ be->pdb.nb_pdb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_PDB_RCP_COMPARE:
+ rv = do_compare_indexes(be->pdb.v9.rcp,
+ sizeof(struct pdb_v9_rcp_s), index, *value,
+ be->pdb.nb_pdb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_PDB_RCP_DESCRIPTOR:
+ get_set(&be->pdb.v9.rcp[index].descriptor, value, get);
+ break;
+ case HW_PDB_RCP_DESC_LEN:
+ get_set(&be->pdb.v9.rcp[index].desc_len, value, get);
+ break;
+ case HW_PDB_RCP_TX_PORT:
+ get_set(&be->pdb.v9.rcp[index].tx_port, value, get);
+ break;
+ case HW_PDB_RCP_TX_IGNORE:
+ get_set(&be->pdb.v9.rcp[index].tx_ignore, value, get);
+ break;
+ case HW_PDB_RCP_TX_NOW:
+ get_set(&be->pdb.v9.rcp[index].tx_now, value, get);
+ break;
+ case HW_PDB_RCP_CRC_OVERWRITE:
+ get_set(&be->pdb.v9.rcp[index].crc_overwrite, value, get);
+ break;
+ case HW_PDB_RCP_ALIGN:
+ get_set(&be->pdb.v9.rcp[index].align, value, get);
+ break;
+ case HW_PDB_RCP_OFS0_DYN:
+ get_set(&be->pdb.v9.rcp[index].ofs0_dyn, value, get);
+ break;
+ case HW_PDB_RCP_OFS0_REL:
+ get_set_signed(&be->pdb.v9.rcp[index].ofs0_rel, value, get);
+ break;
+ case HW_PDB_RCP_OFS1_DYN:
+ get_set(&be->pdb.v9.rcp[index].ofs1_dyn, value, get);
+ break;
+ case HW_PDB_RCP_OFS1_REL:
+ get_set_signed(&be->pdb.v9.rcp[index].ofs1_rel, value, get);
+ break;
+ case HW_PDB_RCP_OFS2_DYN:
+ get_set(&be->pdb.v9.rcp[index].ofs2_dyn, value, get);
+ break;
+ case HW_PDB_RCP_OFS2_REL:
+ get_set_signed(&be->pdb.v9.rcp[index].ofs2_rel, value, get);
+ break;
+ case HW_PDB_RCP_IP_PROT_TNL:
+ get_set(&be->pdb.v9.rcp[index].ip_prot_tnl, value, get);
+ break;
+ case HW_PDB_RCP_PPC_HSH:
+ get_set(&be->pdb.v9.rcp[index].ppc_hsh, value, get);
+ break;
+ case HW_PDB_RCP_DUPLICATE_EN:
+ get_set(&be->pdb.v9.rcp[index].duplicate_en, value, get);
+ break;
+ case HW_PDB_RCP_DUPLICATE_BIT:
+ get_set(&be->pdb.v9.rcp[index].duplicate_bit, value, get);
+ break;
+ case HW_PDB_RCP_PCAP_KEEP_FCS:
+ get_set(&be->pdb.v9.rcp[index].pcap_keep_fcs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 9 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_pdb_rcp_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_pdb_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_pdb_rcp_get(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_pdb_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_pdb_config_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->pdb_config_flush(be->be_dev, &be->pdb);
+}
+
+int hw_mod_pdb_config_set(struct flow_api_backend_s *be, enum hw_pdb_e field,
+ uint32_t value)
+{
+ switch (_VER_) {
+ case 9:
+ switch (field) {
+ case HW_PDB_CONFIG_TS_FORMAT:
+ be->pdb.v9.config->ts_format = value;
+ break;
+ case HW_PDB_CONFIG_PORT_OFS:
+ be->pdb.v9.config->port_ofs = value;
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 9 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h
new file mode 100644
index 0000000000..b14c10bc53
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_pdb_v9.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_PDB_V9_H_
+#define _HW_MOD_PDB_V9_H_
+
+struct pdb_v9_rcp_s {
+ uint32_t descriptor;
+ uint32_t desc_len;
+ uint32_t tx_port;
+ uint32_t tx_ignore;
+ uint32_t tx_now;
+ uint32_t crc_overwrite;
+ uint32_t align;
+ uint32_t ofs0_dyn;
+ int32_t ofs0_rel;
+ uint32_t ofs1_dyn;
+ int32_t ofs1_rel;
+ uint32_t ofs2_dyn;
+ int32_t ofs2_rel;
+ uint32_t ip_prot_tnl;
+ uint32_t ppc_hsh;
+ uint32_t duplicate_en;
+ uint32_t duplicate_bit;
+ uint32_t pcap_keep_fcs; /* only field added to v9 cmp to v7/8 */
+};
+
+struct pdb_v9_config_s {
+ uint32_t ts_format;
+ uint32_t port_ofs;
+};
+
+struct hw_mod_pdb_v9_s {
+ struct pdb_v9_rcp_s *rcp;
+ struct pdb_v9_config_s *config;
+};
+
+#endif /* _HW_MOD_PDB_V9_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c
new file mode 100644
index 0000000000..86d23ea683
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl.c
@@ -0,0 +1,348 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "QSL"
+#define _VER_ be->qsl.ver
+
+#define QSL_QEN_ENTRIES 32
+#define QSL_QNMQ_ENTRIES 256
+
+bool hw_mod_qsl_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_qsl_present(be->be_dev);
+}
+
+int hw_mod_qsl_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_qsl_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "QSL MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_qsl_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "qsl_categories", _MOD_, _VER_);
+ be->qsl.nb_rcp_categories = (uint32_t)nb;
+
+ nb = be->iface->get_nb_qsl_qst_entries(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "qsl_qst_entries", _MOD_, _VER_);
+ be->qsl.nb_qst_entries = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 7:
+ if (!callocate_mod(CAST_COMMON(&be->qsl), 4,
+ &be->qsl.v7.rcp,
+ be->qsl.nb_rcp_categories,
+ sizeof(struct qsl_v7_rcp_s),
+ &be->qsl.v7.qst,
+ be->qsl.nb_qst_entries,
+ sizeof(struct qsl_v7_qst_s),
+ &be->qsl.v7.qen,
+ QSL_QEN_ENTRIES,
+ sizeof(struct qsl_v7_qen_s),
+ &be->qsl.v7.unmq,
+ QSL_QNMQ_ENTRIES,
+ sizeof(struct qsl_v7_unmq_s)))
+ return -1;
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_qsl_free(struct flow_api_backend_s *be)
+{
+ if (be->qsl.base) {
+ free(be->qsl.base);
+ be->qsl.base = NULL;
+ }
+}
+
+int hw_mod_qsl_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->qsl);
+
+ NT_LOG(DBG, FILTER, "INIT QSL RCP\n");
+ hw_mod_qsl_rcp_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT QSL QST\n");
+ hw_mod_qsl_qst_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT QSL QEN\n");
+ hw_mod_qsl_qen_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT QSL UNMQ\n");
+ be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, 0, 256);
+
+ return 0;
+}
+
+int hw_mod_qsl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->qsl.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->qsl.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_rcp_flush(be->be_dev, &be->qsl, start_idx, count);
+}
+
+static int hw_mod_qsl_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->qsl.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->qsl.v7.rcp[index], (uint8_t)*value,
+ sizeof(struct qsl_v7_rcp_s));
+ break;
+ case HW_QSL_RCP_FIND:
+ rv = find_equal_index(be->qsl.v7.rcp,
+ sizeof(struct qsl_v7_rcp_s), index, *value,
+ be->qsl.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_QSL_RCP_COMPARE:
+ rv = do_compare_indexes(be->qsl.v7.rcp,
+ sizeof(struct qsl_v7_rcp_s), index, *value,
+ be->qsl.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_QSL_RCP_DISCARD:
+ get_set(&be->qsl.v7.rcp[index].discard, value, get);
+ break;
+ case HW_QSL_RCP_DROP:
+ get_set(&be->qsl.v7.rcp[index].drop, value, get);
+ break;
+ case HW_QSL_RCP_TBL_LO:
+ get_set(&be->qsl.v7.rcp[index].tbl_lo, value, get);
+ break;
+ case HW_QSL_RCP_TBL_HI:
+ get_set(&be->qsl.v7.rcp[index].tbl_hi, value, get);
+ break;
+ case HW_QSL_RCP_TBL_IDX:
+ get_set(&be->qsl.v7.rcp[index].tbl_idx, value, get);
+ break;
+ case HW_QSL_RCP_TBL_MSK:
+ get_set(&be->qsl.v7.rcp[index].tbl_msk, value, get);
+ break;
+ case HW_QSL_RCP_LR:
+ get_set(&be->qsl.v7.rcp[index].lr, value, get);
+ break;
+ case HW_QSL_RCP_TSA:
+ get_set(&be->qsl.v7.rcp[index].tsa, value, get);
+ break;
+ case HW_QSL_RCP_VLI:
+ get_set(&be->qsl.v7.rcp[index].vli, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_rcp_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_rcp_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_rcp_mod(be, field, index, value, 1);
+}
+
+int hw_mod_qsl_qst_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->qsl.nb_qst_entries;
+ if ((unsigned int)(start_idx + count) > be->qsl.nb_qst_entries)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_qst_flush(be->be_dev, &be->qsl, start_idx, count);
+}
+
+static int hw_mod_qsl_qst_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->qsl.nb_qst_entries)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_QST_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->qsl.v7.qst[index], (uint8_t)*value,
+ sizeof(struct qsl_v7_qst_s));
+ break;
+ case HW_QSL_QST_QUEUE:
+ get_set(&be->qsl.v7.qst[index].queue, value, get);
+ break;
+ case HW_QSL_QST_EN:
+ get_set(&be->qsl.v7.qst[index].en, value, get);
+ break;
+ case HW_QSL_QST_TX_PORT:
+ get_set(&be->qsl.v7.qst[index].tx_port, value, get);
+ break;
+ case HW_QSL_QST_LRE:
+ get_set(&be->qsl.v7.qst[index].lre, value, get);
+ break;
+ case HW_QSL_QST_TCI:
+ get_set(&be->qsl.v7.qst[index].tci, value, get);
+ break;
+ case HW_QSL_QST_VEN:
+ get_set(&be->qsl.v7.qst[index].ven, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_qst_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_qst_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_qst_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_qst_mod(be, field, index, value, 1);
+}
+
+int hw_mod_qsl_qen_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = QSL_QEN_ENTRIES;
+ if ((start_idx + count) > QSL_QEN_ENTRIES)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_qen_flush(be->be_dev, &be->qsl, start_idx, count);
+}
+
+static int hw_mod_qsl_qen_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= QSL_QEN_ENTRIES)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_QEN_EN:
+ get_set(&be->qsl.v7.qen[index].en, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_qen_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_qen_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_qen_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_qen_mod(be, field, index, value, 1);
+}
+
+int hw_mod_qsl_unmq_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = QSL_QNMQ_ENTRIES;
+ if ((start_idx + count) > QSL_QNMQ_ENTRIES)
+ return error_index_too_large(__func__);
+ return be->iface->qsl_unmq_flush(be->be_dev, &be->qsl, start_idx,
+ count);
+}
+
+static int hw_mod_qsl_unmq_mod(struct flow_api_backend_s *be,
+ enum hw_qsl_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= QSL_QNMQ_ENTRIES)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 7:
+ switch (field) {
+ case HW_QSL_UNMQ_DEST_QUEUE:
+ get_set(&be->qsl.v7.unmq[index].dest_queue, value, get);
+ break;
+ case HW_QSL_UNMQ_EN:
+ get_set(&be->qsl.v7.unmq[index].en, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 7 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_qsl_unmq_set(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_qsl_unmq_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_qsl_unmq_get(struct flow_api_backend_s *be, enum hw_qsl_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_qsl_unmq_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h
new file mode 100644
index 0000000000..747da4bc43
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_qsl_v7.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_QSL_V7_H_
+#define _HW_MOD_QSL_V7_H_
+
+struct qsl_v7_rcp_s {
+ uint32_t discard;
+ uint32_t drop;
+ uint32_t tbl_lo;
+ uint32_t tbl_hi;
+ uint32_t tbl_idx;
+ uint32_t tbl_msk;
+ uint32_t lr;
+ uint32_t tsa;
+ uint32_t vli;
+};
+
+struct qsl_v7_qst_s {
+ uint32_t queue;
+ uint32_t en;
+ uint32_t tx_port;
+ uint32_t lre;
+ uint32_t tci;
+ uint32_t ven;
+};
+
+struct qsl_v7_qen_s {
+ uint32_t en;
+};
+
+struct qsl_v7_unmq_s {
+ uint32_t dest_queue;
+ uint32_t en;
+};
+
+struct hw_mod_qsl_v7_s {
+ struct qsl_v7_rcp_s *rcp;
+ struct qsl_v7_qst_s *qst;
+ struct qsl_v7_qen_s *qen;
+ struct qsl_v7_unmq_s *unmq;
+};
+
+#endif /* _HW_MOD_QSL_V7_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c
new file mode 100644
index 0000000000..7f1d695a90
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "RMC"
+#define _VER_ be->rmc.ver
+
+bool hw_mod_rmc_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_rmc_present(be->be_dev);
+}
+
+int hw_mod_rmc_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_rmc_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "RMC MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 0x10003:
+ if (!callocate_mod(CAST_COMMON(&be->rmc), 1,
+ &be->rmc.v1_3.ctrl, 1, sizeof(struct rmc_v1_3_ctrl_s)))
+ return -1;
+ break;
+ /* end case 1_3 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_rmc_free(struct flow_api_backend_s *be)
+{
+ if (be->rmc.base) {
+ free(be->rmc.base);
+ be->rmc.base = NULL;
+ }
+}
+
+int hw_mod_rmc_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->rmc);
+
+ NT_LOG(DBG, FILTER, "INIT RMC CTRL\n");
+ /* disable block stat, block keep alive */
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1);
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_KEEPA, 1);
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_MAC_PORT,
+ 0xff); /* initially block all ports */
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_STATT, 1);
+ hw_mod_rmc_ctrl_set(be, HW_RMC_BLOCK_RPP_SLICE, 0xf);
+ return hw_mod_rmc_ctrl_flush(be);
+}
+
+int hw_mod_rmc_ctrl_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->rmc_ctrl_flush(be->be_dev, &be->rmc);
+}
+
+static int hw_mod_rmc_ctrl_mod(struct flow_api_backend_s *be,
+ enum hw_rmc_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 0x10003:
+ switch (field) {
+ case HW_RMC_BLOCK_STATT:
+ get_set(&be->rmc.v1_3.ctrl->block_statt, value, get);
+ break;
+ case HW_RMC_BLOCK_KEEPA:
+ get_set(&be->rmc.v1_3.ctrl->block_keepa, value, get);
+ break;
+ case HW_RMC_BLOCK_RPP_SLICE:
+ get_set(&be->rmc.v1_3.ctrl->block_rpp_slice, value, get);
+ break;
+ case HW_RMC_BLOCK_MAC_PORT:
+ get_set(&be->rmc.v1_3.ctrl->block_mac_port, value, get);
+ break;
+ case HW_RMC_LAG_PHY_ODD_EVEN:
+ get_set(&be->rmc.v1_3.ctrl->lag_phy_odd_even, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1.3 */
+
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_rmc_ctrl_set(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t value)
+{
+ return hw_mod_rmc_ctrl_mod(be, field, &value, 0);
+}
+
+int hw_mod_rmc_ctrl_get(struct flow_api_backend_s *be, enum hw_rmc_e field,
+ uint32_t *value)
+{
+ return hw_mod_rmc_ctrl_mod(be, field, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h
new file mode 100644
index 0000000000..8f90695821
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_rmc_v1_3.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_RMC_V1_3_H_
+#define _HW_MOD_RMC_V1_3_H_
+
+struct rmc_v1_3_ctrl_s {
+ uint32_t block_statt;
+ uint32_t block_keepa;
+ uint32_t block_rpp_slice;
+ uint32_t block_mac_port;
+ uint32_t lag_phy_odd_even;
+};
+
+struct hw_mod_rmc_v1_3_s {
+ struct rmc_v1_3_ctrl_s *ctrl;
+};
+
+#endif /* _HW_MOD_RMC_V1_3_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c
new file mode 100644
index 0000000000..933caf9fd5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa.c
@@ -0,0 +1,358 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "ROA"
+#define _VER_ be->roa.ver
+
+#define ROA_LAGCFG_ENTRIES 512
+
+bool hw_mod_roa_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_roa_present(be->be_dev);
+}
+
+int hw_mod_roa_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_roa_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "ROA MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_roa_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "roa_categories", _MOD_, _VER_);
+ be->roa.nb_tun_categories = (uint32_t)nb;
+
+ be->roa.nb_tun_categories /= 4;
+
+ switch (_VER_) {
+ case 6:
+ be->roa.nb_lag_entries = ROA_LAGCFG_ENTRIES;
+ if (!callocate_mod(CAST_COMMON(&be->roa), 4,
+ &be->roa.v6.tunhdr,
+ be->roa.nb_tun_categories,
+ sizeof(struct roa_v6_tunhdr_s),
+ &be->roa.v6.tuncfg,
+ be->roa.nb_tun_categories,
+ sizeof(struct roa_v6_tuncfg_s),
+ &be->roa.v6.config,
+ 1,
+ sizeof(struct roa_v6_config_s),
+ &be->roa.v6.lagcfg,
+ be->roa.nb_lag_entries,
+ sizeof(struct roa_v6_lagcfg_s)))
+ return -1;
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+ return 0;
+}
+
+void hw_mod_roa_free(struct flow_api_backend_s *be)
+{
+ if (be->roa.base) {
+ free(be->roa.base);
+ be->roa.base = NULL;
+ }
+}
+
+int hw_mod_roa_reset(struct flow_api_backend_s *be)
+{
+ int err = 0;
+
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->roa);
+
+ NT_LOG(DBG, FILTER, "INIT ROA TUNHDR\n");
+ err = hw_mod_roa_tunhdr_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT ROA TUNCFG\n");
+ hw_mod_roa_tuncfg_flush(be, 0, ALL_ENTRIES);
+
+ NT_LOG(DBG, FILTER, "INIT ROA CONFIG\n");
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_RECIRCULATE, 1);
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_NORMAL_PCKS, 1);
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT0, 1);
+ hw_mod_roa_config_set(be, HW_ROA_CONFIG_FWD_TXPORT1, 1);
+ hw_mod_roa_config_flush(be);
+
+ NT_LOG(DBG, FILTER, "INIT ROA LAGCFG\n");
+ hw_mod_roa_lagcfg_flush(be, 0, ALL_ENTRIES);
+
+ return err;
+}
+
+int hw_mod_roa_tunhdr_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->roa.nb_tun_categories;
+ if ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ return be->iface->roa_tunhdr_flush(be->be_dev, &be->roa, start_idx,
+ count);
+}
+
+static int hw_mod_roa_tunhdr_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t index,
+ uint32_t word_off, uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_TUNHDR_COMPARE:
+ rv = do_compare_indexes(be->roa.v6.tunhdr,
+ sizeof(struct roa_v6_tunhdr_s), index, word_off,
+ be->roa.nb_tun_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_ROA_TUNHDR:
+ get_set(&be->roa.v6.tunhdr[index].tunnel_hdr[word_off],
+ value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_tunhdr_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t value)
+{
+ return hw_mod_roa_tunhdr_mod(be, field, index, word_off, &value, 0);
+}
+
+int hw_mod_roa_tunhdr_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t word_off, uint32_t *value)
+{
+ return hw_mod_roa_tunhdr_mod(be, field, index, word_off, value, 1);
+}
+
+int hw_mod_roa_tuncfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->roa.nb_tun_categories;
+ if ((unsigned int)(start_idx + count) > be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ return be->iface->roa_tuncfg_flush(be->be_dev, &be->roa, start_idx,
+ count);
+}
+
+static int hw_mod_roa_tuncfg_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->roa.nb_tun_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_TUNCFG_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->roa.v6.tuncfg[index], (uint8_t)*value,
+ sizeof(struct roa_v6_tuncfg_s));
+ break;
+ case HW_ROA_TUNCFG_FIND:
+ rv = find_equal_index(be->roa.v6.tuncfg,
+ sizeof(struct roa_v6_tuncfg_s), index, *value,
+ be->roa.nb_tun_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_ROA_TUNCFG_COMPARE:
+ rv = do_compare_indexes(be->roa.v6.tuncfg,
+ sizeof(struct roa_v6_tuncfg_s), index, *value,
+ be->roa.nb_tun_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_ROA_TUNCFG_TUN_LEN:
+ get_set(&be->roa.v6.tuncfg[index].tun_len, value, get);
+ break;
+ case HW_ROA_TUNCFG_TUN_TYPE:
+ get_set(&be->roa.v6.tuncfg[index].tun_type, value, get);
+ break;
+ case HW_ROA_TUNCFG_TUN_VLAN:
+ get_set(&be->roa.v6.tuncfg[index].tun_vlan, value, get);
+ break;
+ case HW_ROA_TUNCFG_IP_TYPE:
+ get_set(&be->roa.v6.tuncfg[index].ip_type, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPCS_UPD:
+ get_set(&be->roa.v6.tuncfg[index].ipcs_upd, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPCS_PRECALC:
+ get_set(&be->roa.v6.tuncfg[index].ipcs_precalc, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPTL_UPD:
+ get_set(&be->roa.v6.tuncfg[index].iptl_upd, value, get);
+ break;
+ case HW_ROA_TUNCFG_IPTL_PRECALC:
+ get_set(&be->roa.v6.tuncfg[index].iptl_precalc, value, get);
+ break;
+ case HW_ROA_TUNCFG_VXLAN_UDP_LEN_UPD:
+ get_set(&be->roa.v6.tuncfg[index].vxlan_udp_len_upd,
+ value, get);
+ break;
+ case HW_ROA_TUNCFG_TX_LAG_IX:
+ get_set(&be->roa.v6.tuncfg[index].tx_lag_ix, value, get);
+ break;
+ case HW_ROA_TUNCFG_RECIRCULATE:
+ get_set(&be->roa.v6.tuncfg[index].recirculate, value, get);
+ break;
+ case HW_ROA_TUNCFG_PUSH_TUNNEL:
+ get_set(&be->roa.v6.tuncfg[index].push_tunnel, value, get);
+ break;
+ case HW_ROA_TUNCFG_RECIRC_PORT:
+ get_set(&be->roa.v6.tuncfg[index].recirc_port, value, get);
+ break;
+ case HW_ROA_TUNCFG_RECIRC_BYPASS:
+ get_set(&be->roa.v6.tuncfg[index].recirc_bypass, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_tuncfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_roa_tuncfg_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_roa_tuncfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_roa_tuncfg_mod(be, field, index, value, 1);
+}
+
+int hw_mod_roa_config_flush(struct flow_api_backend_s *be)
+{
+ return be->iface->roa_config_flush(be->be_dev, &be->roa);
+}
+
+static int hw_mod_roa_config_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t *value, int get)
+{
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_CONFIG_FWD_RECIRCULATE:
+ get_set(&be->roa.v6.config->fwd_recirculate, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_NORMAL_PCKS:
+ get_set(&be->roa.v6.config->fwd_normal_pcks, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_TXPORT0:
+ get_set(&be->roa.v6.config->fwd_txport0, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_TXPORT1:
+ get_set(&be->roa.v6.config->fwd_txport1, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_CELLBUILDER_PCKS:
+ get_set(&be->roa.v6.config->fwd_cellbuilder_pcks, value, get);
+ break;
+ case HW_ROA_CONFIG_FWD_NON_NORMAL_PCKS:
+ get_set(&be->roa.v6.config->fwd_non_normal_pcks, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_config_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t value)
+{
+ return hw_mod_roa_config_mod(be, field, &value, 0);
+}
+
+int hw_mod_roa_config_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t *value)
+{
+ return hw_mod_roa_config_mod(be, field, value, 1);
+}
+
+int hw_mod_roa_lagcfg_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->roa.nb_lag_entries;
+ if ((unsigned int)(start_idx + count) > be->roa.nb_lag_entries)
+ return error_index_too_large(__func__);
+ return be->iface->roa_lagcfg_flush(be->be_dev, &be->roa, start_idx,
+ count);
+}
+
+static int hw_mod_roa_lagcfg_mod(struct flow_api_backend_s *be,
+ enum hw_roa_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->roa.nb_lag_entries)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 6:
+ switch (field) {
+ case HW_ROA_LAGCFG_TXPHY_PORT:
+ get_set(&be->roa.v6.lagcfg[index].txphy_port, value, get);
+ break;
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 6 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_roa_lagcfg_set(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_roa_lagcfg_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_roa_lagcfg_get(struct flow_api_backend_s *be, enum hw_roa_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_roa_lagcfg_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h
new file mode 100644
index 0000000000..9930c52428
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_roa_v6.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_ROA_V6_H_
+#define _HW_MOD_ROA_V6_H_
+
+struct roa_v6_tunhdr_s {
+ uint32_t tunnel_hdr[4 * 4];
+};
+
+struct roa_v6_tuncfg_s {
+ uint32_t tun_len;
+ uint32_t tun_type;
+ uint32_t tun_vlan;
+ uint32_t ip_type;
+ uint32_t ipcs_upd;
+ uint32_t ipcs_precalc;
+ uint32_t iptl_upd;
+ uint32_t iptl_precalc;
+ uint32_t vxlan_udp_len_upd;
+ uint32_t tx_lag_ix;
+ uint32_t recirculate;
+ uint32_t push_tunnel;
+ uint32_t recirc_port;
+ uint32_t recirc_bypass;
+};
+
+struct roa_v6_config_s {
+ uint32_t fwd_recirculate;
+ uint32_t fwd_normal_pcks;
+ uint32_t fwd_txport0;
+ uint32_t fwd_txport1;
+ uint32_t fwd_cellbuilder_pcks;
+ uint32_t fwd_non_normal_pcks;
+};
+
+struct roa_v6_lagcfg_s {
+ uint32_t txphy_port;
+};
+
+struct hw_mod_roa_v6_s {
+ struct roa_v6_tunhdr_s *tunhdr;
+ struct roa_v6_tuncfg_s *tuncfg;
+ struct roa_v6_config_s *config;
+ struct roa_v6_lagcfg_s *lagcfg;
+};
+
+#endif /* _HW_MOD_ROA_V6_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c
new file mode 100644
index 0000000000..ca65db7232
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "SLC"
+#define _VER_ be->slc.ver
+
+bool hw_mod_slc_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_slc_present(be->be_dev);
+}
+
+int hw_mod_slc_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_slc_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "SLC MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 1:
+ if (!callocate_mod(CAST_COMMON(&be->slc), 1,
+ &be->slc.v1.rcp,
+ be->max_categories,
+ sizeof(struct slc_v1_rcp_s)))
+ return -1;
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_slc_free(struct flow_api_backend_s *be)
+{
+ if (be->slc.base) {
+ free(be->slc.base);
+ be->slc.base = NULL;
+ }
+}
+
+int hw_mod_slc_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->slc);
+
+ NT_LOG(DBG, FILTER, "INIT SLC RCP\n");
+ return hw_mod_slc_rcp_flush(be, 0, be->max_categories);
+}
+
+int hw_mod_slc_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->max_categories;
+ if ((unsigned int)(start_idx + count) > be->max_categories)
+ return error_index_too_large(__func__);
+ return be->iface->slc_rcp_flush(be->be_dev, &be->slc, start_idx, count);
+}
+
+static int hw_mod_slc_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_slc_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->max_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ switch (field) {
+ case HW_SLC_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->slc.v1.rcp[index], (uint8_t)*value,
+ sizeof(struct hw_mod_slc_v1_s));
+ break;
+ case HW_SLC_RCP_FIND:
+ rv = find_equal_index(be->slc.v1.rcp,
+ sizeof(struct hw_mod_slc_v1_s), index, *value,
+ be->max_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_RCP_COMPARE:
+ rv = do_compare_indexes(be->slc.v1.rcp,
+ sizeof(struct hw_mod_slc_v1_s), index, *value,
+ be->max_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_RCP_SLC_EN:
+ get_set(&be->slc.v1.rcp[index].tail_slc_en, value, get);
+ break;
+ case HW_SLC_RCP_DYN:
+ get_set(&be->slc.v1.rcp[index].tail_dyn, value, get);
+ break;
+ case HW_SLC_RCP_OFS:
+ get_set_signed(&be->slc.v1.rcp[index].tail_ofs, value, get);
+ break;
+ case HW_SLC_RCP_PCAP:
+ get_set(&be->slc.v1.rcp[index].pcap, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_slc_rcp_set(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_slc_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_slc_rcp_get(struct flow_api_backend_s *be, enum hw_slc_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_slc_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
new file mode 100644
index 0000000000..9f40563e8a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "SLC_LR"
+#define _VER_ be->slc_lr.ver
+
+bool hw_mod_slc_lr_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_slc_lr_present(be->be_dev);
+}
+
+int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be)
+{
+ _VER_ = be->iface->get_slc_lr_version(be->be_dev);
+ NT_LOG(DBG, FILTER, "SLC LR MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ switch (_VER_) {
+ case 2:
+ if (!callocate_mod(CAST_COMMON(&be->slc_lr), 1,
+ &be->slc_lr.v2.rcp,
+ be->max_categories,
+ sizeof(struct slc_lr_v2_rcp_s)))
+ return -1;
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_slc_lr_free(struct flow_api_backend_s *be)
+{
+ if (be->slc_lr.base) {
+ free(be->slc_lr.base);
+ be->slc_lr.base = NULL;
+ }
+}
+
+int hw_mod_slc_lr_reset(struct flow_api_backend_s *be)
+{
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->slc_lr);
+
+ NT_LOG(DBG, FILTER, "INIT SLC LR RCP\n");
+ return hw_mod_slc_lr_rcp_flush(be, 0, be->max_categories);
+}
+
+int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->max_categories;
+ if ((unsigned int)(start_idx + count) > be->max_categories)
+ return error_index_too_large(__func__);
+ return be->iface->slc_lr_rcp_flush(be->be_dev, &be->slc_lr, start_idx,
+ count);
+}
+
+static int hw_mod_slc_lr_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_slc_lr_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->max_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_SLC_LR_RCP_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->slc_lr.v2.rcp[index], (uint8_t)*value,
+ sizeof(struct hw_mod_slc_lr_v2_s));
+ break;
+ case HW_SLC_LR_RCP_FIND:
+ rv = find_equal_index(be->slc_lr.v2.rcp,
+ sizeof(struct hw_mod_slc_lr_v2_s), index, *value,
+ be->max_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_LR_RCP_COMPARE:
+ rv = do_compare_indexes(be->slc_lr.v2.rcp,
+ sizeof(struct hw_mod_slc_lr_v2_s), index, *value,
+ be->max_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_SLC_LR_RCP_SLC_EN:
+ get_set(&be->slc_lr.v2.rcp[index].tail_slc_en, value, get);
+ break;
+ case HW_SLC_LR_RCP_DYN:
+ get_set(&be->slc_lr.v2.rcp[index].tail_dyn, value, get);
+ break;
+ case HW_SLC_LR_RCP_OFS:
+ get_set_signed(&be->slc_lr.v2.rcp[index].tail_ofs,
+ value, get);
+ break;
+ case HW_SLC_LR_RCP_PCAP:
+ get_set(&be->slc_lr.v2.rcp[index].pcap, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t value)
+{
+ return hw_mod_slc_lr_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_slc_lr_rcp_get(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t *value)
+{
+ return hw_mod_slc_lr_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h
new file mode 100644
index 0000000000..d03b206e6d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr_v2.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_SLC_LR_V2_H_
+#define _HW_MOD_SLC_LR_V2_H_
+
+struct slc_lr_v2_rcp_s {
+ uint32_t tail_slc_en;
+ uint32_t tail_dyn;
+ int32_t tail_ofs;
+ uint32_t pcap;
+};
+
+struct hw_mod_slc_lr_v2_s {
+ struct slc_lr_v2_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_SLC_V2_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h
new file mode 100644
index 0000000000..01f60bfb18
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_v1.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_SLC_V1_H_
+#define _HW_MOD_SLC_V1_H_
+
+struct slc_v1_rcp_s {
+ uint32_t tail_slc_en;
+ uint32_t tail_dyn;
+ int32_t tail_ofs;
+ uint32_t pcap;
+};
+
+struct hw_mod_slc_v1_s {
+ struct slc_v1_rcp_s *rcp;
+};
+
+#endif /* _HW_MOD_SLC_V1_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c
new file mode 100644
index 0000000000..dd6f06b2c4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe.c
@@ -0,0 +1,983 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "flow_api_backend.h"
+
+#define _MOD_ "TPE"
+#define _VER_ be->tpe.ver
+
+bool hw_mod_tpe_present(struct flow_api_backend_s *be)
+{
+ return be->iface->get_tpe_present(be->be_dev);
+}
+
+int hw_mod_tpe_alloc(struct flow_api_backend_s *be)
+{
+ int nb;
+
+ _VER_ = be->iface->get_tpe_version(be->be_dev);
+ NT_LOG(DBG, FILTER, _MOD_ " MODULE VERSION %i.%i\n", VER_MAJOR(_VER_),
+ VER_MINOR(_VER_));
+
+ nb = be->iface->get_nb_tpe_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tpe_categories", _MOD_, _VER_);
+ be->tpe.nb_rcp_categories = (uint32_t)nb;
+
+ be->tpe.nb_ifr_categories = 0;
+ if (_VER_ > 1) {
+ nb = be->iface->get_nb_tpe_ifr_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tpe_ifr_categories", _MOD_, _VER_);
+ be->tpe.nb_ifr_categories = (uint32_t)nb;
+ }
+
+ nb = be->iface->get_nb_tx_cpy_writers(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tx_cpy_writers", _MOD_, _VER_);
+ be->tpe.nb_cpy_writers = (uint32_t)nb;
+
+ nb = be->iface->get_nb_tx_rpl_depth(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tx_rpl_depth", _MOD_, _VER_);
+ be->tpe.nb_rpl_depth = (uint32_t)nb;
+
+ nb = be->iface->get_nb_tx_rpl_ext_categories(be->be_dev);
+ if (nb <= 0)
+ return error_resource_count(__func__, "tx_rpl_ext_categories", _MOD_, _VER_);
+ be->tpe.nb_rpl_ext_categories = (uint32_t)nb;
+
+ switch (_VER_) {
+ case 1:
+ if (!callocate_mod(CAST_COMMON(&be->tpe), 8,
+ &be->tpe.v1.rpp_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s),
+ &be->tpe.v1.ins_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_ins_v1_rcp_s),
+ &be->tpe.v1.rpl_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s),
+ &be->tpe.v1.rpl_ext, be->tpe.nb_rpl_ext_categories,
+ sizeof(struct tpe_v1_rpl_v2_ext_s),
+ &be->tpe.v1.rpl_rpl, be->tpe.nb_rpl_depth,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s),
+ &be->tpe.v1.cpy_rcp,
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s),
+ &be->tpe.v1.hfu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s),
+ &be->tpe.v1.csu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_csu_v0_rcp_s)))
+ return -1;
+ break;
+ case 2:
+ if (!callocate_mod(CAST_COMMON(&be->tpe), 10,
+ &be->tpe.v2.rpp_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s),
+ &be->tpe.v2.rpp_ifr_rcp, be->tpe.nb_ifr_categories,
+ sizeof(struct tpe_v2_rpp_v1_ifr_rcp_s),
+ &be->tpe.v2.ifr_rcp, be->tpe.nb_ifr_categories,
+ sizeof(struct tpe_v2_ifr_v1_rcp_s),
+ &be->tpe.v2.ins_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_ins_v1_rcp_s),
+ &be->tpe.v2.rpl_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s),
+ &be->tpe.v2.rpl_ext, be->tpe.nb_rpl_ext_categories,
+ sizeof(struct tpe_v1_rpl_v2_ext_s),
+ &be->tpe.v2.rpl_rpl, be->tpe.nb_rpl_depth,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s),
+ &be->tpe.v2.cpy_rcp,
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s),
+ &be->tpe.v2.hfu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s),
+ &be->tpe.v2.csu_rcp, be->tpe.nb_rcp_categories,
+ sizeof(struct tpe_v1_csu_v0_rcp_s)))
+ return -1;
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+void hw_mod_tpe_free(struct flow_api_backend_s *be)
+{
+ if (be->tpe.base) {
+ free(be->tpe.base);
+ be->tpe.base = NULL;
+ }
+}
+
+int hw_mod_tpe_reset(struct flow_api_backend_s *be)
+{
+ int err = 0;
+
+ /* Zero entire cache area */
+ ZERO_MOD_CACHE(&be->tpe);
+
+ NT_LOG(DBG, FILTER, "INIT TPE\n");
+ err |= hw_mod_tpe_rpp_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_ins_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_rpl_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_rpl_ext_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_rpl_rpl_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_cpy_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_hfu_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_csu_rcp_flush(be, 0, ALL_ENTRIES);
+
+ if (_VER_ == 2) {
+ err |= hw_mod_tpe_rpp_ifr_rcp_flush(be, 0, ALL_ENTRIES);
+ err |= hw_mod_tpe_ifr_rcp_flush(be, 0, ALL_ENTRIES);
+ }
+
+ return err;
+}
+
+/*
+ * RPP_IFR_RCP
+ */
+
+int hw_mod_tpe_rpp_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_ifr_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpp_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpp_ifr_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_TPE_IFR_RCP_EN:
+ get_set(&be->tpe.v2.rpp_ifr_rcp[index].en, value, get);
+ break;
+
+ case HW_TPE_IFR_RCP_MTU:
+ get_set(&be->tpe.v2.rpp_ifr_rcp[index].mtu, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpp_ifr_rcp_set(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t value)
+{
+ return hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpp_ifr_rcp_get(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpp_ifr_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPP_RCP
+ */
+
+int hw_mod_tpe_rpp_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpp_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpp_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpp_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpp_rcp,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpp_rcp,
+ sizeof(struct tpe_v1_rpp_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPP_RCP_EXP:
+ get_set(&be->tpe.v1.rpp_rcp[index].exp, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpp_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_rpp_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpp_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpp_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * IFR_RCP
+ */
+
+int hw_mod_tpe_ifr_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_ifr_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_ifr_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_ifr_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ if (index >= be->tpe.nb_ifr_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_TPE_IFR_RCP_EN:
+ get_set(&be->tpe.v2.ifr_rcp[index].en, value, get);
+ break;
+
+ case HW_TPE_IFR_RCP_MTU:
+ get_set(&be->tpe.v2.ifr_rcp[index].mtu, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_ifr_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_ifr_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_ifr_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_ifr_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * INS_RCP
+ */
+
+int hw_mod_tpe_ins_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_ins_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_ins_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.ins_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_ins_v1_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.ins_rcp,
+ sizeof(struct tpe_v1_ins_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.ins_rcp,
+ sizeof(struct tpe_v1_ins_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_INS_RCP_DYN:
+ get_set(&be->tpe.v1.ins_rcp[index].dyn, value, get);
+ break;
+ case HW_TPE_INS_RCP_OFS:
+ get_set(&be->tpe.v1.ins_rcp[index].ofs, value, get);
+ break;
+ case HW_TPE_INS_RCP_LEN:
+ get_set(&be->tpe.v1.ins_rcp[index].len, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_ins_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_ins_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_ins_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_ins_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPL_RCP
+ */
+
+int hw_mod_tpe_rpl_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpl_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpl_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpl_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpl_rcp,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpl_rcp,
+ sizeof(struct tpe_v1_rpl_v2_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPL_RCP_DYN:
+ get_set(&be->tpe.v1.rpl_rcp[index].dyn, value, get);
+ break;
+ case HW_TPE_RPL_RCP_OFS:
+ get_set(&be->tpe.v1.rpl_rcp[index].ofs, value, get);
+ break;
+ case HW_TPE_RPL_RCP_LEN:
+ get_set(&be->tpe.v1.rpl_rcp[index].len, value, get);
+ break;
+ case HW_TPE_RPL_RCP_RPL_PTR:
+ get_set(&be->tpe.v1.rpl_rcp[index].rpl_ptr, value, get);
+ break;
+ case HW_TPE_RPL_RCP_EXT_PRIO:
+ get_set(&be->tpe.v1.rpl_rcp[index].ext_prio, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpl_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_rpl_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpl_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPL_EXT
+ */
+
+int hw_mod_tpe_rpl_ext_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rpl_ext_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_ext_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpl_ext_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpl_ext_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rpl_ext_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpl_ext[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpl_v2_ext_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpl_ext,
+ sizeof(struct tpe_v1_rpl_v2_ext_s), index, *value,
+ be->tpe.nb_rpl_ext_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpl_ext,
+ sizeof(struct tpe_v1_rpl_v2_ext_s), index, *value,
+ be->tpe.nb_rpl_ext_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPL_EXT_RPL_PTR:
+ get_set(&be->tpe.v1.rpl_ext[index].rpl_ptr, value, get);
+ break;
+ case HW_TPE_RPL_EXT_META_RPL_LEN:
+ get_set(&be->tpe.v1.rpl_ext[index].meta_rpl_len, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpl_ext_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_rpl_ext_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_rpl_ext_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_ext_mod(be, field, index, value, 1);
+}
+
+/*
+ * RPL_RPL
+ */
+
+int hw_mod_tpe_rpl_rpl_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rpl_depth;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rpl_depth)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_rpl_rpl_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_rpl_rpl_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rpl_depth)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.rpl_rpl[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.rpl_rpl,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value,
+ be->tpe.nb_rpl_depth, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.rpl_rpl,
+ sizeof(struct tpe_v1_rpl_v2_rpl_s), index, *value,
+ be->tpe.nb_rpl_depth, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_RPL_RPL_VALUE:
+ if (get)
+ memcpy(value, be->tpe.v1.rpl_rpl[index].value,
+ sizeof(uint32_t) * 4);
+ else
+ memcpy(be->tpe.v1.rpl_rpl[index].value, value,
+ sizeof(uint32_t) * 4);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_rpl_rpl_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 0);
+}
+
+int hw_mod_tpe_rpl_rpl_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_rpl_rpl_mod(be, field, index, value, 1);
+}
+
+/*
+ * CPY_RCP
+ */
+
+int hw_mod_tpe_cpy_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ const uint32_t cpy_size =
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories;
+ if (count == ALL_ENTRIES)
+ count = cpy_size;
+ if ((unsigned int)(start_idx + count) > cpy_size)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_cpy_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_cpy_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ const uint32_t cpy_size =
+ be->tpe.nb_cpy_writers * be->tpe.nb_rcp_categories;
+ int rv = 0;
+ if (index >= cpy_size)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.cpy_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.cpy_rcp,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value,
+ cpy_size, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.cpy_rcp,
+ sizeof(struct tpe_v1_cpy_v1_rcp_s), index, *value,
+ cpy_size, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_CPY_RCP_READER_SELECT:
+ get_set(&be->tpe.v1.cpy_rcp[index].reader_select, value, get);
+ break;
+ case HW_TPE_CPY_RCP_DYN:
+ get_set(&be->tpe.v1.cpy_rcp[index].dyn, value, get);
+ break;
+ case HW_TPE_CPY_RCP_OFS:
+ get_set(&be->tpe.v1.cpy_rcp[index].ofs, value, get);
+ break;
+ case HW_TPE_CPY_RCP_LEN:
+ get_set(&be->tpe.v1.cpy_rcp[index].len, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_cpy_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_cpy_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_cpy_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_cpy_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * HFU_RCP
+ */
+
+int hw_mod_tpe_hfu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_hfu_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_hfu_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.hfu_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.hfu_rcp,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.hfu_rcp,
+ sizeof(struct tpe_v1_hfu_v1_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_OUTER_L4_LEN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_outer_l4_len,
+ value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_pos_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_ADD_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_add_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_ADD_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_add_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_A_SUB_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_a_sub_dyn, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_LEN_B_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_pos_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_ADD_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_add_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_ADD_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_add_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_B_SUB_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_b_sub_dyn, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_LEN_C_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_pos_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_ADD_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_add_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_ADD_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_add_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_LEN_C_SUB_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].len_c_sub_dyn, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_TTL_WR:
+ get_set(&be->tpe.v1.hfu_rcp[index].ttl_wr, value, get);
+ break;
+ case HW_TPE_HFU_RCP_TTL_POS_DYN:
+ get_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_dyn, value, get);
+ break;
+ case HW_TPE_HFU_RCP_TTL_POS_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].ttl_pos_ofs, value, get);
+ break;
+
+ case HW_TPE_HFU_RCP_CS_INF:
+ get_set(&be->tpe.v1.hfu_rcp[index].cs_inf, value, get);
+ break;
+ case HW_TPE_HFU_RCP_L3_PRT:
+ get_set(&be->tpe.v1.hfu_rcp[index].l3_prt, value, get);
+ break;
+ case HW_TPE_HFU_RCP_L3_FRAG:
+ get_set(&be->tpe.v1.hfu_rcp[index].l3_frag, value, get);
+ break;
+ case HW_TPE_HFU_RCP_TUNNEL:
+ get_set(&be->tpe.v1.hfu_rcp[index].tunnel, value, get);
+ break;
+ case HW_TPE_HFU_RCP_L4_PRT:
+ get_set(&be->tpe.v1.hfu_rcp[index].l4_prt, value, get);
+ break;
+ case HW_TPE_HFU_RCP_OUTER_L3_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].outer_l3_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_OUTER_L4_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].outer_l4_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_INNER_L3_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].inner_l3_ofs, value, get);
+ break;
+ case HW_TPE_HFU_RCP_INNER_L4_OFS:
+ get_set(&be->tpe.v1.hfu_rcp[index].inner_l4_ofs, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_hfu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_hfu_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_hfu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_hfu_rcp_mod(be, field, index, value, 1);
+}
+
+/*
+ * CSU_RCP
+ */
+
+int hw_mod_tpe_csu_rcp_flush(struct flow_api_backend_s *be, int start_idx,
+ int count)
+{
+ if (count == ALL_ENTRIES)
+ count = be->tpe.nb_rcp_categories;
+ if ((unsigned int)(start_idx + count) > be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ return be->iface->tpe_csu_rcp_flush(be->be_dev, &be->tpe, start_idx,
+ count);
+}
+
+static int hw_mod_tpe_csu_rcp_mod(struct flow_api_backend_s *be,
+ enum hw_tpe_e field, uint32_t index,
+ uint32_t *value, int get)
+{
+ int rv = 0;
+ if (index >= be->tpe.nb_rcp_categories)
+ return error_index_too_large(__func__);
+ switch (_VER_) {
+ case 1:
+ case 2:
+ switch (field) {
+ case HW_TPE_PRESET_ALL:
+ if (get)
+ return error_unsup_field(__func__);
+ memset(&be->tpe.v1.csu_rcp[index], (uint8_t)*value,
+ sizeof(struct tpe_v1_csu_v0_rcp_s));
+ break;
+ case HW_TPE_FIND:
+ rv = find_equal_index(be->tpe.v1.csu_rcp,
+ sizeof(struct tpe_v1_csu_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, value, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_COMPARE:
+ rv = do_compare_indexes(be->tpe.v1.csu_rcp,
+ sizeof(struct tpe_v1_csu_v0_rcp_s), index, *value,
+ be->tpe.nb_rcp_categories, get, __func__);
+ if (rv != 0)
+ return rv;
+ break;
+ case HW_TPE_CSU_RCP_OUTER_L3_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].ol3_cmd, value, get);
+ break;
+ case HW_TPE_CSU_RCP_OUTER_L4_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].ol4_cmd, value, get);
+ break;
+ case HW_TPE_CSU_RCP_INNER_L3_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].il3_cmd, value, get);
+ break;
+ case HW_TPE_CSU_RCP_INNER_L4_CMD:
+ get_set(&be->tpe.v1.csu_rcp[index].il4_cmd, value, get);
+ break;
+
+ default:
+ return error_unsup_field(__func__);
+ }
+ break;
+ /* end case 1 */
+ default:
+ return error_unsup_ver(__func__, _MOD_, _VER_);
+ }
+
+ return 0;
+}
+
+int hw_mod_tpe_csu_rcp_set(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t value)
+{
+ return hw_mod_tpe_csu_rcp_mod(be, field, index, &value, 0);
+}
+
+int hw_mod_tpe_csu_rcp_get(struct flow_api_backend_s *be, enum hw_tpe_e field,
+ int index, uint32_t *value)
+{
+ return hw_mod_tpe_csu_rcp_mod(be, field, index, value, 1);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h
new file mode 100644
index 0000000000..dacd819659
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v1.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_TPE_V1_H_
+#define _HW_MOD_TPE_V1_H_
+
+struct tpe_v1_rpp_v0_rcp_s {
+ uint32_t exp;
+};
+
+struct tpe_v1_ins_v1_rcp_s {
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+};
+
+struct tpe_v1_rpl_v2_rcp_s {
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+ uint32_t rpl_ptr;
+ uint32_t ext_prio;
+};
+
+struct tpe_v1_rpl_v2_ext_s {
+ uint32_t rpl_ptr;
+ uint32_t meta_rpl_len; /* SW only */
+};
+
+struct tpe_v1_rpl_v2_rpl_s {
+ uint32_t value[4];
+};
+
+struct tpe_v1_cpy_v1_rcp_s {
+ uint32_t reader_select;
+ uint32_t dyn;
+ uint32_t ofs;
+ uint32_t len;
+};
+
+struct tpe_v1_hfu_v1_rcp_s {
+ uint32_t len_a_wr;
+ uint32_t len_a_outer_l4_len;
+ uint32_t len_a_pos_dyn;
+ uint32_t len_a_pos_ofs;
+ uint32_t len_a_add_dyn;
+ uint32_t len_a_add_ofs;
+ uint32_t len_a_sub_dyn;
+
+ uint32_t len_b_wr;
+ uint32_t len_b_pos_dyn;
+ uint32_t len_b_pos_ofs;
+ uint32_t len_b_add_dyn;
+ uint32_t len_b_add_ofs;
+ uint32_t len_b_sub_dyn;
+
+ uint32_t len_c_wr;
+ uint32_t len_c_pos_dyn;
+ uint32_t len_c_pos_ofs;
+ uint32_t len_c_add_dyn;
+ uint32_t len_c_add_ofs;
+ uint32_t len_c_sub_dyn;
+
+ uint32_t ttl_wr;
+ uint32_t ttl_pos_dyn;
+ uint32_t ttl_pos_ofs;
+
+ uint32_t cs_inf;
+ uint32_t l3_prt;
+ uint32_t l3_frag;
+ uint32_t tunnel;
+ uint32_t l4_prt;
+ uint32_t outer_l3_ofs;
+ uint32_t outer_l4_ofs;
+ uint32_t inner_l3_ofs;
+ uint32_t inner_l4_ofs;
+};
+
+struct tpe_v1_csu_v0_rcp_s {
+ uint32_t ol3_cmd;
+ uint32_t ol4_cmd;
+ uint32_t il3_cmd;
+ uint32_t il4_cmd;
+};
+
+struct hw_mod_tpe_v1_s {
+ struct tpe_v1_rpp_v0_rcp_s *rpp_rcp;
+
+ struct tpe_v1_ins_v1_rcp_s *ins_rcp;
+
+ struct tpe_v1_rpl_v2_rcp_s *rpl_rcp;
+ struct tpe_v1_rpl_v2_ext_s *rpl_ext;
+ struct tpe_v1_rpl_v2_rpl_s *rpl_rpl;
+
+ struct tpe_v1_cpy_v1_rcp_s *cpy_rcp;
+
+ struct tpe_v1_hfu_v1_rcp_s *hfu_rcp;
+
+ struct tpe_v1_csu_v0_rcp_s *csu_rcp;
+};
+
+#endif /* _HW_MOD_TPE_V1_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h
new file mode 100644
index 0000000000..c56cad8d89
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_tpe_v2.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _HW_MOD_TPE_V2_H_
+#define _HW_MOD_TPE_V2_H_
+
+struct tpe_v2_rpp_v1_ifr_rcp_s {
+ uint32_t en;
+ uint32_t mtu;
+};
+
+struct tpe_v2_ifr_v1_rcp_s {
+ uint32_t en;
+ uint32_t mtu;
+};
+
+struct hw_mod_tpe_v2_s {
+ struct tpe_v1_rpp_v0_rcp_s *rpp_rcp;
+
+ struct tpe_v1_ins_v1_rcp_s *ins_rcp;
+
+ struct tpe_v1_rpl_v2_rcp_s *rpl_rcp;
+ struct tpe_v1_rpl_v2_ext_s *rpl_ext;
+ struct tpe_v1_rpl_v2_rpl_s *rpl_rpl;
+
+ struct tpe_v1_cpy_v1_rcp_s *cpy_rcp;
+
+ struct tpe_v1_hfu_v1_rcp_s *hfu_rcp;
+
+ struct tpe_v1_csu_v0_rcp_s *csu_rcp;
+
+ struct tpe_v2_rpp_v1_ifr_rcp_s *rpp_ifr_rcp;
+ struct tpe_v2_ifr_v1_rcp_s *ifr_rcp;
+};
+
+#endif /* _HW_MOD_TPE_V2_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h
new file mode 100644
index 0000000000..eae8f176a8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/stream_binary_flow_api.h
@@ -0,0 +1,697 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _STREAM_BINARY_FLOW_API_H_
+#define _STREAM_BINARY_FLOW_API_H_
+
+#include <stdint.h> /* uint16_t, uint32_t, uint64_t */
+#include <stdio.h> /* snprintf */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t be16_t; /* 16-bit big-endian */
+typedef uint32_t be32_t; /* 32-bit big-endian */
+typedef uint64_t be64_t; /* 64-bit big-endian */
+
+/*
+ * Flow frontend for binary programming interface
+ */
+
+#define FLOW_MAX_QUEUES 128
+
+#define RAW_ENCAP_DECAP_ELEMS_MAX 16
+
+/*
+ * Partial flow mark and special flow marks
+ */
+#define FLOW_MARK_LACP 0x7fffffff
+#define FLOW_MARK_MAX 0x7ffffffe
+/*
+ * Flow eth dev profile determines how the FPGA module resources are
+ * managed and what features are available
+ */
+enum flow_eth_dev_profile {
+ FLOW_ETH_DEV_PROFILE_VSWITCH = 0,
+ FLOW_ETH_DEV_PROFILE_INLINE = 1,
+};
+
+/*
+ * Flow rule attributes
+ */
+struct flow_attr {
+ uint32_t group; /* Priority group. */
+ uint32_t priority; /* Rule priority level within group. */
+ uint16_t forced_vlan_vid; /* Forced VLAN VID that filter must match. Ignored if 0. */
+ uint8_t caller_id; /* Unique ID of caller application. */
+};
+
+struct flow_queue_id_s {
+ int id;
+ int hw_id;
+};
+
+/* NT Private rte flow items. */
+
+/* NT Private rte flow actions. */
+
+enum flow_elem_type {
+ FLOW_ELEM_TYPE_END,
+ FLOW_ELEM_TYPE_ANY,
+ FLOW_ELEM_TYPE_ETH,
+ FLOW_ELEM_TYPE_VLAN,
+ FLOW_ELEM_TYPE_IPV4,
+ FLOW_ELEM_TYPE_IPV6,
+ FLOW_ELEM_TYPE_SCTP,
+ FLOW_ELEM_TYPE_TCP,
+ FLOW_ELEM_TYPE_UDP,
+ FLOW_ELEM_TYPE_ICMP,
+ FLOW_ELEM_TYPE_VXLAN,
+ FLOW_ELEM_TYPE_GTP,
+ FLOW_ELEM_TYPE_PORT_ID,
+ FLOW_ELEM_TYPE_TAG,
+ FLOW_ELEM_TYPE_VOID,
+
+ /*
+ * Not associated with a RTE_ITEM..., but rather an restoration API device specific
+ * extension
+ */
+ FLOW_ELEM_TYPE_TUNNEL
+};
+
+enum flow_action_type { /* conf structure */
+ FLOW_ACTION_TYPE_END, /* -none- : End tag for action list */
+ FLOW_ACTION_TYPE_POP_VLAN, /* -none- : Pops outer vlan tag */
+ FLOW_ACTION_TYPE_PUSH_VLAN, /* struct flow_action_push_vlan : Push VLAN TAG */
+ FLOW_ACTION_TYPE_SET_VLAN_VID, /* struct flow_action_set_vlan_vid : Set VLAN VID */
+ FLOW_ACTION_TYPE_SET_VLAN_PCP, /* struct flow_action_set_vlan_pcp : Set VLAN PCP */
+ /* -none- : Decapsulate outer most VXLAN tunnel from matched flow */
+ FLOW_ACTION_TYPE_VXLAN_DECAP,
+ FLOW_ACTION_TYPE_VXLAN_ENCAP, /* struct flow_action_vxlan_encap */
+ FLOW_ACTION_TYPE_DROP, /* -none- : Drop packets of this flow */
+ FLOW_ACTION_TYPE_COUNT, /* struct flow_action_count : Used for "query" flow function */
+ FLOW_ACTION_TYPE_MARK, /* struct flow_action_mark : Used to tag a flow in HW with a MARK */
+ FLOW_ACTION_TYPE_SET_TAG, /* struct flow_action_tag : Used to tag a flow in HW with a TAG */
+ /* struct flow_action_port_id : Destination port ID - HW port ID */
+ FLOW_ACTION_TYPE_PORT_ID,
+ FLOW_ACTION_TYPE_RSS, /* struct flow_action_rss : */
+ FLOW_ACTION_TYPE_QUEUE, /* struct flow_action_queue : */
+ FLOW_ACTION_TYPE_JUMP, /* struct flow_action_jump : */
+ /* struct flow_action_meter : Used to set MBR record ids in FLM learn records */
+ FLOW_ACTION_TYPE_METER,
+ FLOW_ACTION_TYPE_RAW_ENCAP, /* struct flow_action_raw_encap : */
+ FLOW_ACTION_TYPE_RAW_DECAP, /* struct flow_action_raw_decap : */
+ FLOW_ACTION_TYPE_MODIFY_FIELD, /* struct flow_action_modify_field : */
+
+ /*
+ * -none- : not associated with a RTE_ACTION..., but rather an restoration API device
+ * specific extension
+ */
+ FLOW_ACTION_TYPE_TUNNEL_SET
+};
+
+#pragma pack(1)
+struct ether_addr_s {
+ uint8_t addr_b[6];
+};
+
+#pragma pack()
+
+static inline void flow_ether_format_addr(char *buf, uint16_t size,
+ const struct ether_addr_s *eth_addr)
+{
+ snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X",
+ eth_addr->addr_b[0], eth_addr->addr_b[1], eth_addr->addr_b[2],
+ eth_addr->addr_b[3], eth_addr->addr_b[4], eth_addr->addr_b[5]);
+}
+
+/*
+ * IPv4 Header
+ */
+#pragma pack(1)
+struct ipv4_hdr_s {
+ uint8_t version_ihl;
+ uint8_t tos;
+ be16_t length;
+ be16_t id;
+ be16_t frag_offset;
+ uint8_t ttl;
+ uint8_t next_proto_id;
+ be16_t hdr_csum;
+ be32_t src_ip;
+ be32_t dst_ip;
+};
+
+#pragma pack()
+/*
+ * IPv6 Header
+ */
+#pragma pack(1)
+struct ipv6_hdr_s {
+ be32_t vtc_flow; /* IP version, traffic class & flow label */
+ be16_t payload_len; /* IP packet length - includes ip header */
+ uint8_t proto;
+ uint8_t hop_limits;
+ uint8_t src_addr[16];
+ uint8_t dst_addr[16];
+};
+
+#pragma pack()
+
+/*
+ * SCTP Header
+ */
+#pragma pack(1)
+struct sctp_hdr_s {
+ be16_t src_port;
+ be16_t dst_port;
+ be32_t tag; /* Validation tag */
+ be32_t cksum;
+};
+
+#pragma pack()
+
+/*
+ * TCP Header
+ */
+#pragma pack(1)
+struct tcp_hdr_s {
+ be16_t src_port;
+ be16_t dst_port;
+ be32_t sent_seq;
+ be32_t recv_ack;
+ uint8_t data_off;
+ uint8_t tcp_flags;
+ be16_t rx_win;
+ be16_t cksum;
+ be16_t tcp_urp;
+};
+
+#pragma pack()
+
+/*
+ * UDP Header
+ */
+#pragma pack(1)
+struct udp_hdr_s {
+ be16_t src_port;
+ be16_t dst_port;
+ be16_t len;
+ be16_t cksum;
+};
+
+#pragma pack()
+
+/*
+ * ICMP Header
+ */
+#pragma pack(1)
+struct icmp_hdr_s {
+ uint8_t type;
+ uint8_t code;
+ be16_t cksum;
+ be16_t ident;
+ be16_t seq_nb;
+};
+
+#pragma pack()
+/*
+ * FLOW_ELEM_TYPE_ETH specification
+ */
+#pragma pack(1)
+struct flow_elem_eth {
+ struct ether_addr_s d_addr; /* DMAC */
+ struct ether_addr_s s_addr; /* SMAC */
+ be16_t ether_type; /* Frame type */
+};
+
+#pragma pack()
+
+/*
+ * FLOW_ELEM_TYPE_VLAN specification
+ */
+#pragma pack(1)
+struct flow_elem_vlan {
+ be16_t tci; /* Tag control information */
+ be16_t inner_type; /* Inner EtherType or TPID */
+};
+
+#pragma pack()
+
+/*
+ * FLOW_ELEM_TYPE_IPV4 specification
+ */
+struct flow_elem_ipv4 {
+ struct ipv4_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_IPV6 specification
+ */
+struct flow_elem_ipv6 {
+ struct ipv6_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_SCTP specification
+ */
+struct flow_elem_sctp {
+ struct sctp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_TCP specification
+ */
+struct flow_elem_tcp {
+ struct tcp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_UDP specification
+ */
+struct flow_elem_udp {
+ struct udp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_ICMP specification
+ */
+struct flow_elem_icmp {
+ struct icmp_hdr_s hdr;
+};
+
+/*
+ * FLOW_ELEM_TYPE_GTP specification
+ */
+#pragma pack(1)
+struct flow_elem_gtp {
+ uint8_t v_pt_rsv_flags;
+ uint8_t msg_type;
+ be16_t msg_len;
+ be32_t teid;
+};
+
+#pragma pack()
+
+/*
+ * FLOW_ELEM_TYPE_VXLAN specification (RFC 7348)
+ */
+#pragma pack(1)
+struct flow_elem_vxlan {
+ uint8_t flags; /* Normally 0x08 (I flag) */
+ uint8_t rsvd0[3];
+ uint8_t vni[3];
+ uint8_t rsvd1;
+};
+
+#pragma pack()
+/*
+ * FLOW_ELEM_TYPE_PORT_ID specification
+ */
+struct flow_elem_port_id {
+ uint32_t id; /* HW port no */
+};
+
+/*
+ * FLOW_ELEM_TYPE_TAG specification
+ */
+struct flow_elem_tag {
+ uint32_t data;
+ uint8_t index;
+};
+
+/*
+ * FLOW_ELEM_TYPE_ANY specification
+ */
+struct flow_elem_any {
+ uint32_t num; /**< Number of layers covered. */
+};
+
+struct flow_elem {
+ enum flow_elem_type type; /* element type */
+ const void *spec; /* Pointer to element specification structure */
+ const void *mask; /* Bitmask applied to spec - same type */
+};
+
+/*
+ * FLOW_ACTION_TYPE_RSS
+ */
+enum flow_hash_function {
+ FLOW_HASH_FUNCTION_DEFAULT = 0,
+ FLOW_HASH_FUNCTION_TOEPLITZ, /* Unsupported in current supported FPGA */
+ FLOW_HASH_FUNCTION_SIMPLE_XOR /* Simple XOR - not supported */
+};
+
+struct flow_action_rss {
+ enum flow_hash_function func;
+ uint32_t level; /* only level 0 supported */
+ /* Specific RSS hash types (see like DPDK ETH_RSS_*) */
+ uint64_t types;
+ uint32_t key_len; /* Not supported yet - Hash key length in bytes */
+ uint32_t queue_num; /* Number of entries in queue */
+ const uint8_t *key; /* Not supported yet - Hash key */
+ const uint16_t *queue; /* Queue indices to use */
+};
+
+/*
+ * FLOW_ACTION_TYPE_PUSH_VLAN
+ * Push a new vlan TAG
+ */
+struct flow_action_push_vlan {
+ be16_t ethertype;
+};
+
+/*
+ * FLOW_ACTION_TYPE_SET_VLAN_VID
+ */
+struct flow_action_set_vlan_vid {
+ be16_t vlan_vid;
+};
+
+/*
+ * FLOW_ACTION_TYPE_SET_VLAN_PCP
+ */
+struct flow_action_set_vlan_pcp {
+ uint8_t vlan_pcp; /* < VLAN priority. */
+};
+
+/*
+ * FLOW_ACTION_TYPE_VXLAN_ENCAP specification
+ * Valid flow definition:
+ *
+ * - ETH / IPV4 / UDP / VXLAN / END
+ * - ETH / IPV6 / UDP / VXLAN / END
+ * - ETH / VLAN / IPV4 / UDP / VXLAN / END
+ *
+ */
+struct flow_action_vxlan_encap {
+ /* Encapsulating vxlan tunnel definition */
+ struct flow_elem *vxlan_tunnel;
+};
+
+/*
+ * FLOW_ACTION_TYPE_COUNT specification
+ */
+struct flow_action_count {
+ uint32_t id; /* HW port no */
+};
+
+/*
+ * FLOW_ACTION_TYPE_COUNT specification (query)
+ */
+struct flow_query_count {
+ uint32_t reset : 1;
+ uint32_t hits_set : 1;
+ uint32_t bytes_set : 1;
+
+ uint32_t tcp_flags : 9;
+
+ uint32_t reserved : 20;
+ uint64_t hits;
+ uint64_t bytes;
+};
+
+/*
+ * FLOW_ACTION_TYPE_MARK specification
+ */
+struct flow_action_mark {
+ uint32_t id; /* mark flow with this ID */
+};
+
+/*
+ * FLOW_ACTION_TYPE_TAG specification
+ */
+struct flow_action_tag {
+ uint32_t data; /* tag flow with this value */
+ uint32_t mask; /* bit-mask applied to "data" */
+ uint8_t index; /* index of tag to set */
+};
+
+/*
+ * FLOW_ACTION_TYPE_PORT_ID specification
+ */
+struct flow_action_port_id {
+ uint32_t rte_flags; /* not used but to be binary compatible with rte flow */
+ uint32_t id;
+};
+
+/*
+ * FLOW_ACTION_TYPE_QUEUE
+ */
+struct flow_action_queue {
+ uint16_t index;
+};
+
+/*
+ * FLOW_ACTION_TYPE_JUMP
+ */
+struct flow_action_jump {
+ uint32_t group;
+};
+
+/*
+ * FLOW_ACTION_TYPE_METER
+ */
+struct flow_action_meter {
+ uint32_t mtr_id;
+};
+
+/*
+ * FLOW_ACTION_TYPE_RAW_ENCAP
+ */
+struct flow_action_raw_encap {
+ uint8_t *data;
+ uint8_t *preserve;
+ size_t size;
+ struct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX];
+ int item_count;
+};
+
+/*
+ * FLOW_ACTION_TYPE_RAW_DECAP
+ */
+struct flow_action_raw_decap {
+ uint8_t *data;
+ size_t size;
+ struct flow_elem items[RAW_ENCAP_DECAP_ELEMS_MAX];
+ int item_count;
+};
+
+/*
+ * Field IDs for MODIFY_FIELD action.
+ */
+enum flow_field_id {
+ FLOW_FIELD_START = 0, /* Start of a packet. */
+ FLOW_FIELD_MAC_DST, /* Destination MAC Address. */
+ FLOW_FIELD_MAC_SRC, /* Source MAC Address. */
+ FLOW_FIELD_VLAN_TYPE, /* 802.1Q Tag Identifier. */
+ FLOW_FIELD_VLAN_ID, /* 802.1Q VLAN Identifier. */
+ FLOW_FIELD_MAC_TYPE, /* EtherType. */
+ FLOW_FIELD_IPV4_DSCP, /* IPv4 DSCP. */
+ FLOW_FIELD_IPV4_TTL, /* IPv4 Time To Live. */
+ FLOW_FIELD_IPV4_SRC, /* IPv4 Source Address. */
+ FLOW_FIELD_IPV4_DST, /* IPv4 Destination Address. */
+ FLOW_FIELD_IPV6_DSCP, /* IPv6 DSCP. */
+ FLOW_FIELD_IPV6_HOPLIMIT, /* IPv6 Hop Limit. */
+ FLOW_FIELD_IPV6_SRC, /* IPv6 Source Address. */
+ FLOW_FIELD_IPV6_DST, /* IPv6 Destination Address. */
+ FLOW_FIELD_TCP_PORT_SRC, /* TCP Source Port Number. */
+ FLOW_FIELD_TCP_PORT_DST, /* TCP Destination Port Number. */
+ FLOW_FIELD_TCP_SEQ_NUM, /* TCP Sequence Number. */
+ FLOW_FIELD_TCP_ACK_NUM, /* TCP Acknowledgment Number. */
+ FLOW_FIELD_TCP_FLAGS, /* TCP Flags. */
+ FLOW_FIELD_UDP_PORT_SRC, /* UDP Source Port Number. */
+ FLOW_FIELD_UDP_PORT_DST, /* UDP Destination Port Number. */
+ FLOW_FIELD_VXLAN_VNI, /* VXLAN Network Identifier. */
+ FLOW_FIELD_GENEVE_VNI, /* GENEVE Network Identifier. */
+ FLOW_FIELD_GTP_TEID, /* GTP Tunnel Endpoint Identifier. */
+ FLOW_FIELD_TAG, /* Tag value. */
+ FLOW_FIELD_MARK, /* Mark value. */
+ FLOW_FIELD_META, /* Metadata value. */
+ FLOW_FIELD_POINTER, /* Memory pointer. */
+ FLOW_FIELD_VALUE, /* Immediate value. */
+ FLOW_FIELD_IPV4_ECN, /* IPv4 ECN. */
+ FLOW_FIELD_IPV6_ECN, /* IPv6 ECN. */
+ FLOW_FIELD_GTP_PSC_QFI, /* GTP QFI. */
+ FLOW_FIELD_METER_COLOR, /* Meter color marker. */
+};
+
+/*
+ * Field description for MODIFY_FIELD action.
+ */
+struct flow_action_modify_data {
+ enum flow_field_id field; /* Field or memory type ID. */
+ union {
+ struct {
+ /* Encapsulation level or tag index. */
+ uint32_t level;
+ /* Number of bits to skip from a field. */
+ uint32_t offset;
+ };
+ /*
+ * Immediate value for FLOW_FIELD_VALUE, presented in the
+ * same byte order and length as in relevant rte_flow_item_xxx.
+ */
+ uint8_t value[16];
+ /*
+ * Memory address for FLOW_FIELD_POINTER, memory layout
+ * should be the same as for relevant field in the
+ * rte_flow_item_xxx structure.
+ */
+ void *pvalue;
+ };
+};
+
+/*
+ * Operation types for MODIFY_FIELD action.
+ */
+enum flow_modify_op {
+ FLOW_MODIFY_SET = 0,
+ FLOW_MODIFY_ADD,
+ FLOW_MODIFY_SUB,
+};
+
+/*
+ * FLOW_ACTION_TYPE_MODIFY_FIELD
+ */
+struct flow_action_modify_field {
+ enum flow_modify_op operation;
+ struct flow_action_modify_data dst;
+ struct flow_action_modify_data src;
+ uint32_t width;
+};
+
+struct flow_action {
+ enum flow_action_type type;
+ const void *conf;
+};
+
+enum flow_error_e { FLOW_ERROR_NONE, FLOW_ERROR_SUCCESS, FLOW_ERROR_GENERAL };
+
+struct flow_error {
+ enum flow_error_e type;
+ const char *message;
+};
+
+enum flow_lag_cmd {
+ FLOW_LAG_SET_ENTRY,
+ FLOW_LAG_SET_ALL,
+ FLOW_LAG_SET_BALANCE,
+};
+
+/*
+ * Tunnel definition for DPDK RTE tunnel helper function support
+ */
+struct tunnel_cfg_s {
+ union {
+ struct {
+ uint32_t src_ip; /* BE */
+ uint32_t dst_ip; /* BE */
+ } v4;
+ struct {
+ uint8_t src_ip[16];
+ uint8_t dst_ip[16];
+ } v6;
+ struct {
+ uint64_t src_ip[2];
+ uint64_t dst_ip[2];
+ } v6_long;
+ };
+ int ipversion;
+ uint16_t s_port; /* BE */
+ uint16_t d_port; /* BE */
+ int tun_type;
+};
+
+struct flow_eth_dev; /* port device */
+struct flow_handle;
+
+/*
+ * Device Management API
+ */
+int flow_reset_nic_dev(uint8_t adapter_no);
+
+struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t hw_port_no,
+ uint32_t port_id, int alloc_queues,
+ struct flow_queue_id_s queue_ids[],
+ int *rss_target_id,
+ enum flow_eth_dev_profile flow_profile,
+ uint32_t exception_path);
+
+int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev,
+ struct flow_queue_id_s *queue_id);
+
+int flow_delete_eth_dev(struct flow_eth_dev *eth_dev);
+
+int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,
+ uint8_t vport);
+
+/*
+ * NT Flow API
+ */
+int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[],
+ const struct flow_action action[], struct flow_error *error);
+
+struct flow_handle *flow_create(struct flow_eth_dev *dev,
+ const struct flow_attr *attr,
+ const struct flow_elem item[],
+ const struct flow_action action[],
+ struct flow_error *error);
+
+int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow,
+ struct flow_error *error);
+
+int flow_flush(struct flow_eth_dev *dev, struct flow_error *error);
+
+int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow,
+ const struct flow_action *action, void **data, uint32_t *length,
+ struct flow_error *error);
+
+/*
+ * NT Flow FLM Meter API
+ */
+int flow_mtr_supported(struct flow_eth_dev *dev);
+
+uint64_t flow_mtr_meter_policy_n_max(void);
+
+int flow_mtr_set_profile(struct flow_eth_dev *dev, uint32_t profile_id,
+ uint64_t bucket_rate_a, uint64_t bucket_size_a,
+ uint64_t bucket_rate_b, uint64_t bucket_size_b);
+
+int flow_mtr_set_policy(struct flow_eth_dev *dev, uint32_t policy_id, int drop);
+
+int flow_mtr_create_meter(struct flow_eth_dev *dev, uint32_t mtr_id,
+ uint32_t profile_id, uint32_t policy_id,
+ uint64_t stats_mask);
+
+int flow_mtr_destroy_meter(struct flow_eth_dev *dev, uint32_t mtr_id);
+
+int flm_mtr_adjust_stats(struct flow_eth_dev *dev, uint32_t mtr_id,
+ uint32_t adjust_value);
+
+uint32_t flow_mtr_meters_supported(void);
+
+uint32_t flm_mtr_update_stats(struct flow_eth_dev *dev);
+void flm_mtr_read_stats(struct flow_eth_dev *dev, uint32_t id,
+ uint64_t *stats_mask, uint64_t *green_pkt,
+ uint64_t *green_bytes, int clear);
+
+/*
+ * Config API
+ */
+int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask);
+
+int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask);
+
+int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index,
+ uint32_t value);
+
+int flow_set_mtu_inline(struct flow_eth_dev *dev, uint32_t port, uint16_t mtu);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STREAM_BINARY_FLOW_API_H_ */
--
2.39.3
^ permalink raw reply [flat|nested] 142+ messages in thread
* [PATCH v2 6/8] net/ntnic: adds flow logic
2023-08-17 14:43 ` [PATCH v2 1/8] net/ntnic: initial commit which adds register defines Mykola Kostenok
` (3 preceding siblings ...)
2023-08-17 14:43 ` [PATCH v2 5/8] net/ntnic: adds FPGA abstraction layer Mykola Kostenok
@ 2023-08-17 14:43 ` Mykola Kostenok
2023-08-17 14:43 ` [PATCH v2 7/8] net/ntnic: adds ethdev and makes PMD available Mykola Kostenok
` (2 subsequent siblings)
7 siblings, 0 replies; 142+ messages in thread
From: Mykola Kostenok @ 2023-08-17 14:43 UTC (permalink / raw)
To: dev, mko-plv; +Cc: ckm
From: Christian Koue Muf <ckm@napatech.com>
This logic layer takes rte_flow style patterns and actions as input,
and programs the FPGA accordingly.
Signed-off-by: Christian Koue Muf <ckm@napatech.com>
Reviewed-by: Mykola Kostenok <mko-plv@napatech.com>
---
v2:
* Fixed WARNING:TYPO_SPELLING
---
drivers/net/ntnic/adapter/nt4ga_adapter.c | 13 +
drivers/net/ntnic/adapter/nt4ga_stat.c | 20 +-
drivers/net/ntnic/meson.build | 4 +
drivers/net/ntnic/nthw/flow_api/flow_api.c | 1306 +++++
drivers/net/ntnic/nthw/flow_api/flow_api.h | 291 +
.../nthw/flow_api/flow_api_profile_inline.c | 5118 +++++++++++++++++
.../nthw/flow_api/flow_api_profile_inline.h | 56 +
.../net/ntnic/nthw/flow_filter/flow_backend.c | 3205 +++++++++++
.../net/ntnic/nthw/flow_filter/flow_backend.h | 15 +
.../net/ntnic/nthw/flow_filter/flow_filter.c | 39 +
.../net/ntnic/nthw/flow_filter/flow_filter.h | 16 +
11 files changed, 10078 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api.h
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_api_profile_inline.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_backend.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_backend.h
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_filter.c
create mode 100644 drivers/net/ntnic/nthw/flow_filter/flow_filter.h
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index 259aae2831..f9493202c3 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -10,6 +10,8 @@
#include "nt4ga_pci_ta_tg.h"
#include "nt4ga_link_100g.h"
+#include "flow_filter.h"
+
/* Sensors includes */
#include "board_sensors.h"
#include "avr_sensors.h"
@@ -306,6 +308,17 @@ int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info)
n_nim_ports = fpga_info->n_nims;
assert(n_nim_ports >= 1);
+ /* Nt4ga Init Filter */
+ nt4ga_filter_t *p_filter = &p_adapter_info->nt4ga_filter;
+
+ res = flow_filter_init(p_fpga, &p_filter->mp_flow_device,
+ p_adapter_info->adapter_no);
+ if (res != 0) {
+ NT_LOG(ERR, ETHDEV, "%s: Cannot initialize filter\n",
+ p_adapter_id_str);
+ return res;
+ }
+
/*
* HIF/PCI TA/TG
*/
diff --git a/drivers/net/ntnic/adapter/nt4ga_stat.c b/drivers/net/ntnic/adapter/nt4ga_stat.c
index b61c73ea12..2c822c6b97 100644
--- a/drivers/net/ntnic/adapter/nt4ga_stat.c
+++ b/drivers/net/ntnic/adapter/nt4ga_stat.c
@@ -7,6 +7,7 @@
#include "nthw_drv.h"
#include "nthw_fpga.h"
#include "nt4ga_adapter.h"
+#include "flow_filter.h"
#define NO_FLAGS 0
@@ -16,12 +17,13 @@ static inline uint64_t timestamp2ns(uint64_t ts)
return ((ts >> 32) * 1000000000) + (ts & 0xffffffff);
}
-static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+static int nt4ga_stat_collect_cap_v1_stats(struct adapter_info_s *p_adapter_info,
+ nt4ga_stat_t *p_nt4ga_stat,
uint32_t *p_stat_dma_virtual);
static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
uint32_t *p_stat_dma_virtual);
-int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused,
+int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info,
nt4ga_stat_t *p_nt4ga_stat)
{
nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
@@ -39,7 +41,7 @@ int nt4ga_stat_collect(struct adapter_info_s *p_adapter_info _unused,
} else {
p_nt4ga_stat->last_timestamp =
timestamp2ns(*p_nthw_stat->mp_timestamp);
- nt4ga_stat_collect_cap_v1_stats(p_nt4ga_stat,
+ nt4ga_stat_collect_cap_v1_stats(p_adapter_info, p_nt4ga_stat,
p_nt4ga_stat->p_stat_dma_virtual);
}
return 0;
@@ -198,7 +200,9 @@ int nt4ga_stat_setup(struct adapter_info_s *p_adapter_info)
return -1;
}
- p_nt4ga_stat->flm_stat_ver = 0;
+ struct flow_nic_dev *ndev =
+ p_adapter_info->nt4ga_filter.mp_flow_device;
+ p_nt4ga_stat->flm_stat_ver = ndev->be.flm.ver;
p_nt4ga_stat->mp_stat_structs_flm =
calloc(1, sizeof(struct flm_counters_v1));
@@ -394,10 +398,12 @@ static int nt4ga_stat_collect_virt_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
}
/* Called with stat mutex locked */
-static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
+static int nt4ga_stat_collect_cap_v1_stats(struct adapter_info_s *p_adapter_info,
+ nt4ga_stat_t *p_nt4ga_stat,
uint32_t *p_stat_dma_virtual)
{
nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
+ struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
const int n_rx_ports = p_nt4ga_stat->mn_rx_ports;
const int n_tx_ports = p_nt4ga_stat->mn_tx_ports;
@@ -701,5 +707,9 @@ static int nt4ga_stat_collect_cap_v1_stats(nt4ga_stat_t *p_nt4ga_stat,
p_nt4ga_stat->a_port_tx_drops_total[p] += new_drop_events_sum;
}
+ /* _update and get FLM stats */
+ flow_get_flm_stats(ndev, (uint64_t *)p_nt4ga_stat->mp_stat_structs_flm,
+ sizeof(struct flm_counters_v1) / sizeof(uint64_t));
+
return 0;
}
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 387481bb4a..a9892615c9 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -60,8 +60,10 @@ sources = files(
'nthw/core/nthw_spim.c',
'nthw/core/nthw_spis.c',
'nthw/core/nthw_tsm.c',
+ 'nthw/flow_api/flow_api.c',
'nthw/flow_api/flow_api_actions.c',
'nthw/flow_api/flow_api_backend.c',
+ 'nthw/flow_api/flow_api_profile_inline.c',
'nthw/flow_api/flow_engine/flow_group.c',
'nthw/flow_api/flow_engine/flow_hasher.c',
'nthw/flow_api/flow_engine/flow_kcc.c',
@@ -80,6 +82,8 @@ sources = files(
'nthw/flow_api/hw_mod/hw_mod_slc.c',
'nthw/flow_api/hw_mod/hw_mod_slc_lr.c',
'nthw/flow_api/hw_mod/hw_mod_tpe.c',
+ 'nthw/flow_filter/flow_backend.c',
+ 'nthw/flow_filter/flow_filter.c',
'nthw/flow_filter/flow_nthw_cat.c',
'nthw/flow_filter/flow_nthw_csu.c',
'nthw/flow_filter/flow_nthw_flm.c',
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.c b/drivers/net/ntnic/nthw/flow_api/flow_api.c
new file mode 100644
index 0000000000..2598e1e27b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api.c
@@ -0,0 +1,1306 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <arpa/inet.h> /* htons, htonl, ntohs */
+
+#include "ntlog.h"
+
+#include "flow_api.h"
+
+#include "flow_api_nic_setup.h"
+#include "stream_binary_flow_api.h"
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+#include "flow_api_profile_inline.h"
+
+#define SCATTER_GATHER
+
+const char *dbg_res_descr[] = {
+ /* RES_QUEUE */ "RES_QUEUE",
+ /* RES_CAT_CFN */ "RES_CAT_CFN",
+ /* RES_CAT_COT */ "RES_CAT_COT",
+ /* RES_CAT_EXO */ "RES_CAT_EXO",
+ /* RES_CAT_LEN */ "RES_CAT_LEN",
+ /* RES_KM_FLOW_TYPE */ "RES_KM_FLOW_TYPE",
+ /* RES_KM_CATEGORY */ "RES_KM_CATEGORY",
+ /* RES_HSH_RCP */ "RES_HSH_RCP",
+ /* RES_PDB_RCP */ "RES_PDB_RCP",
+ /* RES_QSL_RCP */ "RES_QSL_RCP",
+ /* RES_QSL_LTX */ "RES_QSL_LTX",
+ /* RES_QSL_QST */ "RES_QSL_QST",
+ /* RES_SLC_RCP */ "RES_SLC_RCP",
+ /* RES_IOA_RCP */ "RES_IOA_RCP",
+ /* RES_ROA_RCP */ "RES_ROA_RCP",
+ /* RES_FLM_FLOW_TYPE */ "RES_FLM_FLOW_TYPE",
+ /* RES_FLM_RCP */ "RES_FLM_RCP",
+ /* RES_HST_RCP */ "RES_HST_RCP",
+ /* RES_TPE_RCP */ "RES_TPE_RCP",
+ /* RES_TPE_EXT */ "RES_TPE_EXT",
+ /* RES_TPE_RPL */ "RES_TPE_RPL",
+ /* RES_COUNT */ "RES_COUNT",
+ /* RES_INVALID */ "RES_INVALID"
+};
+
+static struct flow_nic_dev *dev_base;
+static pthread_mutex_t base_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * *****************************************************************************
+ * Error handling
+ * *****************************************************************************
+ */
+
+static const struct {
+ const char *message;
+} err_msg[] = {
+ /* 00 */ { "Operation successfully completed" },
+ /* 01 */ { "Operation failed" },
+ /* 02 */ { "Memory allocation failed" },
+ /* 03 */ { "Too many output destinations" },
+ /* 04 */ { "Too many output queues for RSS" },
+ /* 05 */ { "The VLAN TPID specified is not supported" },
+ /* 06 */ { "The VxLan Push header specified is not accepted" },
+ /* 07 */
+ { "While interpreting VxLan Pop action, could not find a destination port" },
+ /* 08 */ { "Failed in creating a HW-internal VTEP port" },
+ /* 09 */ { "Too many VLAN tag matches" },
+ /* 10 */ { "IPv6 invalid header specified" },
+ /* 11 */ { "Too many tunnel ports. HW limit reached" },
+ /* 12 */ { "Unknown or unsupported flow match element received" },
+ /* 13 */ { "Match failed because of HW limitations" },
+ /* 14 */ { "Match failed because of HW resource limitations" },
+ /* 15 */ { "Match failed because of too complex element definitions" },
+ /* 16 */ { "Action failed. To too many output destinations" },
+ /* 17 */ { "Action Output failed, due to HW resource exhaustion" },
+ /* 18 */
+ { "Push Tunnel Header action cannot output to multiple destination queues" },
+ /* 19 */ { "Inline action HW resource exhaustion" },
+ /* 20 */ { "Action retransmit/recirculate HW resource exhaustion" },
+ /* 21 */ { "Flow counter HW resource exhaustion" },
+ /* 22 */ { "Internal HW resource exhaustion to handle Actions" },
+ /* 23 */ { "Internal HW QSL compare failed" },
+ /* 24 */ { "Internal CAT CFN reuse failed" },
+ /* 25 */ { "Match variations too complex" },
+ /* 26 */ { "Match failed because of CAM/TCAM full" },
+ /* 27 */ { "Internal creation of a tunnel end point port failed" },
+ /* 28 */ { "Unknown or unsupported flow action received" },
+ /* 29 */ { "Removing flow failed" },
+ /* 30 */
+ { "No output queue specified. Ignore this flow offload and uses default queue" },
+ /* 31 */ { "No output queue found" },
+ /* 32 */ { "Unsupported EtherType or rejected caused by offload policy" },
+ /* 33 */
+ { "Destination port specified is invalid or not reachable from this NIC" },
+ /* 34 */ { "Partial offload is not supported in this configuration" },
+ /* 35 */ { "Match failed because of CAT CAM exhausted" },
+ /* 36 */
+ { "Match failed because of CAT CAM Key clashed with an existing KCC Key" },
+ /* 37 */ { "Match failed because of CAT CAM write failed" },
+ /* 38 */ { "Partial flow mark too big for device" },
+};
+
+void flow_nic_set_error(enum flow_nic_err_msg_e msg, struct flow_error *error)
+{
+ assert(msg < ERR_MSG_NO_MSG);
+ if (error) {
+ error->message = err_msg[msg].message;
+ error->type = (msg == ERR_SUCCESS) ? FLOW_ERROR_SUCCESS :
+ FLOW_ERROR_GENERAL;
+ }
+}
+
+/*
+ * *****************************************************************************
+ * Resources
+ * *****************************************************************************
+ */
+
+int flow_nic_alloc_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ uint32_t alignment)
+{
+ for (unsigned int i = 0; i < ndev->res[res_type].resource_count;
+ i += alignment) {
+ if (!flow_nic_is_resource_used(ndev, res_type, i)) {
+ flow_nic_mark_resource_used(ndev, res_type, i);
+ ndev->res[res_type].ref[i] = 1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+int flow_nic_alloc_resource_index(struct flow_nic_dev *ndev, int idx,
+ enum res_type_e res_type)
+{
+ if (!flow_nic_is_resource_used(ndev, res_type, idx)) {
+ flow_nic_mark_resource_used(ndev, res_type, idx);
+ ndev->res[res_type].ref[idx] = 1;
+ return 0;
+ }
+ return -1;
+}
+
+int flow_nic_alloc_resource_contig(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, unsigned int num,
+ uint32_t alignment)
+{
+ unsigned int idx_offs;
+
+ for (unsigned int res_idx = 0;
+ res_idx < ndev->res[res_type].resource_count - (num - 1);
+ res_idx += alignment) {
+ if (!flow_nic_is_resource_used(ndev, res_type, res_idx)) {
+ for (idx_offs = 1; idx_offs < num; idx_offs++) {
+ if (flow_nic_is_resource_used(ndev, res_type,
+ res_idx + idx_offs))
+ break;
+ }
+ if (idx_offs < num)
+ continue;
+
+ /* found a contiguous number of "num" res_type elements - allocate them */
+ for (idx_offs = 0; idx_offs < num; idx_offs++) {
+ flow_nic_mark_resource_used(ndev, res_type,
+ res_idx + idx_offs);
+ ndev->res[res_type].ref[res_idx + idx_offs] = 1;
+ }
+ return res_idx;
+ }
+ }
+ return -1;
+}
+
+void flow_nic_free_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int idx)
+{
+ flow_nic_mark_resource_unused(ndev, res_type, idx);
+}
+
+int flow_nic_ref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int index)
+{
+ NT_LOG(DBG, FILTER,
+ "Reference resource %s idx %i (before ref cnt %i)\n",
+ dbg_res_descr[res_type], index, ndev->res[res_type].ref[index]);
+ assert(flow_nic_is_resource_used(ndev, res_type, index));
+ if (ndev->res[res_type].ref[index] == (uint32_t)-1)
+ return -1;
+ ndev->res[res_type].ref[index]++;
+ return 0;
+}
+
+int flow_nic_deref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
+ int index)
+{
+ NT_LOG(DBG, FILTER,
+ "De-reference resource %s idx %i (before ref cnt %i)\n",
+ dbg_res_descr[res_type], index, ndev->res[res_type].ref[index]);
+ assert(flow_nic_is_resource_used(ndev, res_type, index));
+ assert(ndev->res[res_type].ref[index]);
+ /* deref */
+ ndev->res[res_type].ref[index]--;
+ if (!ndev->res[res_type].ref[index])
+ flow_nic_free_resource(ndev, res_type, index);
+ return !!ndev->res[res_type]
+ .ref[index]; /* if 0 resource has been freed */
+}
+
+int flow_nic_find_next_used_resource(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, int idx_start)
+{
+ for (unsigned int i = idx_start; i < ndev->res[res_type].resource_count;
+ i++) {
+ if (flow_nic_is_resource_used(ndev, res_type, i))
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Allocate a number flow resources.
+ *
+ * Arguments:
+ * ndev : device
+ * res_type : resource type
+ * fh : flow handle
+ * count : number of (contiguous) resources to be allocated
+ * alignment : start index alignment
+ * 1: the allocation can start at any index
+ * 2: the allocation must start at index modulus 2 (0, 2, 4, 6, ...)
+ * 3: the allocation must start at index modulus 3 (0, 3, 6, 9, ...)
+ * etc.
+ * Returns:
+ * 0 : success
+ * -1 : failure
+ */
+int flow_nic_allocate_fh_resource(struct flow_nic_dev *ndev,
+ enum res_type_e res_type,
+ struct flow_handle *fh, uint32_t count,
+ uint32_t alignment)
+{
+ if (count > 1) {
+ /* Contiguous */
+ fh->resource[res_type].index =
+ flow_nic_alloc_resource_contig(ndev, res_type, count, alignment);
+ } else {
+ fh->resource[res_type].index =
+ flow_nic_alloc_resource(ndev, res_type, alignment);
+ }
+
+ if (fh->resource[res_type].index < 0)
+ return -1;
+ fh->resource[res_type].count = count;
+ return 0;
+}
+
+int flow_nic_allocate_fh_resource_index(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, int idx,
+ struct flow_handle *fh)
+{
+ int err = flow_nic_alloc_resource_index(ndev, idx, res_type);
+
+ if (err)
+ return err;
+
+ fh->resource[res_type].index = idx;
+ if (fh->resource[res_type].index < 0)
+ return -1;
+ fh->resource[res_type].count = 1;
+ return 0;
+}
+
+/*
+ * *****************************************************************************
+ * Hash
+ * *****************************************************************************
+ */
+
+int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx,
+ enum flow_nic_hash_e algorithm)
+{
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
+ switch (algorithm) {
+ case HASH_ALGO_5TUPLE:
+ /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE,
+ hsh_idx, 0, 2);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0,
+ DYN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0,
+ -16);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0,
+ DYN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0,
+ 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx, 0,
+ DYN_L4);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_PE, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_OFS, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_P, hsh_idx, 0, 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK, hsh_idx, 0, 1);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 8,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 9,
+ 0);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_SEED, hsh_idx, 0,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_VALID, hsh_idx, 0,
+ 1);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0,
+ HASH_5TUPLE);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+
+ NT_LOG(DBG, FILTER,
+ "Set IPv6 5-tuple hasher with adaptive IPv4 hashing\n");
+ break;
+ default:
+ case HASH_ALGO_ROUND_ROBIN:
+ /* zero is round-robin */
+ break;
+ }
+
+ return 0;
+}
+
+int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx,
+ struct nt_eth_rss f)
+{
+ uint64_t fields = f.fields;
+
+ int res = 0;
+
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0,
+ 0);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, hsh_idx,
+ 0, 2);
+ switch (fields) {
+ case NT_ETH_RSS_C_VLAN:
+ /*
+ * Here we are using 1st VLAN to point C-VLAN which is only try for the single VLAN
+ * provider
+ */
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx,
+ 0, DYN_FIRST_VLAN);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx,
+ 0, 0);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK,
+ hsh_idx, 8, 0xffffffff);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE,
+ hsh_idx, 0, HASH_LAST_VLAN_ID);
+ if (res) {
+ NT_LOG(ERR, FILTER,
+ "VLAN hasher is not set hardware communication problem has "
+ "occurred. The cardware could be in inconsistent state. Rerun.\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER, "Set VLAN hasher.\n");
+ return 0;
+ case NT_ETH_RSS_LEVEL_OUTERMOST | NT_ETH_RSS_L3_DST_ONLY | NT_ETH_RSS_IP:
+ /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0,
+ DYN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0,
+ 0);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7,
+ 0xffffffff);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0,
+ HASH_OUTER_DST_IP);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+ if (res) {
+ NT_LOG(ERR, FILTER,
+ "Outer dst IP hasher is not set hardware communication problem has "
+ "occurred. The cardware could be in inconsistent state. Rerun.\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER, "Set outer dst IP hasher.\n");
+ return 0;
+ case NT_ETH_RSS_LEVEL_INNERMOST | NT_ETH_RSS_L3_SRC_ONLY | NT_ETH_RSS_IP:
+ /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0,
+ DYN_TUN_FINAL_IP_DST);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0,
+ -16);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2,
+ 0xffffffff);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3,
+ 0xffffffff);
+
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0,
+ HASH_INNER_SRC_IP);
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+ if (res) {
+ NT_LOG(ERR, FILTER,
+ "Inner (depth = 1) src IP hasher is not set hardware communication "
+ "problem has occurred. The cardware could be in inconsistent state. "
+ "Rerun.\n");
+ return -1;
+ }
+ NT_LOG(DBG, FILTER, "Set outer dst IP hasher.\n");
+ return 0;
+ default:
+ NT_LOG(ERR, FILTER,
+ "RSS bit flags can't be set up. "
+ "Flags combination is not supported.");
+ return -1;
+ }
+}
+
+/*
+ * *****************************************************************************
+ * Nic port/adapter lookup
+ * *****************************************************************************
+ */
+
+struct flow_eth_dev *nic_and_port_to_eth_dev(uint8_t adapter_no, uint8_t port)
+{
+ struct flow_nic_dev *nic_dev = dev_base;
+
+ while (nic_dev) {
+ if (nic_dev->adapter_no == adapter_no)
+ break;
+ nic_dev = nic_dev->next;
+ }
+
+ if (!nic_dev)
+ return NULL;
+
+ struct flow_eth_dev *dev = nic_dev->eth_base;
+
+ while (dev) {
+ if (port == dev->port)
+ return dev;
+ dev = dev->next;
+ }
+
+ return NULL;
+}
+
+struct flow_nic_dev *get_nic_dev_from_adapter_no(uint8_t adapter_no)
+{
+ struct flow_nic_dev *ndev = dev_base;
+
+ while (ndev) {
+ if (adapter_no == ndev->adapter_no)
+ break;
+ ndev = ndev->next;
+ }
+ return ndev;
+}
+
+/*
+ * *****************************************************************************
+ * LAG control implementation
+ * *****************************************************************************
+ */
+
+int lag_set_port_group(uint8_t adapter_no, uint32_t port_mask)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+ /*
+ * Sets each 2 ports for each bit N as Lag. Ports N*2+N*2+1 are merged together
+ * and reported as N*2 incoming port
+ */
+ hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_LAG_PHY_ODD_EVEN, port_mask);
+ hw_mod_rmc_ctrl_flush(&ndev->be);
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+}
+
+int lag_set_port_block(uint8_t adapter_no, uint32_t port_mask)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+ /* Blocks for traffic from port */
+ hw_mod_rmc_ctrl_set(&ndev->be, HW_RMC_BLOCK_MAC_PORT, port_mask);
+ hw_mod_rmc_ctrl_flush(&ndev->be);
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+}
+
+static void write_lag_entry(struct flow_api_backend_s *be, uint32_t index,
+ uint32_t value)
+{
+ hw_mod_roa_lagcfg_set(be, HW_ROA_LAGCFG_TXPHY_PORT, index, value);
+ hw_mod_roa_lagcfg_flush(be, index, 1);
+}
+
+int lag_set_config(uint8_t adapter_no, enum flow_lag_cmd cmd, uint32_t index,
+ uint32_t value)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+
+ switch (cmd) {
+ case FLOW_LAG_SET_ENTRY:
+ write_lag_entry(&ndev->be, index, value);
+ break;
+
+ case FLOW_LAG_SET_ALL:
+ index &= 3;
+ for (unsigned int i = 0; i < ndev->be.roa.nb_lag_entries;
+ i += 4)
+ write_lag_entry(&ndev->be, i + index, value);
+ break;
+
+ case FLOW_LAG_SET_BALANCE:
+ /*
+ * This function will balance the output port
+ * value: The balance of the distribution:
+ * port P0 / P1
+ * 0: 0 / 100 port 0 is disabled
+ * 25: 25 / 75
+ * 50: 50 / 50
+ * 75: 75 / 25
+ * 100: 100/ 0 port 1 is disabled
+ */
+ {
+ /* Clamp the balance to 100% output on port 1 */
+ if (value > 100)
+ value = 100;
+ double balance = ((double)value / 100.0);
+ double block_count =
+ (double)ndev->be.roa.nb_lag_entries / 4.0;
+
+ int output_port = 1;
+ int port0_output_block_count =
+ (int)(block_count * balance);
+
+ for (int block = 0; block < block_count; block++) {
+ /* When the target port0 balance is reached. */
+ if (block >= port0_output_block_count)
+ output_port = 2;
+ /* Write an entire hash block to a given output port. */
+ for (int idx = 0; idx < 4; idx++) {
+ write_lag_entry(&ndev->be,
+ block * 4 + idx,
+ output_port);
+ } /* for each index in hash block */
+ } /* for each hash block */
+ }
+
+ break;
+ default:
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+ }
+
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+}
+
+/*
+ * *****************************************************************************
+ * Flow API
+ * *****************************************************************************
+ */
+
+int flow_validate(struct flow_eth_dev *dev, const struct flow_elem item[],
+ const struct flow_action action[], struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_validate_profile_inline(dev, item, action, error);
+}
+
+struct flow_handle *flow_create(struct flow_eth_dev *dev,
+ const struct flow_attr *attr,
+ const struct flow_elem item[],
+ const struct flow_action action[],
+ struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return NULL;
+ }
+ return flow_create_profile_inline(dev, attr, item, action, error);
+}
+
+int flow_destroy(struct flow_eth_dev *dev, struct flow_handle *flow,
+ struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_destroy_profile_inline(dev, flow, error);
+}
+
+int flow_flush(struct flow_eth_dev *dev, struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_flush_profile_inline(dev, error);
+}
+
+int flow_query(struct flow_eth_dev *dev, struct flow_handle *flow,
+ const struct flow_action *action, void **data, uint32_t *length,
+ struct flow_error *error)
+{
+ if (dev->ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ return flow_query_profile_inline(dev, flow, action, data, length,
+ error);
+}
+
+/*
+ * *****************************************************************************
+ * Device Management API
+ * *****************************************************************************
+ */
+
+static void nic_insert_eth_port_dev(struct flow_nic_dev *ndev,
+ struct flow_eth_dev *dev)
+{
+ dev->next = ndev->eth_base;
+ ndev->eth_base = dev;
+}
+
+static int nic_remove_eth_port_dev(struct flow_nic_dev *ndev,
+ struct flow_eth_dev *eth_dev)
+{
+ struct flow_eth_dev *dev = ndev->eth_base, *prev = NULL;
+
+ while (dev) {
+ if (dev == eth_dev) {
+ if (prev)
+ prev->next = dev->next;
+
+ else
+ ndev->eth_base = dev->next;
+ return 0;
+ }
+ prev = dev;
+ dev = dev->next;
+ }
+ return -1;
+}
+
+static void flow_ndev_reset(struct flow_nic_dev *ndev)
+{
+ /* Delete all eth-port devices created on this NIC device */
+ while (ndev->eth_base)
+ flow_delete_eth_dev(ndev->eth_base);
+
+ /* Error check */
+ while (ndev->flow_base) {
+ NT_LOG(ERR, FILTER,
+ "ERROR : Flows still defined but all eth-ports deleted. Flow %p\n",
+ ndev->flow_base);
+
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return;
+ }
+ flow_destroy_profile_inline(ndev->flow_base->dev,
+ ndev->flow_base, NULL);
+ }
+
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return;
+ }
+ done_flow_management_of_ndev_profile_inline(ndev);
+
+ km_free_ndev_resource_management(&ndev->km_res_handle);
+ kcc_free_ndev_resource_management(&ndev->kcc_res_handle);
+
+#ifdef FLOW_DEBUG
+ /*
+ * free all resources default allocated, initially for this NIC DEV
+ * Is not really needed since the bitmap will be freed in a sec. Therefore
+ * only in debug mode
+ */
+
+ /* Check if all resources has been released */
+ NT_LOG(DBG, FILTER, "Delete NIC DEV Adaptor %i\n", ndev->adapter_no);
+ for (unsigned int i = 0; i < RES_COUNT; i++) {
+ int err = 0;
+#if defined(FLOW_DEBUG)
+ NT_LOG(DBG, FILTER, "RES state for: %s\n", dbg_res_descr[i]);
+#endif
+ for (unsigned int ii = 0; ii < ndev->res[i].resource_count;
+ ii++) {
+ int ref = ndev->res[i].ref[ii];
+ int used = flow_nic_is_resource_used(ndev, i, ii);
+
+ if (ref || used) {
+ NT_LOG(DBG, FILTER,
+ " [%i]: ref cnt %i, used %i\n", ii, ref,
+ used);
+ err = 1;
+ }
+ }
+ if (err)
+ NT_LOG(DBG, FILTER,
+ "ERROR - some resources not freed\n");
+ }
+#endif
+}
+
+int flow_reset_nic_dev(uint8_t adapter_no)
+{
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev)
+ return -1;
+ flow_ndev_reset(ndev);
+ flow_api_backend_reset(&ndev->be);
+ return 0;
+}
+
+/*
+ * adapter_no physical adapter no
+ * port_no local port no
+ * alloc_rx_queues number of rx-queues to allocate for this eth_dev
+ */
+struct flow_eth_dev *flow_get_eth_dev(uint8_t adapter_no, uint8_t port_no,
+ uint32_t port_id, int alloc_rx_queues,
+ struct flow_queue_id_s queue_ids[],
+ int *rss_target_id,
+ enum flow_eth_dev_profile flow_profile,
+ uint32_t exception_path)
+{
+ int i;
+ struct flow_eth_dev *eth_dev = NULL;
+
+ NT_LOG(DBG, FILTER,
+ "Get eth-port adapter %i, port %i, port_id %u, rx queues %i, profile %i\n",
+ adapter_no, port_no, port_id, alloc_rx_queues, flow_profile);
+
+ if (MAX_OUTPUT_DEST < FLOW_MAX_QUEUES) {
+ assert(0);
+ NT_LOG(ERR, FILTER,
+ "ERROR: Internal array for multiple queues too small for API\n");
+ }
+
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *ndev = get_nic_dev_from_adapter_no(adapter_no);
+
+ if (!ndev) {
+ /* Error - no flow api found on specified adapter */
+ NT_LOG(ERR, FILTER,
+ "ERROR: no flow interface registered for adapter %d\n",
+ adapter_no);
+ pthread_mutex_unlock(&base_mtx);
+ return NULL;
+ }
+
+ if (ndev->ports < ((uint16_t)port_no + 1)) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: port exceeds supported port range for adapter\n");
+ pthread_mutex_unlock(&base_mtx);
+ return NULL;
+ }
+
+ if ((alloc_rx_queues - 1) >
+ FLOW_MAX_QUEUES) { /* 0th is exception so +1 */
+ NT_LOG(ERR, FILTER,
+ "ERROR: Exceeds supported number of rx queues per eth device\n");
+ pthread_mutex_unlock(&base_mtx);
+ return NULL;
+ }
+
+ /* don't accept multiple eth_dev's on same NIC and same port */
+ eth_dev = nic_and_port_to_eth_dev(adapter_no, port_no);
+ if (eth_dev) {
+ NT_LOG(DBG, FILTER,
+ "Re-opening existing NIC port device: NIC DEV: %i Port %i\n",
+ adapter_no, port_no);
+ pthread_mutex_unlock(&base_mtx);
+ flow_delete_eth_dev(eth_dev);
+ eth_dev = NULL;
+ }
+
+ eth_dev = calloc(1, sizeof(struct flow_eth_dev));
+ if (!eth_dev) {
+ NT_LOG(ERR, FILTER, "ERROR: calloc failed\n");
+ goto err_exit1;
+ }
+
+ pthread_mutex_lock(&ndev->mtx);
+
+ eth_dev->ndev = ndev;
+ eth_dev->port = port_no;
+ eth_dev->port_id = port_id;
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ /* First time then NIC is initialized */
+ if (!ndev->flow_mgnt_prepared) {
+ ndev->flow_profile = flow_profile;
+ /* Initialize modules if needed - recipe 0 is used as no-match and must be setup */
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ goto err_exit0;
+ } else if (initialize_flow_management_of_ndev_profile_inline(ndev)
+ != 0) {
+ goto err_exit0;
+ }
+ } else {
+ /* check if same flow type is requested, otherwise fail */
+ if (ndev->flow_profile != flow_profile) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: Different flow types requested on same NIC device. "
+ "Not supported.\n");
+ goto err_exit0;
+ }
+ }
+
+ /* Allocate the requested queues in HW for this dev */
+
+ for (i = 0; i < alloc_rx_queues; i++) {
+#ifdef SCATTER_GATHER
+ eth_dev->rx_queue[i] = queue_ids[i];
+#else
+ int queue_id = flow_nic_alloc_resource(ndev, RES_QUEUE, 1);
+
+ if (queue_id < 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: no more free queue IDs in NIC\n");
+ goto err_exit0;
+ }
+
+ eth_dev->rx_queue[eth_dev->num_queues].id = (uint8_t)queue_id;
+ eth_dev->rx_queue[eth_dev->num_queues].hw_id =
+ ndev->be.iface->alloc_rx_queue(ndev->be.be_dev,
+ eth_dev->rx_queue[eth_dev->num_queues].id);
+ if (eth_dev->rx_queue[eth_dev->num_queues].hw_id < 0) {
+ NT_LOG(ERR, FILTER,
+ "ERROR: could not allocate a new queue\n");
+ goto err_exit0;
+ }
+
+ if (queue_ids) {
+ queue_ids[eth_dev->num_queues] =
+ eth_dev->rx_queue[eth_dev->num_queues];
+ }
+#endif
+ if (i == 0 && (flow_profile == FLOW_ETH_DEV_PROFILE_VSWITCH ||
+ (flow_profile == FLOW_ETH_DEV_PROFILE_INLINE &&
+ exception_path))) {
+ /*
+ * Init QSL UNM - unmatched - redirects otherwise discarded packets in QSL
+ */
+ if (hw_mod_qsl_unmq_set(&ndev->be,
+ HW_QSL_UNMQ_DEST_QUEUE,
+ eth_dev->port,
+ eth_dev->rx_queue[0].hw_id) < 0)
+ goto err_exit0;
+ if (hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_EN,
+ eth_dev->port, 1) < 0)
+ goto err_exit0;
+ if (hw_mod_qsl_unmq_flush(&ndev->be, eth_dev->port, 1) <
+ 0)
+ goto err_exit0;
+ }
+
+ eth_dev->num_queues++;
+ }
+
+ eth_dev->rss_target_id = -1;
+
+ if (flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) {
+ for (i = 0; i < eth_dev->num_queues; i++) {
+ uint32_t qen_value = 0;
+ uint32_t queue_id =
+ (uint32_t)eth_dev->rx_queue[i].hw_id;
+
+ hw_mod_qsl_qen_get(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4, &qen_value);
+ hw_mod_qsl_qen_set(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4,
+ qen_value | (1 << (queue_id % 4)));
+ hw_mod_qsl_qen_flush(&ndev->be, queue_id / 4, 1);
+ }
+ }
+
+ *rss_target_id = eth_dev->rss_target_id;
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ nic_insert_eth_port_dev(ndev, eth_dev);
+
+ pthread_mutex_unlock(&ndev->mtx);
+ pthread_mutex_unlock(&base_mtx);
+ return eth_dev;
+
+err_exit0:
+ pthread_mutex_unlock(&ndev->mtx);
+ pthread_mutex_unlock(&base_mtx);
+
+err_exit1:
+ if (eth_dev)
+ free(eth_dev);
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+ NT_LOG(DBG, FILTER, "ERR in %s\n", __func__);
+ return NULL; /* Error exit */
+}
+
+int flow_eth_dev_add_queue(struct flow_eth_dev *eth_dev,
+ struct flow_queue_id_s *queue_id)
+{
+ uint32_t qen_value = 0;
+
+ eth_dev->rx_queue[eth_dev->num_queues].id = queue_id->id;
+ eth_dev->rx_queue[eth_dev->num_queues].hw_id = queue_id->hw_id;
+ eth_dev->num_queues += 1;
+
+ hw_mod_qsl_qen_get(ð_dev->ndev->be, HW_QSL_QEN_EN,
+ queue_id->hw_id / 4, &qen_value);
+ hw_mod_qsl_qen_set(ð_dev->ndev->be, HW_QSL_QEN_EN,
+ queue_id->hw_id / 4,
+ qen_value | (1 << (queue_id->hw_id % 4)));
+ hw_mod_qsl_qen_flush(ð_dev->ndev->be, queue_id->hw_id / 4, 1);
+
+ return 0;
+}
+
+int flow_delete_eth_dev(struct flow_eth_dev *eth_dev)
+{
+ struct flow_nic_dev *ndev = eth_dev->ndev;
+
+ if (!ndev) {
+ /* Error invalid nic device */
+ return -1;
+ }
+
+ NT_LOG(DBG, FILTER, "Delete eth-port device %p, port %i\n", eth_dev,
+ eth_dev->port);
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_WRITE);
+#endif
+
+ /* delete all created flows from this device */
+ pthread_mutex_lock(&ndev->mtx);
+
+ struct flow_handle *flow = ndev->flow_base;
+
+ while (flow) {
+ if (flow->dev == eth_dev) {
+ struct flow_handle *flow_next = flow->next;
+
+ if (ndev->flow_profile ==
+ FLOW_ETH_DEV_PROFILE_VSWITCH) {
+ NT_LOG(ERR, FILTER, "vSwitch profile not supported");
+ return -1;
+ }
+ flow_destroy_locked_profile_inline(eth_dev,
+ flow, NULL);
+ flow = flow_next;
+ } else {
+ flow = flow->next;
+ }
+ }
+
+ /*
+ * remove unmatched queue if setup in QSL
+ * remove exception queue setting in QSL UNM
+ */
+ hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_DEST_QUEUE, eth_dev->port,
+ 0);
+ hw_mod_qsl_unmq_set(&ndev->be, HW_QSL_UNMQ_EN, eth_dev->port, 0);
+ hw_mod_qsl_unmq_flush(&ndev->be, eth_dev->port, 1);
+
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_INLINE) {
+ for (int i = 0; i < eth_dev->num_queues; ++i) {
+ uint32_t qen_value = 0;
+ uint32_t queue_id =
+ (uint32_t)eth_dev->rx_queue[i].hw_id;
+
+ hw_mod_qsl_qen_get(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4, &qen_value);
+ hw_mod_qsl_qen_set(&ndev->be, HW_QSL_QEN_EN,
+ queue_id / 4,
+ qen_value & ~(1U << (queue_id % 4)));
+ hw_mod_qsl_qen_flush(&ndev->be, queue_id / 4, 1);
+ }
+ }
+
+#ifdef FLOW_DEBUG
+ ndev->be.iface->set_debug_mode(ndev->be.be_dev,
+ FLOW_BACKEND_DEBUG_MODE_NONE);
+#endif
+
+#ifndef SCATTER_GATHER
+ /* free rx queues */
+ for (int i = 0; i < eth_dev->num_queues; i++) {
+ ndev->be.iface->free_rx_queue(ndev->be.be_dev,
+ eth_dev->rx_queue[i].hw_id);
+ flow_nic_deref_resource(ndev, RES_QUEUE,
+ eth_dev->rx_queue[i].id);
+ }
+#endif
+
+ /* take eth_dev out of ndev list */
+ if (nic_remove_eth_port_dev(ndev, eth_dev) != 0)
+ NT_LOG(ERR, FILTER, "ERROR : eth_dev %p not found\n", eth_dev);
+
+ pthread_mutex_unlock(&ndev->mtx);
+
+ /* free eth_dev */
+ free(eth_dev);
+ return 0;
+}
+
+int flow_get_tunnel_definition(struct tunnel_cfg_s *tun, uint32_t flow_stat_id,
+ uint8_t vport)
+{
+ return tunnel_get_definition(tun, flow_stat_id, vport);
+}
+
+/*
+ * ***************************** Flow API NIC Setup ***************************************
+ * Flow backend creation function - register and initialize common backend API to FPA modules
+ * ******************************************************************************************
+ */
+
+static int init_resource_elements(struct flow_nic_dev *ndev,
+ enum res_type_e res_type, uint32_t count)
+{
+ assert(ndev->res[res_type].alloc_bm == NULL);
+ /* allocate bitmap and ref counter */
+ ndev->res[res_type].alloc_bm =
+ calloc(1, BIT_CONTAINER_8_ALIGN(count) + count * sizeof(uint32_t));
+ if (ndev->res[res_type].alloc_bm) {
+ ndev->res[res_type].ref =
+ (uint32_t *)&ndev->res[res_type]
+ .alloc_bm[BIT_CONTAINER_8_ALIGN(count)];
+ ndev->res[res_type].resource_count = count;
+ return 0;
+ }
+ return -1;
+}
+
+static void done_resource_elements(struct flow_nic_dev *ndev,
+ enum res_type_e res_type)
+{
+ assert(ndev);
+ if (ndev->res[res_type].alloc_bm)
+ free(ndev->res[res_type].alloc_bm);
+}
+
+static void list_insert_flow_nic(struct flow_nic_dev *ndev)
+{
+ pthread_mutex_lock(&base_mtx);
+ ndev->next = dev_base;
+ dev_base = ndev;
+ pthread_mutex_unlock(&base_mtx);
+}
+
+static int list_remove_flow_nic(struct flow_nic_dev *ndev)
+{
+ pthread_mutex_lock(&base_mtx);
+ struct flow_nic_dev *nic_dev = dev_base, *prev = NULL;
+
+ while (nic_dev) {
+ if (nic_dev == ndev) {
+ if (prev)
+ prev->next = nic_dev->next;
+ else
+ dev_base = nic_dev->next;
+ pthread_mutex_unlock(&base_mtx);
+ return 0;
+ }
+ prev = nic_dev;
+ nic_dev = nic_dev->next;
+ }
+
+ pthread_mutex_unlock(&base_mtx);
+ return -1;
+}
+
+struct flow_nic_dev *flow_api_create(uint8_t adapter_no,
+ const struct flow_api_backend_ops *be_if,
+ void *be_dev)
+{
+ if (!be_if || be_if->version != 1) {
+ NT_LOG(DBG, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+ }
+
+ struct flow_nic_dev *ndev = calloc(1, sizeof(struct flow_nic_dev));
+
+ if (!ndev) {
+ NT_LOG(ERR, FILTER, "ERROR: calloc failed\n");
+ return NULL;
+ }
+
+ /*
+ * To dump module initialization writes use
+ * FLOW_BACKEND_DEBUG_MODE_WRITE
+ * then remember to set it ...NONE afterwards again
+ */
+ be_if->set_debug_mode(be_dev, FLOW_BACKEND_DEBUG_MODE_NONE);
+
+ if (flow_api_backend_init(&ndev->be, be_if, be_dev) != 0)
+ goto err_exit;
+ ndev->adapter_no = adapter_no;
+
+ ndev->ports = (uint16_t)((ndev->be.num_rx_ports > 256) ?
+ 256 :
+ ndev->be.num_rx_ports);
+
+ /*
+ * Free resources in NIC must be managed by this module
+ * Get resource sizes and create resource manager elements
+ */
+ if (init_resource_elements(ndev, RES_QUEUE, ndev->be.max_queues))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_CFN,
+ ndev->be.cat.nb_cat_funcs))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_COT, ndev->be.max_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_EXO, ndev->be.cat.nb_pm_ext))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_CAT_LEN, ndev->be.cat.nb_len))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_KM_FLOW_TYPE,
+ ndev->be.cat.nb_flow_types))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_KM_CATEGORY,
+ ndev->be.km.nb_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_HSH_RCP, ndev->be.hsh.nb_rcp))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_PDB_RCP,
+ ndev->be.pdb.nb_pdb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_QSL_RCP,
+ ndev->be.qsl.nb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_QSL_QST,
+ ndev->be.qsl.nb_qst_entries))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_SLC_RCP, ndev->be.max_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_IOA_RCP,
+ ndev->be.ioa.nb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_ROA_RCP,
+ ndev->be.roa.nb_tun_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_FLM_FLOW_TYPE,
+ ndev->be.cat.nb_flow_types))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_FLM_RCP,
+ ndev->be.flm.nb_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_HST_RCP,
+ ndev->be.hst.nb_hst_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_TPE_RCP,
+ ndev->be.tpe.nb_rcp_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_TPE_EXT,
+ ndev->be.tpe.nb_rpl_ext_categories))
+ goto err_exit;
+ if (init_resource_elements(ndev, RES_TPE_RPL,
+ ndev->be.tpe.nb_rpl_depth))
+ goto err_exit;
+
+ /* may need IPF, COR */
+
+ /* check all defined has been initialized */
+ for (int i = 0; i < RES_COUNT; i++)
+ assert(ndev->res[i].alloc_bm);
+
+ pthread_mutex_init(&ndev->mtx, NULL);
+ list_insert_flow_nic(ndev);
+
+ return ndev;
+
+err_exit:
+ if (ndev)
+ flow_api_done(ndev);
+ NT_LOG(DBG, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+}
+
+int flow_api_done(struct flow_nic_dev *ndev)
+{
+ NT_LOG(DBG, FILTER, "FLOW API DONE\n");
+ if (ndev) {
+ flow_ndev_reset(ndev);
+
+ /* delete resource management allocations for this ndev */
+ for (int i = 0; i < RES_COUNT; i++)
+ done_resource_elements(ndev, i);
+
+ flow_api_backend_done(&ndev->be);
+ list_remove_flow_nic(ndev);
+ free(ndev);
+ }
+ return 0;
+}
+
+void *flow_api_get_be_dev(struct flow_nic_dev *ndev)
+{
+ if (!ndev) {
+ NT_LOG(DBG, FILTER, "ERR: %s\n", __func__);
+ return NULL;
+ }
+ return ndev->be.be_dev;
+}
+
+int flow_get_num_queues(uint8_t adapter_no, uint8_t port_no)
+{
+ struct flow_eth_dev *eth_dev =
+ nic_and_port_to_eth_dev(adapter_no, port_no);
+ return eth_dev->num_queues;
+}
+
+int flow_get_hw_id(uint8_t adapter_no, uint8_t port_no, uint8_t queue_no)
+{
+ struct flow_eth_dev *eth_dev =
+ nic_and_port_to_eth_dev(adapter_no, port_no);
+ return eth_dev->rx_queue[queue_no].hw_id;
+}
+
+int flow_get_flm_stats(struct flow_nic_dev *ndev, uint64_t *data, uint64_t size)
+{
+ if (ndev->flow_profile == FLOW_ETH_DEV_PROFILE_INLINE)
+ return flow_get_flm_stats_profile_inline(ndev, data, size);
+ return -1;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.h b/drivers/net/ntnic/nthw/flow_api/flow_api.h
new file mode 100644
index 0000000000..9dbaac49e8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api.h
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef _FLOW_API_H_
+#define _FLOW_API_H_
+
+#include <pthread.h>
+
+#include "ntlog.h"
+#include "stream_binary_flow_api.h"
+
+#include "flow_api_actions.h"
+#include "flow_api_backend.h"
+#include "flow_api_engine.h"
+
+/*
+ * ****************************************************
+ * Flow NIC and Eth port device management
+ * ****************************************************
+ */
+
+struct hw_mod_resource_s {
+ uint8_t *alloc_bm; /* allocation bitmap */
+ uint32_t *ref; /* reference counter for each resource element */
+ uint32_t resource_count; /* number of total available entries */
+};
+
+/*
+ * Set of definitions to be used to map desirable fields for RSS
+ * hash functions. Supposed to be used with dpdk, so the values
+ * correspond to dpdk definitions, but we avoid dependency to
+ * dpdk headers here.
+ */
+
+#define NT_ETH_RSS_IPV4 (UINT64_C(1) << 2)
+#define NT_ETH_RSS_FRAG_IPV4 (UINT64_C(1) << 3)
+#define NT_ETH_RSS_NONFRAG_IPV4_OTHER (UINT64_C(1) << 7)
+#define NT_ETH_RSS_IPV6 (UINT64_C(1) << 8)
+#define NT_ETH_RSS_FRAG_IPV6 (UINT64_C(1) << 9)
+#define NT_ETH_RSS_NONFRAG_IPV6_OTHER (UINT64_C(1) << 13)
+#define NT_ETH_RSS_IPV6_EX (UINT64_C(1) << 15)
+#define NT_ETH_RSS_C_VLAN (UINT64_C(1) << 26)
+#define NT_ETH_RSS_L3_DST_ONLY (UINT64_C(1) << 62)
+#define NT_ETH_RSS_L3_SRC_ONLY (UINT64_C(1) << 63)
+
+#define NT_ETH_RSS_IP \
+ (NT_ETH_RSS_IPV4 | NT_ETH_RSS_FRAG_IPV4 | \
+ NT_ETH_RSS_NONFRAG_IPV4_OTHER | NT_ETH_RSS_IPV6 | \
+ NT_ETH_RSS_FRAG_IPV6 | NT_ETH_RSS_NONFRAG_IPV6_OTHER | \
+ NT_ETH_RSS_IPV6_EX)
+
+/*
+ * level 1, requests RSS to be performed on the outermost packet
+ * encapsulation level.
+ */
+#define NT_ETH_RSS_LEVEL_OUTERMOST (UINT64_C(1) << 50)
+
+/*
+ * level 2, requests RSS to be performed on the specified inner packet
+ * encapsulation level, from outermost to innermost (lower to higher values).
+ */
+#define NT_ETH_RSS_LEVEL_INNERMOST (UINT64_C(2) << 50)
+
+/*
+ * Struct wrapping unsigned 64 bit integer carry RSS hash option bits
+ * to avoid occasional incorrect usage interfacing with higher level
+ * framework (e.g. DPDK)
+ */
+struct nt_eth_rss {
+ uint64_t fields;
+};
+
+struct flow_eth_dev {
+ struct flow_nic_dev *ndev; /* NIC that owns this port device */
+ uint8_t port; /* NIC port id */
+ uint32_t port_id; /* App assigned port_id - may be DPDK port_id */
+
+ struct flow_queue_id_s
+ rx_queue[FLOW_MAX_QUEUES + 1]; /* 0th for exception */
+ int num_queues; /* VSWITCH has exceptions sent on queue 0 per design */
+
+ int rss_target_id; /* QSL_HSH index if RSS needed QSL v6+ */
+ struct flow_eth_dev *next;
+};
+
+enum flow_nic_hash_e {
+ HASH_ALGO_ROUND_ROBIN = 0,
+ HASH_ALGO_5TUPLE,
+};
+
+/* registered NIC backends */
+struct flow_nic_dev {
+ uint8_t adapter_no; /* physical adapter no in the host system */
+ uint16_t ports; /* number of in-ports addressable on this NIC */
+ enum flow_eth_dev_profile
+ flow_profile; /* flow profile this NIC is initially prepared for */
+ int flow_mgnt_prepared;
+
+ struct hw_mod_resource_s
+ res[RES_COUNT]; /* raw NIC resource allocation table */
+ void *flm_res_handle;
+ void *km_res_handle;
+ void *kcc_res_handle;
+
+ void *flm_mtr_handle;
+ void *ft_res_handle;
+ void *mtr_stat_handle;
+ void *group_handl