get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/87278/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 87278,
    "url": "https://patches.dpdk.org/api/patches/87278/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1611643528-18311-5-git-send-email-wei.huang@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1611643528-18311-5-git-send-email-wei.huang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1611643528-18311-5-git-send-email-wei.huang@intel.com",
    "date": "2021-01-26T06:45:28",
    "name": "[v12,4/4] examples/ifpga: add example for ifpga opae API",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "d390ecb1ca93257491ec2eb1493bdcf45250b689",
    "submitter": {
        "id": 2033,
        "url": "https://patches.dpdk.org/api/people/2033/?format=api",
        "name": "Wei Huang",
        "email": "wei.huang@intel.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1611643528-18311-5-git-send-email-wei.huang@intel.com/mbox/",
    "series": [
        {
            "id": 14943,
            "url": "https://patches.dpdk.org/api/series/14943/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14943",
            "date": "2021-01-26T06:45:24",
            "name": "raw/ifpga: add extra OPAE APIs",
            "version": 12,
            "mbox": "https://patches.dpdk.org/series/14943/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/87278/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/87278/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 4C2A4A052A;\n\tTue, 26 Jan 2021 07:46:04 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id F3038141297;\n\tTue, 26 Jan 2021 07:45:37 +0100 (CET)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n by mails.dpdk.org (Postfix) with ESMTP id 94588141284;\n Tue, 26 Jan 2021 07:45:34 +0100 (CET)",
            "from orsmga004.jf.intel.com ([10.7.209.38])\n by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 25 Jan 2021 22:45:33 -0800",
            "from unknown (HELO sh_lab5_1.sh.intel.com) ([10.238.175.190])\n by orsmga004.jf.intel.com with ESMTP; 25 Jan 2021 22:45:30 -0800"
        ],
        "IronPort-SDR": [
            "\n aK8Fj/2ttAmH+cAvFMoz4I0SbJu9xdUAI2wGPP8JQq6aej5ZwAqt9grfaz08e94sxNzUhCUJKE\n wWJuV5zrlnHw==",
            "\n LLCOYjTdZ+Ph062aD/D0NhSOTsAgOzjlk+gmTdneLLp+ydWLxMycymzsVyMXoCd2XYsXnhDjZ+\n O3YKUyRvOJMQ=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9875\"; a=\"198641591\"",
            "E=Sophos;i=\"5.79,375,1602572400\"; d=\"scan'208\";a=\"198641591\"",
            "E=Sophos;i=\"5.79,375,1602572400\"; d=\"scan'208\";a=\"504432735\""
        ],
        "X-ExtLoop1": "1",
        "From": "Wei Huang <wei.huang@intel.com>",
        "To": "dev@dpdk.org,\n\trosen.xu@intel.com,\n\tqi.z.zhang@intel.com",
        "Cc": "stable@dpdk.org, tianfei.zhang@intel.com, Wei Huang <wei.huang@intel.com>",
        "Date": "Tue, 26 Jan 2021 01:45:28 -0500",
        "Message-Id": "<1611643528-18311-5-git-send-email-wei.huang@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1611643528-18311-1-git-send-email-wei.huang@intel.com>",
        "References": "<1611643528-18311-1-git-send-email-wei.huang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v12 4/4] examples/ifpga: add example for ifpga\n opae API",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Below major OPAE APIs are added in this example.\n1. opae_init_eal() set up EAL environment.\n2. opae_cleanup_eal() clean up EAL environment.\n3. opae_enumerate() searches PAC with specific FPGA.\n4. opae_get_property() gets properties of FPGA.\n5. opae_partial_reconfigure() perform partial configuration on FPGA.\n6. opae_get_image_info() gets information of image file.\n7. opae_update_flash() updates FPGA flash with specific image file.\n8. opae_cancel_flash_update() cancel process of FPGA flash update.\n9. opae_probe_device() manually probe specific FPGA with ifpga driver.\n10. opae_remove_device() manually remove specific FPGA from ifpga driver.\n11. opae_bind_driver() binds specific FPGA with specified kernel driver.\n12. opae_unbind_driver() unbinds specific FPGA from kernel driver.\n13. opae_reboot_device() reboots specific FPGA.\n\nAn example application shows how to call above OPAE APIs.\nYou can test each API by running corresponding command.\nA guide is also added to show how to run the example.\n\nSigned-off-by: Wei Huang <wei.huang@intel.com>\nAcked-by: Tianfei Zhang <tianfei.zhang@intel.com>\nAcked-by: Rosen Xu <rosen.xu@intel.com>\n---\nv2: fix coding style issue in commands.c\n---\nv3: add guide for running example\n---\nv4: fix compilation issue of ifpga.rst\n---\nv5: add ifpga.rst into sample_app_ug/index.rst\n---\nv6: implement OPAE APIs in example instead of ifpga rawdev\n---\n MAINTAINERS                        |    1 +\n doc/guides/sample_app_ug/ifpga.rst |  433 +++++++\n doc/guides/sample_app_ug/index.rst |    1 +\n examples/ifpga/Makefile            |   45 +\n examples/ifpga/commands.c          | 1321 ++++++++++++++++++++\n examples/ifpga/commands.h          |   16 +\n examples/ifpga/main.c              |   38 +\n examples/ifpga/meson.build         |   20 +\n examples/ifpga/opae_api.c          | 1788 ++++++++++++++++++++++++++++\n examples/ifpga/opae_api.h          |  245 ++++\n 10 files changed, 3908 insertions(+)\n create mode 100644 doc/guides/sample_app_ug/ifpga.rst\n create mode 100644 examples/ifpga/Makefile\n create mode 100644 examples/ifpga/commands.c\n create mode 100644 examples/ifpga/commands.h\n create mode 100644 examples/ifpga/main.c\n create mode 100644 examples/ifpga/meson.build\n create mode 100644 examples/ifpga/opae_api.c\n create mode 100644 examples/ifpga/opae_api.h",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex eafe9f8c4..04a8fdebb 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1237,6 +1237,7 @@ M: Tianfei zhang <tianfei.zhang@intel.com>\n T: git://dpdk.org/next/dpdk-next-net-intel\n F: drivers/raw/ifpga/\n F: doc/guides/rawdevs/ifpga.rst\n+F: doc/guides/sample_app_ug/ifpga.rst\n \n IOAT Rawdev\n M: Bruce Richardson <bruce.richardson@intel.com>\ndiff --git a/doc/guides/sample_app_ug/ifpga.rst b/doc/guides/sample_app_ug/ifpga.rst\nnew file mode 100644\nindex 000000000..adcac3bdf\n--- /dev/null\n+++ b/doc/guides/sample_app_ug/ifpga.rst\n@@ -0,0 +1,433 @@\n+..  SPDX-License-Identifier: BSD-3-Clause\n+    Copyright(c) 2020-2021 Intel Corporation.\n+\n+Intel FPGA Sample Application\n+=============================\n+\n+The Intel FPGA sample application is an example of how to use OPAE API to manage\n+Intel FPGA.\n+\n+Overview\n+--------\n+\n+The Intel FPGA sample application is a simple application that demonstrates\n+the use of the OPAE API provided by ifpga driver in the DPDK.\n+This application is a readline-like interface that can be used to manage\n+Intel FPGA, in a Linux* application environment.\n+\n+Compiling the Application\n+-------------------------\n+\n+To compile the sample application see :doc:`compiling`\n+\n+The application is located in the ``ifpga`` sub-directory.\n+\n+Running the Application\n+-----------------------\n+\n+To run the application in linux environment, issue the following command:\n+\n+.. code-block:: console\n+\n+    $ ./<build_dir>/examples/dpdk-ifpga --proc-type=auto\n+\n+Refer to the *DPDK Getting Started Guide* for general information on running\n+applications and the Environment Abstraction Layer (EAL) options.\n+\n+Explanation\n+-----------\n+\n+The following sections provide some explanation of the code.\n+\n+EAL Initialization and cmdline Start\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+The first task is the initialization of the Environment Abstraction Layer (EAL).\n+This is achieved as follows:\n+\n+.. code-block:: c\n+\n+    int main(int argc, char **argv)\n+    {\n+        ret = opae_init_eal(argc, argv);\n+        if (ret < 0)\n+            rte_panic(\"Cannot init EAL\\n\");\n+\n+Then, a new command line object is created and started to interact with the user\n+through the console:\n+\n+.. code-block:: c\n+\n+    cl = cmdline_stdin_new(main_ctx, \"opae> \");\n+    if (cl == NULL)\n+        rte_panic(\"Cannot create cmdline instance\\n\");\n+    cmdline_interact(cl);\n+    opae_cleanup_eal();\n+    cmdline_stdin_exit(cl);\n+\n+The cmd line_interact() function returns when the user types **Ctrl-d** or\n+**quit**. In this case, EAL is cleaned up and the application exits.\n+\n+Commands Description\n+--------------------\n+\n+The following sections provide some explanation of the commands.\n+\n+help command\n+~~~~~~~~~~~~\n+\n+The application has on-line help for the commands that are available at runtime.\n+\n+.. code-block:: console\n+\n+   opae> help\n+    get_api_version                        get OPAE API version\n+    get_proc_type                          get DPDK process type\n+    get_image_info <FILE>                  get information of image file\n+    get_status <BDF>                       get current status & progress of FPGA\n+    get_property <BDF> <0|1|2|4|8>         get property of FPGA\n+    get_phy_info <BDF>                     get information of PHY\n+    get_parent <BDF>                       get parent PCI device of FPGA\n+    get_child <BDF>                        get child PCI device of FPGA\n+    get_pf1 <BDF>                          get physical function 1 device of FPGA\n+    set_log_level <0-4>                    set logging level\n+    set_log_file <FILE>                    set logging file\n+    set_status <BDF> <0-4> <0-100>         set current status & progress of FPGA\n+    enumerate <VID> <DID>                  enumerate specified FPGA\n+    bind <BDF> <DRIVER>                    bind FPGA with kernel driver\n+    unbind <BDF>                           unbind FPGA from kernel driver\n+    probe <BDF>                            probe FPGA with IFPGA driver\n+    remove <BDF>                           remove FPGA from IFPGA driver\n+    flash <BDF> <FILE>                     update flash of FPGA\n+    pr <BDF> <PORT> <FILE>                 partial reconfigure FPGA\n+    reboot <BDF> <fpga|bmc> <0-1>          reboot FPGA or MAX10\n+    cancel <BDF>                           cancel flash update\n+    check                                  display list of PCI devices\n+    pci_read <BDF> <0-1024>                read PCI configuration space\n+    pci_write <BDF> <0-1024> <NUM>         write PCI configuration space\n+    quit                                   exit DPDK application\n+    help                                   show commands list\n+\n+get_api_version command\n+~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Show OPAE API version which is same to the version of DPDK.\n+\n+.. code-block:: console\n+\n+   opae> get_api_version\n+   21.2.0\n+\n+set_log_level command\n+~~~~~~~~~~~~~~~~~~~~~\n+\n+Set logging level of OPAE API. Logging level is defined as below.\n+0 - CRITICAL\n+1 - ERROR\n+2 - WARNING\n+3 - INFORMATION\n+4 - DEBUG\n+\n+.. code-block:: console\n+\n+   opae> set_log_level 4\n+   OPAE-API: Current log level is DEBUG\n+   Successful\n+   opae> set_log_level 6\n+   OPAE-API: Current log level is DEBUG\n+   Failed\n+\n+set_log_file command\n+~~~~~~~~~~~~~~~~~~~~\n+\n+Set logging file of OPAE API.\n+\n+.. code-block:: console\n+\n+   opae> set_log_file /tmp/ifpga.log\n+   Successful\n+\n+get_proc_type command\n+~~~~~~~~~~~~~~~~~~~~~\n+\n+Show the process type of DPDK. If you start multiple instances of the\n+application, the process type of the first one is 'Primary', the others\n+are 'Secondary'.\n+\n+.. code-block:: console\n+\n+   opae> get_proc_type\n+   Primary\n+\n+get_image_info command\n+~~~~~~~~~~~~~~~~~~~~~~\n+\n+Display information of FPGA image file.\n+\n+.. code-block:: console\n+\n+   opae> get_image_info /home/wei/a10.bin\n+   Type:           FPGA_BBS\n+   Action:         UPDATE\n+   Total length:   58720256\n+   Payload offset: 1024\n+   Payload length: 58719232\n+   opae> get_image_info /home/wei/data.bin\n+   OPAE-ERR: Image '/home/wei/data.bin' can not be recognized\n+   Invalid image file\n+\n+enumerate command\n+~~~~~~~~~~~~~~~~~\n+\n+Display PCI address of FPGA with specified vendor ID and device ID. ID value can\n+be set to 0xffff for arbitrary ID.\n+\n+.. code-block:: console\n+\n+   opae> enumerate 0x8086 0x0b30\n+   0000:24:00.0\n+\n+get_property command\n+~~~~~~~~~~~~~~~~~~~~\n+\n+Display property information of specified FPGA. Property type is defined as below.\n+0 - All properties\n+1 - PCI property\n+2 - FME property\n+4 - port property\n+8 - BMC property\n+PCI property is always available, other properties can only be displayed after\n+ifpga driver is probed to the FPGA.\n+\n+.. code-block:: console\n+\n+   opae> get_property 24:00.0 0\n+   PCI:\n+    PCIe s:b:d.f     : 0000:24:00.0\n+    kernel driver    : vfio-pci\n+   FME:\n+    platform         : Vista Creek\n+    DCP version      : DCP 1.2\n+    phase            : Beta\n+    interface        : 2x2x25G\n+    build version    : 0.0.2\n+    ports num        : 1\n+    boot page        : user\n+    pr interface id  : a5d72a3c-c8b0-4939-912c-f715e5dc10ca\n+   PORT0:\n+    access type      : PF\n+    accelerator id   : 8892c23e-2eed-4b44-8bb6-5c88606e07df\n+   BMC:\n+    MAX10 version    : D.2.0.5\n+    NIOS FW version  : D.2.0.12\n+\n+get_phy_info command\n+~~~~~~~~~~~~~~~~~~~~\n+\n+Display information and status of PHY connects to the specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> get_phy_info 24:00.0\n+    retimers num     : 2\n+    link speed       : 25G\n+    link status      : 00\n+\n+get_parent command\n+~~~~~~~~~~~~~~~~~~\n+\n+Display PCI address of upstream device connects to the specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> get_parent 24:00.0\n+   0000:22:09.0\n+\n+get_child command\n+~~~~~~~~~~~~~~~~~\n+\n+Display PCI address of downstream device connects to the specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> get_child 24:00.0\n+   No child\n+   opae> get_child 22:09.0\n+   0000:24:00.0\n+\n+get_pf1 command\n+~~~~~~~~~~~~~~~\n+\n+Display PCI address of PF1 (physical function 1) of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> get_pf1 24:00.0\n+   0000:26:00.0\n+   0000:26:00.1\n+\n+get_status command\n+~~~~~~~~~~~~~~~~~~\n+\n+Display current RSU status of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> get_status 24:00.0\n+   Status:   IDLE\n+   Progress: 0%\n+\n+set_status command\n+~~~~~~~~~~~~~~~~~~\n+\n+Set current RSU status of specified FPGA. This command is mainly used for debug\n+purpose. Status value is defined as below.\n+0 - IDLE\n+1 - PREPARE\n+2 - PROGRAM\n+3 - COPY\n+4 - REBOOT\n+\n+.. code-block:: console\n+\n+   opae> set_status 24:00.0 2 35\n+   Successful\n+   opae> get_status 24:00.0\n+   Status:   PROGRAM\n+   Progress: 35%\n+\n+unbind command\n+~~~~~~~~~~~~~~\n+\n+Unbind kernel driver from specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> unbind 24:00.0\n+   OPAE-ERR: 0000:24:00.0 is probed, remove it first\n+   Failed\n+   opae> remove 24:00.0\n+   Successful\n+   opae> unbind 24:00.0\n+   Successful\n+\n+bind command\n+~~~~~~~~~~~~\n+\n+Bind specified kernel driver to specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> bind 24:00.0 vfio-pci\n+   Successful\n+\n+probe command\n+~~~~~~~~~~~~~\n+\n+Probe specified FPGA with DPDK PMD driver.\n+\n+.. code-block:: console\n+\n+   opae> probe 24:00.0\n+   Successful\n+\n+remove command\n+~~~~~~~~~~~~~~\n+\n+Remove specified FPGA from DPDK PMD driver. It's a reverse operation to probe\n+command.\n+\n+.. code-block:: console\n+\n+   opae> remove 24:00.0\n+   Successful\n+\n+flash command\n+~~~~~~~~~~~~~\n+\n+Update image in flash of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> flash 24:00.0 /home/wei/a10.bin\n+   Successful\n+\n+pr command\n+~~~~~~~~~~\n+\n+Do partial reconfiguration of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> pr 24:00.0 0 /home/wei/nlb0.gbs\n+   Successful\n+\n+reboot command\n+~~~~~~~~~~~~~~\n+\n+Reboot specified FPGA. Reboot type and page is defined as below.\n+fpga - reboot FPGA only\n+bmc - reboot whole card with FPGA\n+0 - factory page\n+1 - user page\n+\n+.. code-block:: console\n+\n+   opae> reboot 24:00.0 fpga 1\n+   Successful\n+\n+cancel command\n+~~~~~~~~~~~~~~\n+\n+Cancel flash programming of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> cancel 24:00.0\n+   Successful\n+\n+check command\n+~~~~~~~~~~~~~\n+\n+Display PCI device list established by DPDK.\n+\n+.. code-block:: console\n+\n+   opae> check\n+ ID     NAME       SEG BUS DEV FUNC  VID  DID   KDRV\n+  0 0000:00:11.5  0000  00  11  5   8086 2827   unknown\n+  1 0000:00:14.0  0000  00  14  0   8086 a1af   unknown\n+  2 0000:00:16.0  0000  00  16  0   8086 a1ba   unknown\n+  3 0000:00:1c.0  0000  00  1c  0   8086 a190   unknown\n+ ......\n+ 29 0000:24:00.0  0000  24  00  0   8086 0b30   vfio-pci\n+ ......\n+\n+pci_read command\n+~~~~~~~~~~~~~~~~\n+\n+Read PCI configuration space of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> pci_read 24:00.0 0\n+   0x0b308086\n+\n+pci_write command\n+~~~~~~~~~~~~~~~~~\n+\n+Write PCI configuration space of specified FPGA.\n+\n+.. code-block:: console\n+\n+   opae> pci_write 24:00.0 4 0x100406\n+   Successful\n+\n+quit command\n+~~~~~~~~~~~~\n+\n+Exit this sample application.\n+\n+.. code-block:: console\n+\n+   opae> quit\ndiff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst\nindex e8db83d3a..beb94ff3e 100644\n--- a/doc/guides/sample_app_ug/index.rst\n+++ b/doc/guides/sample_app_ug/index.rst\n@@ -23,6 +23,7 @@ Sample Applications User Guides\n     kernel_nic_interface\n     keep_alive\n     ioat\n+    ifpga\n     l2_forward_crypto\n     l2_forward_job_stats\n     l2_forward_real_virtual\ndiff --git a/examples/ifpga/Makefile b/examples/ifpga/Makefile\nnew file mode 100644\nindex 000000000..90ab9ee36\n--- /dev/null\n+++ b/examples/ifpga/Makefile\n@@ -0,0 +1,45 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2020-2021 Intel Corporation\n+\n+# binary name\n+APP = ifpga\n+\n+# all source are stored in SRCS-y\n+SRCS-y := main.c commands.c opae_api.c\n+\n+# Build using pkg-config variables if possible\n+ifneq ($(shell pkg-config --exists libdpdk && echo 0),0)\n+$(error \"no installation of DPDK found\")\n+endif\n+\n+all: static\n+.PHONY: shared static\n+shared: build/$(APP)-shared\n+\tln -sf $(APP)-shared build/$(APP)\n+static: build/$(APP)-static\n+\tln -sf $(APP)-static build/$(APP)\n+\n+PKGCONF ?= pkg-config\n+\n+PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)\n+CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -I../../drivers/raw/ifpga\n+LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) -lrte_bus_pci \\\n+                 -lrte_bus_ifpga -lrte_bus_vdev -lrte_raw_ifpga \\\n+                 -lrte_net_i40e -lrte_net_ipn3ke\n+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)\n+\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+\n+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build\n+\t$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)\n+\n+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build\n+\t$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)\n+\n+build:\n+\t@mkdir -p $@\n+\n+.PHONY: clean\n+clean:\n+\trm -f build/$(APP) build/$(APP)-static build/$(APP)-shared\n+\ttest -d build && rmdir -p build || true\ndiff --git a/examples/ifpga/commands.c b/examples/ifpga/commands.c\nnew file mode 100644\nindex 000000000..eb2fe1ca6\n--- /dev/null\n+++ b/examples/ifpga/commands.c\n@@ -0,0 +1,1321 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020-2021 Intel Corporation.\n+ * All rights reserved.\n+ */\n+\n+#include <stdio.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include <stdarg.h>\n+#include <errno.h>\n+\n+#include <cmdline_rdline.h>\n+#include <cmdline_parse.h>\n+#include <cmdline_parse_num.h>\n+#include <cmdline_parse_string.h>\n+#include <cmdline.h>\n+\n+#include \"commands.h\"\n+\n+static int parse_pciaddr(const char *bdf, opae_pci_device *id)\n+{\n+\tsize_t len = 0;\n+\tunsigned int domain = 0;\n+\tunsigned int bus = 0;\n+\tunsigned int devid = 0;\n+\tunsigned int function = 0;\n+\n+\tif (!bdf || !id)\n+\t\treturn -EINVAL;\n+\n+\tlen = strlen(bdf);\n+\tif ((len < 5) || (len > 12))\n+\t\treturn -EINVAL;\n+\n+\tlen = sscanf(bdf, \"%x:%x:%x.%d\", &domain, &bus, &devid, &function);\n+\tif (len == 4) {\n+\t\tsnprintf(id->bdf, sizeof(id->bdf), \"%04x:%02x:%02x.%d\",\n+\t\t\tdomain, bus, devid, function);\n+\t} else {\n+\t\tlen = sscanf(bdf, \"%x:%x.%d\", &bus, &devid, &function);\n+\t\tif (len == 3) {\n+\t\t\tsnprintf(id->bdf, sizeof(id->bdf), \"%04x:%02x:%02x.%d\",\n+\t\t\t\t0, bus, devid, function);\n+\t\t} else {\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static void uuid_to_str(opae_uuid *id, uuid_str *str)\n+{\n+\tuint8_t *b = NULL;\n+\tchar *p = NULL;\n+\tint i, j;\n+\n+\tif (!id || !str)\n+\t\treturn;\n+\n+\tb = &id->b[15];\n+\tp = str->s;\n+\tfor (i = 0; i < 4; i++, b--, p += 2)\n+\t\tsprintf(p, \"%02x\", *b);\n+\tsprintf(p++, \"-\");\n+\tfor (i = 0; i < 3; i++) {\n+\t\tfor (j = 0; j < 2; j++, b--, p += 2)\n+\t\t\tsprintf(p, \"%02x\", *b);\n+\t\tsprintf(p++, \"-\");\n+\t}\n+\tfor (i = 0; i < 6; i++, b--, p += 2)\n+\t\tsprintf(p, \"%02x\", *b);\n+}\n+\n+/* *** GET API VERSION *** */\n+struct cmd_version_result {\n+\tcmdline_fixed_string_t cmd;\n+};\n+\n+static void cmd_version_parsed(__rte_unused void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\topae_api_version ver;\n+\topae_get_api_version(&ver);\n+\tcmdline_printf(cl, \"%d.%d.%d\\n\", ver.major, ver.minor, ver.micro);\n+}\n+\n+cmdline_parse_token_string_t cmd_version_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_version_result, cmd, \"get_api_version\");\n+\n+cmdline_parse_inst_t cmd_get_api_version = {\n+\t.f = cmd_version_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get OPAE API version\",\n+\t.tokens = {\n+\t\t(void *)&cmd_version_cmd,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET PROC TYPE *** */\n+struct cmd_proc_type_result {\n+\tcmdline_fixed_string_t cmd;\n+};\n+\n+static void cmd_proc_type_parsed(__rte_unused void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tint type = opae_get_proc_type();\n+\n+\tif (type == 0)\n+\t\tcmdline_printf(cl, \"Primary\\n\");\n+\telse if (type == 1)\n+\t\tcmdline_printf(cl, \"Secondary\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Unknown\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_proc_type_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_proc_type_result, cmd, \"get_proc_type\");\n+\n+cmdline_parse_inst_t cmd_get_proc_type = {\n+\t.f = cmd_proc_type_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get DPDK process type\",\n+\t.tokens = {\n+\t\t(void *)&cmd_proc_type_cmd,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET IMAGE INFO *** */\n+struct cmd_image_info_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t path;\n+};\n+\n+static void cmd_image_info_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_image_info_result *res = parsed_result;\n+\topae_img_info info;\n+\n+\tif (opae_get_image_info(res->path, &info) == 0) {\n+\t\tcmdline_printf(cl, \"%-16s\", \"Type:\");\n+\t\tif (info.type == OPAE_IMG_TYPE_BBS)\n+\t\t\tcmdline_printf(cl, \"FPGA_BBS\\n\");\n+\t\telse if (info.type == OPAE_IMG_TYPE_BMC)\n+\t\t\tcmdline_printf(cl, \"BMC\\n\");\n+\t\telse if (info.type == OPAE_IMG_TYPE_GBS)\n+\t\t\tcmdline_printf(cl, \"FGPA_GBS\\n\");\n+\t\telse\n+\t\t\tcmdline_printf(cl, \"Unknown\\n\");\n+\t\tcmdline_printf(cl, \"%-16s\", \"Action:\");\n+\t\tif (info.subtype == OPAE_IMG_SUBTYPE_UPDATE)\n+\t\t\tcmdline_printf(cl, \"UPDATE\\n\");\n+\t\telse if (info.subtype == OPAE_IMG_SUBTYPE_CANCELLATION)\n+\t\t\tcmdline_printf(cl, \"CANCELLATION\\n\");\n+\t\telse if (info.subtype == OPAE_IMG_SUBTYPE_ROOT_KEY_HASH_256)\n+\t\t\tcmdline_printf(cl, \"ROOT_HASH_256\\n\");\n+\t\telse if (info.subtype == OPAE_IMG_SUBTYPE_ROOT_KEY_HASH_384)\n+\t\t\tcmdline_printf(cl, \"ROOT_HASH_384\\n\");\n+\t\telse\n+\t\t\tcmdline_printf(cl, \"Unknown\\n\");\n+\t\tcmdline_printf(cl, \"%-16s%u\\n\", \"Total length:\",\n+\t\t\tinfo.total_len);\n+\t\tcmdline_printf(cl, \"%-16s%u\\n\", \"Payload offset:\",\n+\t\t\tinfo.payload_offset);\n+\t\tcmdline_printf(cl, \"%-16s%u\\n\", \"Payload length:\",\n+\t\t\tinfo.payload_len);\n+\t} else {\n+\t\tcmdline_printf(cl, \"Invalid image file\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_image_info_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_image_info_result, cmd,\n+\t\t\"get_image_info\");\n+cmdline_parse_token_string_t cmd_image_info_path =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_image_info_result, path, NULL);\n+\n+cmdline_parse_inst_t cmd_get_image_info = {\n+\t.f = cmd_image_info_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get information of image file\",\n+\t.tokens = {\n+\t\t(void *)&cmd_image_info_cmd,\n+\t\t(void *)&cmd_image_info_path,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET STATUS *** */\n+struct cmd_get_status_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_get_status_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_get_status_result *res = parsed_result;\n+\topae_pci_device id;\n+\tuint32_t stat, prog;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_load_rsu_status(&id, &stat, &prog) == 0) {\n+\t\tcmdline_printf(cl, \"%-10s\", \"Status:\");\n+\t\tif (stat == 0)\n+\t\t\tcmdline_printf(cl, \"IDLE\\n\");\n+\t\telse if (stat == 1)\n+\t\t\tcmdline_printf(cl, \"PREPARE\\n\");\n+\t\telse if (stat == 2)\n+\t\t\tcmdline_printf(cl, \"PROGRAM\\n\");\n+\t\telse if (stat == 3)\n+\t\t\tcmdline_printf(cl, \"COPY\\n\");\n+\t\telse if (stat == 4)\n+\t\t\tcmdline_printf(cl, \"REBOOT\\n\");\n+\t\telse\n+\t\t\tcmdline_printf(cl, \"unknown\\n\");\n+\t\tcmdline_printf(cl, \"%-10s%u%%\\n\", \"Progress:\", prog);\n+\t} else {\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_get_status_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_get_status_result, cmd, \"get_status\");\n+cmdline_parse_token_string_t cmd_get_status_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_get_status_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_get_status = {\n+\t.f = cmd_get_status_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get current status & progress of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_get_status_cmd,\n+\t\t(void *)&cmd_get_status_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET PROPERTY *** */\n+struct cmd_property_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tint32_t type;\n+};\n+\n+static void cmd_property_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_property_result *res = parsed_result;\n+\topae_pci_device id;\n+\topae_fpga_property prop;\n+\tuuid_str str;\n+\tuint32_t port = 0;\n+\n+\tswitch (res->type) {\n+\tcase 0:\n+\tcase 1:\n+\tcase 2:\n+\tcase 4:\n+\tcase 8:\n+\t\tbreak;\n+\tdefault:\n+\t\tcmdline_printf(cl, \"%d is invalid type of property\\n\",\n+\t\t\tres->type);\n+\t\treturn;\n+\t}\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_get_property(&id, &prop, res->type) == 0) {\n+\t\tif ((res->type == 0) || (res->type == 1)) {\n+\t\t\tcmdline_printf(cl, \"%s:\\n\", \"PCI\");\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"PCIe s:b:d.f\", prop.pci.pci_addr);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"kernel driver\", prop.pci.drv_name);\n+\t\t}\n+\t\tif ((res->type == 0) || (res->type == 2)) {\n+\t\t\tcmdline_printf(cl, \"%s:\\n\", \"FME\");\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"platform\", prop.fme.platform_name);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"DCP version\", prop.fme.dcp_version);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"phase\", prop.fme.release_name);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"interface\", prop.fme.interface_type);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"build version\", prop.fme.build_version);\n+\t\t\tcmdline_printf(cl, \" %-16s : %u\\n\",\n+\t\t\t\t\"ports num\", prop.fme.num_ports);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"boot page\", prop.fme.boot_page ? \"user\" : \"factory\");\n+\t\t\tuuid_to_str(&prop.fme.pr_id, &str);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\", \"pr interface id\",\n+\t\t\t\tstr.s);\n+\t\t}\n+\t\tif ((res->type == 0) || (res->type == 4)) {\n+\t\t\tfor (port = 0; port < prop.fme.num_ports; port++) {\n+\t\t\t\tcmdline_printf(cl, \"%s%d:\\n\", \"PORT\", port);\n+\t\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\t\"access type\",\n+\t\t\t\t\tprop.port[port].type ? \"VF\" : \"PF\");\n+\t\t\t\tuuid_to_str(&prop.port[port].afu_id, &str);\n+\t\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\t\"accelerator id\", str.s);\n+\t\t\t}\n+\t\t}\n+\t\tif ((res->type == 0) || (res->type == 8)) {\n+\t\t\tcmdline_printf(cl, \"%s:\\n\", \"BMC\");\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"MAX10 version\", prop.bmc.bmc_version);\n+\t\t\tcmdline_printf(cl, \" %-16s : %s\\n\",\n+\t\t\t\t\"NIOS FW version\", prop.bmc.fw_version);\n+\t\t}\n+\t} else {\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_property_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_property_result, cmd, \"get_property\");\n+cmdline_parse_token_string_t cmd_property_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_property_result, bdf, NULL);\n+cmdline_parse_token_num_t cmd_property_type =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_property_result, type, RTE_INT32);\n+\n+cmdline_parse_inst_t cmd_get_property = {\n+\t.f = cmd_property_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get property of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_property_cmd,\n+\t\t(void *)&cmd_property_bdf,\n+\t\t(void *)&cmd_property_type,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET PHY INFO *** */\n+struct cmd_phy_info_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_phy_info_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_phy_info_result *res = parsed_result;\n+\topae_pci_device id;\n+\topae_phy_info info;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_get_phy_info(&id, &info) == 0) {\n+\t\tcmdline_printf(cl, \" %-16s : %u\\n\",\n+\t\t\t\"retimers num\", info.num_retimers);\n+\t\tcmdline_printf(cl, \" %-16s : %uG\\n\",\n+\t\t\t\"link speed\", info.link_speed);\n+\t\tcmdline_printf(cl, \" %-16s : %02x\\n\",\n+\t\t\t\"link status\", info.link_status);\n+\t} else {\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_phy_info_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_phy_info_result, cmd, \"get_phy_info\");\n+cmdline_parse_token_string_t cmd_phy_info_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_phy_info_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_phy_info = {\n+\t.f = cmd_phy_info_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get information of PHY\",\n+\t.tokens = {\n+\t\t(void *)&cmd_phy_info_cmd,\n+\t\t(void *)&cmd_phy_info_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET PARENT *** */\n+struct cmd_parent_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_parent_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_parent_result *res = parsed_result;\n+\topae_pci_device id;\n+\topae_pci_device parent;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_get_parent(&id, &parent) > 0)\n+\t\tcmdline_printf(cl, \"%s\\n\", parent.bdf);\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_parent_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_parent_result, cmd, \"get_parent\");\n+cmdline_parse_token_string_t cmd_parent_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_parent_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_get_parent = {\n+\t.f = cmd_parent_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get parent PCI device of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_parent_cmd,\n+\t\t(void *)&cmd_parent_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET CHILD *** */\n+struct cmd_child_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_child_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_child_result *res = parsed_result;\n+\topae_pci_device id;\n+\tpcidev_id child;\n+\tint i, count = 0;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tcount = opae_get_child(&id, NULL, 0);\n+\tif (count > 0) {\n+\t\tchild = (pcidev_id)malloc(sizeof(opae_pci_device) * count);\n+\t\tif (child) {\n+\t\t\topae_get_child(&id, child, count);\n+\t\t\tfor (i = 0; i < count; i++)\n+\t\t\t\tcmdline_printf(cl, \"%s\\n\", child[i].bdf);\n+\t\t\tfree(child);\n+\t\t} else {\n+\t\t\tcmdline_printf(cl, \"No memory\\n\");\n+\t\t}\n+\t} else if (count == 0) {\n+\t\tcmdline_printf(cl, \"No child\\n\");\n+\t} else {\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_child_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_child_result, cmd, \"get_child\");\n+cmdline_parse_token_string_t cmd_child_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_child_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_get_child = {\n+\t.f = cmd_child_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get child PCI device of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_child_cmd,\n+\t\t(void *)&cmd_child_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** GET PF1 *** */\n+struct cmd_pf1_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_pf1_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_pf1_result *res = parsed_result;\n+\topae_pci_device id;\n+\tpcidev_id peer;\n+\tint i, count = 0;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tcount = opae_get_pf1(&id, NULL, 0);\n+\tif (count > 0) {\n+\t\tpeer = (pcidev_id)malloc(sizeof(opae_pci_device) * count);\n+\t\tif (peer) {\n+\t\t\topae_get_pf1(&id, peer, count);\n+\t\t\tfor (i = 0; i < count; i++)\n+\t\t\t\tcmdline_printf(cl, \"%s\\n\", peer[i].bdf);\n+\t\t\tfree(peer);\n+\t\t} else {\n+\t\t\tcmdline_printf(cl, \"No memory\\n\");\n+\t\t}\n+\t} else if (count == 0) {\n+\t\tcmdline_printf(cl, \"No PF1\\n\");\n+\t} else {\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_pf1_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pf1_result, cmd, \"get_pf1\");\n+cmdline_parse_token_string_t cmd_pf1_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pf1_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_get_pf1 = {\n+\t.f = cmd_pf1_parsed,\n+\t.data = NULL,\n+\t.help_str = \"get physical function 1 device of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_pf1_cmd,\n+\t\t(void *)&cmd_pf1_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** SET LOG LEVEL *** */\n+struct cmd_log_level_result {\n+\tcmdline_fixed_string_t cmd;\n+\tint32_t level;\n+};\n+\n+static void cmd_log_level_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_log_level_result *res = parsed_result;\n+\tif (opae_set_log_level(res->level) == res->level)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_log_level_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_log_level_result, cmd, \"set_log_level\");\n+cmdline_parse_token_num_t cmd_log_level_level =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_log_level_result, level, RTE_INT32);\n+\n+cmdline_parse_inst_t cmd_set_log_level = {\n+\t.f = cmd_log_level_parsed,\n+\t.data = NULL,\n+\t.help_str = \"set logging level\",\n+\t.tokens = {\n+\t\t(void *)&cmd_log_level_cmd,\n+\t\t(void *)&cmd_log_level_level,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** SET LOG FILE *** */\n+struct cmd_log_file_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t path;\n+};\n+\n+static void cmd_log_file_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_log_file_result *res = parsed_result;\n+\tif (opae_set_log_file(res->path, 1) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_log_file_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_log_file_result, cmd, \"set_log_file\");\n+cmdline_parse_token_string_t cmd_log_file_path =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_log_file_result, path, NULL);\n+\n+cmdline_parse_inst_t cmd_set_log_file = {\n+\t.f = cmd_log_file_parsed,\n+\t.data = NULL,\n+\t.help_str = \"set logging file\",\n+\t.tokens = {\n+\t\t(void *)&cmd_log_file_cmd,\n+\t\t(void *)&cmd_log_file_path,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** SET STATUS *** */\n+struct cmd_set_status_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tuint32_t stat;\n+\tuint32_t prog;\n+};\n+\n+static void cmd_set_status_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_set_status_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\tif ((res->stat > 4) || (res->prog > 100)) {\n+\t\tcmdline_printf(cl, \"%u,%u is invalid status\\n\", res->stat,\n+\t\t\tres->prog);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_store_rsu_status(&id, res->stat, res->prog) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_set_status_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_set_status_result, cmd, \"set_status\");\n+cmdline_parse_token_string_t cmd_set_status_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_set_status_result, bdf, NULL);\n+cmdline_parse_token_num_t cmd_set_status_stat =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_set_status_result, stat, RTE_UINT32);\n+cmdline_parse_token_num_t cmd_set_status_prog =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_set_status_result, prog, RTE_UINT32);\n+\n+cmdline_parse_inst_t cmd_set_status = {\n+\t.f = cmd_set_status_parsed,\n+\t.data = NULL,\n+\t.help_str = \"set current status & progress of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_set_status_cmd,\n+\t\t(void *)&cmd_set_status_bdf,\n+\t\t(void *)&cmd_set_status_stat,\n+\t\t(void *)&cmd_set_status_prog,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** ENUMERATE *** */\n+struct cmd_enumerate_result {\n+\tcmdline_fixed_string_t cmd;\n+\tuint32_t vid;\n+\tuint32_t did;\n+};\n+\n+static void cmd_enumerate_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_enumerate_result *res = parsed_result;\n+\topae_pci_id filter;\n+\topae_pci_device *id;\n+\tint i, count = 0;\n+\n+\tfilter.vendor_id = res->vid;\n+\tfilter.device_id = res->did;\n+\tfilter.class_id = BIT_SET_32;\n+\tfilter.subsystem_vendor_id = BIT_SET_16;\n+\tfilter.subsystem_device_id = BIT_SET_16;\n+\n+\tcount = opae_enumerate(&filter, NULL, 0);\n+\tif (count > 0) {\n+\t\tid = (opae_pci_device *)malloc(sizeof(opae_pci_device) * count);\n+\t\tif (id) {\n+\t\t\topae_enumerate(&filter, id, count);\n+\t\t\tfor (i = 0; i < count; i++)\n+\t\t\t\tcmdline_printf(cl, \"%s\\n\", id[i].bdf);\n+\t\t\tfree(id);\n+\t\t} else {\n+\t\t\tcmdline_printf(cl, \"No memory\\n\");\n+\t\t}\n+\t} else if (count == 0) {\n+\t\tcmdline_printf(cl, \"Not found\\n\");\n+\t} else {\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+\t}\n+}\n+\n+cmdline_parse_token_string_t cmd_enumerate_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_enumerate_result, cmd, \"enumerate\");\n+cmdline_parse_token_num_t cmd_enumerate_vid =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_enumerate_result, vid, RTE_UINT32);\n+cmdline_parse_token_num_t cmd_enumerate_did =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_enumerate_result, did, RTE_UINT32);\n+\n+cmdline_parse_inst_t cmd_enumerate = {\n+\t.f = cmd_enumerate_parsed,\n+\t.data = NULL,\n+\t.help_str = \"enumerate specified FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_enumerate_cmd,\n+\t\t(void *)&cmd_enumerate_vid,\n+\t\t(void *)&cmd_enumerate_did,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** BIND *** */\n+struct cmd_bind_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tcmdline_fixed_string_t drv;\n+};\n+\n+static void cmd_bind_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_bind_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_bind_driver(&id, res->drv) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_bind_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_bind_result, cmd, \"bind\");\n+cmdline_parse_token_string_t cmd_bind_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_bind_result, bdf, NULL);\n+cmdline_parse_token_string_t cmd_bind_drv =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_bind_result, drv, NULL);\n+\n+cmdline_parse_inst_t cmd_bind = {\n+\t.f = cmd_bind_parsed,\n+\t.data = NULL,\n+\t.help_str = \"bind FPGA with kernel driver\",\n+\t.tokens = {\n+\t\t(void *)&cmd_bind_cmd,\n+\t\t(void *)&cmd_bind_bdf,\n+\t\t(void *)&cmd_bind_drv,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** UNBIND *** */\n+struct cmd_unbind_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_unbind_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_unbind_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_unbind_driver(&id) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_unbind_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_bind_result, cmd, \"unbind\");\n+cmdline_parse_token_string_t cmd_unbind_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_bind_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_unbind = {\n+\t.f = cmd_unbind_parsed,\n+\t.data = NULL,\n+\t.help_str = \"unbind FPGA from kernel driver\",\n+\t.tokens = {\n+\t\t(void *)&cmd_unbind_cmd,\n+\t\t(void *)&cmd_unbind_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** PROBE *** */\n+struct cmd_probe_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_probe_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_probe_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_probe_device(&id) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_probe_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_probe_result, cmd, \"probe\");\n+cmdline_parse_token_string_t cmd_probe_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_probe_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_probe = {\n+\t.f = cmd_probe_parsed,\n+\t.data = NULL,\n+\t.help_str = \"probe FPGA with IFPGA driver\",\n+\t.tokens = {\n+\t\t(void *)&cmd_probe_cmd,\n+\t\t(void *)&cmd_probe_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** REMOVE *** */\n+struct cmd_remove_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_remove_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_remove_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_remove_device(&id) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_remove_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_remove_result, cmd, \"remove\");\n+cmdline_parse_token_string_t cmd_remove_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_remove_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_remove = {\n+\t.f = cmd_remove_parsed,\n+\t.data = NULL,\n+\t.help_str = \"remove FPGA from IFPGA driver\",\n+\t.tokens = {\n+\t\t(void *)&cmd_remove_cmd,\n+\t\t(void *)&cmd_remove_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** FLASH *** */\n+struct cmd_flash_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tcmdline_fixed_string_t path;\n+};\n+\n+static void cmd_flash_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_flash_result *res = parsed_result;\n+\topae_pci_device id;\n+\tuint64_t stat = 0;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_update_flash(&id, res->path, &stat))\n+\t\tcmdline_printf(cl, \"Error: 0x%lx\\n\", stat);\n+}\n+\n+cmdline_parse_token_string_t cmd_flash_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_flash_result, cmd, \"flash\");\n+cmdline_parse_token_string_t cmd_flash_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_flash_result, bdf, NULL);\n+cmdline_parse_token_string_t cmd_flash_path =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_flash_result, path, NULL);\n+\n+cmdline_parse_inst_t cmd_flash = {\n+\t.f = cmd_flash_parsed,\n+\t.data = NULL,\n+\t.help_str = \"update flash of FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_flash_cmd,\n+\t\t(void *)&cmd_flash_bdf,\n+\t\t(void *)&cmd_flash_path,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** PR *** */\n+struct cmd_pr_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tint32_t port;\n+\tcmdline_fixed_string_t path;\n+};\n+\n+static void cmd_pr_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_pr_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_partial_reconfigure(&id, res->port, res->path) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_pr_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pr_result, cmd, \"pr\");\n+cmdline_parse_token_string_t cmd_pr_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pr_result, bdf, NULL);\n+cmdline_parse_token_num_t cmd_pr_port =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_pr_result, port, RTE_INT32);\n+cmdline_parse_token_string_t cmd_pr_path =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pr_result, path, NULL);\n+\n+cmdline_parse_inst_t cmd_pr = {\n+\t.f = cmd_pr_parsed,\n+\t.data = NULL,\n+\t.help_str = \"partial reconfigure FPGA\",\n+\t.tokens = {\n+\t\t(void *)&cmd_pr_cmd,\n+\t\t(void *)&cmd_pr_bdf,\n+\t\t(void *)&cmd_pr_port,\n+\t\t(void *)&cmd_pr_path,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** REBOOT *** */\n+struct cmd_reboot_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tcmdline_fixed_string_t type;\n+\tint32_t page;\n+};\n+\n+static void cmd_reboot_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_reboot_result *res = parsed_result;\n+\topae_pci_device id;\n+\tint type = 0;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (!strcmp(res->type, \"fpga\")) {\n+\t\ttype = 0;\n+\t} else if (!strcmp(res->type, \"bmc\")) {\n+\t\ttype = 1;\n+\t} else {\n+\t\tcmdline_printf(cl, \"%s is invalid reboot type\\n\", res->type);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_reboot_device(&id, type, res->page) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_reboot_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_reboot_result, cmd, \"reboot\");\n+cmdline_parse_token_string_t cmd_reboot_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_reboot_result, bdf, NULL);\n+cmdline_parse_token_string_t cmd_reboot_type =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_reboot_result, type, NULL);\n+cmdline_parse_token_num_t cmd_reboot_page =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_reboot_result, page, RTE_INT32);\n+\n+cmdline_parse_inst_t cmd_reboot = {\n+\t.f = cmd_reboot_parsed,\n+\t.data = NULL,\n+\t.help_str = \"reboot FPGA or MAX10\",\n+\t.tokens = {\n+\t\t(void *)&cmd_reboot_cmd,\n+\t\t(void *)&cmd_reboot_bdf,\n+\t\t(void *)&cmd_reboot_type,\n+\t\t(void *)&cmd_reboot_page,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** CANCEL *** */\n+struct cmd_cancel_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+};\n+\n+static void cmd_cancel_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_cancel_result *res = parsed_result;\n+\topae_pci_device id;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (opae_cancel_flash_update(&id, 0) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_cancel_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_cancel_result, cmd, \"cancel\");\n+cmdline_parse_token_string_t cmd_cancel_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_cancel_result, bdf, NULL);\n+\n+cmdline_parse_inst_t cmd_cancel = {\n+\t.f = cmd_cancel_parsed,\n+\t.data = NULL,\n+\t.help_str = \"cancel flash update\",\n+\t.tokens = {\n+\t\t(void *)&cmd_cancel_cmd,\n+\t\t(void *)&cmd_cancel_bdf,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** CHECK *** */\n+struct cmd_check_result {\n+\tcmdline_fixed_string_t cmd;\n+};\n+\n+static void cmd_check_parsed(__rte_unused void *parsed_result,\n+\t__rte_unused struct cmdline *cl, __rte_unused void *data)\n+{\n+\topae_check_pcidev_list();\n+}\n+\n+cmdline_parse_token_string_t cmd_check_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_check_result, cmd, \"check\");\n+\n+cmdline_parse_inst_t cmd_check = {\n+\t.f = cmd_check_parsed,\n+\t.data = NULL,\n+\t.help_str = \"display list of PCI devices\",\n+\t.tokens = {\n+\t\t(void *)&cmd_check_cmd,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** PCI READ *** */\n+struct cmd_pci_read_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tuint32_t offset;\n+};\n+\n+static void cmd_pci_read_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_pci_read_result *res = parsed_result;\n+\topae_pci_device id;\n+\tuint32_t offset = 0;\n+\tuint32_t value = 0;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (res->offset & 0x3) {\n+\t\toffset = res->offset & ~3;\n+\t\tcmdline_printf(cl, \"align offset to 0x%x\\n\", offset);\n+\t} else {\n+\t\toffset = res->offset;\n+\t}\n+\n+\tif (opae_read_pci_cfg(&id, offset, &value) == 0)\n+\t\tcmdline_printf(cl, \"0x%08x\\n\", value);\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_pci_read_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pci_read_result, cmd, \"pci_read\");\n+cmdline_parse_token_string_t cmd_pci_read_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pci_read_result, bdf, NULL);\n+cmdline_parse_token_num_t cmd_pci_read_offset =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_pci_read_result, offset, RTE_UINT32);\n+\n+cmdline_parse_inst_t cmd_pci_read = {\n+\t.f = cmd_pci_read_parsed,\n+\t.data = NULL,\n+\t.help_str = \"read PCI configuration space\",\n+\t.tokens = {\n+\t\t(void *)&cmd_pci_read_cmd,\n+\t\t(void *)&cmd_pci_read_bdf,\n+\t\t(void *)&cmd_pci_read_offset,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** PCI WRITE *** */\n+struct cmd_pci_write_result {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t bdf;\n+\tuint32_t offset;\n+\tuint32_t value;\n+};\n+\n+static void cmd_pci_write_parsed(void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tstruct cmd_pci_write_result *res = parsed_result;\n+\topae_pci_device id;\n+\tuint32_t offset = 0;\n+\n+\tif (parse_pciaddr(res->bdf, &id) < 0) {\n+\t\tcmdline_printf(cl, \"%s is invalid PCI address\\n\", res->bdf);\n+\t\treturn;\n+\t}\n+\n+\tif (res->offset & 0x3) {\n+\t\toffset = res->offset & ~3;\n+\t\tcmdline_printf(cl, \"align offset to 0x%x\\n\", offset);\n+\t} else {\n+\t\toffset = res->offset;\n+\t}\n+\n+\tif (opae_write_pci_cfg(&id, offset, res->value) == 0)\n+\t\tcmdline_printf(cl, \"Successful\\n\");\n+\telse\n+\t\tcmdline_printf(cl, \"Failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_pci_write_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pci_write_result, cmd, \"pci_write\");\n+cmdline_parse_token_string_t cmd_pci_write_bdf =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pci_write_result, bdf, NULL);\n+cmdline_parse_token_num_t cmd_pci_write_offset =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_pci_write_result, offset, RTE_UINT32);\n+cmdline_parse_token_num_t cmd_pci_write_value =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_pci_write_result, value, RTE_UINT32);\n+\n+cmdline_parse_inst_t cmd_pci_write = {\n+\t.f = cmd_pci_write_parsed,\n+\t.data = NULL,\n+\t.help_str = \"write PCI configuration space\",\n+\t.tokens = {\n+\t\t(void *)&cmd_pci_write_cmd,\n+\t\t(void *)&cmd_pci_write_bdf,\n+\t\t(void *)&cmd_pci_write_offset,\n+\t\t(void *)&cmd_pci_write_value,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** QUIT *** */\n+struct cmd_quit_result {\n+\tcmdline_fixed_string_t quit;\n+};\n+\n+static void cmd_quit_parsed(__rte_unused void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tcmdline_quit(cl);\n+}\n+\n+cmdline_parse_token_string_t cmd_quit_quit =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, \"quit\");\n+\n+cmdline_parse_inst_t cmd_quit = {\n+\t.f = cmd_quit_parsed,\n+\t.data = NULL,\n+\t.help_str = \"exit DPDK application\",\n+\t.tokens = {\n+\t\t(void *)&cmd_quit_quit,\n+\t\tNULL,\n+\t},\n+};\n+\n+/* *** HELP *** */\n+struct cmd_help_result {\n+\tcmdline_fixed_string_t help;\n+};\n+\n+static void cmd_help_parsed(__rte_unused void *parsed_result,\n+\tstruct cmdline *cl, __rte_unused void *data)\n+{\n+\tcmdline_printf(cl,\n+\t\t\" get_api_version               \\t\\t\"\n+\t\t\t\"get OPAE API version\\n\"\n+\t\t\" get_proc_type                 \\t\\t\"\n+\t\t\t\"get DPDK process type\\n\"\n+\t\t\" get_image_info <FILE>         \\t\\t\"\n+\t\t\t\"get information of image file\\n\"\n+\t\t\" get_status <BDF>              \\t\\t\"\n+\t\t\t\"get current status & progress of FPGA\\n\"\n+\t\t\" get_property <BDF> <0|1|2|4|8>\\t\\t\"\n+\t\t\t\"get property of FPGA\\n\"\n+\t\t\" get_phy_info <BDF>            \\t\\t\"\n+\t\t\t\"get information of PHY\\n\"\n+\t\t\" get_parent <BDF>              \\t\\t\"\n+\t\t\t\"get parent PCI device of FPGA\\n\"\n+\t\t\" get_child <BDF>               \\t\\t\"\n+\t\t\t\"get child PCI device of FPGA\\n\"\n+\t\t\" get_pf1 <BDF>                 \\t\\t\"\n+\t\t\t\"get physical function 1 device of FPGA\\n\"\n+\t\t\" set_log_level <0-4>           \\t\\t\"\n+\t\t\t\"set logging level\\n\"\n+\t\t\" set_log_file <FILE>           \\t\\t\"\n+\t\t\t\"set logging file\\n\"\n+\t\t\" set_status <BDF> <0-4> <0-100>\\t\\t\"\n+\t\t\t\"set current status & progress of FPGA\\n\"\n+\t\t\" enumerate <VID> <DID>         \\t\\t\"\n+\t\t\t\"enumerate specified FPGA\\n\"\n+\t\t\" bind <BDF> <DRIVER>           \\t\\t\"\n+\t\t\t\"bind FPGA with kernel driver\\n\"\n+\t\t\" unbind <BDF>                  \\t\\t\"\n+\t\t\t\"unbind FPGA from kernel driver\\n\"\n+\t\t\" probe <BDF>                   \\t\\t\"\n+\t\t\t\"probe FPGA with IFPGA driver\\n\"\n+\t\t\" remove <BDF>                  \\t\\t\"\n+\t\t\t\"remove FPGA from IFPGA driver\\n\"\n+\t\t\" flash <BDF> <FILE>            \\t\\t\"\n+\t\t\t\"update flash of FPGA\\n\"\n+\t\t\" pr <BDF> <PORT> <FILE>        \\t\\t\"\n+\t\t\t\"partial reconfigure FPGA\\n\"\n+\t\t\" reboot <BDF> <fpga|bmc> <0-1> \\t\\t\"\n+\t\t\t\"reboot FPGA or MAX10\\n\"\n+\t\t\" cancel <BDF>                  \\t\\t\"\n+\t\t\t\"cancel flash update\\n\"\n+\t\t\" check                         \\t\\t\"\n+\t\t\t\"display list of PCI devices\\n\"\n+\t\t\" pci_read <BDF> <0-1024>       \\t\\t\"\n+\t\t\t\"read PCI configuration space\\n\"\n+\t\t\" pci_write <BDF> <0-1024> <NUM>\\t\\t\"\n+\t\t\t\"write PCI configuration space\\n\"\n+\t\t\" quit                          \\t\\t\"\n+\t\t\t\"exit DPDK application\\n\"\n+\t\t\" help                          \\t\\t\"\n+\t\t\t\"show commands list\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_help_help =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_help_result, help, \"help\");\n+\n+cmdline_parse_inst_t cmd_help = {\n+\t.f = cmd_help_parsed,\n+\t.data = NULL,\n+\t.help_str = \"show commands list\",\n+\t.tokens = {\n+\t\t(void *)&cmd_help_help,\n+\t\tNULL,\n+\t},\n+};\n+\n+/****** CONTEXT (list of commands) */\n+cmdline_parse_ctx_t main_ctx[] = {\n+\t(cmdline_parse_inst_t *)&cmd_get_image_info,\n+\t(cmdline_parse_inst_t *)&cmd_get_api_version,\n+\t(cmdline_parse_inst_t *)&cmd_get_proc_type,\n+\t(cmdline_parse_inst_t *)&cmd_get_status,\n+\t(cmdline_parse_inst_t *)&cmd_get_property,\n+\t(cmdline_parse_inst_t *)&cmd_phy_info,\n+\t(cmdline_parse_inst_t *)&cmd_get_parent,\n+\t(cmdline_parse_inst_t *)&cmd_get_child,\n+\t(cmdline_parse_inst_t *)&cmd_get_pf1,\n+\t(cmdline_parse_inst_t *)&cmd_set_log_level,\n+\t(cmdline_parse_inst_t *)&cmd_set_log_file,\n+\t(cmdline_parse_inst_t *)&cmd_set_status,\n+\t(cmdline_parse_inst_t *)&cmd_enumerate,\n+\t(cmdline_parse_inst_t *)&cmd_bind,\n+\t(cmdline_parse_inst_t *)&cmd_unbind,\n+\t(cmdline_parse_inst_t *)&cmd_probe,\n+\t(cmdline_parse_inst_t *)&cmd_remove,\n+\t(cmdline_parse_inst_t *)&cmd_flash,\n+\t(cmdline_parse_inst_t *)&cmd_pr,\n+\t(cmdline_parse_inst_t *)&cmd_reboot,\n+\t(cmdline_parse_inst_t *)&cmd_cancel,\n+\t(cmdline_parse_inst_t *)&cmd_check,\n+\t(cmdline_parse_inst_t *)&cmd_pci_read,\n+\t(cmdline_parse_inst_t *)&cmd_pci_write,\n+\t(cmdline_parse_inst_t *)&cmd_quit,\n+\t(cmdline_parse_inst_t *)&cmd_help,\n+\tNULL,\n+};\ndiff --git a/examples/ifpga/commands.h b/examples/ifpga/commands.h\nnew file mode 100644\nindex 000000000..06fe9a68b\n--- /dev/null\n+++ b/examples/ifpga/commands.h\n@@ -0,0 +1,16 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020-2021 Intel Corporation\n+ */\n+\n+#ifndef _COMMANDS_H_\n+#define _COMMANDS_H_\n+\n+#include \"opae_api.h\"\n+\n+extern cmdline_parse_ctx_t main_ctx[];\n+\n+typedef struct {\n+\tchar s[38];\n+} uuid_str;\n+\n+#endif /* _COMMANDS_H_ */\ndiff --git a/examples/ifpga/main.c b/examples/ifpga/main.c\nnew file mode 100644\nindex 000000000..e9380d581\n--- /dev/null\n+++ b/examples/ifpga/main.c\n@@ -0,0 +1,38 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020-2021 Intel Corporation\n+ */\n+\n+#include <stdio.h>\n+#include <string.h>\n+#include <stdint.h>\n+#include <errno.h>\n+#include <sys/queue.h>\n+\n+#include <cmdline_rdline.h>\n+#include <cmdline_parse.h>\n+#include <cmdline_socket.h>\n+#include <cmdline.h>\n+\n+#include <rte_memory.h>\n+#include <rte_eal.h>\n+#include <rte_debug.h>\n+\n+#include \"commands.h\"\n+\n+\n+int main(int argc, char **argv)\n+{\n+\tstruct cmdline *cl;\n+\tint ret;\n+\n+\tret = opae_init_eal(argc, argv);\n+\tif (ret < 0)\n+\t\trte_panic(\"Cannot init EAL\\n\");\n+\tcl = cmdline_stdin_new(main_ctx, \"opae> \");\n+\tif (cl == NULL)\n+\t\trte_panic(\"Cannot create cmdline instance\\n\");\n+\tcmdline_interact(cl);\n+\topae_cleanup_eal();\n+\tcmdline_stdin_exit(cl);\n+\treturn 0;\n+}\ndiff --git a/examples/ifpga/meson.build b/examples/ifpga/meson.build\nnew file mode 100644\nindex 000000000..b88a37a7a\n--- /dev/null\n+++ b/examples/ifpga/meson.build\n@@ -0,0 +1,20 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2020-2021 Intel Corporation\n+\n+# meson file, for building this example as part of a main DPDK build.\n+#\n+# To build this example as a standalone application with an already-installed\n+# DPDK instance, use 'make'\n+\n+# require the raw_ifpga library\n+build = dpdk_conf.has('RTE_RAW_IFPGA')\n+if not build\n+\tsubdir_done()\n+endif\n+\n+deps += 'raw_ifpga'\n+allow_experimental_apis = true\n+sources = files(\n+\t'main.c', 'commands.c', 'opae_api.c'\n+)\n+cflags += '-fPIC'\ndiff --git a/examples/ifpga/opae_api.c b/examples/ifpga/opae_api.c\nnew file mode 100644\nindex 000000000..eccd0d459\n--- /dev/null\n+++ b/examples/ifpga/opae_api.c\n@@ -0,0 +1,1788 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <stdlib.h>\n+#include <string.h>\n+#include <dirent.h>\n+#include <fcntl.h>\n+#include <glob.h>\n+#include <unistd.h>\n+#include <sys/stat.h>\n+#include <rte_eal.h>\n+#include <rte_bus_pci.h>\n+#include <rte_rawdev_pmd.h>\n+#include \"base/opae_hw_api.h\"\n+#include \"base/ifpga_sec_mgr.h\"\n+#include \"ifpga_rawdev.h\"\n+#include \"opae_api.h\"\n+\n+\n+int opae_log_level;\n+FILE *opae_log_file;\n+\n+static opae_api_version api_ver = {21, 2, 0};\n+static int eal_inited;\n+static uint32_t dev_aer[2] = {0};\n+\n+static const char * const log_level_name[] = {\"CRITICAL\", \"ERROR\",\n+\t\"WARNING\", \"INFORMATION\", \"DEBUG\"};\n+static const char * const proc_type_name[] = {\"NON-DPDK\", \"PRIMARY\",\n+\t\"SECONDARY\"};\n+static const char * const platform_name[] = {\"Vista Creek\", \"Rush Creek\",\n+\t\"Darby Creek\", \"Lightning Creek\"};\n+static const char * const release_name[] = {\"Pre-Alpha\", \"Alpha\", \"Beta\", \"PV\"};\n+static const char * const interface_type[] = {\"8x10G\", \"4x25G\", \"2x1x25G\",\n+\t\"4x25G+2x25G\", \"2x2x25G\", \"2x1x25Gx2FVL\", \"1x2x25G\"};\n+static const char * const kdrv[] = {OPAE_KDRV_UNKNOWN, OPAE_KDRV_IGB_UIO,\n+\tOPAE_KDRV_VFIO_PCI, OPAE_KDRV_UIO_PCI};\n+\n+void opae_get_api_version(opae_api_version *version)\n+{\n+\tif (version)\n+\t\tmemcpy(version, &api_ver, sizeof(opae_api_version));\n+\topae_log_info(\"API version is %u.%u.%u\\n\",\n+\t\tapi_ver.major, api_ver.minor, api_ver.micro);\n+}\n+\n+int opae_set_log_level(int level)\n+{\n+\tif ((level >= OPAE_LOG_API) && (level <= OPAE_LOG_DEBUG))\n+\t\topae_log_level = level;\n+\topae_log_api(\"Current log level is %s\\n\",\n+\t\tlog_level_name[opae_log_level]);\n+\treturn opae_log_level;\n+}\n+\n+int opae_set_log_file(char *path, int clean)\n+{\n+\tFILE *f = NULL;\n+\ttime_t start;\n+\tstruct tm *lt = NULL;\n+\n+\tif (path) {\n+\t\tif (clean)\n+\t\t\tf = fopen(path, \"w+\");\n+\t\telse\n+\t\t\tf = fopen(path, \"a+\");\n+\n+\t\tif (f) {\n+\t\t\tif (opae_log_file) {\n+\t\t\t\tfclose(opae_log_file);\n+\t\t\t\topae_log_file = NULL;\n+\t\t\t}\n+\t\t\ttime(&start);\n+\t\t\tlt = localtime(&start);\n+\t\t\tif (lt)\n+\t\t\t\tfprintf(f, \"================%d-%02d-%02d \"\n+\t\t\t\t\t\"%02d:%02d:%02d================\\n\",\n+\t\t\t\t\t1900 + lt->tm_year, 1 + lt->tm_mon,\n+\t\t\t\t\tlt->tm_mday,\n+\t\t\t\t\tlt->tm_hour, lt->tm_min, lt->tm_sec);\n+\t\t\tfflush(f);\n+\t\t\topae_log_file = f;\n+\t\t} else {\n+\t\t\topae_log_err(\"failed to open log file \\'%s\\'\\n\", path);\n+\t\t\treturn -1;\n+\t\t}\n+\t} else {\n+\t\tif (opae_log_file) {\n+\t\t\tfclose(opae_log_file);\n+\t\t\topae_log_file = NULL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int opae_get_image_info(const char *image, opae_img_info *info)\n+{\n+\tint fd = -1;\n+\toff_t file_size = 0;\n+\topae_img_hdr hdr;\n+\tssize_t read_size = 0;\n+\tint ret = 0;\n+\n+\tif (!image || !info) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfd = open(image, O_RDONLY);\n+\tif (fd < 0) {\n+\t\topae_log_err(\"Failed to open \\'%s\\' for RD [e:%s]\\n\",\n+\t\t\timage, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\n+\tfile_size = lseek(fd, 0, SEEK_END);\n+\tif (file_size < (OPAE_IMG_HDR_SIZE + OPAE_IMG_PL_MIN_SIZE)) {\n+\t\topae_log_err(\"Size of \\'%s\\' is less than expected [e:%u]\\n\",\n+\t\t\timage, OPAE_IMG_HDR_SIZE + OPAE_IMG_PL_MIN_SIZE);\n+\t\tret = -EINVAL;\n+\t\tgoto close_fd;\n+\t}\n+\n+\t/* read image header */\n+\tlseek(fd, 0, SEEK_SET);\n+\tread_size = read(fd, (void *)&hdr, sizeof(opae_img_hdr));\n+\tif (read_size < 0) {\n+\t\topae_log_err(\"Failed to read from \\'%s\\' [e:%s]\\n\",\n+\t\t\timage, strerror(errno));\n+\t\tret = -EIO;\n+\t\tgoto close_fd;\n+\t}\n+\tif ((size_t)read_size != sizeof(opae_img_hdr)) {\n+\t\topae_log_err(\"Read length %zd is not expected [e:%zu]\\n\",\n+\t\t\tread_size, sizeof(opae_img_hdr));\n+\t\tret = -EIO;\n+\t\tgoto close_fd;\n+\t}\n+\n+\tinfo->total_len = file_size;\n+\t/* check signed image header */\n+\tif (hdr.magic == OPAE_IMG_BLK0_MAGIC) {\n+\t\tinfo->type = OPAE_IMG_TYPE(hdr.payload_type);\n+\t\tinfo->subtype = OPAE_IMG_SUBTYPE(hdr.payload_type);\n+\t\tinfo->payload_offset = OPAE_IMG_HDR_SIZE;\n+\t\tinfo->payload_len = hdr.payload_len;\n+\t} else {\n+\t\topae_log_err(\"Image \\'%s\\' can not be recognized\\n\", image);\n+\t\tret = -EINVAL;\n+\t}\n+close_fd:\n+\tclose(fd);\n+\treturn ret;\n+}\n+\n+static int write_file(char *path, char *buf, int size)\n+{\n+\tint fd = -1;\n+\tssize_t n = 0;\n+\n+\tif (!path || !buf || (size <= 0))\n+\t\treturn -EINVAL;\n+\n+\tfd = open(path, O_WRONLY);\n+\tif (fd < 0) {\n+\t\topae_log_err(\"Failed to open \\'%s\\' for WR [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\topae_log_dbg(\"Write \\\"%s\\\" to \\'%s\\'\\n\", buf, path);\n+\tn = write(fd, buf, size);\n+\tif (n < size)  {\n+\t\topae_log_err(\"Failed to write to \\'%s\\' [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\tclose(fd);\n+\t\treturn -EIO;\n+\t}\n+\tclose(fd);\n+\n+\treturn 0;\n+}\n+\n+static int read_file(char *path, char *buf, int size)\n+{\n+\tint fd = -1;\n+\tssize_t n = 0;\n+\n+\tif (!path || !buf || (size <= 0))\n+\t\treturn -EINVAL;\n+\n+\tfd = open(path, O_RDONLY);\n+\tif (fd < 0) {\n+\t\topae_log_err(\"Failed to open \\'%s\\' for RD [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\tn = read(fd, buf, size);\n+\tif (n < 0)  {\n+\t\topae_log_err(\"Failed to read from \\'%s\\' [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\tclose(fd);\n+\t\treturn -EIO;\n+\t}\n+\tclose(fd);\n+\n+\tif (n > 0)\n+\t\tbuf[n-1] = 0;\n+\n+\topae_log_dbg(\"Read \\\"%s\\\" from \\'%s\\'\\n\", buf, path);\n+\treturn 0;\n+}\n+\n+int opae_get_proc_type(void)\n+{\n+\tint type = -1;\n+\n+\tif (eal_inited) {\n+\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\t\ttype = 0;\n+\t\telse\n+\t\t\ttype = 1;\n+\t}\n+\topae_log_info(\"Current process type is %s\\n\", proc_type_name[type+1]);\n+\n+\treturn type;\n+}\n+\n+static bool check_eal(int inited)\n+{\n+\tif (!eal_inited) {\n+\t\tif (inited) {\n+\t\t\topae_log_warn(\"EAL is not initialized\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t} else {\n+\t\tif (!inited) {\n+\t\t\topae_log_warn(\"EAL is already initialized\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\treturn 1;\n+}\n+\n+int opae_init_eal(int argc, char **argv)\n+{\n+\tint ret = 0;\n+\n+\tif (!check_eal(0))\n+\t\treturn ret;\n+\n+\topae_log_level = OPAE_LOG_ERR;\n+\n+\tret = rte_eal_init(argc, argv);\n+\tif (ret < 0) {\n+\t\tif (rte_errno == EALREADY) {\n+\t\t\teal_inited = 1;\n+\t\t\treturn 0;\n+\t\t}\n+\t\topae_log_err(\"Cannot initialize EAL [e:%d]\\n\", ret);\n+\t\tif (rte_eal_cleanup())\n+\t\t\topae_log_warn(\"EAL could not release all resources\\n\");\n+\t} else {\n+\t\teal_inited = 1;\n+\t\topae_log_info(\"Initialize EAL done\\n\");\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int opae_cleanup_eal(void)\n+{\n+\tint ret = 0;\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\tifpga_rawdev_cleanup();\n+\n+\tret = rte_eal_cleanup();\n+\tif (ret)\n+\t\topae_log_err(\"Failed to cleanup EAL [e:%d]\\n\", ret);\n+\n+\tif (opae_log_file) {\n+\t\tfclose(opae_log_file);\n+\t\topae_log_file = NULL;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int compare_pci_id(opae_pci_id *id, opae_pci_id *expected_id)\n+{\n+\tif ((expected_id->class_id != BIT_SET_32) &&\n+\t\t(expected_id->class_id != id->class_id))\n+\t\treturn -1;\n+\tif ((expected_id->vendor_id != BIT_SET_16) &&\n+\t\t(expected_id->vendor_id != id->vendor_id))\n+\t\treturn -1;\n+\tif ((expected_id->device_id != BIT_SET_16) &&\n+\t\t(expected_id->device_id != id->device_id))\n+\t\treturn -1;\n+\tif ((expected_id->subsystem_vendor_id != BIT_SET_16) &&\n+\t\t(expected_id->subsystem_vendor_id != id->subsystem_vendor_id))\n+\t\treturn -1;\n+\tif ((expected_id->subsystem_device_id != BIT_SET_16) &&\n+\t\t(expected_id->subsystem_device_id != id->subsystem_device_id))\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+static int parse_sysfs_value(char *node, uint32_t *val)\n+{\n+\tchar buf[16];\n+\tchar *end = NULL;\n+\tint ret = 0;\n+\n+\tret = read_file(node, buf, sizeof(buf));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\t*val = (uint32_t)strtoul(buf, &end, 0);\n+\treturn 0;\n+}\n+\n+static int get_pci_id(const char *dev_path, opae_pci_id *id)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tuint32_t tmp;\n+\n+\tif (!dev_path || !id)\n+\t\treturn -EINVAL;\n+\n+\tsnprintf(path, sizeof(path), \"%s/vendor\", dev_path);\n+\tif (parse_sysfs_value(path, &tmp) < 0)\n+\t\treturn -ENODEV;\n+\tid->vendor_id = (uint16_t)tmp;\n+\n+\tsnprintf(path, sizeof(path), \"%s/device\", dev_path);\n+\tif (parse_sysfs_value(path, &tmp) < 0)\n+\t\treturn -ENODEV;\n+\tid->device_id = (uint16_t)tmp;\n+\n+\tsnprintf(path, sizeof(path), \"%s/subsystem_vendor\", dev_path);\n+\tif (parse_sysfs_value(path, &tmp) < 0)\n+\t\treturn -ENODEV;\n+\tid->subsystem_vendor_id = (uint16_t)tmp;\n+\n+\tsnprintf(path, sizeof(path), \"%s/subsystem_device\", dev_path);\n+\tif (parse_sysfs_value(path, &tmp) < 0)\n+\t\treturn -ENODEV;\n+\tid->subsystem_device_id = (uint16_t)tmp;\n+\n+\tsnprintf(path, sizeof(path), \"%s/class\", dev_path);\n+\tif (parse_sysfs_value(path, &tmp) < 0)\n+\t\treturn -ENODEV;\n+\tid->class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;\n+\n+\treturn 0;\n+}\n+\n+static int extract_path(char *in, int ridx, char *out, uint32_t size)\n+{\n+\tchar src[PATH_MAX] = {0};\n+\tchar *p = NULL;\n+\tint ret = 0;\n+\n+\tif (!in || (strlen(in) > PATH_MAX) || (ridx < 0) || !out)\n+\t\treturn -EINVAL;\n+\n+\tstrncpy(src, in, sizeof(src));\n+\t*out = 0;\n+\n+\twhile (1) {\n+\t\tp = strrchr(src, '/');\n+\t\tif (p) {\n+\t\t\t*p++ = 0;\n+\t\t\tif (*p) {\n+\t\t\t\tif (ridx-- <= 0) {\n+\t\t\t\t\tif (size > strlen(p)) {\n+\t\t\t\t\t\tstrncpy(out, p, size);\n+\t\t\t\t\t\tret = strlen(p);\n+\t\t\t\t\t}\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} else {\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int opae_enumerate(opae_pci_id *filter, pcidev_id list, int size)\n+{\n+\tDIR *dir = NULL;\n+\tstruct dirent *dirent = NULL;\n+\tchar path[PATH_MAX] = {0};\n+\topae_pci_id id;\n+\tint n = 0;\n+\n+\tif (!filter || (size < 0) || (!list && (size > 0))) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tdir = opendir(rte_pci_get_sysfs_path());\n+\tif (!dir) {\n+\t\topae_log_err(\"Failed to open \\'%s\\'\\n\",\n+\t\t\trte_pci_get_sysfs_path());\n+\t\treturn -EINVAL;\n+\t}\n+\twhile ((dirent = readdir(dir))) {\n+\t\tif (!strcmp(dirent->d_name, \".\"))\n+\t\t\tcontinue;\n+\t\tif (!strcmp(dirent->d_name, \"..\"))\n+\t\t\tcontinue;\n+\n+\t\tsnprintf(path, PATH_MAX, \"%s/%s\", rte_pci_get_sysfs_path(),\n+\t\t\tdirent->d_name);\n+\t\tif (get_pci_id(path, &id) < 0)\n+\t\t\tcontinue;\n+\t\tif (compare_pci_id(&id, filter) < 0)\n+\t\t\tcontinue;\n+\n+\t\tif (n++ < size) {\n+\t\t\tsnprintf(list->bdf, sizeof(list->bdf), \"%s\",\n+\t\t\t\tdirent->d_name);\n+\t\t\tlist++;\n+\t\t}\n+\t}\n+\tclosedir(dir);\n+\n+\treturn n;\n+}\n+\n+static int get_driver(pcidev_id id, char *drv_name, uint32_t size)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tchar link[PATH_MAX] = {0};\n+\tint ret = 0;\n+\n+\tif (!id || !drv_name) {\n+\t\tret = -EINVAL;\n+\t\tgoto end;\n+\t}\n+\tsize--;   /* reserve one byte for the end of string */\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s/driver\",\n+\t\trte_pci_get_sysfs_path(), id->bdf);\n+\tret = readlink(path, link, PATH_MAX);\n+\tif (ret >= PATH_MAX) {\n+\t\topae_log_err(\"Link path too long [%d]\\n\", ret);\n+\t\tret = -ENAMETOOLONG;\n+\t\tgoto end;\n+\t}\n+\tif (ret > 0) {\n+\t\tret = extract_path(link, 0, drv_name, size);\n+\t} else {\n+\t\t*drv_name = 0;\n+\t\topae_log_info(\"No link path for \\'%s\\'\\n\", path);\n+\t\tret = 0;\n+\t}\n+\n+end:\n+\tif (ret < 0)\n+\t\topae_log_err(\"Failed to get driver of %s\\n\", id->bdf);\n+\n+\treturn ret;\n+}\n+\n+static int get_pci_addr(const char *bdf, opae_pci_addr *addr)\n+{\n+\tunsigned int domain = 0;\n+\tunsigned int bus = 0;\n+\tunsigned int devid = 0;\n+\tunsigned int function = 0;\n+\tint ret = 0;\n+\n+\tif (!bdf || !addr)\n+\t\treturn -EINVAL;\n+\n+\tret = sscanf(bdf, \"%04x:%02x:%02x.%d\",\n+\t\t&domain, &bus, &devid, &function);\n+\tif (ret == 4) {\n+\t\taddr->domain = (uint32_t)domain;\n+\t\taddr->bus = (uint8_t)bus;\n+\t\taddr->devid = (uint8_t)devid;\n+\t\taddr->function = (uint8_t)function;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -EINVAL;\n+}\n+\n+static struct rte_rawdev *get_rte_rawdev(pcidev_id id, int log)\n+{\n+\topae_pci_addr addr;\n+\tstruct rte_rawdev *rdev = NULL;\n+\tchar rdev_name[OPAE_NAME_SIZE] = {0};\n+\n+\tif (!id)\n+\t\treturn NULL;\n+\n+\tif (get_pci_addr(id->bdf, &addr) < 0)\n+\t\treturn NULL;\n+\n+\tsnprintf(rdev_name, OPAE_NAME_SIZE, \"IFPGA:%02x:%02x.%x\",\n+\t\taddr.bus, addr.devid, addr.function);\n+\trdev = rte_rawdev_pmd_get_named_dev(rdev_name);\n+\tif (log && !rdev)\n+\t\topae_log_warn(\"%s is not probed\\n\", id->bdf);\n+\n+\treturn rdev;\n+}\n+\n+static struct rte_pci_device *get_rte_pcidev(pcidev_id id, int log)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tstruct rte_pci_bus *pci_bus = NULL;\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\n+\tif (!id)\n+\t\treturn NULL;\n+\n+\tpci_bus = ifpga_get_pci_bus();\n+\tif (pci_bus) {\n+\t\tTAILQ_FOREACH(pci_dev, &pci_bus->device_list, next) {\n+\t\t\tif (!strcmp(id->bdf, pci_dev->name))\n+\t\t\t\treturn pci_dev;\n+\t\t}\n+\t} else {\n+\t\trdev = get_rte_rawdev(id, 0);\n+\t\tif (rdev && rdev->device) {\n+\t\t\tpci_dev = RTE_DEV_TO_PCI(rdev->device);\n+\t\t\treturn pci_dev;\n+\t\t}\n+\t}\n+\n+\tif (log)\n+\t\topae_log_err(\"No rte_pci_device for %s\\n\", id->bdf);\n+\n+\treturn NULL;\n+}\n+\n+static int lock(pcidev_id id)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tint ret = 0;\n+\n+\trdev = get_rte_rawdev(id, 0);\n+\tif (rdev)\n+\t\tret = ifpga_rawdev_lock(rdev);\n+\n+\treturn ret;\n+}\n+\n+static int unlock(pcidev_id id)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tint ret = 0;\n+\n+\trdev = get_rte_rawdev(id, 0);\n+\tif (rdev)\n+\t\tret = ifpga_rawdev_unlock(rdev);\n+\n+\treturn ret;\n+}\n+\n+int opae_load_rsu_status(pcidev_id id, uint32_t *status, uint32_t *progress)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tuint32_t value = 0;\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (rdev)\n+\t\tvalue = ifpga_rawdev_get_rsu_stat(rdev);\n+\telse\n+\t\treturn -ENODEV;\n+\n+\tif (status)\n+\t\t*status = (value >> 16) & 0xffff;\n+\tif (progress)\n+\t\t*progress = value & 0xffff;\n+\n+\treturn 0;\n+}\n+\n+int opae_store_rsu_status(pcidev_id id, uint32_t status, uint32_t progress)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tuint32_t value = 0;\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (rdev) {\n+\t\tvalue = ((status << 16) & 0xffff0000) | (progress & 0xffff);\n+\t\tifpga_rawdev_set_rsu_stat(rdev, value);\n+\t} else {\n+\t\treturn -ENODEV;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int get_pci_property(pcidev_id id, opae_pci_property *prop)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tint ret = 0;\n+\n+\tif (!id || !prop)\n+\t\treturn -EINVAL;\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s\", rte_pci_get_sysfs_path(), id->bdf);\n+\n+\tret = get_pci_id(path, &prop->id);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = get_pci_addr(id->bdf, &prop->addr);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tsnprintf(prop->pci_addr, OPAE_NAME_SIZE, \"%s\", id->bdf);\n+\tget_driver(id, prop->drv_name, sizeof(prop->drv_name));\n+\n+\treturn 0;\n+}\n+\n+static int get_fme_property(pcidev_id id, opae_fme_property *prop)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tifpga_fme_property fme_prop;\n+\topae_bitstream_id bbs_id;\n+\tint ret = 0;\n+\n+\tif (!prop)\n+\t\treturn -EINVAL;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\tret = ifpga_rawdev_get_fme_property(rdev, &fme_prop);\n+\tif (!ret) {\n+\t\tprop->boot_page = fme_prop.boot_page;\n+\t\tprop->num_ports = fme_prop.num_ports;\n+\t\tprop->bitstream_id = fme_prop.bitstream_id;\n+\t\tprop->bitstream_metadata = fme_prop.bitstream_metadata;\n+\t\tmemcpy(prop->pr_id.b, fme_prop.pr_id.b, sizeof(opae_uuid));\n+\n+\t\tbbs_id.id = prop->bitstream_id;\n+\t\tif (bbs_id.major < sizeof(platform_name) / sizeof(char *)) {\n+\t\t\tsnprintf(prop->platform_name,\n+\t\t\t\tsizeof(prop->platform_name), \"%s\",\n+\t\t\t\tplatform_name[bbs_id.major]);\n+\t\t} else {\n+\t\t\tsnprintf(prop->platform_name,\n+\t\t\t\tsizeof(prop->platform_name), \"unknown\");\n+\t\t}\n+\n+\t\tsnprintf(prop->dcp_version, sizeof(prop->dcp_version),\n+\t\t\t\"DCP 1.%u\", bbs_id.minor);\n+\n+\t\tif (bbs_id.patch < sizeof(release_name)/sizeof(char *)) {\n+\t\t\tsnprintf(prop->release_name, sizeof(prop->release_name),\n+\t\t\t\t\"%s\", release_name[bbs_id.patch]);\n+\t\t} else {\n+\t\t\tsnprintf(prop->release_name, sizeof(prop->release_name),\n+\t\t\t\t\"unknown\");\n+\t\t}\n+\n+\t\tif (bbs_id.major == 0) {  /* Vista Creek */\n+\t\t\tif (bbs_id.interface <\n+\t\t\t\tsizeof(interface_type) / sizeof(char *)) {\n+\t\t\t\tsnprintf(prop->interface_type,\n+\t\t\t\t\tsizeof(prop->interface_type), \"%s\",\n+\t\t\t\t\tinterface_type[bbs_id.interface]);\n+\t\t\t} else {\n+\t\t\t\tsnprintf(prop->interface_type,\n+\t\t\t\t\tsizeof(prop->interface_type), \"unknown\");\n+\t\t\t}\n+\t\t} else {\n+\t\t\tsnprintf(prop->interface_type,\n+\t\t\t\tsizeof(prop->interface_type), \"unknown\");\n+\t\t}\n+\n+\t\tsnprintf(prop->build_version, sizeof(prop->build_version),\n+\t\t\t\"%u.%u.%u\", bbs_id.build_major, bbs_id.build_minor,\n+\t\t\tbbs_id.build_patch);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int get_port_property(pcidev_id id, uint32_t port,\n+\topae_port_property *prop)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tifpga_port_property port_prop;\n+\tint ret = 0;\n+\n+\tif (!prop || (port >= OPAE_MAX_PORT_NUM))\n+\t\treturn -EINVAL;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\tret = ifpga_rawdev_get_port_property(rdev, port, &port_prop);\n+\tif (!ret) {\n+\t\tmemcpy(prop->afu_id.b, port_prop.afu_id.b, sizeof(opae_uuid));\n+\t\tprop->type = port_prop.type;\n+\t\tprop->index = port;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int get_bmc_property(pcidev_id id, opae_bmc_property *prop)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tifpga_bmc_property bmc_prop;\n+\topae_bmc_version ver;\n+\tint ret = 0;\n+\n+\tif (!prop)\n+\t\treturn -EINVAL;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\tret = ifpga_rawdev_get_bmc_property(rdev, &bmc_prop);\n+\tif (!ret) {\n+\t\tver.version = bmc_prop.bmc_version;\n+\t\tsnprintf(prop->bmc_version, sizeof(prop->bmc_version), \"%c.%u.%u.%u\",\n+\t\t\tver.board, ver.major, ver.minor, ver.micro);\n+\n+\t\tver.version = bmc_prop.fw_version;\n+\t\tsnprintf(prop->fw_version, sizeof(prop->fw_version), \"%c.%u.%u.%u\",\n+\t\t\tver.board, ver.major, ver.minor, ver.micro);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int opae_get_property(pcidev_id id, opae_fpga_property *prop, int type)\n+{\n+\tuint32_t status = 0;\n+\tuint32_t i = 0;\n+\tint ret = 0;\n+\n+\tif (!prop) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (type == 0)\n+\t\ttype = OPAE_PROP_ALL;\n+\n+\tmemset(prop, 0, sizeof(opae_fpga_property));\n+\n+\t/* PCI properties */\n+\tif (type & OPAE_PROP_PCI) {\n+\t\tret = get_pci_property(id, &prop->pci);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to get PCI property\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tif (type == OPAE_PROP_PCI)\n+\t\treturn 0;\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\tif (!get_rte_rawdev(id, 1))\n+\t\treturn -ENODEV;\n+\n+\tlock(id);\n+\topae_load_rsu_status(id, &status, NULL);\n+\tif (status == IFPGA_RSU_REBOOT) {\n+\t\topae_log_warn(\"Reboot is in progress\\n\");\n+\t\tret = -EAGAIN;\n+\t\tgoto unlock_dev;\n+\t}\n+\n+\t/* FME properties */\n+\tif (type & (OPAE_PROP_FME | OPAE_PROP_PORT)) {\n+\t\tret = get_fme_property(id, &prop->fme);\n+\t\tif (ret) {\n+\t\t\topae_log_err(\"Failed to get FME property\\n\");\n+\t\t\tgoto unlock_dev;\n+\t\t}\n+\t}\n+\n+\t/* PORT properties */\n+\tif (type & OPAE_PROP_PORT) {\n+\t\tfor (i = 0; i < prop->fme.num_ports; i++) {\n+\t\t\tret = get_port_property(id, i, &prop->port[i]);\n+\t\t\tif (ret) {\n+\t\t\t\topae_log_err(\"Failed to get port property\\n\");\n+\t\t\t\tgoto unlock_dev;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* BMC properties */\n+\tif (type & OPAE_PROP_BMC) {\n+\t\tret = get_bmc_property(id, &prop->bmc);\n+\t\tif (ret) {\n+\t\t\topae_log_err(\"Failed to get BMC property\\n\");\n+\t\t\tgoto unlock_dev;\n+\t\t}\n+\t}\n+\n+unlock_dev:\n+\tunlock(id);\n+\treturn ret;\n+}\n+\n+int opae_get_phy_info(pcidev_id id, opae_phy_info *info)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tifpga_phy_info phy_info;\n+\tint ret = 0;\n+\n+\tif (!info)\n+\t\treturn -EINVAL;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\tret = ifpga_rawdev_get_phy_info(rdev, &phy_info);\n+\tif (!ret) {\n+\t\tinfo->num_retimers = phy_info.num_retimers;\n+\t\tinfo->link_speed = phy_info.link_speed;\n+\t\tinfo->link_status = phy_info.link_status;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int update_driver(pcidev_id id, char *drv_name)\n+{\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\tchar name[OPAE_NAME_SIZE] = {0};\n+\tint ret = 0;\n+\n+\tif (!id)\n+\t\treturn -EINVAL;\n+\n+\tif (drv_name) {\n+\t\tif (strlen(drv_name) >= OPAE_NAME_SIZE) {\n+\t\t\topae_log_err(\"Driver name \\'%s\\' too long\\n\",\n+\t\t\t\tdrv_name);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tstrncpy(name, drv_name, sizeof(name));\n+\t} else {\n+\t\tret = get_driver(id, name, sizeof(name));\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tpci_dev = get_rte_pcidev(id, 0);\n+\tif (pci_dev) {\n+\t\tif (strlen(name) == 0) {\n+\t\t\tpci_dev->kdrv = RTE_PCI_KDRV_NONE;\n+\t\t} else {\n+\t\t\tif (!strcmp(name, OPAE_KDRV_VFIO_PCI))\n+\t\t\t\tpci_dev->kdrv = RTE_PCI_KDRV_VFIO;\n+\t\t\telse if (!strcmp(name, OPAE_KDRV_IGB_UIO))\n+\t\t\t\tpci_dev->kdrv = RTE_PCI_KDRV_IGB_UIO;\n+\t\t\telse if (!strcmp(name, OPAE_KDRV_UIO_PCI))\n+\t\t\t\tpci_dev->kdrv = RTE_PCI_KDRV_UIO_GENERIC;\n+\t\t\telse\n+\t\t\t\tpci_dev->kdrv = RTE_PCI_KDRV_UNKNOWN;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int opae_unbind_driver(pcidev_id id)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tchar drv_name[OPAE_NAME_SIZE] = {0};\n+\tchar null[] = {0};\n+\tint ret = 0;\n+\n+\tif (get_rte_rawdev(id, 0)) {\n+\t\topae_log_err(\"%s is probed, remove it first\\n\", id->bdf);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tret = get_driver(id, drv_name, sizeof(drv_name));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (strlen(drv_name) > 0) {\n+\t\tsnprintf(path, PATH_MAX, \"/sys/bus/pci/drivers/%s/unbind\",\n+\t\t\tdrv_name);\n+\t\tret = write_file(path, id->bdf, strlen(id->bdf) + 1);\n+\t\tif (ret == 0)\n+\t\t\tret = update_driver(id, null);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int check_driver(const char *drv_name)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tstruct stat buf;\n+\n+\tif (!drv_name)\n+\t\treturn -EINVAL;\n+\n+\tif (strlen(drv_name) > 0) {\n+\t\tsnprintf(path, PATH_MAX, \"/sys/bus/pci/drivers/%s\", drv_name);\n+\t\tif ((stat(path, &buf) < 0) || ((buf.st_mode & S_IFDIR) == 0)) {\n+\t\t\topae_log_warn(\"Driver %s is not installed\\n\",\n+\t\t\t\tdrv_name);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int opae_bind_driver(pcidev_id id, char *drv_name)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tchar name[OPAE_NAME_SIZE] = {0};\n+\tchar null[] = {0};\n+\tint ret = 0;\n+\n+\tret = check_driver(drv_name);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = get_driver(id, name, sizeof(name));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (!strcmp(drv_name, name))   /* driver not change */\n+\t\treturn 0;\n+\n+\tret = opae_unbind_driver(id);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (strlen(drv_name) > 0) {\n+\t\t/* bind driver */\n+\t\tsnprintf(path, PATH_MAX, \"%s/%s/driver_override\",\n+\t\t\trte_pci_get_sysfs_path(), id->bdf);\n+\t\tret = write_file(path, drv_name, strlen(drv_name) + 1);\n+\t\tif (ret < 0)\n+\t\t\tgoto update_drv;\n+\n+\t\tsnprintf(path, PATH_MAX, \"/sys/bus/pci/drivers/%s/bind\",\n+\t\t\tdrv_name);\n+\t\tret = write_file(path, id->bdf, strlen(id->bdf) + 1);\n+\t\tif (ret < 0)\n+\t\t\tgoto update_drv;\n+\n+\t\tsnprintf(path, PATH_MAX, \"%s/%s/driver_override\",\n+\t\t\trte_pci_get_sysfs_path(), id->bdf);\n+\t\tret = write_file(path, null, 1);\n+\t\tif (ret < 0)\n+\t\t\tgoto update_drv;\n+\t}\n+\n+update_drv:\n+\tret = update_driver(id, NULL);\n+\tif (ret < 0)\n+\t\topae_log_err(\"Failed to update driver information of %s\\n\",\n+\t\t\tid->bdf);\n+\n+\treturn 0;\n+}\n+\n+int opae_probe_device(pcidev_id id)\n+{\n+\tstruct rte_pci_bus *pci_bus = NULL;\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\t/* make sure device is added in rte_pci_bus devices list */\n+\tpci_bus = ifpga_get_pci_bus();\n+\tif (pci_bus && pci_bus->bus.scan)\n+\t\tpci_bus->bus.scan();\n+\n+\tpci_dev = get_rte_pcidev(id, 1);\n+\tif (!pci_dev)\n+\t\treturn -ENODEV;\n+\n+\tif (pci_dev->kdrv != RTE_PCI_KDRV_VFIO) {\n+\t\topae_log_err(\"vfio-pci driver is not bound to %s\\n\", id->bdf);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!pci_bus || !pci_bus->bus.plug)\n+\t\treturn -ENODEV;\n+\n+\treturn pci_bus->bus.plug(&pci_dev->device);\n+}\n+\n+int opae_remove_device(pcidev_id id)\n+{\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\tstruct rte_pci_driver *pci_drv = NULL;\n+\tint ret = 0;\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\tpci_dev = get_rte_pcidev(id, 0);\n+\tif (pci_dev && pci_dev->driver) {\n+\t\tpci_drv = pci_dev->driver;\n+\t\tret = pci_drv->remove(pci_dev);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to remove %s [e:%d]\\n\",\n+\t\t\t\tid->bdf, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tpci_dev->driver = NULL;\n+\t\tpci_dev->device.driver = NULL;\n+\t\tif (pci_drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)\n+\t\t\trte_pci_unmap_device(pci_dev);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int is_pac(pcidev_id id)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\topae_pci_id pci_id;\n+\n+\tif (!id)\n+\t\treturn 0;\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s\", rte_pci_get_sysfs_path(), id->bdf);\n+\tif (get_pci_id(path, &pci_id) < 0)\n+\t\treturn 0;\n+\n+\tif ((pci_id.vendor_id == 0x8086) && (pci_id.device_id == 0x0b30))\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+int opae_get_parent(pcidev_id id, pcidev_id parent)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tchar link[PATH_MAX] = {0};\n+\tint ret = 0;\n+\n+\tif (!id || !parent) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\tret = -EINVAL;\n+\t\tgoto end;\n+\t}\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s\", rte_pci_get_sysfs_path(), id->bdf);\n+\tret = readlink(path, link, PATH_MAX);\n+\tif (ret >= PATH_MAX) {\n+\t\topae_log_err(\"Length of link path exceeds %u\\n\", PATH_MAX);\n+\t\tret = -ENAMETOOLONG;\n+\t\tgoto end;\n+\t}\n+\n+\tif (ret > 0) {\n+\t\tret = extract_path(link, 1, parent->bdf, sizeof(parent->bdf));\n+\t\tif (!strncmp(parent->bdf, \"pci\", 3)) {\n+\t\t\tparent->bdf[0] = 0;\n+\t\t\tret = -ENODEV;\n+\t\t}\n+\t} else {\n+\t\tparent->bdf[0] = 0;\n+\t\tif (ret == 0)\n+\t\t\topae_log_err(\"Length of link path is 0\\n\");\n+\t\telse\n+\t\t\topae_log_err(\"No link path for \\'%s\\'\\n\", path);\n+\t}\n+end:\n+\tif (ret <= 0)\n+\t\topae_log_err(\"%s has no parent\\n\", id->bdf);\n+\n+\treturn ret;\n+}\n+\n+int opae_get_child(pcidev_id id, pcidev_id child, int size)\n+{\n+\tglob_t pglob = {.gl_pathc = 0, .gl_pathv = NULL};\n+\tchar path[PATH_MAX] = {0};\n+\tint i, count = 0;\n+\tint len = 0;\n+\tint ret = 0;\n+\n+\tif (!id || (size < 0)) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s/*:*:*.?\", rte_pci_get_sysfs_path(),\n+\t\tid->bdf);\n+\tret = glob(path, 0, NULL, &pglob);\n+\tif (ret == 0) {\n+\t\tif (child && (size > 0)) {\n+\t\t\tfor (i = 0; i < (int)pglob.gl_pathc; i++) {\n+\t\t\t\tlen = extract_path(pglob.gl_pathv[i], 0,\n+\t\t\t\t\tchild->bdf, sizeof(child->bdf));\n+\t\t\t\tif (len <= 0) {\n+\t\t\t\t\tchild->bdf[0] = 0;\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\t\t\t\tif (++count >= size)\n+\t\t\t\t\tbreak;\n+\t\t\t\tchild++;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tcount = (int)pglob.gl_pathc;\n+\t\t}\n+\t\tglobfree(&pglob);\n+\t} else {\n+\t\tif (pglob.gl_pathv)\n+\t\t\tglobfree(&pglob);\n+\t}\n+\n+\treturn count;\n+}\n+\n+int opae_get_pf1(pcidev_id id, pcidev_id peer, int size)\n+{\n+\topae_pci_device parent;\n+\topae_pci_device child[4];\n+\tint n = 0;\n+\tint ret = 0;\n+\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!is_pac(id)) {\n+\t\topae_log_info(\"%s has no peer function\\n\", id->bdf);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = opae_get_parent(id, &parent);\n+\tif (ret < 0)\n+\t\treturn -ENODEV;\n+\tret = opae_get_parent(&parent, &parent);\n+\tif (ret < 0)\n+\t\treturn -ENODEV;\n+\n+\tn = opae_get_child(&parent, child,\n+\t\tsizeof(child) / sizeof(opae_pci_device));\n+\t/* there should have four downstream ports of PCI switch on board */\n+\tif (n == 4) {\n+\t\tn = opae_get_child(&child[3], peer, size);\n+\t} else {\n+\t\tpeer->bdf[0] = 0;\n+\t\topae_log_dbg(\"%s has %d child(s)\\n\", parent.bdf, n);\n+\t\tn = 0;\n+\t}\n+\n+\treturn n;\n+}\n+\n+void opae_check_pcidev_list(void)\n+{\n+\tint i = 0;\n+\tunsigned int k = 0;\n+\tstruct rte_pci_bus *pci_bus = NULL;\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\n+\tif (!check_eal(1))\n+\t\treturn;\n+\n+\tpci_bus = ifpga_get_pci_bus();\n+\tif (!pci_bus)\n+\t\treturn;\n+\n+\tprintf(\" ID     NAME       SEG BUS DEV FUNC  VID  DID   KDRV\\n\");\n+\tTAILQ_FOREACH(pci_dev, &pci_bus->device_list, next) {\n+\t\tk = pci_dev->kdrv;\n+\t\tprintf(\"%3d %s  %04x  %02x  %02x %2d   %04x %04x   %s\\n\",\n+\t\t\ti, pci_dev->name, pci_dev->addr.domain,\n+\t\t\tpci_dev->addr.bus, pci_dev->addr.devid,\n+\t\t\tpci_dev->addr.function, pci_dev->id.vendor_id,\n+\t\t\tpci_dev->id.device_id,\n+\t\t\tk > RTE_PCI_KDRV_UIO_GENERIC ? \"\" : kdrv[k]);\n+\t\ti++;\n+\t}\n+}\n+\n+int opae_update_flash(pcidev_id id, const char *image, uint64_t *status)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\topae_img_info info;\n+\tint ret = 0;\n+\n+\tret = opae_get_image_info(image, &info);\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to get image information [e:%d]\\n\", ret);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif ((info.type != OPAE_IMG_TYPE_BBS) &&\n+\t\t(info.type != OPAE_IMG_TYPE_BMC)) {\n+\t\topae_log_err(\"Image is not supported [t:%u]\\n\", info.type);\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\treturn ifpga_rawdev_update_flash(rdev, image, status);\n+}\n+\n+int opae_cancel_flash_update(pcidev_id id, int force)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\treturn ifpga_rawdev_stop_flash_update(rdev, force);\n+}\n+\n+#define PCI_EXT_CAP_ID_ERR\t\t0x01\t/* Advanced Error Reporting */\n+#define PCI_CFG_SPACE_SIZE\t\t256\n+#define PCI_CFG_SPACE_EXP_SIZE\t4096\n+#define PCI_EXT_CAP_ID(hdr)\t\t((int)((hdr) & 0x0000ffff))\n+#define PCI_EXT_CAP_NEXT(hdr)\t(((hdr) >> 20) & 0xffc)\n+\n+static int find_pci_ecap(int fd, int cap)\n+{\n+\tuint32_t header = 0;\n+\tint ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;\n+\tint pos = PCI_CFG_SPACE_SIZE;  /* start of extension capability area */\n+\tint ret = 0;\n+\n+\tret = pread(fd, &header, sizeof(header), pos);\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to read from PCI configuration space [e:%s]\\n\",\n+\t\t\tstrerror(errno));\n+\t\treturn ret;\n+\t}\n+\topae_log_dbg(\"Read 0x%08x from PCI configuration space 0x%x\\n\",\n+\t\theader, pos);\n+\n+\tif (header == 0) {\n+\t\topae_log_err(\"Capability is empty\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\twhile (ttl-- > 0) {\n+\t\tif ((PCI_EXT_CAP_ID(header) == cap) && (pos != 0))\n+\t\t\treturn pos;\n+\n+\t\tpos = PCI_EXT_CAP_NEXT(header);\n+\t\tif (pos < PCI_CFG_SPACE_SIZE) {\n+\t\t\topae_log_err(\"Position of capability is invalid\"\n+\t\t\t\t\t\t \"[e:%d]\\n\", pos);\n+\t\t\tbreak;\n+\t\t}\n+\t\tret = pread(fd, &header, sizeof(header), pos);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to read from PCI config space [e:%s]\\n\",\n+\t\t\t\tstrerror(errno));\n+\t\t\treturn ret;\n+\t\t}\n+\t\topae_log_dbg(\"Read 0x%08x from PCI configuration space 0x%x\\n\",\n+\t\t\theader, pos);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int set_aer(pcidev_id id, uint32_t v1, uint32_t v2, int record)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tuint32_t val = 0;\n+\tint fd = -1;\n+\tint pos = 0;\n+\tint ret = 0;\n+\n+\tif (!id)\n+\t\treturn -EINVAL;\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s/config\",\n+\t\trte_pci_get_sysfs_path(), id->bdf);\n+\tfd = open(path, O_RDWR);\n+\tif (fd < 0) {\n+\t\topae_log_err(\"Failed to open \\'%s\\' for RDWR [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\n+\tpos = find_pci_ecap(fd, PCI_EXT_CAP_ID_ERR);\n+\tif (pos <= 0) {\n+\t\topae_log_warn(\"AER capability is not present\\n\");\n+\t\tret = -ENXIO;\n+\t\tgoto close_fd;\n+\t}\n+\n+\tif (record) {\n+\t\tret = pread(fd, &val, sizeof(val), pos + 0x08);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to read from PCI config space [e:%s]\\n\",\n+\t\t\t\tstrerror(errno));\n+\t\t\tgoto close_fd;\n+\t\t}\n+\t\topae_log_dbg(\"Read 0x%08x from PCI configuration space 0x%x\\n\",\n+\t\t\tval, pos + 0x08);\n+\t\tdev_aer[0] = val;\n+\n+\t\tret = pread(fd, &val, sizeof(val), pos + 0x14);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to read from PCI config space [e:%s]\\n\",\n+\t\t\t\tstrerror(errno));\n+\t\t\tgoto close_fd;\n+\t\t}\n+\t\topae_log_dbg(\"Read 0x%08x from PCI configuration space 0x%x\\n\",\n+\t\t\tval, pos + 0x14);\n+\t\tdev_aer[1] = val;\n+\t}\n+\n+\topae_log_dbg(\"Write 0x%08x to PCI configuration space 0x%x\\n\",\n+\t\tv1, pos + 0x08);\n+\tret = pwrite(fd, &v1, sizeof(v1), pos + 0x08);\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to write to PCI config space 0x%x [e:%s]\\n\",\n+\t\t\tpos + 0x08, strerror(errno));\n+\t\tgoto close_fd;\n+\t}\n+\n+\topae_log_dbg(\"Write 0x%08x to PCI configuration space 0x%x\\n\",\n+\t\tv2, pos + 0x14);\n+\tret = pwrite(fd, &v2, sizeof(v2), pos + 0x14);\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to write to PCI config space 0x%x [e:%s]\\n\",\n+\t\t\tpos + 0x14, strerror(errno));\n+\t}\n+\n+close_fd:\n+\tclose(fd);\n+\treturn ret < 0 ? ret : 0;\n+}\n+\n+static int enable_aer(pcidev_id id)\n+{\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\topae_log_info(\"Enable AER of %s\\n\", id->bdf);\n+\n+\treturn set_aer(id, dev_aer[0], dev_aer[1], 0);\n+}\n+\n+static int disable_aer(pcidev_id id)\n+{\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\topae_log_info(\"Disable AER of %s\\n\", id->bdf);\n+\n+\treturn set_aer(id, 0xffffffff, 0xffffffff, 1);\n+}\n+\n+static int reload(pcidev_id id, int type, int page)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\tint ret = 0;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (rdev)\n+\t\tret = ifpga_rawdev_reload(rdev, type, page);\n+\telse\n+\t\tret = -ENODEV;\n+\n+\treturn ret;\n+}\n+\n+static int remove_tree(pcidev_id id)\n+{\n+\tint i, n = 0;\n+\tpcidev_id child;\n+\tint ret = 0;\n+\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tn = opae_get_child(id, NULL, 0);\n+\tif (n > 0) {\n+\t\tchild = (pcidev_id)rte_zmalloc(NULL,\n+\t\t\tsizeof(opae_pci_device) * n, 0);\n+\t\tif (!child) {\n+\t\t\topae_log_err(\"Failed to malloc for children of %s\\n\",\n+\t\t\t\tid->bdf);\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto end;\n+\t\t}\n+\n+\t\topae_get_child(id, child, n);\n+\t\tfor (i = 0; i < n; i++)\n+\t\t\tremove_tree(&child[i]);\n+\t\topae_free(child);\n+\t}\n+\n+end:\n+\topae_remove_device(id);\n+\treturn ret;\n+}\n+\n+static int remove_device(pcidev_id id)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tchar one[] = {'1', 0};\n+\tint ret = 0;\n+\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\topae_log_info(\"Remove %s from system\\n\", id->bdf);\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s/remove\",\n+\t\trte_pci_get_sysfs_path(), id->bdf);\n+\tret = write_file(path, one, strlen(one));\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to remove %s from system\\n\", id->bdf);\n+\t\treturn ret;\n+\t}\n+\n+\tremove_tree(id);\n+\n+\treturn 0;\n+}\n+\n+static int scan_device(pcidev_id parent, pcidev_id id)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tchar bus[8] = {0};\n+\tchar one[] = {'1', 0};\n+\tchar pwr[16] = {0};\n+\tchar pwr_on[] = {'o', 'n', 0};\n+\tint pwr_on_failed = 0;\n+\tint ret = 0;\n+\n+\tif (!parent) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\topae_log_info(\"Rescan devices under %s\\n\", parent->bdf);\n+\n+\tif (id) {   /* scan specified bus under parent device */\n+\t\tsnprintf(path, PATH_MAX, \"%s/%s/power/control\",\n+\t\t\trte_pci_get_sysfs_path(), parent->bdf);\n+\t\tret = read_file(path, pwr, sizeof(pwr));\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\n+\t\tif (strcmp(pwr, \"on\")) {\n+\t\t\tret = write_file(path, pwr_on, strlen(pwr_on));\n+\t\t\tif (ret < 0)\n+\t\t\t\tpwr_on_failed = 1;\n+\t\t\telse\n+\t\t\t\tsleep(1);\n+\t\t}\n+\n+\t\tsnprintf(bus, sizeof(bus), \"%s\", id->bdf);\n+\t\tsnprintf(path, PATH_MAX, \"%s/%s/pci_bus/%s/rescan\",\n+\t\t\trte_pci_get_sysfs_path(), parent->bdf, bus);\n+\t\tret = write_file(path, one, strlen(one));\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\n+\t\tif (pwr_on_failed) {   /* workaround for power on failed */\n+\t\t\tret = write_file(path, one, strlen(one));\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t}\n+\n+\t\tif (strcmp(pwr, \"on\")) {\n+\t\t\tsnprintf(path, PATH_MAX, \"%s/%s/power/control\",\n+\t\t\t\trte_pci_get_sysfs_path(), parent->bdf);\n+\t\t\tret = write_file(path, pwr, strlen(pwr));\n+\t\t}\n+\t} else {   /* scan all buses under parent device */\n+\t\tsnprintf(path, PATH_MAX, \"%s/%s/rescan\",\n+\t\t\trte_pci_get_sysfs_path(), parent->bdf);\n+\t\tret = write_file(path, one, strlen(one));\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int opae_reboot_device(pcidev_id id, int type, int page)\n+{\n+\topae_pci_device fpga;    /* FPGA after reboot */\n+\topae_pci_device parent;\n+\topae_pci_device peer[2];   /* physical function 1 of FPGA */\n+\topae_pci_device peer_parent;\n+\topae_pci_device ups;   /* upstream port device */\n+\topae_pci_device root;  /* port connected to PAC */\n+\tpcidev_id peer_primary = NULL;\n+\tuint32_t rsu_stat = 0;\n+\tchar drv_name[OPAE_NAME_SIZE] = {0};\n+\tint n = 0;\n+\tint i = 0;\n+\tint ret = 0;\n+\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!is_pac(id)) {\n+\t\topae_log_err(\"%s can not be rebooted\\n\", id->bdf);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = opae_get_parent(id, &parent);\n+\tif (ret < 0)\n+\t\treturn -ENODEV;\n+\tret = opae_get_parent(&parent, &ups);\n+\tif (ret < 0)\n+\t\treturn -ENODEV;\n+\tret = opae_get_parent(&ups, &root);\n+\tif (ret < 0)\n+\t\treturn -ENODEV;\n+\n+\tn = opae_get_pf1(id, peer, sizeof(peer) / sizeof(opae_pci_device));\n+\tif (n <= 0) {\n+\t\topae_log_err(\"PF1 of %s is not found\\n\", id->bdf);\n+\t} else {\n+\t\tpeer_primary = &peer[0];\n+\t\tret = opae_get_parent(peer_primary, &peer_parent);\n+\t\tif (ret < 0)\n+\t\t\treturn -ENODEV;\n+\t}\n+\n+\tget_driver(id, drv_name, sizeof(drv_name));  /* save original driver */\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\tif (!get_rte_rawdev(id, 1))\n+\t\treturn -ENODEV;\n+\n+\tlock(id);\n+\topae_load_rsu_status(id, &rsu_stat, NULL);\n+\tif (rsu_stat != IFPGA_RSU_IDLE) {\n+\t\tunlock(id);\n+\t\tif (rsu_stat == IFPGA_RSU_REBOOT)\n+\t\t\topae_log_warn(\"Reboot is in progress\\n\");\n+\t\telse\n+\t\t\topae_log_warn(\"Flash is in progress\\n\");\n+\t\treturn -EAGAIN;\n+\t}\n+\topae_store_rsu_status(id, IFPGA_RSU_REBOOT, 0);\n+\tunlock(id);\n+\n+\tif (type == IFPGA_BOOT_TYPE_FPGA) {\n+\t\t/* disable AER */\n+\t\tret = disable_aer(&parent);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to disable AER of %s\\n\",\n+\t\t\t\tparent.bdf);\n+\t\t\tgoto reboot_end;\n+\t\t}\n+\t\tret = disable_aer(&peer_parent);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to disable AER of %s\\n\",\n+\t\t\t\tpeer_parent.bdf);\n+\t\t\tgoto reboot_end;\n+\t\t}\n+\t\topae_store_rsu_status(id, IFPGA_RSU_REBOOT, 1);\n+\n+\t\t/* trigger reconfiguration */\n+\t\tret = reload(id, type, page);\n+\t\topae_store_rsu_status(id, IFPGA_RSU_REBOOT, 2);\n+\t\tif (ret == 0) {\n+\t\t\tret = remove_device(id);\n+\t\t\tfor (i = 0; i < n; i++)\n+\t\t\t\tret += remove_device(&peer[i]);\n+\t\t\tif (ret == 0) {\n+\t\t\t\topae_log_info(\"Wait 10 seconds for FPGA reloading\\n\");\n+\t\t\t\tsleep(10);\n+\t\t\t\tret = scan_device(&parent, id);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\topae_log_err(\"Failed to rescan %s\\n\",\n+\t\t\t\t\t\tid->bdf);\n+\t\t\t\tif (peer_primary) {\n+\t\t\t\t\tret = scan_device(&peer_parent,\n+\t\t\t\t\t\tpeer_primary);\n+\t\t\t\t\tif (ret < 0) {\n+\t\t\t\t\t\topae_log_err(\"Failed to rescan %s\\n\",\n+\t\t\t\t\t\t\tpeer_primary->bdf);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* restore AER */\n+\t\tif (enable_aer(&parent) < 0) {\n+\t\t\topae_log_err(\"Failed to enable AER of %s\\n\",\n+\t\t\t\tparent.bdf);\n+\t\t}\n+\t\tif (enable_aer(&peer_parent) < 0) {\n+\t\t\topae_log_err(\"Failed to enable AER of %s\\n\",\n+\t\t\t\tpeer_parent.bdf);\n+\t\t}\n+\t} else if (type == IFPGA_BOOT_TYPE_BMC) {\n+\t\t/* disable AER */\n+\t\tret = disable_aer(&root);\n+\t\tif (ret < 0) {\n+\t\t\topae_log_err(\"Failed to disable AER of %s\\n\", root.bdf);\n+\t\t\tgoto reboot_end;\n+\t\t}\n+\t\topae_store_rsu_status(id, IFPGA_RSU_REBOOT, 1);\n+\n+\t\t/* trigger reconfiguration */\n+\t\tret = reload(id, type, page);\n+\t\topae_store_rsu_status(id, IFPGA_RSU_REBOOT, 2);\n+\t\tif (ret == 0) {\n+\t\t\tret += remove_device(&ups);\n+\t\t\tif (ret == 0) {\n+\t\t\t\topae_log_info(\"Wait 10 seconds for BMC reloading\\n\");\n+\t\t\t\tsleep(10);\n+\t\t\t\tret = scan_device(&root, &ups);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\topae_log_err(\"Failed to rescan %s\\n\",\n+\t\t\t\t\t\tups.bdf);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* restore AER */\n+\t\tif (enable_aer(&root) < 0)\n+\t\t\topae_log_err(\"Failed to enable AER of %s\\n\", root.bdf);\n+\t} else {\n+\t\topae_log_err(\"Type of reboot is not supported [t:%d]\\n\", type);\n+\t\tret = -EINVAL;\n+\t\tgoto reboot_end;\n+\t}\n+\n+\t/* update id if bdf changed after reboot */\n+\tif (opae_get_child(&parent, &fpga, 1) == 1) {\n+\t\tif (strcmp(id->bdf, fpga.bdf))\n+\t\t\tid = &fpga;\n+\t}\n+\n+\tret = opae_bind_driver(id, drv_name);\n+\tif (ret < 0)\n+\t\topae_log_err(\"Failed to bind original driver of %s\\n\", id->bdf);\n+\n+\tret = opae_probe_device(id);\n+\tif (ret < 0)\n+\t\topae_log_err(\"Failed to probe %s [e:%d]\\n\", id->bdf, ret);\n+\n+reboot_end:\n+\topae_store_rsu_status(id, IFPGA_RSU_IDLE, 0);\n+\treturn ret;\n+}\n+\n+int opae_partial_reconfigure(pcidev_id id, int port, const char *gbs)\n+{\n+\tstruct rte_rawdev *rdev = NULL;\n+\n+\tif (!id || !gbs) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!check_eal(1))\n+\t\treturn -EPERM;\n+\n+\trdev = get_rte_rawdev(id, 1);\n+\tif (!rdev)\n+\t\treturn -ENODEV;\n+\n+\treturn ifpga_rawdev_partial_reconfigure(rdev, port, gbs);\n+}\n+\n+int opae_read_pci_cfg(pcidev_id id, uint32_t address, uint32_t *value)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tint fd = -1;\n+\tint ret = 0;\n+\n+\tif (!id || !value) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s/config\", rte_pci_get_sysfs_path(),\n+\t\tid->bdf);\n+\tfd = open(path, O_RDONLY);\n+\tif (fd < 0) {\n+\t\topae_log_dbg(\"Failed to open \\'%s\\' for RDONLY [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\n+\tret = pread(fd, value, 4, address);\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to read from PCI device %s [e:%s]\\n\",\n+\t\t\tid->bdf, strerror(errno));\n+\t\tclose(fd);\n+\t\treturn ret;\n+\t}\n+\n+\topae_log_dbg(\"CONFIG+0x%08x -> 0x%08x\\n\", address, *value);\n+\tclose(fd);\n+\treturn 0;\n+}\n+\n+int opae_write_pci_cfg(pcidev_id id, uint32_t address, uint32_t value)\n+{\n+\tchar path[PATH_MAX] = {0};\n+\tint fd = -1;\n+\tint ret = 0;\n+\n+\tif (!id) {\n+\t\topae_log_err(\"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsnprintf(path, PATH_MAX, \"%s/%s/config\", rte_pci_get_sysfs_path(),\n+\t\tid->bdf);\n+\tfd = open(path, O_WRONLY);\n+\tif (fd < 0) {\n+\t\topae_log_dbg(\"Failed to open \\'%s\\' for WRONLY [e:%s]\\n\",\n+\t\t\tpath, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\n+\tret = pwrite(fd, &value, 4, address);\n+\tif (ret < 0) {\n+\t\topae_log_err(\"Failed to write to PCI device %s [e:%s]\\n\",\n+\t\t\tid->bdf, strerror(errno));\n+\t\tclose(fd);\n+\t\treturn ret;\n+\t}\n+\n+\topae_log_dbg(\"CONFIG+0x%08x <- 0x%08x\\n\", address, value);\n+\tclose(fd);\n+\treturn 0;\n+}\ndiff --git a/examples/ifpga/opae_api.h b/examples/ifpga/opae_api.h\nnew file mode 100644\nindex 000000000..d4ce64280\n--- /dev/null\n+++ b/examples/ifpga/opae_api.h\n@@ -0,0 +1,245 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _OPAE_API_H\n+#define _OPAE_API_H\n+\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdint.h>\n+\n+extern int opae_log_level;\n+extern FILE *opae_log_file;\n+\n+#define OPAE_LOG_API      0  /**< Critical conditions.              */\n+#define OPAE_LOG_ERR      1  /**< Error conditions.                 */\n+#define OPAE_LOG_WARN     2  /**< Warning conditions.               */\n+#define OPAE_LOG_INFO     3  /**< Informational.                    */\n+#define OPAE_LOG_DEBUG    4  /**< Debug-level messages.             */\n+\n+#define opae_log(type, fmt, args...)             \\\n+do {                                             \\\n+\tif (opae_log_level >= OPAE_LOG_##type) {     \\\n+\t\tprintf(fmt, ##args);                     \\\n+\t\tif (opae_log_file) {                     \\\n+\t\t\tfprintf(opae_log_file, fmt, ##args); \\\n+\t\t\tfflush(opae_log_file);               \\\n+\t\t}                                        \\\n+\t}                                            \\\n+} while (0)\n+\n+#define opae_log_api(fmt, args...)  opae_log(API, \"OPAE-API: \"fmt, ##args)\n+#define opae_log_err(fmt, args...)  opae_log(ERR, \"OPAE-ERR: \"fmt, ##args)\n+#define opae_log_dbg(fmt, args...)  opae_log(DEBUG, \"OPAE-DBG: \"fmt, ##args)\n+#define opae_log_warn(fmt, args...) opae_log(WARN, \"OPAE-WARN: \"fmt, ##args)\n+#define opae_log_info(fmt, args...) opae_log(INFO, \"OPAE-INFO: \"fmt, ##args)\n+\n+#define EAL_INIT_FUNCTION    \"init\"\n+#define EAL_DEFAULT_OPTIONS  \"--proc-type auto\"\n+\n+#define OPAE_KDRV_UNKNOWN           \"unknown\"\n+#define OPAE_KDRV_VFIO_PCI          \"vfio-pci\"\n+#define OPAE_KDRV_IGB_UIO           \"igb_uio\"\n+#define OPAE_KDRV_UIO_PCI           \"uio_pci_generic\"\n+#define OPAE_KDRV_INTEL_FPGA_PCI    \"intel-fpga-pci\"\n+\n+typedef struct {\n+\tuint32_t major;\n+\tuint32_t minor;\n+\tuint32_t micro;\n+} opae_api_version;\n+\n+#define OPAE_NAME_SIZE  32\n+\n+typedef struct {\n+\tchar bdf[OPAE_NAME_SIZE];   /* segment:bus:device.function */\n+} opae_pci_device;\n+\n+typedef opae_pci_device *pcidev_id;\n+\n+typedef struct {\n+\tuint32_t class_id;            /**< Class ID or RTE_CLASS_ANY_ID. */\n+\tuint16_t vendor_id;           /**< Vendor ID or PCI_ANY_ID. */\n+\tuint16_t device_id;           /**< Device ID or PCI_ANY_ID. */\n+\tuint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */\n+\tuint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */\n+} opae_pci_id;\n+\n+typedef struct {\n+\tuint32_t domain;              /**< Device domain */\n+\tuint8_t bus;                  /**< Device bus */\n+\tuint8_t devid;                /**< Device ID */\n+\tuint8_t function;             /**< Device function. */\n+} opae_pci_addr;\n+\n+typedef struct {\n+\tchar pci_addr[OPAE_NAME_SIZE];  /* segment:bus:device.function */\n+\tchar drv_name[OPAE_NAME_SIZE];  /* vfio-pci, intel-fpga-pci, etc. */\n+\topae_pci_id id;\n+\topae_pci_addr addr;\n+} opae_pci_property;\n+\n+#define BIT_SET_8   0xFF\n+#define BIT_SET_16  0xFFFF\n+#define BIT_SET_32  0xFFFFFFFF\n+\n+typedef struct {\n+\tuint8_t b[16];\n+} opae_uuid;\n+\n+typedef struct {\n+\tuint32_t boot_page;\n+\tuint32_t num_ports;\n+\tuint64_t bitstream_id;\n+\tuint64_t bitstream_metadata;\n+\topae_uuid pr_id;\n+\tchar platform_name[OPAE_NAME_SIZE];\n+\tchar dcp_version[OPAE_NAME_SIZE];\n+\tchar release_name[OPAE_NAME_SIZE];\n+\tchar interface_type[OPAE_NAME_SIZE];\n+\tchar build_version[OPAE_NAME_SIZE];\n+} opae_fme_property;\n+\n+typedef struct {\n+\topae_uuid afu_id;\n+\tuint32_t type;   /* AFU memory access control type */\n+\tuint32_t index;  /* PORT index */\n+} opae_port_property;\n+\n+typedef struct {\n+\tchar bmc_version[OPAE_NAME_SIZE];\n+\tchar fw_version[OPAE_NAME_SIZE];\n+} opae_bmc_property;\n+\n+typedef struct {\n+\tuint32_t num_retimers;\n+\tuint32_t link_speed;\n+\tuint32_t link_status;  /* each bit corresponding to one link status */\n+} opae_phy_info;\n+\n+typedef struct {\n+\tunion {\n+\t\tuint64_t id;\n+\t\tstruct {\n+\t\t\tuint8_t build_patch;\n+\t\t\tuint8_t build_minor;\n+\t\t\tuint8_t build_major;\n+\t\t\tuint8_t fvl_bypass:1;\n+\t\t\tuint8_t mac_lightweight:1;\n+\t\t\tuint8_t disagregate:1;\n+\t\t\tuint8_t lightweiht:1;\n+\t\t\tuint8_t seu:1;\n+\t\t\tuint8_t ptp:1;\n+\t\t\tuint8_t reserve:2;\n+\t\t\tuint16_t interface:4;\n+\t\t\tuint16_t afu_revision:12;\n+\t\t\tuint16_t patch:4;\n+\t\t\tuint16_t minor:4;\n+\t\t\tuint16_t major:4;\n+\t\t\tuint16_t reserved:4;\n+\t\t};\n+\t};\n+} opae_bitstream_id;\n+\n+typedef struct {\n+\tunion {\n+\t\tuint32_t version;\n+\t\tstruct {\n+\t\t\tuint8_t micro;\n+\t\t\tuint8_t minor;\n+\t\t\tuint8_t major;\n+\t\t\tuint8_t board;\n+\t\t};\n+\t};\n+} opae_bmc_version;\n+\n+#define OPAE_MAX_PORT_NUM   4\n+\n+#define OPAE_PROP_PCI   0x01\n+#define OPAE_PROP_FME   0x02\n+#define OPAE_PROP_PORT  0x04\n+#define OPAE_PROP_BMC   0x08\n+#define OPAE_PROP_ALL   \\\n+\t(OPAE_PROP_PCI | OPAE_PROP_FME | OPAE_PROP_PORT | OPAE_PROP_BMC)\n+\n+typedef struct {\n+\topae_pci_property pci;\n+\topae_fme_property fme;\n+\topae_port_property port[OPAE_MAX_PORT_NUM];\n+\topae_bmc_property bmc;\n+} opae_fpga_property;\n+\n+typedef struct {\n+\tuint64_t guid_h;\n+\tuint64_t guid_l;\n+\tuint32_t metadata_len;\n+} gbs_header;\n+\n+#define OPAE_IMG_TYPE_BBS       0\n+#define OPAE_IMG_TYPE_BMC       1\n+#define OPAE_IMG_TYPE_GBS       2\n+#define OPAE_IMG_TYPE(t)        ((t) & 0xff)\n+\n+#define OPAE_IMG_SUBTYPE_UPDATE             0\n+#define OPAE_IMG_SUBTYPE_CANCELLATION       1\n+#define OPAE_IMG_SUBTYPE_ROOT_KEY_HASH_256  2\n+#define OPAE_IMG_SUBTYPE_ROOT_KEY_HASH_384  3\n+#define OPAE_IMG_SUBTYPE(t)     (((t) >> 8) & 0xff)\n+\n+#define OPAE_IMG_BLK0_SIZE      128\n+#define OPAE_IMG_BLK0_MAGIC     0xb6eafd19\n+#define OPAE_IMG_BLK1_SIZE      896\n+#define OPAE_IMG_HDR_SIZE   (OPAE_IMG_BLK0_SIZE + OPAE_IMG_BLK1_SIZE)\n+#define OPAE_IMG_PL_MIN_SIZE    128\n+\n+typedef struct {\n+\tuint32_t magic;\n+\tuint32_t payload_len;\n+\tuint32_t payload_type;\n+} opae_img_hdr;\n+\n+typedef struct {\n+\tint type;\n+\tint subtype;\n+\tuint32_t total_len;\n+\tuint32_t payload_offset;\n+\tuint32_t payload_len;\n+} opae_img_info;\n+\n+void opae_get_api_version(opae_api_version *version);\n+void opae_check_pcidev_list(void);\n+int opae_set_log_level(int level);\n+int opae_set_log_file(char *path, int clean);\n+int opae_get_proc_type(void);\n+int opae_get_parent(pcidev_id id, pcidev_id parent);\n+int opae_get_child(pcidev_id id, pcidev_id child, int size);\n+int opae_get_pf1(pcidev_id id, pcidev_id peer, int size);\n+int opae_init_eal(int argc, char **argv);\n+int opae_cleanup_eal(void);\n+int opae_enumerate(opae_pci_id *filter, pcidev_id list, int size);\n+int opae_probe_device(pcidev_id id);\n+int opae_remove_device(pcidev_id id);\n+int opae_unbind_driver(pcidev_id id);\n+int opae_bind_driver(pcidev_id id, char *drv_name);\n+int opae_get_property(pcidev_id id, opae_fpga_property *prop, int type);\n+int opae_get_phy_info(pcidev_id id, opae_phy_info *info);\n+int opae_partial_reconfigure(pcidev_id id, int port, const char *gbs);\n+int opae_get_image_info(const char *image, opae_img_info *info);\n+int opae_cancel_flash_update(pcidev_id id, int force);\n+int opae_update_flash(pcidev_id id, const char *image, uint64_t *status);\n+int opae_reboot_device(pcidev_id id, int type, int page);\n+int opae_store_rsu_status(pcidev_id id, uint32_t status, uint32_t progress);\n+int opae_load_rsu_status(pcidev_id id, uint32_t *status, uint32_t *progress);\n+int opae_read_pci_cfg(pcidev_id id, uint32_t address, uint32_t *value);\n+int opae_write_pci_cfg(pcidev_id id, uint32_t address, uint32_t value);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+\n+#endif  /* _OPAE_API_H */\n",
    "prefixes": [
        "v12",
        "4/4"
    ]
}