Add HW interface registers and initialize the HW
interface.

Signed-off-by: Yanling Song <son...@ramaxel.com>
---
 drivers/net/spnic/base/meson.build   |   2 +
 drivers/net/spnic/base/spnic_csr.h   | 104 ++++
 drivers/net/spnic/base/spnic_hwdev.c |  41 ++
 drivers/net/spnic/base/spnic_hwdev.h |  29 +
 drivers/net/spnic/base/spnic_hwif.c  | 774 +++++++++++++++++++++++++++
 drivers/net/spnic/base/spnic_hwif.h  | 155 ++++++
 drivers/net/spnic/spnic_ethdev.c     |  66 +++
 drivers/net/spnic/spnic_ethdev.h     |  48 +-
 8 files changed, 1212 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/spnic/base/spnic_csr.h
 create mode 100644 drivers/net/spnic/base/spnic_hwdev.c
 create mode 100644 drivers/net/spnic/base/spnic_hwdev.h
 create mode 100644 drivers/net/spnic/base/spnic_hwif.c
 create mode 100644 drivers/net/spnic/base/spnic_hwif.h

diff --git a/drivers/net/spnic/base/meson.build 
b/drivers/net/spnic/base/meson.build
index e83a473881..edd6e94772 100644
--- a/drivers/net/spnic/base/meson.build
+++ b/drivers/net/spnic/base/meson.build
@@ -2,6 +2,8 @@
 # Copyright(c) 2021 Ramaxel Memory Technology, Ltd
 
 sources = [
+       'spnic_hwdev.c',
+       'spnic_hwif.c'
 ]
 
 extra_flags = []
diff --git a/drivers/net/spnic/base/spnic_csr.h 
b/drivers/net/spnic/base/spnic_csr.h
new file mode 100644
index 0000000000..b4cf7c2593
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_csr.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_CSR_H_
+#define _SPNIC_CSR_H_
+
+#define PCI_VENDOR_ID_RAMAXEL                  0x1E81
+
+/* Device ids */
+#define SPNIC_DEV_ID_PF                                0x9020
+#define SPNIC_DEV_ID_VF                                0x9001
+
+/*
+ * Bit30/bit31 for bar index flag
+ * 00: bar0
+ * 01: bar1
+ * 10: bar2
+ * 11: bar3
+ */
+#define SPNIC_CFG_REGS_FLAG                    0x40000000
+
+#define SPNIC_MGMT_REGS_FLAG                   0xC0000000
+
+#define SPNIC_REGS_FLAG_MASK                   0x3FFFFFFF
+
+#define SPNIC_VF_CFG_REG_OFFSET                 0x2000
+
+#define SPNIC_HOST_CSR_BASE_ADDR               (SPNIC_MGMT_REGS_FLAG + 0x6000)
+#define SPNIC_CSR_GLOBAL_BASE_ADDR             (SPNIC_MGMT_REGS_FLAG + 0x6400)
+
+/* HW interface registers */
+#define SPNIC_CSR_FUNC_ATTR0_ADDR              (SPNIC_CFG_REGS_FLAG + 0x0)
+#define SPNIC_CSR_FUNC_ATTR1_ADDR              (SPNIC_CFG_REGS_FLAG + 0x4)
+#define SPNIC_CSR_FUNC_ATTR2_ADDR              (SPNIC_CFG_REGS_FLAG + 0x8)
+#define SPNIC_CSR_FUNC_ATTR3_ADDR              (SPNIC_CFG_REGS_FLAG + 0xC)
+#define SPNIC_CSR_FUNC_ATTR4_ADDR              (SPNIC_CFG_REGS_FLAG + 0x10)
+#define SPNIC_CSR_FUNC_ATTR5_ADDR              (SPNIC_CFG_REGS_FLAG + 0x14)
+#define SPNIC_CSR_FUNC_ATTR6_ADDR              (SPNIC_CFG_REGS_FLAG + 0x18)
+
+#define SPNIC_FUNC_CSR_MAILBOX_DATA_OFF        0x80
+#define SPNIC_FUNC_CSR_MAILBOX_CONTROL_OFF     (SPNIC_CFG_REGS_FLAG + 0x0100)
+#define SPNIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF  (SPNIC_CFG_REGS_FLAG + 0x0104)
+#define SPNIC_FUNC_CSR_MAILBOX_RESULT_H_OFF    (SPNIC_CFG_REGS_FLAG + 0x0108)
+#define SPNIC_FUNC_CSR_MAILBOX_RESULT_L_OFF    (SPNIC_CFG_REGS_FLAG + 0x010C)
+
+#define SPNIC_PPF_ELECTION_OFFSET              0x0
+#define SPNIC_MPF_ELECTION_OFFSET              0x20
+
+#define SPNIC_CSR_PPF_ELECTION_ADDR            \
+                       (SPNIC_HOST_CSR_BASE_ADDR + SPNIC_PPF_ELECTION_OFFSET)
+
+#define SPNIC_CSR_GLOBAL_MPF_ELECTION_ADDR             \
+                       (SPNIC_HOST_CSR_BASE_ADDR + SPNIC_MPF_ELECTION_OFFSET)
+
+#define SPNIC_CSR_DMA_ATTR_TBL_ADDR            (SPNIC_CFG_REGS_FLAG + 0x380)
+#define SPNIC_CSR_DMA_ATTR_INDIR_IDX_ADDR      (SPNIC_CFG_REGS_FLAG + 0x390)
+
+/* MSI-X registers */
+#define SPNIC_CSR_MSIX_INDIR_IDX_ADDR          (SPNIC_CFG_REGS_FLAG + 0x310)
+#define SPNIC_CSR_MSIX_CTRL_ADDR               (SPNIC_CFG_REGS_FLAG + 0x300)
+#define SPNIC_CSR_MSIX_CNT_ADDR                        (SPNIC_CFG_REGS_FLAG + 
0x304)
+#define SPNIC_CSR_FUNC_MSI_CLR_WR_ADDR         (SPNIC_CFG_REGS_FLAG + 0x58)
+
+#define SPNIC_MSI_CLR_INDIR_RESEND_TIMER_CLR_SHIFT     0
+#define SPNIC_MSI_CLR_INDIR_INT_MSK_SET_SHIFT          1
+#define SPNIC_MSI_CLR_INDIR_INT_MSK_CLR_SHIFT          2
+#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_SET_SHIFT         3
+#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_CLR_SHIFT         4
+#define SPNIC_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_SHIFT     22
+
+#define SPNIC_MSI_CLR_INDIR_RESEND_TIMER_CLR_MASK      0x1U
+#define SPNIC_MSI_CLR_INDIR_INT_MSK_SET_MASK           0x1U
+#define SPNIC_MSI_CLR_INDIR_INT_MSK_CLR_MASK           0x1U
+#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_SET_MASK          0x1U
+#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_CLR_MASK          0x1U
+#define SPNIC_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_MASK      0x3FFU
+
+#define SPNIC_MSI_CLR_INDIR_SET(val, member)           \
+               (((val) & SPNIC_MSI_CLR_INDIR_##member##_MASK) << \
+               SPNIC_MSI_CLR_INDIR_##member##_SHIFT)
+
+/* EQ registers */
+#define SPNIC_AEQ_INDIR_IDX_ADDR               (SPNIC_CFG_REGS_FLAG + 0x210)
+
+#define SPNIC_AEQ_MTT_OFF_BASE_ADDR            (SPNIC_CFG_REGS_FLAG + 0x240)
+
+#define SPNIC_CSR_EQ_PAGE_OFF_STRIDE                   8
+
+#define SPNIC_AEQ_HI_PHYS_ADDR_REG(pg_num)     \
+               (SPNIC_AEQ_MTT_OFF_BASE_ADDR + \
+               (pg_num) * SPNIC_CSR_EQ_PAGE_OFF_STRIDE)
+
+#define SPNIC_AEQ_LO_PHYS_ADDR_REG(pg_num)     \
+               (SPNIC_AEQ_MTT_OFF_BASE_ADDR + \
+               (pg_num) * SPNIC_CSR_EQ_PAGE_OFF_STRIDE + 4)
+
+#define SPNIC_CSR_AEQ_CTRL_0_ADDR              (SPNIC_CFG_REGS_FLAG + 0x200)
+#define SPNIC_CSR_AEQ_CTRL_1_ADDR              (SPNIC_CFG_REGS_FLAG + 0x204)
+#define SPNIC_CSR_AEQ_CONS_IDX_ADDR            (SPNIC_CFG_REGS_FLAG + 0x208)
+#define SPNIC_CSR_AEQ_PROD_IDX_ADDR            (SPNIC_CFG_REGS_FLAG + 0x20C)
+#define SPNIC_CSR_AEQ_CI_SIMPLE_INDIR_ADDR     (SPNIC_CFG_REGS_FLAG + 0x50)
+
+#endif /* _SPNIC_CSR_H_ */
diff --git a/drivers/net/spnic/base/spnic_hwdev.c 
b/drivers/net/spnic/base/spnic_hwdev.c
new file mode 100644
index 0000000000..de73f244fd
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_hwdev.c
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include "spnic_compat.h"
+#include "spnic_csr.h"
+#include "spnic_hwif.h"
+#include "spnic_hwdev.h"
+
+int spnic_init_hwdev(struct spnic_hwdev *hwdev)
+{
+       int err;
+
+       hwdev->chip_fault_stats = rte_zmalloc("chip_fault_stats",
+                                             SPNIC_CHIP_FAULT_SIZE,
+                                             RTE_CACHE_LINE_SIZE);
+       if (!hwdev->chip_fault_stats) {
+               PMD_DRV_LOG(ERR, "Alloc memory for chip_fault_stats failed");
+               return -ENOMEM;
+       }
+
+       err = spnic_init_hwif(hwdev);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Initialize hwif failed");
+               goto init_hwif_err;
+       }
+
+       return 0;
+
+init_hwif_err:
+       rte_free(hwdev->chip_fault_stats);
+
+       return -EFAULT;
+}
+
+void spnic_free_hwdev(struct spnic_hwdev *hwdev)
+{
+       spnic_free_hwif(hwdev);
+
+       rte_free(hwdev->chip_fault_stats);
+}
diff --git a/drivers/net/spnic/base/spnic_hwdev.h 
b/drivers/net/spnic/base/spnic_hwdev.h
new file mode 100644
index 0000000000..c89a4fa840
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_hwdev.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_HWDEV_H_
+#define _SPNIC_HWDEV_H_
+
+#include <rte_ether.h>
+
+#define SPNIC_CHIP_FAULT_SIZE          (110 * 1024)
+
+struct spnic_hwdev {
+       void *dev_handle; /* Pointer to spnic_nic_dev */
+       void *pci_dev; /* Pointer to rte_pci_device */
+       void *eth_dev; /* Pointer to rte_eth_dev */
+
+       uint16_t port_id;
+
+       struct spnic_hwif *hwif;
+       u8 *chip_fault_stats;
+
+       u16 max_vfs;
+       u16 link_status;
+};
+
+int spnic_init_hwdev(struct spnic_hwdev *hwdev);
+
+void spnic_free_hwdev(struct spnic_hwdev *hwdev);
+#endif /* _SPNIC_HWDEV_H_ */
diff --git a/drivers/net/spnic/base/spnic_hwif.c 
b/drivers/net/spnic/base/spnic_hwif.c
new file mode 100644
index 0000000000..d61061ccfa
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_hwif.c
@@ -0,0 +1,774 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <rte_bus_pci.h>
+#include "spnic_compat.h"
+#include "spnic_csr.h"
+#include "spnic_hwdev.h"
+#include "spnic_hwif.h"
+
+#define WAIT_HWIF_READY_TIMEOUT                        10000
+
+#define DB_IDX(db, db_base)    \
+       ((u32)(((u64)(db) - (u64)(db_base)) /   \
+       SPNIC_DB_PAGE_SIZE))
+
+#define SPNIC_AF0_FUNC_GLOBAL_IDX_SHIFT                0
+#define SPNIC_AF0_P2P_IDX_SHIFT                        12
+#define SPNIC_AF0_PCI_INTF_IDX_SHIFT           17
+#define SPNIC_AF0_VF_IN_PF_SHIFT               20
+#define SPNIC_AF0_FUNC_TYPE_SHIFT              28
+
+#define SPNIC_AF0_FUNC_GLOBAL_IDX_MASK         0xFFF
+#define SPNIC_AF0_P2P_IDX_MASK                 0x1F
+#define SPNIC_AF0_PCI_INTF_IDX_MASK            0x7
+#define SPNIC_AF0_VF_IN_PF_MASK                        0xFF
+#define SPNIC_AF0_FUNC_TYPE_MASK               0x1
+
+#define SPNIC_AF0_GET(val, member)                             \
+       (((val) >> SPNIC_AF0_##member##_SHIFT) & SPNIC_AF0_##member##_MASK)
+
+#define SPNIC_AF1_PPF_IDX_SHIFT                        0
+#define SPNIC_AF1_AEQS_PER_FUNC_SHIFT          8
+#define SPNIC_AF1_MGMT_INIT_STATUS_SHIFT       30
+#define SPNIC_AF1_PF_INIT_STATUS_SHIFT         31
+
+#define SPNIC_AF1_PPF_IDX_MASK                 0x3F
+#define SPNIC_AF1_AEQS_PER_FUNC_MASK           0x3
+#define SPNIC_AF1_MGMT_INIT_STATUS_MASK                0x1
+#define SPNIC_AF1_PF_INIT_STATUS_MASK          0x1
+
+#define SPNIC_AF1_GET(val, member)                             \
+       (((val) >> SPNIC_AF1_##member##_SHIFT) & SPNIC_AF1_##member##_MASK)
+
+#define SPNIC_AF2_CEQS_PER_FUNC_SHIFT          0
+#define SPNIC_AF2_DMA_ATTR_PER_FUNC_SHIFT      9
+#define SPNIC_AF2_IRQS_PER_FUNC_SHIFT          16
+
+#define SPNIC_AF2_CEQS_PER_FUNC_MASK           0x1FF
+#define SPNIC_AF2_DMA_ATTR_PER_FUNC_MASK       0x7
+#define SPNIC_AF2_IRQS_PER_FUNC_MASK           0x7FF
+
+#define SPNIC_AF2_GET(val, member)                             \
+       (((val) >> SPNIC_AF2_##member##_SHIFT) & SPNIC_AF2_##member##_MASK)
+
+#define SPNIC_AF3_GLOBAL_VF_ID_OF_NXT_PF_SHIFT 0
+#define SPNIC_AF3_GLOBAL_VF_ID_OF_PF_SHIFT     16
+
+#define SPNIC_AF3_GLOBAL_VF_ID_OF_NXT_PF_MASK  0xFFF
+#define SPNIC_AF3_GLOBAL_VF_ID_OF_PF_MASK      0xFFF
+
+#define SPNIC_AF3_GET(val, member)                             \
+       (((val) >> SPNIC_AF3_##member##_SHIFT) & SPNIC_AF3_##member##_MASK)
+
+#define SPNIC_AF4_DOORBELL_CTRL_SHIFT          0
+#define SPNIC_AF4_DOORBELL_CTRL_MASK           0x1
+
+#define SPNIC_AF4_GET(val, member)                             \
+       (((val) >> SPNIC_AF4_##member##_SHIFT) & SPNIC_AF4_##member##_MASK)
+
+#define SPNIC_AF4_SET(val, member)                             \
+       (((val) & SPNIC_AF4_##member##_MASK) << SPNIC_AF4_##member##_SHIFT)
+
+#define SPNIC_AF4_CLEAR(val, member)                           \
+       ((val) & (~(SPNIC_AF4_##member##_MASK <<                \
+       SPNIC_AF4_##member##_SHIFT)))
+
+#define SPNIC_AF5_OUTBOUND_CTRL_SHIFT          0
+#define SPNIC_AF5_OUTBOUND_CTRL_MASK           0x1
+
+#define SPNIC_AF5_GET(val, member)                             \
+       (((val) >> SPNIC_AF5_##member##_SHIFT) & SPNIC_AF5_##member##_MASK)
+
+#define SPNIC_AF5_SET(val, member)                             \
+       (((val) & SPNIC_AF5_##member##_MASK) << SPNIC_AF5_##member##_SHIFT)
+
+#define SPNIC_AF5_CLEAR(val, member)                           \
+       ((val) & (~(SPNIC_AF5_##member##_MASK <<                \
+       SPNIC_AF5_##member##_SHIFT)))
+
+#define SPNIC_AF6_PF_STATUS_SHIFT              0
+#define SPNIC_AF6_PF_STATUS_MASK               0xFFFF
+
+#define SPNIC_AF6_SET(val, member)                             \
+       ((((u32)(val)) & SPNIC_AF6_##member##_MASK) <<          \
+       SPNIC_AF6_##member##_SHIFT)
+
+#define SPNIC_AF6_GET(val, member)                             \
+       (((val) >> SPNIC_AF6_##member##_SHIFT) & SPNIC_AF6_##member##_MASK)
+
+#define SPNIC_AF6_CLEAR(val, member)                           \
+       ((val) & (~(SPNIC_AF6_##member##_MASK <<                \
+       SPNIC_AF6_##member##_SHIFT)))
+
+#define SPNIC_PPF_ELECTION_IDX_SHIFT           0
+
+#define SPNIC_PPF_ELECTION_IDX_MASK            0x3F
+
+#define SPNIC_PPF_ELECTION_SET(val, member)                    \
+       (((val) & SPNIC_PPF_ELECTION_##member##_MASK) <<        \
+               SPNIC_PPF_ELECTION_##member##_SHIFT)
+
+#define SPNIC_PPF_ELECTION_GET(val, member)                    \
+       (((val) >> SPNIC_PPF_ELECTION_##member##_SHIFT) &       \
+               SPNIC_PPF_ELECTION_##member##_MASK)
+
+#define SPNIC_PPF_ELECTION_CLEAR(val, member)                  \
+       ((val) & (~(SPNIC_PPF_ELECTION_##member##_MASK  \
+               << SPNIC_PPF_ELECTION_##member##_SHIFT)))
+
+#define SPNIC_MPF_ELECTION_IDX_SHIFT           0
+
+#define SPNIC_MPF_ELECTION_IDX_MASK            0x1F
+
+#define SPNIC_MPF_ELECTION_SET(val, member)                    \
+       (((val) & SPNIC_MPF_ELECTION_##member##_MASK) <<        \
+               SPNIC_MPF_ELECTION_##member##_SHIFT)
+
+#define SPNIC_MPF_ELECTION_GET(val, member)                    \
+       (((val) >> SPNIC_MPF_ELECTION_##member##_SHIFT) &       \
+               SPNIC_MPF_ELECTION_##member##_MASK)
+
+#define SPNIC_MPF_ELECTION_CLEAR(val, member)                  \
+       ((val) & (~(SPNIC_MPF_ELECTION_##member##_MASK  \
+               << SPNIC_MPF_ELECTION_##member##_SHIFT)))
+
+#define SPNIC_GET_REG_FLAG(reg)        ((reg) & (~(SPNIC_REGS_FLAG_MASK)))
+
+#define SPNIC_GET_REG_ADDR(reg)        ((reg) & (SPNIC_REGS_FLAG_MASK))
+
+#define SPNIC_IS_VF_DEV(pdev)  ((pdev)->id.device_id == SPNIC_DEV_ID_VF)
+
+u32 spnic_hwif_read_reg(struct spnic_hwif *hwif, u32 reg)
+{
+       if (SPNIC_GET_REG_FLAG(reg) == SPNIC_MGMT_REGS_FLAG)
+               return be32_to_cpu(rte_read32(hwif->mgmt_regs_base +
+                                  SPNIC_GET_REG_ADDR(reg)));
+       else
+               return be32_to_cpu(rte_read32(hwif->cfg_regs_base +
+                                  SPNIC_GET_REG_ADDR(reg)));
+}
+
+void spnic_hwif_write_reg(struct spnic_hwif *hwif, u32 reg, u32 val)
+{
+       if (SPNIC_GET_REG_FLAG(reg) == SPNIC_MGMT_REGS_FLAG)
+               rte_write32(cpu_to_be32(val),
+                      hwif->mgmt_regs_base + SPNIC_GET_REG_ADDR(reg));
+       else
+               rte_write32(cpu_to_be32(val),
+                      hwif->cfg_regs_base + SPNIC_GET_REG_ADDR(reg));
+}
+
+/**
+ * Judge whether HW initialization ok
+ *
+ * @param[in] hwdev
+ *   The pointer to the private hardware device object
+ *
+ * @retval zero: Success
+ * @retval negative: Failure
+ */
+static int hwif_ready(struct spnic_hwdev *hwdev)
+{
+       u32 addr, attr1;
+
+       addr   = SPNIC_CSR_FUNC_ATTR1_ADDR;
+       attr1  = spnic_hwif_read_reg(hwdev->hwif, addr);
+       if (attr1 == SPNIC_PCIE_LINK_DOWN)
+               return -EBUSY;
+
+       if (!SPNIC_AF1_GET(attr1, MGMT_INIT_STATUS))
+               return -EBUSY;
+
+       return 0;
+}
+
+static int wait_hwif_ready(struct spnic_hwdev *hwdev)
+{
+       u64 timeout = 0;
+
+       do {
+               if (!hwif_ready(hwdev))
+                       return 0;
+
+               rte_delay_ms(1);
+               timeout++;
+       } while (timeout <= WAIT_HWIF_READY_TIMEOUT);
+
+       PMD_DRV_LOG(ERR, "Hwif is not ready");
+       return -EBUSY;
+}
+
+/**
+ * Set the attributes as members in hwif
+ *
+ * @param[in] hwif
+ *   The hardware interface of a pci function device
+ * @param[in] attr0
+ *   The first attribute that was read from the hw
+ * @param[in] attr1
+ *   The second attribute that was read from the hw
+ * @param[in] attr2
+ *   The third attribute that was read from the hw
+ * @param[in] attr3
+ *   The fourth attribute that was read from the hw
+ */
+static void set_hwif_attr(struct spnic_hwif *hwif, u32 attr0, u32 attr1,
+                         u32 attr2, u32 attr3)
+{
+       hwif->attr.func_global_idx = SPNIC_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+       hwif->attr.port_to_port_idx = SPNIC_AF0_GET(attr0, P2P_IDX);
+       hwif->attr.pci_intf_idx = SPNIC_AF0_GET(attr0, PCI_INTF_IDX);
+       hwif->attr.vf_in_pf = SPNIC_AF0_GET(attr0, VF_IN_PF);
+       hwif->attr.func_type = SPNIC_AF0_GET(attr0, FUNC_TYPE);
+
+       hwif->attr.ppf_idx = SPNIC_AF1_GET(attr1, PPF_IDX);
+       hwif->attr.num_aeqs = BIT(SPNIC_AF1_GET(attr1, AEQS_PER_FUNC));
+
+       hwif->attr.num_ceqs = (u8)SPNIC_AF2_GET(attr2, CEQS_PER_FUNC);
+       hwif->attr.num_irqs = SPNIC_AF2_GET(attr2, IRQS_PER_FUNC);
+       hwif->attr.num_dma_attr = BIT(SPNIC_AF2_GET(attr2, DMA_ATTR_PER_FUNC));
+
+       hwif->attr.global_vf_id_of_pf = SPNIC_AF3_GET(attr3,
+                                                     GLOBAL_VF_ID_OF_PF);
+}
+
+/**
+ * Read and set the attributes as members in hwif
+ *
+ * @param[in] hwif
+ *   The hardware interface of a pci function device
+ */
+static void get_hwif_attr(struct spnic_hwif *hwif)
+{
+       u32 addr, attr0, attr1, attr2, attr3;
+
+       addr   = SPNIC_CSR_FUNC_ATTR0_ADDR;
+       attr0  = spnic_hwif_read_reg(hwif, addr);
+
+       addr   = SPNIC_CSR_FUNC_ATTR1_ADDR;
+       attr1  = spnic_hwif_read_reg(hwif, addr);
+
+       addr   = SPNIC_CSR_FUNC_ATTR2_ADDR;
+       attr2  = spnic_hwif_read_reg(hwif, addr);
+
+       addr   = SPNIC_CSR_FUNC_ATTR3_ADDR;
+       attr3  = spnic_hwif_read_reg(hwif, addr);
+
+       set_hwif_attr(hwif, attr0, attr1, attr2, attr3);
+}
+
+void spnic_set_pf_status(struct spnic_hwif *hwif, enum spnic_pf_status status)
+{
+       u32 attr6 = SPNIC_AF6_SET(status, PF_STATUS);
+       u32 addr  = SPNIC_CSR_FUNC_ATTR6_ADDR;
+
+       if (hwif->attr.func_type == TYPE_VF)
+               return;
+
+       spnic_hwif_write_reg(hwif, addr, attr6);
+}
+
+enum spnic_pf_status spnic_get_pf_status(struct spnic_hwif *hwif)
+{
+       u32 attr6 = spnic_hwif_read_reg(hwif, SPNIC_CSR_FUNC_ATTR6_ADDR);
+
+       return SPNIC_AF6_GET(attr6, PF_STATUS);
+}
+
+static enum spnic_doorbell_ctrl
+spnic_get_doorbell_ctrl_status(struct spnic_hwif *hwif)
+{
+       u32 attr4 = spnic_hwif_read_reg(hwif, SPNIC_CSR_FUNC_ATTR4_ADDR);
+
+       return SPNIC_AF4_GET(attr4, DOORBELL_CTRL);
+}
+
+static enum spnic_outbound_ctrl
+spnic_get_outbound_ctrl_status(struct spnic_hwif *hwif)
+{
+       u32 attr5 = spnic_hwif_read_reg(hwif, SPNIC_CSR_FUNC_ATTR5_ADDR);
+
+       return SPNIC_AF5_GET(attr5, OUTBOUND_CTRL);
+}
+
+void spnic_enable_doorbell(struct spnic_hwif *hwif)
+{
+       u32 addr, attr4;
+
+       addr = SPNIC_CSR_FUNC_ATTR4_ADDR;
+       attr4 = spnic_hwif_read_reg(hwif, addr);
+
+       attr4 = SPNIC_AF4_CLEAR(attr4, DOORBELL_CTRL);
+       attr4 |= SPNIC_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL);
+
+       spnic_hwif_write_reg(hwif, addr, attr4);
+}
+
+void spnic_disable_doorbell(struct spnic_hwif *hwif)
+{
+       u32 addr, attr4;
+
+       addr = SPNIC_CSR_FUNC_ATTR4_ADDR;
+       attr4 = spnic_hwif_read_reg(hwif, addr);
+
+       attr4 = SPNIC_AF4_CLEAR(attr4, DOORBELL_CTRL);
+       attr4 |= SPNIC_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL);
+
+       spnic_hwif_write_reg(hwif, addr, attr4);
+}
+
+/**
+ * Try to set hwif as ppf and set the type of hwif in this case
+ *
+ * @param[in] hwif
+ *   The hardware interface of a pci function device
+ */
+static void set_ppf(struct spnic_hwif *hwif)
+{
+       struct spnic_func_attr *attr = &hwif->attr;
+       u32 addr, val, ppf_election;
+
+       addr  = SPNIC_CSR_PPF_ELECTION_ADDR;
+
+       val = spnic_hwif_read_reg(hwif, addr);
+       val = SPNIC_PPF_ELECTION_CLEAR(val, IDX);
+
+       ppf_election =  SPNIC_PPF_ELECTION_SET(attr->func_global_idx, IDX);
+       val |= ppf_election;
+
+       spnic_hwif_write_reg(hwif, addr, val);
+
+       /* Check PPF */
+       val = spnic_hwif_read_reg(hwif, addr);
+
+       attr->ppf_idx = SPNIC_PPF_ELECTION_GET(val, IDX);
+       if (attr->ppf_idx == attr->func_global_idx)
+               attr->func_type = TYPE_PPF;
+}
+
+/**
+ * Get the mpf index from the hwif
+ *
+ * @param[in] hwif
+ *   The hardware interface of a pci function device
+ */
+static void get_mpf(struct spnic_hwif *hwif)
+{
+       struct spnic_func_attr *attr = &hwif->attr;
+       u32 mpf_election, addr;
+
+       addr = SPNIC_CSR_GLOBAL_MPF_ELECTION_ADDR;
+
+       mpf_election = spnic_hwif_read_reg(hwif, addr);
+       attr->mpf_idx = SPNIC_MPF_ELECTION_GET(mpf_election, IDX);
+}
+
+/**
+ * Try to set hwif as mpf and set the mpf idx in hwif
+ *
+ * @param[in] hwif
+ *   The hardware interface of a pci function device
+ */
+static void set_mpf(struct spnic_hwif *hwif)
+{
+       struct spnic_func_attr *attr = &hwif->attr;
+       u32 addr, val, mpf_election;
+
+       addr  = SPNIC_CSR_GLOBAL_MPF_ELECTION_ADDR;
+
+       val = spnic_hwif_read_reg(hwif, addr);
+
+       val = SPNIC_MPF_ELECTION_CLEAR(val, IDX);
+       mpf_election = SPNIC_MPF_ELECTION_SET(attr->func_global_idx, IDX);
+
+       val |= mpf_election;
+       spnic_hwif_write_reg(hwif, addr, val);
+}
+
+static void init_db_area_idx(struct spnic_free_db_area *free_db_area,
+                            u64 db_dwqe_len)
+{
+       u32 i, db_max_areas;
+
+       db_max_areas = (db_dwqe_len > SPNIC_DB_DWQE_SIZE) ?
+                      SPNIC_DB_MAX_AREAS :
+                      (u32)(db_dwqe_len / SPNIC_DB_PAGE_SIZE);
+
+       for (i = 0; i < db_max_areas; i++)
+               free_db_area->db_idx[i] = i;
+
+       free_db_area->num_free = db_max_areas;
+       free_db_area->db_max_areas = db_max_areas;
+
+       rte_spinlock_init(&free_db_area->idx_lock);
+}
+
+static int get_db_idx(struct spnic_hwif *hwif, u32 *idx)
+{
+       struct spnic_free_db_area *free_db_area = &hwif->free_db_area;
+       u32 pos;
+       u32 pg_idx;
+
+       rte_spinlock_lock(&free_db_area->idx_lock);
+
+       do {
+               if (free_db_area->num_free == 0) {
+                       rte_spinlock_unlock(&free_db_area->idx_lock);
+                       return -ENOMEM;
+               }
+
+               free_db_area->num_free--;
+
+               pos = free_db_area->alloc_pos++;
+               /* Doorbell max areas should be 2^n */
+               pos &= free_db_area->db_max_areas - 1;
+
+               pg_idx = free_db_area->db_idx[pos];
+
+               free_db_area->db_idx[pos] = 0xFFFFFFFF;
+       } while (pg_idx >= free_db_area->db_max_areas);
+
+       rte_spinlock_unlock(&free_db_area->idx_lock);
+
+       *idx = pg_idx;
+
+       return 0;
+}
+
+static void free_db_idx(struct spnic_hwif *hwif, u32 idx)
+{
+       struct spnic_free_db_area *free_db_area = &hwif->free_db_area;
+       u32 pos;
+
+       if (idx >= free_db_area->db_max_areas)
+               return;
+
+       rte_spinlock_lock(&free_db_area->idx_lock);
+
+       pos = free_db_area->return_pos++;
+       pos &= free_db_area->db_max_areas - 1;
+
+       free_db_area->db_idx[pos] = idx;
+
+       free_db_area->num_free++;
+
+       rte_spinlock_unlock(&free_db_area->idx_lock);
+}
+
+void spnic_free_db_addr(void *hwdev, const void *db_base,
+                        __rte_unused void *dwqe_base)
+{
+       struct spnic_hwif *hwif = NULL;
+       u32 idx;
+
+       if (!hwdev || !db_base)
+               return;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+       idx = DB_IDX(db_base, hwif->db_base);
+
+       free_db_idx(hwif, idx);
+}
+
+int spnic_alloc_db_addr(void *hwdev, void **db_base, void **dwqe_base)
+{
+       struct spnic_hwif *hwif = NULL;
+       u32 idx;
+       int err;
+
+       if (!hwdev || !db_base)
+               return -EINVAL;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       err = get_db_idx(hwif, &idx);
+       if (err)
+               return -EFAULT;
+
+       *db_base = hwif->db_base + idx * SPNIC_DB_PAGE_SIZE;
+
+       if (!dwqe_base)
+               return 0;
+
+       *dwqe_base = (u8 *)*db_base + SPNIC_DWQE_OFFSET;
+
+       return 0;
+}
+
+/**
+ * Set msix state
+ *
+ * @param[in] hwdev
+ *   The pointer to the private hardware device object
+ * @param[in] msix_idx
+ *   MSIX index
+ * @param[in] flag
+ *   MSIX state flag, 0-enable, 1-disable
+ */
+void spnic_set_msix_state(void *hwdev, u16 msix_idx, enum spnic_msix_state 
flag)
+{
+       struct spnic_hwif *hwif = NULL;
+       u32 mask_bits;
+       u32 addr;
+       u8 int_msk = 1;
+
+       if (!hwdev)
+               return;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       if (flag)
+               mask_bits = SPNIC_MSI_CLR_INDIR_SET(int_msk, INT_MSK_SET);
+       else
+               mask_bits = SPNIC_MSI_CLR_INDIR_SET(int_msk, INT_MSK_CLR);
+       mask_bits = mask_bits |
+                   SPNIC_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX);
+
+       addr = SPNIC_CSR_FUNC_MSI_CLR_WR_ADDR;
+       spnic_hwif_write_reg(hwif, addr, mask_bits);
+}
+
+static void disable_all_msix(struct spnic_hwdev *hwdev)
+{
+       u16 num_irqs = hwdev->hwif->attr.num_irqs;
+       u16 i;
+
+       for (i = 0; i < num_irqs; i++)
+               spnic_set_msix_state(hwdev, i, SPNIC_MSIX_DISABLE);
+}
+
+void spnic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx,
+                                             u8 clear_resend_en)
+{
+       struct spnic_hwif *hwif = NULL;
+       u32 msix_ctrl = 0, addr;
+
+       if (!hwdev)
+               return;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       msix_ctrl = SPNIC_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX) |
+                   SPNIC_MSI_CLR_INDIR_SET(clear_resend_en, RESEND_TIMER_CLR);
+
+       addr = SPNIC_CSR_FUNC_MSI_CLR_WR_ADDR;
+       spnic_hwif_write_reg(hwif, addr, msix_ctrl);
+}
+#ifdef SPNIC_RELEASE
+static int wait_until_doorbell_flush_states(struct spnic_hwif *hwif,
+                                           enum spnic_doorbell_ctrl states)
+{
+       enum spnic_doorbell_ctrl db_ctrl;
+       u32 cnt = 0;
+
+       if (!hwif)
+               return -EINVAL;
+
+       while (cnt < SPNIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT) {
+               db_ctrl = spnic_get_doorbell_ctrl_status(hwif);
+               if (db_ctrl == states)
+                       return 0;
+
+               rte_delay_ms(1);
+               cnt++;
+       }
+
+       return -EFAULT;
+}
+#endif
+
+static int wait_until_doorbell_and_outbound_enabled(struct spnic_hwif *hwif)
+{
+       enum spnic_doorbell_ctrl db_ctrl;
+       enum spnic_outbound_ctrl outbound_ctrl;
+       u32 cnt = 0;
+
+       while (cnt < SPNIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT) {
+               db_ctrl = spnic_get_doorbell_ctrl_status(hwif);
+               outbound_ctrl = spnic_get_outbound_ctrl_status(hwif);
+               if (outbound_ctrl == ENABLE_OUTBOUND &&
+                   db_ctrl == ENABLE_DOORBELL)
+                       return 0;
+
+               rte_delay_ms(1);
+               cnt++;
+       }
+
+       return -EFAULT;
+}
+
+static void spnic_get_bar_addr(struct spnic_hwdev *hwdev)
+{
+       struct rte_pci_device *pci_dev = hwdev->pci_dev;
+       struct spnic_hwif *hwif = hwdev->hwif;
+       void *cfg_regs_base = NULL;
+       void *mgmt_reg_base = NULL;
+       void *intr_reg_base = NULL;
+       void *db_base = NULL;
+       int cfg_bar;
+
+       cfg_bar = SPNIC_IS_VF_DEV(pci_dev) ?
+                       SPNIC_VF_PCI_CFG_REG_BAR : SPNIC_PF_PCI_CFG_REG_BAR;
+
+       cfg_regs_base = pci_dev->mem_resource[cfg_bar].addr;
+       intr_reg_base = pci_dev->mem_resource[SPNIC_PCI_INTR_REG_BAR].addr;
+       if (!SPNIC_IS_VF_DEV(pci_dev)) {
+               mgmt_reg_base =
+                       pci_dev->mem_resource[SPNIC_PCI_MGMT_REG_BAR].addr;
+       }
+       db_base = pci_dev->mem_resource[SPNIC_PCI_DB_BAR].addr;
+
+       /* If function is VF, mgmt_regs_base will be NULL */
+       if (!mgmt_reg_base)
+               hwif->cfg_regs_base = (u8 *)cfg_regs_base +
+                                     SPNIC_VF_CFG_REG_OFFSET;
+       else
+               hwif->cfg_regs_base = cfg_regs_base;
+       hwif->intr_regs_base = intr_reg_base;
+       hwif->mgmt_regs_base = mgmt_reg_base;
+       hwif->db_base = db_base;
+       hwif->db_dwqe_len = pci_dev->mem_resource[SPNIC_PCI_DB_BAR].len;
+}
+
+/**
+ * Initialize the hw interface
+ *
+ * @param[in] hwdev
+ *   The pointer to the private hardware device object
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure.
+ */
+int spnic_init_hwif(void *dev)
+{
+       struct spnic_hwdev *hwdev = NULL;
+       struct spnic_hwif *hwif;
+       int err;
+
+       hwif = rte_zmalloc("spnic_hwif", sizeof(struct spnic_hwif),
+                          RTE_CACHE_LINE_SIZE);
+       if (!hwif)
+               return -ENOMEM;
+
+       hwdev = (struct spnic_hwdev *)dev;
+       hwdev->hwif = hwif;
+
+       spnic_get_bar_addr(hwdev);
+
+       init_db_area_idx(&hwif->free_db_area, hwif->db_dwqe_len);
+
+       err = wait_hwif_ready(hwdev);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Chip status is not ready");
+               goto hwif_ready_err;
+       }
+
+       get_hwif_attr(hwif);
+
+       err = wait_until_doorbell_and_outbound_enabled(hwif);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Hw doorbell/outbound is disabled");
+               goto hwif_ready_err;
+       }
+
+       if (!SPNIC_IS_VF(hwdev)) {
+               set_ppf(hwif);
+
+               if (SPNIC_IS_PPF(hwdev))
+                       set_mpf(hwif);
+
+               get_mpf(hwif);
+       }
+
+       disable_all_msix(hwdev);
+       /* Disable mgmt cpu reporting any event */
+       spnic_set_pf_status(hwdev->hwif, SPNIC_PF_STATUS_INIT);
+
+       PMD_DRV_LOG(INFO, "global_func_idx: %d, func_type: %d, host_id: %d, 
ppf: %d, mpf: %d",
+                   hwif->attr.func_global_idx, hwif->attr.func_type,
+                   hwif->attr.pci_intf_idx, hwif->attr.ppf_idx,
+                   hwif->attr.mpf_idx);
+
+       return 0;
+
+hwif_ready_err:
+       rte_free(hwdev->hwif);
+       hwdev->hwif = NULL;
+
+       return err;
+}
+
+/**
+ * Free the hw interface
+ *
+ * @param[in] dev
+ *   The pointer to the private hardware device object
+ */
+void spnic_free_hwif(void *dev)
+{
+       struct spnic_hwdev *hwdev = (struct spnic_hwdev *)dev;
+
+       rte_free(hwdev->hwif);
+}
+
+u16 spnic_global_func_id(void *hwdev)
+{
+       struct spnic_hwif *hwif = NULL;
+
+       if (!hwdev)
+               return 0;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.func_global_idx;
+}
+
+u8 spnic_pf_id_of_vf(void *hwdev)
+{
+       struct spnic_hwif *hwif = NULL;
+
+       if (!hwdev)
+               return 0;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.port_to_port_idx;
+}
+
+u8 spnic_pcie_itf_id(void *hwdev)
+{
+       struct spnic_hwif *hwif = NULL;
+
+       if (!hwdev)
+               return 0;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.pci_intf_idx;
+}
+
+enum func_type spnic_func_type(void *hwdev)
+{
+       struct spnic_hwif *hwif = NULL;
+
+       if (!hwdev)
+               return 0;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.func_type;
+}
+
+u16 spnic_glb_pf_vf_offset(void *hwdev)
+{
+       struct spnic_hwif *hwif = NULL;
+
+       if (!hwdev)
+               return 0;
+
+       hwif = ((struct spnic_hwdev *)hwdev)->hwif;
+
+       return hwif->attr.global_vf_id_of_pf;
+}
diff --git a/drivers/net/spnic/base/spnic_hwif.h 
b/drivers/net/spnic/base/spnic_hwif.h
new file mode 100644
index 0000000000..e2be026cba
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_hwif.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_HWIF_H_
+#define _SPNIC_HWIF_H_
+
+#define SPNIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT       60000
+#define SPNIC_PCIE_LINK_DOWN           0xFFFFFFFF
+
+/* PCIe bar space */
+#define SPNIC_VF_PCI_CFG_REG_BAR       0
+#define SPNIC_PF_PCI_CFG_REG_BAR       1
+
+#define SPNIC_PCI_INTR_REG_BAR         2
+#define SPNIC_PCI_MGMT_REG_BAR         3 /* Only PF has mgmt bar */
+#define SPNIC_PCI_DB_BAR               4
+
+#define SPNIC_DB_DWQE_SIZE             0x00400000
+
+/* Doorbell or direct wqe page size is 4K */
+#define SPNIC_DB_PAGE_SIZE             0x00001000ULL
+#define SPNIC_DWQE_OFFSET              0x00000800ULL
+
+#define SPNIC_DB_MAX_AREAS     (SPNIC_DB_DWQE_SIZE / SPNIC_DB_PAGE_SIZE)
+
+enum func_type {
+       TYPE_PF,
+       TYPE_VF,
+       TYPE_PPF,
+       TYPE_UNKNOWN
+};
+
+enum spnic_msix_state {
+       SPNIC_MSIX_ENABLE,
+       SPNIC_MSIX_DISABLE
+};
+
+struct spnic_free_db_area {
+       u32 db_idx[SPNIC_DB_MAX_AREAS];
+
+       u32 num_free;
+
+       u32 alloc_pos;
+       u32 return_pos;
+       u32 db_max_areas;
+
+       /* Spinlock for allocating doorbell area */
+       rte_spinlock_t idx_lock;
+};
+
+struct spnic_func_attr {
+       u16 func_global_idx;
+       u8 port_to_port_idx;
+       u8 pci_intf_idx;
+       u8 vf_in_pf;
+       enum func_type func_type;
+
+       u8 mpf_idx;
+
+       u8 ppf_idx;
+
+       u16 num_irqs; /* Max: 2 ^ 15 */
+       u8 num_aeqs; /* Max: 2 ^ 3 */
+       u8 num_ceqs; /* Max: 2 ^ 7 */
+
+       u8 num_dma_attr; /* Max: 2 ^ 6 */
+
+       u16 global_vf_id_of_pf;
+};
+
+struct spnic_hwif {
+       /* Configure virtual address, PF is bar1, VF is bar0/1 */
+       u8 *cfg_regs_base;
+       /* Interrupt configuration register address, PF is bar2, VF is bar2/3 */
+       u8 *intr_regs_base;
+       /* For PF bar3 virtual address, if function is VF should set NULL */
+       u8 *mgmt_regs_base;
+       u8 *db_base;
+       u64 db_dwqe_len;
+       struct spnic_free_db_area free_db_area;
+
+       struct spnic_func_attr attr;
+
+       void *pdev;
+};
+
+enum spnic_outbound_ctrl {
+       ENABLE_OUTBOUND  = 0x0,
+       DISABLE_OUTBOUND = 0x1
+};
+
+enum spnic_doorbell_ctrl {
+       ENABLE_DOORBELL  = 0x0,
+       DISABLE_DOORBELL = 0x1
+};
+
+enum spnic_pf_status {
+       SPNIC_PF_STATUS_INIT = 0X0,
+       SPNIC_PF_STATUS_ACTIVE_FLAG = 0x11,
+       SPNIC_PF_STATUS_FLR_START_FLAG = 0x12,
+       SPNIC_PF_STATUS_FLR_FINISH_FLAG = 0x13
+};
+
+#define SPNIC_HWIF_NUM_AEQS(hwif)              ((hwif)->attr.num_aeqs)
+#define SPNIC_HWIF_NUM_IRQS(hwif)              ((hwif)->attr.num_irqs)
+#define SPNIC_HWIF_GLOBAL_IDX(hwif)            ((hwif)->attr.func_global_idx)
+#define SPNIC_HWIF_GLOBAL_VF_OFFSET(hwif) ((hwif)->attr.global_vf_id_of_pf)
+#define SPNIC_HWIF_PPF_IDX(hwif)               ((hwif)->attr.ppf_idx)
+#define SPNIC_PCI_INTF_IDX(hwif)               ((hwif)->attr.pci_intf_idx)
+
+#define SPNIC_FUNC_TYPE(dev)           ((dev)->hwif->attr.func_type)
+#define SPNIC_IS_PF(dev)               (SPNIC_FUNC_TYPE(dev) == TYPE_PF)
+#define SPNIC_IS_VF(dev)               (SPNIC_FUNC_TYPE(dev) == TYPE_VF)
+#define SPNIC_IS_PPF(dev)              (SPNIC_FUNC_TYPE(dev) == TYPE_PPF)
+
+u32 spnic_hwif_read_reg(struct spnic_hwif *hwif, u32 reg);
+
+void spnic_hwif_write_reg(struct spnic_hwif *hwif, u32 reg, u32 val);
+
+void spnic_set_msix_state(void *hwdev, u16 msix_idx,
+                         enum spnic_msix_state flag);
+
+void spnic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx,
+                                      u8 clear_resend_en);
+
+u16 spnic_global_func_id(void *hwdev);
+
+u8 spnic_pf_id_of_vf(void *hwdev);
+
+u8 spnic_pcie_itf_id(void *hwdev);
+
+enum func_type spnic_func_type(void *hwdev);
+
+u16 spnic_glb_pf_vf_offset(void *hwdev);
+
+void spnic_set_pf_status(struct spnic_hwif *hwif,
+                        enum spnic_pf_status status);
+
+enum spnic_pf_status spnic_get_pf_status(struct spnic_hwif *hwif);
+
+int spnic_alloc_db_addr(void *hwdev, void **db_base, void **dwqe_base);
+
+void spnic_free_db_addr(void *hwdev, const void *db_base,
+                       __rte_unused void *dwqe_base);
+
+void spnic_disable_doorbell(struct spnic_hwif *hwif);
+
+void spnic_enable_doorbell(struct spnic_hwif *hwif);
+
+int spnic_init_hwif(void *dev);
+
+void spnic_free_hwif(void *dev);
+
+#endif /* _SPNIC_HWIF_H_ */
diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c
index b06492a8e9..228ed0c936 100644
--- a/drivers/net/spnic/spnic_ethdev.c
+++ b/drivers/net/spnic/spnic_ethdev.c
@@ -9,15 +9,48 @@
 #include <rte_ether.h>
 
 #include "base/spnic_compat.h"
+#include "base/spnic_csr.h"
+#include "base/spnic_hwdev.h"
+#include "base/spnic_hwif.h"
+
 #include "spnic_ethdev.h"
 
 /* Driver-specific log messages type */
 int spnic_logtype;
 
+#define SPNIC_MAX_UC_MAC_ADDRS         128
+#define SPNIC_MAX_MC_MAC_ADDRS         128
+
+/**
+ * Close the device.
+ *
+ * @param[in] dev
+ *   Pointer to ethernet device structure.
+ */
+static int spnic_dev_close(struct rte_eth_dev *eth_dev)
+{
+       struct spnic_nic_dev *nic_dev =
+               SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+
+       if (rte_bit_relaxed_test_and_set32(SPNIC_DEV_CLOSE, 
&nic_dev->dev_status)) {
+               PMD_DRV_LOG(WARNING, "Device %s already closed",
+                           nic_dev->dev_name);
+               return 0;
+       }
+
+       spnic_free_hwdev(nic_dev->hwdev);
+
+       rte_free(nic_dev->hwdev);
+       nic_dev->hwdev = NULL;
+
+       return 0;
+}
+
 static int spnic_func_init(struct rte_eth_dev *eth_dev)
 {
        struct spnic_nic_dev *nic_dev = NULL;
        struct rte_pci_device *pci_dev = NULL;
+       int err;
 
        pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 
@@ -35,11 +68,42 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
                 pci_dev->addr.domain, pci_dev->addr.bus,
                 pci_dev->addr.devid, pci_dev->addr.function);
 
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+       /* Create hardware device */
+       nic_dev->hwdev = rte_zmalloc("spnic_hwdev", sizeof(*nic_dev->hwdev),
+                                    RTE_CACHE_LINE_SIZE);
+       if (!nic_dev->hwdev) {
+               PMD_DRV_LOG(ERR, "Allocate hwdev memory failed, dev_name: %s",
+                           eth_dev->data->name);
+               err = -ENOMEM;
+               goto alloc_hwdev_mem_fail;
+       }
+       nic_dev->hwdev->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+       nic_dev->hwdev->dev_handle = nic_dev;
+       nic_dev->hwdev->eth_dev = eth_dev;
+       nic_dev->hwdev->port_id = eth_dev->data->port_id;
+
+       err = spnic_init_hwdev(nic_dev->hwdev);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Init chip hwdev failed, dev_name: %s",
+                           eth_dev->data->name);
+               goto init_hwdev_fail;
+       }
+
        rte_bit_relaxed_set32(SPNIC_DEV_INIT, &nic_dev->dev_status);
        PMD_DRV_LOG(INFO, "Initialize %s in primary succeed",
                    eth_dev->data->name);
 
        return 0;
+
+init_hwdev_fail:
+       rte_free(nic_dev->hwdev);
+       nic_dev->hwdev = NULL;
+
+alloc_hwdev_mem_fail:
+       PMD_DRV_LOG(ERR, "Initialize %s in primary failed",
+                   eth_dev->data->name);
+       return err;
 }
 
 static int spnic_dev_init(struct rte_eth_dev *eth_dev)
@@ -67,6 +131,8 @@ static int spnic_dev_uninit(struct rte_eth_dev *dev)
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
+       spnic_dev_close(dev);
+
        return 0;
 }
 
diff --git a/drivers/net/spnic/spnic_ethdev.h b/drivers/net/spnic/spnic_ethdev.h
index d4ec641d83..654234aaa4 100644
--- a/drivers/net/spnic/spnic_ethdev.h
+++ b/drivers/net/spnic/spnic_ethdev.h
@@ -5,21 +5,55 @@
 #ifndef _SPNIC_ETHDEV_H_
 #define _SPNIC_ETHDEV_H_
 
-/* Vendor id */
-#define PCI_VENDOR_ID_RAMAXEL  0x1E81
-
-/* Device ids */
-#define SPNIC_DEV_ID_PF                        0x9020
-#define SPNIC_DEV_ID_VF                        0x9001
+#define SPNIC_UINT32_BIT_SIZE          (CHAR_BIT * sizeof(uint32_t))
+#define SPNIC_VFTA_SIZE                        (4096 / SPNIC_UINT32_BIT_SIZE)
+#define SPNIC_MAX_QUEUE_NUM            64
 
 enum spnic_dev_status {
-       SPNIC_DEV_INIT
+       SPNIC_DEV_INIT,
+       SPNIC_DEV_CLOSE,
+       SPNIC_DEV_START,
+       SPNIC_DEV_INTR_EN
 };
 
 #define SPNIC_DEV_NAME_LEN             32
 struct spnic_nic_dev {
+       struct spnic_hwdev *hwdev; /* Hardware device */
+
+       struct spnic_txq **txqs;
+       struct spnic_rxq **rxqs;
+       struct rte_mempool *cpy_mpool;
+
+       u16 num_sqs;
+       u16 num_rqs;
+       u16 max_sqs;
+       u16 max_rqs;
+
+       u16 rx_buff_len;
+       u16 mtu_size;
+
+       u16 rss_state;
+       u8 num_rss;
+       u8 rsvd0;
+
+       u32 rx_mode;
+       u8 rx_queue_list[SPNIC_MAX_QUEUE_NUM];
+       rte_spinlock_t queue_list_lock;
+       pthread_mutex_t rx_mode_mutex;
+
+       u32 default_cos;
+       u32 rx_csum_en;
+
        u32 dev_status;
+
+       bool pause_set;
+       pthread_mutex_t pause_mutuex;
+
+       struct rte_ether_addr default_addr;
+       struct rte_ether_addr *mc_list;
+
        char dev_name[SPNIC_DEV_NAME_LEN];
+       u32 vfta[SPNIC_VFTA_SIZE]; /* VLAN bitmap */
 };
 
 #define SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev) \
-- 
2.32.0

Reply via email to