FAPI TM, WLS_LIB and ODULOW documentation 99/3899/1
authorLuis Farias <luis.farias@intel.com>
Fri, 29 May 2020 02:01:58 +0000 (19:01 -0700)
committerLuis Farias <luis.farias@intel.com>
Fri, 29 May 2020 02:01:58 +0000 (19:01 -0700)
    * Additional ODU-Low components for Bronze Rel
    * 5G Fapi Translator Module
    * Wireless Services library based on DPDK
    * Full ODULOW Documentation set

    Issue-Id: ODULOW-2

Change-Id: I3d0df696286ad50798ccd0765f809fb04629b660
Signed-off-by: Luis Farias <luis.farias@intel.com>
154 files changed:
docs/Architecture-Overview_fh.rst [new file with mode: 0644]
docs/Assumptions_Dependencies.rst [new file with mode: 0644]
docs/Introduction_fh.rst [new file with mode: 0644]
docs/PTP-configuration_fh.rst [new file with mode: 0644]
docs/Sample-Application_fh.rst [new file with mode: 0644]
docs/Setup-Configuration_fh.rst [new file with mode: 0644]
docs/Transport-Layer-and-ORAN-Fronthaul-Protocol-Implementation_fh.rst [new file with mode: 0644]
docs/build_prerequisite.rst [new file with mode: 0644]
docs/conf.yaml
docs/fapi_5g_tm_build.rst [new file with mode: 0644]
docs/fapi_5g_tm_overview.rst [new file with mode: 0644]
docs/fapi_5g_tm_rel-notes.rst [new file with mode: 0644]
docs/images/Architecture-Block-Diagram.jpg [new file with mode: 0644]
docs/images/Bit-Allocations-of-ecpriRtcid-ecpriPcid.jpg [new file with mode: 0644]
docs/images/C-plane-and-U-plane-Packet-Exchange.jpg [new file with mode: 0644]
docs/images/Configuration-C1.jpg [new file with mode: 0644]
docs/images/Configuration-C3.jpg [new file with mode: 0644]
docs/images/Data-Flows.jpg [new file with mode: 0644]
docs/images/Data-Payload.jpg [new file with mode: 0644]
docs/images/Data-Section-Application-Data-Header.jpg [new file with mode: 0644]
docs/images/Functional-Split.jpg [new file with mode: 0644]
docs/images/Illustration-of-xRAN-Sublayers.jpg [new file with mode: 0644]
docs/images/Native-Ethernet-Frame-with-VLAN.jpg [new file with mode: 0644]
docs/images/ORAN-Fronthaul-Process.jpg [new file with mode: 0644]
docs/images/ORAN_OCU_ODU_ORU.jpg [new file with mode: 0644]
docs/images/Radio-Application-Common-Header.jpg [new file with mode: 0644]
docs/images/Radio-Application-Header.jpg [new file with mode: 0644]
docs/images/Sample-Application-Threads.jpg [new file with mode: 0644]
docs/images/Sample-Application.jpg [new file with mode: 0644]
docs/images/Section-Type-0-Structure.jpg [new file with mode: 0644]
docs/images/Section-Type-1-Structure.jpg [new file with mode: 0644]
docs/images/Section-Type-3-Structure.jpg [new file with mode: 0644]
docs/images/Section-Type-5-Structure.jpg [new file with mode: 0644]
docs/images/Section-Type-6-Structure.jpg [new file with mode: 0644]
docs/images/Setup-for-xRAN-Testing-with-PHY-and-Configuration-C3.jpg [new file with mode: 0644]
docs/images/Setup-for-xRAN-Testing.jpg [new file with mode: 0644]
docs/images/eCPRI-Header-Field-Definitions.jpg [new file with mode: 0644]
docs/images/eNB-gNB-Architecture-with-O-DU-and-RU.jpg [new file with mode: 0644]
docs/images/fapi_tm_architecture.jpg [new file with mode: 0644]
docs/images/xRAN-Packet-Components.jpg [new file with mode: 0644]
docs/index.rst
docs/overview.rst
docs/overview1.rst [new file with mode: 0644]
docs/release-notes.rst
docs/run_l1.rst [new file with mode: 0644]
docs/test_cases.rst [new file with mode: 0644]
docs/wls-lib-installation-guide.rst [new file with mode: 0644]
docs/wls-lib-release-notes.rst [new file with mode: 0644]
docs/wls-lib.rst [new file with mode: 0644]
docs/xRAN-Library-Design_fh.rst [new file with mode: 0644]
fapi_5g/bin/oran_5g_fapi.cfg [new file with mode: 0644]
fapi_5g/bin/oran_5g_fapi.sh [new file with mode: 0644]
fapi_5g/build/build.sh [new file with mode: 0644]
fapi_5g/build/makefile [new file with mode: 0644]
fapi_5g/include/fapi_interface.h [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/nr5g_fapi_fapi2mac_api.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/nr5g_fapi_fapi2mac_api.h [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/nr5g_fapi_proc_error_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/nr5g_fapi_proc_error_ind.h [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_fapi2mac_p5_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_config_resp.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_dl_iq_samples_resp.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_fapi_msg_header.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_shutdown_resp.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_start_resp.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_stop_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_ul_iq_samples_resp.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_fapi2mac_p7_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_fapi2mac_p7_pvt_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_crc_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_rach_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_rx_data_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_slot_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_srs_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_uci_ind.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/nr5g_fapi_fapi2phy_api.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/nr5g_fapi_fapi2phy_api.h [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_fapi2phy_p5_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_fapi2phy_p5_pvt_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_config_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_dl_iq_samples_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_shutdown_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_start_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_stop_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_ul_iq_samples_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_fapi2phy_p7_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_fapi2phy_p7_pvt_proc.h [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_dl_tti_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_tx_data_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_ul_dci_req.c [new file with mode: 0644]
fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_ul_tti_req.c [new file with mode: 0644]
fapi_5g/source/framework/nr5g_fapi_framework.c [new file with mode: 0644]
fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.c [new file with mode: 0644]
fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.h [new file with mode: 0644]
fapi_5g/source/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.c [new file with mode: 0644]
fapi_5g/source/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.h [new file with mode: 0644]
fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.c [new file with mode: 0644]
fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.h [new file with mode: 0644]
fapi_5g/source/framework/workers/nr5g_fapi_mac2phy_thread.c [new file with mode: 0644]
fapi_5g/source/framework/workers/nr5g_fapi_mac2phy_thread.h [new file with mode: 0644]
fapi_5g/source/framework/workers/nr5g_fapi_phy2mac_thread.c [new file with mode: 0644]
fapi_5g/source/framework/workers/nr5g_fapi_phy2mac_thread.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_args.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_cmd.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_common_types.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_config_loader.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_dpdk.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_framework.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_internal.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_log.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_memory.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_stats.h [new file with mode: 0644]
fapi_5g/source/include/nr5g_fapi_std.h [new file with mode: 0644]
fapi_5g/source/nr5g_fapi.c [new file with mode: 0644]
fapi_5g/source/utils/nr5g_fapi_args.c [new file with mode: 0644]
fapi_5g/source/utils/nr5g_fapi_cmd.c [new file with mode: 0644]
fapi_5g/source/utils/nr5g_fapi_config_loader.c [new file with mode: 0644]
fapi_5g/source/utils/nr5g_fapi_log.c [new file with mode: 0644]
fapi_5g/source/utils/nr5g_fapi_memory.c [new file with mode: 0644]
fapi_5g/source/utils/nr5g_fapi_stats.c [new file with mode: 0644]
fhi_lib/test/test_xran/Makefile
wls_lib/Makefile [new file with mode: 0644]
wls_lib/build.sh [new file with mode: 0644]
wls_lib/syslib.c [new file with mode: 0644]
wls_lib/syslib.h [new file with mode: 0644]
wls_lib/test/bin/fapi/fapi.sh [new file with mode: 0644]
wls_lib/test/bin/mac/mac.sh [new file with mode: 0644]
wls_lib/test/bin/phy/phy.sh [new file with mode: 0644]
wls_lib/test/build.sh [new file with mode: 0644]
wls_lib/test/build/fapi/dep_file [new file with mode: 0644]
wls_lib/test/build/mac/dep_file [new file with mode: 0644]
wls_lib/test/build/phy/dep_file [new file with mode: 0644]
wls_lib/test/fapi/fapi_main.c [new file with mode: 0644]
wls_lib/test/fapi/makefile [new file with mode: 0644]
wls_lib/test/mac/mac_main.c [new file with mode: 0644]
wls_lib/test/mac/mac_wls.c [new file with mode: 0644]
wls_lib/test/mac/mac_wls.h [new file with mode: 0644]
wls_lib/test/mac/makefile [new file with mode: 0644]
wls_lib/test/phy/makefile [new file with mode: 0644]
wls_lib/test/phy/phy_main.c [new file with mode: 0644]
wls_lib/testapp/Makefile [new file with mode: 0644]
wls_lib/testapp/pool.c [new file with mode: 0644]
wls_lib/testapp/pool.h [new file with mode: 0644]
wls_lib/testapp/testapp.c [new file with mode: 0644]
wls_lib/testapp/wls_test.sh [new file with mode: 0644]
wls_lib/ttypes.h [new file with mode: 0644]
wls_lib/wls.h [new file with mode: 0644]
wls_lib/wls_debug.h [new file with mode: 0644]
wls_lib/wls_drv.c [new file with mode: 0644]
wls_lib/wls_drv.h [new file with mode: 0644]
wls_lib/wls_lib.c [new file with mode: 0644]
wls_lib/wls_lib.h [new file with mode: 0644]
wls_lib/wls_lib_dpdk.c [new file with mode: 0644]
wls_lib/wls_start.sh [new file with mode: 0644]

diff --git a/docs/Architecture-Overview_fh.rst b/docs/Architecture-Overview_fh.rst
new file mode 100644 (file)
index 0000000..1a8bb45
--- /dev/null
@@ -0,0 +1,412 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+Architecture Overview
+=====================
+
+.. contents::
+    :depth: 3
+    :local:
+
+This section provides an overview of the xRAN architecture.
+
+.. _introduction-1:
+
+Introduction
+------------
+
+The front haul interface, according to the ORAN Fronthaul specification,
+performs communication between O-RAN |br|
+Distributed Unit (O-DU) and O-RAN
+Radio Unit (O-RU) and consists of multiple HW and SW components.
+
+The logical representation of HW and SW components is shown in Figure 1.
+
+.. image:: images/Architecture-Block-Diagram.jpg
+  :width: 600
+  :alt: Figure 1. Architecture Block Diagram
+
+Figure 1. Architecture Block Diagram
+
+|br|
+|br|
+
+From the hardware perspective, two networking ports are used to
+communicate to the Front Haul and Back (Mid) Haul network as well as to
+receive PTP synchronization. The system timer is used to provide a
+“sense” of time to the gNB |br|
+application.
+
+From the software perspective, the following components are used:
+
+-  Linux PTP provides synchronization of system timer to GPS time:
+
+-  Ptp4l is used to synchronize oscillator on Network Interface
+   Controller (NIC) to PTP GM.
+
+-  Phc2sys is used to synchronize system timer to oscillator on NIC.
+
+-  DPDK to provide the interface to the Ethernet port.
+
+-  xRAN library is built on top of DPDK to perform U-plane and C-plane
+   functionality according to the ORAN Fronthaul specification.
+
+-  5GNR reference PHY uses the xRAN library to access interface to O-RU.
+   The interface between the library and PHY is defined to communicate
+   TTI event, symbol time, C-plane information as well as IQ sample
+   data.
+
+-  5G NR PHY communicates with the L2 application using the set of
+   MAC/PHY APIs and the shared memory interface defined as WLS.
+
+-  L2, in turn, can use Back (Mid) Haul networking port to connect to
+   the CU unit in the context of 3GPP specification.
+
+In this document, we focus on the details of the design and
+implementation of the xRAN library with respect to providing Front Haul
+functionality for both mmWave and Sub-6 scenarios
+
+The xRAN M-plane is not implemented and is outside of the scope of this
+description. Configuration files are used to |br|
+specify selected M-plane
+level parameters.
+
+ORAN FH Threads
+---------------
+
+ORAN FH Thread Performs:
+
+-  Symbol base “time event” to the rest of the system based on System
+   Clock synchronized to GPS time via PTP
+
+-  Baseline polling mode driver performing TX and RX of Ethernet packets
+
+-  Most of the packet processing such as Transport header, Application
+   header, Data section header and interactions with the rest of the PHY
+   processing pipeline.
+
+-  Polling of other call back function that was registered.
+
+ORAN FH thread created the independent of usage of xRAN as an interface
+to the Radio.
+
+Communication between L1 and xRAN layer is performed using a set of
+callback functions where L1 assigned callback and xRAN layer executes
+those functions at a particular event or time moment. Detailed
+information on callback function |br|
+options and setting as well as design,
+can be found in the sections below.
+
+Sample Application Thread Model
+-------------------------------
+
+Configuration of a sample application for both O-DU and O-RU follows the
+model of 5G NR l1app application in the |br|
+section of xRAN only. No BBU or
+FEC related threads are needed as minimal xRAN functionality is used
+only.
+
+.. image:: images/Sample-Application-Threads.jpg
+  :width: 600
+  :alt: Figure 3. Sample Application Threads
+
+Figure 3. Sample Application Threads
+
+|br|
+|br|
+
+In this scenario, the main thread is used only for initializing and
+closing the application. No execution happens on core 0 during run time.
+
+Functional Split
+----------------
+
+Figure 1 corresponds to the O-RU part of the xRAN split. Implementation
+of the RU side of the xRAN protocol is not |br|
+covered in this document.
+
+.. image:: images/eNB-gNB-Architecture-with-O-DU-and-RU.jpg
+  :width: 600
+  :alt: Figure 4. eNB/gNB Architecture with O-DU and RU
+
+Figure 4. eNB/gNB Architecture with O-DU and RU
+
+|br|
+|br|
+
+More than one RU can be supported with the same implementation of the
+xRAN library and depends on the configuration of gNB in general. In this
+document, we address details of implementation for single O-DU – O-RU
+connection.
+
+The ORAN Fronthaul specification provides two categories of the split of
+Layer 1 functionality between O-DU and O‑RU: Category A and Category B.
+
+.. image:: images/Functional-Split.jpg
+  :width: 600
+  :alt: Figure 5. Functional Split
+
+Figure 5. Functional Split
+
+|br|
+
+Data Flow
+---------
+
+|br|
+
+Table 3 lists the data flows supported for a single RU with a single
+Component Carrier.
+
+|br|
+|br|
+
+Table 3. Supported Data Flow
+
++---------+----+-----------------+-----------------+----------------+
+| Plane   | ID | Name            | Contents        | Periodicity    |
++---------+----+-----------------+-----------------+----------------+
+| U-Plane | 1a | DL Frequency    | DL user data    | symbol         |
+|         |    | Domain IQ Data  | (PDSCH),        |                |
+|         |    |                 | control channel |                |
+|         |    |                 | data (PDCCH,    |                |
+|         |    |                 | etc.)           |                |
++---------+----+-----------------+-----------------+----------------+
+|         | 1b | UL Frequency    | UL user data    | symbol         |
+|         |    | Domain IQ Data  | (PUSCH),        |                |
+|         |    |                 | control channel |                |
+|         |    |                 | data (PUCCH,    |                |
+|         |    |                 | etc.)           |                |
++---------+----+-----------------+-----------------+----------------+
+|         | 1c | PRACH Frequency | UL PRACH data   | slot or symbol |
+|         |    | Domain IQ Data  |                 |                |
++---------+----+-----------------+-----------------+----------------+
+| C-Plane | 2a | Scheduling      | Scheduling      | ~ slot         |
+|         |    | Commands        | information,    |                |
+|         |    |                 | FFT size, CP    |                |
+|         |    | (Beamforming is | length,         |                |
+|         |    | not supported)  | Subcarrier      |                |
+|         |    |                 | spacing, UL     |                |
+|         |    |                 | PRACH           |                |
+|         |    |                 | scheduling      |                |
++---------+----+-----------------+-----------------+----------------+
+| S-Plane | S  | Timing and      | IEEE 1588 PTP   |                |
+|         |    | Synchronization | packets         |                |
++---------+----+-----------------+-----------------+----------------+
+
+|br|
+|br|
+
+.. image:: images/Data-Flows.jpg
+  :width: 600
+  :alt: Figure 6. Data Flows
+
+Figure 6. Data Flows
+
+|br|
+|br|
+
+Information on specific features of C-Plane and U-plane provided in
+Section 6.0. Configuration of S-plane used on test |br|
+setup for simulation
+is provided in Appendix Appendix 2.
+
+Data flow separation is based on VLAN (applicable when layer 2 or layer
+3 is used for the C/U-plane transport.)
+
+#. The mechanism for assigning VLAN ID to U-Plane and C-Plane is assumed
+to be via the M-Plane.
+
+VLAN Tag is configurable via the standard Linux IP tool (refer to
+Appendix Appendix 1).
+
+No Quality of Service (QoS) is supported.
+
+|br|
+|br|
+
+.. image:: images/C-plane-and-U-plane-Packet-Exchange.jpg
+  :width: 600
+  :alt: Figure 7. C-plane and U-plane Packet Exchange
+
+Figure 7. C-plane and U-plane Packet Exchange
+
+|br|
+|br|
+
+Timing, Latency, and Synchronization to GPS
+-------------------------------------------
+
+The ORAN Fronthaul specification defines the latency model of the front
+haul interface and interaction between O-DU and 0-RU. This
+implementation of the xRAN library supports only the category with fixed
+timing advance and Defined Transport method. It determines O-DU transmit
+and receive windows based on pre-defined transport network |br|
+characteristics, and the delay characteristics of the RUs within the
+timing domain.
+
+Table 4 below provides default values used for the implementation of
+O-DU – O-RU simulation with mmWave scenario. Table 5 and Table 6 below
+provide default values used for the implementation of O-DU – O-RU
+simulation with |br|
+numerology 0 and numerology 1 for Sub6 scenarios.
+Configuration can be adjusted via configuration files for sample |br|
+application and reference PHY. However, simulation of the different
+range of the settings was not performed, and |bR|
+additional implementation changes might be required as well as testing with actual O-RU. |br|
+The
+parameters for the front haul network are out of scope as a direct
+connection between O-DU and 0-RU is used for simulation.
+
+|br|
+|br|
+
+Table 4. Front Haul Interface Latency (numerology 3 - mmWave)
+
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Model      | C-Plane           | U-Plane           |                |            |
+|      | Parameters |                   |                   |                |            |
++------+------------+-------------------+-------------------+----------------+------------+
+|      |            | DL                | UL                | DL             | UL         |
++------+------------+-------------------+-------------------+----------------+------------+
+| O-RU | T2amin     | T2a_min_cp_dl=50  | T2a_min_cp_ul=50  | T2a_min_up=25  | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | T2amax     | T2a_max_cp_dl=140 | T2a_max_cp_ul=140 | T2a_max_up=140 | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      |            | Tadv_cp_dl        | NA                | NA             | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta3min     | NA                | NA                | NA             | Ta3_min=20 |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta3max     | NA                | NA                | NA             | Ta3_max=32 |
++------+------------+-------------------+-------------------+----------------+------------+
+| O-DU | T1amin     | T1a_min_cp_dl=70  | T1a_min_cp_ul=60  | T1a_min_up=35  | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | T1amax     | T1a_max_cp_dl=100 | T1a_max_cp_ul=70  | T1a_max_up=50  | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta4min     | NA                | NA                | NA             | Ta4_min=0  |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta4max     | NA                | NA                | NA             | Ta4_max=45 |
++------+------------+-------------------+-------------------+----------------+------------+
+
+|br|
+|br|
+|br|
+
+Table 5. Front Haul Interface Latency (numerology 0 - Sub6)
+
++------+----------+----------+----------+----------+----------+
+|      | Model    | C-Plane  | U-Plane  |          |          |
+|      | Pa       |          |          |          |          |
+|      | rameters |          |          |          |          |
++------+----------+----------+----------+----------+----------+
+|      |          | DL       | UL       | DL       | UL       |
++------+----------+----------+----------+----------+----------+
+| O-RU | T2amin   | T        | T        | T2a_mi   | NA       |
+|      |          | 2a_min_c | 2a_min_c | n_up=200 |          |
+|      |          | p_dl=400 | p_ul=400 |          |          |
++------+----------+----------+----------+----------+----------+
+|      | T2amax   | T2       | T2       | T2a_max  | NA       |
+|      |          | a_max_cp | a_max_cp | _up=1120 |          |
+|      |          | _dl=1120 | _ul=1120 |          |          |
++------+----------+----------+----------+----------+----------+
+|      |          | Ta       | NA       | NA       | NA       |
+|      |          | dv_cp_dl |          |          |          |
++------+----------+----------+----------+----------+----------+
+|      | Ta3min   | NA       | NA       | NA       | Ta3      |
+|      |          |          |          |          | _min=160 |
++------+----------+----------+----------+----------+----------+
+|      | Ta3max   | NA       | NA       | NA       | Ta3      |
+|      |          |          |          |          | _max=256 |
++------+----------+----------+----------+----------+----------+
+| O-DU | T1amin   | T        | T        | T1a_mi   | NA       |
+|      |          | 1a_min_c | 1a_min_c | n_up=280 |          |
+|      |          | p_dl=560 | p_ul=480 |          |          |
++------+----------+----------+----------+----------+----------+
+|      | T1amax   | T        | T        | T1a_ma   | NA       |
+|      |          | 1a_max_c | 1a_max_c | x_up=400 |          |
+|      |          | p_dl=800 | p_ul=560 |          |          |
++------+----------+----------+----------+----------+----------+
+|      | Ta4min   | NA       | NA       | NA       | T        |
+|      |          |          |          |          | a4_min=0 |
++------+----------+----------+----------+----------+----------+
+|      | Ta4max   | NA       | NA       | NA       | Ta4      |
+|      |          |          |          |          | _max=360 |
++------+----------+----------+----------+----------+----------+
+
+|br|
+|br|
+|br|
+
+Table 6. Front Haul Interface Latency (numerology 1 - Sub6)
+
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Model      | C-Plane           | U-Plane           |                |            |
+|      | Parameters |                   |                   |                |            |
++------+------------+-------------------+-------------------+----------------+------------+
+|      |            | DL                | UL                | DL             | UL         |
++------+------------+-------------------+-------------------+----------------+------------+
+| O-RU | T2amin     | T2a_min_cp_dl=285 | T2a_min_cp_ul=285 | T2a_min_up=71  | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | T2amax     | T2a_max_cp_dl=429 | T2a_max_cp_ul=429 | T2a_max_up=428 | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      |            | Tadv_cp_dl        | NA                | NA             | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta3min     | NA                | NA                | NA             | Ta3_min=20 |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta3max     | NA                | NA                | NA             | Ta3_max=32 |
++------+------------+-------------------+-------------------+----------------+------------+
+| O-DU | T1amin     | T1a_min_cp_dl=285 | T1a_min_cp_ul=285 | T1a_min_up=96  | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | T1amax     | T1a_max_cp_dl=429 | T1a_max_cp_ul=300 | T1a_max_up=196 | NA         |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta4min     | NA                | NA                | NA             | Ta4_min=0  |
++------+------------+-------------------+-------------------+----------------+------------+
+|      | Ta4max     | NA                | NA                | NA             | Ta4_max=75 |
++------+------------+-------------------+-------------------+----------------+------------+
+
+|br|
+|br|
+|br|
+
+IEEE 1588 protocol and PTP for Linux\* implementations are used to
+synchronize local time to GPS time. Details of the configuration used
+are provided in Appendix Appendix 2. Local time is used to get Top of
+the Second (ToS) as a 1pps event for SW implementation. Timing event is
+obtained by performing polling of local time using |br|
+clock_gettime(CLOCK_REALTIME,..)
+
+All-time intervals are specified with respect to GPS time which
+corresponds to OTA time.
+
+|br|
+|br|
+|br|
+
+Virtualization and Container-Based Usage
+----------------------------------------
+
+xRAN implementation is deployment agnostic and does not require special
+changes to be used in virtualized or |br|
+container-based deployment options.
+The only requirement is to provide one SRIOV base virtual port for
+C-plane and one port for U-plane traffic per O-DU instance. This can be
+achieved with the default Virtual Infrastructure Manager (VIM) as well
+as using standard container networking.
+
+
+
diff --git a/docs/Assumptions_Dependencies.rst b/docs/Assumptions_Dependencies.rst
new file mode 100644 (file)
index 0000000..2524dc2
--- /dev/null
@@ -0,0 +1,66 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+
+Assumptions and Dependencies
+===============================
+
+.. contents::
+    :depth: 3
+    :local:
+
+This chapter contains the assumptions, requirements and dependencies for the O-DU Low current implementation.
+
+Assumptions
+-----------
+
+An L1 with a proprietary interface and a testmac supporting the FAPI interface are available through the Open Source Community(OSC) github in binary blob form and with the reference
+files that support the tests required for the ORAN Bronze Release. The required header files that are needed to build the 5G FAPI TM and to run validation tests and to |br|
+integrate with the O-DU
+High to check network functionality are available from the same site.
+The L1 App and Testmac |br|
+repository is at https://github.com/intel/FlexRAN/
+
+Requirements
+------------
+* Only Xeon® series Processor with Intel Architecture are supported and the platform should be |br|
+  Intel® Xeon® SkyLake / CascadeLake platforms with at least 2.0 GHz core frequency
+* FPGA/ASIC card for FEC acceleration that's compliance with BBDev framework and interface if you need run high throughput case with HW FEC card assistant.
+* Bios setting steps and options might have difference, however at least you should have the same Bios setting as decribed in the https://github.com/intel/FlexRAN/README.md Bios settings section
+* Runing with FH requires PTP for Linux\* version 2.0 (or later) to be installed to provide IEEE 1588 synchronization.
+
+Dependencies
+------------
+
+* Centos OS 7 (7.5+) (7.7 was used for the L1 and testmac binaries)
+
+* RT Kernel kernel-rt-3.10.0-1062.12.1.rt56.1042
+
+* Data Plane Development Kit (DPDK v18.08) with corresponding DPDK patch according to O-RAN FH setup |br|
+  configuation section.
+
+* FEC SDK lib which was needed when you run FEC in SW mode, download through: https://software.intel.com/en-us/articles/flexran-lte-and-5g-nr-fec-software-development-kit-modules
+
+* Intel® C++ Compiler v19.0.3 is used for test application and system integration. Free Intel® C++ Compiler can be gotten through below link with community license, however the version you could get is always latest ICC version, the verification for that version might not be performed yet, please feedback through O-DU Low WIKI page if you meet issue.
+  https://software.intel.com/en-us/system-studio/choose-download 
+
+* Optionally Octave v3.8.2 can be used to generate reference IQ samples (octave-3.8.2-20.el7.x86_64) for O-RAN FH Sample App, which is not needed if running sample APP for O-RAN FHI is not performed.
+
+
+
+
diff --git a/docs/Introduction_fh.rst b/docs/Introduction_fh.rst
new file mode 100644 (file)
index 0000000..06861aa
--- /dev/null
@@ -0,0 +1,33 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+
+O-RAN FH Lib Introduction
+==========================
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+   Architecture-Overview_fh.rst
+   Transport-Layer-and-ORAN-Fronthaul-Protocol-Implementation_fh.rst
+   xRAN-Library-Design_fh.rst
+   Sample-Application_fh.rst
+   Setup-Configuration_fh.rst
+   PTP-configuration_fh.rst
+   
+
+
+
+
diff --git a/docs/PTP-configuration_fh.rst b/docs/PTP-configuration_fh.rst
new file mode 100644 (file)
index 0000000..63135b8
--- /dev/null
@@ -0,0 +1,731 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+   
+PTP configuration
+=================
+
+A.5 PTP Synchronization
+-----------------------
+Precision Time Protocol (PTP) provides an efficient way to synchronize
+time on the network nodes. This protocol uses Master-Slave architecture.
+Grandmaster Clock (Master) is a reference clock for the other nodes,
+which adapt their clocks to the master.
+
+Using Physical Hardware Clock (PHC) from the Grandmaster Clock, NIC port
+precision timestamp packets can be served for other network nodes. Slave
+nodes adjust their PHC to the master following the IEEE 1588
+specification.
+
+There are existing implementations of PTP protocol that are widely used
+in the industry. One of them is PTP for Linux, which is a set of tools
+providing necessary PTP functionality. There is no need to re-implement
+the 1588 protocol because PTP for Linux is precise and efficient enough
+to be used out of the box.
+
+To meet xRAN requirements, two tools from PTP for Linux package are
+required: ptp4l and phc2sys.
+
+PTP for Linux\* Requirements
+----------------------------
+
+PTP for Linux\* introduces some software and hardware requirements. The
+machine on which the tools will be run needs to use at least a 3.10
+Kernel version (built-in PTP support). There are several Kernel options
+that need to be enabled in Kernel configuration:
+
+-  CONFIG_PPS
+
+-  CONFIG_NETWORK_PHY_TIMESTAMPING
+
+-  PTP_1588_CLOCK
+
+Be sure that the Kernel is compiled with these options.
+
+For the best precision, PTP uses hardware timestamping. NIC has its own
+clock, called Physical Hardware Clock (PHC) to read current time just a
+moment before the packet is sent to minimalize the delays added by the
+Kernel processing the packet. Not every NIC supports that feature. To
+confirm that currently attached NIC support Hardware Timestamps, use
+ethtool with the command:
+
+ethtool -T eth0
+
+where eth0 is the potential PHC port. The output from the command should
+say that there is Hardware Timestamps support.
+
+To set up PTP for Linux*:
+
+1.Download source code::
+
+    git clone http://git.code.sf.net/p/linuxptp/code linuxptp
+    
+    git checkout v2.0
+    
+2.Apply patch (this is required to work around issue with some of the
+GM PTP packet size.)::
+
+    diff --git a/msg.c b/msg.c
+    
+    old mode 100644
+    
+    new mode 100755
+    
+    index d1619d4..40d1538
+    
+    --- a/msg.c
+    
+    +++ b/msg.c
+    
+    @@ -399,9 +399,11 @@ int msg_post_recv(struct ptp_message \*m, int cnt)
+    
+    port_id_post_recv(&m->pdelay_resp.requestingPortIdentity);
+    
+    break;
+    
+    case FOLLOW_UP:
+    
+    + cnt -= 4;
+    
+    timestamp_post_recv(m, &m->follow_up.preciseOriginTimestamp);
+    
+    break;
+    
+    case DELAY_RESP:
+    
+    + cnt -= 4;
+    
+    timestamp_post_recv(m, &m->delay_resp.receiveTimestamp);
+    
+    port_id_post_recv(&m->delay_resp.requestingPortIdentity);
+    
+    break;
+
+3.Build and install ptp41::
+
+   # make && make install
+
+4.Modify configs/default.cfg to control frequency of Sync interval to
+0.0625s::
+
+    logSyncInterval -4
+
+ptp4l 
+----------
+
+This tool handles all PTP traffic on the provided NIC port and updated
+PHC. It also determines the Grandmaster Clock and tracks |br|
+synchronization
+status. This tool can be run as a daemon or as a regular Linux\*
+application. When the synchronization is reached, it gives output on the
+screen for precision tracking. The configuration file of ptp4l contains
+many options that can be set to get the best synchronization precision.
+Although, even with default.cfg the synchronization quality is good.
+
+To start the synchronization process run::
+
+    cd linuxptp
+    
+    ./ptp4l -f ./configs/default.cfg -2 -i <if_name> -m
+
+The output below shows what the output on non-master node should look
+like when synchronization is started. This means that PHC on this
+machine is synchronized to the master PHC::
+
+    ptp4l[1434165.358]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
+    
+    ptp4l[1434165.358]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
+    
+    ptp4l[1434166.384]: port 1: new foreign master fcaf6a.fffe.029708-1
+    
+    ptp4l[1434170.352]: selected best master clock fcaf6a.fffe.029708
+    
+    ptp4l[1434170.352]: updating UTC offset to 37
+    
+    ptp4l[1434170.352]: port 1: LISTENING to UNCALIBRATED on RS_SLAVE
+    
+    ptp4l[1434171.763]: master offset -5873 s0 freq -18397 path delay 2778
+    
+    ptp4l[1434172.763]: master offset -6088 s2 freq -18612 path delay 2778
+    
+    ptp4l[1434172.763]: port 1: UNCALIBRATED to SLAVE on
+    MASTER_CLOCK_SELECTED
+    
+    ptp4l[1434173.763]: master offset -5886 s2 freq -24498 path delay 2732
+    
+    ptp4l[1434174.763]: master offset 221 s2 freq -20157 path delay 2728
+    
+    ptp4l[1434175.763]: master offset 1911 s2 freq -18401 path delay 2724
+    
+    ptp4l[1434176.763]: master offset 1774 s2 freq -17964 path delay 2728
+    
+    ptp4l[1434177.763]: master offset 1198 s2 freq -18008 path delay 2728
+    
+    ptp4l[1434178.763]: master offset 746 s2 freq -18101 path delay 2755
+    
+    ptp4l[1434179.763]: master offset 218 s2 freq -18405 path delay 2792
+    
+    ptp4l[1434180.763]: master offset 103 s2 freq -18454 path delay 2792
+    
+    ptp4l[1434181.763]: master offset -13 s2 freq -18540 path delay 2813
+    
+    ptp4l[1434182.763]: master offset 9 s2 freq -18521 path delay 2813
+    
+    ptp4l[1434183.763]: master offset 11 s2 freq -18517 path delay 2813
+    
+phc2sys
+-----------
+
+The PHC clock is independent from the system clock. Synchronizing only
+PHC does not make the system clock exactly the same as the master. The
+xRAN library requires use of the system clock to determine a common
+point in time on two |br|
+machines (O-DU and RU) to start transmission at the
+same moment and keep time frames defined by ORAN Fronthaul |br|
+specification.
+
+This application keeps the system clock updated to PHC. It makes it
+possible to use POSIX timers as a time reference in xRAN application.
+
+Run phc2sys with the command::
+
+    cd linuxptp
+    
+    ./phc2sys -s enp25s0f0 -w -m -R 8
+
+Command output will look like::
+
+    ptp4l[1434165.342]: selected /dev/ptp4 as PTP
+    
+    phc2sys[1434344.651]: CLOCK_REALTIME phc offset 450 s2 freq -39119 delay
+    1354
+    
+    phc2sys[1434344.776]: CLOCK_REALTIME phc offset 499 s2 freq -38620 delay
+    1344
+    
+    phc2sys[1434344.902]: CLOCK_REALTIME phc offset 485 s2 freq -38484 delay
+    1347
+    
+    phc2sys[1434345.027]: CLOCK_REALTIME phc offset 476 s2 freq -38348 delay
+    1346
+    
+    phc2sys[1434345.153]: CLOCK_REALTIME phc offset 392 s2 freq -38289 delay
+    1340
+    
+    phc2sys[1434345.278]: CLOCK_REALTIME phc offset 319 s2 freq -38244 delay
+    1340
+    
+    phc2sys[1434345.404]: CLOCK_REALTIME phc offset 278 s2 freq -38190 delay
+    1349
+    
+    phc2sys[1434345.529]: CLOCK_REALTIME phc offset 221 s2 freq -38163 delay
+    1343
+    
+    phc2sys[1434345.654]: CLOCK_REALTIME phc offset 97 s2 freq -38221 delay
+    1342
+    
+    phc2sys[1434345.780]: CLOCK_REALTIME phc offset 67 s2 freq -38222 delay
+    1344
+    
+    phc2sys[1434345.905]: CLOCK_REALTIME phc offset 68 s2 freq -38201 delay
+    1341
+    
+    phc2sys[1434346.031]: CLOCK_REALTIME phc offset 104 s2 freq -38144 delay
+    1340
+    
+    phc2sys[1434346.156]: CLOCK_REALTIME phc offset 58 s2 freq -38159 delay
+    1340
+    
+    phc2sys[1434346.281]: CLOCK_REALTIME phc offset 12 s2 freq -38188 delay
+    1343
+    
+    phc2sys[1434346.407]: CLOCK_REALTIME phc offset -36 s2 freq -38232 delay
+    1342
+    
+    phc2sys[1434346.532]: CLOCK_REALTIME phc offset -103 s2 freq -38310
+    delay 1348
+
+Configuration C3
+------------------
+
+Configuration C3 27 can be simulated for O-DU using a separate server
+acting as Fronthaul Network and O-RU at the same time. O-RU server can
+be configured to relay PTP and act as PTP master for O-DU. Settings
+below can be used to |br|
+instantiate this scenario. The difference is that
+on the O-DU side, the Fronthaul port can be used as the source of PTP as
+well as for U-plane and C-plane traffic.
+
+1.Follow the steps in Section A.6.1 to install PTP on the O-RU server.
+
+2.Copy configs/default.cfg to configs/default_slave.cfg and modify the
+copied file as below::
+
+    diff --git a/configs/default.cfg b/configs/default.cfg
+    
+    old mode 100644
+    
+    new mode 100755
+    
+    index e23dfd7..f1ecaf1
+    
+    --- a/configs/default.cfg
+    
+    +++ b/configs/default.cfg
+    
+    @@ -3,26 +3,26 @@
+    
+    # Default Data Set
+    
+    #
+    
+    twoStepFlag 1
+    
+    -slaveOnly 0
+    
+    +slaveOnly 1
+    
+    priority1 128
+    
+    -priority2 128
+    
+    +priority2 255
+    
+    domainNumber 0
+    
+    #utc_offset 37
+    
+    -clockClass 248
+    
+    +clockClass 255
+    
+    clockAccuracy 0xFE
+    
+    offsetScaledLogVariance 0xFFFF
+    
+    free_running 0
+    
+    freq_est_interval 1
+    
+    dscp_event 0
+    
+    dscp_general 0
+    
+    -dataset_comparison ieee1588
+    
+    +dataset_comparison G.8275.x
+    
+    G.8275.defaultDS.localPriority 128
+    
+    maxStepsRemoved 255
+    
+    #
+    
+    # Port Data Set
+    
+    #
+    
+    logAnnounceInterval 1
+    
+    -logSyncInterval 0
+    
+    +logSyncInterval -4
+    
+    operLogSyncInterval 0
+    
+    logMinDelayReqInterval 0
+    
+    logMinPdelayReqInterval 0
+    
+    @@ -37,7 +37,7 @@ G.8275.portDS.localPriority 128
+    
+    asCapable auto
+    
+    BMCA ptp
+    
+    inhibit_announce 0
+    
+    -inhibit_pdelay_req 0
+    
+    +#inhibit_pdelay_req 0
+    
+    ignore_source_id 0
+    
+    #
+    
+    # Run time options
+
+1.Start slave port toward PTP GM:: 
+
+    ./ptp4l -f ./configs/default_slave.cfg -2 -i enp25s0f0 –m
+
+Example of output::
+
+    ./ptp4l -f ./configs/default_slave.cfg -2 -i enp25s0f0 -m
+    
+    ptp4l[3904470.256]: selected /dev/ptp6 as PTP clock
+    
+    ptp4l[3904470.274]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
+    
+    ptp4l[3904470.275]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
+    
+    ptp4l[3904471.085]: port 1: new foreign master fcaf6a.fffe.029708-1
+    
+    ptp4l[3904475.053]: selected best master clock fcaf6a.fffe.029708
+    
+    ptp4l[3904475.053]: updating UTC offset to 37
+    
+    ptp4l[3904475.053]: port 1: LISTENING to UNCALIBRATED on RS_SLAVE
+    
+    ptp4l[3904477.029]: master offset 196 s0 freq -18570 path delay 1109
+    
+    ptp4l[3904478.029]: master offset 212 s2 freq -18554 path delay 1109
+    
+    ptp4l[3904478.029]: port 1: UNCALIBRATED to SLAVE on
+    MASTER_CLOCK_SELECTED
+    
+    ptp4l[3904479.029]: master offset 86 s2 freq -18468 path delay 1109
+    
+    ptp4l[3904480.029]: master offset 23 s2 freq -18505 path delay 1124
+    
+    ptp4l[3904481.029]: master offset 3 s2 freq -18518 path delay 1132
+    
+    ptp4l[3904482.029]: master offset -169 s2 freq -18689 path delay 1141
+
+2.Synchronize local timer clock on O-RU for sample application::
+
+   ./phc2sys -s enp25s0f0 -w -m -R 8
+
+Example of output::
+
+   ./phc2sys -s enp25s0f0 -w -m -R 8
+   
+   phc2sys[3904510.892]: CLOCK_REALTIME phc offset 343 s0 freq -38967 delay
+   1530
+   
+   phc2sys[3904511.017]: CLOCK_REALTIME phc offset 368 s2 freq -38767 delay
+   1537
+   
+   phc2sys[3904511.142]: CLOCK_REALTIME phc offset 339 s2 freq -38428 delay
+   1534
+   
+   phc2sys[3904511.267]: CLOCK_REALTIME phc offset 298 s2 freq -38368 delay
+   1532
+   
+   phc2sys[3904511.392]: CLOCK_REALTIME phc offset 239 s2 freq -38337 delay
+   1534
+   
+   phc2sys[3904511.518]: CLOCK_REALTIME phc offset 145 s2 freq -38360 delay
+   1530
+   
+   phc2sys[3904511.643]: CLOCK_REALTIME phc offset 106 s2 freq -38355 delay
+   1527
+   
+   phc2sys[3904511.768]: CLOCK_REALTIME phc offset -30 s2 freq -38459 delay
+   1534
+   
+   phc2sys[3904511.893]: CLOCK_REALTIME phc offset -92 s2 freq -38530 delay
+   1530
+   
+   phc2sys[3904512.018]: CLOCK_REALTIME phc offset -173 s2 freq -38639
+   delay 1528
+   
+   phc2sys[3904512.143]: CLOCK_REALTIME phc offset -246 s2 freq -38764
+   delay 1530
+   
+   phc2sys[3904512.268]: CLOCK_REALTIME phc offset -300 s2 freq -38892
+   delay 1532
+
+3. Modify configs/default.cfg as shown below to run PTP master on
+Fronthaul of O-RU::
+
+    diff --git a/configs/default.cfg b/configs/default.cfg
+    
+    old mode 100644
+    
+    new mode 100755
+    
+    index e23dfd7..c9e9d4c
+    
+    --- a/configs/default.cfg
+    
+    +++ b/configs/default.cfg
+    
+    @@ -15,14 +15,14 @@ free_running 0
+    
+    freq_est_interval 1
+    
+    dscp_event 0
+    
+    dscp_general 0
+    
+    -dataset_comparison ieee1588
+    
+    +dataset_comparison G.8275.x
+    
+    G.8275.defaultDS.localPriority 128
+    
+    maxStepsRemoved 255
+    
+    #
+    
+    # Port Data Set
+    
+    #
+    
+    logAnnounceInterval 1
+    
+    -logSyncInterval 0
+    
+    +logSyncInterval -4
+    
+    operLogSyncInterval 0
+    
+    logMinDelayReqInterval 0
+    
+    logMinPdelayReqInterval 0
+    
+    @@ -37,7 +37,7 @@ G.8275.portDS.localPriority 128
+    
+    asCapable auto
+    
+    BMCA ptp
+    
+    inhibit_announce 0
+    
+    -inhibit_pdelay_req 0
+    
+    +#inhibit_pdelay_req 0
+    
+    ignore_source_id 0
+    
+    #
+    
+    # Run time options
+
+4.Start PTP master toward O-DU::
+
+   ./ptp4l -f ./configs/default.cfg -2 -i enp175s0f1 –m
+
+Example of output::
+
+   ./ptp4l -f ./configs/default.cfg -2 -i enp175s0f1 -m
+   
+   ptp4l[3903857.249]: selected /dev/ptp3 as PTP clock
+   
+   ptp4l[3903857.266]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
+   
+   ptp4l[3903857.267]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
+   
+   ptp4l[3903863.734]: port 1: LISTENING to MASTER on
+   ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
+   
+   ptp4l[3903863.734]: selected local clock 3cfdfe.fffe.bd005d as best
+   master
+   
+   ptp4l[3903863.734]: assuming the grand master role
+
+5.Synchronize local NIC PTP master clock to local NIC PTP slave clock::
+
+   ./phc2sys -c enp175s0f1 -s enp25s0f0 -w -m -R 8
+
+Example of output::
+
+   ./phc2sys -c enp175s0f1 -s enp25s0f0 -w -m -R 8
+
+   phc2sys[3904600.332]: enp175s0f1 phc offset 2042 s0 freq -2445 delay
+   4525
+   
+   phc2sys[3904600.458]: enp175s0f1 phc offset 2070 s2 freq -2223 delay
+   4506
+   
+   phc2sys[3904600.584]: enp175s0f1 phc offset 2125 s2 freq -98 delay 4505
+   
+   phc2sys[3904600.710]: enp175s0f1 phc offset 1847 s2 freq +262 delay 4518
+   
+   phc2sys[3904600.836]: enp175s0f1 phc offset 1500 s2 freq +469 delay 4515
+   
+   phc2sys[3904600.961]: enp175s0f1 phc offset 1146 s2 freq +565 delay 4547
+   
+   phc2sys[3904601.086]: enp175s0f1 phc offset 877 s2 freq +640 delay 4542
+   
+   phc2sys[3904601.212]: enp175s0f1 phc offset 517 s2 freq +543 delay 4517
+   
+   phc2sys[3904601.337]: enp175s0f1 phc offset 189 s2 freq +370 delay 4510
+   
+   phc2sys[3904601.462]: enp175s0f1 phc offset -125 s2 freq +113 delay 4554
+   
+   phc2sys[3904601.587]: enp175s0f1 phc offset -412 s2 freq -212 delay 4513
+   
+   phc2sys[3904601.712]: enp175s0f1 phc offset -693 s2 freq -617 delay 4519
+   
+   phc2sys[3904601.837]: enp175s0f1 phc offset -878 s2 freq -1009 delay
+   4515
+   
+   phc2sys[3904601.962]: enp175s0f1 phc offset -965 s2 freq -1360 delay
+   4518
+   
+   phc2sys[3904602.088]: enp175s0f1 phc offset -1048 s2 freq -1732 delay
+   4510
+   
+   phc2sys[3904602.213]: enp175s0f1 phc offset -1087 s2 freq -2086 delay
+   4531
+   
+   phc2sys[3904602.338]: enp175s0f1 phc offset -1014 s2 freq -2339 delay
+   4528
+   
+   phc2sys[3904602.463]: enp175s0f1 phc offset -1009 s2 freq -2638 delay
+   4531
+
+6. On O-DU Install PTP for Linux tools from source code the same way as
+on O-RU above but no need to apply the patch for msg.c
+
+7. Start slave port toward PTP master from O-RU using the same
+default_slave.cfg as on O-RU (see above)::
+
+    ./ptp4l -f ./configs/default_slave.cfg -2 -i enp181s0f0 –m
+
+Example of output::
+
+    ./ptp4l -f ./configs/default_slave.cfg -2 -i enp181s0f0 -m
+    
+    ptp4l[809092.918]: selected /dev/ptp6 as PTP clock
+    
+    ptp4l[809092.934]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
+    
+    ptp4l[809092.934]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
+    
+    ptp4l[809092.949]: port 1: new foreign master 3cfdfe.fffe.bd005d-1
+    
+    ptp4l[809096.949]: selected best master clock 3cfdfe.fffe.bd005d
+    
+    ptp4l[809096.950]: port 1: LISTENING to UNCALIBRATED on RS_SLAVE
+    
+    ptp4l[809098.363]: port 1: UNCALIBRATED to SLAVE on
+    MASTER_CLOCK_SELECTED
+    
+    ptp4l[809099.051]: rms 38643 max 77557 freq +719 +/- 1326 delay 1905 +/-
+    0
+    
+    ptp4l[809100.051]: rms 1134 max 1935 freq -103 +/- 680 delay 1891 +/- 4
+    
+    ptp4l[809101.051]: rms 453 max 855 freq +341 +/- 642 delay 1888 +/- 0
+    
+    ptp4l[809102.052]: rms 491 max 772 freq +1120 +/- 752 delay 1702 +/- 0
+    
+    ptp4l[809103.052]: rms 423 max 654 freq +1352 +/- 653 delay 1888 +/- 0
+    
+    ptp4l[809104.052]: rms 412 max 579 freq +1001 +/- 672 delay 1702 +/- 0
+    
+    ptp4l[809105.053]: rms 441 max 672 freq +807 +/- 709 delay 1826 +/- 88
+    
+    ptp4l[809106.053]: rms 422 max 607 freq +1353 +/- 636 delay 1702 +/- 0
+    
+    ptp4l[809107.054]: rms 401 max 466 freq +946 +/- 646 delay 1702 +/- 0
+    
+    ptp4l[809108.055]: rms 401 max 502 freq +912 +/- 659
+
+8. Synchronize local clock on O-DU for sample application or l1
+application::
+
+    ./phc2sys -s enp181s0f0 -w -m -R 8
+
+Example of output::
+
+   ./phc2sys -s enp181s0f0 -w -m -R 8
+
+    phc2sys[809127.123]: CLOCK_REALTIME phc offset 675 s0 freq -37379 delay
+    1646
+    
+    phc2sys[809127.249]: CLOCK_REALTIME phc offset 696 s2 freq -37212 delay
+    1654
+    
+    phc2sys[809127.374]: CLOCK_REALTIME phc offset 630 s2 freq -36582 delay
+    1648
+    
+    phc2sys[809127.500]: CLOCK_REALTIME phc offset 461 s2 freq -36562 delay
+    1642
+    
+    phc2sys[809127.625]: CLOCK_REALTIME phc offset 374 s2 freq -36510 delay
+    1643
+    
+    phc2sys[809127.751]: CLOCK_REALTIME phc offset 122 s2 freq -36650 delay
+    1649
+    
+    phc2sys[809127.876]: CLOCK_REALTIME phc offset 34 s2 freq -36702 delay
+    1650
+    
+    phc2sys[809128.002]: CLOCK_REALTIME phc offset -112 s2 freq -36837 delay
+    1645
+    
+    phc2sys[809128.127]: CLOCK_REALTIME phc offset -160 s2 freq -36919 delay
+    1643
+    
+    phc2sys[809128.252]: CLOCK_REALTIME phc offset -270 s2 freq -37077 delay
+    1657
+    
+    phc2sys[809128.378]: CLOCK_REALTIME phc offset -285 s2 freq -37173 delay
+    1644
+    
+    phc2sys[809128.503]: CLOCK_REALTIME phc offset -349 s2 freq -37322 delay
+    1644
+    
+    phc2sys[809128.629]: CLOCK_REALTIME phc offset -402 s2 freq -37480 delay
+    1641
+    
+    phc2sys[809128.754]: CLOCK_REALTIME phc offset -377 s2 freq -37576 delay
+    1648
+    
+    phc2sys[809128.879]: CLOCK_REALTIME phc offset -467 s2 freq -37779 delay
+    1650
+    
+    phc2sys[809129.005]: CLOCK_REALTIME phc offset -408 s2 freq -37860 delay
+    1648
+    
+    phc2sys[809129.130]: CLOCK_REALTIME phc offset -480 s2 freq -38054 delay
+    1655
+    
+    phc2sys[809129.256]: CLOCK_REALTIME phc offset -350 s2 freq -38068 delay
+    1650
+
+Support in xRAN Library
+----------------------------
+
+The xRAN library provides an API to check whether PTP for Linux is
+running correctly. There is a function called xran_is_synchronized(). It
+checks if ptp4l and phc2sys are running in the system by making PMC tool
+requests for current port state and comparing it with the expected
+value. This verification should be done before initialization.
+
+*notes. “SLAVE” is the only expected value in this release; only a
+non-master scenario is supported currently.*
+
+.. |image0| image:: media/image3.png
+   :width: 2.52364in
+   :height: 3.77174in
+.. |image1| image:: media/image8.png
+   :width: 6.258in
+   :height: 1.40538in
+.. |image2| image:: media/image10.emf
+   :width: 6.18493in
+   :height: 0.53448in
+.. |image3| image:: media/image15.png
+   :width: 6.27856in
+   :height: 2.672in
+.. |image4| image:: media/image21.JPG
+   :width: 6.17708in
+   :height: 6.09375in
diff --git a/docs/Sample-Application_fh.rst b/docs/Sample-Application_fh.rst
new file mode 100644 (file)
index 0000000..3df722e
--- /dev/null
@@ -0,0 +1,145 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+Sample Application
+==================
+
+.. contents::
+    :depth: 3
+    :local:
+
+Figure 25 illustrates a sample xRAN application.
+
+.. image:: images/Sample-Application.jpg
+  :width: 600
+  :alt: Figure 25. Sample Application
+
+Figure 25. Sample Application
+
+The sample application was created to execute test scenarios with
+features of the xRAN library and test external API as well as timing.
+The sample application is named sample-app, and depending on
+configuration file settings can act as O-DU or simplified simulation of
+O-RU. The first O-DU should be run on the machine that acts as O-DU and
+the second as O-RU. Both machines are connected via ETH. The sample
+application on both sides executes using a constant configuration |br|
+according to settings in corresponding config files
+(./app/usecase/mu0_10mhz/config_file_o_du.dat and |br|
+./app/usecase/mu0_10mhz/config_file_o_ru.dat) and uses binary files
+(ant.bin) with IQ samples as input. Multiple-use |br| 
+cases for different
+numerologies and different BW are available as examples. Configuration
+files provide descriptions of each |br|
+parameter and in general, those are
+related to M-plane level settings as per the ORAN Fronthaul
+specification.
+
+From the start of the process, the application (O-DU) sends DL packets
+for the U-plane and C-plane and receives U-plane UL packets.
+Synchronization of O-DU and O-RU sides is achieved via IEEE 1588.
+
+U-plane packets for UL and DL direction are constructed the same way
+except for the direction field.
+
+The several default configurations used with the sample app for v20.02
+release are:
+
+1 Cell mmWave 100MHz TDD DDDS:
+
+
+-  Numerology 3 (mmWave)
+
+-  TTI period 125 µs
+
+-  100 Mhz Bandwidth: 792 subcarriers (all 66 RB utilized at all times)
+
+-  4x4 MIMO
+
+-  No beamforming
+
+-  1 Component carrier
+
+-  Jumbo Frame for Ethernet (up to 9728 bytes)
+
+-  Front haul throughput ~11.5 Gbps.
+
+12 Cells Sub6 10MHz FDD:
+
+
+-  Numerology 0 (Sub-6)
+
+-  TTI period 1000 µs
+
+-  10Mhz Bandwidth: 624 subcarriers (all 52 RB utilized at all times)
+
+-  4x4 MIMO
+
+-  No beamforming
+
+-  12 Component carrier
+
+-  Jumbo Frame for Ethernet (up to 9728 bytes)
+
+-  Front haul throughput ~13.7Gbps.
+
+1 Cell Sub6 100MHz TDD:
+
+
+-  Numerology 1 (Sub-6)
+
+-  TTI period 500us
+
+-  100Mhz Bandwidth: 3276 subcarriers (all 273RB utilized at all times)
+
+-  4x4 MIMO
+
+-  No beamforming
+
+-  1 Component carrier
+
+-  Jumbo Frame for Ethernet (up to 9728 bytes)
+
+-  Front haul throughput ~11.7 Gbps.
+
+.. _cell-sub6-100mhz-tdd-1:
+
+1 Cell Sub6 100MHz TDD:
+
+
+-  Numerology 1 (Sub-6)
+
+-  TTI period 500 µs
+
+-  100 Mhz Bandwidth: 3276 subcarriers (all 273RB utilized at all
+   times). 8 UEs per TTI per layer
+
+-  8DL /4UL MIMO Layers
+
+-  Digital beamforming with 32T32R
+
+-  1 Component carrier
+
+-  Jumbo Frame for Ethernet (up to 9728 bytes)
+
+-  Front haul throughput ~23.5 Gbps.
+
+Other configurations can be constructed by modifying config files
+(please see app/usecase/)
+
+
+
diff --git a/docs/Setup-Configuration_fh.rst b/docs/Setup-Configuration_fh.rst
new file mode 100644 (file)
index 0000000..5108267
--- /dev/null
@@ -0,0 +1,561 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+Setup Configuration
+===================
+
+A.1 Setup Configuration
+-----------------------
+The configuration shown in Figure 26 shows how to set up a test
+environment to execute xRAN scenarios where O-DU and 0-RU are simulated
+using the sample application. This setup allows development and
+prototyping as well as testing of xRAN specific functionality. The O-DU
+side can be instantiated with a full 5G NR L1 reference as well. The
+configuration differences of the 5G NR l1app configuration are provided
+below. Steps for running the sample application on the O-DU side and
+0-RU side are the same, except configuration file options may be
+different.
+
+.. image:: images/Setup-for-xRAN-Testing.jpg
+  :width: 400
+  :alt: Figure 26. Setup for xRAN Testing
+
+Figure 26. Setup for xRAN Testing
+
+.. image:: images/Setup-for-xRAN-Testing-with-PHY-and-Configuration-C3.jpg
+  :width: 400
+  :alt: Figure 27. Setup for xRAN Testing with PHY and Configuration C3
+
+Figure 27. Setup for xRAN Testing with PHY and Configuration C3
+
+A.2 Prerequisites
+-----------------
+Each server in Figure 26 requires the following:
+
+-  Wolfpass server according to recommended BOM for FlexRAN such as
+   Intel® Xeon® Skylake Gold 6148 FC-LGA3647 2.4 GHz 27.5 MB 150W 20
+   cores (two sockets)
+
+-  BIOS settings:
+
+-  Intel(R) Virtualization Technology Enabled
+
+-  Intel(R) VT for Directed I/O - Enabled
+
+-  ACS Control - Enabled
+
+-  Coherency Support - Disabled
+
+-  Front Haul networking cards:
+
+-  Intel® Ethernet Converged Network Adapter XL710-QDA2
+
+-  Intel® Ethernet Converged Network Adapter XXV710-DA2
+
+-  Intel® FPGA Programmable Acceleration Card (Intel® FPGA PAC) N3000
+
+**The Front Haul NIC requires support for PTP HW timestamping.**
+
+The recommended configuration for NICs is::
+
+
+    ethtool -i enp216s0f0
+    
+    driver: i40e
+    
+    version: 2.9.21
+    
+    firmware-version: 6.80 0x80003d05 1.2007.0
+    
+    expansion-rom-version:
+    
+    bus-info: 0000:d8:00.0
+    
+    supports-statistics: yes
+    
+    supports-test: yes
+    
+    supports-eeprom-access: yes
+    
+    supports-register-dump: yes
+    
+    supports-priv-flags: yes
+    
+   [root@5gnr-sc12-xran testmac]# ethtool -T enp216s0f0::
+   
+   
+   Time stamping parameters for enp216s0f0:
+   
+   Capabilities:
+   
+   hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE)
+   
+   software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE)
+   
+   hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE)
+   
+   software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
+   
+   software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
+   
+   hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE)
+   
+   PTP Hardware Clock: 2
+   
+   Hardware Transmit Timestamp Modes:
+   
+   off (HWTSTAMP_TX_OFF)
+   
+   on (HWTSTAMP_TX_ON)
+   
+   Hardware Receive Filter Modes:
+   
+   none (HWTSTAMP_FILTER_NONE)
+   
+   ptpv1-l4-sync (HWTSTAMP_FILTER_PTP_V1_L4_SYNC)
+   
+   ptpv1-l4-delay-req (HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ)
+   
+   ptpv2-l4-event (HWTSTAMP_FILTER_PTP_V2_L4_EVENT)
+   
+   ptpv2-l4-sync (HWTSTAMP_FILTER_PTP_V2_L4_SYNC)
+   
+   ptpv2-l4-delay-req (HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)
+   
+   ptpv2-l2-event (HWTSTAMP_FILTER_PTP_V2_L2_EVENT)
+   
+   ptpv2-l2-sync (HWTSTAMP_FILTER_PTP_V2_L2_SYNC)
+   
+   ptpv2-l2-delay-req (HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ)
+   
+   ptpv2-event (HWTSTAMP_FILTER_PTP_V2_EVENT)
+   
+   ptpv2-sync (HWTSTAMP_FILTER_PTP_V2_SYNC)
+   
+   ptpv2-delay-req (HWTSTAMP_FILTER_PTP_V2_DELAY_REQ)
+
+PTP Grand Master is required to be available in the network to provide
+synchronization of both O-DU and RU to GPS time.
+
+The software package includes Linux\* CentOS\* operating system and RT
+patch according to *Cloud-Native*-platform *Setup* document (refer to
+Table 2). Only real-time HOST is required.
+
+1.Installing Intel® C++ Compiler v19.0.3 is preferred. or you could get
+Intel® C++ Compiler through below link with community license,
+however the version you could get is always latest version, the
+verification for that version might not be performed yet, please
+feedback through O-DU Low project WIKI page if you meet an issue. |br|
+`https://software.intel.com/en-us/system-studio/choose-download <https://software.intel.com/en-us/system-studio/choose-download%20>`__
+
+2.Download DPDK 18.08.
+
+3.With FlexRAN BBDev patch as per release 20.02. (Note currently this may require a license from Intel)
+
+4.Change DPDK files according to below diff information which relevant to O-RAN FH::
+
+    diff --git a/drivers/net/i40e/i40e_ethdev.c
+    b/drivers/net/i40e/i40e_ethdev.c
+    
+    index 85a6a86..236fbe0 100644
+    
+    --- a/drivers/net/i40e/i40e_ethdev.c
+    
+    +++ b/drivers/net/i40e/i40e_ethdev.c
+    
+    @@ -2207,7 +2207,7 @@ void i40e_flex_payload_reg_set_default(struct
+    i40e_hw \*hw)
+    
+    /\* Map queues with MSIX interrupt \*/
+    
+    main_vsi->nb_used_qps = dev->data->nb_rx_queues -
+    
+    pf->nb_cfg_vmdq_vsi \* RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
+    
+    - i40e_vsi_queues_bind_intr(main_vsi, I40E_ITR_INDEX_DEFAULT);
+    
+    + i40e_vsi_queues_bind_intr(main_vsi, I40E_ITR_INDEX_NONE);
+    
+    i40e_vsi_enable_queues_intr(main_vsi);
+    
+    /\* Map VMDQ VSI queues with MSIX interrupt \*/
+    
+    @@ -2218,6 +2218,10 @@ void i40e_flex_payload_reg_set_default(struct
+    i40e_hw \*hw)
+    
+    i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
+    
+    }
+    
+    + i40e_aq_debug_write_global_register(hw,
+    
+    + 0x0012A504,
+    
+    + 0, NULL);
+    
+    +
+    
+    /\* enable FDIR MSIX interrupt \*/
+    
+    if (pf->fdir.fdir_vsi) {
+    
+    i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi,
+    
+    diff --git a/drivers/net/i40e/i40e_ethdev_vf.c
+    b/drivers/net/i40e/i40e_ethdev_vf.c
+    
+    index 001c301..6f9ffdb 100644
+    
+    --- a/drivers/net/i40e/i40e_ethdev_vf.c
+    
+    +++ b/drivers/net/i40e/i40e_ethdev_vf.c
+    
+    @@ -640,7 +640,7 @@ struct rte_i40evf_xstats_name_off {
+    
+    map_info = (struct virtchnl_irq_map_info \*)cmd_buffer;
+    
+    map_info->num_vectors = 1;
+    
+    - map_info->vecmap[0].rxitr_idx = I40E_ITR_INDEX_DEFAULT;
+    
+    + map_info->vecmap[0].rxitr_idx = I40E_ITR_INDEX_NONE;
+    
+    map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id;
+    
+    /\* Alway use default dynamic MSIX interrupt \*/
+    
+    map_info->vecmap[0].vector_id = vector_id;
+    
+    diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
+    b/drivers/net/ixgbe/ixgbe_ethdev.c
+    
+    index 26b1927..018eb8f 100644
+    
+    --- a/drivers/net/ixgbe/ixgbe_ethdev.c
+    
+    +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
+    
+    @@ -3705,7 +3705,7 @@ static int
+    ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev \*dev,
+    
+    \* except for 82598EB, which remains constant.
+    
+    \*/
+    
+    if (dev_conf->txmode.mq_mode == ETH_MQ_TX_NONE &&
+    
+    - hw->mac.type != ixgbe_mac_82598EB)
+    
+    + hw->mac.type != ixgbe_mac_82598EB && hw->mac.type !=
+    ixgbe_mac_82599EB)
+    
+    dev_info->max_tx_queues = IXGBE_NONE_MODE_TX_NB_QUEUES;
+    
+    }
+    
+    dev_info->min_rx_bufsize = 1024; /\* cf BSIZEPACKET in SRRCTL register
+    \*/
+    
+    diff --git a/lib/librte_eal/common/include/rte_dev.h
+    b/lib/librte_eal/common/include/rte_dev.h
+    
+    old mode 100644
+    
+    new mode 100755
+
+5.Build and install DPDK::
+
+   [root@xran dpdk]# ./usertools/dpdk-setup.sh
+   
+   select [16] x86_64-native-linuxapp-icc
+   
+   select [19] Insert VFIO module
+   
+   exit [35] Exit Script
+
+6.Make below file changes in dpdk that assure i40e to get best
+latency of packet processing::
+
+    --- i40e.h 2018-11-30 11:27:00.000000000 +0000
+    
+    +++ i40e_patched.h 2019-03-06 15:49:06.877522427 +0000
+    
+    @@ -451,7 +451,7 @@
+    
+    #define I40E_QINT_RQCTL_VAL(qp, vector, nextq_type) \\
+    
+    (I40E_QINT_RQCTL_CAUSE_ENA_MASK \| \\
+    
+    - (I40E_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) \| \\
+    
+    + (I40E_ITR_NONE << I40E_QINT_RQCTL_ITR_INDX_SHIFT) \| \\
+    
+    ((vector) << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) \| \\
+    
+    ((qp) << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) \| \\
+    
+    (I40E_QUEUE_TYPE_##nextq_type << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT))
+    
+    --- i40e_main.c 2018-11-30 11:27:00.000000000 +0000
+    
+    +++ i40e_main_patched.c 2019-03-06 15:46:13.521518062 +0000
+    
+    @@ -15296,6 +15296,9 @@
+    
+    pf->hw_features \|= I40E_HW_HAVE_CRT_RETIMER;
+    
+    /\* print a string summarizing features \*/
+    
+    i40e_print_features(pf);
+    
+    +
+    
+    + /\* write to this register to clear rx descriptor \*/
+    
+    + i40e_aq_debug_write_register(hw, 0x0012A504, 0, NULL);
+    
+    return 0;
+    
+A.3 Configuration of System
+---------------------------
+1.Boot Linux with the following arguments::
+
+    cat /proc/cmdline
+    
+    BOOT_IMAGE=/vmlinuz-3.10.0-957.10.1.rt56.921.el7.x86_64
+    root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root
+    rd.lvm.lv=centos/swap intel_iommu=on iommu=pt usbcore.autosuspend=-1
+    selinux=0 enforcing=0 nmi_watchdog=0 softlockup_panic=0 audit=0
+    intel_pstate=disable cgroup_memory=1 cgroup_enable=memory mce=off
+    idle=poll hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0
+    default_hugepagesz=1G isolcpus=1-19,21-39 rcu_nocbs=1-19,21-39
+    kthread_cpus=0,20 irqaffinity=0,20 nohz_full=1-19,21-39
+    
+2.Download from Intel Website and install updated version of i40e
+driver if needed. The current recommended version of i40e is x2.9.21.
+
+3.Identify PCIe Bus address of the Front Haul NIC::
+
+    lspci \|grep Eth
+    
+    19:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit
+    SFI/SFP+ Network Connection (rev 01)
+    
+    19:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit
+    SFI/SFP+ Network Connection (rev 01)
+    
+    41:00.0 Ethernet controller: Intel Corporation Ethernet Connection X722
+    for 10GBASE-T (rev 04)
+    
+    41:00.1 Ethernet controller: Intel Corporation Ethernet Connection X722
+    for 10GBASE-T (rev 04)
+    
+    d8:00.0 Ethernet controller: Intel Corporation Ethernet Controller XL710
+    for 40GbE QSFP+ (rev 02) <<< port used for FH
+    
+    d8:00.1 Ethernet controller: Intel Corporation Ethernet Controller XL710
+    for 40GbE QSFP+ (rev 02)
+    
+4.Identify the Ethernet device name::
+
+    ethtool -i enp216s0f0
+    
+    driver: i40e
+    
+    version: 2.9.21
+    
+    firmware-version: 6.80 0x80003d05 1.2007.0
+    
+    expansion-rom-version:
+    
+    bus-info: 0000:d8:00.0
+    
+    supports-statistics: yes
+    
+    supports-test: yes
+    
+    supports-eeprom-access: yes
+    
+    supports-register-dump: yes
+    
+    supports-priv-flags: yes
+
+5.Enable two virtual functions (VF) on the device::
+
+    echo 2 > /sys/class/net/enp216s0f0/device/sriov_numvfs
+
+More information about VFs supported by Intel NICs can be found at
+https://doc.dpdk.org/guides/nics/intel_vf.html.
+
+The resulting configuration can look like the listing below, where two
+new VFs were added::
+
+    lspci|grep Eth
+    
+    19:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit
+    SFI/SFP+ Network Connection (rev 01)
+    
+    19:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit
+    SFI/SFP+ Network Connection (rev 01)
+    
+    41:00.0 Ethernet controller: Intel Corporation Ethernet Connection X722
+    for 10GBASE-T (rev 04)
+    
+    41:00.1 Ethernet controller: Intel Corporation Ethernet Connection X722
+    for 10GBASE-T (rev 04)
+    
+    d8:00.0 Ethernet controller: Intel Corporation Ethernet Controller XL710
+    for 40GbE QSFP+ (rev 02)
+    
+    d8:00.1 Ethernet controller: Intel Corporation Ethernet Controller XL710
+    for 40GbE QSFP+ (rev 02)
+    
+    d8:02.0 Ethernet controller: Intel Corporation XL710/X710 Virtual
+    Function (rev 02)
+    
+    d8:02.1 Ethernet controller: Intel Corporation XL710/X710 Virtual
+    Function (rev 02)
+
+6.Configure MAC address and VLAN settings for VFs for XRAN, based on
+requirements for xRAN scenario and assignment of VLAN ID using IP
+tool perform configuration of VF as shown below::
+
+    [root@xran app]# ip link set enp216s0f0 vf 0 mac 00:11:22:33:44:66 vlan
+    2
+    
+    [root@xran app]# ip link set enp216s0f0 vf 1 mac 00:11:22:33:44:66 vlan
+    1
+    
+    [root@xran app]# ip link show
+    
+    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode
+    DEFAULT qlen 1
+    
+    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+    
+    2: enp65s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state
+    UP mode DEFAULT qlen 1000
+    
+    link/ether a4:bf:01:3e:6b:79 brd ff:ff:ff:ff:ff:ff
+    
+    3: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
+    mode DEFAULT qlen 1000
+    
+    link/ether a4:bf:01:3e:6b:7a brd ff:ff:ff:ff:ff:ff
+    
+    4: enp25s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state
+    UP mode DEFAULT qlen 1000
+    
+    link/ether 90:e2:ba:d3:b2:ec brd ff:ff:ff:ff:ff:ff
+    
+    5: enp129s0f0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq
+    state DOWN mode DEFAULT qlen 1000
+    
+    link/ether 3c:fd:fe:a8:e0:70 brd ff:ff:ff:ff:ff:ff
+    
+    6: enp129s0f1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq
+    state DOWN mode DEFAULT qlen 1000
+    
+    link/ether 3c:fd:fe:a8:e0:71 brd ff:ff:ff:ff:ff:ff
+    
+    7: enp216s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state
+    UP mode DEFAULT qlen 1000
+    
+    link/ether 3c:fd:fe:9e:93:68 brd ff:ff:ff:ff:ff:ff
+    
+    vf 0 MAC 00:11:22:33:44:66, vlan 2, spoof checking on, link-state auto,
+    trust off
+    
+    vf 1 MAC 00:11:22:33:44:66, vlan 1, spoof checking on, link-state auto,
+    trust off
+    
+    8: enp25s0f1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq
+    state DOWN mode DEFAULT qlen 1000
+    
+    link/ether 90:e2:ba:d3:b2:ed brd ff:ff:ff:ff:ff:ff
+    
+    9: enp216s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state
+    UP mode DEFAULT qlen 1000
+    
+    link/ether 3c:fd:fe:9e:93:69 brd ff:ff:ff:ff:ff:ff
+    
+    12: enp216s2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state
+    UP mode DEFAULT qlen 1000
+    
+    link/ether 96:fa:4d:04:4d:87 brd ff:ff:ff:ff:ff:ff
+    
+    13: enp216s2f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq
+    state UP mode DEFAULT qlen 1000
+    
+    link/ether a6:67:49:bb:bd:5e brd ff:ff:ff:ff:ff:ff
+
+After this step FH NIC is configured.
+
+VF for C-plane is VF1 on PH enp216s0f0, it has ETH mac address
+00:11:22:33:44:66 and VLAN tag 1. PCIe Bus address is VF1 is d8:02.1
+
+VF for U-plane is VF0 on PH enp216s0f0, it has ETH mac address
+00:11:22:33:44:66 and VLAN tag 2. PCIe Bus address is VF1 is d8:02.0
+
+A.4 Install and Configure Sample Application
+--------------------------------------------
+To install and configure the sample application:
+
+1. Set up the environment:
+
+   export GTEST_ROOT=`pwd`/gtest-1.7.0
+   
+   export RTE_SDK=`pwd`/dpdk-18.08
+   
+   export RTE_TARGET=x86_64-native-linuxapp-icc
+   
+   export MLOG_DIR=`pwd`/flexran_l1_sw/libs/mlog
+   
+   export XRAN_DIR=`pwd`/flexran_xran
+
+2. Compile xRAN library and test the application:
+
+   [turner@xran home]$ cd $XRAN_DIR
+   
+   [turner@xran xran]$ ./build.sh
+   
+3. Configure the sample app.
+
+IQ samples can be generated using Octave\* and script
+libs/xran/app/gen_test.m. (CentOS\* has octave-3.8.2-20.el7.x86_64
+compatible with get_test.m)
+
+Other IQ sample test vectors can be used as well. The format of IQ
+samples is binary int16_t I and Q for N slots of the OTA RF signal. For
+example, for mmWave, it corresponds to 792RE*2*14symbol*8slots*10 ms =
+3548160 bytes per antenna. Refer to comments in gen_test.m to correctly
+specify the configuration for IQ test vector generation.
+
+Update config_file_o_du.dat (or config_file_o_ru.dat) with a suitable
+configuration for your scenario.
+
+Update run_o_du.sh (run_o_ru.sh) with PCIe bus address of VF0 and VF1
+used for U-plane and C-plane correspondingly::
+
+    ./build/sample-app ./usecase/mu0_10mhz/config_file_o_du.dat 0000:d8:02.0
+    0000:d8:02.1
+
+4. Run application using run_o_du.sh (run_o_ru.sh).
+
+
+
diff --git a/docs/Transport-Layer-and-ORAN-Fronthaul-Protocol-Implementation_fh.rst b/docs/Transport-Layer-and-ORAN-Fronthaul-Protocol-Implementation_fh.rst
new file mode 100644 (file)
index 0000000..661f09e
--- /dev/null
@@ -0,0 +1,1468 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+Transport Layer and ORAN Fronthaul Protocol Implementation
+==========================================================
+
+.. contents::
+    :depth: 3
+    :local:
+
+This chapter describes how the transport layer and ORAN Fronthaul
+protocol are implemented.
+
+.. _introduction-2:
+
+Introduction
+------------
+
+Figure 8 presents an overview of the ORAN Fronthaul process.
+
+.. image:: images/ORAN-Fronthaul-Process.jpg
+  :width: 600
+  :alt: Figure 8. ORAN Fronthaul Process
+
+Figure 8. ORAN Fronthaul Process
+
+The XRAN library provides support for transporting In-band and
+Quadrature (IQ) samples between the O-DU and O-RU within the RAN
+architecture based on functional split 7.2x. The library defines the
+xRAN packet formats to be used to transport radio samples within Front
+Haul according to the ORAN Fronthaul specification. It provides
+functionality for generating xRAN packets, appending IQ samples in the
+packet payload, and extracting IQ samples from xRAN packets. The Bronze release version
+of the library supports U-plane and C-plane only. It is ready to
+be used in the PTP synchronized |br|
+environment.
+
+Regarding the clock model and synchronization topology, configurations
+C1 and C3 of the connection between O-DU and O-RU are the only
+configurations supported in this release of the xRAN implementation.
+
+Quality of PTP synchronization with respect to S-plane of ORAN Fronthaul
+requirements as defined for O-RU is out of the scope of this document.
+PTP master and PTP slave configuration are expected to satisfy only the
+O-DU side of |br|
+requirements and provide the “best-effort” PTP master for
+O-RU. This may or may not be sufficient for achieving the end to end
+system requirements of S-plane. Specialized dedicated NIC card with
+additional HW functionality might be |br|
+required to achieve PTP master
+functionality to satisfy O-RU precision requirements for RAN deployments
+scenarios.
+
+.. image:: images/Configuration-C1.jpg
+  :width: 600
+  :alt: Figure 9. Configuration C1
+
+Figure 9. Configuration C1
+
+
+.. image:: images/Configuration-C3.jpg
+  :width: 600
+  :alt: Figure 10. Configuration C3
+
+Figure 10. Configuration C3
+
+Supported Feature Set
+---------------------
+
+The ORAN Fronthaul specification defines a list of mandatory
+functionality. Not all features defined as Mandatory for |br|
+O-DU are
+currently supported to fully extended. The following tables contain
+information on what is available and the level of validation performed
+for this release.
+
+2. Cells with a red background are listed as mandatory in the
+specification but not supported in this implementation of xRAN.
+
+Table 7. ORAN Mandatory and Optional Feature Support
+
++-----------------+-----------------+-----------+----------------+
+| Category        | Feature         | O-DU      | Support        |
+|                 |                 | Support   |                |
++=================+=================+===========+================+
+| RU Category     | Support for     | Mandatory | Y              |
+|                 | CAT-A RU (up to |           |                |
+|                 | 8 spatial       |           |                |
+|                 | streams)        |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Support for     |           | N              |
+|                 | CAT-A RU (> 8   |           |                |
+|                 | spatial         |           |                |
+|                 | streams)        |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Support for     | Mandatory | Y              |
+|                 | CAT-B RU        |           |                |
+|                 | (precoding in   |           |                |
+|                 | RU)             |           |                |
++-----------------+-----------------+-----------+----------------+
+| Beamforming     | Beam Index      | Mandatory | Y              |
+|                 | based           |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Real-time BF    | Mandatory | Y              |
+|                 | Weights         |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Real-Time       |           | N              |
+|                 | Beamforming     |           |                |
+|                 | Attributes      |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | UE Channel Info |           | N              |
++-----------------+-----------------+-----------+----------------+
+| Bandwidth       | Programmable    | Mandatory | Y              |
+| Saving          | s               |           |                |
+|                 | tatic-bit-width |           |                |
+|                 | Fixed Point IQ  |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Real-time       |           | Y              |
+|                 | var             |           |                |
+|                 | iable-bit-width |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Compressed IQ   |           | Y              |
++-----------------+-----------------+-----------+----------------+
+|                 | Block floating  |           | Y              |
+|                 | point           |           |                |
+|                 | compression     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Block scaling   |           | N              |
+|                 | compression     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | u-law           |           | N              |
+|                 | compression     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | modulation      |           | N              |
+|                 | compression     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | beamspace       |           | N              |
+|                 | compression     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Variable Bit    |           | Y              |
+|                 | Width per       |           |                |
+|                 | Channel (per    |           |                |
+|                 | data section)   |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Static          |           | N              |
+|                 | configuration   |           |                |
+|                 | of U-Plane IQ   |           |                |
+|                 | format and      |           |                |
+|                 | compression     |           |                |
+|                 | header          |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Use of “symInc” |           | N              |
+|                 | flag to allow   |           |                |
+|                 | multiple        |           |                |
+|                 | symbols in a    |           |                |
+|                 | C-Plane section |           |                |
++-----------------+-----------------+-----------+----------------+
+| Energy Saving   | Transmission    |           | N              |
+|                 | blanking        |           |                |
++-----------------+-----------------+-----------+----------------+
+| O-DU - RU       | Pre-configured  | Mandatory | Y              |
+| Timing          | Transport Delay |           |                |
+|                 | Method          |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Measured        |           | N              |
+|                 | Transport       |           |                |
+|                 | Method (eCPRI   |           |                |
+|                 | Msg 5)          |           |                |
++-----------------+-----------------+-----------+----------------+
+| Synchronization | G.8275.1        | Mandatory | Y     (C3 only)|
+|                 |                 |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | G.8275.2        |           | N              |
++-----------------+-----------------+-----------+----------------+
+|                 | GNSS based sync |           | N              |
++-----------------+-----------------+-----------+----------------+
+|                 | SyncE           |           | N              |
++-----------------+-----------------+-----------+----------------+
+| Transport       | L2 : Ethernet   | Mandatory | Y              |
+| Features        |                 |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | L3 : IPv4, IPv6 |           | N              |
+|                 | (CUS Plane)     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | QoS over        | Mandatory | N              |
+|                 | Fronthaul       |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Prioritization  |           | N              |
+|                 | of different    |           |                |
+|                 | U-plane traffic |           |                |
+|                 | types           |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Support of      |           | N              |
+|                 | Jumbo Ethernet  |           |                |
+|                 | frames          |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | eCPRI           | Mandatory | Y              |
++-----------------+-----------------+-----------+----------------+
+|                 | support of      |           | N              |
+|                 | eCPRI           |           |                |
+|                 | concatenation   |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | IEEE 1914.3     |           | N              |
++-----------------+-----------------+-----------+----------------+
+|                 | Application     | Mandatory | Y              |
+|                 | fragmentation   |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | Transport       |           | N              |
+|                 | fragmentation   |           |                |
++-----------------+-----------------+-----------+----------------+
+| Other           | LAA LBT O-DU    |           | N              |
+|                 | Congestion      |           |                |
+|                 | Window mgmt     |           |                |
++-----------------+-----------------+-----------+----------------+
+|                 | LAA LBT RU      |           | N              |
+|                 | Congestion      |           |                |
+|                 | Window mgmt     |           |                |
++-----------------+-----------------+-----------+----------------+
+
+Details on the subset of xRAN functionality implemented are shown in
+Table 8.
+
+Level of Validation Specified as:
+
+
+-  C: Completed code implementation for xRAN Library
+
+-  I: Integrated into Intel FlexRAN PHY
+
+-  T: Tested end to end with O-RU
+
+Table 8. Levels of Validation
+
++------------+------------+------------+------------+-----+-----+---+
+| Category   | Item       | Q4 (20.02) |            |     |     |   |
++============+============+============+============+=====+=====+===+
+|            |            | Status     | C          | I   | T   |   |
++------------+------------+------------+------------+-----+-----+---+
+| General    | Radio      | NR         | N/A        | N/A | N/A |   |
+|            | access     |            |            |     |     |   |
+|            | technology |            |            |     |     |   |
+|            | (LTE / NR) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Nominal    | 15         | Y          | Y   | N   |   |
+|            | s\         | /30/120KHz |            |     |     |   |
+|            | ub-carrier |            |            |     |     |   |
+|            | spacing    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | FFT size   | 512/1024   | Y          | Y   | N   |   |
+|            |            | /2048/4096 |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Channel    | 5/10       | Y          | Y   | N   |   |
+|            | bandwidth  | /20/100Mhz |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Number of  | 12         | Y          | Y   | N   |   |
+|            | the        |            |            |     |     |   |
+|            | channel    |            |            |     |     |   |
+|            | (Component |            |            |     |     |   |
+|            | Carrier)   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | RU         | A          | Y          | Y   | N   |   |
+|            | category   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | TDD Config | Supporte\  | Y          | Y   | N   |   |
+|            |            | d/Flexible |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | FDD        | Supported  | Y          | Y   | N   |   |
+|            | Support    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Tx/Rx      | Supported  | Y          | Y   | N   |   |
+|            | switching  |            |            |     |     |   |
+|            | based on   |            |            |     |     |   |
+|            | 'data      |            |            |     |     |   |
+|            | Direction' |            |            |     |     |   |
+|            | field of   |            |            |     |     |   |
+|            | C-plane    |            |            |     |     |   |
+|            | message    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | IP version | N/A        | N/A        | N/A | N/A |   |
+|            | for        |            |            |     |     |   |
+|            | Management |            |            |     |     |   |
+|            | traffic at |            |            |     |     |   |
+|            | fronthaul  |            |            |     |     |   |
+|            | network    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| PRACH      | One Type 3 | Supported  | Y          | Y   | N   |   |
+|            | message    |            |            |     |     |   |
+|            | for all    |            |            |     |     |   |
+|            | repeated   |            |            |     |     |   |
+|            | PRACH      |            |            |     |     |   |
+|            | preambles  |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Type 3     | 1          | Y          | Y   | N   |   |
+|            | message    |            |            |     |     |   |
+|            | per        |            |            |     |     |   |
+|            | repeated   |            |            |     |     |   |
+|            | PRACH      |            |            |     |     |   |
+|            | preambles  |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | timeOffset | Supported  | Y          | Y   | N   |   |
+|            | including  |            |            |     |     |   |
+|            | cpLength   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Supported  | Supported  | Y          | Y   | N   |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | PRACH      | Supported  | Y          | Y   | N   |   |
+|            | preamble   |            |            |     |     |   |
+|            | format /   |            |            |     |     |   |
+|            | index      |            |            |     |     |   |
+|            | number     |            |            |     |     |   |
+|            | (number of |            |            |     |     |   |
+|            | the        |            |            |     |     |   |
+|            | occasion)  |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| Delay      | Network    | Supported  | Y          | Y   | N   |   |
+| management | delay      |            |            |     |     |   |
+|            | det\       |            |            |     |     |   |
+|            | ermination |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | lls-CU     | Supported  | Y          | Y   | N   |   |
+|            | timing     |            |            |     |     |   |
+|            | advance    |            |            |     |     |   |
+|            | type       |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Non-delay  | Not        | N          | N   | N   |   |
+|            | managed    | supported  |            |     |     |   |
+|            | U-plane    |            |            |     |     |   |
+|            | traffic    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| C/U-plane  | Transport  | Ethernet   | Y          | Y   | N   |   |
+| Transport  | enc\       |            |            |     |     |   |
+|            | apsulation |            |            |     |     |   |
+|            | (Ethernet  |            |            |     |     |   |
+|            | / IP)      |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Jumbo      | Supported  | Y          | Y   | N   |   |
+|            | frames     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Transport  | eCPRI      | Y          | Y   | N   |   |
+|            | header     |            |            |     |     |   |
+|            | (eCPRI /   |            |            |     |     |   |
+|            | RoE)       |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | IP version | N/A        | N/A        | N/A | N/A |   |
+|            | when       |            |            |     |     |   |
+|            | Transport  |            |            |     |     |   |
+|            | header is  |            |            |     |     |   |
+|            | IP/UDP     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | eCPRI      | Not        | N          | N   | N   |   |
+|            | Con\       | supported  |            |     |     |   |
+|            | catenation |            |            |     |     |   |
+|            | when       |            |            |     |     |   |
+|            | Transport  |            |            |     |     |   |
+|            | header is  |            |            |     |     |   |
+|            | eCPRI      |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | eAxC ID    | 4 \*       | Y          | Y   | N   |   |
+|            | CU_Port_ID |            |            |     |     |   |
+|            | bitwidth   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | eAxC ID    | 4 \*       | Y          | Y   | N   |   |
+|            | Ban\       |            |            |     |     |   |
+|            | dSector_ID |            |            |     |     |   |
+|            | bitwidth   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | eAxC ID    | 4 \*       | Y          | Y   | N   |   |
+|            | CC_ID      |            |            |     |     |   |
+|            | bitwidth   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | eAxC ID    | 4 \*       | Y          | Y   | N   |   |
+|            | RU_Port_ID |            |            |     |     |   |
+|            | bitwidth   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Fra\       | Supported  | Y          | Y   | N   |   |
+|            | gmentation |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Transport  | N/A        | N          | N   | N   |   |
+|            | prio\      |            |            |     |     |   |
+|            | ritization |            |            |     |     |   |
+|            | within     |            |            |     |     |   |
+|            | U-plane    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Separation | Supported  | Y          | Y   | N   |   |
+|            | of         |            |            |     |     |   |
+|            | C/U-plane  |            |            |     |     |   |
+|            | and        |            |            |     |     |   |
+|            | M-plane    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Separation | VLAN ID    | Y          | Y   | N   |   |
+|            | of C-plane |            |            |     |     |   |
+|            | and        |            |            |     |     |   |
+|            | U-plane    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Max Number | 4          | Y          | Y   | N   |   |
+|            | of VLAN    |            |            |     |     |   |
+|            | per        |            |            |     |     |   |
+|            | physical   |            |            |     |     |   |
+|            | port       |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| Reception  | Rx_on_time | Supported  | Y          | Y   | N   |   |
+| Window     |            |            |            |     |     |   |
+| Monitoring |            |            |            |     |     |   |
+| (Counters) |            |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Rx_early   | Supported  | N          | N   | N   |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Rx_late    | Supported  | N          | N   | N   |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Rx_corrupt | Supported  | N          | N   | N   |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | R\         | Supported  | N          | N   | N   |   |
+|            | x_pkt_dupl |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Total      | Supported  | Y          | N   | N   |   |
+|            | _msgs_rcvd |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| B\         | RU         | Index and  | Y          | N   | N   |   |
+| eamforming | b\         | weights    |            |     |     |   |
+|            | eamforming |            |            |     |     |   |
+|            | type       |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | B\         | C-plane    | Y          | N   | N   |   |
+|            | eamforming |            |            |     |     |   |
+|            | control    |            |            |     |     |   |
+|            | method     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Number of  | No-re      | Y          | N   | N   |   |
+|            | beams      | strictions |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| IQ         | U-plane    | Supported  | Y          | N   | N   |   |
+| c\         | data       |            |            |     |     |   |
+| ompression | c\         |            |            |     |     |   |
+|            | ompression |            |            |     |     |   |
+|            | method     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | U-plane    | BFP:       | Y          | N   | N   |   |
+|            | data IQ    | 8,9,12,14  |            |     |     |   |
+|            | bitwidth   | bits       |            |     |     |   |
+|            | (Before /  |            |            |     |     |   |
+|            | After      |            |            |     |     |   |
+|            | co         |            |            |     |     |   |
+|            | mpression) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Static     | Supported  | Y          | Y   | N   |   |
+|            | con\       |            |            |     |     |   |
+|            | figuration |            |            |     |     |   |
+|            | of U-plane |            |            |     |     |   |
+|            | IQ format  |            |            |     |     |   |
+|            | and        |            |            |     |     |   |
+|            | c\         |            |            |     |     |   |
+|            | ompression |            |            |     |     |   |
+|            | header     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| eCPRI      | ec\        | 001b       | Y          | Y   | Y   |   |
+| Header     | priVersion |            |            |     |     |   |
+| Format     |            |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | ecp\       | Supported  | Y          | Y   | Y   |   |
+|            | riReserved |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | ecpriCon\  | Not        | N          | N   | N   |   |
+|            | catenation | supported  |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | ec\        | U-plane    | Supported  | Y   | Y   | Y |
+|            | priMessage |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | C-plane    | Supported  | Y   | Y   | Y |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | Delay      | Not        | N   | N   | N |
+|            |            | m\         | supported  |     |     |   |
+|            |            | easurement |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | ec\        | Supported  | Y          | Y   | Y   |   |
+|            | priPayload |            |            |     |     |   |
+|            | (payload   |            |            |     |     |   |
+|            | size in    |            |            |     |     |   |
+|            | bytes)     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | ecpriRtcid | Supported  | Y          | Y   | Y   |   |
+|            | /ecpriPcid |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | e\         | Supported  | Y          | Y   | Y   |   |
+|            | cpriSeqid: |            |            |     |     |   |
+|            | Sequence   |            |            |     |     |   |
+|            | ID         |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | e\         | Supported  | Y          | Y   | Y   |   |
+|            | cpriSeqid: |            |            |     |     |   |
+|            | E bit      |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | e\         | Not        | N          | N   | N   |   |
+|            | cpriSeqid: | supported  |            |     |     |   |
+|            | S\         |            |            |     |     |   |
+|            | ubsequence |            |            |     |     |   |
+|            | ID         |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| C-plane    | Section    | Not        | N          | N   | N   |   |
+| Type       | Type 0     | supported  |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Section    | Supported  | Y          | Y   | Y   |   |
+|            | Type 1     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Section    | Supported  | Y          | Y   | N   |   |
+|            | Type 3     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Section    | Not        | N          | N   | N   |   |
+|            | Type 5     | supported  |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Section    | Not        | N          | N   | N   |   |
+|            | Type 6     | supported  |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Section    | Not        | N          | N   | N   |   |
+|            | Type 7     | supported  |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| C-plane    | *Coding of | dat\       | Supported  | Y   | Y   | N |
+| Packet     | I\         | aDirection |            |     |     |   |
+| Format     | nformation | (data      |            |     |     |   |
+|            | Elements – | direction  |            |     |     |   |
+|            | A\         | (gNB       |            |     |     |   |
+|            | pplication | Tx/Rx))    |            |     |     |   |
+|            | Layer,     |            |            |     |     |   |
+|            | Common*    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | payl\      | 001b       | Y   | Y   | N |
+|            |            | oadVersion |            |     |     |   |
+|            |            | (payload   |            |     |     |   |
+|            |            | version)   |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | f\         | Supported  | Y   | Y   | N |
+|            |            | ilterIndex |            |     |     |   |
+|            |            | (filter    |            |     |     |   |
+|            |            | index)     |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | frameId    | Supported  | Y   | Y   | N |
+|            |            | (frame     |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | dentifier) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | subframeId | Supported  | Y   | Y   | N |
+|            |            | (subframe  |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | dentifier) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | slotId     | Supported  | Y   | Y   | N |
+|            |            | (slot      |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | dentifier) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | sta\       | Supported  | Y   | Y   | N |
+|            |            | rtSymbolid |            |     |     |   |
+|            |            | (start     |            |     |     |   |
+|            |            | symbol     |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | dentifier) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | number     | up to the  | Y   | Y   | N |
+|            |            | Ofsections | maximum    |     |     |   |
+|            |            | (number of | number of  |     |     |   |
+|            |            | sections)  | PRBs       |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | s\         | 1 and 3    | Y   | Y   | N |
+|            |            | ectionType |            |     |     |   |
+|            |            | (section   |            |     |     |   |
+|            |            | type)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | udCompHdr  | Supported  | N   | N   | N |
+|            |            | (user data |            |     |     |   |
+|            |            | c\         |            |     |     |   |
+|            |            | ompression |            |     |     |   |
+|            |            | header)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | n\         | Not        | N   | N   | N |
+|            |            | umberOfUEs | supported  |     |     |   |
+|            |            | (number Of |            |     |     |   |
+|            |            | UEs)       |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | timeOffset | Supported  | Y   | Y   | N |
+|            |            | (time      |            |     |     |   |
+|            |            | offset)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | fram\      | mu=0,1,3   | Y   | Y   | N |
+|            |            | eStructure |            |     |     |   |
+|            |            | (frame     |            |     |     |   |
+|            |            | structure) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | cpLength   | Supported  | Y   | Y   | N |
+|            |            | (cyclic    |            |     |     |   |
+|            |            | prefix     |            |     |     |   |
+|            |            | length)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | *Coding of | sectionId  | Supported  | Y   | Y   | N |
+|            | I\         | (section   |            |     |     |   |
+|            | nformation | i\         |            |     |     |   |
+|            | Elements – | dentifier) |            |     |     |   |
+|            | A\         |            |            |     |     |   |
+|            | pplication |            |            |     |     |   |
+|            | Layer,     |            |            |     |     |   |
+|            | Sections*  |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | rb         | 0          | Y   | Y   | N |
+|            |            | (resource  |            |     |     |   |
+|            |            | block      |            |     |     |   |
+|            |            | indicator) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | symInc     | 0 or 1     | Y   | Y   | N |
+|            |            | (symbol    |            |     |     |   |
+|            |            | number     |            |     |     |   |
+|            |            | increment  |            |     |     |   |
+|            |            | command)   |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | startPrbc  | Supported  | Y   | Y   | N |
+|            |            | (starting  |            |     |     |   |
+|            |            | PRB of     |            |     |     |   |
+|            |            | control    |            |     |     |   |
+|            |            | section)   |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | reMask     | Supported  | Y   | Y   | N |
+|            |            | (resource  |            |     |     |   |
+|            |            | element    |            |     |     |   |
+|            |            | mask)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | numPrbc    | Supported  | Y   | Y   | N |
+|            |            | (number of |            |     |     |   |
+|            |            | contiguous |            |     |     |   |
+|            |            | PRBs per   |            |     |     |   |
+|            |            | control    |            |     |     |   |
+|            |            | section)   |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | numSymbol  | Supported  | Y   | Y   | N |
+|            |            | (number of |            |     |     |   |
+|            |            | symbols)   |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | ef         | Supported  | Y   | Y   | N |
+|            |            | (extension |            |     |     |   |
+|            |            | flag)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | beamId     | Support    | Y   | Y   | N |
+|            |            | (beam      |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | dentifier) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | ueId (UE   | Not        | N   | N   | N |
+|            |            | i\         | supported  |     |     |   |
+|            |            | dentifier) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | freqOffset | Supported  | Y   | Y   | N |
+|            |            | (frequency |            |     |     |   |
+|            |            | offset)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | regulariza\| Not        | N   | N   | N |
+|            |            | tionFactor | supported  |     |     |   |
+|            |            | (regu\     |            |     |     |   |
+|            |            | larization |            |     |     |   |
+|            |            | Factor)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | ciIsample, | Not        | N   | N   | N |
+|            |            | ciQsample  | supported  |     |     |   |
+|            |            | (channel   |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | nformation |            |     |     |   |
+|            |            | I and Q    |            |     |     |   |
+|            |            | values)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | laaMsgType | Not        | N   | N   | N |
+|            |            | (LAA       | supported  |     |     |   |
+|            |            | message    |            |     |     |   |
+|            |            | type)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | laaMsgLen  | Not        | N   | N   | N |
+|            |            | (LAA       | supported  |     |     |   |
+|            |            | message    |            |     |     |   |
+|            |            | length)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtHandle  | Not        | N   | N   | N |
+|            |            |            | supported  |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtD\      | Not        | N   | N   | N |
+|            |            | eferFactor | supported  |     |     |   |
+|            |            | (listen-b  |            |     |     |   |
+|            |            | efore-talk |            |     |     |   |
+|            |            | defer      |            |     |     |   |
+|            |            | factor)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtBack    | Not        | N   | N   | N |
+|            |            | offCounter | supported  |     |     |   |
+|            |            | (listen-b\ |            |     |     |   |
+|            |            | efore-talk |            |     |     |   |
+|            |            | backoff    |            |     |     |   |
+|            |            | counter)   |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtOffset  | Not        | N   | N   | N |
+|            |            | (listen-b\ | supported  |     |     |   |
+|            |            | efore-talk |            |     |     |   |
+|            |            | offset)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | MCOT       | Not        | N   | N   | N |
+|            |            | (maximum   | supported  |     |     |   |
+|            |            | channel    |            |     |     |   |
+|            |            | occupancy  |            |     |     |   |
+|            |            | time)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtMode    | Not        | N   | N   | N |
+|            |            | (LBT Mode) | supported  |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | l\         | Not        | N   | N   | N |
+|            |            | btPdschRes | supported  |     |     |   |
+|            |            | (LBT PDSCH |            |     |     |   |
+|            |            | Result)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | sfStatus   | Not        | N   | N   | N |
+|            |            | (subframe  | supported  |     |     |   |
+|            |            | status)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtDrsRes  | Not        | N   | N   | N |
+|            |            | (LBT DRS   | supported  |     |     |   |
+|            |            | Result)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | initia\    | Not        | N   | N   | N |
+|            |            | lPartialSF | supported  |     |     |   |
+|            |            | (Initial   |            |     |     |   |
+|            |            | partial    |            |     |     |   |
+|            |            | SF)        |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtBufErr  | Not        | N   | N   | N |
+|            |            | (LBT       | supported  |     |     |   |
+|            |            | Buffer     |            |     |     |   |
+|            |            | Error)     |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | sfnSf      | Not        | N   | N   | N |
+|            |            | (SFN/SF    | supported  |     |     |   |
+|            |            | End)       |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbt        | Not        | N   | N   | N |
+|            |            | CWConfig_H | supported  |     |     |   |
+|            |            | (HARQ      |            |     |     |   |
+|            |            | Parameters |            |     |     |   |
+|            |            | for        |            |     |     |   |
+|            |            | Congestion |            |     |     |   |
+|            |            | Window     |            |     |     |   |
+|            |            | m          |            |     |     |   |
+|            |            | anagement) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbt        | Not        | N   | N   | N |
+|            |            | CWConfig_T | supported  |     |     |   |
+|            |            | (TB        |            |     |     |   |
+|            |            | Parameters |            |     |     |   |
+|            |            | for        |            |     |     |   |
+|            |            | Congestion |            |     |     |   |
+|            |            | Window     |            |     |     |   |
+|            |            | m          |            |     |     |   |
+|            |            | anagement) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtTr\     | Not        | N   | N   | N |
+|            |            | afficClass | supported  |     |     |   |
+|            |            | (Traffic   |            |     |     |   |
+|            |            | class      |            |     |     |   |
+|            |            | priority   |            |     |     |   |
+|            |            | for        |            |     |     |   |
+|            |            | Congestion |            |     |     |   |
+|            |            | Window     |            |     |     |   |
+|            |            | m          |            |     |     |   |
+|            |            | anagement) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | lbtCWR_Rst | Not        | N   | N   | N |
+|            |            | (No        | supported  |     |     |   |
+|            |            | tification |            |     |     |   |
+|            |            | about      |            |     |     |   |
+|            |            | packet     |            |     |     |   |
+|            |            | reception  |            |     |     |   |
+|            |            | successful |            |     |     |   |
+|            |            | or not)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | reserved   | 0          | N   | N   | N |
+|            |            | (reserved  |            |     |     |   |
+|            |            | for future |            |     |     |   |
+|            |            | use)       |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | *Section   |            |     |     |   |
+|            |            | Extension  |            |     |     |   |
+|            |            | Commands*  |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | extType    | Supported  | Y   | N   | N |
+|            |            | (extension |            |     |     |   |
+|            |            | type)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | ef         | Supported  | Y   | N   | N |
+|            |            | (extension |            |     |     |   |
+|            |            | flag)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | extLen     | Supported  | Y   | N   | N |
+|            |            | (extension |            |     |     |   |
+|            |            | length)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Coding of  |            |            |     |     |   |
+|            | I\         |            |            |     |     |   |
+|            | nformation |            |            |     |     |   |
+|            | Elements – |            |            |     |     |   |
+|            | A\         |            |            |     |     |   |
+|            | pplication |            |            |     |     |   |
+|            | Layer,     |            |            |     |     |   |
+|            | Section    |            |            |     |     |   |
+|            | E\         |            |            |     |     |   |
+|            | xtensions  |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | *ExtType=1:| bfwCompHdr | Supported  | Y   | N   | N |
+|            | B\         | (beam\     |            |     |     |   |
+|            | eamforming | forming    |            |     |     |   |
+|            | Weights    | weight     |            |     |     |   |
+|            | Extension  | c\         |            |     |     |   |
+|            | Type*      | ompression |            |     |     |   |
+|            |            | header)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bf         | Supported  | Y   | N   | N |
+|            |            | wCompParam |            |     |     |   |
+|            |            | (b\        |            |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | weight     |            |     |     |   |
+|            |            | c\         |            |     |     |   |
+|            |            | ompression |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfwl       | Supported  | Y   | N   | N |
+|            |            | (b\        |            |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | weight     |            |     |     |   |
+|            |            | in-phase   |            |     |     |   |
+|            |            | value)     |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfwQ       | Supported  | Y   | N   | N |
+|            |            | (b\        |            |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | weight     |            |     |     |   |
+|            |            | quadrature |            |     |     |   |
+|            |            | value)     |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfaCompHdr | Not        | Y   | N   | N |
+|            | *ExtType=2:| (b\        | supported  |     |     |   |
+|            | B\         | eamforming |            |     |     |   |
+|            | eamforming | attributes |            |     |     |   |
+|            | Attributes | c\         |            |     |     |   |
+|            | Extension  | ompression |            |     |     |   |
+|            | Type*      | header)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfAzPt     | Not        | Y   | N   | N |
+|            |            | (b\        | supported  |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | azimuth    |            |     |     |   |
+|            |            | pointing   |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfZePt     | Not        | Y   | N   | N |
+|            |            | (b\        | supported  |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | zenith     |            |     |     |   |
+|            |            | pointing   |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfAz3dd    | Not        | Y   | N   | N |
+|            |            | (b         | supported  |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | azimuth    |            |     |     |   |
+|            |            | beamwidth  |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfZe3dd    | Not        | Y   | N   | N |
+|            |            | (b\        | supported  |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | zenith     |            |     |     |   |
+|            |            | beamwidth  |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfAzSl     | Not        | Y   | N   | N |
+|            |            | (b\        | supported  |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | azimuth    |            |     |     |   |
+|            |            | sidelobe   |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | bfZeSl     | Not        | Y   | N   | N |
+|            |            | (b\        | supported  |     |     |   |
+|            |            | eamforming |            |     |     |   |
+|            |            | zenith     |            |     |     |   |
+|            |            | sidelobe   |            |     |     |   |
+|            |            | parameter) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | ze\        | Not        | Y   | N   | N |
+|            |            | ro-padding | supported  |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | cod        | Not        | N   | N   | N |
+|            | *ExtType=3:| ebookIndex | supported  |     |     |   |
+|            | DL         | (precoder  |            |     |     |   |
+|            | Precoding  | codebook   |            |     |     |   |
+|            | Extension  | used for   |            |     |     |   |
+|            | Type*      | tra        |            |     |     |   |
+|            |            | nsmission) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | layerID    | Not        | N   | N   | N |
+|            |            | (Layer ID  | supported  |     |     |   |
+|            |            | for DL     |            |     |     |   |
+|            |            | tra\       |            |     |     |   |
+|            |            | nsmission) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | txScheme   | Not        | N   | N   | N |
+|            |            | (tr        | supported  |     |     |   |
+|            |            | ansmission |            |     |     |   |
+|            |            | scheme)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | numLayers  | Not        | N   | N   | N |
+|            |            | (number of | supported  |     |     |   |
+|            |            | layers     |            |     |     |   |
+|            |            | used for   |            |     |     |   |
+|            |            | DL         |            |     |     |   |
+|            |            | tra\       |            |     |     |   |
+|            |            | nsmission) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | crsReMask  | Not        | N   | N   | N |
+|            |            | (CRS       | supported  |     |     |   |
+|            |            | resource   |            |     |     |   |
+|            |            | element    |            |     |     |   |
+|            |            | mask)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | c          | Not        | N   | N   | N |
+|            |            | rsSyumINum | supported  |     |     |   |
+|            |            | (CRS       |            |     |     |   |
+|            |            | symbol     |            |     |     |   |
+|            |            | number     |            |     |     |   |
+|            |            | i\         |            |     |     |   |
+|            |            | ndication) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | crsShift   | Not        | N   | N   | N |
+|            |            | (crsShift  | supported  |     |     |   |
+|            |            | used for   |            |     |     |   |
+|            |            | DL         |            |     |     |   |
+|            |            | tra\       |            |     |     |   |
+|            |            | nsmission) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | beamIdAP1  | Not        | N   | N   | N |
+|            |            | (beam id   | supported  |     |     |   |
+|            |            | to be used |            |     |     |   |
+|            |            | for        |            |     |     |   |
+|            |            | antenna    |            |     |     |   |
+|            |            | port 1)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | beamIdAP2  | Not        | N   | N   | N |
+|            |            | (beam id   | supported  |     |     |   |
+|            |            | to be used |            |     |     |   |
+|            |            | for        |            |     |     |   |
+|            |            | antenna    |            |     |     |   |
+|            |            | port 2)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | beamIdAP3  | Not        | N   | N   | N |
+|            |            | (beam id   | supported  |     |     |   |
+|            |            | to be used |            |     |     |   |
+|            |            | for        |            |     |     |   |
+|            |            | antenna    |            |     |     |   |
+|            |            | port 3)    |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | csf        | Not        | Y   | N   | N |
+|            | *ExtType=4:| (con\      | supported  |     |     |   |
+|            | Modulation | stellation |            |     |     |   |
+|            | C\         | shift      |            |     |     |   |
+|            | ompression | flag)      |            |     |     |   |
+|            | Parameters |            |            |     |     |   |
+|            | Extension  |            |            |     |     |   |
+|            | Type*      |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | mod        | Not        | Y   | N   | N |
+|            |            | CompScaler | supported  |     |     |   |
+|            |            | (          |            |     |     |   |
+|            |            | modulation |            |     |     |   |
+|            |            | c\         |            |     |     |   |
+|            |            | ompression |            |     |     |   |
+|            |            | scaler     |            |     |     |   |
+|            |            | value)     |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | mcS\       | Not        | Y   | N   | N |
+|            | *ExtType=5:| caleReMask | supported  |     |     |   |
+|            | Modulation | (          |            |     |     |   |
+|            | C\         | modulation |            |     |     |   |
+|            | ompression | c\         |            |     |     |   |
+|            | Additional | ompression |            |     |     |   |
+|            | Parameters | power      |            |     |     |   |
+|            | Extension  | scale RE   |            |     |     |   |
+|            | Type*      | mask)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | csf        | Not        | Y   | N   | N |
+|            |            | (con\      | supported  |     |     |   |
+|            |            | stellation |            |     |     |   |
+|            |            | shift      |            |     |     |   |
+|            |            | flag)      |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            |            | mcS        | Not        | Y   | N   | N |
+|            |            | caleOffset | supported  |     |     |   |
+|            |            | (scaling   |            |     |     |   |
+|            |            | value for  |            |     |     |   |
+|            |            | modulation |            |     |     |   |
+|            |            | co\        |            |     |     |   |
+|            |            | mpression) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| U-plane    | dat        | Supported  | Y          | Y   | Y   |   |
+| Packet     | aDirection |            |            |     |     |   |
+| Format     | (data      |            |            |     |     |   |
+|            | direction  |            |            |     |     |   |
+|            | (gNB       |            |            |     |     |   |
+|            | Tx/Rx))    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | payl\      | 001b       | Y          | Y   | Y   |   |
+|            | oadVersion |            |            |     |     |   |
+|            | (payload   |            |            |     |     |   |
+|            | version)   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | f\         | Supported  | Y          | Y   | Y   |   |
+|            | ilterIndex |            |            |     |     |   |
+|            | (filter    |            |            |     |     |   |
+|            | index)     |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | frameId    | Supported  | Y          | Y   | Y   |   |
+|            | (frame     |            |            |     |     |   |
+|            | i\         |            |            |     |     |   |
+|            | dentifier) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | subframeId | Supported  | Y          | Y   | Y   |   |
+|            | (subframe  |            |            |     |     |   |
+|            | i\         |            |            |     |     |   |
+|            | dentifier) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | slotId     | Supported  | Y          | Y   | Y   |   |
+|            | (slot      |            |            |     |     |   |
+|            | i          |            |            |     |     |   |
+|            | dentifier) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | symbolId   | Supported  | Y          | Y   | Y   |   |
+|            | (symbol    |            |            |     |     |   |
+|            | i\         |            |            |     |     |   |
+|            | dentifier) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | sectionId  | Supported  | Y          | Y   | Y   |   |
+|            | (section   |            |            |     |     |   |
+|            | i\         |            |            |     |     |   |
+|            | dentifier) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | rb         | 0          | Y          | Y   | Y   |   |
+|            | (resource  |            |            |     |     |   |
+|            | block      |            |            |     |     |   |
+|            | indicator) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | symInc     | 0          | Y          | Y   | Y   |   |
+|            | (symbol    |            |            |     |     |   |
+|            | number     |            |            |     |     |   |
+|            | increment  |            |            |     |     |   |
+|            | command)   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | startPrbu  | Supported  | Y          | Y   | Y   |   |
+|            | (s\        |            |            |     |     |   |
+|            | tartingPRB |            |            |     |     |   |
+|            | of user    |            |            |     |     |   |
+|            | plane      |            |            |     |     |   |
+|            | section)   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | numPrbu    | Supported  | Y          | Y   | Y   |   |
+|            | (number of |            |            |     |     |   |
+|            | PRBs per   |            |            |     |     |   |
+|            | user plane |            |            |     |     |   |
+|            | section)   |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | udCompHdr  | Supported  | Y          | Y   | N   |   |
+|            | (user data |            |            |     |     |   |
+|            | c\         |            |            |     |     |   |
+|            | ompression |            |            |     |     |   |
+|            | header)    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | reserved   | 0          | Y          | Y   | Y   |   |
+|            | (reserved  |            |            |     |     |   |
+|            | for future |            |            |     |     |   |
+|            | use)       |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | u\         | Supported  | Y          | Y   | N   |   |
+|            | dCompParam |            |            |     |     |   |
+|            | (user data |            |            |     |     |   |
+|            | c\         |            |            |     |     |   |
+|            | ompression |            |            |     |     |   |
+|            | parameter) |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | iSample    | 16         | Y          | Y   | Y   |   |
+|            | (in-phase  |            |            |     |     |   |
+|            | sample)    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | qSample    | 16         | Y          | Y   | Y   |   |
+|            | (          |            |            |     |     |   |
+|            | quadrature |            |            |     |     |   |
+|            | sample)    |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| S-plane    | Topology   | Supported  | N          | N   | N   |   |
+|            | conf\      |            |            |     |     |   |
+|            | iguration: |            |            |     |     |   |
+|            | C1         |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Topology   | Supported  | N          | N   | N   |   |
+|            | conf\      |            |            |     |     |   |
+|            | iguration: |            |            |     |     |   |
+|            | C2         |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Topology   | Supported  | Y          | Y   | Y   |   |
+|            | conf\      |            |            |     |     |   |
+|            | iguration: |            |            |     |     |   |
+|            | C3         |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | Topology   | Supported  | N          | N   | N   |   |
+|            | conf\      |            |            |     |     |   |
+|            | iguration: |            |            |     |     |   |
+|            | C4         |            |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+|            | PTP        | Full       | Supported  | Y   | Y   | N |
+|            |            | Timing     |            |     |     |   |
+|            |            | Support    |            |     |     |   |
+|            |            | (G.8275.1) |            |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+| M-plane    |            |            | Not        | N   | N   | N |
+|            |            |            | supported  |     |     |   |
++------------+------------+------------+------------+-----+-----+---+
+
+\* The bit width of each component in eAxC ID can be configurable.
+
+Transport Layer
+---------------
+
+ORAN Fronthaul data can be transported over Ethernet or IPv4/IPv6. In
+the current implementation, the xRAN library supports only Ethernet with
+VLAN.
+
+.. image:: images/Native-Ethernet-Frame-with-VLAN.jpg
+  :width: 600
+  :alt: Figure 11. Native Ethernet Frame with VLAN
+
+Figure 11. Native Ethernet Frame with VLAN
+
+
+Standard DPDK routines are used to perform Transport Layer
+functionality.
+
+VLAN tag functionality is offloaded to NIC as per the configuration of
+VF (refer to Appendix Appendix 1).
+
+The transport header is defined in the ORAN Fronthaul specification
+based on the eCPRI specification.
+
+.. image:: images/eCPRI-Header-Field-Definitions.jpg
+  :width: 600
+  :alt: Figure 12. eCPRI Header Field Definitions
+
+Figure 12. eCPRI Header Field Definitions
+
+Only ECPRI_IQ_DATA = 0x00 and ECPRI_RT_CONTROL_DATA= 0x02 message types
+are supported.
+
+Handling of ecpriRtcid/ecpriPcid Bit field size is configurable and can
+be defined on the initialization stage of the xRAN |br|
+library.
+
+.. image:: images/Bit-Allocations-of-ecpriRtcid-ecpriPcid.jpg
+  :width: 600
+  :alt: Figure 13. Bit Allocations of ecpriRtcid/ecpriPcid
+
+Figure 13. Bit Allocations of ecpriRtcid/ecpriPcid
+
+For ecpriSeqid only, the support for a sequence number is implemented.
+The subsequent number is not supported.
+
+U-plane
+-------
+
+The following diagrams show xRAN packet protocols’ headers and data
+arrangement with and without compression |br|
+support.
+
+XRAN packet meant for traffic with compression enabled has the
+Compression Header added after each Application Header. According to
+ORAN Fronthaul's specification, the Compression Header is part of a
+repeated Section Application Header. In the xRAN library implementation,
+the header is implemented as a separate structure, following the
+Application Section Header. As a result, the Compression Header is not
+included in the xRAN packet, if compression is not used.
+
+Figure 14 shows the components of an xRAN packet.
+
+.. image:: images/xRAN-Packet-Components.jpg
+  :width: 600
+  :alt: Figure 14. xRAN Packet Components
+
+Figure 14. xRAN Packet Components
+
+Radio Application Header
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The next header is a common header used for time reference.
+
+.. image:: images/Radio-Application-Header.jpg
+  :width: 600
+  :alt: Figure 15. Radio Application Header
+
+Figure 15. Radio Application Header
+
+The radio application header specific field values are implemented as
+follows:
+
+-  filterIndex = 0
+
+-  frameId = [0:99]
+
+-  subframeId = [0:9]
+
+-  slotId = [0:7]
+
+-  symbolId = [0:13]
+
+Data Section Application Data Header
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Common Radio Application Header is followed by the Application
+Header that is repeated for each Data Section |br|
+within the eCPRI message.
+The relevant section of xRAN packet is shown in color.
+
+.. image:: images/Data-Section-Application-Data-Header.jpg
+  :width: 600
+  :alt: Figure 16. Data Section Application Data Header
+
+Figure 16. Data Section Application Data Header
+
+
+A single section is used per one Ethernet packet with IQ samples
+startPrbu is equal to 0 and numPrbu is wqual to the number of RBs used:
+
+-  rb field is not used (value 0).
+
+-  symInc is not used (value 0)
+
+Data Payload
+~~~~~~~~~~~~
+
+An xRAN packet data payload contains a number of PRBs. Each PRB is built
+of 12 IQ samples. The supported IQ bit width is 16. udCompParam is not
+included in the data payload as compression currently is not supported.
+The data section is shown in color.
+
+.. image:: images/Data-Payload.jpg
+  :width: 600
+  :alt: Figure 17. Data Payload
+
+Figure 17. Data Payload
+
+C-plane
+-------
+
+C-Plane messages are encapsulated using a two-layered header approach.
+The first layer consists of an eCPRI standard header, including
+corresponding fields used to indicate the message type, while the second
+layer is an application layer |br|
+including necessary fields for control and
+synchronization. Within the application layer, a “section” defines the |br|
+characteristics of U-plane data to be transferred or received from a
+beam with one pattern id. In general, the transport header, |br|
+application
+header, and sections are all intended to be aligned on 4-byte boundaries
+and are transmitted in “network byte |br|
+order” meaning the most significant
+byte of a multi-byte parameter is transmitted first.
+
+Table 9 is a list of sections currently supported.
+
+Table 9. Section Types
+
++--------------+--------------------------+--------------------------+
+| Section Type | Target Scenario          | Remarks                  |
++--------------+--------------------------+--------------------------+
+| 0            | Unused Resource Blocks   | Not supported            |
+|              | or symbols in Downlink   |                          |
+|              | or Uplink                |                          |
++--------------+--------------------------+--------------------------+
+| 1            | Most DL/UL radio         | Supported                |
+|              | channels                 |                          |
++--------------+--------------------------+--------------------------+
+| 2            | reserved for future use  | N/A                      |
++--------------+--------------------------+--------------------------+
+| 3            | PRACH and                | Only PRACH is supported. |
+|              | mixed-numerology         | Mixed numerology is not  |
+|              | channels                 | supported.               |
++--------------+--------------------------+--------------------------+
+| 4            | Reserved for future use  | Not supported            |
++--------------+--------------------------+--------------------------+
+| 5            | UE scheduling            | Not supported            |
+|              | information (UE-ID       |                          |
+|              | assignment to section)   |                          |
++--------------+--------------------------+--------------------------+
+| 6            | Channel information      | Not supported            |
++--------------+--------------------------+--------------------------+
+| 7            | LAA                      | Not supported            |
++--------------+--------------------------+--------------------------+
+| 8-255        | Reserved for future use  | N/A                      |
++--------------+--------------------------+--------------------------+
+
+Section extensions are not supported in this release.
+
+The definition of the C-Plane packet can be found lib/api/xran_pkt_cp.h
+and the fields are appropriately re-ordered in |br|
+order to apply the
+conversion of network byte order after setting values.
+
+Ethernet Header
+~~~~~~~~~~~~~~~
+
+Refer to Figure 11.
+
+eCPRI Header
+~~~~~~~~~~~~
+
+Refer to Figure 12.
+
+This header is defined as the structure of xran_ecpri_hdr in
+lib/api/xran_pkt.h.
+
+Radio Application Common Header
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Radio Application Common Header is used for time reference. Its
+structure is shown in Figure 18.
+
+.. image:: images/Radio-Application-Common-Header.jpg
+  :width: 600
+  :alt: Figure 18. Radio Application Common Header
+
+Figure 18. Radio Application Common Header
+
+This header is defined as the structure of
+xran_cp_radioapp_common_header in lib/api/xran_pkt_cp.h.
+
+Please note that the payload version in this header is fixed to
+XRAN_PAYLOAD_VER (defined as 1) in this release.
+
+Section Type 0 Structure
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Figure 19 describes the structure of Section Type 0.
+
+.. image:: images/Section-Type-0-Structure.jpg
+  :width: 600
+  :alt: Figure 19. Section Type 0 Structure
+
+Figure 19. Section Type 0 Structure
+
+In Figure 18 through Figure 22, the color yellow means it is a transport
+header; the color pink is the radio application header; others are
+repeated sections.
+
+Section Type 1 Structure
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Figure 20 describes the structure of Section Type 1.
+
+.. image:: images/Section-Type-1-Structure.jpg
+  :width: 600
+  :alt: Figure 20. Section Type 1 Structure
+
+Figure 20. Section Type 1 Structure
+
+Section Type 1 message has two additional parameters in addition to
+radio application common header:
+
+-  udCompHdr : defined as the structure of xran_radioapp_udComp_header
+
+-  reserved : fixed by zero
+
+Section type 1 is defined as the structure of xran_cp_radioapp_section1,
+and this part can be repeated to have multiple sections.
+
+Whole section type 1 message can be described in this summary:
+
++----------------------------------+
+| xran_cp_radioapp_common_header   |
++==================================+
+| xran_cp_radioapp_section1_header |
++----------------------------------+
+| xran_cp_radioapp_section1        |
++----------------------------------+
+| ……                               |
++----------------------------------+
+| xran_cp_radioapp_section1        |
++----------------------------------+
+
+Section Type 3 Structure
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Figure 21 describes the structure of Section Type 3.
+
+.. image:: images/Section-Type-3-Structure.jpg
+  :width: 600
+  :alt: Figure 21. Section Type 3 Structure
+
+Figure 21. Section Type 3 Structure
+
+Section Type 3 message has below four additional parameters in addition
+to radio application common header.
+
+-  timeOffset
+
+-  frameStrucutre: defined as the structure of
+   xran_cp_radioapp_frameStructure
+
+-  cpLength
+
+-  udCompHdr: defined as the structure of xran_radioapp_udComp_header
+
+Section Type 3 is defined as the structure of xran_cp_radioapp_section3
+and this part can be repeated to have multiple sections.
+
+Whole section type 3 message can be described in this summary:
+
++----------------------------------+
+| xran_cp_radioapp_common_header   |
++==================================+
+| xran_cp_radioapp_section3_header |
++----------------------------------+
+| xran_cp_radioapp_section3        |
++----------------------------------+
+| ……                               |
++----------------------------------+
+| xran_cp_radioapp_section3        |
++----------------------------------+
+
+Section Type 5 Structure
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Figure 22 describes the structure of Section Type 5.
+
+.. image:: images/Section-Type-5-Structure.jpg
+  :width: 600
+  :alt: Figure 22.   Section Type 5 Structure
+
+Figure 22.   Section Type 5 Structure
+
+
+Section Type 6 Structure
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Figure 23 describes the structure of Section Type 6.
+
+.. image:: images/Section-Type-6-Structure.jpg
+  :width: 600
+  :alt: Figure 23. Section Type 6 Structure
+
+Figure 23. Section Type 6 Structure
+
diff --git a/docs/build_prerequisite.rst b/docs/build_prerequisite.rst
new file mode 100644 (file)
index 0000000..040d133
--- /dev/null
@@ -0,0 +1,157 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+Build Prerequisite
+====================
+
+.. contents::
+    :depth: 3
+    :local:
+    
+This section describes how to install and build the required components needed to build the FHI Library, WLS Library and the 5G FAPI TM modules.
+
+Install ICC
+------------
+Intel® C++ Compiler v19.0.3 is used for the test application and system integration with L1, 
+The Intel® C++ Compiler can be obtained using the follwoing link https://software.intel.com/en-us/system-studio/choose-download with community |br|
+license::
+
+         COPY $icc_license_file $BUILD_DIR/license.lic
+    
+*Note: The version available at this link is always the latest ICC version, the verification for that version may not have been 
+performed yet, so please provide feedback through O-DU Low project WIKI page if you face any issues.*
+
+
+Download Intel System Studio from Intel website and install ICC ::
+
+         #wget https://registrationcenter-download.intel.com/akdlm/irc_nas/16242/system_studio_2020_ultimate_edition_offline.tar.gz 
+         #cd /opt && mkdir intel && cp $BUILD_DIR/license.lic intel/license.lic
+         #tar -zxvf $BUILD_DIR/system_studio_2020_ultimate_edition_offline.tar.gz
+
+Edit system_studio_2020_ultimate_edition_offline/silent.cfg to accept the EULA file as below example::
+  
+         ACCEPT_EULA=accept
+         PSET_INSTALL_DIR=opt/intel
+         ACTIVATION_LICENSE_FILE=/opt/intel/license.lic
+         ACTIVATION_TYPE=license_file
+    
+Silent installation::
+
+         #./install.sh -s silent.cfg
+
+Set env for ICC::
+         #source /opt/intel/system_studio_2020/bin/iccvars.sh intel64
+         #export PATH=/opt/intel/system_studio_2020/bin/:$PATH
+
+
+Build DPDK
+-----------
+   - download FEC SDK lib::
+   
+         #wget https://software.intel.com/sites/default/files/managed/23/b8/FlexRAN-FEC-SDK-19-04.tar.gz
+         #tar -xzvf FlexRAN-FEC-SDK-19-04.tar.gz
+
+   - build FEC SDK lib::
+        
+         #./FlexRAN-FEC-SDK-19-04.sh
+         #cd FlexRAN-FEC-SDK-19-04/sdk
+         #./create-makefiles-linux.sh
+         #cd build-avx512-icc
+         #make;make install
+
+   *note: you need to accept the Intel OBL commercial use license during the installation*
+
+   - download DPDK::
+     
+         #wget http://fast.dpdk.org/rel/dpdk-18.08.tar.xz
+         #tar -xf dpdk-18.08.tar.xz
+         #export RTE_TARGET=x86_64-native-linuxapp-icc
+         #export RTE_SDK=Intallation_DIR/dpdk-18.08
+
+
+   - patch DPDK for O-RAN FHI lib, this patch is specific for O-RAN FHI to reduce the data transmission latency of Intel NIC. This may not be needed for some NICs, please refer to O-RAN FHI Lib Introduction -> setup configuration -> A.2 prerequisites
+
+
+   - change DPDK config to enable SW FEC support
+
+     check the configuration as below in dpdk-18.08/config/common_base::
+     
+         CONFIG_RTE_LIBRTE_BBDEV=y
+         CONFIG_RTE_LIBRTE_BBDEV_DEBUG=n
+         CONFIG_RTE_BBDEV_MAX_DEVS=128
+         CONFIG_RTE_BBDEV_OFFLOAD_COST=y
+         CONFIG_RTE_BBDEV_SDK_AVX2=y
+         CONFIG_RTE_BBDEV_SDK_AVX512=y
+
+   - enable FEC accelerator card, DPDK BBDev framework support any kind of accelerator card to plug in the associated driver while using the same interface. Right now there is no open source driver available yet, so you need to get the associated vendor's driver to enable the capability to use an accelerator card. 
+
+   - enable IGB UIO for FEC card and NIC configure::
+   
+         CONFIG_RTE_EAL_IGB_UIO=y
+         CONFIG_RTE_KNI_KMOD=y
+
+   - build DPDK
+      setup Env for BBDev SW::
+
+        #export FLEXRAN_SDK=$Intallation_DIR/FlexRAN-FEC-SDK-19-04/sdk/build-avx512-icc/install
+
+      build DPDK::
+
+        #./usertools/dpdk-setup.sh
+        select [16] x86_64-native-linuxapp-icc
+        select [19] Insert VFIO module
+        exit   [35] Exit Script
+   - set DPDK path
+     this path should be always there during you build and run lib/app::
+
+        #export RTE_SDK="your DPDK path"
+
+
+Install google test
+-------------------
+Download google test from https://github.com/google/googletest/releases 
+   - Example build and installation commands::
+
+        #tar -xvf googletest-release-1.7.0.tar.gz
+        #mv googletest-release-1.7.0 gtest-1.7.0
+        #export GTEST_DIR=YOUR_DIR/gtest-1.7.0
+        #cd ${GTEST_DIR}
+        #g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} -pthread -c ${GTEST_DIR}/src/gtest-all.cc
+        #ar -rv libgtest.a gtest-all.o
+        #cd ${GTEST_DIR}/build-aux
+        #cmake ${GTEST_DIR}
+        #make
+        #cd ${GTEST_DIR}
+        #ln -s build-aux/libgtest_main.a libgtest_main.a
+
+- Set the google test Path
+   this path should be always here when you build and run O-RAN FH lib unit test::
+
+        #export DIR_ROOT_GTEST="your google test path"
+
+
+Configure FEC card
+--------------------
+For the Bronze Release only as SW FEC is available so this step is not needed, for later releases the required information will be added to the document.
+
+
+
+
+
+
index 7374c80..2fb4530 100644 (file)
@@ -1,3 +1,3 @@
 ---
 project_cfg: oran
-project: o-du-phy
+project: o-du-low
diff --git a/docs/fapi_5g_tm_build.rst b/docs/fapi_5g_tm_build.rst
new file mode 100644 (file)
index 0000000..da40ad8
--- /dev/null
@@ -0,0 +1,162 @@
+..    Copyright (c) 2019-2020 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br /> 
+   
+ORAN 5G FAPI TM Installation Guide
+==================================
+
+The 5G FAPI TM uses the wls library which uses DPDK as the basis for the shared memory operations 
+and requires that DPDK 
+be installed in the system since in the makefile it uses the RTE_SDK environment variable when
+building the library. |br|
+The current release was tested using DPDK version 18.08 but it doesn't preclude the 
+use of newer releases. |br|
+Also the 5G FAPI TM currently uses the Intel Compiler that is defined as part of the ODULOW documentation.
+
+Contents
+--------
+
+- Overview
+- Building and Installation
+- Command Line Parameters
+- Known Issues/Troubleshooting
+- License
+
+
+================================================================================
+
+Overview
+--------
+
+This document describes how to install and build the 5G FAPI TM for ODULOW to ODUHIGH
+communication as part of the |br|
+ORAN Reference Architecture.
+
+
+================================================================================
+
+
+Building and Installation
+-------------------------
+
+Retrieve the source files from the Linux Foundation Gerrit server:
+    `<https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=summary>`_
+
+1. Make sure that the follwoing environment variables are defined
+   DIR_WIRELESS_WLS for the wls_lib and RTE_SDK for the DPDK |br|
+2. cd fapi_5g/build |br|
+3. $ ./build.sh xclean  // Force full rebuild |br|
+4. $ ./build.sh         // Build the 5G FAPI TM |br|
+
+The executable is available at fapi_5g/bin and it is called oran_5g_fapi
+
+Unit Test and validation
+---------------------------------
+
+The unit test for the ORAN 5G FAPI TM requires the testmac and L1 binaries that are described
+in a later section and that for the Bronze Release consists of 15 basic tests in timer mode
+where the DL, UL and FD paths are exercised for different channel types and numerology 0 and 1.
+
+1.Open SSH session and cd l1\bin\nr5g\gnb\l1 |br|
+2.Issue l1.sh |br|
+3.Open a second SSH session and cd fapi_5g\bin |br|
+4.Issue ./oran_5g_fapi.sh --cfg oran_5g_fapi.cfg |br|
+5.Open a third SSH session and cd l1\bin\nr5g\gnb\testmac |br|
+6.Issue ./l2.sh |br|
+7.From the testmac command prompt (i.e. the l2 executable) issue::
+run Direction Numerology Bandwidth TestCase
+where Direction is 0 DL, 1 UL and 2 FD
+Numerology 0 15 Khz, 1 30 Khz, 2 60 KHz, etc
+Bandwidth is 5, 10 , 20, 100 
+Testcase is defined from the set supported in this release
+In general issue only the cases provided with this release that have the full set
+of supporting files required. |br|
+8.Observe in the SSH associated with the testmac the PASS/FAIL status. All of the reference cases
+pass.
+
+
+Testmac cases used for 5g FAPI TM
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following DL, UL and PRACH test cases are used for validation.
+
+Downlink Tx Sub6 Test Cases [mu = 0 (15khz) and 5Mhz]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+1.Test case 1001 1 PDSCH and 1 Control symbol
+
+2.Test case 1002 1 PUCCH Format 2 channel
+
+Uplink Rx Sub6 Test Cases [mu = 0 (15khz) and 5Mhz]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+3.Test case 1001 1 PUSCH
+
+4.Test case 1002 1 PUCCH Format 2
+
+Uplink Rx Sub6 Test Cases [mu = 0 (15khz) and 20Mhz]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+5.Test case 1002 1 PRACH
+
+6.Test case 1003 1 PRACH
+
+
+PDSCH {QAM256, mcs28, 272rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM64, mcs28, 248rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+7.TEST_FD, 1300, 1, fd/mu1_100mhz/300/fd_testconfig_tst300.cfg
+
+PDSCH {QAM64, mcs16, 272rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM16, mcs16, 248rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+8.TEST_FD, 1301, 1, fd/mu1_100mhz/301/fd_testconfig_tst301.cfg
+
+PDSCH {QAM16, mcs9, 272rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QPSK, mcs9, 248rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+9.TEST_FD, 1302, 1, fd/mu1_100mhz/302/fd_testconfig_tst302.cfg
+
+PDSCH {QAM256, mcs28, 190rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM64, mcs28, 190rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+10.TEST_FD, 1303, 1, fd/mu1_100mhz/303/fd_testconfig_tst303.cfg
+
+PDSCH {QAM64, mcs16, 190rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM16, mcs16, 190rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+11.TEST_FD, 1304, 1, fd/mu1_100mhz/304/fd_testconfig_tst304.cfg
+
+PDSCH {QAM16, mcs9, 190rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QPSK, mcs9, 190rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+12.TEST_FD, 1305, 1, fd/mu1_100mhz/305/fd_testconfig_tst305.cfg
+
+PDSCH {QAM256, mcs28, 96rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM64, mcs28, 96rbs, 14symbols, 2Layers, 16UE/TTI}, 94 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+13.TEST_FD, 1306, 1, fd/mu1_100mhz/306/fd_testconfig_tst306.cfg
+
+PDSCH {QAM64, mcs16, 96rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM16, mcs16, 96rbs, 14symbols, 2Layers, 16UE/TTI}, 94 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+14.TEST_FD, 1307, 1, fd/mu1_100mhz/307/fd_testconfig_tst307.cfg
+
+PDSCH {QAM16, mcs9, 96rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QPSK, mcs9, 96rbs, 14symbols, 2Layers, 16UE/TTI}, 94 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+15.TEST_FD, 1308, 1, fd/mu1_100mhz/308/fd_testconfig_tst308.cfg
\ No newline at end of file
diff --git a/docs/fapi_5g_tm_overview.rst b/docs/fapi_5g_tm_overview.rst
new file mode 100644 (file)
index 0000000..4fc163c
--- /dev/null
@@ -0,0 +1,156 @@
+..    Copyright (c) 2020 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+
+.. |br| raw:: html
+
+   <br />
+
+O-RAN FAPI 5G TM Introduction
+=============================
+
+.. contents::
+    :depth: 3
+    :local:
+
+The ORAN FAPI 5G Translator Module (TM) is a standalone application that communicates with the ODU-High using the 5G FAPI protocol defined
+by the Small Cell Forum and communicates with the ODU Low using the Intel L2-L1 API using the Wireless Subsystem Interface
+Library (WLS) to handle the shared memory and buffer management required by the |br|
+Interfaces. In addition the ORAN 5G FAPI TM requires the
+Data Plane Design Kit (DPDK) which is integrated with the WLS Library.
+
+Table 1. Terminology
+
++----------+----------------------------------------------------------+
+| Term     | Description                                              |
++----------+----------------------------------------------------------+
+| API      | Application Platform Interface                           |
++----------+----------------------------------------------------------+
+| BBU      | Baseband Unit                                            |
++----------+----------------------------------------------------------+
+| CORESET  | Control Resource Set                                     |
++----------+----------------------------------------------------------+
+| DOS      | Denial of Service Attack                                 |
++----------+----------------------------------------------------------+
+| DPDK     | Data Plane Design Kit                                    |
++----------+----------------------------------------------------------+
+| eNb      | Enode B                                                  |
++----------+----------------------------------------------------------+
+| EPC      | Evolved Packet Core                                      |
++----------+----------------------------------------------------------+
+| EVM      | Error Vector magnitude                                   |
++----------+----------------------------------------------------------+
+| FAPI     | Functional Application Platform Interface                |
++----------+----------------------------------------------------------+
+| gNB      | Next generation eNB or g Node B                          |
++----------+----------------------------------------------------------+
+| IQ       | In-phase and in-quadrature                               |
++----------+----------------------------------------------------------+
+| ISA      | Intel Software Architecture i.e. AVX2, AVX256, AVX512    |
++----------+----------------------------------------------------------+
+| MAC      | Medium Access Control                                    |
++----------+----------------------------------------------------------+
+| MIB      | Master Information Block                                 |
++----------+----------------------------------------------------------+
+| nFAPI    | Network FAPI (Between VNF(L2/L3) and PNF(L1))            |
++----------+----------------------------------------------------------+
+| PDU      | Protocol Data Unit                                       |
++----------+----------------------------------------------------------+
+| PHY      | Physical Layer Processing                                |
++----------+----------------------------------------------------------+
+| PMD      | Poll Mode Driver                                         |
++----------+----------------------------------------------------------+
+| PNF      | Physical Network Function                                |
++----------+----------------------------------------------------------+
+| PSS      | Primary Synchronization Signal                           |
++----------+----------------------------------------------------------+
+| QPSK     | Quadrature Phase Shift Keying                            |
++----------+----------------------------------------------------------+
+| RAN      | Radio Access Network                                     |
++----------+----------------------------------------------------------+
+| RE       | Radio Equipment                                          |
++----------+----------------------------------------------------------+
+| REC      | Radio Equipment Control                                  |
++----------+----------------------------------------------------------+
+| ROE      | Radio Over Ethernet                                      |
++----------+----------------------------------------------------------+
+| RX or Rx | Receive                                                  |
++----------+----------------------------------------------------------+
+| SCF      | Small Cell Forum                                         |
++----------+----------------------------------------------------------+
+| SFN      | System Frame Number ∈ {0,…,1023}                         |
++----------+----------------------------------------------------------+
+| SIB      | System Information Block                                 |
++----------+----------------------------------------------------------+
+| SSS      | Secondary Synchronization Signal                         |
++----------+----------------------------------------------------------+
+| TLV      | Type Length Value                                        |
++----------+----------------------------------------------------------+
+| TX or Tx | Transmit                                                 |
++----------+----------------------------------------------------------+
+| U-Plane  | User Plane                                               |
++----------+----------------------------------------------------------+
+| URLLC    | Ultra Reliable Low Latency Coding                        |
++----------+----------------------------------------------------------+
+| VNF      | Virtual Network Function                                 |
++----------+----------------------------------------------------------+
+| WLS      | Wireless Subsystem Interface                             |
++----------+----------------------------------------------------------+
+| WLS_DPDK | WLS that uses DPDK functions instead of accessing kernel |
+|          | functions                                                |
++----------+----------------------------------------------------------+
+
+
+Reference Documents
+-------------------
+
+Table 2. Reference Documents
+
++-------------------------------------+-------------------------------+
+| Document                            | Document                      |
+|                                     | No./Location                  |
++-------------------------------------+-------------------------------+
+| 1) FlexRAN 5G New Radio Reference   | CDI 603575   Intel Corp.      |
+|    Solution L1-L2 API Specification |                               |
+|    July 2019                        |                               |
++-------------------------------------+-------------------------------+
+| 2) 5G FAPI:PHY API Specification,   | 222.10.02/ smallcellforum.org |
+|    Version 1.0.5, March 2020        |                               |
++-------------------------------------+-------------------------------+
+
+
+Translator Module Top Level Design
+==================================
+
+The following diagram illustrates the different functions and components
+used by this module and how it interconnects to the L2 and L1 layers.
+
+Figure 1. ORAN 5G FAPI Translator Module Top Level Architecture
+
+
+.. image:: images/fapi_tm_architecture.jpg
+  :width: 900
+  :alt: Figure 1. ORAN 5G FAPI TM
+
+Figure 1. ORAN 5G FAPI TM Top Level Diagram
+
+The Translator Module consists of the following functions:
+
+-  A 5G FAPI Parser facing the L2 interface.
+
+-  An Inter API Mapper and Logic.
+
+-  An Intel API Parser facing the L1 interface.
+
+-  WLS dpdk based library supporting 2 instances.
diff --git a/docs/fapi_5g_tm_rel-notes.rst b/docs/fapi_5g_tm_rel-notes.rst
new file mode 100644 (file)
index 0000000..131e92b
--- /dev/null
@@ -0,0 +1,43 @@
+..    Copyright (c) 2019-2020 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+
+.. |br| raw:: html
+
+   <br />
+   
+ORAN 5G FAPI TM Release Notes
+=============================
+
+Version oran_release_bronze_v1.0, May 2020
+------------------------------------------
+* First release of the 5G FAPI TM to ORAN in support of the Bronze Release
+* This version supports 5G only
+* PARAM.config and PARAM.resp are not supported
+* ERROR.ind relies on the L1 support for error detection as the 5G FAPI TM \
+  only enforces security checks and |br|
+  integrity checks to avoid DOS attacks but \
+  it doesn't perform full validation of the input parameters for compliance to
+  the standard
+* Deviations from the March version of the SCF 5G FAPI document have been \
+  implemented in order to deal with |br|
+  limitations and ommisions found in the
+  current SCF document, these differences are being provided to the SCF for
+  the next document update. The 5G FAPI implementation is defined in the file
+  fapi_interface.h
+* Multi-user MIMO, Beamforming, Precoding and URLLC are not supported in the
+  current implementation as they |br|
+  require additional alignment between the SCF
+  P19 and the ORAN
+* The option for the MAC layer doing the full generation of the PBCH payload is not supported in this release and it will be added in the maintainance release cycle.
\ No newline at end of file
diff --git a/docs/images/Architecture-Block-Diagram.jpg b/docs/images/Architecture-Block-Diagram.jpg
new file mode 100644 (file)
index 0000000..d425fc7
Binary files /dev/null and b/docs/images/Architecture-Block-Diagram.jpg differ
diff --git a/docs/images/Bit-Allocations-of-ecpriRtcid-ecpriPcid.jpg b/docs/images/Bit-Allocations-of-ecpriRtcid-ecpriPcid.jpg
new file mode 100644 (file)
index 0000000..c4755cc
Binary files /dev/null and b/docs/images/Bit-Allocations-of-ecpriRtcid-ecpriPcid.jpg differ
diff --git a/docs/images/C-plane-and-U-plane-Packet-Exchange.jpg b/docs/images/C-plane-and-U-plane-Packet-Exchange.jpg
new file mode 100644 (file)
index 0000000..2ad32b0
Binary files /dev/null and b/docs/images/C-plane-and-U-plane-Packet-Exchange.jpg differ
diff --git a/docs/images/Configuration-C1.jpg b/docs/images/Configuration-C1.jpg
new file mode 100644 (file)
index 0000000..2e8dc48
Binary files /dev/null and b/docs/images/Configuration-C1.jpg differ
diff --git a/docs/images/Configuration-C3.jpg b/docs/images/Configuration-C3.jpg
new file mode 100644 (file)
index 0000000..b60eb53
Binary files /dev/null and b/docs/images/Configuration-C3.jpg differ
diff --git a/docs/images/Data-Flows.jpg b/docs/images/Data-Flows.jpg
new file mode 100644 (file)
index 0000000..0c289cb
Binary files /dev/null and b/docs/images/Data-Flows.jpg differ
diff --git a/docs/images/Data-Payload.jpg b/docs/images/Data-Payload.jpg
new file mode 100644 (file)
index 0000000..f393668
Binary files /dev/null and b/docs/images/Data-Payload.jpg differ
diff --git a/docs/images/Data-Section-Application-Data-Header.jpg b/docs/images/Data-Section-Application-Data-Header.jpg
new file mode 100644 (file)
index 0000000..f7b806a
Binary files /dev/null and b/docs/images/Data-Section-Application-Data-Header.jpg differ
diff --git a/docs/images/Functional-Split.jpg b/docs/images/Functional-Split.jpg
new file mode 100644 (file)
index 0000000..0682934
Binary files /dev/null and b/docs/images/Functional-Split.jpg differ
diff --git a/docs/images/Illustration-of-xRAN-Sublayers.jpg b/docs/images/Illustration-of-xRAN-Sublayers.jpg
new file mode 100644 (file)
index 0000000..9867e37
Binary files /dev/null and b/docs/images/Illustration-of-xRAN-Sublayers.jpg differ
diff --git a/docs/images/Native-Ethernet-Frame-with-VLAN.jpg b/docs/images/Native-Ethernet-Frame-with-VLAN.jpg
new file mode 100644 (file)
index 0000000..d749159
Binary files /dev/null and b/docs/images/Native-Ethernet-Frame-with-VLAN.jpg differ
diff --git a/docs/images/ORAN-Fronthaul-Process.jpg b/docs/images/ORAN-Fronthaul-Process.jpg
new file mode 100644 (file)
index 0000000..703d5e9
Binary files /dev/null and b/docs/images/ORAN-Fronthaul-Process.jpg differ
diff --git a/docs/images/ORAN_OCU_ODU_ORU.jpg b/docs/images/ORAN_OCU_ODU_ORU.jpg
new file mode 100644 (file)
index 0000000..1fc351b
Binary files /dev/null and b/docs/images/ORAN_OCU_ODU_ORU.jpg differ
diff --git a/docs/images/Radio-Application-Common-Header.jpg b/docs/images/Radio-Application-Common-Header.jpg
new file mode 100644 (file)
index 0000000..403ff3a
Binary files /dev/null and b/docs/images/Radio-Application-Common-Header.jpg differ
diff --git a/docs/images/Radio-Application-Header.jpg b/docs/images/Radio-Application-Header.jpg
new file mode 100644 (file)
index 0000000..6442a83
Binary files /dev/null and b/docs/images/Radio-Application-Header.jpg differ
diff --git a/docs/images/Sample-Application-Threads.jpg b/docs/images/Sample-Application-Threads.jpg
new file mode 100644 (file)
index 0000000..6f8c744
Binary files /dev/null and b/docs/images/Sample-Application-Threads.jpg differ
diff --git a/docs/images/Sample-Application.jpg b/docs/images/Sample-Application.jpg
new file mode 100644 (file)
index 0000000..a4d01a6
Binary files /dev/null and b/docs/images/Sample-Application.jpg differ
diff --git a/docs/images/Section-Type-0-Structure.jpg b/docs/images/Section-Type-0-Structure.jpg
new file mode 100644 (file)
index 0000000..0886af6
Binary files /dev/null and b/docs/images/Section-Type-0-Structure.jpg differ
diff --git a/docs/images/Section-Type-1-Structure.jpg b/docs/images/Section-Type-1-Structure.jpg
new file mode 100644 (file)
index 0000000..2c57be7
Binary files /dev/null and b/docs/images/Section-Type-1-Structure.jpg differ
diff --git a/docs/images/Section-Type-3-Structure.jpg b/docs/images/Section-Type-3-Structure.jpg
new file mode 100644 (file)
index 0000000..79576d9
Binary files /dev/null and b/docs/images/Section-Type-3-Structure.jpg differ
diff --git a/docs/images/Section-Type-5-Structure.jpg b/docs/images/Section-Type-5-Structure.jpg
new file mode 100644 (file)
index 0000000..f2dc53b
Binary files /dev/null and b/docs/images/Section-Type-5-Structure.jpg differ
diff --git a/docs/images/Section-Type-6-Structure.jpg b/docs/images/Section-Type-6-Structure.jpg
new file mode 100644 (file)
index 0000000..53a0916
Binary files /dev/null and b/docs/images/Section-Type-6-Structure.jpg differ
diff --git a/docs/images/Setup-for-xRAN-Testing-with-PHY-and-Configuration-C3.jpg b/docs/images/Setup-for-xRAN-Testing-with-PHY-and-Configuration-C3.jpg
new file mode 100644 (file)
index 0000000..782c785
Binary files /dev/null and b/docs/images/Setup-for-xRAN-Testing-with-PHY-and-Configuration-C3.jpg differ
diff --git a/docs/images/Setup-for-xRAN-Testing.jpg b/docs/images/Setup-for-xRAN-Testing.jpg
new file mode 100644 (file)
index 0000000..7aa42ff
Binary files /dev/null and b/docs/images/Setup-for-xRAN-Testing.jpg differ
diff --git a/docs/images/eCPRI-Header-Field-Definitions.jpg b/docs/images/eCPRI-Header-Field-Definitions.jpg
new file mode 100644 (file)
index 0000000..96476eb
Binary files /dev/null and b/docs/images/eCPRI-Header-Field-Definitions.jpg differ
diff --git a/docs/images/eNB-gNB-Architecture-with-O-DU-and-RU.jpg b/docs/images/eNB-gNB-Architecture-with-O-DU-and-RU.jpg
new file mode 100644 (file)
index 0000000..1824195
Binary files /dev/null and b/docs/images/eNB-gNB-Architecture-with-O-DU-and-RU.jpg differ
diff --git a/docs/images/fapi_tm_architecture.jpg b/docs/images/fapi_tm_architecture.jpg
new file mode 100644 (file)
index 0000000..f78ea2e
Binary files /dev/null and b/docs/images/fapi_tm_architecture.jpg differ
diff --git a/docs/images/xRAN-Packet-Components.jpg b/docs/images/xRAN-Packet-Components.jpg
new file mode 100644 (file)
index 0000000..6849324
Binary files /dev/null and b/docs/images/xRAN-Packet-Components.jpg differ
index db26dab..64625fb 100644 (file)
@@ -1,4 +1,4 @@
-..    Copyright (c) 2019 Intel
+..    Copyright (c) 2020 Intel
 ..
 ..  Licensed under the Apache License, Version 2.0 (the "License");
 ..  you may not use this file except in compliance with the License.
 ..  See the License for the specific language governing permissions and
 ..  limitations under the License.
 
+.. ODULOW documentation master
+
+.. _odulow documentation master:
+
+O-RAN O-DU Low
+==============
+
+**User Guide, May 2020**
+  
+.. toctree::
+   :maxdepth: 2
+  
+   overview1.rst
+   Assumptions_Dependencies.rst
+   build_prerequisite.rst   
+
 .. _odulow_phy_fhi_library:
 
 .. fhi library documentation master
@@ -22,10 +38,53 @@ FHI Library
 
 .. toctree::
    :maxdepth: 2
-   :caption: Contents:
 
    overview.rst
-   installation-guide.rst
+   Introduction_fh.rst
    release-notes.rst
 
 * :ref:`search`
+
+WLS Library
+===========
+
+.. toctree::
+   :maxdepth: 2
+   
+   wls-lib.rst
+   wls-lib-installation-guide.rst
+   wls-lib-release-notes.rst
+* :ref:`search` 
+
+FAPI 5G TM
+==========
+
+.. toctree::
+   :maxdepth: 2
+
+   fapi_5g_tm_overview.rst
+   fapi_5g_tm_build.rst
+   fapi_5g_tm_rel-notes.rst
+
+* :ref:`search`
+
+Running L1 and TESTMAC
+======================
+
+.. toctree::
+   :maxdepth: 2
+
+   run_l1.rst
+
+* :ref:`search`
+
+Test Cases for the Bronze Release
+=================================
+
+.. toctree::
+   :maxdepth: 2
+
+   test_cases.rst
+
+* :ref:`search`
index 20d4c7a..5f117d0 100644 (file)
 ..  See the License for the specific language governing permissions and
 ..  limitations under the License.
 
+.. |br| raw:: html
+
+   <br />
+
 Front Haul Interface Library Overview
 =====================================
 
 The O-RAN FHI Lib is built on top of DPDK to perform U-plane and C-plane functions according to the 
-ORAN Fronthaul Interface specification between O-DU and O-RU.
-S-Plane support requires PTP for Linux version 2.0 or later
+ORAN Fronthaul |br|
+Interface specification between O-DU and O-RU.
+S-Plane support requires PTP for Linux version 2.0 or later |br|
 The management plane is outside of the scope of this library implementation.
 
 
@@ -25,18 +30,15 @@ Project Resources
 -----------------
 
 The source code is available from the Linux Foundation Gerrit server:
-    `<https://gerrit.o-ran-sc.org/r/a/o-du/phy/fhi_lib/src>`_
+    `<https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=summary>`_
  
 The build (CI) jobs will be in the Linux Foundation Jenkins server:
-
     `<https://jenkins.o-ran-sc.org>`_
 
 Issues are tracked in the Linux Foundation Jira server:
-
     `<https://jira.o-ran-sc.org/secure/Dashboard.jspa>`_
 
 Project information is available in the Linux Foundation Wiki:
-
     `<https://wiki.o-ran-sc.org>`_
 
 
diff --git a/docs/overview1.rst b/docs/overview1.rst
new file mode 100644 (file)
index 0000000..fecd348
--- /dev/null
@@ -0,0 +1,166 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+O-DU Low Project Introduction
+================================
+
+.. contents::
+    :depth: 3
+    :local:
+
+The O-DU low project focus on the baseband PHY Reference Design, which uses Xeon® series Processor with Intel |br|
+Architecture. This 5GNR Reference PHY consists of a L1 binary \
+and three kinds of interfaces which are validated on a |br|
+Intel® Xeon® SkyLake / CascadeLake platforms and demonstrates the capabilities of the software running different \
+5GNR L1 features. It implements the relevant functions described in [3GPP TS 38.211, 212, 213, 214 and 215].
+The L1 has three \ 
+interfaces to communicate with other network functions as described below:
+
+* Interface between L1 and Front Haul, it adopts the WG4 specification for the CUS plane communication. 
+
+* Interface between O-DU Low and O-DU High, it adopts the FAPI interface according to the WG8 AAL specification.
+
+* Interface between O-DU Low and accelerator, DPDK BBDev was adopted as original contribution, it will follow the WG6 definition after the WG6 specification is finalized. 
+
+The following figure shows the ORAN O-CU, O-DU and O-RU blocks for a gNB implemetation. The O-DU Low projects implements the FAPI interface by a 5G FAPI TM module, the OFH-U and OFH-C
+by means of the FHI Library and the functionality of the High-PHY and a test MAC are available through github in the form of a binary blob for the current release. For the details refer to the Running L1 and Testmac section of this document 
+
+
+.. image:: images/ORAN_OCU_ODU_ORU.jpg
+   :width: 600
+   :alt: Figure1.Oran OCU ODU and ORU Block Diagram
+   
+Scope
+-----
+
+In this O-DU Low document, the details on how the build the modules supporting each interface, how to run the L1 and associated components, the architecture for each
+interface implementation and the release notes that describe each component release details are provided.
+
+Intended Audience
+-------------------
+
+The intended audience for this document are software engineers and system architects who design and develop |br|
+5G systems using the O-RAN Specifications.
+
+Terminology
+-------------
+
+Table 1. Terminology
+
++--------+------------------------------------------------------------+
+| Term   | Description                                                |
++--------+------------------------------------------------------------+
+| 5G NR  | Fifth Generation New Radio                                 |
++--------+------------------------------------------------------------+
+| BOM    | Bill of Materials                                          |
++--------+------------------------------------------------------------+
+| CP     | Cyclic Prefix                                              |
++--------+------------------------------------------------------------+
+| DPDK   | Data Plane Development Kit                                 |
++--------+------------------------------------------------------------+
+| gNB    | Next-generation NodeB also named as Base Station           |
++--------+------------------------------------------------------------+
+| HARQ   | Hybrid Automatic Repeat Request                            |
++--------+------------------------------------------------------------+
+| HW     | Hardware                                                   |
++--------+------------------------------------------------------------+
+| IOT    | Inter-Operability Testing                                  |
++--------+------------------------------------------------------------+
+| IQ     | In-band and Quadrature                                     |
++--------+------------------------------------------------------------+
+| NIC    | Network Interface Controller                               |
++--------+------------------------------------------------------------+
+| O-DU   | O-RAN Distributed Unit: a logical node hosting             |
+|        | RLC/MAC/High-PHY layers based on a lower layer functional  |
+|        | split.                                                     |
++--------+------------------------------------------------------------+
+| O-RU   | O-RAN Radio Unit: a logical node hosting Low-PHY layer and |
+|        | RF processing based on a lower layer functional split.     |
+|        | This is similar to 3GPP’s “TRP” or “RRH” but more specific |
+|        | in including the Low-PHY layer (FFT/IFFT, PRACH            |
+|        | extraction).                                               |
++--------+------------------------------------------------------------+
+| PDCCH  | Physical Downlink Control Channel                          |
++--------+------------------------------------------------------------+
+| PDSCH  | Physical Downlink Shared Channel                           |
++--------+------------------------------------------------------------+
+| PRACH  | Physical Random Access Channel                             |
++--------+------------------------------------------------------------+
+| PUCCH  | Physical Uplink Control Channel                            |
++--------+------------------------------------------------------------+
+| PUSCH  | Physical Uplink Shared Channel                             |
++--------+------------------------------------------------------------+
+| PTP    | Precision Time Protocol                                    |
++--------+------------------------------------------------------------+
+| RA     | Random Access                                              |
++--------+------------------------------------------------------------+
+| RAN    | Radio Access Network                                       |
++--------+------------------------------------------------------------+
+| RB     | Resource Block                                             |
++--------+------------------------------------------------------------+
+| RE     | Resource Element                                           |
++--------+------------------------------------------------------------+
+| RU     | Radio Unit                                                 |
++--------+------------------------------------------------------------+
+| SR-IOV | Single Root Input/Output Virtualization                    |
++--------+------------------------------------------------------------+
+| SW     | Software                                                   |
++--------+------------------------------------------------------------+
+| ToS    | Top of the Second                                          |
++--------+------------------------------------------------------------+
+| UE     | User Equipment                                             |
++--------+------------------------------------------------------------+
+| UL     | Uplink                                                     |
++--------+------------------------------------------------------------+
+| VIM    | Virtual Infrastructure Manager                             |
++--------+------------------------------------------------------------+
+| VLAN   | Virtual Local Area Network                                 |
++--------+------------------------------------------------------------+
+| xRAN   | Extensible Radio Access Network                            |
++--------+------------------------------------------------------------+
+
+Reference Documents
+-------------------
+
+Table 2. Reference Documents
+
++----------------------------------+----------------------------------+
+| Document or Reference            | Document No./                    |
+|                                  | Location                         |
++----------------------------------+----------------------------------+
+| 3GPP\* specification series      | http://www.3                     |
+|                                  | gpp.org/DynaReport/38-series.htm |
++----------------------------------+----------------------------------+
+| Wolf Pass Server Documentation   | https://ark.intel.com/p          |
+|                                  | roducts/codename/80739/Wolf-Pass |
++----------------------------------+----------------------------------+
+| *Intel® C++ Compiler             |https://software.intel.com/en-us/ |
+| system Studio XE*                |system-studio/choose-download     |
++----------------------------------+----------------------------------+
+| DPDK documentation               | http://dpdk.org/doc/guides/      |
++----------------------------------+----------------------------------+
+| O-RAN Fronthaul Working Group    | `https://www.o-ran.org/          |
+| Control, User and                | specifications <https://         |
+| Synchronization Plane            | www.o-ran.org/specifications>`__ |
+| Specification                    |                                  |
+| (ORAN-WG4.CUS.0-v02.00)          |                                  |
++----------------------------------+----------------------------------+
+
+
+
index deccb60..0e3c67d 100644 (file)
 ..  See the License for the specific language governing permissions and
 ..  limitations under the License.
 
+.. |br| raw:: html
+
+   <br /> 
+   
 Front Haul Interface Library Release Notes
 ==========================================
 
+Version ORAN-seedcode_v1.3, May 2020
+--------------------------------------
+
+* Third version released to ORAN in support of Release B
+* Add scripts to run refPHY in Docker* containers, Kubernetes* clusters, Multus*, and Data Plane
+  Development Kit-Single-Root Input/Output Visualization (DPDK-SRIOV) plugin.
+* Integration and optimization of block floating point compression and decompression.
+* Category B support
+* Add support for alpha and beta value when calculating SFN based on GPS time.
+* Support End to End integration with commercial UE with xRAN/ORAN RRU for both mmWave and
+  sub-6 scenarios
+
 Version ORAN-seedcode_v1.2, 1 Nov 2019
 --------------------------------------
 * Second version released to ORAN in support of Release A
 * Incorporates support for 5G NR sub 6 and mmWave
 * Support for Application fragementation under Transport features was added
-* This release has been designed and implemented to support the following numerologies defined in the 3GPP specification 
+* This release has been designed and implemented to support the following numerologies defined in the 3GPP |br|
+  specification 
 *      Numerology 0 with bandwidth 5/10/20 MHz with up to 12 cells
 *      Numerology 1 with bandwidth 100MHz with up to 1 cell
 *      Numerology 3 with bandwidth 100MHz with up to 1 cell
diff --git a/docs/run_l1.rst b/docs/run_l1.rst
new file mode 100644 (file)
index 0000000..2f1d6d6
--- /dev/null
@@ -0,0 +1,113 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+Run L1
+======
+
+.. contents::
+    :depth: 3
+    :local:
+
+For the Bronze release, the L1 only has a binary image as well as the testmac which is an L2 test application, details of the L1 and testmac application are in https://github.com/intel/FlexRAN
+
+Download L1 and testmac
+------------------------
+
+Download L1 and testmac through https://github.com/intel/FlexRAN
+
+
+Run L1 with testmac
+--------------------
+Three console windows are needed, one for L1 app, one for FAPI TM, one for testmac. They need to run in the following order L1-> FAPI TM-> testmac. |br|
+In each console window, the environment needs to be set using a shell script of example::
+
+       #source ./setupenv.sh
+
+* Run L1 under folder FlexRAN/l1/bin/nr5g/gnb/l1 in timer mode using::
+
+     #l1.sh -e
+
+**Note** that the markups dpdkBasebandFecMode and dpdkBasebandDevice needs to be adjusted in the relevant phycfg.xml under folder |br|
+ FlexRAN/l1/bin/nr5g/gnb/l1 before starting L1. |br|
+ dpdkBasebandFecMode = 0 for LDPC Encoder/Decoder in software. |br|
+ dpdkBasebandFecMode = 1 for LDPC Encoder/Decoder in FPGA. (Not supported in the Bronze Release for the Open Source Community) |br|
+
+* Run FAPI TM under folder phy/fapi_5g/bin::
+
+     #./oran_5g_fapi.sh --cfg=oran_5g_fapi.cfg
+
+* Run testmac under folder FlexRAN/l1/bin/nr5g/gnb/testmac::
+
+     #./l2.sh
+
+Once the application comes up, you will see a *<TESTMAC>* prompt. The same Unit tests can be run using the command:
+
+- **run   testtype   numerology   bandwidth   testnum** where
+
+- **testtype** is 0 (DL), 1 (UL) or 2 (FD)
+
+- **numerology** [0 -> 4], 0=15khz, 1=30khz, 2=60khz, 3=120khz, 4=240khz
+
+- **bandwidth** 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 400 (in Mhz)
+
+- **testnum** is the Bit Exact TestNum. [1001 -> above]If this is left blank, then all tests under type testtype are run
+
+testnum is always a 4 digit number. First digit represents the number of carriers to run.
+For example, to run Test Case 5 for Uplink Rx mu=3, 100Mhz for 1 carrier, the command would be:
+run 1 3 100 1005
+All the pre-defined test cases for the Bronze Release are defined in the Test Cases section in https://github.com/intel/FlexRAN and also in the Test |br|
+Cases section of this document.
+If user wants to run more slots (than specified in test config file) or change the mode or change the TTI interval of the test, then the command phystart can be used as follows:
+
+- **phystart   mode   interval   num_tti**
+
+- **mode** is 0 (Radio) or 1 (Timer)
+
+- **interval** is the TTI duration scaled as per Numerology (only used in timer mode).
+
+    - So if Numerology is 3 and this parameter is set to 1, then the interval will be programmed to 0.125 ms.
+    
+    - If this is set to 10, then interval is programmed to 1.25ms
+    
+- **num_tti** is the total number of TTIs to run the test.
+
+    - If 0, then the test config file defines how many slots to run.
+    
+    - If a non zero number, then test is run for these many slots.
+    
+    - If the num_tti is more than the number of slots in config file, then the configuration is repeated till end of test.
+    
+    - So if num_tti=200 and num_slot from config file is 10, then the 10 slot configs are repeated 20 times in a cyclic fashion.
+    
+- The default mode set at start of testmac is (phystart 1 10 0). So it is timer mode at 10ms TTI intervals running for duration specified in each test config file
+
+- Once user manually types the phystart command on the l2 console, then all subsequent tests will use this phystart config till user changes it or testmac is restarted.
+
+- If user wants to run a set of tests which are programmed in a cfg file (for example tests_customer.cfg):
+     ./l2.sh –testfile=tests_customer.cfg
+
+   example::
+
+      #./l2.sh --testfile=oran_bronze_rel_fec_sw.cfg
+
+- This will run all the tests that are listed in the config file. Please see the tests_customer.cfg present in the release for example of how to program the tests 
+
+
+
+
+
diff --git a/docs/test_cases.rst b/docs/test_cases.rst
new file mode 100644 (file)
index 0000000..f393954
--- /dev/null
@@ -0,0 +1,102 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+
+.. |br| raw:: html
+
+   <br />
+   
+Test Cases
+============
+
+.. contents::
+    :depth: 3
+    :local:
+
+This section describes the downlink, uplink and full duplex bit exact test cases that are present as part of the Bronze |br|
+release. All the test config files, IQ samples and reference Inputs are placed under the FlexRAN/testcase folder. These test config files are used for testmac.
+
+There are 3 kinds of tests: dl, ul, and fd. The following test cases are part of the Bronze Release and reside in the github repo mentioned earlier in this document.
+
+Downlink Tx Sub6 Test Cases [mu = 0 (15khz) and 5Mhz]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**Test case 1001 1 PDSCH and 1 Control symbol**
+
+**Test case 1002 1 PUCCH Format 2 channel**
+
+Uplink Rx Sub6 Test Cases [mu = 0 (15khz) and 5Mhz]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**Test case 1001 1 PUSCH**
+
+**Test case 1002 1 PUCCH Format 2**
+
+Uplink Rx Sub6 Test Cases [mu = 0 (15khz) and 20Mhz]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**Test case 1002 1 PRACH**
+
+**Test case 1003 1 PRACH**
+
+PDSCH {QAM256, mcs28, 272rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM64, mcs28, 248rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1300, 1, fd/mu1_100mhz/300/fd_testconfig_tst300.cfg**
+
+PDSCH {QAM64, mcs16, 272rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM16, mcs16, 248rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1301, 1, fd/mu1_100mhz/301/fd_testconfig_tst301.cfg**
+
+PDSCH {QAM16, mcs9, 272rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QPSK, mcs9, 248rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1302, 1, fd/mu1_100mhz/302/fd_testconfig_tst302.cfg**
+
+PDSCH {QAM256, mcs28, 190rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM64, mcs28, 190rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1303, 1, fd/mu1_100mhz/303/fd_testconfig_tst303.cfg**
+
+PDSCH {QAM64, mcs16, 190rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM16, mcs16, 190rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1304, 1, fd/mu1_100mhz/304/fd_testconfig_tst304.cfg**
+
+PDSCH {QAM16, mcs9, 190rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QPSK, mcs9, 190rbs, 14symbols, 2Layers, 16UE/TTI}, 189 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1305, 1, fd/mu1_100mhz/305/fd_testconfig_tst305.cfg**
+
+PDSCH {QAM256, mcs28, 96rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM64, mcs28, 96rbs, 14symbols, 2Layers, 16UE/TTI}, 94 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1306, 1, fd/mu1_100mhz/306/fd_testconfig_tst306.cfg**
+
+PDSCH {QAM64, mcs16, 96rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QAM16, mcs16, 96rbs, 14symbols, 2Layers, 16UE/TTI}, 94 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1307, 1, fd/mu1_100mhz/307/fd_testconfig_tst307.cfg**
+
+PDSCH {QAM16, mcs9, 96rbs, 12symbols, 4Layers, 16UE/TTI}, PUSCH {QPSK, mcs9, 96rbs, 14symbols, 2Layers, 16UE/TTI}, 94 PUCCH and PRACH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**TEST_FD, 1308, 1, fd/mu1_100mhz/308/fd_testconfig_tst308.cfg**
+
+
+
+
+
+
diff --git a/docs/wls-lib-installation-guide.rst b/docs/wls-lib-installation-guide.rst
new file mode 100644 (file)
index 0000000..1cb6c56
--- /dev/null
@@ -0,0 +1,105 @@
+..    Copyright (c) 2019-2020 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br /> 
+   
+Wls Lib Installation Guide
+==========================
+
+The wls library uses DPDK as the basis for the shared memory operations and requires that DPDK 
+be installed in the system since in the makefile it uses the RTE_SDK environment variable when
+building the library. |br|
+The current release was tested using DPDK version 18.08 but it doesn't preclude the 
+use of newer releases. |br|
+Also the library uses the Intel Compiler that is defined as part of the ODULOW documentation.
+
+Contents
+--------
+
+- Overview
+- Building and Installation
+- Command Line Parameters
+- Known Issues/Troubleshooting
+- License
+
+
+================================================================================
+
+Overview
+--------
+
+This document describes the wls DPDK base library for ODULOW to ODUHIGH
+communication as part of the |br|
+ORAN Reference Architecture where an intermediate
+shin layer can be present between these components.
+
+
+================================================================================
+
+
+Building and Installation
+-------------------------
+
+Retrieve the source files from the Linux Foundation Gerrit server:
+    `<https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=summary>`_
+
+1. cd wls_lib
+2. wls_lib$ ./build.sh xclean
+3. wls_lib$ ./build.sh
+
+The shared library is available at wls_lib/lib
+
+This library is used by the ODUHIGH, shin layer implementing a 5G FAPI to IAPI translator and the 
+ODULOW components.
+
+Please define an environment variable DIR_WIRELESS_WLS with the path to the root folder of
+the wls_lib as it is needed for the fapi_5g build process.
+
+Unit Test building and validation
+---------------------------------
+
+In order to build the unit test do the following steps:
+
+1. cd test
+2. ./build.sh xclean
+3. ./build.sh
+4. Create an SSH session into the target an change directory to wls_lib/bin/phy
+5. issue ./phy.sh
+6. Create a second SSH session into the target and change directory to wls_lib/bin/fapi
+7. issue ./fapi.sh
+8. Create a third SSH session into the target and change directory to wls_lib/bin/mac
+9. issue ./mac.sh
+
+After the test run you should see that each module sent and receive 16 messages from
+the display status messages.
+
+================================================================================
+
+
+
+Known Issues/Troubleshooting
+----------------------------
+No known issues.
+For troubleshooting use unit test application.
+
+================================================================================
+
+License
+-------
+
+Please see License.txt at the root of the phy repository for license information details
+
+
diff --git a/docs/wls-lib-release-notes.rst b/docs/wls-lib-release-notes.rst
new file mode 100644 (file)
index 0000000..22dbc13
--- /dev/null
@@ -0,0 +1,21 @@
+..    Copyright (c) 2019-2020 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+WLS Library Release Notes
+=========================
+
+Version oran_release_bronze_v1.0, May 2020
+------------------------------------------
+* First release of the wls library to ORAN in support of the Bronze Release
+* This version supports both single and dual instances using a single Open function
diff --git a/docs/wls-lib.rst b/docs/wls-lib.rst
new file mode 100644 (file)
index 0000000..12c303c
--- /dev/null
@@ -0,0 +1,76 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br /> 
+   
+Wls Lib Overview
+================
+
+The Wls_lib is a Wireless Service library that supports shared memory and buffer management used by applications |br| 
+implementing a gNb or eNb. |br|
+This library uses DPDK, libhugetlbfs and pthreads to provide memcpy less data exchange between an L2 application, |br|
+API Translator Module and a L1 application by sharing the same memory zone from the DPDK perspective.
+
+Project Resources
+-----------------
+
+The source code is avalable from the Linux Foundation Gerrit server:
+    `<https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=summary>`_
+    
+The build (CI) jobs will be in the Linux Foundation Jenkins server:
+    `<https://jenkins.o-ran-sc.org>`_
+
+Issues are tracked in the Linux Foundation Jira server:
+    `<https://jira.o-ran-sc.org/secure/Dashboard.jspa>`_
+
+Project information is available in the Linux Foundation Wiki:
+    `<https://wiki.o-ran-sc.org>`_
+    
+
+Library Functions
+-----------------
+
+* **WLS_Open() and WLS_Open_Dual()** that open a single or dual wls instance interface and registers the instance with the kernel space driver.
+    
+* **WLS_Close(), WLS_Close1()** closes the wls instance and deregisters it from the kernel space driver.
+
+* **WLS_Ready(), WLS_Ready1()** checks state of remote peer of WLS interface and returns 1 if remote peer is available.
+    
+* **WLS_Alloc()** allocates a memory block for data exchange shared memory. This block uses hugepages.
+
+* **WLS_Free()** frees memory block for data exchange shared memory.
+
+* **WLS_Put(), WLS_Put1()** puts memory block (or group of blocks) allocated from WLS memory into the interface for transfer to remote peer.
+
+* **WLS_Check(), WLS_Check1()** checks if there are memory blocks with data from remote peer and returns number of blocks available for "get" operation.
+
+* **WLS_Get(), WLS_Get1()** gets memory block from interface received from remote peer. Function is a non-blocking operation and returns NULL if no blocks available.
+
+* **WLS_Wait(), WLS_Wait1()** waits for new memory block from remote peer. This Function is a blocking call and returns number of blocks received.
+    
+* **WLS_WakeUp(), WLS_WakeUp1()** performs "wakeup" notification to remote peer to unblock "wait" operations pending.
+
+* **WLS_Get(), WLS_Get1()** gets a memory block from the interface received from remote peer. This Function is blocking operation and waits till next memory block from remote peer.
+
+* **WLS_VA2PA()** converts virtual address (VA) to physical address (PA).
+
+* **WLS_PA2VA()** converts physical address (PA) to virtual address (VA).
+
+* **WLS_EnqueueBlock(), WLS_EnqueueBlock1()** This function is used by a master or secondary master to provide memory blocks to a slave for next slave to master (sec master) transfer of data.
+
+* **WLS_NumBlocks()** returns number of current available blocks provided by master for a new transfer of data from the slave.
+
+The **_1()** functions are only needed when using the WLS_Open_Dual().
\ No newline at end of file
diff --git a/docs/xRAN-Library-Design_fh.rst b/docs/xRAN-Library-Design_fh.rst
new file mode 100644 (file)
index 0000000..07e2694
--- /dev/null
@@ -0,0 +1,1692 @@
+..    Copyright (c) 2019 Intel
+..
+..  Licensed under the Apache License, Version 2.0 (the "License");
+..  you may not use this file except in compliance with the License.
+..  You may obtain a copy of the License at
+..
+..      http://www.apache.org/licenses/LICENSE-2.0
+..
+..  Unless required by applicable law or agreed to in writing, software
+..  distributed under the License is distributed on an "AS IS" BASIS,
+..  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+..  See the License for the specific language governing permissions and
+..  limitations under the License.
+
+.. |br| raw:: html
+
+   <br />
+
+xRAN Library Design
+===================
+
+.. contents::
+    :depth: 3
+    :local:
+
+The xRAN Library consists of multiple modules where different
+functionality is encapsulated. The complete list of all \*.c and \*.h
+files as well as Makefile for xRAN (aka FHI Lib Bronze Release) release is:
+
+├──fhi_lib
+
+│   ├── lib
+
+│   │   ├── api
+
+│   │   │   ├── xran_compression.h
+
+│   │   │   ├── xran_compression.hpp
+
+│   │   │   ├── xran_cp_api.h
+
+│   │   │   ├── xran_fh_o_du.h
+
+│   │   │   ├── xran_mlog_lnx.h
+
+│   │   │   ├── xran_pkt_cp.h
+
+│   │   │   ├── xran_pkt.h
+
+│   │   │   ├── xran_pkt_up.h
+
+│   │   │   ├── xran_sync_api.h
+
+│   │   │   ├── xran_timer.h
+
+│   │   │   ├── xran_transport.h
+
+│   │   │   └── xran_up_api.h
+
+│   │   ├── ethernet
+
+│   │   │   ├── ethdi.c
+
+│   │   │   ├── ethdi.h
+
+│   │   │   ├── ethernet.c
+
+│   │   │   └── ethernet.h
+
+│   │   ├── Makefile
+
+│   │   └── src
+
+│   │   │   ├── xran_app_frag.c
+
+│   │   │   ├── xran_app_frag.h
+
+│   │   │   ├── xran_common.c
+
+│   │   │   ├── xran_common.h
+
+│   │   │   ├── xran_compression.cpp
+
+│   │   │   ├── xran_cp_api.c
+
+│   │   │   ├── xran_frame_struct.c
+
+│   │   │   ├── xran_frame_struct.h
+
+│   │   │   ├── xran_lib_mlog_tasks_id.h
+
+│   │   │   ├── xran_main.c
+
+│   │   │   ├── xran_printf.h
+
+│   │   │   ├── xran_sync_api.c
+
+│   │   │   ├── xran_timer.c
+
+│   │   │   ├── xran_transport.c
+
+│   │   │   ├── xran_ul_tables.c
+
+│   │   │   └── xran_up_api.c
+
+│   ├── readme.txt
+
+│   ├── Licenses.txt
+
+│   ├── build.sh
+
+│   └── test
+
+│   │   ├── common
+
+│   │   │   ├── common.cpp
+
+│   │   │   ├── common.hpp
+
+│   │   │   ├── common_typedef_xran.h
+
+│   │   ├── xranlib_unit_test_main.cc
+
+│   │   └── xran_lib_wrap.hpp
+
+│   │   ├── master.py
+
+│   │   ├── readme.txt
+
+│   │   └── test_xran
+
+│   │   │   ├── chain_tests.cc
+
+│   │   │   ├── compander_functional.cc
+
+│   │   │   ├── conf.json
+
+│   │   │   ├── c_plane_tests.cc
+
+│   │   │   ├── init_sys_functional.cc
+
+│   │   │   ├── Makefile
+
+│   │   │   ├── prach_functional.cc
+
+│   │   │   ├── prach_performance.cc
+
+│   │   │   ├── unittests.cc
+
+│   │   │   ├── u_plane_functional.cc
+
+General Introduction
+--------------------
+
+The xRAN Library functionality is broken down into two main sections:
+
+-  XRAN specific packet handling (src)
+
+-  Ethernet and supporting functionality (Ethernet)
+
+External functions and structures are available via set of header files
+in the API folder.
+
+This library depends on DPDK primitives to perform Ethernet networking
+in userspace, including initialization and control of Ethernet ports.
+Ethernet ports are expected to be SRIOV virtual functions (VF) but also
+can be physical functions (PF) as well
+
+This library is expected to be included in the project via
+xran_fh_o_du.h, statically compiled and linked with the L1 application
+as well as DPDK libraries. The xRAN packet processing-specific
+functionality is encapsulated into this library and not exposed to the
+rest of the 5G NR pipeline. An abstract interface similar to the mmWave
+front haul interface is defined in xran_fh_o_du.h to be available for
+usage.
+
+This way, xRAN specific changes are decoupled from the 5G NR L1
+pipeline. As a result, the design and implementation of the 5G L1
+pipeline code and xRAN library can be done in parallel, provided the
+defined interface is not modified.
+
+Ethernet consists of two modules:
+
+-  Ethernet implements xRAN specific HW Ethernet initialization, close,
+   send and receive
+
+-  ethdi provides Ethernet level software primitives to handle xRAN
+   packet exchange
+
+The xRAN layer implements the next set of functionalities:
+
+-  Common code specific for both C-plane and U-plane as well as TX and
+   RX
+
+-  Implementation of C-plane API available within the library and
+   externally
+
+-  The primary function where general library initialization and
+   configuration performed
+
+-  Module to provide the status of PTP synchronization
+
+-  Timing module where system time is polled
+
+-  eCPRI specific transport layer functions
+
+-  APIs to handle U-plane packets
+
+-  A set of utility modules for debugging (printf) and data tables are
+   included as well.
+
+.. image:: images/Illustration-of-xRAN-Sublayers.jpg
+  :width: 600
+  :alt: Figure 24. Illustration of xRAN Sublayers
+
+Figure 24. Illustration of xRAN Sublayers
+
+A detailed description of functions and input/output arguments, as well
+as key data structures, can be found in the Doxygen file for the FlexRAN
+5G NR release. In this document supplemental information is provided
+with respect to the overall design and implementation assumptions.
+
+Initialization and Close
+------------------------
+
+An example of the initialization sequence can be found in the sample
+application code. It consists of the following steps:
+
+1.Setup structure struct xran_fh_init according to configuration.
+
+2.Call xran_init() to instantiate the xRAN lib memory model and
+threads. The function returns a pointer to xRAN handle which is used
+for consecutive configuration functions.
+
+3.Initialize memory buffers used for L1 and xRAN exchange of
+information.
+
+4.Assign callback functions for (one) TTI event and for the reception
+of half of the slot of symbols (7 symbols) and Full slot of symbols
+14 symbols).
+
+5.Call xran_open() to initialize PRACH configuration, initialize DPDK,
+and launch xRAN timing thread.
+
+6.Call xran_start() to start processing xRAN packets for DL and UL.
+
+After this is complete 5G L1 runs with xRAN Front haul interface. During
+run time for every TTI event, the corresponding call back is called. For
+packet reception on UL direction, the corresponding call back is called.
+OTA time information such as frame id, subframe id and slot id can be
+obtained as result synchronization of the L1 pipeline to GPS time is
+performed.
+
+To stop and close the interface, perform this sequence of steps:
+
+7.Call xran_stop() to stop the processing of DL and UL.
+
+8.Call xran_close() to remove usage of xRAN resources.
+
+9.Call xran_mm_destroy() to destroy memory management subsystem.
+
+After this session is complete, a restart of the full L1 application is
+required. The current version of the library does not support multiple
+sessions without a restart of the full L1 application.
+
+
+~~~~~~~~~~~~~
+
+The xRAN library configuration is provided in the set of structures,
+such as struct xran_fh_init and struct xran_fh_config. The sample
+application gives an example of a test configuration used for mmWave.
+
+Some configuration options are not used in the Bronze Release and are reserved
+for future use.
+
+The following options are available: 
+
+**Structure** struct xran_fh_init\ **:**
+
+-  Number of CC and corresponding settings for each
+
+-  Core allocation for xRAN
+
+-  Ethernet port allocation
+
+-  O-DU and RU Ethernet Mac address
+
+-  Timing constraints of O-DU and 0-RU
+
+-  Debug features
+
+**Structure** struct xran_fh_config\ **:**
+
+-  Number of eAxC
+
+-  TTI Callback function and parameters
+
+-  PRACH 5G NR specific settings
+
+-  TDD frame configuration
+
+-  BBU specific configuration
+
+-  RU specific configuration
+
+**From an implementation perspective:**
+
+xran_init() performs init of the xRAN library and interface according to
+struct xran_fh_init information as per the start of application
+configuration.:
+
+-  Init DPDK with corresponding networking ports and core assignment
+
+-  Init mbuf pools
+
+-  Init DPDK timers and DPDK rings for internal packet processing
+
+-  Instantiate ORAH FH thread doing
+
+-  Timing processing (xran_timing_source_thread())
+
+-  ETH PMD (process_dpdk_io())
+
+-  IO XRAN-PHY exchange (ring_processing_func())
+
+**xran_open()** performs additional configuration as per run scenario:
+
+-  PRACH configuration
+
+-  C-plane initialization
+
+The Function **xran_close()** performs free of resources and allows potential
+restart of front haul interface with a different scenario.
+
+Start/Stop
+~~~~~~~~~~
+
+The Functions **xran_start()/xran_stop()** enable/disable packet processing for
+both DL and UL. This triggers execution of callbacks into the L1
+application.
+
+Data Exchange
+~~~~~~~~~~~~~
+
+Exchange of IQ samples, as well as C-plane specific information, is
+performed using a set of buffers allocated by xRAN |br|
+library from DPDK
+memory and shared with the l1 application. Buffers are allocated as a
+standard mbuf structure and DPDK pools are used to manage the allocation
+and free resources. Shared buffers are allocated at the init stage and
+are expected to be reused within 80 TTIs (10 ms).
+
+The xRAN protocol requires U-plane IQ data to be transferred in network
+byte order, and the L1 application handles IQ sample data in CPU byte
+order, requiring a swap. The PHY BBU pooling tasks perform copy and byte
+order swap during packet processing.
+
+C-plane Information Settings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The interface between the xRAN library and PHY is defined via struct
+xran_prb_map and similar to the data plane. The same mbuf memory is used
+to allocate memory map of PRBs for each TTI.
+
+/\* Beamforming weights for single stream for each PRBs given number of
+Antenna elements \*/
+
+struct xran_cp_bf_weight{
+
+int16_t nAntElmTRx; /* num TRX for this allocation \*/
+
+int8_t\* p_ext_section; /* pointer to form extType \*/
+
+int16_t ext_section_sz; /* extType section size \*/
+
+};
+
+struct xran_cp_bf_attribute{
+
+int16_t weight[4];
+
+};
+
+struct xran_cp_bf_precoding{
+
+int16_t weight[4];
+
+};
+
+/\* section descriptor for given number of PRBs used on U-plane packet
+creation \*/
+
+struct xran_section_desc {
+
+uint16_t section_id; /* section id used for this element \*/
+
+int16_t iq_buffer_offset; /* Offset in bytes for the content of IQs
+with in main symb buffer \*/
+
+int16_t iq_buffer_len; /* Length in bytes for the content of IQs with
+in main symb buffer \*/
+
+uint8_t \*pData; /* optional pointer to data buffer \*/
+
+void \*pCtrl; /* optional poitner to mbuf \*/
+
+};
+
+/* PRB element structure \*/
+
+struct xran_prb_elm {
+
+int16_t nRBStart; /* start RB of RB allocation \*/
+
+int16_t nRBSize; /* number of RBs used \*/
+
+int16_t nStartSymb; /* start symbol ID \*/
+
+int16_t numSymb; /* number of symbols \*/
+
+int16_t nBeamIndex; /* beam index for given PRB \*/
+
+int16_t bf_weight_update; /* need to update beam weights or not \*/
+
+int16_t compMethod; /* compression index for given PRB \*/
+
+int16_t iqWidth; /* compression bit width for given PRB \*/
+
+int16_t BeamFormingType; /* index based, weights based or
+attribute-based beam forming*/
+
+struct xran_section_desc \* p_sec_desc[XRAN_NUM_OF_SYMBOL_PER_SLOT];
+/* section desctiptors to U-plane data given RBs \*/
+
+struct xran_cp_bf_weight bf_weight; /* beam forming information
+relevant for given RBs \*/
+
+union {
+
+struct xran_cp_bf_attribute bf_attribute;
+
+struct xran_cp_bf_precoding bf_precoding;
+
+};
+
+};
+
+/* PRB map structure \*/
+
+struct xran_prb_map {
+
+uint8_t dir; /* DL or UL direction \*/
+
+uint8_t xran_port; /* xran id of given RU [0-(XRAN_PORTS_NUM-1)] \*/
+
+uint16_t band_id; /* xran band id \*/
+
+uint16_t cc_id; /* componnent carrier id [0 - (XRAN_MAX_SECTOR_NR-1)]
+\*/
+
+uint16_t ru_port_id; /* RU device antenna portid [0 -
+(XRAN_MAX_ANTENNA_NR-1)*/
+
+uint16_t tti_id; /* xRAN slot id [0 - (max tti-1)] \*/
+
+uint8_t start_sym_id; /* start symbol Id [0-13] \*/
+
+uint32_t nPrbElm; /* total number of PRB elements for given map [0-
+(XRAN_MAX_PRBS-1)] \*/
+
+struct xran_prb_elm prbMap[XRAN_MAX_PRBS];
+
+};
+
+For the Bronze release C-plane sections are expected to be provided by L1
+pipeline. If 100% of RBs allocated at all times single element of RB map
+is expected to be allocated across all symbols. Dynamic RB allocation is
+performed base on C-plane configuration.
+
+The xRAN library will require that the content of the PRB map should be
+sorted in increasing order of PRB first and then symbols.
+
+Memory Management
+-----------------
+
+Memory used for the exchange of IQ data as well as control information,
+is controlled by the xRAN library. L1 application at the init stage
+performs:
+
+-  init memory management subsystem
+
+-  init buffer management subsystem (via DPDK pools)
+
+-  allocate buffers (mbuf) for each CC, antenna, symbol, and direction \
+   (DL, UL, PRACH) for XRAN_N_FE_BUF_LEN TTIs.
+
+-  buffers are reused for every XRAN_N_FE_BUF_LEN TTIs
+
+After the session is completed, the application can free buffers and
+destroy the memory management subsystem.
+
+From an implementation perspective, the xRAN library uses a standard
+mbuf primitive and allocates a pool of buffers for each sector. This
+function is performed using rte_pktmbuf_pool_create(),
+rte_pktmbuf_alloc(), rte_pktmbuf_append() to allocate one buffer per
+symbol for the mmWave case. More information on mbuf and DPDK pools can
+be found in the DPDK documentation.
+
+In the current implementation, mbuf, the number of buffers shared with
+the L1 application is the same number of buffers used to send to and
+receive from the Ethernet port. Memory copy operations are not required
+if the packet size is smaller than or equal to MTU. Future versions of
+the xRAN library are required to remove the memory copy requirement for
+packets where the size larger than MTU.
+
+External Interface Memory
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The xRAN library header file defines a set of structures to simplify
+access to memory buffers used for IQ data.
+
+struct xran_flat_buffer {
+
+uint32_t nElementLenInBytes;
+
+uint32_t nNumberOfElements;
+
+uint32_t nOffsetInBytes;
+
+uint32_t nIsPhyAddr;
+
+uint8_t \*pData;
+
+void \*pCtrl;
+
+};
+
+struct xran_buffer_list {
+
+uint32_t nNumBuffers;
+
+struct xran_flat_buffer \*pBuffers;
+
+void \*pUserData;
+
+void \*pPrivateMetaData;
+
+};
+
+typedef struct {
+
+int32_t bValid ;
+
+int32_t nSegToBeGen;
+
+int32_t nSegGenerated;
+
+int32_t nSegTransferred;
+
+struct rte_mbuf \*pData[N_MAX_BUFFER_SEGMENT];
+
+struct xran_buffer_list sBufferList;
+
+} BbuIoBufCtrlStruct;
+
+There is no explicit requirement for user to organize a set of buffers
+in this particular way. From a compatibility |br|
+perspective it is useful to
+follow the existing design of the 5G NR l1app used for Front Haul FPGA
+and define structures shared between l1 and xRAN lib as shown:
+
+/\* io struct \*/
+
+BbuIoBufCtrlStruct
+sFrontHaulTxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR]\
+[XRAN_MAX_ANTENNA_NR];
+
+BbuIoBufCtrlStruct
+sFrontHaulTxPrbMapBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+
+BbuIoBufCtrlStruct
+sFrontHaulRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+
+BbuIoBufCtrlStruct
+sFrontHaulRxPrbMapBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+
+BbuIoBufCtrlStruct
+sFHPrachRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+
+/\* Cat B \*/
+
+BbuIoBufCtrlStruct
+sFHSrsRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANT_ARRAY_ELM_NR];
+
+/\* buffers list \*/
+
+struct xran_flat_buffer
+sFrontHaulTxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+
+struct xran_flat_buffer
+sFrontHaulTxPrbMapBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+
+struct xran_flat_buffer
+sFrontHaulRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+
+struct xran_flat_buffer
+sFrontHaulRxPrbMapBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+
+struct xran_flat_buffer
+sFHPrachRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+
+/\* Cat B SRS buffers \*/
+
+struct xran_flat_buffer
+sFHSrsRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_MAX_NUM_OF_SRS_SYMBOL_PER_SLOT];
+
+Doxygen file and xran_fh_o_du.h provide more details on the definition
+and usage of these structures.
+
+xRAN Specific Functionality
+---------------------------
+
+Front haul interface implementation in the general case is abstracted
+away using the interface defined in xran_fh_o_du.h
+
+The L1 application is not required to access xRAN protocol primitives
+(eCPRI header, application header, and others) directly. It is
+recommended to use the interface to remove dependencies between
+different software modules such as the l1 pipeline and xRAN library.
+
+External API
+~~~~~~~~~~~~
+
+The U-plane and C-plane APIs can be used directly from the application
+if such an option is required. The set of header files can be exported
+and called directly.
+
+xran_fh_o_du.h – xRAN main header file for O-DU scenario
+
+xran_cp_api.h – Control plane functions
+
+xran_pkt_cp.h – xRAN control plane packet definition
+
+xran_pkt.h – xRAN packet definition
+
+xran_pkt_up.h – xRAN User plane packet definition
+
+xran_sync_api.h – api functions to check PTP status
+
+xran_timer.h – API for timing
+
+xran_transport.h – eCPRI transport layer definition and api
+
+xran_up_api.h – user plane functions and definitions
+
+xran_compression.h – interface to compression/decompression functions
+
+Doxygen files provide detailed information on functions and structures
+available.
+
+.. _c-plane-1:
+
+C-plane
+~~~~~~~
+
+Implementation of the C-plane set of functions is defined in
+xran_cp_api.c and is used to prepare the content of C-plane packets
+according to the given configuration. Users can enable/disable
+generation of C-plane messages using enableCP field in struct
+xran_fh_init structure during init of ORAN front haul. The time of
+generation of C-plane message for DL and UL is done “Slot-based,” and
+timing can be controlled using O-DU settings according to Table 4.
+
+The C-plane module contains:
+
+-  initialization of C-plane database to keep track of allocation of
+   resources
+
+-  code to prepare C-plane packet for TX (O-DU)
+
+-  eCPRI header
+
+-  append radio application header
+
+-  append control section header
+
+-  append control section
+
+-  parser of C-plane packet for RX (O-RU emulation)
+
+-  parses and checks Section 1 and Section 3 packet content
+
+Sending and receiving packets is performed using xRAN ethdi sublayer
+functions.
+
+Creating a C-Plane Packet
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+API and Data Structures
+'''''''''''''''''''''''
+
+A C-Plane message can be composed using the following API:
+
+int xran_prepare_ctrl_pkt(struct rte_mbuf \*mbuf,
+
+struct xran_cp_gen_params \*params,
+
+uint8_t CC_ID, uint8_t Ant_ID, uint8_t seq_id);
+
+mbuf is the pointer of a DPDK packet buffer, which is allocated from the
+caller.
+
+params are the pointer of the structure which has the parameters to
+create the message.
+
+CC_ID is the parameter to specify component carrier index, Ant_ID is the
+parameters to specify the antenna port index (RU port index).
+
+seq_id is the sequence index for the message.
+
+params, the parameters to create a C-Plane message are defined as the
+structure of xran_cp_gen_params with an |br|
+example given below:
+
+struct xran_cp_gen_params {
+
+uint8_t dir;
+
+uint8_t sectionType;
+
+uint16_t numSections;
+
+struct xran_cp_header_params hdr;
+
+struct xran_section_gen_info \*sections;
+
+};
+
+dir is the direction of the C-Plane message to be generated. Available
+parameters are defined as XRAN_DIR_UL and XRAN_DIR_DL.
+
+sectionType is the section type for C-Plane message to generate, as ORAN
+specification defines all sections in a C-Plane message shall have the
+same section type. If different section types are required, they shall
+be sent with separate C-Plane messages. Available types of sections are
+defined as XRAN_CP_SECTIONTYPE_x. Please refer to the Table 5-2 Section
+Types in chapter 5.4 of ORAN specification.
+
+numSections is the total number of sections to generate, i.e., the
+number of the array in sections (struct xran_section_gen_info).
+
+hdr is the structure to hold the information to generate the radio
+application and section header in the C-Plane message. It is defined as
+the structure of xran_cp_header_params. Not all parameters in this
+structure are used for the generation, and the required parameters are
+slightly different by the type of section, as described in Table 10 and
+Table 11.
+
+Table 10. struct xran_cp_header_params – Common Radio Application Header
+
++------------+---------------------------------------------+---------+
+|            | Description                                 | Remarks |
++============+=============================================+=========+
+| filterIdx  | Filter Index. Available values are defined  | 5.4.4.3 |
+|            | as XRAN_FILTERINDEX_xxxxx.                  |         |
++------------+---------------------------------------------+---------+
+| frameId    | Frame Index. It is modulo 256 of frame      | 5.4.4.4 |
+|            | number.                                     |         |
++------------+---------------------------------------------+---------+
+| subframeId | Sub-frame Index.                            | 5.4.4.5 |
++------------+---------------------------------------------+---------+
+| slotId     | Slot Index. The maximum number is 15, as    | 5.4.4.6 |
+|            | defined in the specification.               |         |
++------------+---------------------------------------------+---------+
+| startSymId | Start Symbol Index.                         | 5.4.4.7 |
++------------+---------------------------------------------+---------+
+
+Table 11. struct xran_cp_header_params – Section Specific Parameters
+
++----------+----------+----------+---------+---+---+---+---+----------+
+|          | Des\     | Section  | Remarks |   |   |   |   |          |
+|          | cription | Type     |         |   |   |   |   |          |
+|          |          | ap\      |         |   |   |   |   |          |
+|          |          | plicable |         |   |   |   |   |          |
++==========+==========+==========+=========+===+===+===+===+==========+
+|          |          | 0        | 1       | 3 | 5 | 6 | 7 |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| fftSize  | FFT size | X        |         | X |   |   |   | 5.4.4.13 |
+|          | in frame |          |         |   |   |   |   |          |
+|          | st\      |          |         |   |   |   |   |          |
+|          | ructure. |          |         |   |   |   |   |          |
+|          | A\       |          |         |   |   |   |   |          |
+|          | vailable |          |         |   |   |   |   |          |
+|          | values   |          |         |   |   |   |   |          |
+|          | are      |          |         |   |   |   |   |          |
+|          | defined  |          |         |   |   |   |   |          |
+|          | as       |          |         |   |   |   |   |          |
+|          | X\       |          |         |   |   |   |   |          |
+|          | RAN_FFTS\|          |         |   |   |   |   |          |
+|          | IZE_xxxx |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| Scs      | Su\      | X        |         | X |   |   |   | 5.4.4.13 |
+|          | bcarrier |          |         |   |   |   |   |          |
+|          | Spacing  |          |         |   |   |   |   |          |
+|          | in the   |          |         |   |   |   |   |          |
+|          | frame    |          |         |   |   |   |   |          |
+|          | st\      |          |         |   |   |   |   |          |
+|          | ructure. |          |         |   |   |   |   |          |
+|          | A\       |          |         |   |   |   |   |          |
+|          | vailable |          |         |   |   |   |   |          |
+|          | values   |          |         |   |   |   |   |          |
+|          | are      |          |         |   |   |   |   |          |
+|          | defined  |          |         |   |   |   |   |          |
+|          | as       |          |         |   |   |   |   |          |
+|          | XRAN_SCS\|          |         |   |   |   |   |          |          
+|          | _xxxx    |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| iqWidth  | I/Q bit  |          | X       | X | X |   |   | 5.4.4.10 |
+|          | width in |          |         |   |   |   |   |          |
+|          | user     |          |         |   |   |   |   | 6.3.3.13 |
+|          | data     |          |         |   |   |   |   |          |
+|          | com\     |          |         |   |   |   |   |          |
+|          | pression |          |         |   |   |   |   |          |
+|          | header.  |          |         |   |   |   |   |          |
+|          | Should   |          |         |   |   |   |   |          |
+|          | be set   |          |         |   |   |   |   |          |
+|          | by zero  |          |         |   |   |   |   |          |
+|          | for      |          |         |   |   |   |   |          |
+|          | 16bits   |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| compMeth | Com\     |          | X       | X | X |   |   | 5.4.4.10 |
+|          | pression |          |         |   |   |   |   |          |
+|          | Method   |          |         |   |   |   |   | 6.3.3.13 |
+|          | in user  |          |         |   |   |   |   |          |
+|          | data     |          |         |   |   |   |   |          |
+|          | com\     |          |         |   |   |   |   |          |
+|          | pression |          |         |   |   |   |   |          |
+|          | header.  |          |         |   |   |   |   |          |
+|          | A\       |          |         |   |   |   |   |          |
+|          | vailable |          |         |   |   |   |   |          |
+|          | values   |          |         |   |   |   |   |          |
+|          | are      |          |         |   |   |   |   |          |
+|          | defined  |          |         |   |   |   |   |          |
+|          | as       |          |         |   |   |   |   |          |
+|          | XRAN\    |          |         |   |   |   |   |          |
+|          | _COMPMET\|          |         |   |   |   |   |          |
+|          | HOD_xxxx |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| numUEs   | Number   |          |         |   |   | X |   | 5.4.4.11 |
+|          | of UEs.  |          |         |   |   |   |   |          |
+|          | Applies  |          |         |   |   |   |   |          |
+|          | to       |          |         |   |   |   |   |          |
+|          | section  |          |         |   |   |   |   |          |
+|          | type 6   |          |         |   |   |   |   |          |
+|          | and not  |          |         |   |   |   |   |          |
+|          | s\       |          |         |   |   |   |   |          |
+|          | upported |          |         |   |   |   |   |          |
+|          | in this  |          |         |   |   |   |   |          |
+|          | release. |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| ti\      | Time     | X        |         | X |   |   |   | 5.4.4.12 |
+| meOffset | Offset.  |          |         |   |   |   |   |          |
+|          | Time     |          |         |   |   |   |   |          |
+|          | offset   |          |         |   |   |   |   |          |
+|          | from the |          |         |   |   |   |   |          |
+|          | start of |          |         |   |   |   |   |          |
+|          | the slot |          |         |   |   |   |   |          |
+|          | to start |          |         |   |   |   |   |          |
+|          | of       |          |         |   |   |   |   |          |
+|          | Cyclic   |          |         |   |   |   |   |          |
+|          | Prefix.  |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+| cpLength | Cyclic   | X        |         | X |   |   |   | 5.4.4.14 |
+|          | Prefix   |          |         |   |   |   |   |          |
+|          | Length.  |          |         |   |   |   |   |          |
++----------+----------+----------+---------+---+---+---+---+----------+
+
+**Only sections types 1 and 3 are supported in the current release.**
+
+Sections are the pointer to the array of structure which has the
+parameters for section(s) and it is defined as below:
+
+struct xran_section_gen_info {
+
+struct xran_section_info info;
+
+uint32_t exDataSize;
+
+struct {
+
+uint16_t type;
+
+uint16_t len;
+
+void \*data;
+
+} exData[XRAN_MAX_NUM_EXTENSIONS];
+
+};
+
+info is the structure to hold the information to generate section and it
+is defined as the structure of xran_section_info. Like
+xran_cp_header_params, all parameters are not required to generate
+section and Table 12 describes which |br|
+parameters are required for each
+section.
+
+Table 12. Parameters for Sections
+
++-------+-------+-------+-------+-------+-------+-------+-------+
+|       | D\    | Se\   | Re\   |       |       |       |       |
+|       | escri\| ction | marks |       |       |       |       |
+|       | ption | Type  |       |       |       |       |       |
+|       |       | appli\|       |       |       |       |       |
+|       |       | cable |       |       |       |       |       |
++=======+=======+=======+=======+=======+=======+=======+=======+
+|       |       | 0     | 1     | 3     | 5     | 6     |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| Id    | Se\   | **X** | **X** | **X** | **X** | **X** | 5.\   |
+|       | ction |       |       |       |       |       | 4.5.1 |
+|       | I\    |       |       |       |       |       |       |
+|       | denti\|       |       |       |       |       |       |
+|       | fier. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| Rb    | Res\  | **X** | **X** | **X** | **X** | **X** | 5.\   |
+|       | ource |       |       |       |       |       | 4.5.2 |
+|       | Block\|       |       |       |       |       |       |
+|       | Indic\|       |       |       |       |       |       |
+|       | ator. |       |       |       |       |       |       |
+|       | Avai\ |       |       |       |       |       |       |
+|       | lable |       |       |       |       |       |       |
+|       | v\    |       |       |       |       |       |       |
+|       | alues |       |       |       |       |       |       |
+|       | are   |       |       |       |       |       |       |
+|       | de\   |       |       |       |       |       |       |
+|       | fined |       |       |       |       |       |       |
+|       | as    |       |       |       |       |       |       |
+|       | XRAN\ |       |       |       |       |       |       |
+|       | _\    |       |       |       |       |       |       |
+|       | RBI\  |       |       |       |       |       |       |
+|       | ND_xx\|       |       |       |       |       |       |
+|       | xx.   |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| s\    | S\    | **X** | **X** | **X** | **X** | **X** | 5.\   |
+| ymInc | ymbol |       |       |       |       |       | 4.5.3 |
+|       | n\    |       |       |       |       |       |       |
+|       | umber |       |       |       |       |       |       |
+|       | Incr\ |       |       |       |       |       |       |
+|       | ement |       |       |       |       |       |       |
+|       | com\  |       |       |       |       |       |       |
+|       | mand. |       |       |       |       |       |       |
+|       | Avai\ |       |       |       |       |       |       |
+|       | lable |       |       |       |       |       |       |
+|       | v\    |       |       |       |       |       |       |
+|       | alues |       |       |       |       |       |       |
+|       | are   |       |       |       |       |       |       |
+|       | de\   |       |       |       |       |       |       |
+|       | fined |       |       |       |       |       |       |
+|       | as    |       |       |       |       |       |       |
+|       | XRA\  |       |       |       |       |       |       |
+|       | N_SYM\|       |       |       |       |       |       |
+|       | BOL\  |       |       |       |       |       |       |
+|       | NUMBE\|       |       |       |       |       |       |
+|       | R_xx\ |       |       |       |       |       |       |
+|       | xx.   |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| star\ | Sta\  | **X** | **X** | **X** | **X** | **X** | 5.\   |
+| tPrbc | rting\|       |       |       |       |       | 4.5.4 |
+|       | PRB   |       |       |       |       |       |       |
+|       | of    |       |       |       |       |       |       |
+|       | data  |       |       |       |       |       |       |
+|       | se\   |       |       |       |       |       |       |
+|       | ction |       |       |       |       |       |       |
+|       | de\   |       |       |       |       |       |       |
+|       | scrip\|       |       |       |       |       |       |
+|       | tion. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| nu    | The   | **X** | **X** | **X** | **X** | **X** | 5.\   |
+| mPrbc | n\    |       |       |       |       |       | 4.5.6 |
+|       | umber |       |       |       |       |       |       |
+|       | of    |       |       |       |       |       |       |
+|       | conti\|       |       |       |       |       |       |
+|       | guous |       |       |       |       |       |       |
+|       | PRBs  |       |       |       |       |       |       |
+|       | per   |       |       |       |       |       |       |
+|       | data  |       |       |       |       |       |       |
+|       | se\   |       |       |       |       |       |       |
+|       | ction |       |       |       |       |       |       |
+|       | de\   |       |       |       |       |       |       |
+|       | scrip\|       |       |       |       |       |       |
+|       | tion. |       |       |       |       |       |       |
+|       | When  |       |       |       |       |       |       |
+|       | nu\   |       |       |       |       |       |       |
+|       | mPrbc |       |       |       |       |       |       |
+|       | is    |       |       |       |       |       |       |
+|       | gr\   |       |       |       |       |       |       |
+|       | eater |       |       |       |       |       |       |
+|       | than  |       |       |       |       |       |       |
+|       | 255,  |       |       |       |       |       |       |
+|       | it    |       |       |       |       |       |       |
+|       | will  |       |       |       |       |       |       |
+|       | be    |       |       |       |       |       |       |
+|       | conv\ |       |       |       |       |       |       |
+|       | erted |       |       |       |       |       |       |
+|       | to    |       |       |       |       |       |       |
+|       | zero  |       |       |       |       |       |       |
+|       | by    |       |       |       |       |       |       |
+|       | the   |       |       |       |       |       |       |
+|       | macro |       |       |       |       |       |       |
+|       | (XR\  |       |       |       |       |       |       |
+|       | AN_CO\|       |       |       |       |       |       |
+|       | NVERT\|       |       |       |       |       |       |
+|       | _NUMP\|       |       |       |       |       |       |
+|       | RBC). |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| r\    | Res\  | **X** | **X** | **X** | **X** |       | 5.\   |
+| eMask | ource\|       |       |       |       |       | 4.5.5 |
+|       | El\   |       |       |       |       |       |       |
+|       | ement\|       |       |       |       |       |       |
+|       | Mask. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| numS\ | N\    | **X** | **X** | **X** | **X** |       | 5.\   |
+| ymbol | umber |       |       |       |       |       | 4.5.7 |
+|       | of    |       |       |       |       |       |       |
+|       | Sym\  |       |       |       |       |       |       |
+|       | bols. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| b\    | Beam\ |       | **X** | **X** |       |       | 5.\   |
+| eamId | I\    |       |       |       |       |       | 4.5.9 |
+|       | denti\|       |       |       |       |       |       |
+|       | fier. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| freqO\| Freq\ |       |       | **X** |       |       | 5.4\  |
+| ffset | uency\|       |       |       |       |       | .5.11 |
+|       | Of\   |       |       |       |       |       |       |
+|       | fset. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| ueId  | UE\   |       |       |       | **X** | **X** | 5.4\  |
+|       | i\    |       |       |       |       |       | .5.10 |
+|       | denti\|       |       |       |       |       |       |
+|       | fier. |       |       |       |       |       |       |
+|       | Not   |       |       |       |       |       |       |
+|       | supp\ |       |       |       |       |       |       |
+|       | orted |       |       |       |       |       |       |
+|       | in    |       |       |       |       |       |       |
+|       | this  |       |       |       |       |       |       |
+|       | rel\  |       |       |       |       |       |       |
+|       | ease. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| regF\ | Regu\ |       |       |       |       | **X** | 5.4\  |
+| actor | lariz\|       |       |       |       |       | .5.12 |
+|       | ation |       |       |       |       |       |       |
+|       | Fa\   |       |       |       |       |       |       |
+|       | ctor. |       |       |       |       |       |       |
+|       | Not   |       |       |       |       |       |       |
+|       | supp\ |       |       |       |       |       |       |
+|       | orted |       |       |       |       |       |       |
+|       | in    |       |       |       |       |       |       |
+|       | this  |       |       |       |       |       |       |
+|       | re\   |       |       |       |       |       |       |
+|       | lease |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+| Ef    | Exte\ |       | **X** | **X** | **X** | **X** | 5.\   |
+|       | nsion |       |       |       |       |       | 4.5.8 |
+|       | Flag. |       |       |       |       |       |       |
+|       | Not   |       |       |       |       |       |       |
+|       | supp\ |       |       |       |       |       |       |
+|       | orted |       |       |       |       |       |       |
+|       | in    |       |       |       |       |       |       |
+|       | this  |       |       |       |       |       |       |
+|       | rel\  |       |       |       |       |       |       |
+|       | ease. |       |       |       |       |       |       |
++-------+-------+-------+-------+-------+-------+-------+-------+
+
+**Only sections types 1 and 3 are supported in the current release.**
+
+**The xran_section_info has more parameters – type, startSymId, iqWidth,
+compMeth. These are the same parameters as those of radio application
+or section header but need to be copied into this structure again for
+the section data base.**
+
+exDataSize and exData are used to add section extensions for the
+section.
+
+exDataSize is the number of elements in the exData array. The maximum
+number of elements is defined as XRAN_MAX_NUM_EXTENSIONS and it is
+defined by four in this release with the assumption that four different
+types of section extensions can be added to a section (section extension
+type 3 is excluded since it is not supported). exData.type is the type
+of section extension and exData.len is the length of structure of
+section extension parameter in exData.data. exData.data is the pointer
+to the structure of section extensions and different structures are used
+by the type of section extensions like below.
+
+struct xran_sectionext1_info {
+
+uint16_t rbNumber; /* number RBs to ext1 chain \*/
+
+uint16_t bfwNumber; /* number of bf weights in this section \*/
+
+uint8_t bfwiqWidth;
+
+uint8_t bfwCompMeth;
+
+int16_t \*p_bfwIQ; /* pointer to formed section extention \*/
+
+int16_t bfwIQ_sz; /* size of buffer with section extention information
+\*/
+
+union {
+
+uint8_t exponent;
+
+uint8_t blockScaler;
+
+uint8_t compBitWidthShift;
+
+uint8_t activeBeamspaceCoeffMask[XRAN_MAX_BFW_N]; /\* ceil(N/8)*8,
+should be multiple of 8 \*/
+
+} bfwCompParam;
+
+};
+
+For section extension type 1, the structure of xran_sectionext1_info is
+used. Please note that the xRAN library will use bfwIQ (beamforming
+weight) as-is, i.e., xRAN library will not perform the compression, so
+the user should provide proper data to bfwIQ.
+
+struct xran_sectionext2_info {
+
+uint8_t bfAzPtWidth;
+
+uint8_t bfAzPt;
+
+uint8_t bfZePtWidth;
+
+uint8_t bfZePt;
+
+uint8_t bfAz3ddWidth;
+
+uint8_t bfAz3dd;
+
+uint8_t bfZe3ddWidth;
+
+uint8_t bfZe3dd;
+
+uint8_t bfAzSI;
+
+uint8_t bfZeSI;
+
+};
+
+For section extension type 2, the structure of xran_sectionext2_info is
+used. Each parameter will be packed as specified bit width.
+
+struct xran_sectionext4_info {
+
+uint8_t csf;
+
+uint8_t pad0;
+
+uint16_t modCompScaler;
+
+};
+
+For section extension type 4, the structure of xran_sectionext4_info is
+used.
+
+struct xran_sectionext5_info {
+
+uint8_t num_sets;
+
+struct {
+
+uint16_t csf;
+
+uint16_t mcScaleReMask;
+
+uint16_t mcScaleOffset;
+
+} mc[XRAN_MAX_MODCOMP_ADDPARMS];
+
+};
+
+For section extension type 5, the structure of xran_sectionext5_info is
+used. Please note that current implementation supports maximum two sets
+of additional parameters.
+
+**Section extensions type 3 is not supported since it is LTE specific.**
+
+Section Extensions are not fully verified in this release.
+
+Detail Procedures in API
+''''''''''''''''''''''''
+
+xran_prepare_ctrl_pkt() has several procedures to compose a C-Plane
+packet.
+
+1. Append transport header
+
+-  Reserve eCPRI header space in the packet buffer
+
+-  eCPRI version is fixed by XRAN_ECPRI_VER (0x0001)
+
+-  Concatenation and transport layer fragmentation is not supported.
+
+   ecpri_concat=0, ecpri_seq_id.sub_seq_id=0 and ecpri_seq_id.e_bit=1
+
+-  The caller needs to provide a component carrier index, antenna index,
+   and message identifier through function arguments.
+
+   CC_ID, Ant_ID and seq_id
+
+-  ecpriRtcid (ecpri_xtc_id) is composed with CC_ID and Ant_ID by
+   xran_compose_cid.
+
+-  DU port ID and band sector ID are fixed by zero in this release.
+
+-  The output of xran_compose_cid is stored in network byte order.
+
+-  The length of the payload is initialized by zero.
+
+2. Append radio application header:
+
+-  xran_append_radioapp_header() checks the type of section through
+   params->sectionType and determines proper function to append
+   remaining header components.
+
+-  Only section type 1 and 3 are supported, returns
+   XRAN_STATUS_INVALID_PARAM for other types.
+
+-  Each section uses a different function to compose the remaining
+   header and size to calculate the total length in the transport
+   header.
+
+For section type 1, xran_prepare_section1_hdr() and sizeof(struct
+xran_cp_radioapp_section1_header)
+
+For section type 3, xran_prepare_section3_hdr() and sizeof(struct
+xran_cp_radioapp_section3_header)
+
+-  Reserves the space of common radio application header and composes
+   header by xran_prepare_radioapp_common_header().
+
+-  The header is stored in network byte order.
+
+-  Appends remaining header components by the selected function above
+
+-  The header is stored in network byte order
+
+3. Append section header and section
+
+-  xran_append_control_section() determines proper size and function to
+   append section header and contents.
+
+-  For section type 1, xran_prepare_section1() and sizeof(struct
+   xran_cp_radioapp_section1)
+
+-  For section type 3, xran_prepare_section3() and sizeof(struct
+   xran_cp_radioapp_section3)
+
+-  Appends section header and section(s) by selected function above.
+
+-  If multiple sections are configured, then those will be added.
+
+-  Since fragmentation is not considered in this implementation, the
+   total length of a single C-Plane message shall not exceed MTU
+   size.
+
+-  The header and section(s) are stored in network byte order.
+
+-  Appends section extensions if it is set (ef=1)
+
+-  xran_append_section_extensions() adds all configured extensions by
+   its type.
+
+-  xran_prepare_sectionext_x() (x = 1,2,4,5) will be called by the
+   type from xran_append_section_extensions() and these functions
+   will create extension field.
+
+**Example Usage of API**
+''''''''''''''''''''''''
+
+There are two reference usages of API to generate C-Plane message in
+lib/src/xran_common.c
+
+-  generate_cpmsg_dlul()
+
+-  generate_cpmsg_prach()
+
+generate_cpmsg_dlul() is to generate the C-Plane message with section
+type 1 for DL or UL symbol data scheduling.
+
+This function has hardcoded values for some parameters such as:
+
+-  The filter index is fixed to XRAN_FILTERINDEX_STANDARD.
+
+-  RB indicator is fixed to XRAN_RBIND_EVERY.
+
+-  Symbol increment is not used (XRAN_SYMBOLNUMBER_NOTINC)
+
+-  Resource Element Mask is fixed to 0xfff
+
+The extension is not used.
+
+After C-Plane message generation, API send_cpmsg() is called. This
+function also includes the implementation for these capabilities:
+
+-  Send the generated packet to the TX ring after adding an Ethernet
+   header.
+
+-  Add section information of generated C-Plane packet to section
+   database, to generate U-plane message by C-Plane configuration
+
+send_cpmsg_prach() is to generate the C-Plane message with section type
+3 for PRACH scheduling.
+
+This functions also has some hardcoded values for the following
+parameters:
+
+-  RB indicator is fixed to XRAN_RBIND_EVERY.
+
+-  Symbol increment is not used (XRAN_SYMBOLNUMBER_NOTINC).
+
+-  Resource Element Mask is fixed to 0xfff.
+
+And similar to generate_cpmsg_dlul(), after this function generates the
+message, send_cpmsg() sends the generated packet to the TX ring and adds
+section information of the packet to the section database. Checking and
+parsing received PRACH symbol data by section information from the
+C-Plane are not implemented in this release.
+
+Example Configuration of C-Plane Messages
+'''''''''''''''''''''''''''''''''''''''''
+
+C-Plane messages can be composed through API, and the sample application
+shows several reference usages of the configuration for different
+numerologies.
+
+Below are the examples of C-Plane message configuration with a sample
+application for mmWave – numerology 3, 100 MHz bandwidth, TDD (DDDS)
+
+**C-Plane Message – downlink symbol data for a downlink slot**
+
+-  Single CP message with the single section of section type 1
+
+-  Configures single CP message for all consecutive downlink symbols
+
+-  Configures whole RBs (66) for a symbol
+
+-  Compression and beamforming are not used
+
+**C-Plane Message – uplink symbol data for uplink slot**
+
+-  Single CP message with the single section of section type 1
+
+-  Configures single CP message for all consecutive uplink symbols (UL
+   symbol starts from 3)
+
+-  Configures whole RBs (66) for a symbol
+
+-  Compression and beamforming are not used
+
+**C-Plane Message – PRACH**
+
+-  Single CP message with the single section of section type 3 including
+   repetition
+
+-  Configures PRACH format A3, config index 81, and detail parameters
+   are:
+
+-  Filter Index : 3
+
+-  CP length : 0
+
+-  Time offset : 2026
+
+-  FFT size : 1024
+
+-  Subcarrier spacing : 120KHz
+
+-  Start symbol index : 7
+
+-  Number of symbols : 6
+
+-  Number of PRBCs : 12
+
+-  Frequency offset : -792
+
+-  Compression and beamforming are not used
+
+Functions to Store/Retrieve Section Information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are several functions to store/retrieve section information of
+C-Plane messages. Since U-plane messages must be generated by the
+information in the sections of a C-Plane message, it is required to
+store and retrieve section |br|
+information.
+
+**APIs and Data Structure**
+'''''''''''''''''''''''''''
+
+APIs for initialization and release storage are:
+
+-  int xran_cp_init_sectiondb(void \*pHandle);
+
+-  int xran_cp_free_sectiondb(void \*pHandle);
+
+APIs to store and retrieve section information are:
+
+-  int xran_cp_add_section_info(void \*pHandle, uint8_t dir, uint8_t
+   cc_id, uint8_t ruport_id, uint8_t ctx_id, struct xran_section_info
+   \*info);
+
+-  int xran_cp_add_multisection_info(void \*pHandle, uint8_t cc_id,
+   uint8_t ruport_id, uint8_t ctx_id, struct xran_cp_gen_params
+   \*gen_info);
+
+-  struct xran_section_info \*xran_cp_find_section_info(void \*pHandle,
+   uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
+   uint16_t section_id);
+
+-  struct xran_section_info \*xran_cp_iterate_section_info(void
+   \*pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t
+   ctx_id, uint32_t \*next);
+
+-  int xran_cp_getsize_section_info(void \*pHandle, uint8_t dir, uint8_t
+   cc_id, uint8_t ruport_id, uint8_t ctx_id);
+
+APIs to reset the storage for a new slot are:
+
+-  int xran_cp_reset_section_info(void \*pHandle, uint8_t dir, uint8_t
+   cc_id, uint8_t ruport_id, uint8_t ctx_id);
+
+The structure of xran_section_info is used to store/retrieve
+information. This is the same structure used to generate a C-Plane
+message. Please refer to Section 5.4.2.1.1 for more details.
+
+The storage for section information is declared as a multi-dimensional
+array and declared as a local static variable to limit direct access.
+Each item is defined as the structure of xran_sectioninfo_db, and it has
+the number of stored section information items (cur_index) and the array
+of the information (list), as shown below.
+
+/*
+
+\* This structure to store the section information of C-Plane
+
+\* in order to generate and parse corresponding U-Plane \*/
+
+struct xran_sectioninfo_db {
+
+uint32_t cur_index; /* Current index to store for this eAXC \*/
+
+struct xran_section_info list[XRAN_MAX_NUM_SECTIONS]; /* The array of
+section information \*/
+
+};
+
+static struct xran_sectioninfo_db
+sectiondb[XRAN_MAX_SECTIONDB_CTX][XRAN_DIR_MAX][XRAN_COMPONENT_CARRIERS_MAX][XRAN_MAX_ANTENNA_NR*2
++ XRAN_MAX_ANT_ARRAY_ELM_NR];
+
+The maximum size of the array can be adjusted if required by system
+configuration. Since transmission and reception window of U-Plane can be
+overlapped with the start of new C-Plane for next slot, functions have
+context index to identify and protect the information. Currently the
+maximum number of context is defined by two and it can be adjusted if
+needed.
+
+8. Since the context index is not managed by the library and APIs are
+expecting it from the caller as a parameter, the caller shall
+consider a proper method to manage it to avoid corruption. The
+current reference implementation uses a slot and subframe index to
+calculate the context index.
+
+**Example Usage of APIs**
+'''''''''''''''''''''''''
+
+There are references to show the usage of APIs as below.
+
+-  Initialization and release:
+
+-  xran_cp_init_sectiondb(): xran_open() in lib/src/xran_main.c
+
+-  xran_cp_free_sectiondb(): xran_close() in lib/src/xran_main.c
+
+-  Store section information:
+
+-  xran_cp_add_section_info(): send_cpmsg_dlul() and
+   send_cpmsg_prach()in lib/src/xran_main.c
+
+-  Retrieve section information:
+
+-  xran_cp_iterate_section_info(): xran_process_tx_sym() in
+   lib/src/xran_main.c
+
+-  xran_cp_getsize_section_info(): xran_process_tx_sym() in
+   lib/src/xran_main.c
+
+-  Reset the storage for a new slot:
+
+-  xran_cp_reset_section_info(): tx_cp_dl_cb() and tx_cp_ul_cb() in
+   lib/src/xran_main.c
+
+**Function for RU emulation and Debug**
+'''''''''''''''''''''''''''''''''''''''
+
+xran_parse_cp_pkt() is a function which can be utilized for RU emulation
+or debug. It is defined below:
+
+int xran_parse_cp_pkt(struct rte_mbuf \*mbuf,
+
+struct xran_cp_gen_params \*result,
+
+struct xran_recv_packet_info \*pkt_info);
+
+It parses a received C-Plane packet and retrieves the information from
+its headers and sections.
+
+The retrieved information is stored in the structures:
+
+struct xran_cp_gen_params: section information from received C-Plane
+packet
+
+struct xran_recv_packet_info: transport layer header information (eCPRI
+header)
+
+These functions can be utilized to debug or RU emulation purposes.
+
+.. _u-plane-1:
+
+U-plane
+~~~~~~~
+
+Single Section is the default mode of xRAN packet creation. It assumes
+that there is only one section per packet, and all IQ samples are
+attached to it. Compression is not supported.
+
+A message is built in mbuf space given as a parameter. The library
+builds eCPRI header filling structure fields by taking the IQ sample
+size and populating a particular packet length and sequence number.
+
+Currently, the supported IQ bit width is 16.
+
+Implementation of a U-plane set of functions is defined in xran_up_api.c
+and is used to prepare U-plane packet content according to the given
+configuration.
+
+The following list of functions is implemented for U-plane:
+
+-  Build eCPRI header
+
+-  Build application header
+
+-  Build section header
+
+-  Append IQ samples to packet
+
+-  Prepare full symbol of xRAN data for single eAxC
+
+-  Process RX packet per symbol.
+
+The time of generation of a U-plane message for DL and UL is
+“symbol-based” and can be controlled using O-DU settings (O-RU),
+according to Table 4.
+
+Supporting Code
+---------------
+
+The xRAN library has a set of functions used to assist in packet
+processing and data exchange not directly used for xRAN packet
+processing.
+
+Timing
+~~~~~~
+
+The sense of time for the xRAN protocol is obtained from system time,
+where the system timer is synchronized to GPS time via PTP protocol
+using the Linux PHP package. On the software side, a simple polling loop
+is utilized to get time up to nanosecond precision and particular packet
+processing jobs are scheduled via the DPDK timer.
+
+long poll_next_tick(int interval)
+
+{
+
+struct timespec start_time;
+
+struct timespec cur_time;
+
+long target_time;
+
+long delta;
+
+clock_gettime(CLOCK_REALTIME, &start_time);
+
+target_time = (start_time.tv_sec \* NSEC_PER_SEC + start_time.tv_nsec +
+interval \* NSEC_PER_USEC) / (interval \* NSEC_PER_USEC) \* interval;
+
+while(1)
+
+{
+
+clock_gettime(CLOCK_REALTIME, &cur_time);
+
+delta = (cur_time.tv_sec \* NSEC_PER_SEC + cur_time.tv_nsec) -
+target_time \* NSEC_PER_USEC;
+
+if(delta > 0 \|\| (delta < 0 && abs(delta) < THRESHOLD))
+
+{
+
+break;
+
+}
+
+}
+
+return delta;
+
+}
+
+Polling is used to achieve the required precision of symbol time. For
+example, in the mmWave scenario, the symbol time is 125µs/14=~8.9µs.
+Small deterministic tasks can be executed within the polling interval
+provided. It’s smaller than the symbol interval time.
+
+DPDK Timers
+~~~~~~~~~~~
+
+DPDK provides sets of primitives (struct rte_rimer) and functions
+(rte_timer_reset_sync() rte_timer_manage()) to |br|
+schedule processing of
+function as timer. The timer is based on the TSC clock and is not
+synchronized to PTP time. As a |br|
+result, this timer cannot be used as a
+periodic timer because the TSC clock can drift substantially relative to
+the system timer which in turn is synchronized to PTP (GPS)
+
+Only single-shot timers are used to schedule processing based on
+particular events such as symbol time. The packet |br|
+processing function
+calls rte_timer_manage() in the loop, and the resulting execution of
+timer function happens right |br|
+after the timer was “armed”.
+
+xRAN Ethernet
+~~~~~~~~~~~~~
+
+xran_init_port() function performs initialization of DPDK ETH port.
+Standard port configuration is used as per reference example from DPDK.
+
+Jumbo Frames are used by default. Mbufs size is extended to support 9600
+bytes packets.
+
+Mac address and VLAN tag are expected to be configured by Infrastructure
+software. See Appendix A.4.
+
+From an implementation perspective, modules provide functions to handle:
+
+-  Ethernet headers
+
+-  VLAN tag
+
+-  Send and Receive mbuf.
+
+xRAN Ethdi
+~~~~~~~~~~
+
+Ethdi provides functionality to work with the content of an Ethernet
+packet and dispatch processing to/from the xRAN layer. Ethdi
+instantiates a main PMD driver thread and dispatches packets between the
+ring and RX/TX using rte_eth_rx_burst() and rte_eth_tx_burst() DPDK
+functions.
+
+For received packets, it maintains a set of handlers for ethertype
+handlers and xRAN layer register one xRAN ethtype |br|
+0xAEFE, resulting in
+packets with this ethertype being routed to the xRAN processing
+function. This function checks the message type of the eCPRI header and
+dispatches packet to either C-plane processing or U-plane processing.
+
+Initialization of memory pools, allocation and freeing of mbuf for
+Ethernet packets occur in this layer.
+
+
+
+
+
diff --git a/fapi_5g/bin/oran_5g_fapi.cfg b/fapi_5g/bin/oran_5g_fapi.cfg
new file mode 100644 (file)
index 0000000..fc3d7d4
--- /dev/null
@@ -0,0 +1,52 @@
+;******************************************************************************
+;
+;   Copyright (c) 2019 Intel.
+;
+;   Licensed under the Apache License, Version 2.0 (the "License");
+;   you may not use this file except in compliance with the License.
+;   You may obtain a copy of the License at
+;
+;       http://www.apache.org/licenses/LICENSE-2.0
+;
+;   Unless required by applicable law or agreed to in writing, software
+;   distributed under the License is distributed on an "AS IS" BASIS,
+;   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;   See the License for the specific language governing permissions and
+;   limitations under the License.
+;
+;******************************************************************************
+
+
+; FAPI TM CFG
+; Core configuration
+; Note:
+; Schedule Policy [1: SCHED_FIFO 2: SCHED_RR]
+[MAC2PHY_WORKER]
+core_id = 11
+thread_sched_policy = 1
+thread_priority = 89
+
+[PHY2MAC_WORKER]
+core_id = 12
+thread_sched_policy = 1
+thread_priority = 89
+
+[WLS_CFG]
+device_name = /dev/wls
+
+shmem_size = 2126512128
+
+; Log level
+; none
+; info
+; error
+; trace
+; hexdump
+[LOGGER]
+level = info
+
+; URRLC Not Supported
+; [URLLC_WORKER]
+; core_id = 12
+; thread_priority = 96
+; thread_sched_policy = 0
diff --git a/fapi_5g/bin/oran_5g_fapi.sh b/fapi_5g/bin/oran_5g_fapi.sh
new file mode 100644 (file)
index 0000000..d61191d
--- /dev/null
@@ -0,0 +1,44 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DIR_WIRELESS_WLS
+
+MACHINE_TYPE=`uname -m`
+
+if [ ${MACHINE_TYPE} == 'x86_64' ]; then
+
+       ulimit -c unlimited
+       echo 1 > /proc/sys/kernel/core_uses_pid
+
+       sysctl -w kernel.sched_rt_runtime_us=-1
+       sysctl -w kernel.shmmax=2147483648
+       sysctl -w kernel.shmall=2147483648
+       chkconfig --level 12345 irqbalance off
+       echo 0 > /proc/sys/kernel/nmi_watchdog
+       echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress
+
+fi
+
+echo start ORAN 5G FAPI
+if [ "$1" = "-g" ]; then
+    shift
+    #gdb-ia --args ./oran_5g_fapi $@
+    gdb --args ./oran_5g_fapi $@
+else
+    ./oran_5g_fapi $@
+fi
diff --git a/fapi_5g/build/build.sh b/fapi_5g/build/build.sh
new file mode 100644 (file)
index 0000000..d8dcc1e
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+make -C ../source --no-print-directory -f ../build/makefile $* PLATFORM=X86_64BIT
diff --git a/fapi_5g/build/makefile b/fapi_5g/build/makefile
new file mode 100644 (file)
index 0000000..f54657d
--- /dev/null
@@ -0,0 +1,216 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+.SUFFIXES: .o .c .s .i .cpp
+
+# Makefile to build TestMac application
+
+##############################################################
+#  Tools configuration
+##############################################################
+CC := icc
+CPP := icpc
+AS := as
+AR := ar
+LD := icc
+OBJDUMP := objdump
+
+ifeq ($(SHELL),cmd.exe)
+MD := mkdir.exe -p
+RM := rm.exe -rf
+else
+MD := mkdir -p
+RM := rm -rf
+endif
+
+##############################################################
+# TARGET
+##############################################################
+ifeq ($(RTE_TARGET),)
+    RTE_TARGET :=x86_64-native-linuxapp-icc
+endif
+##############################################################
+# DPDK
+##############################################################
+ifeq ($(RTE_SDK),)
+$(info Please make sure RTE_SDK points to DPDK folder (current version of DPDK is 18.08))
+    RTE_SDK := /opt/dpdk-18.08
+endif
+
+##############################################################
+# Projects folders
+##############################################################
+FLEXRANDIR        := $(DIR_WIRELESS)
+WLSDIR            := $(DIR_WIRELESS_WLS)
+BUILDDIR          := ../build/make
+SRCDIR            := $(CURDIR)
+
+oran_5g_fapi_dep_file = $(BUILDDIR)/oran_5g_fapi_dep
+
+APP := ../bin/oran_5g_fapi
+
+INC := \
+ $(WLSDIR) \
+ $(SRCDIR)/../include \
+ $(SRCDIR)/common \
+ $(SRCDIR)/include \
+ $(SRCDIR)/framework/workers \
+ $(SRCDIR)/framework/wls/fapi2mac \
+ $(SRCDIR)/framework/wls/fapi2phy \
+ $(SRCDIR)/framework/wls/lib \
+ $(SRCDIR)/api/fapi2mac \
+ $(SRCDIR)/api/fapi2phy \
+ $(FLEXRANDIR)/source/nr5g/api \
+ $(FLEXRANDIR)/source/common \
+ $(RTE_SDK)/$(RTE_TARGET)/include \
+ $(SRCDIR)/api/fapi2phy/p5 \
+ $(SRCDIR)/api/fapi2phy/p7 \
+ $(SRCDIR)/api/fapi2mac/p5 \
+ $(SRCDIR)/api/fapi2mac/p7 \
+ $(SRCDIR)/utils \
+
+INC := $(addprefix -I,$(INC))
+DEFS := USE_WO_LOCK _GNU_SOURCE
+
+ifneq ($(PRINTDBG),)
+DEFS := $(DEFS) PRINTF_DBG_OK
+endif
+
+ifeq ($(DEBUG_MODE),true)
+DEFS := $(DEFS) DEBUG_MODE
+endif
+
+DEFS := $(addprefix -D,$(DEFS))
+
+CFLAGS := -g -Wall -Wextra -Wunused -wd9 -Wno-deprecated-declarations -Wimplicit-function-declaration -fasm-blocks -fstack-protector-strong -z,now, -z,relro -z noexecstack -Wformat -Wformat-security -Werror=format-security -fno-strict-overflow -fwrapv $(DEFS) $(INC)
+
+ifeq ($(PRINTDBG),)
+CFLAGS := $(CFLAGS) -Werror
+endif
+
+RTE_LIBS := -L$(RTE_SDK)/$(RTE_TARGET)/lib -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lrte_ethdev -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_pci -Wl,-lrte_net -Wl,-lrte_eal -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ring -Wl,-lrt -Wl,-lm -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
+LDFLAGS := -g -Wl,-lrt -Wl,-lpthread -Wl,-lhugetlbfs -Wl,-lm -Wl,-lnuma -L $(WLSDIR) -lwls
+
+LINUX_ORAN_5G_FAPI_SRC := \
+       $(SRCDIR)/nr5g_fapi.c \
+       $(SRCDIR)/utils/nr5g_fapi_args.c \
+       $(SRCDIR)/utils/nr5g_fapi_config_loader.c \
+       $(SRCDIR)/utils/nr5g_fapi_log.c \
+       $(SRCDIR)/utils/nr5g_fapi_stats.c \
+       $(SRCDIR)/utils/nr5g_fapi_memory.c \
+       $(SRCDIR)/utils/nr5g_fapi_cmd.c \
+       $(SRCDIR)/framework/workers/nr5g_fapi_mac2phy_thread.c \
+       $(SRCDIR)/framework/workers/nr5g_fapi_phy2mac_thread.c \
+       $(SRCDIR)/framework/nr5g_fapi_framework.c \
+       $(SRCDIR)/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.c \
+       $(SRCDIR)/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.c \
+       $(SRCDIR)/framework/wls/lib/nr5g_fapi_wls.c \
+       $(SRCDIR)/api/fapi2mac/nr5g_fapi_fapi2mac_api.c \
+       $(SRCDIR)/api/fapi2mac/nr5g_fapi_proc_error_ind.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_config_resp.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_start_resp.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_stop_ind.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_ul_iq_samples_resp.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_dl_iq_samples_resp.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_shutdown_resp.c \
+       $(SRCDIR)/api/fapi2mac/p5/nr5g_fapi_proc_fapi_msg_header.c \
+       $(SRCDIR)/api/fapi2mac/p7/nr5g_fapi_proc_slot_ind.c \
+       $(SRCDIR)/api/fapi2mac/p7/nr5g_fapi_proc_crc_ind.c \
+       $(SRCDIR)/api/fapi2mac/p7/nr5g_fapi_proc_rach_ind.c \
+    $(SRCDIR)/api/fapi2mac/p7/nr5g_fapi_proc_rx_data_ind.c \
+       $(SRCDIR)/api/fapi2mac/p7/nr5g_fapi_proc_srs_ind.c \
+       $(SRCDIR)/api/fapi2mac/p7/nr5g_fapi_proc_uci_ind.c \
+       $(SRCDIR)/api/fapi2phy/nr5g_fapi_fapi2phy_api.c \
+       $(SRCDIR)/api/fapi2phy/p5/nr5g_fapi_proc_config_req.c \
+       $(SRCDIR)/api/fapi2phy/p5/nr5g_fapi_proc_start_req.c \
+       $(SRCDIR)/api/fapi2phy/p5/nr5g_fapi_proc_stop_req.c \
+       $(SRCDIR)/api/fapi2phy/p5/nr5g_fapi_proc_shutdown_req.c \
+       $(SRCDIR)/api/fapi2phy/p5/nr5g_fapi_proc_dl_iq_samples_req.c \
+       $(SRCDIR)/api/fapi2phy/p5/nr5g_fapi_proc_ul_iq_samples_req.c \
+       $(SRCDIR)/api/fapi2phy/p7/nr5g_fapi_proc_dl_tti_req.c \
+       $(SRCDIR)/api/fapi2phy/p7/nr5g_fapi_proc_ul_tti_req.c \
+    $(SRCDIR)/api/fapi2phy/p7/nr5g_fapi_proc_tx_data_req.c \
+       $(SRCDIR)/api/fapi2phy/p7/nr5g_fapi_proc_ul_dci_req.c
+
+OBJS := $(LINUX_ORAN_5G_FAPI_SRC:.c=.o)
+
+PROJECT_OBJ_DIR = $(BUILDDIR)
+
+OBJS := $(addprefix $(PROJECT_OBJ_DIR)/,$(OBJS))
+
+DIRLIST := $(sort $(dir $(OBJS)))
+
+CC_DEPS := $(addprefix __dep__,$(LINUX_ORAN_5G_FAPI_SRC))
+
+GEN_DEP :=
+ifeq ($(wildcard $(oran_5g_fapi_dep_file)),)
+GEN_DEP := regenerate_dep
+endif
+
+.PHONY: $(APP)
+$(APP): $(DIRLIST) echo_options $(GEN_DEP) $(OBJS)
+       @echo [LD] $(APP)
+       @$(CC) -o $(APP) $(OBJS) $(RTE_LIBS) $(LDFLAGS)
+#      $(OBJDUMP) -d $(APP) > $(APP).asm
+
+.PHONY : echo_options
+echo_options:
+       @echo [CFLAGS]  $(CFLAGS)
+       @echo [LDFAGS]  $(LDFLAGS)
+
+
+ifneq ($(wildcard $(oran_5g_fapi_dep_file)),)
+include $(oran_5g_fapi_dep_file)
+endif
+
+$(DIRLIST) :
+       -@$(MD) $@
+
+.PHONY : regenerate_dep
+regenerate_dep : clean_dep echo_regeenrate_dep  $(CC_DEPS)
+
+.PHONY: clean_dep
+clean_dep:
+       $(RM) $(oran_5g_fapi_dep_file)
+
+.PHONY : echo_regeenrate_dep
+echo_regeenrate_dep:
+       @echo regenerating dep files
+
+
+.PHONY : CC_DEPS
+$(CC_DEPS):
+       @$(CC) -MM $(subst __dep__,,$@) -MT $(addprefix $(PROJECT_OBJ_DIR)/,$(patsubst %.c,%.o,$(subst __dep__,,$@))) $(CFLAGS) >> $(oran_5g_fapi_dep_file)
+
+$(OBJS) : $(PROJECT_OBJ_DIR)/%.o: %.c
+       @echo [CC]    $(subst $(PROJECT_OBJ_DIR)/,,$@)
+       @$(CC) -c $(CFLAGS) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@))
+
+
+.PHONY: xclean
+xclean : clean_dep
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+       @$(RM) $(BUILDDIR)
+
+.PHONY: clean
+clean :
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+
diff --git a/fapi_5g/include/fapi_interface.h b/fapi_5g/include/fapi_interface.h
new file mode 100644 (file)
index 0000000..5946b46
--- /dev/null
@@ -0,0 +1,1434 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef _FAPI_INTERFACE_H_
+#define _FAPI_INTERFACE_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "stdint.h"
+
+#define FAPI_PARAM_REQUEST                                                                     0x00
+#define FAPI_PARAM_RESPONSE                                                                    0x01
+#define FAPI_CONFIG_REQUEST                                                                    0x02
+#define FAPI_CONFIG_RESPONSE                                                           0x03
+#define FAPI_START_REQUEST                                                                     0x04
+#define FAPI_STOP_REQUEST                                                                      0x05
+#define FAPI_STOP_INDICATION                                                           0x06
+#define FAPI_ERROR_INDICATION                               0x07
+// Reserved 0x08 - 0x7f
+#define FAPI_VENDOR_EXT_SHUTDOWN_REQUEST                    0x08
+#define FAPI_VENDOR_MESSAGE                                 0x09
+#ifdef DEBUG_MODE
+#define FAPI_VENDOR_EXT_DL_IQ_SAMPLES                       0x0A
+#define FAPI_VENDOR_EXT_UL_IQ_SAMPLES                       0x0B
+#endif
+// WLS operation 
+#define FAPI_MSG_HEADER_IND                                 0x2A
+
+// WLS operation with PDSCH Payload
+#define FAPI_MSG_PHY_ZBC_BLOCK_REQ                          0x2B
+
+// WLS operation with PUSCH Payload
+#define FAPI_MSG_PHY_ZBC_BLOCK_IND                          0x2C
+
+#define FAPI_DL_TTI_REQUEST                                                            0x80
+#define FAPI_UL_TTI_REQUEST                                                            0x81
+#define FAPI_SLOT_INDICATION                                                           0x82
+#define FAPI_UL_DCI_REQUEST                                                            0x83
+#define FAPI_TX_DATA_REQUEST                                                           0x84
+#define FAPI_RX_DATA_INDICATION                                                                0x85
+#define FAPI_CRC_INDICATION                                                            0x86
+#define FAPI_UCI_INDICATION                                                            0x87
+#define FAPI_SRS_INDICATION                                                            0x88
+#define FAPI_RACH_INDICATION                                                           0x89
+// Reserved 0x8a -0xff
+#ifdef DEBUG_MODE
+#define FAPI_VENDOR_EXT_START_RESPONSE                      0x8A
+#endif
+#define FAPI_VENDOR_EXT_SHUTDOWN_RESPONSE                   0x8B
+
+// Tags per 5G FAPI
+// Cell Parameters
+#define FAPI_RELEASE_CAPABILITY_TAG                                            0x0001
+#define FAPI_PHY_STATE_TAG                                                 0x0002
+#define FAPI_SKIP_BLANK_DL_CONFIG_TAG                                          0x0003
+#define FAPI_SKIP_BLANK_UL_CONFIG_TAG                                  0x0004
+#define FAPI_NUM_CONFIG_TLVS_TO_REPORT_TYPE_TAG                                0x0005
+#define FAPI_CYCLIC_PREFIX_TAG                              0x0006
+// PDCCH Parameters
+#define FAPI_SUPPORTED_SUBCARRIER_SPACING_DL_TAG                   0x0007
+#define FAPI_SUPPORTED_BANDWIDTH_DL_TAG                                            0x0008
+#define FAPI_SUPPORTED_SUBCARRIER_SPACING_UL_TAG                       0x0009
+#define FAPI_SUPPORTED_BANDWIDTH_UL_TAG                                                0x000A
+#define FAPI_CCE_MAPPING_TYPE_TAG                                              0x000B
+#define FAPI_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG     0x000c
+#define FAPI_PRECODER_GRANULARITY_CORESET_TAG                          0x000d
+#define FAPI_PDCCH_MU_MIMO_TAG                                                         0x000e
+#define FAPI_PDCCH_PRECODER_CYCLING_TAG                                            0x000f
+#define FAPI_MAX_PDCCHS_PER_SLOT_TAG                                   0x0010
+// PUCCH Parameters
+#define FAPI_PUCCH_FORMATS_TAG                                                 0x0011
+#define FAPI_MAX_PUCCHS_PER_SLOT_TAG                                       0x0012
+// PDSCH Parameters
+#define FAPI_PDSCH_MAPPING_TYPE_TAG                                            0x0013
+#define FAPI_PDSCH_ALLOCATION_TYPES_TAG                        0x0014
+#define FAPI_PDSCH_VRB_TO_PRB_MAPPING_TAG                                      0x0015
+#define FAPI_PDSCH_CBG_TAG                                                         0x0016
+#define FAPI_PDSCH_DMRS_CONFIG_TYPES_TAG                                       0x0017
+#define FAPI_PDSCH_DMRS_MAX_LENGTH_TAG                                         0x0018
+#define FAPI_PDSCH_DMRS_ADDITIONAL_POS_TAG                                     0x0019
+#define FAPI_MAX_PDSCHS_TBS_PER_SLOT_TAG                                       0x001a
+#define FAPI_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG                          0x001b
+#define FAPI_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG                 0x001c
+#define FAPI_MAX_MU_MIMO_USERS_DL_TAG                                          0x001d
+#define FAPI_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG                                0x001e
+#define FAPI_PREMPTIONSUPPORT_TAG                                                      0x001f
+#define FAPI_PDSCH_NON_SLOT_SUPPORT_TAG                                            0x0020
+// PUSCH Parameters
+#define FAPI_UCI_MUX_ULSCH_IN_PUSCH_TAG                                    0x0021
+#define FAPI_UCI_ONLY_PUSCH_TAG                                                0x0022
+#define FAPI_PUSCH_FREQUENCY_HOPPING_TAG                                   0x0023
+#define FAPI_PUSCH_DMRS_CONFIG_TYPES_TAG                               0x0024
+#define FAPI_PUSCH_DMRS_MAX_LEN_TAG                                            0x0025
+#define FAPI_PUSCH_DMRS_ADDITIONAL_POS_TAG                                 0x0026
+#define FAPI_PUSCH_CBG_TAG                                  0x0027
+#define FAPI_PUSCH_MAPPING_TYPE_TAG                         0x0028
+#define FAPI_PUSCH_ALLOCATION_TYPES_TAG                     0x0029
+#define FAPI_PUSCH_VRB_TO_PRB_MAPPING_TAG                   0x002a
+#define FAPI_PUSCH_MAX_PTRS_PORTS_TAG                       0x002b
+#define FAPI_MAX_PDUSCHS_TBS_PER_SLOT_TAG                   0x002c
+#define FAPI_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG        0x002d
+#define FAPI_SUPPORTED_MODULATION_ORDER_UL_TAG              0x002e
+#define FAPI_MAX_MU_MIMO_USERS_UL_TAG                       0x002f
+#define FAPI_DFTS_OFDM_SUPPORT_TAG                          0x0030
+#define FAPI_PUSCH_AGGREGATION_FACTOR_TAG                   0x0031
+// PRACH Parameters
+#define FAPI_PRACH_LONG_FORMATS_TAG                         0x0032
+#define FAPI_PRACH_SHORT_FORMATS_TAG                        0x0033
+#define FAPI_PRACH_RESTRICTED_SETS_TAG                      0x0034
+#define FAPI_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG           0x0035
+// Measurement Parameters
+#define FAPI_RSSI_MEASUREMENT_SUPPORT_TAG                   0x0036
+
+// CONFIG TLV TAGS per 5G FAPI
+// Carrier Configuration
+#define FAPI_DL_BANDWIDTH_TAG                               0x1001
+#define FAPI_DL_FREQUENCY_TAG                               0x1002
+#define FAPI_DL_K0_TAG                                      0x1003
+#define FAPI_DL_GRIDSIZE_TAG                                0x1004
+#define FAPI_NUM_TX_ANT_TAG                                 0x1005
+#define FAPI_UPLINK_BANDWIDTH_TAG                           0x1006
+#define FAPI_UPLINK_FREQUENCY_TAG                           0x1007
+#define FAPI_UL_K0_TAG                                      0x1008
+#define FAPI_UL_GRID_SIZE_TAG                               0x1009
+#define FAPI_NUM_RX_ANT_TAG                                 0x100a
+#define FAPI_FREQUENCY_SHIFT_7P5_KHZ_TAG                    0x100b
+// Cell Configuration
+#define FAPI_PHY_CELL_ID_TAG                                0x100c
+#define FAPI_FRAME_DUPLEX_TYPE_TAG                          0x100d
+// SSB Configuration
+#define FAPI_SS_PBCH_POWER_TAG                              0x100e
+#define FAPI_BCH_PAYLOAD_TAG                                0x100f
+#define FAPI_SCS_COMMON_TAG                                 0x1010
+// PRACH Configuration
+#define FAPI_PRACH_SEQUENCE_LENGTH_TAG                      0x1011
+#define FAPI_PRACH_SUBC_SPACING_TAG                         0x1012
+#define FAPI_RESTRICTED_SET_CONFIG_TAG                      0x1013
+#define FAPI_NUM_PRACH_FD_OCCASIONS_TAG                     0x1014
+#define FAPI_PRACH_ROOT_SEQUENCE_INDEX_TAG                  0x1015
+#define FAPI_NUM_ROOT_SEQUENCES_TAG                         0x1016
+#define FAPI_K1_TAG                                         0x1017
+#define FAPI_PRACH_ZERO_CORR_CONF_TAG                       0x1018
+#define FAPI_NUM_UNUSED_ROOT_SEQUENCES_TAG                  0x1019
+#define FAPI_UNUSED_ROOT_SEQUENCES_TAG                      0x101a
+#define FAPI_SSB_PER_RACH_TAG                               0x101b
+#define FAPI_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG          0x101c
+// SSB Table
+#define FAPI_SSB_OFFSET_POINT_A_TAG                         0x101d
+#define FAPI_BETA_PSS_TAG                                   0x101e
+#define FAPI_SSB_PERIOD_TAG                                 0x101f
+#define FAPI_SSB_SUBCARRIER_OFFSET_TAG                      0x1020
+#define FAPI_MIB_TAG                                        0x1021
+#define FAPI_SSB_MASK_TAG                                   0x1022
+#define FAPI_BEAM_ID_TAG                                    0x1023
+#define FAPI_SS_PBCH_MULTIPLE_CARRIERS_IN_A_BAND_TAG        0x1024
+#define FAPI_MULTIPLE_CELLS_SS_PBCH_IN_A_CARRIER_TAG        0x1025
+// TDD Table
+#define FAPI_TDD_PERIOD_TAG                                 0x1026
+#define FAPI_SLOT_CONFIG_TAG                                0x1027
+// Measurement Configuration
+#define FAPI_RSSI_MEASUREMENT_TAG                           0x1028
+// Prach Configuration Index
+#define FAPI_PRACH_CONFIG_INDEX_TAG                                                    0x1029
+// DMRS-TypeA Pos
+#define FAPI_DMRS_TYPE_A_POS_TAG                                                       0x102A
+
+// Error Codes updated per 5G FAPI Table 3-31
+#define FAPI_MSG_OK                                                                                    0x0
+#define FAPI_MSG_INVALID_STATE                                                         0x1
+#define FAPI_MSG_INVALID_CONFIG                                                                0x2
+#define FAPI_MSG_SFN_OUT_OF_SYNC                                                       0x3
+#define FAPI_MSG_SLOT_ERR                                                              0x4
+#define FAPI_MSG_BCH_MISSING                                                           0x5
+#define FAPI_MSG_INVALID_SFN                                                           0x6
+#define FAPI_MSG_UL_DCI_ERR                                                                    0x7
+#define FAPI_MSG_TX_ERR                                                                                0x8
+
+// TODO : Work out what the correct maximums should be// Needs Review for 5G
+#if 0
+// Number of UL/DL configurations, I, as defined by 36.212 section 5.3.3.1.4
+// todo : work out what the max is
+#define FAPI_MAX_UL_DL_CONFIGURATIONS                                          4
+#define FAPI_MAX_NUM_PHYSICAL_ANTENNAS                                         4
+#define FAPI_MAX_NUM_SCHEDULED_UES                                                     8
+#define FAPI_MAX_NUM_SUBBANDS                                                          8
+#define FAPI_MAX_ANTENNA_PORT_COUNT                                                    2
+#endif
+
+// 5G FAPI Definitions
+#define FAPI_NUMEROLOGIES                                   5
+#define FAPI_MAX_NUM_UNUSED_ROOT_SEQUENCES                  63  // 38.331 page 383
+#define FAPI_MAX_NUM_PRACH_FD_OCCASIONS                     64  // 38.331 page 383
+#define FAPI_MAX_NUM_OF_SYMBOLS_PER_SLOT                    14
+#define FAPI_MAX_TDD_PERIODICITY                            160 // 38.212 11.1 for u=4 and P=10 ms
+// m=p*q with p number of panels and q number of TxRU/RxRU per panel,
+// depends on the RF configuration, currently n=m=4, q=1, p=4 and k=21
+// (number of beams per pannel). n number of antenna ports
+#define FAPI_MAX_NUMBER_TX_RUS                              4
+#define FAPI_MAX_NUMBER_OF_BEAMS                            64  // Intel API Page 27
+#define FAPI_MAX_NUM_ANT_PORTS                              8   // Based on current RF
+#define FAPI_MAX_NUM_LAYERS                                 8   // 38.211 Table 7.3.1.3-1
+#define FAPI_MAX_NUM_TLVS_CELL_PARMS                       1505    // 5G FAPI Table 3-9  (A)
+#define FAPI_MAX_NUM_TLVS_CARRIER_PARMS                                        27  // 5G FAPI Table 3-10 (B)
+#define FAPI_MAX_NUM_TLVS_PDCCH_PARMS                      6   // 5G FAPI Table 3-11 (C)
+#define FAPI_MAX_NUM_TLVS_PUCCH_PARMS                      2   // 5G FAPI Table 3-12 (D)
+#define FAPI_MAX_NUM_TLVS_PDSCH_PARMS                      14  // 5G FAPI Table 3-13 (E)
+#define FAPI_MAX_NUM_TLVS_PUSCH_PARMS                      17  // 5G FAPI Table 3-14 (F)
+#define FAPI_MAX_NUM_TLVS_PRACH_PARMS                      4   // 5G FAPI Table 3-15 (G)
+#define FAPI_MAX_NUM_TLVS_MEAS_PARMS                       1   // 5G FAPI Table 3-16 (H)
+#define FAPI_MAX_NUM_TLVS_PARAMS                            1576    //  A+B+C+D+E+F+G+H + Padding
+// Carrier Table 11 + Cell Config 2 + SSB Config 3 + PRACH Config 414 + SSB
+// Table 71 + TDD Table  141 + Measurements 1
+#define FAPI_MAX_NUM_TLVS_CONFIG                                                       1500
+
+#define FAPI_UL_DCI_REQUEST_PDCCH_PDU                                  0
+
+#define FAPI_MAX_NUMBER_UNSUPPORTED_TLVS                    74
+#define FAPI_MAX_NUMBER_OF_INVALID_IDLE_ONLY_TLVS           74
+#define FAPI_MAX_NUMBER_OF_INVALID_RUNNING_ONLY_TLVS        74
+#define FAPI_MAX_NUMBER_OF_MISSING_TLVS                     74
+#define FAPI_MAX_NUM_DIGBFINTERFACES                        4   // Based on RF, 5G FAPI says {0,255}
+#define FAPI_MAX_NUM_PRGS_PER_TTI                           4   // Based on 38.214 5.1.2.3
+#define FAPI_DCI_PAYLOAD_BYTE_LEN                           32  // Based on Intel API MAX_DCI_BIT_BYTE_LEN
+#define FAPI_MAX_NUMBER_DL_DCI                              1   // Based on Intel API MAX_NUM_PDCCH
+#define FAPI_MAX_NUMBER_OF_CODEWORDS_PER_PDU                2   // Based on MAX_DL_CODEWORD
+// Based on (MAX_NUM_PDSCH*MAX_DL_CODEWORD + MAX_NUM_PDCCH + MAX_NUM_SRS +
+// 1 PBCH/SLOT)
+#define FAPI_MAX_NUMBER_DL_PDUS_PER_TTI                     129
+
+#define FAPI_MAX_NUMBER_OF_UES_PER_TTI                      16  // Per common_ran_parameters.h
+// Based on Max Tb size of 1376264 bits + 24 crc over (8848-24) and O/H
+#define FAPI_MAX_NUM_CB_PER_TTI_IN_BYTES                    192
+
+#define FAPI_MAX_NUM_PTRS_PORTS                             2   // Per 3GPP 38.212 Table 7.3.1.1.2-21
+#define FAPI_MAX_NUMBER_OF_GROUPS_PER_TTI                   16  // FlexRAN API Table 33
+#define FAPI_MAX_NUMBER_UL_PDUS_PER_TTI                     328 // (MAX_NUM_PUSCH+MAX_NUM_PUCCH+MAX_NUM_SRS+MAX_NUM_PRACH_DET)
+#define FAPI_MAX_NUMBER_DCI_PDUS_PER_TTI                    32  // Based on MAX_NUM_PDCCH
+#define FAPI_MAX_NUMBER_OF_TLVS_PER_PDU                     2   // one for each codeword
+#define FAPI_MAX_NUMBER_TX_PDUS_PER_TTI                     129 // Same as FAPI_MAX_NUMBER_DL_PDUS_PER_TTI
+// Based on 38.214 5.1.3.4, the TBS is 1376264 bits and divided by 8 and
+// aligned to 64 bytes
+#define FAPI_MAX_PDU_LENGTH                                 172096
+
+#define FAPI_MAX_NUMBER_OF_PDUS_PER_TTI                     129 // Same as FAPI_MAX_NUMBER_DL_PDUS_PER_TTI
+#define FAPI_MAX_NUMBER_OF_ULSCH_PDUS_PER_SLOT              64  // NUM_PUSCH_CHAN*FAPI_MAX_NUMBER_OF_CODEWORDS_PER_PDU
+#define FAPI_MAX_NUMBER_OF_CRCS_PER_SLOT                    32  // Based on MAX_NUM_UL_CHAN
+#define FAPI_MAX_HARQ_INFO_LEN_BYTES                        214 // Based on 5G FAPI Table 3-70
+#define FAPI_MAX_CSI_PART1_DATA_BYTES                       214 // Based on 5G FAPI Table 3-71
+#define FAPI_MAX_CSI_PART2_DATA_BYTES                       214 // Based on 5G FAPI Table 3-72
+#define FAPI_MAX_NUMBER_OF_HARQS_PER_IND                    2   // Based on 5G FAPI Table 3-68
+#define FAPI_MAX_SR_PAYLOAD_SIZE                            1   // Based on 5G FAPI Table 3-69
+#define FAPI_MAX_HARQ_PAYLOAD_SIZE                          214 // Based on 5G FAPI Table 3-70
+#define FAPI_MAX_NUMBER_UCI_PDUS_PER_SLOT                   200 // Based on MAX_NUM_PUCCH
+#define FAPI_MAX_NUMBER_RBS                                 273 // Based on MAX_NUM_OF_PRB_IN_FULL_BAND
+#define FAPI_MAX_NUMBER_OF_REP_SYMBOLS                      4   // Based on 5g FAPI Table 3-73
+#define FAPI_MAX_NUMBER_SRS_PDUS_PER_SLOT                   32  // Based on MAX_NUM_SRS
+#define FAPI_MAX_NUM_PREAMBLES_PER_SLOT                     64  // Based on MAX_NUM_PRACH_DET
+#define FAPI_MAX_NUMBER_RACH_PDUS_PER_SLOT                  64  // Based on MAX_NUM_PRACH_DET
+#define FAPI_MAX_PDUS_PER_SLOT                                                         64
+#define FAPI_MAX_NUM_TLVS_START                             3   // Based on Timer Mode requirement.
+#define FAPI_MAX_NUM_TLVS_SHUTDOWN                          1   // Based on Timer Mode requirement.
+#define FAPI_MAX_UCI_BIT_BYTE_LEN                           256
+
+#ifdef DEBUG_MODE
+#define FAPI_MAX_IQ_SAMPLE_FILE_SIZE                        576
+#define FAPI_MAX_IQ_SAMPLE_DL_PORTS                           8
+#define FAPI_MAX_IQ_SAMPLE_UL_PORTS                           2
+#define FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS                   4
+#define FAPI_MAX_IQ_SAMPLE_UL_ANTENNA                         32
+#define FAPI_MAX_IQ_SAMPLE_BUFFER_SIZE                     4096
+#endif
+
+#define FAPI_PRACH_PDU_TYPE                                   0
+#define FAPI_PUSCH_PDU_TYPE                                   1
+#define FAPI_PUCCH_PDU_TYPE                                   2
+#define FAPI_SRS_PDU_TYPE                                     3
+
+#define FAPI_PDCCH_PDU_TYPE                                   0
+#define FAPI_PDSCH_PDU_TYPE                                   1
+#define FAPI_PBCH_PDU_TYPE                                    2
+#define FAPI_CSIRS_PDU_TYPE                                   3
+
+//------------------------------------------------------------------------------------------------------------
+// Linked list header prent at the top of all messages
+    typedef struct _fapi_api_queue_elem {
+        struct _fapi_api_queue_elem *p_next;
+        // p_tx_data_elm_list used for TX_DATA.request processing
+        struct _fapi_api_queue_elem *p_tx_data_elm_list;
+        uint8_t msg_type;
+        uint8_t num_message_in_block;
+        uint32_t msg_len;
+        uint32_t align_offset;
+        uint64_t time_stamp;
+    } fapi_api_queue_elem_t, *p_fapi_api_queue_elem_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t num_msg;
+        // Can be used for Phy Id or Carrier Id  5G FAPI Table 3-2
+        uint8_t handle;
+        uint8_t pad[2];
+    } fapi_msg_header_t, *p_fapi_msg_header_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t msg_id;
+        uint16_t pad;
+        uint32_t length;        // Length of the message body in bytes  5G FAPI Table 3-3
+    } fapi_msg_t;
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t tag;
+        uint16_t length;        // 5G FAPI Table 3-7 Fixed part
+    } fapi_tl_t;
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_tl_t tl;
+        uint8_t value;          // TLV with byte value
+        uint8_t rsv[3];         // Per 5g FAPI 3.3.1.4 the lenght of the value parameter must be 32 bits
+    } fapi_uint8_tlv_t;
+    typedef struct {
+        fapi_tl_t tl;
+        uint8_t *value;         // TLV with unsigned 32 bit value
+    } fapi_uint8_ptr_tlv_t;
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_tl_t tl;
+        uint16_t value;         // TLV with unsigned 16 bit value
+        uint8_t rsv[2];         // Per 5g FAPI 3.3.1.4 the lenght of the value parameter must be 32 bits
+    } fapi_uint16_tlv_t;
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_tl_t tl;
+        int16_t value;          // TLV with signed 16 bit value
+        uint8_t rsv[2];         // Per 5g FAPI 3.3.1.4 the lenght of the value parameter must be 32 bits
+    } fapi_int16_tlv_t;
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_tl_t tl;
+        uint32_t value;         // TLV with unsigned 32 bit value
+    } fapi_uint32_tlv_t;
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t tag;           // In 5G FAPI for Cell Params inside Table 3-9 under NumConfigTLVsToReport Loop
+        uint8_t length;
+        uint8_t value;
+    } fapi_config_tlv_t;
+
+    typedef struct {
+        fapi_tl_t tl;
+        uint16_t value[FAPI_NUMEROLOGIES];
+        uint16_t rsv;           // To be 32-bit aligned, if FAPI_NUMEROLOGIES changes to some other value than 5 please ensure 32 bit alignment
+    } fapi_config_num_tlv_t;
+
+    typedef struct {
+        uint16_t hopping_id;
+        uint8_t carrier_aggregation_level;
+        uint8_t group_hop_flag;
+        uint8_t sequence_hop_flag;
+        // uint8_t                     nDMRS_type_A_pos;
+        uint8_t pad[3];
+    } fapi_config_req_vendor_msg_t;
+
+    typedef struct {
+        uint16_t sfn;
+        uint16_t slot;
+        uint32_t mode;
+#ifdef DEBUG_MODE
+        uint32_t count;
+        uint32_t period;
+#endif
+    } fapi_start_req_vendor_msg_t;
+
+    typedef struct {
+        uint16_t sfn;
+        uint16_t slot;
+    } fapi_stop_req_vendor_msg_t;
+
+    typedef struct {
+        fapi_msg_t header;
+        fapi_config_req_vendor_msg_t config_req_vendor;
+        fapi_start_req_vendor_msg_t start_req_vendor;
+        fapi_stop_req_vendor_msg_t stop_req_vendor;
+    } fapi_vendor_msg_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;      // For PARAM.req message length in fapi_msg_t is zero per 5G FAPI 3.3.1.1
+    } fapi_param_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint16_tlv_t releaseCapability;
+        fapi_uint16_tlv_t phyState;
+        fapi_uint8_tlv_t skipBlankDlConfig;
+        fapi_uint8_tlv_t skipBlankUlConfig;
+        fapi_uint16_tlv_t numTlvsToReport;
+        fapi_config_tlv_t tlvStatus[FAPI_MAX_NUM_TLVS_CONFIG];  // 5G FAPI Table 3-9
+    } fapi_cell_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t cyclicPrefix;
+        fapi_uint8_tlv_t supportedSubcarrierSpacingDl;
+        fapi_uint16_tlv_t supportedBandwidthDl;
+        fapi_uint8_tlv_t supportedSubcarrierSpecingsUl;
+        fapi_uint16_tlv_t supportedBandwidthUl; // 5G FAPI Table 3-10
+    } fapi_carrier_parms_t;
+
+// Updated per 5G FAPI    
+    typedef struct {
+        fapi_uint8_tlv_t cceMappingType;
+        fapi_uint8_tlv_t coresetOutsideFirst3OfdmSymsOfSlot;
+        fapi_uint8_tlv_t precoderGranularityCoreset;
+        fapi_uint8_tlv_t pdcchMuMimo;
+        fapi_uint8_tlv_t pdcchPrecoderCycling;
+        fapi_uint8_tlv_t maxPdcchsPerSlot;  // 5G FAPI Table 3-11
+    } fapi_pdcch_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t pucchFormats;
+        fapi_uint8_tlv_t maxPucchsPerSlot;  // 5G FAPI Table 3-12
+    } fapi_pucch_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t pdschMappingType;
+        fapi_uint8_tlv_t pdschAllocationTypes;
+        fapi_uint8_tlv_t pdschVrbToPrbMapping;
+        fapi_uint8_tlv_t pdschCbg;
+        fapi_uint8_tlv_t pdschDmrsConfigTypes;
+        fapi_uint8_tlv_t pdschDmrsMaxLength;
+        fapi_uint8_tlv_t pdschDmrsAdditionalPos;
+        fapi_uint8_tlv_t maxPdschsTBsPerSlot;
+        fapi_uint8_tlv_t maxNumberMimoLayersPdsch;
+        fapi_uint8_tlv_t supportedMaxModulationOrderDl;
+        fapi_uint8_tlv_t maxMuMimoUsersDl;
+        fapi_uint8_tlv_t pdschDataInDmrsSymbols;
+        fapi_uint8_tlv_t premptionSupport;
+        fapi_uint8_tlv_t pdschNonSlotSupport;   // 5G FAPI Table 3-13
+    } fapi_pdsch_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t uciMuxUlschInPusch;
+        fapi_uint8_tlv_t uciOnlyPusch;
+        fapi_uint8_tlv_t puschFrequencyHopping;
+        fapi_uint8_tlv_t puschDmrsConfigTypes;
+        fapi_uint8_tlv_t puschDmrsMaxLen;
+        fapi_uint8_tlv_t puschDmrsAdditionalPos;
+        fapi_uint8_tlv_t puschCbg;
+        fapi_uint8_tlv_t puschMappingType;
+        fapi_uint8_tlv_t puschAllocationTypes;
+        fapi_uint8_tlv_t puschVrbToPrbMapping;
+        fapi_uint8_tlv_t puschMaxPtrsPorts;
+        fapi_uint8_tlv_t maxPduschsTBsPerSlot;
+        fapi_uint8_tlv_t maxNumberMimoLayersNonCbPusch;
+        fapi_uint8_tlv_t supportedModulationOrderUl;
+        fapi_uint8_tlv_t maxMuMimoUsersUl;
+        fapi_uint8_tlv_t dftsOfdmSupport;
+        fapi_uint8_tlv_t puschAggregationFactor;    // 5G FAPI Table 3-14
+    } fapi_pusch_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t prachLongFormats;
+        fapi_uint16_tlv_t prachShortFormats;
+        fapi_uint8_tlv_t prachRestrictedSets;
+        fapi_uint8_tlv_t maxPrachFdOccasionsInASlot;    // 5G FAPI Table 3-15
+    } fapi_prach_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t rssiMeasurementSupport;    // 5G FAPI Table 3-16
+    } fapi_meas_parms_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_cell_parms_t cell_parms;
+        fapi_carrier_parms_t carr_parms;
+        fapi_pdcch_parms_t pdcch_parms;
+        fapi_pucch_parms_t pucch_parms;
+        fapi_pdsch_parms_t pdsch_parms;
+        fapi_pusch_parms_t pusch_parms;
+        fapi_prach_parms_t prach_parms;
+        fapi_meas_parms_t meas_parms;   // 5G FAPI Table 3-8
+    } fapi_params_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint8_t error_code;
+        uint8_t number_of_tlvs;
+        uint8_t pad[2];
+        fapi_uint16_tlv_t tlvs[FAPI_MAX_NUM_TLVS_PARAMS];   // 5G FAPI Table 3-5
+    } fapi_param_resp_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint16_tlv_t dlBandwidth;
+        fapi_uint32_tlv_t dlFrequency;
+        fapi_config_num_tlv_t dlk0;
+        fapi_config_num_tlv_t dlGridSize;
+        fapi_uint16_tlv_t numTxAnt;
+        fapi_uint16_tlv_t uplinkBandwidth;
+        fapi_uint32_tlv_t uplinkFrequency;
+        fapi_config_num_tlv_t ulk0;
+        fapi_config_num_tlv_t ulGridSize;
+        fapi_uint16_tlv_t numRxAnt;
+        fapi_uint8_tlv_t frequencyShift7p5KHz;  // 5G FAPI Table 3-21
+    } fapi_carrier_config_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t phyCellId;
+        fapi_uint8_tlv_t frameDuplexType;   // 5G FAPI Table 3-22
+    } fapi_cell_config_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint32_tlv_t ssPbchPower;
+        fapi_uint8_tlv_t bchPayload;
+        fapi_uint8_tlv_t scsCommon; // 5G FAPI Table 3-23
+    } fapi_ssb_config_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint16_tlv_t prachRootSequenceIndex;
+        fapi_uint8_tlv_t numRootSequences;
+        fapi_uint16_tlv_t k1;
+        fapi_uint8_tlv_t prachZeroCorrConf;
+        fapi_uint16_tlv_t numUnusedRootSequences;   // 5G FAPI Table 3-24 Subset
+        fapi_uint16_tlv_t
+            unusedRootSequences[FAPI_MAX_NUM_UNUSED_ROOT_SEQUENCES];
+    } fapi_prachFdOccasion_t;
+
+// Updated per 5G FAPI_
+    typedef struct {
+        fapi_uint8_tlv_t prachSequenceLength;
+        fapi_uint8_tlv_t prachSubCSpacing;
+        fapi_uint8_tlv_t restrictedSetConfig;
+        fapi_uint8_tlv_t numPrachFdOccasions;
+        fapi_uint8_tlv_t prachConfigIndex;
+        fapi_prachFdOccasion_t prachFdOccasion[FAPI_MAX_NUM_PRACH_FD_OCCASIONS];
+        fapi_uint8_tlv_t ssbPerRach;
+        fapi_uint8_tlv_t prachMultipleCarriersInABand;  // 5G FAPI Table 3-24
+    } fapi_prach_configuration_t;
+
+//Updated per 5G FAPI
+    typedef struct {
+        fapi_uint16_tlv_t ssbOffsetPointA;
+        fapi_uint8_tlv_t betaPss;
+        fapi_uint8_tlv_t ssbPeriod;
+        fapi_uint8_tlv_t ssbSubCarrierOffset;
+        fapi_uint32_tlv_t mib;
+        fapi_uint32_tlv_t ssbMask[2];
+        fapi_uint8_tlv_t beamId[64];
+        fapi_uint8_tlv_t ssPbchMultipleCarriersInABand;
+        fapi_uint8_tlv_t multipleCellsSsPbchInACarrier; // 5G FAPI Table 3-25
+    } fapi_ssb_table_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t slotConfig[FAPI_MAX_NUM_OF_SYMBOLS_PER_SLOT];  // 5G FAPI Table 3-26 Subset
+    } fapi_slotconfig_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t tddPeriod;
+        fapi_slotconfig_t slotConfig[FAPI_MAX_TDD_PERIODICITY]; // 5G FAPI Table 3-26
+    } fapi_tdd_table_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_uint8_tlv_t rssiMeasurement;   // 5G FAPI Table 3-27
+    } fapi_meas_config_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        int16_t digBeamWeightRe;
+        int16_t digBeamWeightIm;    // 5G FAPI Table 3-32 Subset
+    } fapi_dig_beam_weight_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t beamIdx;
+        fapi_dig_beam_weight_t digBeamWeight[FAPI_MAX_NUMBER_TX_RUS];   // 5G FAPI Table 3-32 Subset
+    } fapi_dig_beam_config_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t numDigBeams;
+        uint16_t numTxRus;
+        fapi_dig_beam_config_t digBeam[FAPI_MAX_NUMBER_OF_BEAMS];   // 5G FAPI Table 3-32
+    } fapi_beamforming_table_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        int16_t preCoderWeightRe;
+        int16_t preCoderWeightIm;   // 5G FAPI Table 3-33 Subset
+    } fapi_precoderWeight_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_precoderWeight_t precoder_weight[FAPI_MAX_NUM_ANT_PORTS];  // 5G FAPI Table 3-33 Subset
+    } fapi_precoder_weight_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pmIdx;
+        uint16_t numLayers;
+        uint16_t numAntPorts;
+        uint16_t pad[1];
+        fapi_precoder_weight_t precoderWeight[FAPI_MAX_NUM_LAYERS]; // 5G FAPI Table 3-33
+    } fapi_precoding_table_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_carrier_config_t carrierConfig;
+        fapi_cell_config_t cellConfig;
+        fapi_ssb_config_t ssbConfig;
+        fapi_prach_configuration_t prachConfig;
+        fapi_ssb_table_t ssbTable;
+        fapi_tdd_table_t tddTable;
+        fapi_meas_config_t measConfig;
+        fapi_beamforming_table_t beamformingTable;
+        fapi_precoding_table_t precodingTable;  // 5G FAPI Table 3-20
+    } fapi_config_t;
+
+// Updated per 5G FAPI 
+    typedef struct {
+        fapi_msg_t header;
+        uint8_t number_of_tlvs;
+        uint8_t pad[3];
+        fapi_uint32_tlv_t tlvs[FAPI_MAX_NUM_TLVS_CONFIG];   // 5G FAPI Table 3-17
+    } fapi_config_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint8_t error_code;
+        uint8_t number_of_invalid_tlvs;
+        uint8_t number_of_inv_tlvs_idle_only;
+        uint8_t number_of_inv_tlvs_running_only;
+        uint8_t number_of_missing_tlvs;
+        uint8_t pad[3];
+        fapi_uint16_tlv_t tlvs[4 * FAPI_MAX_NUM_TLVS_CONFIG];   // 5G FAPI Table 3-18
+        //   fapi_uint16_tlv_t unsupported_or_invalid_tlvs[FAPI_MAX_NUMBER_UNSUPPORTED_TLVS];
+        //   fapi_uint16_tlv_t invalid_idle_only_tlvs[FAPI_MAX_NUMBER_OF_INVALID_IDLE_ONLY_TLVS];
+        //   fapi_uint16_tlv_t invalid_running_only_tlvs[FAPI_MAX_NUMBER_OF_INVALID_RUNNING_ONLY_TLVS];
+        //   fapi_uint16_tlv_t missing_tlvs[FAPI_MAX_NUMBER_OF_MISSING_TLVS];            
+    } fapi_config_resp_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+    } fapi_start_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;      // Message Length is zero for STOP.request
+    } fapi_stop_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;      // Message Length is zero for STOP.indication
+    } fapi_stop_ind_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint8_t message_id;
+        uint8_t error_code;     // 5G FAPI Table 3-30
+        uint8_t pad[2];
+    } fapi_error_ind_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;          // 5G FAPI Table 3-34
+    } fapi_slot_ind_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t beamidx;       // 5G FAPI Table 3-43 subset
+    } fapi_bmi_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pmIdx;
+        uint8_t pad[2];
+        fapi_bmi_t beamIdx[FAPI_MAX_NUM_DIGBFINTERFACES];   // 5G FAPI Table 3-43 subset
+    } fapi_pmi_bfi_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t numPrgs;
+        uint16_t prgSize;
+        uint8_t digBfInterfaces;
+        uint8_t pad[3];
+        fapi_pmi_bfi_t pmi_bfi[FAPI_MAX_NUM_PRGS_PER_TTI];  // 5G FAPI Table 3-43
+    } fapi_precoding_bmform_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t rnti;
+        uint16_t scramblingId;
+        uint16_t scramblingRnti;
+        uint8_t cceIndex;
+        uint8_t aggregationLevel;
+        fapi_precoding_bmform_t pc_and_bform;
+        uint8_t beta_pdcch_1_0;
+        uint8_t powerControlOfssetSS;
+        uint16_t payloadSizeBits;
+        uint8_t payload[FAPI_DCI_PAYLOAD_BYTE_LEN]; // 5G FAPI Table 3-37
+    } fapi_dl_dci_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t bwpSize;
+        uint16_t bwpStart;
+        uint8_t subCarrierSpacing;
+        uint8_t cyclicPrefix;
+        uint8_t startSymbolIndex;
+        uint8_t durationSymbols;
+        uint8_t freqDomainResource[6];
+        uint8_t cceRegMappingType;
+        uint8_t regBundleSize;
+        uint8_t interleaverSize;
+        uint8_t coreSetSize;
+        uint16_t shiftIndex;
+        uint8_t precoderGranularity;
+        uint8_t coreSetType;
+        uint16_t numDlDci;      // 5G FAPI Table 3-36
+        fapi_dl_dci_t dlDci[FAPI_MAX_NUMBER_DL_DCI];
+    } fapi_dl_pdcch_pdu_t;
+
+    // Updated per 5G FAPI
+    typedef struct {
+        uint16_t targetCodeRate;
+        uint8_t qamModOrder;
+        uint8_t mcsIndex;
+        uint8_t mcsTable;
+        uint8_t rvIndex;
+        uint8_t pad[2];
+        uint32_t tbSize;        // 5G FAPI Table 3-38 Subset
+    } fapi_codeword_pdu_t;
+
+    // Updated per 5G FAPI
+    typedef struct {
+        uint16_t pduBitMap;
+        uint16_t rnti;
+        uint16_t pdu_index;
+        uint16_t bwpSize;
+        uint16_t bwpStart;
+        uint8_t subCarrierSpacing;
+        uint8_t cyclicPrefix;
+        uint8_t nrOfCodeWords;
+        uint8_t pad[3];
+        fapi_codeword_pdu_t cwInfo[FAPI_MAX_NUMBER_OF_CODEWORDS_PER_PDU];
+        uint16_t dataScramblingId;
+        uint8_t nrOfLayers;
+        uint8_t transmissionScheme;
+        uint8_t refPoint;
+        uint8_t dmrsConfigType;
+        uint16_t dlDmrsSymbPos;
+        uint8_t scid;
+        uint8_t numDmrsCdmGrpsNoData;
+        uint8_t resourceAlloc;
+        uint8_t pad1;
+        uint16_t dlDmrsScramblingId;
+        uint16_t dmrsPorts;
+        uint16_t rbStart;
+        uint16_t rbSize;
+        uint8_t rbBitmap[36];
+        uint8_t vrbToPrbMapping;
+        uint8_t startSymbIndex;
+        uint8_t nrOfSymbols;
+        uint8_t ptrsPortIndex;
+        uint8_t ptrsTimeDensity;
+        uint8_t ptrsFreqDensity;
+        uint8_t ptrsReOffset;
+        uint8_t nEpreRatioOfPdschToPtrs;
+        fapi_precoding_bmform_t preCodingAndBeamforming;
+        uint8_t powerControlOffset;
+        uint8_t powerControlOffsetSS;
+        uint8_t isLastCbPresent;
+        uint8_t isInlineTbCrc;
+        uint32_t dlTbCrc;       // 5G FAPI Table 3-38
+        uint8_t mappingType;
+        uint8_t nrOfDmrsSymbols;
+        uint8_t dmrsAddPos;
+        uint8_t pad2;
+    } fapi_dl_pdsch_pdu_t;
+
+    // Updated per 5G FAPI
+    typedef struct {
+        uint16_t bwpSize;
+        uint16_t bwpStart;
+        uint8_t subCarrierSpacing;
+        uint8_t cyclicPrefix;
+        uint16_t startRb;
+        uint16_t nrOfRbs;
+        uint8_t csiType;
+        uint8_t row;
+        uint16_t freqDomain;
+        uint8_t symbL0;
+        uint8_t symbL1;
+        uint8_t cdmType;
+        uint8_t freqDensity;
+        uint16_t scramId;
+        uint8_t powerControlOffset;
+        uint8_t powerControlOffsetSs;
+        uint8_t pad[2];
+        fapi_precoding_bmform_t preCodingAndBeamforming;    // 5G FAPI Table 3-39
+    } fapi_dl_csi_rs_pdu_t;
+
+// Updated per 5G FAPI 
+    typedef struct {
+        uint8_t dmrsTypeAPosition;
+        uint8_t pdcchConfigSib1;
+        uint8_t cellBarred;
+        uint8_t intraFreqReselection;   // 5G FAPI Table 3-42
+    } fapi_phy_mib_pdu_t;
+
+// Updated per 5G FAPI 
+    typedef struct {
+        union {
+            uint32_t bchPayload;
+            fapi_phy_mib_pdu_t phyMibPdu;   // 5G FAPI Table 3-40 Subset
+        };
+    } fapi_bch_payload_t;
+
+    // Updated per 5G FAPI
+    typedef struct {
+        uint16_t physCellId;
+        uint8_t betaPss;
+        uint8_t ssbBlockIndex;
+        uint8_t ssbSubCarrierOffset;
+        uint8_t bchPayloadFlag;
+        uint16_t ssbOffsetPointA;
+        fapi_bch_payload_t bchPayload;
+        fapi_precoding_bmform_t preCodingAndBeamforming;    // 5G FAPI Table 3-40
+    } fapi_dl_ssb_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pduType;
+        uint16_t pduSize;
+        union {
+            fapi_dl_pdcch_pdu_t pdcch_pdu;
+            fapi_dl_pdsch_pdu_t pdsch_pdu;
+            fapi_dl_csi_rs_pdu_t csi_rs_pdu;
+            fapi_dl_ssb_pdu_t ssb_pdu;  // 5G FAPI Table 3-35 Subset
+        } pdu;
+    } fapi_dl_tti_req_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t nUe;
+        uint8_t pad[3];
+        uint8_t pduIdx[FAPI_MAX_NUMBER_OF_UES_PER_TTI]; // 5G FAPI Subset Table 3-35 and Table 3-44
+    } fapi_ue_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint8_t nPdus;
+        uint8_t nGroup;
+        uint8_t pad[2];
+        fapi_dl_tti_req_pdu_t pdus[FAPI_MAX_PDUS_PER_SLOT]; // 5G FAPI Table 3-35
+        fapi_ue_info_t ue_grp_info[FAPI_MAX_NUMBER_OF_GROUPS_PER_TTI];
+    } fapi_dl_tti_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t rvIndex;
+        uint8_t harqProcessId;
+        uint8_t newDataIndicator;
+        uint8_t pad;
+        uint32_t tbSize;
+        uint16_t numCb;         // 5G FAPI Table 3-47
+        uint8_t cbPresentAndPosition[2];    // Since the maximum number of Code Blocks per TCB in a CBG is 8 for 1 CW or 4 for 2CW and this is a bit field with pading to align to 32 bits
+    } fapi_pusch_data_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t harqAckBitLength;
+        uint16_t csiPart1BitLength;
+        uint16_t csiPart2BitLength;
+        uint8_t alphaScaling;
+        uint8_t betaOffsetHarqAck;
+        uint8_t betaOffsetCsi1;
+        uint8_t betaOffsetCsi2; // 5G FAPI Table 3-48
+        uint8_t pad[2];
+    } fapi_pusch_uci_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t ptrsPortIndex;
+        uint8_t ptrsDmrsPort;
+        uint8_t ptrsReOffset;   // 5G FAPI Table 3-49 Subset
+    } fapi_ptrs_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t numPtrsPorts;
+        uint8_t ptrsTimeDensity;
+        uint8_t ptrsFreqDensity;    // 5G FAPI Table 3-49 Subset
+        uint8_t ulPtrsPower;
+        fapi_ptrs_info_t ptrsInfo[FAPI_MAX_NUM_PTRS_PORTS];
+    } fapi_pusch_ptrs_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t lowPaprSequenceNumber;
+        uint8_t lowPaprGroupNumber;
+        uint8_t ulPtrsSampleDensity;
+        uint8_t ulPtrsTimeDensityTransformPrecoding;
+        uint8_t pad;            // 5G FAPI Table 3-50
+    } fapi_dfts_ofdm_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_bmi_t beamIdx[FAPI_MAX_NUM_DIGBFINTERFACES];
+    } fapi_rx_bfi_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t numPrgs;
+        uint16_t prgSize;
+        uint8_t digBfInterface;
+        uint8_t pad[3];
+        fapi_rx_bfi_t rx_bfi[FAPI_MAX_NUM_PRGS_PER_TTI];    // 5G FAPI Table 3-53
+    } fapi_ul_rx_bmform_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t physCellId;
+        uint8_t numPrachOcas;
+        uint8_t prachFormat;
+        uint8_t numRa;
+        uint8_t prachStartSymbol;
+        uint16_t numCs;
+        fapi_ul_rx_bmform_pdu_t beamforming;
+    } fapi_ul_prach_pdu_t;      // 5G FAPI Table 3-45
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pduBitMap;
+        uint16_t rnti;
+        uint32_t handle;
+        uint16_t bwpSize;
+        uint16_t bwpStart;
+        uint8_t subCarrierSpacing;
+        uint8_t cyclicPrefix;
+        uint8_t mcsIndex;
+        uint8_t mcsTable;
+        uint16_t targetCodeRate;
+        uint8_t qamModOrder;
+        uint8_t transformPrecoding;
+        uint16_t dataScramblingId;
+        uint8_t nrOfLayers;
+        uint8_t dmrsConfigType;
+        uint16_t ulDmrsSymbPos;
+        uint16_t ulDmrsScramblingId;
+        uint8_t scid;
+        uint8_t numDmrsCdmGrpsNoData;
+        uint16_t dmrsPorts;
+        uint16_t nTpPuschId;
+        uint16_t tpPi2Bpsk;
+        uint8_t rbBitmap[36];
+        uint16_t rbStart;
+        uint16_t rbSize;
+        uint8_t vrbToPrbMapping;
+        uint8_t frequencyHopping;
+        uint16_t txDirectCurrentLocation;
+        uint8_t resourceAlloc;
+        uint8_t uplinkFrequencyShift7p5khz;
+        uint8_t startSymbIndex;
+        uint8_t nrOfSymbols;
+        uint8_t mappingType;
+        uint8_t nrOfDmrsSymbols;
+        uint8_t dmrsAddPos;
+        uint8_t pad;
+
+        fapi_pusch_data_t puschData;
+        fapi_pusch_uci_t puschUci;
+        fapi_pusch_ptrs_t puschPtrs;
+        fapi_dfts_ofdm_t dftsOfdm;
+        fapi_ul_rx_bmform_pdu_t beamforming;    // 5G FAPI Table 3-46
+    } fapi_ul_pusch_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t rnti;
+        uint8_t pad1[2];
+        uint32_t handle;
+        uint16_t bwpSize;
+        uint16_t bwpStart;
+        uint8_t subCarrierSpacing;
+        uint8_t cyclicPrefix;
+        uint8_t formatType;
+        uint8_t multiSlotTxIndicator;
+        uint8_t pi2Bpsk;
+        uint8_t pad2;
+        uint16_t prbStart;
+        uint16_t prbSize;
+        uint8_t startSymbolIndex;
+        uint8_t nrOfSymbols;
+        uint8_t freqHopFlag;
+        uint8_t groupHopFlag;
+        uint8_t sequenceHopFlag;
+        uint8_t pad3;
+        uint16_t secondHopPrb;
+        uint16_t hoppingId;
+        uint16_t initialCyclicShift;
+        uint16_t dataScramblingId;
+        uint8_t timeDomainOccIdx;
+        uint8_t preDftOccIdx;
+        uint8_t preDftOccLen;
+        uint8_t addDmrsFlag;
+        uint16_t dmrsScramblingId;
+        uint8_t dmrsCyclicShift;
+        uint8_t srFlag;
+        uint16_t bitLenHarq;
+        uint8_t pad4[2];
+        uint16_t bitLenCsiPart1;
+        uint16_t bitLenCsiPart2;
+        fapi_ul_rx_bmform_pdu_t beamforming;    // 5G FAPI Table 3-51
+    } fapi_ul_pucch_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t rnti;
+        uint8_t pad[2];
+        uint32_t handle;
+        uint16_t bwpSize;
+        uint16_t bwpStart;
+        uint8_t subCarrierSpacing;
+        uint8_t cyclicPrefix;
+        uint8_t numAntPorts;
+        uint8_t numSymbols;
+        uint8_t numRepetitions;
+        uint8_t timeStartPosition;
+        uint8_t configIndex;
+        uint8_t bandwidthIndex;
+        uint16_t sequenceId;
+        uint8_t combSize;
+        uint8_t combOffset;
+        uint8_t cyclicShift;
+        uint8_t frequencyPosition;
+        uint16_t frequencyShift;
+        uint8_t frequencyHopping;
+        uint8_t groupOrSequenceHopping;
+        uint8_t resourceType;
+        uint8_t pad1[2];
+        uint16_t tSrs;
+        uint16_t tOffset;
+        fapi_ul_rx_bmform_pdu_t beamforming;    // 5G FAPI Table 3-52
+    } fapi_ul_srs_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pduType;
+        uint16_t pduSize;
+        union {
+            fapi_ul_prach_pdu_t prach_pdu;
+            fapi_ul_pusch_pdu_t pusch_pdu;
+            fapi_ul_pucch_pdu_t pucch_pdu;
+            fapi_ul_srs_pdu_t srs_pdu;
+        } pdu;
+    } fapi_ul_tti_req_pdu_t;    // 5G FAPI Subset Table 3-44
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint8_t nPdus;
+        uint8_t rachPresent;
+        uint8_t nUlsch;
+        uint8_t nUlcch;
+        uint8_t nGroup;
+        uint8_t pad[3];
+        fapi_ul_tti_req_pdu_t pdus[FAPI_MAX_NUMBER_UL_PDUS_PER_TTI];    // 5G FAPI Table 3-44
+        fapi_ue_info_t ueGrpInfo[FAPI_MAX_NUMBER_OF_GROUPS_PER_TTI];
+    } fapi_ul_tti_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pduType;
+        uint16_t pduSize;
+        fapi_dl_pdcch_pdu_t pdcchPduConfig; // 5G FAPI Table 3-54 Subset
+    } fapi_dci_pdu_t;
+
+    // Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint8_t numPdus;
+        uint8_t pad[3];
+        fapi_dci_pdu_t pdus[FAPI_MAX_NUMBER_UCI_PDUS_PER_SLOT]; // 5G FAPI Table 3-54
+    } fapi_ul_dci_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pdu_length;
+        uint16_t pdu_index;
+        uint32_t num_tlvs;
+        fapi_uint8_ptr_tlv_t tlvs[FAPI_MAX_NUMBER_OF_TLVS_PER_PDU]; // 5G FAPI Table 3-58 Subset
+    } fapi_tx_pdu_desc_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint16_t num_pdus;
+        uint8_t pad[2];
+        fapi_tx_pdu_desc_t pdu_desc[FAPI_MAX_NUMBER_DL_PDUS_PER_TTI];   // 5G FAPI Table 3-58
+    } fapi_tx_data_req_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint32_t handle;
+        uint16_t rnti;
+        uint8_t harqId;
+        uint8_t ul_cqi;
+        uint16_t timingAdvance;
+        uint16_t rssi;
+        uint16_t pdu_length;
+        uint8_t pad[2];
+        void *pduData;          // 5G FAPI Table 3-61 Subset
+    } fapi_pdu_ind_info_t;
+
+    // Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint16_t numPdus;
+        uint8_t pad[2];
+        fapi_pdu_ind_info_t pdus[FAPI_MAX_NUMBER_OF_ULSCH_PDUS_PER_SLOT];   // 5G FAPI Table 3-61
+    } fapi_rx_data_indication_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint32_t handle;
+        uint16_t rnti;
+        uint8_t harqId;
+        uint8_t tbCrcStatus;
+        uint8_t ul_cqi;
+        uint8_t pad;
+        uint16_t numCb;
+        uint16_t timingAdvance;
+        uint16_t rssi;
+        uint8_t cbCrcStatus[FAPI_MAX_NUM_CB_PER_TTI_IN_BYTES];  // 5G FAPI Table 3-62 subset
+    } fapi_crc_ind_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint16_t numCrcs;
+        uint8_t pad[2];
+        fapi_crc_ind_info_t crc[FAPI_MAX_NUMBER_OF_CRCS_PER_SLOT];  // 5G FAPI Table 3-62
+    } fapi_crc_ind_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t harqCrc;
+        uint8_t pad;
+        uint16_t harqBitLen;
+        uint8_t harqPayload[FAPI_MAX_HARQ_INFO_LEN_BYTES];  // 5G FAPI Table 3-70
+    } fapi_harq_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t csiPart1Crc;
+        uint8_t pad;
+        uint16_t csiPart1BitLen;
+        uint8_t csiPart1Payload[FAPI_MAX_CSI_PART1_DATA_BYTES]; // 5G FAPI Table 3-71
+    } fapi_csi_p1_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t csiPart2Crc;
+        uint8_t pad;
+        uint16_t csiPart2BitLen;
+        uint8_t csiPart2Payload[FAPI_MAX_CSI_PART2_DATA_BYTES]; // 5G FAPI Table 3-72
+    } fapi_csi_p2_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+
+        uint32_t handle;
+        uint8_t pduBitmap;
+        uint8_t ul_cqi;
+        uint16_t rnti;
+        uint16_t timingAdvance;
+        uint16_t rssi;          // 5G FAPI Table 3-64
+        fapi_harq_info_t harqInfo;  // This is included if indicated by the pduBitmap
+        fapi_csi_p1_info_t csiPart1info;    // This is included if indicated by the pduBitmap
+        fapi_csi_p2_info_t csiPart2info;    // This is included if indicated by the pduBitmap
+    } fapi_uci_o_pusch_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t srIndication;
+        uint8_t srConfidenceLevel;  // 5G FAPI Table 3-67
+        uint8_t pad[2];
+    } fapi_sr_f0f1_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t numHarq;
+        uint8_t harqConfidenceLevel;
+        uint8_t harqValue[FAPI_MAX_NUMBER_OF_HARQS_PER_IND];    // 5G FAPI Table 3-68
+    } fapi_harq_f0f1_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t srBitlen;
+        uint8_t srPayload[FAPI_MAX_SR_PAYLOAD_SIZE + 1];    // 5G FAPI Table 3-69
+    } fapi_sr_f2f3f4_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t harqCrc;
+        uint8_t pad;
+        uint16_t harqBitLen;
+        uint8_t harqPayload[FAPI_MAX_HARQ_PAYLOAD_SIZE + 2];    // 5G FAPI Table 3-70
+    } fapi_harq_f2f3f4_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint32_t handle;
+        uint8_t pduBitmap;
+        uint8_t pucchFormat;
+        uint8_t ul_cqi;
+        uint8_t pad;
+        uint16_t rnti;
+        uint16_t timingAdvance;
+        uint16_t rssi;          // 5G FAPI Table 3-66
+        uint16_t num_uci_bits;
+        uint8_t uciBits[FAPI_MAX_UCI_BIT_BYTE_LEN];
+    } fapi_uci_o_pucch_f2f3f4_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint32_t handle;
+        uint8_t pduBitmap;
+        uint8_t pucchFormat;
+        uint8_t ul_cqi;
+        uint8_t pad;
+        uint16_t rnti;
+        uint16_t timingAdvance;
+        uint16_t rssi;          // 5G FAPI Table 3-65
+        uint8_t pad1[2];
+        uint8_t uciBits[FAPI_MAX_UCI_BIT_BYTE_LEN];
+        fapi_sr_f0f1_info_t srInfo; // This is included if indicated by the pduBitmap
+        fapi_harq_f0f1_info_t harqInfo; // This is included if indicated by the pduBitmap
+    } fapi_uci_o_pucch_f0f1_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t pduType;
+        uint16_t pduSize;
+        union {
+            fapi_uci_o_pusch_t uciPusch;
+            fapi_uci_o_pucch_f0f1_t uciPucchF0F1;
+            fapi_uci_o_pucch_f2f3f4_t uciPucchF2F3F4;   // 5G FAPI Table 3-63 subset
+        } uci;
+    } fapi_uci_pdu_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint16_t numUcis;       // 5G FAPI Table 3-63
+        uint8_t pad[2];
+        fapi_uci_pdu_info_t uciPdu[FAPI_MAX_NUMBER_UCI_PDUS_PER_SLOT];
+    } fapi_uci_indication_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t numRbs;
+        uint8_t pad[2];
+        uint8_t rbSNR[FAPI_MAX_NUMBER_RBS]; // 5G FAPI Table 3-73 Subset
+    } fapi_symb_snr_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint32_t handle;
+        uint16_t rnti;
+        uint16_t timingAdvance;
+        uint8_t numSymbols;
+        uint8_t wideBandSnr;
+        uint8_t numReportedSymbols;
+        uint8_t pad;
+        fapi_symb_snr_t symbSnr[FAPI_MAX_NUMBER_OF_REP_SYMBOLS];    // 5G FAPI Table 3-73 subset
+    } fapi_srs_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint8_t numPdus;
+        uint8_t pad[3];
+        fapi_srs_pdu_t srsPdus[FAPI_MAX_NUMBER_SRS_PDUS_PER_SLOT];  // 5G FAPI Table 3-73
+    } fapi_srs_indication_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint8_t preambleIndex;
+        uint8_t pad;
+        uint16_t timingAdvance;
+        uint32_t preamblePwr;   // 5G FAPI Table 3-74 Subset
+    } fapi_preamble_info_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        uint16_t phyCellId;
+        uint8_t symbolIndex;
+        uint8_t slotIndex;
+        uint8_t freqIndex;
+        uint8_t avgRssi;
+        uint8_t avgSnr;
+        uint8_t numPreamble;
+        fapi_preamble_info_t preambleInfo[FAPI_MAX_NUM_PREAMBLES_PER_SLOT]; // 5G FAPI Table 3-74 Subset
+    } fapi_rach_pdu_t;
+
+// Updated per 5G FAPI
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint8_t numPdus;
+        uint8_t pad[3];
+        fapi_rach_pdu_t rachPdu[FAPI_MAX_NUMBER_RACH_PDUS_PER_SLOT];    // 5G FAPI Table 3-74
+    } fapi_rach_indication_t;
+
+//Vendor extension messages
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint32_t test_type;
+    } fapi_vendor_ext_shutdown_req_t;
+
+    typedef struct {
+        fapi_msg_t header;
+        uint16_t sfn;
+        uint16_t slot;
+        uint32_t nStatus;
+    } fapi_vendor_ext_shutdown_res_t;
+
+#ifdef DEBUG_MODE
+    typedef struct {
+        uint32_t carrNum;
+        uint32_t numSubframes;
+        uint32_t testUeMode;
+        uint32_t timerModeFreqDomain;
+        uint32_t phaseCompensationEnable;
+        uint32_t startFrameNum;
+        uint32_t startSlotNum;
+        char filename_in_ul_iq[FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS]
+            [FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_in_ul_urllc[FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS]
+            [FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_in_prach_iq[FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS]
+            [FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_in_srs_iq[FAPI_MAX_IQ_SAMPLE_UL_ANTENNA]
+            [FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_out_dl_iq[FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_out_dl_iq_urllc[FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_out_dl_beam[FAPI_MAX_IQ_SAMPLE_DL_PORTS]
+            [FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        char filename_out_ul_beam[FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS]
+            [FAPI_MAX_IQ_SAMPLE_FILE_SIZE];
+        uint8_t buffer[FAPI_MAX_IQ_SAMPLE_BUFFER_SIZE];
+    } fapi_vendor_ext_iq_samples_info_t;
+
+    typedef struct {
+        fapi_msg_t header;
+        fapi_vendor_ext_iq_samples_info_t iq_samples_info;
+    } fapi_vendor_ext_iq_samples_req_t;
+
+    typedef struct {
+        fapi_msg_t header;
+    } fapi_vendor_ext_dl_iq_samples_res_t;
+
+    typedef struct {
+        fapi_msg_t header;
+    } fapi_vendor_ext_ul_iq_samples_res_t;
+
+    typedef struct {
+        fapi_msg_t header;
+    } fapi_vendor_ext_start_response_t;
+#endif
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/fapi_5g/source/api/fapi2mac/nr5g_fapi_fapi2mac_api.c b/fapi_5g/source/api/fapi2mac/nr5g_fapi_fapi2mac_api.c
new file mode 100644 (file)
index 0000000..9ac2892
--- /dev/null
@@ -0,0 +1,162 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file contains implementation of all the functions used 
+ * to send APIs from FAPI to MAC
+ *
+ **/
+
+#include <stdio.h>
+#include "nr5g_fapi_internal.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_wls.h"
+
+static nr5g_fapi_fapi2mac_queue_t fapi2mac_q[FAPI_MAX_PHY_INSTANCES];
+
+//------------------------------------------------------------------------------
+/** @ingroup     group_source_api_fapi2phy
+ *
+ *  @param[in]   p_list_elem Pointer to the ListElement
+ *
+ *  @return      void
+ *
+ *  @description This function adds a ListElement API to a Linked list which will
+ *               be sent to L1 once all APIs for a TTI are added
+ *
+**/
+//------------------------------------------------------------------------------
+inline p_nr5g_fapi_fapi2mac_queue_t nr5g_fapi_fapi2mac_queue(
+    uint8_t phy_id)
+{
+    return &fapi2mac_q[phy_id];
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup     group_lte_source_phy_fapi
+ *
+ *  @param[in]   pListElem Pointer to the ListElement
+ *
+ *  @return      void
+ *
+ *  @description This function adds a ListElement API to a Linked list which will
+ *               be sent to L1 once all APIs for a TTI are added
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_fapi2mac_add_api_to_list(
+    uint8_t phy_id,
+    p_fapi_api_queue_elem_t p_list_elem)
+{
+    p_nr5g_fapi_fapi2mac_queue_t queue = NULL;
+    p_fapi_msg_header_t p_fapi_msg_hdr = NULL;
+
+    if (!p_list_elem) {
+        return;
+    }
+
+    queue = nr5g_fapi_fapi2mac_queue(phy_id);
+    if (queue->p_send_list_head && queue->p_send_list_tail) {
+        p_fapi_msg_hdr = (p_fapi_msg_header_t) (queue->p_send_list_head + 1);
+        p_fapi_msg_hdr->num_msg += 1;
+        queue->p_send_list_tail->p_next = p_list_elem;
+        queue->p_send_list_tail = p_list_elem;
+    } else {
+        queue->p_send_list_head = queue->p_send_list_tail = p_list_elem;
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup      group_lte_source_phy_fapi
+ *
+ *  @param        A pointer to phy Instance
+ *
+ *  @return       FAPI status
+ *
+ *  @description  This function send API list to L1
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_fapi2mac_send_api_list(
+    )
+{
+    uint8_t phy_id = 0;
+    p_fapi_api_queue_elem_t p_commit_list_head = NULL;
+    p_fapi_api_queue_elem_t p_commit_list_tail = NULL;
+    p_nr5g_fapi_fapi2mac_queue_t queue = NULL;
+
+    for (phy_id = 0; phy_id < FAPI_MAX_PHY_INSTANCES; phy_id++) {
+        queue = nr5g_fapi_fapi2mac_queue(phy_id);
+        if (queue->p_send_list_head && queue->p_send_list_tail) {
+            if (p_commit_list_head && p_commit_list_tail) {
+                p_commit_list_tail->p_next = queue->p_send_list_head;
+                p_commit_list_tail = queue->p_send_list_tail;
+            } else {
+                p_commit_list_head = queue->p_send_list_head;
+                p_commit_list_tail = queue->p_send_list_tail;
+            }
+            queue->p_send_list_head = queue->p_send_list_tail = NULL;
+        }
+    }
+
+    if (p_commit_list_head)
+        nr5g_fapi_fapi2mac_wls_send(p_commit_list_head);
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup     group_lte_source_phy_fapi
+ *
+ *  @param[in]   phyInstance PhyInstance Id
+ *  @param[in]   NumMessageInBlock Number of Messages in Block
+ *  @param[in]   AlignOffset Align Offset
+ *  @param[in]   MsgType Message Type
+ *  @param[in]   FrameNum Frame Number
+ *  @param[in]   subFrameNum subframe Number
+ *
+ *  @return      Pointer to the List Element structure
+ *
+ *  @description This function allocates a buffer from shared memory WLS
+ *               interface and creates a List Element structures. It then fills
+ *               all the fields with data being passed in.
+ *
+**/
+//------------------------------------------------------------------------------
+p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_create_api_list_elem(
+    uint32_t msg_type,
+    uint16_t num_message_in_block,
+    uint32_t align_offset)
+{
+    p_fapi_api_queue_elem_t p_list_elem = NULL;
+
+    p_list_elem = (p_fapi_api_queue_elem_t)
+        nr5g_fapi_fapi2mac_wls_alloc_buffer();
+    //Fill header for link list of API messages
+    if (p_list_elem) {
+        p_list_elem->msg_type = (uint8_t) msg_type;
+        p_list_elem->num_message_in_block = num_message_in_block;
+        p_list_elem->align_offset = (uint16_t) align_offset;
+        p_list_elem->msg_len = num_message_in_block * align_offset;
+        p_list_elem->p_next = NULL;
+        p_list_elem->p_tx_data_elm_list = NULL;
+        p_list_elem->time_stamp = 0;
+    }
+
+    return p_list_elem;
+}
+
diff --git a/fapi_5g/source/api/fapi2mac/nr5g_fapi_fapi2mac_api.h b/fapi_5g/source/api/fapi2mac/nr5g_fapi_fapi2mac_api.h
new file mode 100644 (file)
index 0000000..dc0b7ee
--- /dev/null
@@ -0,0 +1,49 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file defines all the functions used to send APIs
+ * from FAPI to MAC
+ *
+ **/
+
+#ifndef NR5G_FAPI_FAPI2MAC_API_H
+#define NR5G_FAPI_FAPI2MAC_API_H
+
+#include "fapi_interface.h"
+
+typedef struct _nr5g_fapi_fapi2mac_queue {
+    p_fapi_api_queue_elem_t p_send_list_head;   // list head to, send to MAC
+    p_fapi_api_queue_elem_t p_send_list_tail;   // list tail to, send to MAC
+} nr5g_fapi_fapi2mac_queue_t, *p_nr5g_fapi_fapi2mac_queue_t;
+
+// Function definitions
+// -----------------------------------------------------------------------------
+p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_create_api_list_elem(
+    uint32_t msg_type,
+    uint16_t num_message_in_block,
+    uint32_t align_offset);
+
+void nr5g_fapi_fapi2mac_send_api_list(
+    );
+
+void nr5g_fapi_fapi2mac_add_api_to_list(
+    uint8_t phy_id,
+    p_fapi_api_queue_elem_t p_list_elem);
+
+#endif
diff --git a/fapi_5g/source/api/fapi2mac/nr5g_fapi_proc_error_ind.c b/fapi_5g/source/api/fapi2mac/nr5g_fapi_proc_error_ind.c
new file mode 100644 (file)
index 0000000..8759ca5
--- /dev/null
@@ -0,0 +1,99 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI ERROR.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_proc_error_ind.h"
+
+ /** @ingroup group_source_api_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_iapi_resp Pointer to IAPI ERROR.indication message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows PHY to report errors to L2/L3.
+ *
+**/
+uint8_t nr5g_fapi_error_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PERRORIndicationStruct p_iapi_resp)
+{
+    uint8_t phy_id;
+    fapi_error_ind_t *p_fapi_error_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI] [ERROR.indication] Invalid handle to "
+                "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI] [ERROR.indication] Invalid handle to iapi "
+                "stop indication message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != p_iapi_resp->sSFN_Slot.nCarrierIdx) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI] [ERROR.indication] Invalid handle"
+                "to phy instance"));
+        return FAILURE;
+    }
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_ERROR_INDICATION, 1,
+        sizeof(fapi_error_ind_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI] [ERROR.indication] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_error_ind = (fapi_error_ind_t *) (p_list_elem + 1);
+    p_fapi_error_ind->header.msg_id = FAPI_ERROR_INDICATION;
+    p_fapi_error_ind->header.length = p_iapi_resp->sMsgHdr.nMessageLen;
+    p_fapi_error_ind->sfn = p_iapi_resp->sSFN_Slot.nSFN;
+    p_fapi_error_ind->slot = p_iapi_resp->sSFN_Slot.nSlot;
+    // p_fapi_error_ind->message_id     =   ; // TODO message id is not supported in IAPI error indication
+    p_fapi_error_ind->error_code = p_iapi_resp->nStatus;
+
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    // phyStats->iaL1ApiStats.errorInd++; //TODO
+    NR5G_FAPI_LOG(INFO_LOG, ("[NR5G_FAPI][ERROR.indication][%d][%d,%d]",
+                p_phy_instance->phy_id,
+                p_iapi_resp->sSFN_Slot.nSFN,
+                p_iapi_resp->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/nr5g_fapi_proc_error_ind.h b/fapi_5g/source/api/fapi2mac/nr5g_fapi_proc_error_ind.h
new file mode 100644 (file)
index 0000000..7706db8
--- /dev/null
@@ -0,0 +1,33 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * Error indication message
+ *
+ **/
+
+#ifndef _NR5G_FAPI_PROC_ERROR_IND_H_
+#define _NR5G_FAPI_PROC_ERROR_IND_H_
+
+uint8_t nr5g_fapi_error_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PERRORIndicationStruct p_iapi_resp);
+
+#endif                          //_NR5G_FAPI_PROC_ERROR_IND_H_
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_fapi2mac_p5_proc.h b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_fapi2mac_p5_proc.h
new file mode 100644 (file)
index 0000000..1f1cc7b
--- /dev/null
@@ -0,0 +1,66 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to MAC P5 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2MAC_P5_PROC_H_
+#define _NR5G_FAPI_FAP2MAC_P5_PROC_H_
+
+#include "gnb_l1_l2_api.h"
+
+uint8_t nr5g_fapi_message_header(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx);
+
+uint8_t nr5g_fapi_message_header_per_phy(
+    uint8_t phy_id);
+
+uint8_t nr5g_fapi_config_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PCONFIGRESPONSEStruct p_iapi_resp);
+
+uint8_t nr5g_fapi_stop_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSTOPRESPONSEStruct p_iapi_resp);
+
+uint8_t nr5g_fapi_shutdown_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSHUTDOWNRESPONSEStruct p_iapi_resp);
+
+#ifdef DEBUG_MODE
+uint8_t nr5g_fapi_start_resp(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSTARTRESPONSEStruct p_iapi_resp);
+
+uint8_t nr5g_fapi_dl_iq_samples_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PADD_REMOVE_BBU_CORES p_iapi_resp);
+
+uint8_t nr5g_fapi_ul_iq_samples_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PADD_REMOVE_BBU_CORES p_iapi_resp);
+
+uint8_t nr5g_fapi_message_header_for_ul_iq_samples(
+    uint8_t phy_id);
+
+#endif
+#endif                          //_NR5G_FAPI_FAP2MAC_P5_PROC_H_
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_config_resp.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_config_resp.c
new file mode 100644 (file)
index 0000000..a7669ac
--- /dev/null
@@ -0,0 +1,106 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI CONFIG.response message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+
+ /** @ingroup group_source_api_p5_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_resp Pointer to IAPI CONFIG.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows PHY to report L2/L3 about CONFIG.request's status.
+ *
+**/
+uint8_t nr5g_fapi_config_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PCONFIGRESPONSEStruct p_iapi_resp)
+{
+    uint8_t phy_id;
+    fapi_config_resp_t *p_fapi_resp;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.response] Invalid " "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.response] Invalid iapi "
+                "config response message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.response] Invalid " "phy instance"));
+        return FAILURE;
+    }
+    // Create FAPI message header
+    if (FAPI_STATE_IDLE == p_phy_instance->state)
+        nr5g_fapi_message_header_per_phy(phy_id);
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_config_res++;
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_CONFIG_RESPONSE, 1,
+        sizeof(fapi_config_resp_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.response] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_resp = (fapi_config_resp_t *) (p_list_elem + 1);
+    p_fapi_resp->header.msg_id = FAPI_CONFIG_RESPONSE;
+    p_fapi_resp->header.length = (uint16_t) sizeof(fapi_config_resp_t);
+    p_fapi_resp->error_code = p_iapi_resp->nStatus;
+
+    if (FAPI_STATE_IDLE == p_phy_instance->state && 0 == p_iapi_resp->nStatus) {
+        p_phy_ctx->num_phy_instance += 1;
+        p_phy_instance->state = FAPI_STATE_CONFIGURED;
+    }
+    // TODO: Update phy_id to 0 in phy_instance on error.
+
+    /* TLV report is not supported in PHY */
+    p_fapi_resp->number_of_invalid_tlvs = 0;
+    p_fapi_resp->number_of_inv_tlvs_idle_only = 0;
+    p_fapi_resp->number_of_inv_tlvs_running_only = 0;
+    p_fapi_resp->number_of_missing_tlvs = 0;
+
+    // Add element to send list
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_config_res++;
+    NR5G_FAPI_LOG(INFO_LOG, ("[CONFIG.response][%d]", phy_id));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_dl_iq_samples_resp.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_dl_iq_samples_resp.c
new file mode 100644 (file)
index 0000000..ac0ab4b
--- /dev/null
@@ -0,0 +1,92 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI DL_IQ_SAMPLES.response message.
+ *
+ **/
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+
+#ifdef DEBUG_MODE
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_fapi_resp Pointer to IAPI DL_IQ_SAMPLES.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This timer mode vendor specific message used for acknowledging the DL_IQ_SAMPLES.Request
+ *  message used by TestMAC to validate Downlink messages
+ *
+**/
+uint8_t nr5g_fapi_dl_iq_samples_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PADD_REMOVE_BBU_CORES p_iapi_resp)
+{
+    uint8_t phy_id;
+    fapi_vendor_ext_dl_iq_samples_res_t *p_fapi_resp;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_SAMPLES.response] Invalid "
+                "phy ctx"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_SAMPLES.response] Invalid iapi "
+                "message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_SAMPLES.response] Invalid "
+                "phy instance"));
+        return FAILURE;
+    }
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_VENDOR_EXT_DL_IQ_SAMPLES,
+        1, sizeof(fapi_vendor_ext_dl_iq_samples_res_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_SAMPLES.response] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_resp = (fapi_vendor_ext_dl_iq_samples_res_t *) (p_list_elem + 1);
+    p_fapi_resp->header.msg_id = FAPI_VENDOR_EXT_DL_IQ_SAMPLES;
+    p_fapi_resp->header.length =
+        (uint16_t) sizeof(fapi_vendor_ext_dl_iq_samples_res_t);
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    NR5G_FAPI_LOG(INFO_LOG, ("[DL_IQ_SAMPLES.response][%d]", phy_id));
+
+    return SUCCESS;
+}
+#endif
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_fapi_msg_header.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_fapi_msg_header.c
new file mode 100644 (file)
index 0000000..e5c5810
--- /dev/null
@@ -0,0 +1,111 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI CONFIG.response message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+#include "nr5g_fapi_internal.h"
+
+ /** @ingroup group_source_api_p5_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_resp Pointer to IAPI CONFIG.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This Message is the FAPI Message Header.
+ *
+**/
+uint8_t nr5g_fapi_message_header(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx)
+{
+    uint8_t phy_id = 0;
+
+    p_fapi_api_queue_elem_t p_list_elem = NULL;
+    p_fapi_msg_header_t p_fapi_msg_hdr = NULL;
+
+    for (phy_id = 0; phy_id < FAPI_MAX_PHY_INSTANCES; phy_id++) {
+        if ((FAPI_STATE_CONFIGURED == p_phy_ctx->phy_instance[phy_id].state) ||
+            (FAPI_STATE_RUNNING == p_phy_ctx->phy_instance[phy_id].state)) {
+            p_list_elem =
+                nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_MSG_HEADER_IND, 1,
+                sizeof(fapi_msg_header_t));
+            if (!p_list_elem) {
+                NR5G_FAPI_LOG(ERROR_LOG, ("[FAPI MSG HDR] Unable to create "
+                        "list element. Out of memory!!!"));
+                return FAILURE;
+            }
+
+            p_fapi_msg_hdr = (fapi_msg_header_t *) (p_list_elem + 1);
+            p_fapi_msg_hdr->num_msg = 0;
+            p_fapi_msg_hdr->handle = phy_id;
+
+            // Add element to send list
+            nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+            NR5G_FAPI_LOG(DEBUG_LOG,
+                ("[FAPI MSG HDR] FAPI Message Header Added for PHY: %d",
+                    phy_id));
+        }
+    }
+
+    return SUCCESS;
+}
+
+/** @ingroup group_source_api_p5_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_resp Pointer to IAPI CONFIG.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This Message is the FAPI Message Header.
+ *
+**/
+uint8_t nr5g_fapi_message_header_per_phy(
+    uint8_t phy_id)
+{
+    p_fapi_api_queue_elem_t p_list_elem = NULL;
+    p_fapi_msg_header_t p_fapi_msg_hdr = NULL;
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_MSG_HEADER_IND, 1,
+        sizeof(fapi_msg_header_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[FAPI MSG HDR] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_msg_hdr = (fapi_msg_header_t *) (p_list_elem + 1);
+    p_fapi_msg_hdr->num_msg = 0;
+    p_fapi_msg_hdr->handle = phy_id;
+
+    // Add element to send list
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+    NR5G_FAPI_LOG(DEBUG_LOG,
+        ("[FAPI MSG HDR] FAPI Message Header Added for PHY: %d", phy_id));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_shutdown_resp.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_shutdown_resp.c
new file mode 100644 (file)
index 0000000..ce7cfb1
--- /dev/null
@@ -0,0 +1,174 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI SHUTDOWN.response message.
+ *
+ **/
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+#include "nr5g_fapi_stats.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_fapi_resp Pointer to IAPI SHUTDOWN.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows PHY to indicate whether it has successfully cleaned up 
+ *  the PHY resources alloted or not.
+ *
+**/
+uint8_t nr5g_fapi_shutdown_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSHUTDOWNRESPONSEStruct p_iapi_resp)
+{
+    uint8_t phy_id;
+#ifdef DEBUG_MODE
+    fapi_vendor_ext_shutdown_res_t *p_fapi_resp;
+#else
+    fapi_stop_ind_t *p_stop_ind;
+#endif
+    fapi_error_ind_t *p_fapi_error_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.response] Invalid "
+                "phy instance"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.response] Invalid iapi "
+                "shutdown response message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.response] Invalid "
+                "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_shutdown_res++;
+
+    if (p_iapi_resp->nStatus == SUCCESS) {
+#ifdef DEBUG_MODE
+        p_list_elem =
+            nr5g_fapi_fapi2mac_create_api_list_elem(
+                    FAPI_VENDOR_EXT_SHUTDOWN_RESPONSE, 1,
+                    sizeof(fapi_vendor_ext_shutdown_res_t));
+        if (!p_list_elem) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.response] Unable to create "
+                    "list element. Out of memory!!!"));
+            return FAILURE;
+        }
+
+        p_fapi_resp = (fapi_vendor_ext_shutdown_res_t *) (p_list_elem + 1);
+        p_fapi_resp->header.msg_id = FAPI_VENDOR_EXT_SHUTDOWN_RESPONSE;
+        p_fapi_resp->header.length =
+            (uint16_t) sizeof(fapi_vendor_ext_shutdown_res_t);
+        p_fapi_resp->sfn = p_iapi_resp->sSFN_Slot.nSFN;
+        p_fapi_resp->slot = p_iapi_resp->sSFN_Slot.nSlot;
+        p_fapi_resp->nStatus = p_iapi_resp->nStatus;
+
+        /* Add element to send list */
+        nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+        p_stats->fapi_stats.fapi_vext_shutdown_res++;
+        NR5G_FAPI_LOG(INFO_LOG, ("[SHUTDOWN.response][%d]", phy_id));
+        p_phy_instance->shutdown_retries = 0;
+#else
+        p_list_elem =
+            nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_STOP_INDICATION, 1,
+            sizeof(fapi_stop_ind_t));
+        if (!p_list_elem) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[SHUTDOWN.response][STOP.Indication] Unable to create "
+                    "list element. Out of memory!!!"));
+            return FAILURE;
+        }
+        p_stop_ind = (fapi_stop_ind_t *) (p_list_elem + 1);
+        p_stop_ind->header.msg_id = FAPI_STOP_INDICATION;
+        p_stop_ind->header.length = sizeof(fapi_stop_ind_t);
+
+        /* Add element to send list */
+        nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+        p_stats->fapi_stats.fapi_stop_ind++;
+        NR5G_FAPI_LOG(INFO_LOG, ("[STOP.Indication][%d]", phy_id));
+        p_phy_instance->shutdown_retries = 0;
+#endif
+    } else {
+        /* PHY SHUTDOWN  Failed. Retrigger Shutdown request for 3 tries before
+         * triggering error indication towards  L2 */
+        p_phy_instance->shutdown_retries++;
+        if (p_phy_instance->shutdown_retries <= 3) {
+            fapi_vendor_ext_shutdown_req_t fapi_req;
+            fapi_req.header.msg_id = FAPI_VENDOR_EXT_SHUTDOWN_REQUEST;
+            fapi_req.header.length = sizeof(fapi_vendor_ext_shutdown_req_t);
+            fapi_req.sfn = 0;
+            fapi_req.slot = 0;
+            fapi_req.test_type = p_phy_instance->shutdown_test_type;
+            nr5g_fapi_shutdown_request(p_phy_instance, &fapi_req);
+        } else {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.response] Invalid status "
+                    "from PHY, hence triggering Error Indication"));
+            p_list_elem =
+                nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_ERROR_INDICATION,
+                1, sizeof(fapi_error_ind_t));
+
+            if (!p_list_elem) {
+                NR5G_FAPI_LOG(ERROR_LOG,
+                    ("[SHUTDOWN.response][Error.Indication] Unable to create "
+                        "list element. Out of memory!!!"));
+                return FAILURE;
+            }
+            p_fapi_error_ind = (fapi_error_ind_t *) (p_list_elem + 1);
+            p_fapi_error_ind->header.msg_id = FAPI_ERROR_INDICATION;
+            p_fapi_error_ind->header.length =
+                (uint16_t) sizeof(fapi_error_ind_t);
+            p_fapi_error_ind->sfn = p_iapi_resp->sSFN_Slot.nSFN;
+            p_fapi_error_ind->slot = p_iapi_resp->sSFN_Slot.nSlot;
+            p_fapi_error_ind->message_id = FAPI_VENDOR_EXT_SHUTDOWN_REQUEST;
+            p_fapi_error_ind->error_code = p_iapi_resp->nStatus;
+
+            /* Add element to send list */
+            nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+            p_stats->fapi_stats.fapi_error_ind++;
+            p_phy_instance->shutdown_retries = 0;
+            NR5G_FAPI_LOG(INFO_LOG, ("[Error.Indication][%d]", phy_id));
+        }
+    }
+
+    nr5g_fapi_print_phy_instance_stats(p_phy_instance);
+    NR5G_FAPI_MEMSET(&p_phy_instance->stats, sizeof(nr5g_fapi_stats_t), 0,
+        sizeof(nr5g_fapi_stats_t));
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_start_resp.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_start_resp.c
new file mode 100644 (file)
index 0000000..ad0b291
--- /dev/null
@@ -0,0 +1,127 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI STOP.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+
+/** @ingroup group_source_api_p5_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_fapi_resp Pointer to IAPI START.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows PHY to indicate that it has successfully started PHY
+ *  
+ *
+**/
+uint8_t nr5g_fapi_start_resp(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSTARTRESPONSEStruct p_iapi_resp)
+{
+    uint8_t phy_id;
+    fapi_vendor_ext_start_response_t *p_fapi_resp;
+    fapi_error_ind_t *p_fapi_error_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.response] Invalid " "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.response] Invalid "
+                "start response message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.response] Invalid  " "phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_start_res++;
+    if (0 == p_iapi_resp->nStatus) {
+        if (FAPI_STATE_CONFIGURED == p_phy_instance->state) {
+            p_phy_instance->state = FAPI_STATE_RUNNING;
+        }
+#ifdef DEBUG_MODE
+        p_list_elem =
+            nr5g_fapi_fapi2mac_create_api_list_elem
+            (FAPI_VENDOR_EXT_START_RESPONSE, 1,
+            sizeof(fapi_vendor_ext_start_response_t));
+        if (!p_list_elem) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[START.Response] Unable to create "
+                    "list element. Out of memory!!!"));
+            return FAILURE;
+        }
+
+        p_fapi_resp = (fapi_vendor_ext_start_response_t *) (p_list_elem + 1);
+        p_fapi_resp->header.msg_id = FAPI_VENDOR_EXT_START_RESPONSE;
+        p_fapi_resp->header.length =
+            (uint16_t) sizeof(fapi_vendor_ext_start_response_t);
+
+        /* Add element to send list */
+        nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+        p_stats->fapi_stats.fapi_vext_start_res++;
+        NR5G_FAPI_LOG(INFO_LOG, ("[START.response][%d]", phy_id));
+#endif
+    } else if (1 == p_iapi_resp->nStatus) {
+        p_list_elem =
+            nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_ERROR_INDICATION, 1,
+            sizeof(fapi_error_ind_t));
+        if (!p_list_elem) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[START.response] Unable to create "
+                    "list element. Out of memory!!!"));
+            return FAILURE;
+        }
+
+        /* PHY STOP Failed. Sending Error Indication to MAC */
+        p_fapi_error_ind = (fapi_error_ind_t *) (p_list_elem + 1);
+        p_fapi_error_ind->header.msg_id = FAPI_ERROR_INDICATION;
+        p_fapi_error_ind->header.length = (uint16_t) sizeof(fapi_error_ind_t);
+        p_fapi_error_ind->sfn = p_iapi_resp->sSFN_Slot.nSFN;
+        p_fapi_error_ind->slot = p_iapi_resp->sSFN_Slot.nSlot;
+        p_fapi_error_ind->message_id = FAPI_START_REQUEST;
+        p_fapi_error_ind->error_code = p_iapi_resp->nStatus;
+
+        /* Add element to send list */
+        nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+        p_stats->fapi_stats.fapi_error_ind++;
+        NR5G_FAPI_LOG(INFO_LOG, ("[ERROR.Indication][%d]", phy_id));
+    } else {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.response] Invalid status "
+                "from PHY"));
+        return FAILURE;
+    }
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_stop_ind.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_stop_ind.c
new file mode 100644 (file)
index 0000000..0ed27b6
--- /dev/null
@@ -0,0 +1,122 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI STOP.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+
+/** @ingroup group_source_api_p5_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_fapi_resp Pointer to IAPI STOP.indication message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows PHY to indicate that it has successfully stopped
+ *  and returned to the CONFIGURED state. 
+ *
+**/
+uint8_t nr5g_fapi_stop_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSTOPRESPONSEStruct p_iapi_resp)
+{
+    uint8_t phy_id;
+
+    fapi_stop_ind_t *p_fapi_resp;
+    fapi_error_ind_t *p_fapi_error_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.indication] Invalid " "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.indication] Invalid "
+                "stop response message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.indication] Invalid " "phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_stop_ind++;
+    if (0 == p_iapi_resp->nStatus) {
+        if (FAPI_STATE_RUNNING == p_phy_instance->state) {
+            p_phy_instance->state = FAPI_STATE_CONFIGURED;
+        }
+        p_list_elem =
+            nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_STOP_INDICATION, 1,
+            sizeof(fapi_stop_ind_t));
+        if (!p_list_elem) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.indication] Unable to create "
+                    "list element. Out of memory!!!"));
+            return FAILURE;
+        }
+
+        p_fapi_resp = (fapi_stop_ind_t *) (p_list_elem + 1);
+        p_fapi_resp->header.msg_id = FAPI_STOP_INDICATION;
+        p_fapi_resp->header.length = (uint16_t) sizeof(fapi_stop_ind_t);
+        /* Add element to send list */
+        nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+        p_stats->fapi_stats.fapi_stop_ind++;
+        NR5G_FAPI_LOG(INFO_LOG, ("[STOP.indication][%d]", phy_id));
+    } else if (1 == p_iapi_resp->nStatus) {
+        p_list_elem =
+            nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_ERROR_INDICATION, 1,
+            sizeof(fapi_error_ind_t));
+        if (!p_list_elem) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.indication] Unable to create "
+                    "list element. Out of memory!!!"));
+            return FAILURE;
+        }
+
+        /* PHY STOP Failed. Sending Error Indication to MAC */
+        p_fapi_error_ind = (fapi_error_ind_t *) (p_list_elem + 1);
+        p_fapi_error_ind->header.msg_id = FAPI_ERROR_INDICATION;
+        p_fapi_error_ind->header.length = (uint16_t) sizeof(fapi_error_ind_t);
+        p_fapi_error_ind->sfn = p_iapi_resp->sSFN_Slot.nSFN;
+        p_fapi_error_ind->slot = p_iapi_resp->sSFN_Slot.nSlot;
+        p_fapi_error_ind->message_id = FAPI_STOP_REQUEST;
+        p_fapi_error_ind->error_code = p_iapi_resp->nStatus;
+        /* Add element to send list */
+        nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+        p_stats->fapi_stats.fapi_error_ind++;
+        NR5G_FAPI_LOG(INFO_LOG, ("[STOP.indication][ERROR.indication][%d]",
+                phy_id));
+    } else {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.indication] Invalid status "
+                "from PHY"));
+        return FAILURE;
+    }
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_ul_iq_samples_resp.c b/fapi_5g/source/api/fapi2mac/p5/nr5g_fapi_proc_ul_iq_samples_resp.c
new file mode 100644 (file)
index 0000000..94ebb4a
--- /dev/null
@@ -0,0 +1,95 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI ULIQ_Samples.response message.
+ *
+ **/
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+
+#ifdef DEBUG_MODE
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_resp Pointer to IAPI ULIQ_Samples.response message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This timer mode vendor specific message used for acknowledging the ULIQ_Samples.Request
+ *  message used by TestMAC to validate uplink message indications. 
+ *
+**/
+uint8_t nr5g_fapi_ul_iq_samples_response(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PADD_REMOVE_BBU_CORES p_iapi_resp)
+{
+    uint8_t phy_id;
+    fapi_vendor_ext_ul_iq_samples_res_t *p_fapi_resp;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_IQ_SAMPLES.response] Invalid handle to "
+                "phy instance"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_IQ_SAMPLES.response] Invalid iapi "
+                "ULIQ_Samples response message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, (" [UL_IQ_SAMPLES.response] Invalid "
+                "phy instance"));
+        return FAILURE;
+    }
+    // Create FAPI message header
+    if (p_phy_instance->state == FAPI_STATE_IDLE) {
+        nr5g_fapi_message_header_per_phy(phy_id);
+    }
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_VENDOR_EXT_UL_IQ_SAMPLES,
+        1, sizeof(fapi_vendor_ext_ul_iq_samples_res_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_IQ_SAMPLES.response] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_resp = (fapi_vendor_ext_ul_iq_samples_res_t *) (p_list_elem + 1);
+    p_fapi_resp->header.msg_id = FAPI_VENDOR_EXT_UL_IQ_SAMPLES;
+    p_fapi_resp->header.length =
+        (uint16_t) sizeof(fapi_vendor_ext_ul_iq_samples_res_t);
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    NR5G_FAPI_LOG(INFO_LOG, ("[UL_IQ_SAMPLES.response]%d]", phy_id));
+
+    return SUCCESS;
+}
+#endif
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_fapi2mac_p7_proc.h b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_fapi2mac_p7_proc.h
new file mode 100644 (file)
index 0000000..aaaae0d
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to MAC P7 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2MAC_P7_PROC_H_
+#define _NR5G_FAPI_FAP2MAC_P7_PROC_H_
+
+uint8_t nr5g_fapi_slot_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSlotIndicationStruct p_iapi_resp);
+uint8_t nr5g_fapi_rach_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXRACHIndicationStruct p_phy_rach_ind);
+uint8_t nr5g_fapi_crc_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PCRCIndicationStruct p_phy_crc_ind);
+uint8_t nr5g_fapi_rx_data_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXULSCHIndicationStruct p_phy_ulsch_ind);
+uint8_t nr5g_fapi_uci_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXUCIIndicationStruct p_phy_uci_ind);
+uint8_t nr5g_fapi_srs_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXSRSIndicationStruct p_phy_srs_ind);
+#endif                          //_NR5G_FAPI_FAP2MAC_P7_PROC_H_
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_fapi2mac_p7_pvt_proc.h b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_fapi2mac_p7_pvt_proc.h
new file mode 100644 (file)
index 0000000..121bafc
--- /dev/null
@@ -0,0 +1,62 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to PHY P7 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2MAC_P7_PVT_PROC_H_
+#define _NR5G_FAPI_FAP2MAC_P7_PVT_PROC_H_
+
+uint8_t nr5g_fapi_rach_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXRACHIndicationStruct p_phy_rach_ind,
+    fapi_rach_indication_t * p_fapi_rach_ind);
+
+uint8_t nr5g_fapi_crc_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PCRCIndicationStruct p_phy_crc_ind,
+    fapi_crc_ind_t * p_fapi_crc_ind);
+
+uint8_t nr5g_fapi_rx_data_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXULSCHIndicationStruct p_phy_rx_ulsch_ind,
+    fapi_rx_data_indication_t * p_fapi_rx_data_ind);
+
+uint8_t nr5g_fapi_uci_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXUCIIndicationStruct p_phy_uci_ind,
+    fapi_uci_indication_t * p_fapi_uci_ind);
+
+uint8_t nr5g_fapi_srs_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXSRSIndicationStruct p_phy_srs_ind,
+    fapi_srs_indication_t * p_fapi_srs_ind);
+
+nr5g_fapi_pusch_info_t *nr5g_fapi_get_pusch_info(
+    uint16_t ue_id,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info);
+
+nr5g_fapi_srs_info_t *nr5g_fapi_get_srs_info(
+    uint16_t nUEId,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info);
+
+#endif                          //_NR5G_FAPI_FAP2MAC_P7_PVT_PROC_H_
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_crc_ind.c b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_crc_ind.c
new file mode 100644 (file)
index 0000000..c934569
--- /dev/null
@@ -0,0 +1,181 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ * @file
+ * This file consist of implementation of FAPI CRC.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+#include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_phy_crc_ind Pointer to FAPI CRC.indication message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message includes CRC PDU.
+ *
+**/
+uint8_t nr5g_fapi_crc_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PCRCIndicationStruct p_phy_crc_ind)
+{
+    uint8_t phy_id;
+    fapi_crc_ind_t *p_fapi_crc_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CRC.indication] Invalid " "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_phy_crc_ind) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI [CRC.indication] Invalid Phy "
+                "CRC indication"));
+        return FAILURE;
+    }
+
+    phy_id = p_phy_crc_ind->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CRC.indication] Invalid " "phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_crc_ind++;
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_CRC_INDICATION, 1,
+        sizeof(fapi_crc_ind_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CRC.indication] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_crc_ind = (fapi_crc_ind_t *) (p_list_elem + 1);
+    p_fapi_crc_ind->header.msg_id = FAPI_CRC_INDICATION;
+    p_fapi_crc_ind->header.length = (uint16_t) sizeof(fapi_crc_ind_t);
+
+    if (nr5g_fapi_crc_indication_to_fapi_translation(p_phy_instance,
+            p_phy_crc_ind, p_fapi_crc_ind)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CRC.indication] L1 to FAPI "
+                "translation failed"));
+        return FAILURE;
+    }
+
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_crc_ind++;
+
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[CRC.indication][%d][%d,%d]",
+                p_phy_instance->phy_id,
+                p_phy_crc_ind->sSFN_Slot.nSFN,
+                p_phy_crc_ind->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]   p_phy_crc_ind Pointer to IAPI CRC.indication structure.
+ *  @param[out]  p_fapi_crc_ind Pointer to FAPI CRC.indication structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts IAPI CRC.indication to FAPI CRC.indication
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_crc_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PCRCIndicationStruct p_phy_crc_ind,
+    fapi_crc_ind_t * p_fapi_crc_ind)
+{
+    uint8_t num_crc, i;
+    uint8_t slot_no;
+    uint16_t frame_no;
+
+    nr5g_fapi_pusch_info_t *p_pusch_info;
+    fapi_crc_ind_info_t *p_fapi_crc_ind_info;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+    nr5g_fapi_stats_t *p_stats;
+    ULCRCStruct *p_ul_crc_struct;
+
+    p_stats = &p_phy_instance->stats;
+
+    frame_no = p_fapi_crc_ind->sfn = p_phy_crc_ind->sSFN_Slot.nSFN;
+    slot_no = p_fapi_crc_ind->slot = p_phy_crc_ind->sSFN_Slot.nSlot;
+
+    p_ul_slot_info =
+        nr5g_fapi_get_ul_slot_info(frame_no, slot_no, p_phy_instance);
+
+    if (p_ul_slot_info == NULL) {
+        NR5G_FAPI_LOG(ERROR_LOG, (" [CRC.indication] No Valid data available "
+                "for frame :%d and slot: %d", frame_no, slot_no));
+        return FAILURE;
+    }
+
+    num_crc = p_fapi_crc_ind->numCrcs = p_phy_crc_ind->nCrc;
+    for (i = 0; i < num_crc; i++) {
+        p_stats->iapi_stats.iapi_crc_ind_pdus++;
+
+        p_fapi_crc_ind_info = &p_fapi_crc_ind->crc[i];
+        p_ul_crc_struct = &p_phy_crc_ind->sULCRCStruct[i];
+        p_pusch_info =
+            nr5g_fapi_get_pusch_info(p_ul_crc_struct->nUEId, p_ul_slot_info);
+
+        if (p_pusch_info == NULL) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                (" [CRC.indication] No Valid data available "
+                    "nUEId:%d, frame_no:%d, slot_no:%d", p_ul_crc_struct->nUEId,
+                    frame_no, slot_no));
+            return FAILURE;
+        }
+
+        p_fapi_crc_ind_info->handle = p_pusch_info->handle;
+        p_fapi_crc_ind_info->rnti = p_ul_crc_struct->nRNTI;
+        p_fapi_crc_ind_info->harqId = p_pusch_info->harq_process_id;
+        p_fapi_crc_ind_info->tbCrcStatus = !(p_ul_crc_struct->nCrcFlag);
+        p_fapi_crc_ind_info->ul_cqi = (p_ul_crc_struct->nSNR + 64) * 2;
+        p_pusch_info->ul_cqi = p_fapi_crc_ind_info->ul_cqi;
+
+        p_fapi_crc_ind_info->numCb = 0;
+        p_pusch_info->timing_advance = p_fapi_crc_ind_info->timingAdvance = 31;
+#ifdef DEBUG_MODE
+        p_pusch_info->timing_advance = p_fapi_crc_ind_info->timingAdvance =
+            p_ul_crc_struct->nTA;
+#endif
+        p_fapi_crc_ind_info->rssi = 880;
+
+        p_stats->fapi_stats.fapi_crc_ind_pdus++;
+    }
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_rach_ind.c b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_rach_ind.c
new file mode 100644 (file)
index 0000000..bd40411
--- /dev/null
@@ -0,0 +1,231 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ * @file
+ * This file consist of implementation of FAPI RACH.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+#include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY Context.
+ *  @param[in]  p_phy_rach_ind Pointer to FAPI RACH.indication message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message includes RACH PDU. 
+ *
+**/
+uint8_t nr5g_fapi_rach_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXRACHIndicationStruct p_phy_rach_ind)
+{
+    uint8_t phy_id;
+
+    fapi_rach_indication_t *p_fapi_rach_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[RACH.indication] Invalid " "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_phy_rach_ind) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[RACH.indication] Invalid handle to phy "
+                "RACH indication"));
+        return FAILURE;
+    }
+
+    phy_id = p_phy_rach_ind->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if ((p_phy_instance->phy_id != phy_id)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[RACH.indication] Invalid " "phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_rach_ind++;
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_RACH_INDICATION, 1,
+        sizeof(fapi_rach_indication_t));
+
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[RACH.indication] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_rach_ind = (fapi_rach_indication_t *) (p_list_elem + 1);
+    p_fapi_rach_ind->header.msg_id = FAPI_RACH_INDICATION;
+    p_fapi_rach_ind->header.length = (uint16_t) sizeof(fapi_rach_indication_t);
+
+    if (nr5g_fapi_rach_indication_to_fapi_translation(p_phy_instance,
+            p_phy_rach_ind, p_fapi_rach_ind)) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[RACH.indication] L1 to FAPI " "translation failed"));
+        return FAILURE;
+    }
+
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_rach_ind++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[RACH.indication][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_phy_rach_ind->sSFN_Slot.nSFN, p_phy_rach_ind->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   slot_index Variable holding nStartSlotdx received in IAPI RACH.Indication.
+ *  @param[in]   freq_index Variable holding nFreqIdx received in IAPI RACH.Indication.
+ *  @param[in]   symbol_index Variable holding nSymbolIdx received in IAPI RACH.Indication.
+ *  @param[in]   num_pdus Variable holding the num_pdus filled in FAPI RACH.Indication till then.
+ *  @param[in]   p_fapi_rach_ind Pointer to FAPI RACH.indication structure.
+ *  
+ *  @return     Returns pdu_index at which slot_index and freq_index match occurs
+ *                         
+ *
+ *  @description
+ *  This function returns the pdu_index at which slot_index and freq_index match
+ *  occurs in FAPI RACH.Indication populated till then
+ *
+**/
+uint8_t nr5g_fapi_start_slot_freq_idx_occ(
+    uint8_t slot_index,
+    uint8_t freq_index,
+    uint8_t symbol_index,
+    uint8_t num_pdus,
+    fapi_rach_indication_t * p_fapi_rach_ind)
+{
+    uint8_t i, pdu_index = 0xFF;
+
+    fapi_rach_pdu_t *p_fapi_rach_pdu;
+
+    for (i = 0; i < num_pdus; i++) {
+        p_fapi_rach_pdu = &p_fapi_rach_ind->rachPdu[i];
+        if ((slot_index == p_fapi_rach_pdu->slotIndex)
+            && (freq_index == p_fapi_rach_pdu->freqIndex)
+            && (symbol_index == p_fapi_rach_pdu->symbolIndex)) {
+            pdu_index = i;
+            break;
+        }
+    }
+    return pdu_index;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]   p_phy_rach_ind Pointer to IAPI RACH.indication structure.
+ *  @param[out]  p_fapi_rach_ind Pointer to FAPI RACH.indication structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts IAPI RACH.indication to FAPI RACH.indication
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_rach_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXRACHIndicationStruct p_phy_rach_ind,
+    fapi_rach_indication_t * p_fapi_rach_ind)
+{
+    uint8_t num_preamble, num_pdus = 0, i;
+    uint8_t slot_no, preamble_no;
+    uint8_t slot_freq_idx_entry;
+    uint8_t slot_index, freq_index, symbol_index;
+    uint16_t frame_no;
+
+    fapi_rach_pdu_t *p_fapi_rach_pdu;
+    fapi_rach_pdu_t *p_fapi_rach_pdu_match;
+    fapi_preamble_info_t *p_fapi_preamble_info;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+    nr5g_fapi_stats_t *p_stats;
+    PreambleStruct *p_phy_preamble_struct;
+
+    p_stats = &p_phy_instance->stats;
+
+    frame_no = p_fapi_rach_ind->sfn = p_phy_rach_ind->sSFN_Slot.nSFN;
+    slot_no = p_fapi_rach_ind->slot = p_phy_rach_ind->sSFN_Slot.nSlot;
+
+    p_ul_slot_info =
+        nr5g_fapi_get_ul_slot_info(frame_no, slot_no, p_phy_instance);
+
+    if (p_ul_slot_info == NULL) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[RACH.indication] No Valid data available "
+                "for frame :%d and slot: %d", frame_no, slot_no));
+        return FAILURE;
+    }
+
+    if (p_ul_slot_info->rach_presence == 0) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[RACHindication] RACH is not requested"
+                "for frame :%d and slot: %d", frame_no, slot_no));
+        return FAILURE;
+    }
+
+    num_preamble = p_phy_rach_ind->nNrOfPreamb;
+    for (i = 0; i < num_preamble; i++) {
+        p_stats->iapi_stats.iapi_rach_preambles++;
+        p_phy_preamble_struct = &p_phy_rach_ind->sPreambleStruct[i];
+        slot_index = p_phy_preamble_struct->nStartSlotdx;
+        freq_index = p_phy_preamble_struct->nFreqIdx;
+        symbol_index = p_phy_preamble_struct->nStartSymbIdx;
+        //returns 0xFF if its a new preamble, else pdu index of p_fapi_rach_ind;
+        slot_freq_idx_entry = nr5g_fapi_start_slot_freq_idx_occ(slot_index,
+            freq_index, symbol_index, num_pdus, p_fapi_rach_ind);
+        if (slot_freq_idx_entry == 0xFF) {
+            p_fapi_rach_pdu = &p_fapi_rach_ind->rachPdu[i];
+            p_fapi_rach_pdu->phyCellId = p_ul_slot_info->rach_info.phy_cell_id;
+            p_fapi_rach_pdu->numPreamble = 0;
+            p_fapi_rach_pdu->symbolIndex = p_phy_preamble_struct->nStartSymbIdx;
+            p_fapi_rach_pdu->slotIndex = slot_index;
+            p_fapi_rach_pdu->freqIndex = freq_index;
+            p_fapi_rach_pdu->avgRssi = 0xFF;
+            p_fapi_rach_pdu->avgSnr = 0xFF;
+            preamble_no = p_fapi_rach_pdu->numPreamble++;
+            p_fapi_preamble_info = &p_fapi_rach_pdu->preambleInfo[preamble_no];
+            num_pdus++;
+            p_stats->fapi_stats.fapi_rach_ind_pdus++;
+        } else {
+            p_fapi_rach_pdu_match =
+                &p_fapi_rach_ind->rachPdu[slot_freq_idx_entry];
+            preamble_no = p_fapi_rach_pdu_match->numPreamble++;
+            p_fapi_preamble_info =
+                &p_fapi_rach_pdu_match->preambleInfo[preamble_no];
+        }
+        p_fapi_preamble_info->preambleIndex = p_phy_preamble_struct->nPreambIdx;
+        p_fapi_preamble_info->timingAdvance = p_phy_preamble_struct->nTa;
+        p_fapi_preamble_info->preamblePwr = p_phy_preamble_struct->nPreambPwr;
+    }
+    p_fapi_rach_ind->numPdus = num_pdus;
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_rx_data_ind.c b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_rx_data_ind.c
new file mode 100644 (file)
index 0000000..666e811
--- /dev/null
@@ -0,0 +1,211 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI CRC.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+#include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY Context.
+ *  @param[in]  p_phy_rx_data_ind Pointer to FAPI RX_DATA.indication message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message includes RX_DATA to be sent to L2.
+ *
+**/
+uint8_t nr5g_fapi_rx_data_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXULSCHIndicationStruct p_phy_rx_ulsch_ind)
+{
+    uint8_t phy_id;
+
+    fapi_rx_data_indication_t *p_fapi_rx_data_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] Invalid "
+                "Phy Context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_phy_rx_ulsch_ind) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] Invalid "
+                "RX_USLCH indication"));
+        return FAILURE;
+    }
+
+    phy_id = p_phy_rx_ulsch_ind->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] Invalid "
+                "handle to phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_rx_data_ind++;
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_RX_DATA_INDICATION, 1,
+        sizeof(fapi_rx_data_indication_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI][RX_DATA.indication] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_rx_data_ind = (fapi_rx_data_indication_t *) (p_list_elem + 1);
+    p_fapi_rx_data_ind->header.msg_id = FAPI_RX_DATA_INDICATION;
+    p_fapi_rx_data_ind->header.length =
+        (uint16_t) sizeof(fapi_rx_data_indication_t);
+
+    if (nr5g_fapi_rx_data_indication_to_fapi_translation(p_phy_instance,
+            p_phy_rx_ulsch_ind, p_fapi_rx_data_ind)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][RX_DATA.indication] L1 to FAPI "
+                "translation failed"));
+        return FAILURE;
+    }
+
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_rx_data_ind++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[NR5G_FAPI][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_phy_rx_ulsch_ind->sSFN_Slot.nSFN,
+            p_phy_rx_ulsch_ind->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   ue_id  Variable holding ue_id received in RX_DATA.Indication..
+ *  @param[in]   p_ul_slot_info Pointer to ul slot info structure that stores the 
+ *               UL_TTI.request PDU info.
+ *  
+ *  @return     Returns Pointer to pusch info, if handle of p_ul_slot_info matches ue_id.
+                        NULL, if handle of p_ul_slot_info not matches ue_id
+ *
+ *  @description
+ *  This function retrieves the pusch info stored during corresponding UL_TTI.request processing.  
+ *  based on ue_id.
+ *
+**/
+nr5g_fapi_pusch_info_t *nr5g_fapi_get_pusch_info(
+    uint16_t ue_id,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
+{
+    uint8_t i, num_ulsch;
+
+    nr5g_fapi_pusch_info_t *p_pusch_info;
+
+    num_ulsch = p_ul_slot_info->num_ulsch;
+    for (i = 0; i < num_ulsch; i++) {
+        p_pusch_info = &p_ul_slot_info->pusch_info[i];
+        if (p_pusch_info->handle == ue_id) {
+            return p_pusch_info;
+        }
+    }
+    return NULL;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   p_phy_instance Pointer to PHY instance.
+ *  @param[in]   p_phy_rx_ulsch_ind Pointer to IAPI RX_ULSCH.indication structure.
+ *  @param[out]  p_fapi_rx_data_ind Pointer to FAPI RX_DATA.indication structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts IAPI RX_DATA.indication to FAPI CRC.indication
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_rx_data_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXULSCHIndicationStruct p_phy_rx_ulsch_ind,
+    fapi_rx_data_indication_t * p_fapi_rx_data_ind)
+{
+    uint8_t num_ulsch, i;
+    uint8_t slot_no;
+    uint16_t frame_no;
+
+    nr5g_fapi_pusch_info_t *p_pusch_info;
+    fapi_pdu_ind_info_t *p_fapi_pdu_ind_info;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+    nr5g_fapi_stats_t *p_stats;
+    ULSCHPDUDataStruct *p_rx_ulsch_pdu_data;
+
+    p_stats = &p_phy_instance->stats;
+
+    frame_no = p_fapi_rx_data_ind->sfn = p_phy_rx_ulsch_ind->sSFN_Slot.nSFN;
+    slot_no = p_fapi_rx_data_ind->slot = p_phy_rx_ulsch_ind->sSFN_Slot.nSlot;
+
+    p_ul_slot_info =
+        nr5g_fapi_get_ul_slot_info(frame_no, slot_no, p_phy_instance);
+
+    if (p_ul_slot_info == NULL) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI] [RX_DATA.indication] No Valid data available "
+                "for frame :%d and slot: %d", frame_no, slot_no));
+        return FAILURE;
+    }
+
+    num_ulsch = p_fapi_rx_data_ind->numPdus = p_phy_rx_ulsch_ind->nUlsch;
+    for (i = 0; i < num_ulsch; i++) {
+        p_stats->iapi_stats.iapi_rx_data_ind_pdus++;
+        p_fapi_pdu_ind_info = &p_fapi_rx_data_ind->pdus[i];
+        p_rx_ulsch_pdu_data = &p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i];
+        p_pusch_info =
+            nr5g_fapi_get_pusch_info(p_rx_ulsch_pdu_data->nUEId,
+            p_ul_slot_info);
+        if (p_pusch_info == NULL) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[NR5G_FAPI] [RX_DATA.indication] No Valid data available "
+                    "nUEId:%d, frame_no:%d, slot_no:%d",
+                    p_rx_ulsch_pdu_data->nUEId, frame_no, slot_no));
+            return FAILURE;
+        }
+
+        p_fapi_pdu_ind_info->handle = p_pusch_info->handle;
+        p_fapi_pdu_ind_info->rnti = p_rx_ulsch_pdu_data->nRNTI;
+        p_fapi_pdu_ind_info->harqId = p_pusch_info->harq_process_id;
+        p_fapi_pdu_ind_info->ul_cqi = p_pusch_info->ul_cqi;
+        p_fapi_pdu_ind_info->timingAdvance = p_pusch_info->timing_advance;
+        p_fapi_pdu_ind_info->rssi = 880;
+        p_fapi_pdu_ind_info->pdu_length = p_rx_ulsch_pdu_data->nPduLen;
+        p_fapi_pdu_ind_info->pduData = (void *)p_rx_ulsch_pdu_data->pPayload;
+
+        p_stats->fapi_stats.fapi_rx_data_ind_pdus++;
+    }
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_slot_ind.c b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_slot_ind.c
new file mode 100644 (file)
index 0000000..9a01e02
--- /dev/null
@@ -0,0 +1,99 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI SLOT.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx   Pointer to PHY context.
+ *  @param[in]  p_fapi_resp Pointer to IAPI SLOT.indication message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows PHY to send slot indication message periodically 
+ *  to L2/L3 based on the highest numerology cconfigured in CONFIG.request
+ *
+**/
+uint8_t nr5g_fapi_slot_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PSlotIndicationStruct p_iapi_resp)
+{
+    uint8_t phy_id;
+
+    fapi_slot_ind_t *p_fapi_slot_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SLOT.indication] Invalid handle to "
+                "phy context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_iapi_resp) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SLOT.indication] Invalid handle to iapi "
+                "slot indication message"));
+        return FAILURE;
+    }
+
+    phy_id = p_iapi_resp->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if ((p_phy_instance->phy_id != phy_id)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SLOT.indication] Invalid " "phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_slot_ind++;
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_SLOT_INDICATION, 1,
+        sizeof(fapi_slot_ind_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SLOT.indication] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_slot_ind = (fapi_slot_ind_t *) (p_list_elem + 1);
+    p_fapi_slot_ind->header.msg_id = FAPI_SLOT_INDICATION;
+    p_fapi_slot_ind->header.length = (uint16_t) sizeof(fapi_slot_ind_t);
+    p_fapi_slot_ind->sfn = p_iapi_resp->sSFN_Slot.nSFN;
+    p_fapi_slot_ind->slot = p_iapi_resp->sSFN_Slot.nSlot;
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_slot_ind++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[SLOT.indication][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_iapi_resp->sSFN_Slot.nSFN,
+            p_iapi_resp->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_srs_ind.c b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_srs_ind.c
new file mode 100644 (file)
index 0000000..ebda4ed
--- /dev/null
@@ -0,0 +1,225 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI SRS.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+#include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx Pointer to PHY context.
+ *  @param[in]  p_phy_srs_ind Pointer to FAPI SRS.indication message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message includes SRS PDU. 
+ *
+**/
+uint8_t nr5g_fapi_srs_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXSRSIndicationStruct p_phy_srs_ind)
+{
+    uint8_t phy_id;
+    fapi_srs_indication_t *p_fapi_srs_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SRS.indication] Invalid " "Phy Context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_phy_srs_ind) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SRS.indication] Invalid "
+                "SRS Indication"));
+        return FAILURE;
+    }
+
+    phy_id = p_phy_srs_ind->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if (p_phy_instance->phy_id != phy_id) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SRS.indication] Invalid " "Phy Instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_srs_ind++;
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_SRS_INDICATION, 1,
+        sizeof(fapi_srs_indication_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SRS.indication] Unable "
+                "to create list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_srs_ind = (fapi_srs_indication_t *) (p_list_elem + 1);
+    p_fapi_srs_ind->header.msg_id = FAPI_SRS_INDICATION;
+    p_fapi_srs_ind->header.length = (uint16_t) sizeof(fapi_srs_indication_t);
+
+    if (nr5g_fapi_srs_indication_to_fapi_translation(p_phy_instance,
+            p_phy_srs_ind, p_fapi_srs_ind)) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[SRS.indication] L1 to FAPI " "translation failed"));
+        return FAILURE;
+    }
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_srs_ind++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[SRS.indication][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_phy_srs_ind->sSFN_Slot.nSFN,
+            p_phy_srs_ind->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   ue_id  Variable holding ue_id received SRS.Indication..
+ *  @param[in]   p_ul_slot_info Pointer to ul slot info structure that stores the 
+ *               UL_TTI.request PDU info.
+ *  
+ *  @return     Returns Pointer to srs info, if handle of p_ul_slot_info matches ue_id.
+                        NULL, if handle of p_ul_slot_info not matches ue_id
+ *
+ *  @description
+ *  This function retrieves the srs info stored during corresponding UL_TTI.request processing.  
+ *  based on ue_id.
+ *
+**/
+nr5g_fapi_srs_info_t *nr5g_fapi_get_srs_info(
+    uint16_t nUEId,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
+{
+    uint8_t i, num_srs;
+
+    nr5g_fapi_srs_info_t *p_srs_info;
+
+    num_srs = p_ul_slot_info->num_srs;
+    for (i = 0; i < num_srs; i++) {
+        p_srs_info = &p_ul_slot_info->srs_info[i];
+        if (p_srs_info->handle == nUEId) {
+            return p_srs_info;
+        }
+    }
+    return NULL;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]   p_phy_srs_ind Pointer to IAPI SRS.indication structure.
+ *  @param[out]  p_fapi_srs_ind Pointer to FAPI SRS.indication structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts IAPI SRS.indication to FAPI SRS.indication
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_srs_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXSRSIndicationStruct p_phy_srs_ind,
+    fapi_srs_indication_t * p_fapi_srs_ind)
+{
+    uint8_t num_srs_pdus, i;
+    uint8_t slot_no, num_rept_symbols, nr_of_symbols;
+    uint16_t frame_no, num_rbs, j, k;
+    int8_t wideband_snr = 0, rb_snr;
+    int16_t temp = 0;
+
+    nr5g_fapi_srs_info_t *p_srs_info;
+    fapi_srs_pdu_t *p_fapi_srs_pdu;
+    fapi_symb_snr_t *p_fapi_symb_snr;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+    nr5g_fapi_stats_t *p_stats;
+    ULSRSEstStruct *p_ul_srs_est_struct;
+
+    p_stats = &p_phy_instance->stats;
+
+    frame_no = p_fapi_srs_ind->sfn = p_phy_srs_ind->sSFN_Slot.nSFN;
+    slot_no = p_fapi_srs_ind->slot = p_phy_srs_ind->sSFN_Slot.nSlot;
+
+    p_ul_slot_info =
+        nr5g_fapi_get_ul_slot_info(frame_no, slot_no, p_phy_instance);
+
+    if (p_ul_slot_info == NULL) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SRS.indication] No Valid data available "
+                "for frame :%d and slot: %d", frame_no, slot_no));
+        return FAILURE;
+    }
+
+    num_srs_pdus = p_fapi_srs_ind->numPdus = p_phy_srs_ind->nNrOfSrs;
+    for (i = 0; i < num_srs_pdus; i++) {
+        p_stats->iapi_stats.iapi_srs_ind_pdus++;
+        p_fapi_srs_pdu = &p_fapi_srs_ind->srsPdus[i];
+        p_ul_srs_est_struct = &p_phy_srs_ind->sULSRSEstStruct[i];
+        p_srs_info =
+            nr5g_fapi_get_srs_info(p_ul_srs_est_struct->nUEId, p_ul_slot_info);
+        if (p_srs_info == NULL) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[SRS.indication] No Valid data available "
+                    "for nUEId:%d with frameno:%d, slot_no:%d",
+                    p_ul_srs_est_struct->nUEId, frame_no, slot_no));
+            return FAILURE;
+        }
+
+        p_fapi_srs_pdu->handle = p_srs_info->handle;
+        p_fapi_srs_pdu->rnti = p_ul_srs_est_struct->nRNTI;
+        p_fapi_srs_pdu->timingAdvance = 0xFFFF;
+
+        nr_of_symbols = p_fapi_srs_pdu->numSymbols =
+            p_ul_srs_est_struct->nNrOfSymbols;
+        for (j = 0; j < nr_of_symbols; j++) {
+            temp += p_ul_srs_est_struct->nWideBandSNR[j];
+        }
+        wideband_snr = temp / nr_of_symbols;
+
+        p_fapi_srs_pdu->wideBandSnr = (wideband_snr + 64) * 2;
+        num_rept_symbols = p_fapi_srs_pdu->numReportedSymbols = 1;
+
+        for (j = 0; j < num_rept_symbols; j++) {
+            p_fapi_symb_snr = &p_fapi_srs_pdu->symbSnr[j];
+            num_rbs = p_fapi_symb_snr->numRbs =
+                p_ul_srs_est_struct->nNrOfBlocks * 4;
+
+            for (k = 0; k < num_rbs; k++) {
+                rb_snr = p_ul_srs_est_struct->nBlockSNR[k / 68][k % 68];
+                p_fapi_symb_snr->rbSNR[k] = (rb_snr + 64) * 2;
+            }
+        }
+        p_stats->fapi_stats.fapi_srs_ind_pdus++;
+    }
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_uci_ind.c b/fapi_5g/source/api/fapi2mac/p7/nr5g_fapi_proc_uci_ind.c
new file mode 100644 (file)
index 0000000..46e3b5e
--- /dev/null
@@ -0,0 +1,357 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ * @file
+ * This file consist of implementation of FAPI UCI.indication message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+#include "nr5g_fapi_fapi2mac_p7_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_ctx     Pointer to PHY context.
+ *  @param[in]  p_phy_uci_ind Pointer to FAPI UCI.indication message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message includes UCI payload in PUCCH or PUSCH. 
+ *
+**/
+uint8_t nr5g_fapi_uci_indication(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx,
+    PRXUCIIndicationStruct p_phy_uci_ind)
+{
+    uint8_t phy_id;
+    fapi_uci_indication_t *p_fapi_uci_ind;
+    p_fapi_api_queue_elem_t p_list_elem;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_ctx) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Invalid Phy " "Context"));
+        return FAILURE;
+    }
+
+    if (NULL == p_phy_uci_ind) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Invalid Phy "
+                "UCI indication"));
+        return FAILURE;
+    }
+
+    phy_id = p_phy_uci_ind->sSFN_Slot.nCarrierIdx;
+    p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+    if ((p_phy_instance->phy_id != phy_id)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Invalid " "phy instance"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->iapi_stats.iapi_uci_ind++;
+
+    p_list_elem =
+        nr5g_fapi_fapi2mac_create_api_list_elem(FAPI_UCI_INDICATION, 1,
+        sizeof(fapi_uci_indication_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UCI.indication] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_fapi_uci_ind = (fapi_uci_indication_t *) (p_list_elem + 1);
+    p_fapi_uci_ind->header.msg_id = FAPI_UCI_INDICATION;
+    p_fapi_uci_ind->header.length = (uint16_t) sizeof(fapi_uci_indication_t);
+
+    if (nr5g_fapi_uci_indication_to_fapi_translation(p_phy_instance,
+            p_phy_uci_ind, p_fapi_uci_ind)) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[UCI.indication] FAPI to L1 " "translation failed"));
+        return FAILURE;
+    }
+    /* Add element to send list */
+    nr5g_fapi_fapi2mac_add_api_to_list(phy_id, p_list_elem);
+
+    p_stats->fapi_stats.fapi_uci_ind++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[UCI.indication][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_phy_uci_ind->sSFN_Slot.nSFN,
+            p_phy_uci_ind->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   ue_id  Variable holding ue_id received in RX_DATA.Indication..
+ *  @param[in]   p_ul_slot_info Pointer to ul slot info structure that stores the 
+ *               UL_TTI.request PDU info.
+ *  
+ *  @return     Returns Pointer to pucch info, if handle of p_ul_slot_info matches ue_id.
+                        NULL, if handle of p_ul_slot_info not matches ue_id
+ *
+ *  @description
+**/
+nr5g_fapi_pucch_info_t *nr5g_fapi_get_pucch_info(
+    uint16_t ue_id,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
+{
+    uint8_t i, num_ulcch;
+    nr5g_fapi_pucch_info_t *p_pucch_info;
+
+    num_ulcch = p_ul_slot_info->num_ulcch;
+    for (i = 0; i < num_ulcch; i++) {
+        p_pucch_info = &p_ul_slot_info->pucch_info[i];
+        if (p_pucch_info->handle == ue_id) {
+            return p_pucch_info;
+        }
+    }
+    return NULL;
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   p_pucch_info Pointer to pucch_info stored in ul slot info during
+ *               UL_TTI.request processing
+ *  @param[in]   p_uci_pdu_data_struct Pointer to IAPI UCI PDU structure.
+ *  @param[out]  p_fapi_uci_pdu_info   Pointer to FAPI UCI PDU structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function fills  FAPI UCI FORMAT0_FORMAT1 PDU from IAPI UCI PDU
+ *  structure.
+ *
+**/
+void nr5g_fapi_fill_uci_format_0_1(
+    nr5g_fapi_pucch_info_t * p_pucch_info,
+    ULUCIPDUDataStruct * p_uci_pdu_data_struct,
+    fapi_uci_pdu_info_t * p_fapi_uci_pdu_info)
+{
+    uint8_t pucch_detected, num_harq, i;
+
+    fapi_uci_o_pucch_f0f1_t *p_uci_pucch_f0_f1;
+    fapi_sr_f0f1_info_t *p_sr_info;
+    fapi_harq_f0f1_info_t *p_harq_info;
+
+    p_uci_pucch_f0_f1 = &p_fapi_uci_pdu_info->uci.uciPucchF0F1;
+    NR5G_FAPI_MEMSET(p_uci_pucch_f0_f1, sizeof(fapi_uci_o_pucch_f0f1_t), 0,
+        sizeof(fapi_uci_o_pucch_f0f1_t));
+
+    p_uci_pucch_f0_f1->handle = p_pucch_info->handle;
+    p_uci_pucch_f0_f1->pduBitmap = 0;
+    p_uci_pucch_f0_f1->pucchFormat = p_pucch_info->pucch_format;
+
+    p_uci_pucch_f0_f1->ul_cqi = (p_uci_pdu_data_struct->nSNR + 64) * 2;
+    p_uci_pucch_f0_f1->rnti = p_uci_pdu_data_struct->nRNTI;
+    p_uci_pucch_f0_f1->timingAdvance = 31;
+    p_uci_pucch_f0_f1->rssi = 880;
+
+    if (p_uci_pdu_data_struct->nSRPresent) {
+        p_uci_pucch_f0_f1->pduBitmap |= 0x01;
+        p_sr_info = &p_uci_pucch_f0_f1->srInfo;
+        p_sr_info->srIndication = 1;
+        p_sr_info->srConfidenceLevel = 0xff;
+    }
+    pucch_detected = p_uci_pdu_data_struct->pucchDetected;
+    if (pucch_detected == 1) {
+        p_uci_pucch_f0_f1->pduBitmap |= 0x02;
+        p_harq_info = &p_uci_pucch_f0_f1->harqInfo;
+        p_harq_info->harqConfidenceLevel = 0xff;
+        num_harq = p_harq_info->numHarq = p_uci_pdu_data_struct->nPduBitLen;
+        for (i = 0; i < num_harq; i++) {
+            p_harq_info->harqValue[i] = p_uci_pdu_data_struct->nUciBits[i];
+        }
+    } else {                    // 0 or 2
+        p_uci_pucch_f0_f1->rssi = 0;
+    }
+#ifdef DEBUG_MODE
+    p_uci_pucch_f0_f1->timingAdvance = p_uci_pdu_data_struct->nTA;
+    if (pucch_detected == 2) {
+        p_uci_pucch_f0_f1->pduBitmap |= 0x80;
+        p_harq_info = &p_uci_pucch_f0_f1->harqInfo;
+        p_harq_info->harqConfidenceLevel = 0xff;
+        num_harq = p_harq_info->numHarq = p_uci_pdu_data_struct->nPduBitLen;
+        for (i = 0; i < num_harq; i++) {
+            p_harq_info->harqValue[i] = p_uci_pdu_data_struct->nUciBits[i];
+        }
+    }
+#endif
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]   p_pucch_info Pointer to pucch_info stored in ul slot info during
+ *               UL_TTI.request processing
+ *  @param[in]   p_uci_pdu_data_struct Pointer to IAPI UCI PDU structure.
+ *  @param[out]  p_fapi_uci_pdu_info   Pointer to FAPI UCI PDU structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function fills  FAPI UCI FORMAT2_FORMAT3_FORMAT4 PDU from IAPI UCI PDU
+ *  structure.
+ *
+**/
+void nr5g_fapi_fill_uci_format_2_3_4(
+    nr5g_fapi_pucch_info_t * p_pucch_info,
+    ULUCIPDUDataStruct * p_uci_pdu_data_struct,
+    fapi_uci_pdu_info_t * p_fapi_uci_pdu_info)
+{
+    uint8_t pucch_detected;
+    uint16_t num_uci_bits;
+
+    fapi_uci_o_pucch_f2f3f4_t *p_uci_pucch_f2_f3_f4;
+
+    p_uci_pucch_f2_f3_f4 = &p_fapi_uci_pdu_info->uci.uciPucchF2F3F4;
+
+    p_uci_pucch_f2_f3_f4->handle = p_pucch_info->handle;
+    p_uci_pucch_f2_f3_f4->pduBitmap = 0;
+    p_uci_pucch_f2_f3_f4->pucchFormat = p_pucch_info->pucch_format;
+    p_uci_pucch_f2_f3_f4->ul_cqi = (p_uci_pdu_data_struct->nSNR + 64) * 2;
+    p_uci_pucch_f2_f3_f4->rnti = p_uci_pdu_data_struct->nRNTI;
+    p_uci_pucch_f2_f3_f4->timingAdvance = 31;
+
+    pucch_detected = p_uci_pdu_data_struct->pucchDetected;
+#ifdef DEBUG_MODE
+    p_uci_pucch_f2_f3_f4->timingAdvance = p_uci_pdu_data_struct->nTA;
+    if (pucch_detected == 2) {
+        p_uci_pucch_f2_f3_f4->pduBitmap |= 0x80;
+    }
+#endif
+    p_uci_pucch_f2_f3_f4->rssi = 880;
+    if (p_uci_pdu_data_struct->nSRPresent) {
+        p_uci_pucch_f2_f3_f4->pduBitmap |= 0x01;
+    }
+    pucch_detected = p_uci_pdu_data_struct->pucchDetected;
+    if (pucch_detected == 1) {
+        p_uci_pucch_f2_f3_f4->pduBitmap |= 0x02;
+    } else {
+        p_uci_pucch_f2_f3_f4->rssi = 0;
+    }
+    num_uci_bits = p_uci_pucch_f2_f3_f4->num_uci_bits =
+        p_uci_pdu_data_struct->nPduBitLen;
+    if (num_uci_bits > 0) {
+        NR5G_FAPI_MEMCPY(p_uci_pucch_f2_f3_f4->uciBits,
+            sizeof(uint8_t) * FAPI_MAX_UCI_BIT_BYTE_LEN,
+            p_uci_pdu_data_struct->nUciBits, num_uci_bits);
+    }
+}
+
+ /** @ingroup group_source_api_p7_fapi2mac_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]   p_phy_uci_ind Pointer to IAPI UCI.indication structure.
+ *  @param[out]  p_fapi_uci_ind Pointer to FAPI UCI.indication structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts IAPI UCI.indication to FAPI UCI.indication
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_uci_indication_to_fapi_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PRXUCIIndicationStruct p_phy_uci_ind,
+    fapi_uci_indication_t * p_fapi_uci_ind)
+{
+    uint8_t num_uci, i;
+    uint8_t slot_no, pucch_format;
+    uint16_t frame_no;
+
+    nr5g_fapi_pucch_info_t *p_pucch_info;
+    fapi_uci_pdu_info_t *p_fapi_uci_pdu_info;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+    nr5g_fapi_stats_t *p_stats;
+    ULUCIPDUDataStruct *p_uci_pdu_data_struct;
+
+    p_stats = &p_phy_instance->stats;
+
+    frame_no = p_fapi_uci_ind->sfn = p_phy_uci_ind->sSFN_Slot.nSFN;
+    slot_no = p_fapi_uci_ind->slot = p_phy_uci_ind->sSFN_Slot.nSlot;
+
+    p_ul_slot_info =
+        nr5g_fapi_get_ul_slot_info(frame_no, slot_no, p_phy_instance);
+
+    if (p_ul_slot_info == NULL) {
+        NR5G_FAPI_LOG(ERROR_LOG, (" [UCI.indication] No Valid data available "
+                "for frame :%d and slot: %d", frame_no, slot_no));
+        return FAILURE;
+    }
+
+    num_uci = p_fapi_uci_ind->numUcis = p_phy_uci_ind->nUCI;
+    for (i = 0; i < num_uci; i++) {
+        p_stats->iapi_stats.iapi_uci_ind_pdus++;
+        p_fapi_uci_pdu_info = &p_fapi_uci_ind->uciPdu[i];
+        p_uci_pdu_data_struct = &p_phy_uci_ind->sULUCIPDUDataStruct[i];
+        p_pucch_info =
+            nr5g_fapi_get_pucch_info(p_uci_pdu_data_struct->nUEId,
+            p_ul_slot_info);
+        if (p_pucch_info == NULL) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                (" [UCI.indication] No Valid data available "
+                    "for nUEId:%d with frameno:%d, slot_no:%d",
+                    p_uci_pdu_data_struct->nUEId, frame_no, slot_no));
+            return FAILURE;
+        }
+
+        pucch_format = p_pucch_info->pucch_format;
+
+        switch (pucch_format) {
+            case FAPI_PUCCH_FORMAT_TYPE_0:
+            case FAPI_PUCCH_FORMAT_TYPE_1:
+                {
+                    p_fapi_uci_pdu_info->pduType = 1;
+                    p_fapi_uci_pdu_info->pduSize =
+                        sizeof(fapi_uci_o_pucch_f0f1_t);
+                    nr5g_fapi_fill_uci_format_0_1(p_pucch_info,
+                        p_uci_pdu_data_struct, p_fapi_uci_pdu_info);
+                }
+                break;
+
+            case FAPI_PUCCH_FORMAT_TYPE_2:
+            case FAPI_PUCCH_FORMAT_TYPE_3:
+            case FAPI_PUCCH_FORMAT_TYPE_4:
+                {
+                    p_fapi_uci_pdu_info->pduType = 2;
+                    p_fapi_uci_pdu_info->pduSize =
+                        sizeof(fapi_uci_o_pucch_f2f3f4_t);
+                    nr5g_fapi_fill_uci_format_2_3_4(p_pucch_info,
+                        p_uci_pdu_data_struct, p_fapi_uci_pdu_info);
+                }
+                break;
+
+            default:
+                {
+                    NR5G_FAPI_LOG(ERROR_LOG,
+                        (" [UCI.indication] Invalid PUCCH Format"
+                            "pucch_format:%d", pucch_format));
+                    return FAILURE;
+                }
+                break;
+        }
+        p_stats->fapi_stats.fapi_uci_ind_pdus++;
+    }
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2phy/nr5g_fapi_fapi2phy_api.c b/fapi_5g/source/api/fapi2phy/nr5g_fapi_fapi2phy_api.c
new file mode 100644 (file)
index 0000000..fb8984b
--- /dev/null
@@ -0,0 +1,222 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file contains implementation of all the functions used 
+ * to send APIs from FAPI to PHY
+ *
+ **/
+
+#include <stdio.h>
+#include "nr5g_fapi_internal.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_wls.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_wls.h"
+#include "nr5g_fapi_log.h"
+
+nr5g_fapi_fapi2phy_queue_t fapi2phy_q;
+
+//------------------------------------------------------------------------------
+/** @ingroup     group_source_api_fapi2phy
+ *
+ *  @param[in]   p_list_elem Pointer to the ListElement
+ *
+ *  @return      void
+ *
+ *  @description This function adds a ListElement API to a Linked list which will
+ *               be sent to L1 once all APIs for a TTI are added
+ *
+**/
+//------------------------------------------------------------------------------
+p_nr5g_fapi_fapi2phy_queue_t nr5g_fapi_fapi2phy_queue(
+    )
+{
+    return &fapi2phy_q;
+}
+
+uint8_t nr5g_fapi_get_stats_location(
+    uint8_t msg_type)
+{
+    uint8_t loc;
+    switch (msg_type) {
+        case MSG_TYPE_PHY_CONFIG_REQ:
+            loc = MEM_STAT_CONFIG_REQ;
+            break;
+
+        case MSG_TYPE_PHY_START_REQ:
+            loc = MEM_STAT_START_REQ;
+            break;
+
+        case MSG_TYPE_PHY_STOP_REQ:
+            loc = MEM_STAT_STOP_REQ;
+            break;
+
+        case MSG_TYPE_PHY_SHUTDOWN_REQ:
+            loc = MEM_STAT_SHUTDOWN_REQ;
+            break;
+
+        case MSG_TYPE_PHY_DL_CONFIG_REQ:
+            loc = MEM_STAT_DL_CONFIG_REQ;
+            break;
+
+        case MSG_TYPE_PHY_UL_CONFIG_REQ:
+            loc = MEM_STAT_UL_CONFIG_REQ;
+            break;
+
+        case MSG_TYPE_PHY_UL_DCI_REQ:
+            loc = MEM_STAT_UL_DCI_REQ;
+            break;
+
+        case MSG_TYPE_PHY_TX_REQ:
+            loc = MEM_STAT_TX_REQ;
+            break;
+
+        case MSG_TYPE_PHY_DL_IQ_SAMPLES:
+            loc = MEM_STAT_DL_IQ_SAMPLES;
+            break;
+
+        case MSG_TYPE_PHY_UL_IQ_SAMPLES:
+            loc = MEM_STAT_UL_IQ_SAMPLES;
+            break;
+
+        default:
+            loc = MEM_STAT_DEFAULT;
+    }
+
+    return loc;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup     group_source_api_fapi2phy
+ *
+ *  @param[in]   msg_type Message Type
+ *  @param[in]   num_message_in_blockn Number of Messages in Block
+ *  @param[in]   align_offset Align Offset
+ *
+ *  @return      Pointer to the List Element structure
+ *
+ *  @description This function allocates a buffer from shared memory WLS
+ *               interface and creates a List Element structures. It then fills
+ *               all the fields with data being passed in.
+ *
+**/
+//------------------------------------------------------------------------------
+PMAC2PHY_QUEUE_EL nr5g_fapi_fapi2phy_create_api_list_elem(
+    uint32_t msg_type,
+    uint16_t num_message_in_block,
+    uint32_t align_offset)
+{
+    PMAC2PHY_QUEUE_EL p_list_elem = NULL;
+    uint8_t loc;
+
+    loc = nr5g_fapi_get_stats_location(msg_type);
+    p_list_elem = (PMAC2PHY_QUEUE_EL) wls_fapi_alloc_buffer(0, loc);
+    //Fill header for link list of API messages
+    if (p_list_elem) {
+        p_list_elem->nMessageType = (uint8_t) msg_type;
+        p_list_elem->nNumMessageInBlock = num_message_in_block;
+        p_list_elem->nAlignOffset = (uint16_t) align_offset;
+        p_list_elem->nMessageLen = num_message_in_block * align_offset;
+        p_list_elem->pNext = NULL;
+    }
+
+    return p_list_elem;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup     group_source_api_fapi2phy
+ *
+ *  @param[in]   p_list_elem Pointer to the ListElement
+ *
+ *  @return      void
+ *
+ *  @description This function adds a ListElement API to a Linked list which will
+ *               be sent to L1 once all APIs for a TTI are added
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_fapi2phy_add_to_api_list(
+    PMAC2PHY_QUEUE_EL p_list_elem)
+{
+    p_nr5g_fapi_fapi2phy_queue_t queue = NULL;
+
+    if (!p_list_elem) {
+        return;
+    }
+
+    queue = nr5g_fapi_fapi2phy_queue();
+    if (queue->p_send_list_head && queue->p_send_list_tail) {
+        queue->p_send_list_tail->pNext = p_list_elem;
+        queue->p_send_list_tail = p_list_elem;
+    } else {
+        queue->p_send_list_head = queue->p_send_list_tail = p_list_elem;
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup      group_source_api_fapi2phy
+ *
+ *  @param        A pointer to phy Instance
+ *
+ *  @return       FAPI status
+ *
+ *  @description  This function send API list to L1
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_fapi2phy_send_api_list(
+    )
+{
+    uint8_t ret = FAILURE;
+    p_nr5g_fapi_fapi2phy_queue_t queue = NULL;
+
+    queue = nr5g_fapi_fapi2phy_queue();
+    if (queue->p_send_list_head) {
+
+        NR5G_FAPI_LOG(TRACE_LOG,
+            ("[NR5G_FAPI][FAPI2PHY] Sending API's to PHY"));
+        ret = nr5g_fapi_fapi2phy_wls_send(queue->p_send_list_head);
+        if (FAILURE == ret) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[NR5G_FAPI][FAPI2PHY] Error sending API's to PHY"));
+        }
+        queue->p_send_list_tail = queue->p_send_list_head = NULL;
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup        group_source_api_fapi2phy
+ *
+ *  @param[in]      A pointer to phy instance
+ *
+ *  @return         void
+ *
+ *  @description    The function adds all memory elements to WLS free list
+ *
+ **/
+//-------------------------------------------------------------------------------------------
+
+void nr5g_fapi_fapi2phy_destroy_api_list_elem(
+    PMAC2PHY_QUEUE_EL p_list_elem)
+{
+    if (p_list_elem) {
+        uint8_t loc = nr5g_fapi_get_stats_location(p_list_elem->nMessageType);
+        wls_fapi_free_buffer(p_list_elem, loc);
+    }
+}
diff --git a/fapi_5g/source/api/fapi2phy/nr5g_fapi_fapi2phy_api.h b/fapi_5g/source/api/fapi2phy/nr5g_fapi_fapi2phy_api.h
new file mode 100644 (file)
index 0000000..42ef246
--- /dev/null
@@ -0,0 +1,56 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file defines all the functions used to send APIs
+ * from FAPI to PHY
+ *
+ **/
+
+#ifndef NR5G_FAPI_FAPI2PHY_API_H
+#define NR5G_FAPI_FAPI2PHY_API_H
+
+#include "gnb_l1_l2_api.h"
+
+typedef struct _nr5g_fapi_fapi2phy_queue {
+    PMAC2PHY_QUEUE_EL p_send_list_head; // list head to, send to PHY
+    PMAC2PHY_QUEUE_EL p_send_list_tail; // list tail to, send to PHY
+    PMAC2PHY_QUEUE_EL p_recv_list_head; // list head received from PHY
+    PMAC2PHY_QUEUE_EL p_recv_list_tail; // list tail received from PHY
+} nr5g_fapi_fapi2phy_queue_t,
+*p_nr5g_fapi_fapi2phy_queue_t;
+
+// Function definitions
+// -----------------------------------------------------------------------------
+PMAC2PHY_QUEUE_EL nr5g_fapi_fapi2phy_create_api_list_elem(
+    uint32_t msg_type,
+    uint16_t num_message_in_block,
+    uint32_t align_offset);
+
+void nr5g_fapi_fapi2phy_add_to_api_list(
+    PMAC2PHY_QUEUE_EL p_list_elem);
+
+void nr5g_fapi_fapi2phy_send_api_list(
+    );
+
+void nr5g_fapi_fapi2phy_add_to_free_list(
+    PMAC2PHY_QUEUE_EL p_list_elem);
+
+void nr5g_fapi_fapi2phy_destroy_api_list_elem(
+    PMAC2PHY_QUEUE_EL p_list_elem);
+#endif
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_fapi2phy_p5_proc.h b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_fapi2phy_p5_proc.h
new file mode 100644 (file)
index 0000000..c7bbee3
--- /dev/null
@@ -0,0 +1,59 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to PHY P5 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2PHY_P5_PROC_H_
+#define _NR5G_FAPI_FAP2PHY_P5_PROC_H_
+
+uint8_t nr5g_fapi_config_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_config_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+uint8_t nr5g_fapi_start_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_start_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+uint8_t nr5g_fapi_stop_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_stop_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+uint8_t nr5g_fapi_shutdown_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_vendor_ext_shutdown_req_t * p_fapi_req);
+
+uint8_t nr5g_fapi_shutdown_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_vendor_ext_shutdown_req_t * p_fapi_msg);
+
+#ifdef DEBUG_MODE
+uint8_t nr5g_fapi_dl_iq_samples_request(
+    fapi_vendor_ext_iq_samples_req_t * p_fapi_req);
+uint8_t nr5g_fapi_ul_iq_samples_request(
+    fapi_vendor_ext_iq_samples_req_t * p_fapi_req);
+#endif
+
+#endif                          //_NR5G_FAPI_FAP2PHY_P5_PROC_H_
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_fapi2phy_p5_pvt_proc.h b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_fapi2phy_p5_pvt_proc.h
new file mode 100644 (file)
index 0000000..d9c00a5
--- /dev/null
@@ -0,0 +1,57 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to PHY P5 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2PHY_P5_PVT_PROC_H_
+#define _NR5G_FAPI_FAP2PHY_P5_PVT_PROC_H_
+
+//x is 32 bit variable, y is length in bytes
+#define GETVLFRM32B(x, y)  ((x) & ((0xFFFFFFFF) >> (32 - (y << 3))))
+
+uint8_t nr5g_fapi_config_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_config_req_t * p_fapi_req,
+    PCONFIGREQUESTStruct p_ia_config_req);
+
+uint8_t nr5g_fapi_calc_phy_tdd_period(
+    uint8_t fapi_tdd_period,
+    uint8_t n_subc_common);
+
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_0(
+    uint8_t fapi_tdd_period);
+
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_1(
+    uint8_t fapi_tdd_period);
+
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_2(
+    uint8_t fapi_tdd_period);
+
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_3(
+    uint8_t fapi_tdd_period);
+
+uint16_t nr5g_fapi_calc_fft_size(
+    uint8_t nSubcCommon,
+    uint16_t bw);
+
+#endif                          //_NR5G_FAPI_FAP2PHY_P5_PVT_PROC_H_
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_config_req.c b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_config_req.c
new file mode 100644 (file)
index 0000000..7b7e68a
--- /dev/null
@@ -0,0 +1,590 @@
+/******************************************************************************
+ << 3)*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI CONFIG.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI CONFIG.request message structure.
+ *  @param[in]  p_fapi_vendor_msg Pointer to FAPI vendor message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message instructs how the PHY should be configured.
+ *
+ *  The *carrier_aggregation_level* parameter is a vendor specific 
+ *  configuration and programmed through Vendor Specific Message structure 
+ *  ::fapi_config_req_vendor_msg_t 
+ *
+**/
+uint8_t nr5g_fapi_config_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_config_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PCONFIGREQUESTStruct p_ia_config_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+
+#ifndef DEBUG_MODE
+    /* Below print is for better logging on console in radio mode. */
+    NR5G_FAPI_LOG(INFO_LOG, (""));
+#endif
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Invalid " "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_config_req++;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Invalid fapi " "message"));
+        return FAILURE;
+    }
+
+    if (NULL == p_fapi_vendor_msg) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Invalid fapi "
+                "vendor message"));
+        return FAILURE;
+    }
+
+    if (FAPI_STATE_RUNNING == p_phy_instance->state) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Message not "
+                "supported by PHY in Running State"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_CONFIG_REQ, 1, (uint32_t) sizeof(CONFIGREQUESTStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_ia_config_req = (PCONFIGREQUESTStruct) (p_list_elem + 1);
+    NR5G_FAPI_MEMSET(p_ia_config_req, sizeof(CONFIGREQUESTStruct), 0,
+        sizeof(CONFIGREQUESTStruct));
+    p_ia_config_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_CONFIG_REQ;
+    p_ia_config_req->sMsgHdr.nMessageLen =
+        (uint16_t) sizeof(CONFIGREQUESTStruct);
+    p_ia_config_req->nCarrierIdx = p_phy_instance->phy_id;
+
+    nr5g_fapi_config_req_to_phy_translation(p_phy_instance, p_fapi_req,
+        p_ia_config_req);
+    /* Vendor Parameters */
+    if (p_fapi_vendor_msg) {
+        p_ia_config_req->nCarrierAggregationLevel =
+            p_fapi_vendor_msg->config_req_vendor.carrier_aggregation_level;
+        p_ia_config_req->nGroupHopFlag =
+            p_fapi_vendor_msg->config_req_vendor.group_hop_flag;
+        p_ia_config_req->nSequenceHopFlag =
+            p_fapi_vendor_msg->config_req_vendor.sequence_hop_flag;
+        p_ia_config_req->nHoppingId =
+            p_fapi_vendor_msg->config_req_vendor.hopping_id;
+    }
+
+    p_ia_config_req->nDLFftSize =
+        nr5g_fapi_calc_fft_size(p_ia_config_req->nSubcCommon,
+        p_ia_config_req->nDLBandwidth);
+    p_ia_config_req->nULFftSize =
+        nr5g_fapi_calc_fft_size(p_ia_config_req->nSubcCommon,
+        p_ia_config_req->nULBandwidth);
+    p_ia_config_req->nPrachNrofRxRU = p_ia_config_req->nNrOfRxAnt;
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_config_req++;
+    NR5G_FAPI_LOG(INFO_LOG, ("[CONFIG.request][%d]", p_phy_instance->phy_id));
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI CONFIG.request structure.
+ *  @param[in]  p_ia_config_req Pointer to IAPI CONFIG.request structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts FAPI CONFIG.request TLVs to IAPI Config.request
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_config_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_config_req_t * p_fapi_req,
+    PCONFIGREQUESTStruct p_ia_config_req)
+{
+    fapi_uint32_tlv_t *tlvs = p_fapi_req->tlvs;
+    uint32_t i = 0, j = 0, k = 0;
+    uint32_t ss_pbch_power = 0;
+    uint32_t mib = 0;
+    uint32_t n_ssb_mask_idx = 0;
+    uint32_t n_beamid_idx = 0;
+    SLOTCONFIGStruct *p_sslot_Config = NULL;
+
+    while (i < p_fapi_req->number_of_tlvs) {
+        switch (tlvs[i].tl.tag) {
+            /***** Carrier Config *****/
+            case FAPI_DL_BANDWIDTH_TAG:
+                p_ia_config_req->nDLBandwidth =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_DL_FREQUENCY_TAG:
+                p_ia_config_req->nDLAbsFrePointA = tlvs[i++].value;
+                break;
+
+                /* FAPI_DL_K0_TAG - NA */
+                /* FAPI_DL_GRIDSIZE_TAG - NA */
+
+            case FAPI_NUM_TX_ANT_TAG:
+                p_ia_config_req->nNrOfTxAnt =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
+                p_ia_config_req->nNrOfDLPorts =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_UPLINK_BANDWIDTH_TAG:
+                p_ia_config_req->nULBandwidth =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_UPLINK_FREQUENCY_TAG:
+                p_ia_config_req->nULAbsFrePointA = tlvs[i++].value;
+                break;
+
+                /* FAPI_UL_K0_TAG - NA */
+                /* FAPI_UL_GRIDSIZE_TAG - NA */
+
+            case FAPI_NUM_RX_ANT_TAG:
+                p_phy_instance->phy_config.n_nr_of_rx_ant =
+                    p_ia_config_req->nNrOfRxAnt =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
+                p_ia_config_req->nNrOfULPorts =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+                /* FAPI_FREQUENCY_SHIFT_7P5_KHZ_TAG - NA */
+
+            /***** Cell Config *****/
+            case FAPI_PHY_CELL_ID_TAG:
+                p_phy_instance->phy_config.phy_cell_id =
+                    p_ia_config_req->nPhyCellId =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_FRAME_DUPLEX_TYPE_TAG:
+                p_ia_config_req->nFrameDuplexType =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            /***** SSB Config *****/
+            case FAPI_SS_PBCH_POWER_TAG:
+                ss_pbch_power = tlvs[i++].value;
+                if (0 == ss_pbch_power) {
+                    p_ia_config_req->nSSBPwr = 1;
+                } else if (54002 == ss_pbch_power) {
+                    p_ia_config_req->nSSBPwr = 20000;
+                } else {
+                    p_ia_config_req->nSSBPwr = ss_pbch_power - 54000;
+                }
+                break;
+
+                /* FAPI_BCH_PAYLOAD_TAG - NA */
+
+            case FAPI_SCS_COMMON_TAG:
+                p_ia_config_req->nSubcCommon =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                p_ia_config_req->nSSBSubcSpacing = p_ia_config_req->nSubcCommon;
+                break;
+
+            /***** PRACH Config *****/
+            case FAPI_PRACH_SUBC_SPACING_TAG:
+                p_ia_config_req->nPrachSubcSpacing =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_RESTRICTED_SET_CONFIG_TAG:
+                p_ia_config_req->nPrachRestrictSet =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_NUM_PRACH_FD_OCCASIONS_TAG:
+                p_ia_config_req->nPrachFdm =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_PRACH_CONFIG_INDEX_TAG:
+                p_ia_config_req->nPrachConfIdx =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_PRACH_ROOT_SEQUENCE_INDEX_TAG:
+                p_ia_config_req->nPrachRootSeqIdx =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_K1_TAG:
+                p_ia_config_req->nPrachFreqStart =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_PRACH_ZERO_CORR_CONF_TAG:
+                p_ia_config_req->nPrachZeroCorrConf =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_SSB_PER_RACH_TAG:
+                p_ia_config_req->nPrachSsbRach =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+            /***** SSB Table *****/
+            case FAPI_SSB_OFFSET_POINT_A_TAG:
+                p_ia_config_req->nSSBPrbOffset =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length) / (pow(2,
+                        p_ia_config_req->nSubcCommon));
+                break;
+
+            case FAPI_SSB_PERIOD_TAG:
+                p_ia_config_req->nSSBPeriod =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_SSB_SUBCARRIER_OFFSET_TAG:
+                p_ia_config_req->nSSBSubcOffset =
+                    (tlvs[i].value >> tlvs[i++].tl.length);
+                break;
+
+            case FAPI_MIB_TAG:
+                mib = tlvs[i++].value;
+                p_ia_config_req->nMIB[0] = (uint8_t) (mib >> 24);
+                p_ia_config_req->nMIB[1] = (uint8_t) (mib >> 16);
+                p_ia_config_req->nMIB[2] = (uint8_t) (mib >> 8);
+                break;
+
+            case FAPI_DMRS_TYPE_A_POS_TAG:
+                p_ia_config_req->nDMRSTypeAPos =
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                break;
+
+            case FAPI_SSB_MASK_TAG:
+                if (n_ssb_mask_idx < 2) {
+                    p_ia_config_req->nSSBMask[n_ssb_mask_idx++] =
+                        tlvs[i++].value;
+                }
+                break;
+
+            case FAPI_BEAM_ID_TAG:
+                if (n_beamid_idx < 64) {
+                    p_ia_config_req->nBeamId[n_beamid_idx++] =
+                        GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                }
+                break;
+
+                /* FAPI_SS_PBCH_MULTIPLE_CARRIERS_IN_A_BAND_TAG - NA */
+                /* FAPI_MULTIPLE_CELLS_SS_PBCH_IN_A_CARRIER_TAG - NA */
+
+            /***** TDD Table *****/
+            case FAPI_TDD_PERIOD_TAG:
+                p_ia_config_req->nTddPeriod =
+                    nr5g_fapi_calc_phy_tdd_period((uint8_t)
+                    GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length),
+                    p_ia_config_req->nSubcCommon);
+                break;
+
+            case FAPI_SLOT_CONFIG_TAG:
+                for (j = 0; j < p_ia_config_req->nTddPeriod; j++) {
+                    p_sslot_Config = &p_ia_config_req->sSlotConfig[j];
+                    for (k = 0; k < MAX_NUM_OF_SYMBOL_PER_SLOT; k++) {
+                        p_sslot_Config->nSymbolType[k] =
+                            GETVLFRM32B(tlvs[i].value, tlvs[i++].tl.length);
+                    }
+                }
+                break;
+
+            /***** Measurement Config *****/
+                /* FAPI_RSSI_MEASUREMENT_TAG - NA */
+
+            /***** Beamforming Table *****/
+
+            /***** Precoding Table *****/
+            default:
+                {
+                    NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Unsupported "
+                            "TLV tag : 0x%x", tlvs[i].tl.tag));
+                }
+                break;
+        }
+    }
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
+ *  @param[in]  n_subc_common subcarrierSpacing for common.
+ *  
+ *  @return     IAPI *nTddPeriod*.
+ *
+ *  @description
+ *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_calc_phy_tdd_period(
+    uint8_t fapi_tdd_period,
+    uint8_t n_subc_common)
+{
+    switch (n_subc_common) {
+        case 0:
+            return
+                nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_0
+                (fapi_tdd_period);
+        case 1:
+            return
+                nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_1
+                (fapi_tdd_period);
+        case 2:
+            return
+                nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_2
+                (fapi_tdd_period);
+        case 3:
+            return
+                nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_3
+                (fapi_tdd_period);
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
+ *  
+ *  @return     IAPI *nTddPeriod*.
+ *
+ *  @description
+ *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
+ *  structure based on *subCarrierSpacingCommon - 0*.
+ *
+**/
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_0(
+    uint8_t fapi_tdd_period)
+{
+    if (2 == fapi_tdd_period)
+        return 1;
+    else if (4 == fapi_tdd_period)
+        return 2;
+    else if (6 == fapi_tdd_period)
+        return 5;
+    else if (7 == fapi_tdd_period)
+        return 10;
+    else
+        return 0;
+
+    return 0;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
+ *  
+ *  @return     IAPI *nTddPeriod*.
+ *
+ *  @description
+ *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
+ *  structure based on *subCarrierSpacingCommon - 1*.
+ *
+**/
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_1(
+    uint8_t fapi_tdd_period)
+{
+    if (0 == fapi_tdd_period)
+        return 1;
+    else if (2 == fapi_tdd_period)
+        return 2;
+    else if (4 == fapi_tdd_period)
+        return 4;
+    else if (5 == fapi_tdd_period)
+        return 5;
+    else if (6 == fapi_tdd_period)
+        return 10;
+    else if (7 == fapi_tdd_period)
+        return 20;
+    else
+        return 0;
+
+    return 0;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
+ *  
+ *  @return     IAPI *nTddPeriod*.
+ *
+ *  @description
+ *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
+ *  structure based on *subCarrierSpacingCommon - 2*.
+ *
+**/
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_2(
+    uint8_t fapi_tdd_period)
+{
+    if (0 == fapi_tdd_period)
+        return 2;
+    else if (2 == fapi_tdd_period)
+        return 4;
+    else if (3 == fapi_tdd_period)
+        return 5;
+    else if (4 == fapi_tdd_period)
+        return 8;
+    else if (5 == fapi_tdd_period)
+        return 10;
+    else if (6 == fapi_tdd_period)
+        return 20;
+    else if (7 == fapi_tdd_period)
+        return 40;
+    else
+        return 0;
+
+    return 0;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
+ *  
+ *  @return     IAPI *nTddPeriod*.
+ *
+ *  @description
+ *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
+ *  structure based on *subCarrierSpacingCommon - 3*.
+ *
+**/
+uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_3(
+    uint8_t fapi_tdd_period)
+{
+    if (0 == fapi_tdd_period)
+        return 4;
+    else if (1 == fapi_tdd_period)
+        return 5;
+    else if (2 == fapi_tdd_period)
+        return 8;
+    else if (3 == fapi_tdd_period)
+        return 10;
+    else if (4 == fapi_tdd_period)
+        return 16;
+    else if (5 == fapi_tdd_period)
+        return 20;
+    else if (6 == fapi_tdd_period)
+        return 40;
+    else if (7 == fapi_tdd_period)
+        return 80;
+    else
+        return 0;
+
+    return 0;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  nSubcCommon  Sub carrier spacing
+ *  @param[in]  nDLBandwidth/ nULBandwidth  Sub carrier spacing
+ *  
+ *  
+ *  @return     IAPI FFT size for DL UL
+ *
+ *  @description
+ *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
+ *  structure based on *subCarrierSpacingCommon - 3*.
+ *
+**/
+uint16_t nr5g_fapi_calc_fft_size(
+    uint8_t sub_carrier_common,
+    uint16_t bw)
+{
+    if (FAPI_SUBCARRIER_SPACING_15 == sub_carrier_common) {
+        if (FAPI_BANDWIDTH_5_MHZ == bw)
+            return FAPI_FFT_SIZE_512;
+        else if (FAPI_BANDWIDTH_10_MHZ == bw)
+            return FAPI_FFT_SIZE_1024;
+        else if ((FAPI_BANDWIDTH_15_MHZ == bw) || (FAPI_BANDWIDTH_20_MHZ == bw))
+            return FAPI_FFT_SIZE_2048;
+        else if ((FAPI_BANDWIDTH_25_MHZ == bw) || (FAPI_BANDWIDTH_30_MHZ == bw)
+            || (FAPI_BANDWIDTH_40_MHZ == bw) || (FAPI_BANDWIDTH_50_MHZ == bw))
+            return FAPI_FFT_SIZE_4096;
+    } else if (FAPI_SUBCARRIER_SPACING_30 == sub_carrier_common) {
+        if ((FAPI_BANDWIDTH_5_MHZ == bw) || (FAPI_BANDWIDTH_10_MHZ == bw))
+            return FAPI_FFT_SIZE_512;
+        else if ((FAPI_BANDWIDTH_15_MHZ == bw) || (FAPI_BANDWIDTH_20_MHZ == bw))
+            return FAPI_FFT_SIZE_1024;
+        else if ((FAPI_BANDWIDTH_25_MHZ == bw) || (FAPI_BANDWIDTH_30_MHZ == bw)
+            || (FAPI_BANDWIDTH_40_MHZ == bw) || (FAPI_BANDWIDTH_50_MHZ == bw))
+            return FAPI_FFT_SIZE_2048;
+        else if ((FAPI_BANDWIDTH_60_MHZ == bw) || (FAPI_BANDWIDTH_70_MHZ == bw)
+            || (FAPI_BANDWIDTH_80_MHZ == bw) || ((FAPI_BANDWIDTH_90_MHZ == bw))
+            || (FAPI_BANDWIDTH_100_MHZ == bw))
+            return FAPI_FFT_SIZE_4096;
+    } else if (FAPI_SUBCARRIER_SPACING_60 == sub_carrier_common) {
+        if ((FAPI_BANDWIDTH_10_MHZ == bw) || (FAPI_BANDWIDTH_15_MHZ == bw) ||
+            (FAPI_BANDWIDTH_20_MHZ == bw) || (FAPI_BANDWIDTH_25_MHZ == bw))
+            return FAPI_FFT_SIZE_512;
+        else if ((FAPI_BANDWIDTH_30_MHZ == bw) || (FAPI_BANDWIDTH_40_MHZ == bw)
+            || (FAPI_BANDWIDTH_50_MHZ == bw))
+            return FAPI_FFT_SIZE_1024;
+        else if ((FAPI_BANDWIDTH_60_MHZ == bw) || (FAPI_BANDWIDTH_70_MHZ == bw)
+            || (FAPI_BANDWIDTH_80_MHZ == bw) || (FAPI_BANDWIDTH_90_MHZ == bw) ||
+            (FAPI_BANDWIDTH_100_MHZ == bw))
+            return FAPI_FFT_SIZE_2048;
+        else if (FAPI_BANDWIDTH_200_MHZ == bw)
+            return FAPI_FFT_SIZE_4096;
+    } else if (FAPI_SUBCARRIER_SPACING_120 == sub_carrier_common) {
+        if (FAPI_BANDWIDTH_50_MHZ == bw)
+            return FAPI_FFT_SIZE_512;
+        else if (FAPI_BANDWIDTH_100_MHZ == bw)
+            return FAPI_FFT_SIZE_1024;
+        else if (FAPI_BANDWIDTH_200_MHZ == bw)
+            return FAPI_FFT_SIZE_2048;
+        else if (FAPI_BANDWIDTH_400_MHZ == bw)
+            return FAPI_FFT_SIZE_4096;
+    } else {
+    }
+
+    return 0;
+}
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_dl_iq_samples_req.c b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_dl_iq_samples_req.c
new file mode 100644 (file)
index 0000000..c6b3b35
--- /dev/null
@@ -0,0 +1,130 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ * @file
+ * This file consist of implementation of FAPI DLIQSamples.request message.
+ *
+ **/
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_fapi_req Pointer to FAPI DLIQSamples.request message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This is a timer mode specific message used to transmit IQ Sample API to L1.
+ *  In DL direction, L1 copies the IQ samples into a file. 
+ *
+ *
+**/
+#ifdef DEBUG_MODE
+uint8_t nr5g_fapi_dl_iq_samples_request(
+    fapi_vendor_ext_iq_samples_req_t * p_fapi_req)
+{
+    uint16_t num_ant;
+
+    fapi_vendor_ext_iq_samples_info_t *p_file_info;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_Samples.request] Invalid FAPI "
+                "message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_DL_IQ_SAMPLES, 1,
+        (uint32_t) sizeof(fapi_vendor_ext_iq_samples_info_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_Samples.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_file_info = (fapi_vendor_ext_iq_samples_info_t *) (p_list_elem + 1);
+    p_file_info->carrNum = p_fapi_req->iq_samples_info.carrNum;
+    p_file_info->numSubframes = p_fapi_req->iq_samples_info.numSubframes;
+    p_file_info->testUeMode = p_fapi_req->iq_samples_info.testUeMode;
+    p_file_info->timerModeFreqDomain =
+        p_fapi_req->iq_samples_info.timerModeFreqDomain;
+    p_file_info->phaseCompensationEnable =
+        p_fapi_req->iq_samples_info.phaseCompensationEnable;
+    p_file_info->startFrameNum = p_fapi_req->iq_samples_info.startFrameNum;
+    p_file_info->startSlotNum = p_fapi_req->iq_samples_info.startSlotNum;
+    if (FAILURE == NR5G_FAPI_MEMCPY(p_file_info->buffer,
+            sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_BUFFER_SIZE,
+            p_fapi_req->iq_samples_info.buffer, sizeof(CONFIGREQUESTStruct))) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_Samples.request] Buffer copy "
+                "failed!!!"));
+    }
+
+    if (FAILURE == NR5G_FAPI_STRCPY(p_file_info->filename_out_dl_iq,
+            sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+            p_fapi_req->iq_samples_info.filename_out_dl_iq,
+            sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_Samples.request] file name copy "
+                "failed!!!"));
+    }
+
+    if (FAILURE == NR5G_FAPI_STRCPY(p_file_info->filename_out_dl_iq_urllc,
+            sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+            p_fapi_req->iq_samples_info.filename_out_dl_iq_urllc,
+            sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_Samples.request] URLLC file name "
+                "copy failed!!!"));
+    }
+
+    for (num_ant = 0; num_ant < FAPI_MAX_IQ_SAMPLE_DL_PORTS; num_ant++) {
+        if (FAILURE ==
+            NR5G_FAPI_STRCPY(p_file_info->filename_out_dl_beam[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+                p_fapi_req->iq_samples_info.filename_out_dl_beam[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+
+            NR5G_FAPI_LOG(ERROR_LOG, ("[DL_IQ_Samples.request] DL Beam "
+                    "file name copy failed!!!"));
+        }
+    }
+
+    for (num_ant = 0; num_ant < FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS; num_ant++) {
+        if (FAILURE ==
+            NR5G_FAPI_STRCPY(p_file_info->filename_out_ul_beam[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+                p_fapi_req->iq_samples_info.filename_out_ul_beam[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[DL_IQ_Samples.request] UL Beam "
+                    "file name copy failed!!!"));
+        }
+    }
+
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    NR5G_FAPI_LOG(INFO_LOG, ("[DL_IQ_Samples.request][%d]",
+            p_fapi_req->iq_samples_info.carrNum));
+
+    return SUCCESS;
+}
+#endif
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_shutdown_req.c b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_shutdown_req.c
new file mode 100644 (file)
index 0000000..376f6f9
--- /dev/null
@@ -0,0 +1,89 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI Start.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI SHUTDOWN.request message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This vendor specific message  instructs a configured PHY to Shutdown its processing 
+ *  by cleaning up the resources alloted when PHY is up and running.
+ *
+**/
+uint8_t nr5g_fapi_shutdown_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_vendor_ext_shutdown_req_t * p_fapi_req)
+{
+    PSHUTDOWNREQUESTStruct p_shutdown_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.request] Invalid "
+                "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_vext_shutdown_req++;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.request] Invalid handle to fapi "
+                "message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_SHUTDOWN_REQ, 1, (uint32_t) sizeof(SHUTDOWNREQUESTStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[SHUTDOWN.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+    p_shutdown_req = (PSHUTDOWNREQUESTStruct) (p_list_elem + 1);
+    p_shutdown_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_SHUTDOWN_REQ;
+    p_shutdown_req->sMsgHdr.nMessageLen =
+        (uint16_t) sizeof(SHUTDOWNREQUESTStruct);
+    p_shutdown_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
+    p_shutdown_req->sSFN_Slot.nSlot = p_fapi_req->slot;
+    p_shutdown_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+    p_phy_instance->shutdown_test_type = p_shutdown_req->nTestType =
+        p_fapi_req->test_type;
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_shutdown_req++;
+    NR5G_FAPI_LOG(INFO_LOG, ("[SHUTDOWN.request][%d]", p_phy_instance->phy_id));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_start_req.c b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_start_req.c
new file mode 100644 (file)
index 0000000..659a1f2
--- /dev/null
@@ -0,0 +1,127 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI START.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI START.request message structure.
+ *  @param[in]  p_fapi_vendor_msg Pointer to FAPI vendor message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message instructs a configured PHY to start transmitting as an eNB. If
+ *  the PHY is in the CONFIGURED state, it will issue SLOT indication.
+ *  After the PHY has sent its first SLOT.indication message it enters the
+ *  RUNNING state. If the PHY receives a START.request in either the IDLE or
+ *  RUNNING state it will return an ERROR.indication including an INVALID_STATE
+ *  error.
+ *
+ *  The *nSFN*, *nSlot*, and *nCarrierIdx* parameters are vendor specific 
+ *  configuration and programmed through Vendor Specific Message structure 
+ *  ::fapi_start_req_vendor_msg_t 
+ *
+ *  The *phyMode*, *ttiPeriod*, and *numSubframes* parameters of Vendor Specific 
+ *  Message structure ::fapi_start_req_vendor_msg_t are applicable only for 
+ *  TIMER mode (used for debugging only).
+ *
+**/
+uint8_t nr5g_fapi_start_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_start_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PSTARTREQUESTStruct p_start_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.request] Invalid " "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_start_req++;
+
+    if (FAPI_STATE_CONFIGURED != p_phy_instance->state) {
+        // TODO: Return Error indication to mac 
+        //         // Please refer PHY State transition.
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.request] Received in "
+                "other than CONFIGURED State"));
+        return FAILURE;
+    }
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.request] Invalid fapi " "message"));
+        return FAILURE;
+    }
+
+    if (NULL == p_fapi_vendor_msg) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.request] Invalid fapi "
+                "vendor message"));
+        return FAILURE;
+    }
+
+    if (p_fapi_vendor_msg->start_req_vendor.mode > 1) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[START.request] PHY Mode %u invalid",
+                p_fapi_vendor_msg->start_req_vendor.mode));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_START_REQ, 1, (uint32_t) sizeof(STARTREQUESTStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, (" [START.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_start_req = (PSTARTREQUESTStruct) (p_list_elem + 1);
+    p_start_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_START_REQ;
+    p_start_req->sMsgHdr.nMessageLen = (uint16_t) sizeof(STARTREQUESTStruct);
+    p_start_req->sSFN_Slot.nSFN = p_fapi_vendor_msg->start_req_vendor.sfn;
+    p_start_req->sSFN_Slot.nSlot = p_fapi_vendor_msg->start_req_vendor.slot;
+    p_start_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+    p_start_req->nMode = p_fapi_vendor_msg->start_req_vendor.mode;
+#ifdef DEBUG_MODE
+    /* Setting period and count only for timer mode */
+    if (1 == p_fapi_vendor_msg->start_req_vendor.mode) {
+        p_start_req->nCount = p_fapi_vendor_msg->start_req_vendor.count;
+        p_start_req->nPeriod = p_fapi_vendor_msg->start_req_vendor.period;
+    }
+#endif
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_start_req++;
+    NR5G_FAPI_LOG(INFO_LOG, ("[START.request][%d]", p_phy_instance->phy_id));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_stop_req.c b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_stop_req.c
new file mode 100644 (file)
index 0000000..30350bc
--- /dev/null
@@ -0,0 +1,97 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI STOP.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI STOP.request message structure.
+ *  @param[in]  p_fapi_vendor_msg Pointer to FAPI vendor message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message allows L2/L3 to move the PHY from RUNNING state to CONFIGURED
+ *  state. This stops the PHY transmitting as an gNB.
+ *
+ *  The *nSFN*, *nSlot*, and *nCarrierIdx* parameters are vendor specific 
+ *  configuration and programmed through Vendor Specific Message structure 
+ *  ::fapi_start_req_vendor_msg_t 
+ *
+**/
+uint8_t nr5g_fapi_stop_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_stop_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PSTOPREQUESTStruct p_stop_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.request] Invalid " "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_stop_req++;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.request] Invalid fapi " "message"));
+        return FAILURE;
+    }
+
+    if (NULL == p_fapi_vendor_msg) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.request] Invalid fapi "
+                "vendor message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_STOP_REQ, 1, (uint32_t) sizeof(STOPREQUESTStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[STOP.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_stop_req = (PSTOPREQUESTStruct) (p_list_elem + 1);
+    p_stop_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_STOP_REQ;
+    p_stop_req->sMsgHdr.nMessageLen = (uint16_t) sizeof(STOPREQUESTStruct);
+    p_stop_req->sSFN_Slot.nSFN = p_fapi_vendor_msg->stop_req_vendor.sfn;
+    p_stop_req->sSFN_Slot.nSlot = p_fapi_vendor_msg->stop_req_vendor.slot;
+    p_stop_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+
+    /* Add element to send list */
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_stop_req++;
+    NR5G_FAPI_LOG(INFO_LOG, ("[STOP.request][%d]", p_phy_instance->phy_id));
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_ul_iq_samples_req.c b/fapi_5g/source/api/fapi2phy/p5/nr5g_fapi_proc_ul_iq_samples_req.c
new file mode 100644 (file)
index 0000000..c951937
--- /dev/null
@@ -0,0 +1,133 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI UL_IQ_SAMPLES.request message.
+ *
+ **/
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI UL_IQ_SAMPLES.request message structure.
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This is a timer mode specific message used to transmit IQ Sample API to L1.
+ *  In UL direction, L1 opens the IQ samples file and stores it into local
+ *  buffers for processing. 
+ *
+ *
+**/
+#ifdef DEBUG_MODE
+uint8_t nr5g_fapi_ul_iq_samples_request(
+    fapi_vendor_ext_iq_samples_req_t * p_fapi_req)
+{
+    uint16_t num_ant;
+
+    fapi_vendor_ext_iq_samples_info_t *p_file_info;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+
+    /* Below print is for better logging on console in debug mode. */
+    NR5G_FAPI_LOG(INFO_LOG, (""));
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, (" [UL_IQ_SAMPLES.request] Invalid fapi "
+                "message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_UL_IQ_SAMPLES, 1,
+        (uint32_t) sizeof(fapi_vendor_ext_iq_samples_info_t));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_IQ_SAMPLES.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_file_info = (fapi_vendor_ext_iq_samples_info_t *) (p_list_elem + 1);
+    p_file_info->carrNum = p_fapi_req->iq_samples_info.carrNum;
+    p_file_info->numSubframes = p_fapi_req->iq_samples_info.numSubframes;
+    p_file_info->testUeMode = p_fapi_req->iq_samples_info.testUeMode;
+    p_file_info->timerModeFreqDomain =
+        p_fapi_req->iq_samples_info.timerModeFreqDomain;
+    p_file_info->phaseCompensationEnable =
+        p_fapi_req->iq_samples_info.phaseCompensationEnable;
+    p_file_info->startFrameNum = p_fapi_req->iq_samples_info.startFrameNum;
+    p_file_info->startSlotNum = p_fapi_req->iq_samples_info.startSlotNum;
+    if (FAILURE == NR5G_FAPI_MEMCPY(p_file_info->buffer,
+            sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_BUFFER_SIZE,
+            p_fapi_req->iq_samples_info.buffer, sizeof(CONFIGREQUESTStruct))) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_IQ_Samples.request] Buffer copy "
+                "failed!!!"));
+    }
+
+    for (num_ant = 0; num_ant < FAPI_MAX_IQ_SAMPLE_UL_VIRTUAL_PORTS; num_ant++) {
+        if (FAILURE == NR5G_FAPI_STRCPY(p_file_info->filename_in_ul_iq[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+                p_fapi_req->iq_samples_info.filename_in_ul_iq[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[UL_IQ_Samples.request] file name copy "
+                    "failed!!!"));
+        }
+
+        if (FAILURE ==
+            NR5G_FAPI_STRCPY(p_file_info->filename_in_ul_urllc[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+                p_fapi_req->iq_samples_info.filename_in_ul_urllc[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[UL_IQ_Samples.request] URLLC file name " "copy failed!!!"));
+        }
+        if (FAILURE ==
+            NR5G_FAPI_STRCPY(p_file_info->filename_in_prach_iq[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+                p_fapi_req->iq_samples_info.filename_in_prach_iq[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[UL_IQ_Samples.request] PRACH file name " "copy failed!!!"));
+        }
+    }
+
+    for (num_ant = 0; num_ant < FAPI_MAX_IQ_SAMPLE_UL_ANTENNA; num_ant++) {
+        if (FAILURE ==
+            NR5G_FAPI_STRCPY(p_file_info->filename_in_srs_iq[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE,
+                p_fapi_req->iq_samples_info.filename_in_srs_iq[num_ant],
+                sizeof(uint8_t) * FAPI_MAX_IQ_SAMPLE_FILE_SIZE)) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("[UL_IQ_Samples.request] SRS file name " "copy failed!!!"));
+        }
+    }
+
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+    NR5G_FAPI_LOG(INFO_LOG, ("[UL_IQ_SAMPLES.request][%d]",
+            p_fapi_req->iq_samples_info.carrNum));
+
+    return SUCCESS;
+}
+#endif
diff --git a/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_fapi2phy_p7_proc.h b/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_fapi2phy_p7_proc.h
new file mode 100644 (file)
index 0000000..1d75608
--- /dev/null
@@ -0,0 +1,49 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to PHY P7 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2PHY_P7_PROC_H_
+#define _NR5G_FAPI_FAP2PHY_P7_PROC_H_
+
+uint8_t nr5g_fapi_dl_tti_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_tti_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+uint8_t nr5g_fapi_ul_tti_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_tti_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+uint8_t nr5g_fapi_ul_dci_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_dci_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+uint8_t nr5g_fapi_tx_data_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_tx_data_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg);
+
+#endif                          //_NR5G_FAPI_FAP2PHY_P7_PROC_H_
diff --git a/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_fapi2phy_p7_pvt_proc.h b/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_fapi2phy_p7_pvt_proc.h
new file mode 100644 (file)
index 0000000..8ba887a
--- /dev/null
@@ -0,0 +1,134 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of macros, structures and prototypes of all FAPI
+ * to PHY P7 messages
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FAP2PHY_P7_PVT_PROC_H_
+#define _NR5G_FAPI_FAP2PHY_P7_PVT_PROC_H_
+// DL_TTI.req
+uint8_t nr5g_fapi_dl_tti_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_tti_req_t * p_fapi_req,
+    PDLConfigRequestStruct p_ia_dl_config_req);
+
+void nr5g_fapi_fill_dci_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_pdcch_pdu_t * p_pdcch_pdu,
+    PDCIPDUStruct p_dci_pdu);
+
+void nr5g_fapi_fill_dci_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_pdcch_pdu_t * p_pdcch_pdu,
+    PDCIPDUStruct p_dci_pdu);
+
+void nr5g_fapi_fill_pdsch_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_pdsch_pdu_t * p_pdsch_pdu,
+    PDLSCHPDUStruct p_dlsch_pdu);
+
+uint8_t nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(
+    uint8_t beta_pdcch_1_0);
+
+void nr5g_fapi_fill_ssb_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PBCHPDUStruct p_bch_pdu,
+    fapi_dl_ssb_pdu_t * p_ssb_pdu);
+
+void nr5g_fapi_fill_csi_rs_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PCSIRSPDUStruct pCSIRSPdu,
+    fapi_dl_csi_rs_pdu_t * p_csi_rs_pdu);
+
+// UL_TTI.req
+uint8_t nr5g_fapi_calc_n_rbg_size(
+    uint16_t bwp_size);
+
+uint32_t nr5g_fapi_calc_n_rbg_index_entry(
+    uint8_t n_rbg_size,
+    fapi_ul_pusch_pdu_t * p_pusch_pdu);
+
+uint8_t nr5g_fapi_calc_alpha_scaling(
+    uint8_t fapi_alpha_scaling);
+
+void nr5g_fapi_pusch_to_phy_ulsch_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    nr5g_fapi_pusch_info_t * pusch_info,
+    fapi_ul_pusch_pdu_t * p_pusch_pdu,
+    ULSCHPDUStruct * p_ul_data_chan);
+
+void nr5g_fapi_pusch_data_to_phy_ulsch_translation(
+    nr5g_fapi_pusch_info_t * p_pusch_info,
+    fapi_pusch_data_t * p_pusch_data,
+    ULSCHPDUStruct * p_ul_data_chan);
+
+void nr5g_fapi_pusch_uci_to_phy_ulsch_translation(
+    fapi_pusch_uci_t * p_pusch_uci,
+    ULSCHPDUStruct * p_ul_data_chan);
+
+void nr5g_fapi_pusch_ptrs_to_phy_ulsch_translation(
+    fapi_pusch_ptrs_t * p_pusch_ptrs,
+    ULSCHPDUStruct * p_ul_data_chan);
+
+void nr5g_fapi_pusch_to_phy_ulsch_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    nr5g_fapi_pusch_info_t * p_pusch_info,
+    fapi_ul_pusch_pdu_t * p_pusch_pdu,
+    ULSCHPDUStruct * p_ul_data_chan);
+
+uint8_t nr5g_get_pucch_resources_group_id(
+    uint8_t num_groups,
+    uint16_t initial_cyclic_shift,
+    uint8_t nr_of_symbols,
+    uint8_t start_symbol_index,
+    uint8_t time_domain_occ_idx,
+    nr5g_fapi_pucch_resources_t * p_pucch_resources);
+
+void nr5g_fapi_pucch_to_phy_ulcch_uci_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    nr5g_fapi_pucch_info_t * p_pucch_info,
+    fapi_ul_pucch_pdu_t * p_pucch_pdu,
+    uint8_t * num_groups,
+    nr5g_fapi_pucch_resources_t * p_pucch_resources,
+    ULCCHUCIPDUStruct * p_ul_ctrl_chan);
+
+void nr5g_fapi_srs_to_phy_srs_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_srs_pdu_t * p_srs_pdu,
+    nr5g_fapi_srs_info_t * p_srs_info,
+    SRSPDUStruct * p_ul_srs_chan);
+
+uint8_t nr5g_fapi_ul_tti_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_tti_req_t * p_fapi_req,
+    PULConfigRequestStruct p_ia_ul_config_req);
+
+uint8_t nr5g_fapi_ul_dci_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_dci_req_t * p_fapi_req,
+    PULDCIRequestStruct p_ia_ul_dci_req);
+
+uint8_t nr5g_fapi_tx_data_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_tx_data_req_t * p_fapi_req,
+    PTXRequestStruct p_ia_tx_req);
+#endif                          //_NR5G_FAPI_FAP2PHY_P7_PVT_PROC_H_
diff --git a/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_dl_tti_req.c b/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_dl_tti_req.c
new file mode 100644 (file)
index 0000000..510405b
--- /dev/null
@@ -0,0 +1,504 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI DL_TTI.request message.
+ *
+ **/
+#include <rte_memcpy.h>
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_dpdk.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p7_proc.h"
+#include "nr5g_fapi_fapi2phy_p7_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+/** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI DL_TTI.request message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message indicates the control information for a downlink slot. 
+ *
+**/
+uint8_t nr5g_fapi_dl_tti_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_tti_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PDLConfigRequestStruct p_ia_dl_config_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+    UNUSED(p_fapi_vendor_msg);
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Invalid " "Phy Instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_dl_tti_req++;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Invalid fapi " "message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_DL_CONFIG_REQ, 1,
+        (uint32_t) sizeof(DLConfigRequestStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_ia_dl_config_req = (PDLConfigRequestStruct) (p_list_elem + 1);
+    if (FAILURE == nr5g_fapi_dl_tti_req_to_phy_translation(p_phy_instance,
+            p_fapi_req, p_ia_dl_config_req)) {
+        nr5g_fapi_fapi2phy_destroy_api_list_elem(p_list_elem);
+        NR5G_FAPI_LOG(DEBUG_LOG, ("[DL_TTI.request][%d][%d,%d] Not Sent",
+                p_phy_instance->phy_id, p_ia_dl_config_req->sSFN_Slot.nSFN,
+                p_ia_dl_config_req->sSFN_Slot.nSlot));
+        return FAILURE;
+    }
+    /* Add element to send list */
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_dl_config_req++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[DL_TTI.request][%d][%d,%d]",
+            p_phy_instance->phy_id, p_ia_dl_config_req->sSFN_Slot.nSFN,
+            p_ia_dl_config_req->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p5_fapi2phy_proc
+ *
+ *  @param[in]   p_fapi_req Pointer to FAPI DL_TTI.request structure.
+ *  @param[out]  p_ia_dl_config_req Pointer to IAPI DL_TTI.request structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts FAPI DL_TTI.request to IAPI DL_Config.request
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_dl_tti_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_tti_req_t * p_fapi_req,
+    PDLConfigRequestStruct p_phy_req)
+{
+    int idx = 0, nDCI = 0, jdx = 0;
+    uint32_t pdsch_size, pdcch_size, pbch_size, csirs_size, total_size;
+    nr5g_fapi_stats_t *p_stats;
+
+    fapi_dl_tti_req_pdu_t *p_fapi_dl_tti_req_pdu = NULL;
+    fapi_dl_pdcch_pdu_t *p_pdcch_pdu = NULL;
+    fapi_dl_pdsch_pdu_t *p_pdsch_pdu = NULL;
+    fapi_dl_csi_rs_pdu_t *p_csi_rs_pdu = NULL;
+    fapi_dl_ssb_pdu_t *p_ssb_pdu = NULL;
+    fapi_ue_info_t *p_ueGrpInfo = NULL;
+
+    PPDUStruct pPduStruct = NULL;
+    PDLSCHPDUStruct p_dlsch_pdu = NULL;
+    PDCIPDUStruct p_dci_pdu = NULL;
+    PBCHPDUStruct p_bch_pdu = NULL;
+    PCSIRSPDUStruct pCSIRSPdu = NULL;
+    PPDSCHGroupInfoStruct pPDSCHGroupInfoStruct = NULL;
+
+    total_size = sizeof(DLConfigRequestStruct);
+    pdsch_size = RUP32B(sizeof(DLSCHPDUStruct));
+    pdcch_size = RUP32B(sizeof(DCIPDUStruct));
+    pbch_size = RUP32B(sizeof(BCHPDUStruct));
+    csirs_size = RUP32B(sizeof(CSIRSPDUStruct));
+
+    p_stats = &p_phy_instance->stats;
+    NR5G_FAPI_MEMSET(p_phy_req, sizeof(DLConfigRequestStruct), 0, total_size);
+    p_phy_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_DL_CONFIG_REQ;
+    p_phy_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+    p_phy_req->nGroup = p_fapi_req->nGroup;
+    p_phy_req->nPDU = p_fapi_req->nPdus;
+    p_phy_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
+    p_phy_req->sSFN_Slot.nSlot = p_fapi_req->slot;
+
+    // setting to defaults
+    p_phy_req->nLte_CRS_carrierBandwidthDL = 100;
+    p_phy_req->nLte_CRS_nrofCRS_Ports = 2;
+
+    for (idx = 0; idx < p_phy_req->nGroup; ++idx) {
+        p_ueGrpInfo = &p_fapi_req->ue_grp_info[idx];
+        pPDSCHGroupInfoStruct = &p_phy_req->sPDSCHGroupInfoStruct[idx];
+        pPDSCHGroupInfoStruct->nUE = p_ueGrpInfo->nUe;
+        pPDSCHGroupInfoStruct->rsv1[0] = 0;
+        pPDSCHGroupInfoStruct->rsv1[1] = 0;
+        pPDSCHGroupInfoStruct->rsv1[2] = 0;
+        for (jdx = 0; jdx < p_ueGrpInfo->nUe; ++jdx) {
+            pPDSCHGroupInfoStruct->nPduIdx[jdx] = p_ueGrpInfo->pduIdx[jdx];
+        }
+    }
+
+    pPduStruct = p_phy_req->sDLPDU;
+    for (idx = 0; idx < p_phy_req->nPDU; ++idx) {
+        p_stats->fapi_stats.fapi_dl_tti_pdus++;
+        p_fapi_dl_tti_req_pdu = &p_fapi_req->pdus[idx];
+        switch (p_fapi_dl_tti_req_pdu->pduType) {
+            case DL_PDU_TYPE_DCI:
+                nDCI++;
+                p_dci_pdu = (PDCIPDUStruct) pPduStruct;
+                NR5G_FAPI_MEMSET(p_dci_pdu, RUP32B(sizeof(DCIPDUStruct)), 0,
+                    pdcch_size);
+                p_pdcch_pdu = &p_fapi_dl_tti_req_pdu->pdu.pdcch_pdu;
+                p_dci_pdu->sPDUHdr.nPDUType = p_fapi_dl_tti_req_pdu->pduType;
+                p_dci_pdu->sPDUHdr.nPDUSize = pdcch_size;
+                total_size += pdcch_size;
+                nr5g_fapi_fill_dci_pdu(p_phy_instance, p_pdcch_pdu, p_dci_pdu);
+                break;
+
+            case DL_PDU_TYPE_DLSCH:
+                p_dlsch_pdu = (PDLSCHPDUStruct) pPduStruct;
+                p_pdsch_pdu = &p_fapi_dl_tti_req_pdu->pdu.pdsch_pdu;
+                NR5G_FAPI_MEMSET(p_dlsch_pdu, RUP32B(sizeof(DLSCHPDUStruct)), 0,
+                    pdsch_size);
+                p_dlsch_pdu->sPDUHdr.nPDUType = p_fapi_dl_tti_req_pdu->pduType;
+                p_dlsch_pdu->sPDUHdr.nPDUSize = pdsch_size;
+                total_size += pdsch_size;
+                nr5g_fapi_fill_pdsch_pdu(p_phy_instance, p_pdsch_pdu,
+                    p_dlsch_pdu);
+                break;
+
+            case DL_PDU_TYPE_PBCH:
+                p_bch_pdu = (PBCHPDUStruct) pPduStruct;
+                p_ssb_pdu = &p_fapi_dl_tti_req_pdu->pdu.ssb_pdu;
+                NR5G_FAPI_MEMSET(p_bch_pdu, RUP32B(sizeof(BCHPDUStruct)), 0,
+                    pbch_size);
+                p_bch_pdu->sPDUHdr.nPDUType = p_fapi_dl_tti_req_pdu->pduType;
+                p_bch_pdu->sPDUHdr.nPDUSize = pbch_size;
+                total_size += pbch_size;
+                nr5g_fapi_fill_ssb_pdu(p_phy_instance, p_bch_pdu, p_ssb_pdu);
+                break;
+
+            case DL_PDU_TYPE_CSIRS:
+                pCSIRSPdu = (PCSIRSPDUStruct) pPduStruct;
+                p_csi_rs_pdu = &p_fapi_dl_tti_req_pdu->pdu.csi_rs_pdu;
+                NR5G_FAPI_MEMSET(pCSIRSPdu, RUP32B(sizeof(CSIRSPDUStruct)), 0,
+                    csirs_size);
+                pCSIRSPdu->sPDUHdr.nPDUType = p_fapi_dl_tti_req_pdu->pduType;
+                pCSIRSPdu->sPDUHdr.nPDUSize = csirs_size;
+                total_size += csirs_size;
+                nr5g_fapi_fill_csi_rs_pdu(p_phy_instance, pCSIRSPdu,
+                    p_csi_rs_pdu);
+                break;
+
+            default:
+                NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI] Invalid Pdu Type: %d",
+                        pPduStruct->nPDUType));
+                return FAILURE;
+        }
+        pPduStruct =
+            (PDUStruct *) ((uint8_t *) pPduStruct + pPduStruct->nPDUSize);
+        p_stats->iapi_stats.iapi_dl_tti_pdus++;
+    }
+
+    p_phy_req->nDCI = nDCI;
+    p_phy_req->sMsgHdr.nMessageLen = total_size;
+    return SUCCESS;
+}
+
+/** @ingroup group_nr5g_test_config
+ *
+ *  @param[in]   p_pdcch_pdu
+ *  @param[out]  p_dci_pdu
+ *
+ *  @return      void
+ *
+ *  @description
+ *  This function fills FAPI PDCCH Pdu from IAPI DCIPdu
+ *
+**/
+void nr5g_fapi_fill_dci_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_pdcch_pdu_t * p_pdcch_pdu,
+    PDCIPDUStruct p_dci_pdu)
+{
+    nr5g_fapi_stats_t *p_stats = NULL;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_dl_tti_pdcch_pdus++;
+
+    p_dci_pdu->nBWPSize = p_pdcch_pdu->bwpSize;
+    p_dci_pdu->nBWPStart = p_pdcch_pdu->bwpStart;
+    p_dci_pdu->nSubcSpacing = p_pdcch_pdu->subCarrierSpacing;
+    p_dci_pdu->nCpType = p_pdcch_pdu->cyclicPrefix;
+    p_dci_pdu->nCCEStartIndex = p_pdcch_pdu->startSymbolIndex;
+    p_dci_pdu->nNrOfSymbols = p_pdcch_pdu->durationSymbols;
+    p_dci_pdu->nStartSymbolIndex = p_pdcch_pdu->startSymbolIndex;
+    p_dci_pdu->nFreqDomain[0] = ((uint32_t) p_pdcch_pdu->freqDomainResource[0] |
+        (((uint32_t) p_pdcch_pdu->freqDomainResource[1]) << 8) |
+        (((uint32_t) p_pdcch_pdu->freqDomainResource[2]) << 16) |
+        (((uint32_t) p_pdcch_pdu->freqDomainResource[3]) << 24));
+    p_dci_pdu->nFreqDomain[1] = ((uint32_t) p_pdcch_pdu->freqDomainResource[4] |
+        (((uint32_t) p_pdcch_pdu->freqDomainResource[5]) << 8));
+    p_dci_pdu->nCCEToREGType = p_pdcch_pdu->cceRegMappingType;
+    p_dci_pdu->nREGBundleSize = p_pdcch_pdu->regBundleSize;
+    p_dci_pdu->nInterleaveSize = p_pdcch_pdu->interleaverSize;
+    p_dci_pdu->nShift = p_pdcch_pdu->shiftIndex;
+    p_dci_pdu->nCoreSetType = p_pdcch_pdu->coreSetType;
+    p_dci_pdu->nCCEStartIndex = p_pdcch_pdu->dlDci[0].cceIndex;
+    p_dci_pdu->nAggrLvl = p_pdcch_pdu->dlDci[0].aggregationLevel;
+    p_dci_pdu->nScid = p_pdcch_pdu->dlDci[0].scramblingId;
+    p_dci_pdu->nID = p_pdcch_pdu->dlDci[0].scramblingId;
+    p_dci_pdu->nRNTIScramb = p_pdcch_pdu->dlDci[0].scramblingRnti;
+    p_dci_pdu->nRNTI = p_pdcch_pdu->dlDci[0].rnti;
+    p_dci_pdu->nTotalBits = p_pdcch_pdu->dlDci[0].payloadSizeBits;
+
+    p_dci_pdu->nEpreRatioOfPDCCHToSSB =
+        nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(p_pdcch_pdu->dlDci[0].
+        beta_pdcch_1_0);
+    p_dci_pdu->nEpreRatioOfDmrsToSSB =
+        p_pdcch_pdu->dlDci[0].powerControlOfssetSS;
+    if (FAILURE == NR5G_FAPI_MEMCPY(p_dci_pdu->nDciBits,
+            sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN,
+            p_pdcch_pdu->dlDci[0].payload,
+            sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("PDCCH: RNTI: %d -- DCI Bits copy error.",
+                p_pdcch_pdu->dlDci[0].rnti));
+    }
+
+    p_stats->iapi_stats.iapi_dl_tti_pdcch_pdus++;
+}
+
+/** @ingroup group_nr5g_test_config
+ *
+ *  @param[in]    p_pdsch_pdu
+ *  @param[out]   p_dlsch_pdu
+ *
+ *  @return      void
+ *
+ *  @description
+ *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
+ *
+**/
+void nr5g_fapi_fill_pdsch_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_dl_pdsch_pdu_t * p_pdsch_pdu,
+    PDLSCHPDUStruct p_dlsch_pdu)
+{
+    uint8_t idx, port_index = 0;
+    nr5g_fapi_stats_t *p_stats;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_dl_tti_pdsch_pdus++;
+
+    p_dlsch_pdu->nBWPSize = p_pdsch_pdu->bwpSize;
+    p_dlsch_pdu->nBWPStart = p_pdsch_pdu->bwpStart;
+    p_dlsch_pdu->nSubcSpacing = p_pdsch_pdu->subCarrierSpacing;
+    p_dlsch_pdu->nCpType = p_pdsch_pdu->cyclicPrefix;
+    p_dlsch_pdu->nRNTI = p_pdsch_pdu->rnti;
+    p_dlsch_pdu->nUEId = p_pdsch_pdu->pdu_index;
+
+    // Codeword Information
+    p_dlsch_pdu->nNrOfCodeWords = p_pdsch_pdu->nrOfCodeWords;
+    p_dlsch_pdu->nMCS[0] = p_pdsch_pdu->cwInfo[0].mcsIndex;
+    p_dlsch_pdu->nMcsTable = p_pdsch_pdu->cwInfo[0].mcsTable;
+    p_dlsch_pdu->nRV[0] = p_pdsch_pdu->cwInfo[0].rvIndex;
+    p_dlsch_pdu->nTBSize[0] = p_pdsch_pdu->cwInfo[0].tbSize;
+    if (p_pdsch_pdu->nrOfCodeWords == 2) {
+        p_dlsch_pdu->nMCS[1] = p_pdsch_pdu->cwInfo[1].mcsIndex;
+        p_dlsch_pdu->nRV[1] = p_pdsch_pdu->cwInfo[1].rvIndex;
+        p_dlsch_pdu->nTBSize[1] = p_pdsch_pdu->cwInfo[1].tbSize;
+    }
+
+    p_dlsch_pdu->nNrOfAntennaPorts = p_phy_instance->phy_config.n_nr_of_rx_ant;
+    p_dlsch_pdu->nNrOfLayers = p_pdsch_pdu->nrOfLayers;
+    p_dlsch_pdu->nTransmissionScheme = p_pdsch_pdu->transmissionScheme;
+    p_dlsch_pdu->nDMRSConfigType = p_pdsch_pdu->dmrsConfigType;
+    p_dlsch_pdu->nNIDnSCID = p_pdsch_pdu->dlDmrsScramblingId;
+    p_dlsch_pdu->nNid = p_pdsch_pdu->dataScramblingId;
+    p_dlsch_pdu->nSCID = p_pdsch_pdu->scid;
+
+    for (idx = 0;
+        (idx < FAPI_MAX_DMRS_PORTS && port_index < p_dlsch_pdu->nNrOfLayers);
+        idx++) {
+        if ((p_pdsch_pdu->dmrsPorts >> idx) && 0x0001) {
+            p_dlsch_pdu->nPortIndex[port_index++] = idx;
+        }
+    }
+
+    // Resource Allocation Information
+    if (FAILURE == NR5G_FAPI_MEMCPY(p_dlsch_pdu->nRBGIndex,
+            sizeof(uint32_t) * MAX_DL_RBG_BIT_NUM,
+            p_pdsch_pdu->rbBitmap, sizeof(uint32_t) * MAX_DL_RBG_BIT_NUM)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("PDSCH: RNTI: %d Pdu Index: %d -- RB Bitmap"
+                "cpy error.", p_pdsch_pdu->rnti, p_pdsch_pdu->pdu_index));
+    }
+    p_dlsch_pdu->nResourceAllocType = p_pdsch_pdu->resourceAlloc;
+    p_dlsch_pdu->nRBStart = p_pdsch_pdu->rbStart;
+    p_dlsch_pdu->nRBSize = p_pdsch_pdu->rbSize;
+    p_dlsch_pdu->nVRBtoPRB = p_pdsch_pdu->vrbToPrbMapping;
+    p_dlsch_pdu->nStartSymbolIndex = p_pdsch_pdu->startSymbIndex;
+    p_dlsch_pdu->nNrOfSymbols = p_pdsch_pdu->nrOfSymbols;
+    p_dlsch_pdu->nNrOfCDMs = p_pdsch_pdu->numDmrsCdmGrpsNoData;
+    p_dlsch_pdu->nMappingType = p_pdsch_pdu->mappingType;
+    p_dlsch_pdu->nNrOfDMRSSymbols = p_pdsch_pdu->nrOfDmrsSymbols;
+    p_dlsch_pdu->nDMRSAddPos = p_pdsch_pdu->dmrsAddPos;
+
+    // PTRS Information
+    p_dlsch_pdu->nPTRSTimeDensity = p_pdsch_pdu->ptrsTimeDensity;
+    p_dlsch_pdu->nPTRSFreqDensity = p_pdsch_pdu->ptrsFreqDensity;
+    p_dlsch_pdu->nPTRSReOffset = p_pdsch_pdu->ptrsReOffset;
+    p_dlsch_pdu->nEpreRatioOfPDSCHToPTRS = p_pdsch_pdu->nEpreRatioOfPdschToPtrs;
+    // PTRS Information
+    p_dlsch_pdu->nPTRSPresent = p_pdsch_pdu->pduBitMap & 0x0001;
+    p_dlsch_pdu->nNrOfPTRSPorts =
+        __builtin_popcount(p_pdsch_pdu->ptrsPortIndex);
+    p_dlsch_pdu->nPTRSPortIndex[0] = p_pdsch_pdu->ptrsPortIndex;
+    // Don't Cares
+    p_dlsch_pdu->nNrOfDMRSAssPTRS[0] = 0x1;
+    p_dlsch_pdu->nNrOfDMRSAssPTRS[1] = 0x1;
+    p_dlsch_pdu->n1n2 = 0x201;
+    p_stats->iapi_stats.iapi_dl_tti_pdsch_pdus++;
+}
+
+/** @ingroup group_nr5g_test_config
+ *
+ *  @param[in]  nEpreRatioOfPDCCHToSSB
+ *
+ *  @return     uint8_t mapping
+ *
+ *  @description
+ *  This function maps IAPI to FAPI value range.
+ *
+ *
+ * Please refer 5G FAPI-IAPI Translator Module SW Design Document for details on
+ * the mapping.
+ *
+ * |-----------------------------------------|
+ * | nEpreRatioOfPDCCHToSSb | beta_PDCCH_1_0 |
+ * |-----------------------------------------|
+ * |             1          |      0 - 2     |
+ * |          1000          |        3       |
+ * |          2000          |        4       |
+ * |          3000          |        5       |
+ * |          4000          |        6       |
+ * |          5000          |        7       |
+ * |          6000          |        8       |
+ * |          7000          |        9       |
+ * |          8000          |       10       |
+ * |          9000          |       11       |
+ * |         10000          |       12       |
+ * |         11000          |       13       |
+ * |         12000          |       14       |
+ * |         13000          |       15       |
+ * |         14000          |       16       |
+ * |         14000          |       17       |
+ * |-----------------------------------------|
+ *
+**/
+uint8_t nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(
+    uint8_t beta_pdcch_1_0)
+{
+    if (beta_pdcch_1_0 > 0 && beta_pdcch_1_0 <= 2) {
+        return 1;
+    } else if (beta_pdcch_1_0 > 1 && beta_pdcch_1_0 < 17) {
+        return ((beta_pdcch_1_0 - 2) * 1000);
+    } else if (beta_pdcch_1_0 == 17) {
+        return ((beta_pdcch_1_0 - 3) * 1000);
+    } else {
+        return 0;
+    }
+}
+
+/** @ingroup group_nr5g_test_config
+ *
+ *  @param[in]   p_dlsch_pdu
+ *  @param[out]  p_pdsch_pdu
+ *
+ *  @return      void
+ *
+ *  @description
+ *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
+ *
+**/
+void nr5g_fapi_fill_ssb_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PBCHPDUStruct p_bch_pdu,
+    fapi_dl_ssb_pdu_t * p_ssb_pdu)
+{
+    nr5g_fapi_stats_t *p_stats;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_dl_tti_ssb_pdus++;
+    p_bch_pdu->nSSBSubcOffset = p_ssb_pdu->ssbSubCarrierOffset;
+    p_stats->iapi_stats.iapi_dl_tti_ssb_pdus++;
+    // p_ssb_pdu->bchPayload = p_bch_pdu->nMIB
+    // p_ssb_pdu->ssbBlockIndex 
+    // p_ssb_pdu->physCellId
+    // p_ssb_pdu->betaPss
+    // p_ssb_pdu->bchPayloadFlag
+    // p_ssb_pdu->ssbOffsetPointA
+    // p_ssb_pdu->preCodingAndBeamforming
+}
+
+/** @ingroup group_nr5g_test_config
+ *
+ *  @param[in]   p_dlsch_pdu
+ *  @param[out]  p_pdsch_pdu
+ *
+ *  @return      void
+ *
+ *  @description
+ *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
+ *
+**/
+void nr5g_fapi_fill_csi_rs_pdu(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    PCSIRSPDUStruct pCSIRSPdu,
+    fapi_dl_csi_rs_pdu_t * p_csi_rs_pdu)
+{
+    nr5g_fapi_stats_t *p_stats;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_dl_tti_csi_rs_pdus++;
+
+    pCSIRSPdu->nBWPSize = p_csi_rs_pdu->bwpSize;
+    pCSIRSPdu->nBWPStart = p_csi_rs_pdu->bwpStart;
+    pCSIRSPdu->nCDMType = p_csi_rs_pdu->cdmType;
+    pCSIRSPdu->nCSIType = p_csi_rs_pdu->csiType;
+    pCSIRSPdu->nCpType = p_csi_rs_pdu->cyclicPrefix;
+    pCSIRSPdu->nFreqDensity = p_csi_rs_pdu->freqDensity;
+    pCSIRSPdu->nFreqDomain = p_csi_rs_pdu->freqDomain;
+    pCSIRSPdu->nNrOfRBs = p_csi_rs_pdu->nrOfRbs;
+    pCSIRSPdu->nScrambId = p_csi_rs_pdu->scramId;
+    pCSIRSPdu->nStartRB = p_csi_rs_pdu->startRb;
+    pCSIRSPdu->nSubcSpacing = p_csi_rs_pdu->subCarrierSpacing;
+    pCSIRSPdu->nSymbL0 = p_csi_rs_pdu->symbL0;
+    pCSIRSPdu->nSymbL1 = p_csi_rs_pdu->symbL1;
+    pCSIRSPdu->nRow = p_csi_rs_pdu->row;
+    // Not mapping the beamforming parameters
+    // pCSIRSPdu->powerControlOffset = p_csi_rs_pdu->powerControlOffset;
+    // pCSIRSPdu->nEpreRatioToSSB = p_csi_rs_pdu->powerControlOffsetSs;
+    p_stats->iapi_stats.iapi_dl_tti_csi_rs_pdus++;
+}
+
diff --git a/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_tx_data_req.c b/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_tx_data_req.c
new file mode 100644 (file)
index 0000000..74e631a
--- /dev/null
@@ -0,0 +1,136 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI TX_Data.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p7_proc.h"
+#include "nr5g_fapi_fapi2phy_p7_pvt_proc.h"
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI TX_Data.request message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message contains the MAC PDU data for transmission over the air 
+ *  interface. The PDUs described in this message must follow the same order 
+ *  as DL_TTI.request. 
+ *
+**/
+uint8_t nr5g_fapi_tx_data_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_tx_data_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PTXRequestStruct p_ia_tx_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+    UNUSED(p_fapi_vendor_msg);
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[TX_Data.request] Invalid " "phy instance"));
+        return FAILURE;
+    }
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[TX_Data.request] Invalid fapi " "message"));
+        return FAILURE;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_tx_data_req++;
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_TX_REQ, 1, (uint32_t) sizeof(TXRequestStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[TX_Data.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_ia_tx_req = (PTXRequestStruct) (p_list_elem + 1);
+    nr5g_fapi_tx_data_req_to_phy_translation(p_phy_instance, p_fapi_req,
+        p_ia_tx_req);
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_tx_req++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[TX_Data.request][%d][%d,%d]",
+            p_phy_instance->phy_id, p_ia_tx_req->sSFN_Slot.nSFN,
+            p_ia_tx_req->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_fapi_req Pointer to FAPI TX_Data.request structure.
+ *  @param[in]  p_ia_tx_req Pointer to IAPI TX_Data.request structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts FAPI TX_Data.request to IAPI TX.request
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_tx_data_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_tx_data_req_t * p_fapi_req,
+    PTXRequestStruct p_phy_req)
+{
+    uint16_t idx;
+    uint32_t tlv;
+    fapi_tx_pdu_desc_t *p_fapi_pdu = NULL;
+    PDLPDUDataStruct p_phy_pdu = NULL;
+
+    p_phy_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_TX_REQ;
+    p_phy_req->sMsgHdr.nMessageLen = (uint16_t) sizeof(TXRequestStruct);
+    p_phy_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+    p_phy_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
+    p_phy_req->sSFN_Slot.nSlot = p_fapi_req->slot;
+    p_phy_req->nPDU = p_fapi_req->num_pdus;
+    p_phy_pdu = (PDLPDUDataStruct) (p_phy_req + 1);
+    for (idx = 0; idx < p_fapi_req->num_pdus; idx++) {
+        p_fapi_pdu = &p_fapi_req->pdu_desc[idx];
+        for (tlv = 0; tlv < p_fapi_pdu->num_tlvs; tlv++) {
+            p_phy_pdu->nPduIdx = p_fapi_pdu->pdu_index;
+            p_phy_pdu->nPduLen1 = 0;
+            p_phy_pdu->nPduLen2 = 0;
+            p_phy_pdu->pPayload1 = NULL;
+            p_phy_pdu->pPayload2 = NULL;
+            if (tlv == 0) {
+                p_phy_pdu->nPduLen1 = p_fapi_pdu->tlvs[tlv].tl.length;
+                p_phy_pdu->pPayload1 = p_fapi_pdu->tlvs[tlv].value;
+            } else {
+                p_phy_pdu->nPduLen2 = p_fapi_pdu->tlvs[tlv].tl.length;
+                p_phy_pdu->pPayload2 = p_fapi_pdu->tlvs[tlv].value;
+            }
+        }
+        p_phy_pdu++;
+    }
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_ul_dci_req.c b/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_ul_dci_req.c
new file mode 100644 (file)
index 0000000..edd30fe
--- /dev/null
@@ -0,0 +1,199 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI UL_DCI.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p7_proc.h"
+#include "nr5g_fapi_fapi2phy_p7_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI UL_DCI.request message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message includes DCI content used for the scheduling of PUSCH.
+ *
+**/
+uint8_t nr5g_fapi_ul_dci_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_dci_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PULDCIRequestStruct p_ia_ul_dci_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+    UNUSED(p_fapi_vendor_msg);
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_DCI.request] Invalid " "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_ul_dci_req++;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_DCI.request] Invalid fapi " "message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_UL_DCI_REQ, 1, (uint32_t) sizeof(ULDCIRequestStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[UL_DCI.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_ia_ul_dci_req = (PULDCIRequestStruct) (p_list_elem + 1);
+    p_ia_ul_dci_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_UL_DCI_REQ;
+    p_ia_ul_dci_req->sMsgHdr.nMessageLen =
+        (uint16_t) sizeof(ULDCIRequestStruct);
+    p_ia_ul_dci_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
+    p_ia_ul_dci_req->sSFN_Slot.nSlot = p_fapi_req->slot;
+    p_ia_ul_dci_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+
+    if (FAILURE == nr5g_fapi_ul_dci_req_to_phy_translation(p_phy_instance,
+            p_fapi_req, p_ia_ul_dci_req)) {
+        nr5g_fapi_fapi2phy_destroy_api_list_elem(p_list_elem);
+        NR5G_FAPI_LOG(DEBUG_LOG, ("[UL_DCI.request][%d][%d,%d] Not Sent",
+                p_phy_instance->phy_id, p_ia_ul_dci_req->sSFN_Slot.nSFN,
+                p_ia_ul_dci_req->sSFN_Slot.nSlot));
+        return FAILURE;
+    }
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_ul_dci_req++;
+    NR5G_FAPI_LOG(DEBUG_LOG, ("[UL_DCI.request][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_ia_ul_dci_req->sSFN_Slot.nSFN, p_ia_ul_dci_req->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]   p_fapi_req Pointer to FAPI UL_DCI.request structure.
+ *  @param[out]  p_ia_ul_dci_req Pointer to IAPI UL_DCI.request structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts FAPI UL_DCI.request to IAPI UL_DCI.request
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_ul_dci_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_dci_req_t * p_fapi_req,
+    PULDCIRequestStruct p_ia_ul_dci_req)
+{
+    int idx;
+    fapi_dci_pdu_t *p_fapi_dci_pdu;
+    DCIPDUStruct *p_ia_dci_pdu;
+    nr5g_fapi_stats_t *p_stats;
+    uint8_t *p_ia_curr, *p_freq_dom_res = NULL;
+
+    p_stats = &p_phy_instance->stats;
+
+    p_ia_ul_dci_req->nDCI = p_fapi_req->numPdus;
+
+    p_ia_curr = (uint8_t *) p_ia_ul_dci_req->sULDCIPDU;
+
+    for (idx = 0; idx < p_ia_ul_dci_req->nDCI; idx++) {
+        p_stats->fapi_stats.fapi_ul_dci_pdus++;
+        p_fapi_dci_pdu = &p_fapi_req->pdus[idx];
+        p_ia_dci_pdu = (DCIPDUStruct *) p_ia_curr;
+        p_ia_dci_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_DCI;
+        p_ia_dci_pdu->sPDUHdr.nPDUSize = RUP32B(sizeof(DCIPDUStruct));
+        p_ia_dci_pdu->nRNTI = p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].rnti;
+        p_ia_dci_pdu->nBWPSize = p_fapi_dci_pdu->pdcchPduConfig.bwpSize;
+        p_ia_dci_pdu->nBWPStart = p_fapi_dci_pdu->pdcchPduConfig.bwpStart;
+        p_ia_dci_pdu->nSubcSpacing =
+            p_fapi_dci_pdu->pdcchPduConfig.subCarrierSpacing;
+        p_ia_dci_pdu->nCpType = p_fapi_dci_pdu->pdcchPduConfig.cyclicPrefix;
+        p_freq_dom_res = &p_fapi_dci_pdu->pdcchPduConfig.freqDomainResource[0];
+        p_ia_dci_pdu->nFreqDomain[0] =
+            ((uint32_t)  (p_freq_dom_res[0])) |
+            (((uint32_t) (p_freq_dom_res[1])) << 8) |
+            (((uint32_t) (p_freq_dom_res[2])) << 16) |
+            (((uint32_t) (p_freq_dom_res[3])) << 24);
+        p_ia_dci_pdu->nFreqDomain[1] =
+            ((uint32_t)  (p_freq_dom_res[4])) |
+            (((uint32_t) (p_freq_dom_res[5])) << 8);
+        p_ia_dci_pdu->nStartSymbolIndex =
+            p_fapi_dci_pdu->pdcchPduConfig.startSymbolIndex;
+        p_ia_dci_pdu->nNrOfSymbols =
+            p_fapi_dci_pdu->pdcchPduConfig.durationSymbols;
+        p_ia_dci_pdu->nCCEToREGType =
+            p_fapi_dci_pdu->pdcchPduConfig.cceRegMappingType;
+        p_ia_dci_pdu->nREGBundleSize =
+            p_fapi_dci_pdu->pdcchPduConfig.regBundleSize;
+        p_ia_dci_pdu->nShift = p_fapi_dci_pdu->pdcchPduConfig.shiftIndex;
+        p_ia_dci_pdu->nScid =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].scramblingId;
+        p_ia_dci_pdu->nCCEStartIndex =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].cceIndex;
+        p_ia_dci_pdu->nAggrLvl =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].aggregationLevel;
+        p_ia_dci_pdu->nInterleaveSize =
+            p_fapi_dci_pdu->pdcchPduConfig.interleaverSize;
+        p_ia_dci_pdu->nCoreSetType = p_fapi_dci_pdu->pdcchPduConfig.coreSetType;
+        p_ia_dci_pdu->nRNTIScramb =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].scramblingRnti;
+        p_ia_dci_pdu->nTotalBits =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].payloadSizeBits;
+        p_ia_dci_pdu->nEpreRatioOfPDCCHToSSB =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].powerControlOfssetSS;
+        p_ia_dci_pdu->nEpreRatioOfDmrsToSSB =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].beta_pdcch_1_0;
+        p_ia_dci_pdu->nTotalBits =
+            p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].payloadSizeBits;
+        if (FAILURE == NR5G_FAPI_MEMCPY(p_ia_dci_pdu->nDciBits,
+                sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN,
+                p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].payload,
+                sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN)) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("UL_DCI Pdu: RNTI: %d -- DCI Bits copy" " failed.",
+                    p_fapi_dci_pdu->pdcchPduConfig.dlDci[0].rnti));
+            return FAILURE;
+        }
+        p_ia_dci_pdu->nID = p_ia_dci_pdu->nScid;
+        p_ia_dci_pdu->nNrofTxRU = 0x0;
+        p_ia_dci_pdu->nBeamId = 0x0;
+        p_ia_curr += RUP32B(sizeof(DCIPDUStruct));
+    }
+
+    p_stats->iapi_stats.iapi_ul_dci_pdus++;
+    return SUCCESS;
+}
+
+
+
+
diff --git a/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_ul_tti_req.c b/fapi_5g/source/api/fapi2phy/p7/nr5g_fapi_proc_ul_tti_req.c
new file mode 100644 (file)
index 0000000..737cca0
--- /dev/null
@@ -0,0 +1,744 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file
+ * This file consist of implementation of FAPI UL_TTI.request message.
+ *
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p7_proc.h"
+#include "nr5g_fapi_fapi2phy_p7_pvt_proc.h"
+#include "nr5g_fapi_memory.h"
+#include <math.h>
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_fapi_req Pointer to FAPI UL_TTI.request message structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This message indicates the control information for an uplink slot.
+ *
+**/
+uint8_t nr5g_fapi_ul_tti_request(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_tti_req_t * p_fapi_req,
+    fapi_vendor_msg_t * p_fapi_vendor_msg)
+{
+    PULConfigRequestStruct p_ia_ul_config_req;
+    PMAC2PHY_QUEUE_EL p_list_elem;
+    nr5g_fapi_stats_t *p_stats;
+    UNUSED(p_fapi_vendor_msg);
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][UL_TTI.request] Invalid "
+                "phy instance"));
+        return FAILURE;
+    }
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_ul_tti_req++;
+
+    if (NULL == p_fapi_req) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][UL_TTI.request] Invalid fapi "
+                "message"));
+        return FAILURE;
+    }
+
+    p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
+        MSG_TYPE_PHY_UL_CONFIG_REQ, 1,
+        (uint32_t) sizeof(ULConfigRequestStruct));
+    if (!p_list_elem) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("[NR5G_FAPI][UL_TTI.request] Unable to create "
+                "list element. Out of memory!!!"));
+        return FAILURE;
+    }
+
+    p_ia_ul_config_req = (PULConfigRequestStruct) (p_list_elem + 1);
+    NR5G_FAPI_MEMSET(p_ia_ul_config_req, sizeof(ULConfigRequestStruct), 0,
+        sizeof(ULConfigRequestStruct));
+    p_ia_ul_config_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_UL_CONFIG_REQ;
+    p_ia_ul_config_req->sMsgHdr.nMessageLen =
+        (uint16_t) sizeof(ULConfigRequestStruct);
+
+    if (FAILURE == nr5g_fapi_ul_tti_req_to_phy_translation(p_phy_instance,
+            p_fapi_req, p_ia_ul_config_req)) {
+        nr5g_fapi_fapi2phy_destroy_api_list_elem(p_list_elem);
+        NR5G_FAPI_LOG(DEBUG_LOG, ("[UL_TTI.request][%d][%d,%d] Not Sent",
+                p_phy_instance->phy_id, p_ia_ul_config_req->sSFN_Slot.nSFN,
+                p_ia_ul_config_req->sSFN_Slot.nSlot));
+        return FAILURE;
+    }
+
+    nr5g_fapi_fapi2phy_add_to_api_list(p_list_elem);
+
+    p_stats->iapi_stats.iapi_ul_config_req++;
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][UL_TTI.request][%d][%d,%d]",
+            p_phy_instance->phy_id,
+            p_ia_ul_config_req->sSFN_Slot.nSFN,
+            p_ia_ul_config_req->sSFN_Slot.nSlot));
+
+    return SUCCESS;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  bwp_size  Variable holding the Bandwidth part size.
+ *  
+ *  @return     Returns ::RBG Size.
+ *
+ *  @description
+ *  This functions calculates and return RBG Size from Bandwidth part size provided. 
+ *
+**/
+uint8_t nr5g_fapi_calc_n_rbg_size(
+    uint16_t bwp_size)
+{
+    uint8_t n_rbg_size = 0;
+    if (bwp_size >= 1 && bwp_size <= 36) {
+        n_rbg_size = 2;
+    } else if (bwp_size >= 37 && bwp_size <= 72) {
+        n_rbg_size = 4;
+    } else if (bwp_size >= 73 && bwp_size <= 144) {
+        n_rbg_size = 8;
+    } else if (bwp_size >= 145 && bwp_size <= 275) {
+        n_rbg_size = 16;
+    } else {
+        n_rbg_size = 0;
+    }
+    return n_rbg_size;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  n_rbg_size  Variable holding the RBG Size
+ *  @param[in]  p_push_pdu Pointer to FAPI PUSCH Pdu
+ *  
+ *  @return     Returns ::RBG Bitmap entry
+ *
+ *  @description
+ *  This functions derives the RBG Bitmap entry for PUSCH Type-0 allocation. 
+ *
+**/
+uint32_t nr5g_fapi_calc_n_rbg_index_entry(
+    uint8_t n_rbg_size,
+    fapi_ul_pusch_pdu_t * p_pusch_pdu)
+{
+    uint8_t i, temp, num_bits = 0;
+    uint32_t n_rbg_bitmap = 0;
+    uint8_t rb_bitmap_entries, rb_bitmap;
+
+    rb_bitmap_entries = ceil(n_rbg_size / 8);
+    for (i = 0; i < rb_bitmap_entries; i++) {
+        num_bits = 0;
+        temp = 0;
+        rb_bitmap = p_pusch_pdu->rbBitmap[i];
+        while (num_bits < 8) {
+            if (rb_bitmap & (1 << num_bits)) {
+                temp |= (1 << (7 - num_bits));
+            }
+            num_bits++;
+        }
+        n_rbg_bitmap |= ((n_rbg_bitmap | temp) << (32 - (8 * (i + 1))));
+    }
+    return n_rbg_bitmap;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  fapi_alpha_scaling  Variable holding the FAPI Alpha Scaling Value.
+ *  
+ *  @return     Returns ::PHY equivalent Alpha Scaling Value.
+ *
+ *  @description
+ *  This functions derives the PHY equivalent Alpha Scaling value from FAPI Alpha Scaling Value. 
+ *
+**/
+uint8_t nr5g_fapi_calc_alpha_scaling(
+    uint8_t fapi_alpha_scaling)
+{
+    uint8_t alpha_scaling;
+
+    switch (fapi_alpha_scaling) {
+        case 0:
+            alpha_scaling = 127;
+            break;
+
+        case 1:
+            alpha_scaling = 166;
+            break;
+
+        case 2:
+            alpha_scaling = 205;
+            break;
+
+        case 3:
+            alpha_scaling = 255;
+            break;
+
+        default:
+            alpha_scaling = 0;
+            break;
+    }
+    return alpha_scaling;
+}
+
+/** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_pusch_data Pointer to FAPI Optional PUSCH Data structure.
+ *  @param[in]  p_ul_data_chan Pointer to IAPI ULSCH PDU structure.
+ *  
+ *  @return     None.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request's Optional PUSCH Data to IAPI UL_Config.request's
+ *  ULSCH PDU structure.
+ *
+**/
+void nr5g_fapi_pusch_data_to_phy_ulsch_translation(
+    nr5g_fapi_pusch_info_t * p_pusch_info,
+    fapi_pusch_data_t * p_pusch_data,
+    ULSCHPDUStruct * p_ul_data_chan)
+{
+    p_ul_data_chan->nRV = p_pusch_data->rvIndex;
+    p_pusch_info->harq_process_id = p_ul_data_chan->nHARQID =
+        p_pusch_data->harqProcessId;
+    p_ul_data_chan->nNDI = p_pusch_data->newDataIndicator;
+    p_ul_data_chan->nTBSize = p_pusch_data->tbSize;
+    //numCb and cbPresentAndPoistion[] is ignored as per design 
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_pusch_uci Pointer to FAPI Optional PUSCH UCI structure.
+ *  @param[in]  p_ul_data_chan Pointer to IAPI ULSCH PDU structure.
+ *  
+ *  @return     None.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request's Optional PUSCH UCI to IAPI UL_Config.request's
+ *  ULSCH PDU structure.
+ *
+**/
+void nr5g_fapi_pusch_uci_to_phy_ulsch_translation(
+    fapi_pusch_uci_t * p_pusch_uci,
+    ULSCHPDUStruct * p_ul_data_chan)
+{
+    p_ul_data_chan->nAck = p_pusch_uci->harqAckBitLength;
+    //csiPart1BitLength and csiPart2BitLength are ignored as per design
+    p_ul_data_chan->nAlphaScaling =
+        nr5g_fapi_calc_alpha_scaling(p_pusch_uci->alphaScaling);
+    //p_ul_data_chan->nAlphaScaling = 0;
+    p_ul_data_chan->nBetaOffsetACKIndex = p_pusch_uci->betaOffsetHarqAck;
+    //betaOffsetCsi1 and betaOffsetCsi2 are ignored as per design
+}
+
+/** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_pusch_ptrs Pointer to FAPI Optional PUSCH PTRS structure.
+ *  @param[in]  p_ul_data_chan Pointer to IAPI ULSCH PDU structure.
+ *  
+ *  @return     None.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request's Optional PUSCH PTRS to IAPI UL_Config.request's
+ *  ULSCH PDU structure.
+ *
+**/
+void nr5g_fapi_pusch_ptrs_to_phy_ulsch_translation(
+    fapi_pusch_ptrs_t * p_pusch_ptrs,
+    ULSCHPDUStruct * p_ul_data_chan)
+{
+    uint8_t i, num_ptrs_ports = 0, port_index = 0;
+    fapi_ptrs_info_t *p_ptrs_info;
+
+    if (p_pusch_ptrs->ptrsTimeDensity <= 2) {
+        p_ul_data_chan->nPTRSTimeDensity =
+            pow(2, p_pusch_ptrs->ptrsTimeDensity);
+    }
+    if (p_pusch_ptrs->ptrsFreqDensity == 0 ||
+        p_pusch_ptrs->ptrsFreqDensity == 1) {
+        p_ul_data_chan->nPTRSFreqDensity =
+            pow(2, (p_pusch_ptrs->ptrsFreqDensity + 1));
+    }
+    if (p_pusch_ptrs->numPtrsPorts > 0) {
+        num_ptrs_ports = p_ul_data_chan->nNrOfPTRSPorts = 1;
+    }
+    for (i = 0; (i < num_ptrs_ports && port_index < FAPI_MAX_PTRS_PORTS); i++) {
+        p_ptrs_info = &p_pusch_ptrs->ptrsInfo[i];
+        if ((p_ptrs_info->ptrsPortIndex >> i) & 0x01) {
+            p_ul_data_chan->nPTRSPortIndex[port_index++] = i;
+        }
+        //PTRSDmrsPort is ignored as per Design
+        p_ul_data_chan->nPTRSReOffset = p_ptrs_info->ptrsReOffset;
+    }
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_pusch_pdu Pointer to FAPI PUSCH PDU structure.
+ *  @param[out]  p_ul_data_chan Pointer to IAPI ULSCH PDU structure.
+ *  
+ *  @return     None.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request's PUSCH PDU to IAPI UL_Config.request's
+ *  ULSCH PDU structure.
+ *
+**/
+void nr5g_fapi_pusch_to_phy_ulsch_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    nr5g_fapi_pusch_info_t * p_pusch_info,
+    fapi_ul_pusch_pdu_t * p_pusch_pdu,
+    ULSCHPDUStruct * p_ul_data_chan)
+{
+    uint8_t mcs_table, nr_of_layers, n_rbg_size;
+    uint8_t i, port_index = 0;
+    uint16_t dmrs_ports, bwp_size, bwp_start, pdu_bitmap;
+    nr5g_fapi_stats_t *p_stats;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_ul_tti_pusch_pdus++;
+
+    NR5G_FAPI_MEMSET(p_ul_data_chan, sizeof(ULSCHPDUStruct), 0,
+        sizeof(ULSCHPDUStruct));
+
+    p_ul_data_chan->sPDUHdr.nPDUType = UL_PDU_TYPE_ULSCH;
+    p_ul_data_chan->sPDUHdr.nPDUSize = RUP32B(sizeof(ULSCHPDUStruct));
+
+    p_ul_data_chan->nRNTI = p_pusch_pdu->rnti;
+
+    p_pusch_info->handle = p_ul_data_chan->nUEId =
+        (uint16_t) p_pusch_pdu->handle;
+
+    bwp_size = p_ul_data_chan->nBWPSize = p_pusch_pdu->bwpSize;
+    bwp_start = p_ul_data_chan->nBWPStart = p_pusch_pdu->bwpStart;
+
+    p_ul_data_chan->nSubcSpacing = p_pusch_pdu->subCarrierSpacing;
+    p_ul_data_chan->nCpType = p_pusch_pdu->cyclicPrefix;
+    p_ul_data_chan->nMCS = p_pusch_pdu->mcsIndex;
+    p_ul_data_chan->nTransPrecode = 0;
+    mcs_table = p_pusch_pdu->mcsTable;
+    if (mcs_table <= 2) {
+        p_ul_data_chan->nMcsTable = mcs_table;
+    }
+    if ((mcs_table > 2) && (mcs_table <= 4)) {
+        p_ul_data_chan->nTransPrecode = 1;
+
+        if (mcs_table == 3) {
+            p_ul_data_chan->nMcsTable = 0;
+        } else {
+            p_ul_data_chan->nMcsTable = 2;
+        }
+    }
+
+    p_ul_data_chan->nNid = p_pusch_pdu->dataScramblingId;
+    p_ul_data_chan->nDMRSConfigType = p_pusch_pdu->dmrsConfigType;
+    p_ul_data_chan->nMappingType = p_pusch_pdu->mappingType;
+    p_ul_data_chan->nNrOfDMRSSymbols = p_pusch_pdu->nrOfDmrsSymbols;
+    p_ul_data_chan->nDMRSAddPos = p_pusch_pdu->dmrsAddPos;
+    p_ul_data_chan->nNIDnSCID = p_pusch_pdu->ulDmrsScramblingId;
+    p_ul_data_chan->nSCID = p_pusch_pdu->scid;
+    p_ul_data_chan->nNrOfCDMs = p_pusch_pdu->numDmrsCdmGrpsNoData;
+
+    dmrs_ports = p_pusch_pdu->dmrsPorts;
+    nr_of_layers = p_ul_data_chan->nNrOfLayers = p_pusch_pdu->nrOfLayers;
+    for (i = 0; (i < FAPI_MAX_DMRS_PORTS && port_index < nr_of_layers); i++) {
+        if (port_index < FAPI_MAX_UL_LAYERS) {
+            if ((dmrs_ports >> i) && 0x0001) {
+                p_ul_data_chan->nPortIndex[port_index++] = i;
+            }
+        } else {
+            break;
+        }
+    }
+    p_ul_data_chan->nTPPuschID = p_pusch_pdu->nTpPuschId;
+    p_ul_data_chan->nTpPi2BPSK = p_pusch_pdu->tpPi2Bpsk;
+    //Config-1 alone is supported
+    n_rbg_size = p_ul_data_chan->nRBGSize = nr5g_fapi_calc_n_rbg_size(bwp_size);
+    if (n_rbg_size > 0) {
+        p_ul_data_chan->nNrOfRBGs =
+            ceil((bwp_size + (bwp_start % n_rbg_size)) / n_rbg_size);
+    }
+    //First entry would be sufficient as maximum no of RBG's is at max 18.
+    p_ul_data_chan->nRBGIndex[0] =
+        nr5g_fapi_calc_n_rbg_index_entry(n_rbg_size, p_pusch_pdu);
+    p_ul_data_chan->nRBStart = p_pusch_pdu->rbStart;
+    p_ul_data_chan->nRBSize = p_pusch_pdu->rbSize;
+    p_ul_data_chan->nVRBtoPRB = p_pusch_pdu->vrbToPrbMapping;
+    p_ul_data_chan->nResourceAllocType = p_pusch_pdu->resourceAlloc;
+    p_ul_data_chan->nStartSymbolIndex = p_pusch_pdu->startSymbIndex;
+    p_ul_data_chan->nNrOfSymbols = p_pusch_pdu->nrOfSymbols;
+
+    p_ul_data_chan->nPTRSPresent = 0;
+    pdu_bitmap = p_pusch_pdu->pduBitMap;
+    if (pdu_bitmap & 0x01) {
+        nr5g_fapi_pusch_data_to_phy_ulsch_translation(p_pusch_info,
+            &p_pusch_pdu->puschData, p_ul_data_chan);
+    }
+    if (pdu_bitmap & 0x02) {
+        nr5g_fapi_pusch_uci_to_phy_ulsch_translation(&p_pusch_pdu->puschUci,
+            p_ul_data_chan);
+    }
+    if (pdu_bitmap & 0x04) {
+        nr5g_fapi_pusch_ptrs_to_phy_ulsch_translation(&p_pusch_pdu->puschPtrs,
+            p_ul_data_chan);
+    }
+    if ((pdu_bitmap & (1 << 15))) {
+        p_ul_data_chan->nPTRSPresent = 1;
+    }
+    p_ul_data_chan->nULType = 0;
+    p_ul_data_chan->nNrOfAntennaPorts =
+        p_phy_instance->phy_config.n_nr_of_rx_ant;
+    p_ul_data_chan->nRBBundleSize = 0;
+    p_ul_data_chan->nPMI = 0;
+    p_ul_data_chan->nTransmissionScheme = 0;
+    p_ul_data_chan->rsv1 = 0;
+    p_ul_data_chan->nNrofRxRU = p_phy_instance->phy_config.n_nr_of_rx_ant;
+    p_stats->iapi_stats.iapi_ul_tti_pusch_pdus++;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  num_groups Variable holding the groups for which PUCCH resources 
+                are unique
+ *  @param[in]  initial_cyclic_shift Variable holding the parameter initial_cyclic 
+                shift to be verified against the already receieved pucch resources.
+ *  @param[in]  nr_of_layers Variable holding the parameter nr_of_symbols
+                to be verified against the already received pucch resources.
+ *  @param[in]  start_symbol_index  Variable holding the parameter start_symbol_index
+                to be verified against the already received pucch resources.
+ *  @param[in]  time_domain_occ_idx Variable holding the parameter time_domain_occ_idx
+                to be verified against the already received pucch resources.
+ *  @param[in]  p_pucch_resources Pointer pointing to the received pucch resources.
+*  @return     group_id, if pucch_resources match with parameters passed.
+ *             0xFF, if pucch_resources not match with parameters passed.
+ *  @description
+ *  This function returns the group_id if parameters  passed already available in
+ *  pucch_resources received earlier.
+ *
+**/
+uint8_t nr5g_get_pucch_resources_group_id(
+    uint8_t num_groups,
+    uint16_t initial_cyclic_shift,
+    uint8_t nr_of_symbols,
+    uint8_t start_symbol_index,
+    uint8_t time_domain_occ_idx,
+    nr5g_fapi_pucch_resources_t * p_pucch_resources)
+{
+    uint8_t i, group_id = 0xFF;
+    for (i = 0; i < num_groups; i++) {
+        if ((initial_cyclic_shift == p_pucch_resources[i].initial_cyclic_shift)
+            && (nr_of_symbols == p_pucch_resources[i].nr_of_symbols)
+            && (start_symbol_index == p_pucch_resources[i].start_symbol_index)
+            && (time_domain_occ_idx ==
+                p_pucch_resources[i].time_domain_occ_idx)) {
+            group_id = p_pucch_resources[i].group_id;
+            break;
+        }
+    }
+    return group_id;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_phy_instance Pointer to PHY instance.
+ *  @param[in]  p_pucch_pdu Pointer to FAPI PUSCH PDU structure.
+ *  @param[in]  p_ul_ctrl_chan Pointer to IAPI ULCCH_UCIPDU structure.
+ *  
+ *  @return     None.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request's PUCCH PDU to IAPI UL_Config.request's
+ *  ULCCH_UCI PDU structure.
+ *
+**/
+void nr5g_fapi_pucch_to_phy_ulcch_uci_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    nr5g_fapi_pucch_info_t * p_pucch_info,
+    fapi_ul_pucch_pdu_t * p_pucch_pdu,
+    uint8_t * num_group_ids,
+    nr5g_fapi_pucch_resources_t * p_pucch_resources,
+    ULCCHUCIPDUStruct * p_ul_ctrl_chan)
+{
+    uint8_t group_id;
+    nr5g_fapi_stats_t *p_stats;
+    uint8_t initial_cyclic_shift, nr_of_symbols;
+    uint8_t start_symbol_index, time_domain_occ_idx;
+    uint8_t num_groups = *num_group_ids;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_ul_tti_pucch_pdus++;
+    NR5G_FAPI_MEMSET(p_ul_ctrl_chan, sizeof(ULCCHUCIPDUStruct), 0,
+        sizeof(ULCCHUCIPDUStruct));
+    p_ul_ctrl_chan->sPDUHdr.nPDUType = UL_PDU_TYPE_ULCCH_UCI;
+    p_ul_ctrl_chan->sPDUHdr.nPDUSize = RUP32B(sizeof(ULCCHUCIPDUStruct));
+
+    p_ul_ctrl_chan->nRNTI = p_pucch_pdu->rnti;
+    p_pucch_info->handle = p_ul_ctrl_chan->nUEId =
+        (uint16_t) p_pucch_pdu->handle;
+
+    p_ul_ctrl_chan->nSubcSpacing = p_pucch_pdu->subCarrierSpacing;
+    p_ul_ctrl_chan->nCpType = p_pucch_pdu->cyclicPrefix;
+    p_pucch_info->pucch_format = p_ul_ctrl_chan->nFormat =
+        p_pucch_pdu->formatType;
+    if (p_pucch_pdu->pi2Bpsk) {
+        p_ul_ctrl_chan->modType = 1;
+    } else {                    //QPSK
+        p_ul_ctrl_chan->modType = 2;
+    }
+    p_ul_ctrl_chan->nStartPRB = p_pucch_pdu->prbStart;
+    p_ul_ctrl_chan->nPRBs = p_pucch_pdu->prbSize;
+    start_symbol_index = p_ul_ctrl_chan->nStartSymbolx =
+        p_pucch_pdu->startSymbolIndex;
+    nr_of_symbols = p_ul_ctrl_chan->nSymbols = p_pucch_pdu->nrOfSymbols;
+    p_ul_ctrl_chan->nFreqHopFlag = p_pucch_pdu->freqHopFlag;
+
+    p_ul_ctrl_chan->n2ndHopPRB = p_pucch_pdu->secondHopPrb;
+    initial_cyclic_shift = p_ul_ctrl_chan->nM0 =
+        p_pucch_pdu->initialCyclicShift;
+    p_ul_ctrl_chan->nID = p_pucch_pdu->dataScramblingId;
+    time_domain_occ_idx = p_ul_ctrl_chan->nFmt1OrthCCodeIdx =
+        p_pucch_pdu->timeDomainOccIdx;
+    p_ul_ctrl_chan->nFmt4OrthCCodeIdx = p_pucch_pdu->preDftOccIdx;
+    p_ul_ctrl_chan->nFmt4OrthCCodeLength = p_pucch_pdu->preDftOccLen;
+    p_ul_ctrl_chan->nAddDmrsFlag = p_pucch_pdu->addDmrsFlag;
+    p_ul_ctrl_chan->nScramID = p_pucch_pdu->dmrsScramblingId;
+    p_ul_ctrl_chan->nSRPriodAriv = p_pucch_pdu->srFlag;
+    p_ul_ctrl_chan->nBitLenUci = p_pucch_pdu->bitLenHarq;
+    p_ul_ctrl_chan->nNrofRxRU = p_phy_instance->phy_config.n_nr_of_rx_ant;
+
+    group_id =
+        nr5g_get_pucch_resources_group_id(num_groups, initial_cyclic_shift,
+        nr_of_symbols, start_symbol_index, time_domain_occ_idx,
+        p_pucch_resources);
+    if (group_id == 0xFF) {
+        p_pucch_resources[num_groups].group_id = num_groups;
+        p_pucch_resources[num_groups].initial_cyclic_shift =
+            initial_cyclic_shift;
+        p_pucch_resources[num_groups].nr_of_symbols = nr_of_symbols;
+        p_pucch_resources[num_groups].start_symbol_index = start_symbol_index;
+        p_pucch_resources[num_groups].time_domain_occ_idx = time_domain_occ_idx;
+        p_ul_ctrl_chan->nGroupId = num_groups;
+        num_groups++;
+    } else {
+        p_ul_ctrl_chan->nGroupId = group_id;
+    }
+    *num_group_ids = num_groups;
+    p_stats->iapi_stats.iapi_ul_tti_pucch_pdus++;
+}
+
+/** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_srs_pdu Pointer to FAPI SRS PDU structure.
+ *  @param[in]  p_ul_srs_chan Pointer to IAPI SRS PDU structure.
+ *  
+ *  @return     None.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request's SRS PDU to IAPI UL_Config.request's
+ *  SRS PDU structure.
+ *
+**/
+void nr5g_fapi_srs_to_phy_srs_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_srs_pdu_t * p_srs_pdu,
+    nr5g_fapi_srs_info_t * p_srs_info,
+    SRSPDUStruct * p_ul_srs_chan)
+{
+    nr5g_fapi_stats_t *p_stats;
+
+    p_stats = &p_phy_instance->stats;
+    p_stats->fapi_stats.fapi_ul_tti_srs_pdus++;
+    NR5G_FAPI_MEMSET(p_ul_srs_chan, sizeof(SRSPDUStruct), 0,
+        sizeof(SRSPDUStruct));
+    p_ul_srs_chan->sPDUHdr.nPDUType = UL_PDU_TYPE_SRS;
+    p_ul_srs_chan->sPDUHdr.nPDUSize = RUP32B(sizeof(SRSPDUStruct));
+
+    p_ul_srs_chan->nRNTI = p_srs_pdu->rnti;
+    p_srs_info->handle = p_ul_srs_chan->nUEId = (uint16_t) p_srs_pdu->handle;
+
+    p_ul_srs_chan->nSubcSpacing = p_srs_pdu->subCarrierSpacing;
+    p_ul_srs_chan->nCpType = p_srs_pdu->cyclicPrefix;
+    p_ul_srs_chan->nNrOfSrsPorts = pow(2, p_srs_pdu->numAntPorts);
+    p_ul_srs_chan->nNrOfSymbols = pow(2, p_srs_pdu->numSymbols);
+    p_ul_srs_chan->nRepetition = pow(2, p_srs_pdu->numRepetitions);
+    if (p_ul_srs_chan->nCpType) {   //Extended Cyclic Prefix
+        p_ul_srs_chan->nStartPos = 11 - p_srs_pdu->timeStartPosition;
+    } else {
+        p_ul_srs_chan->nStartPos = 13 - p_srs_pdu->timeStartPosition;
+    }
+    p_ul_srs_chan->nCsrs = p_srs_pdu->configIndex;
+    p_ul_srs_chan->nBsrs = p_srs_pdu->bandwidthIndex;
+    p_ul_srs_chan->nSrsId = p_srs_pdu->sequenceId;
+
+    if (p_srs_pdu->combSize) {
+        p_ul_srs_chan->nComb = 4;
+    } else {
+        p_ul_srs_chan->nComb = 2;
+    }
+    p_ul_srs_chan->nCombOffset = p_srs_pdu->combOffset;
+    p_ul_srs_chan->nCyclicShift = p_srs_pdu->cyclicShift;
+    p_ul_srs_chan->nFreqPos = p_srs_pdu->frequencyPosition;
+    p_ul_srs_chan->nFreqShift = p_srs_pdu->frequencyShift;
+    p_ul_srs_chan->nBHop = p_srs_pdu->frequencyHopping;
+    p_ul_srs_chan->nHopping = p_srs_pdu->groupOrSequenceHopping;
+    p_ul_srs_chan->nResourceType = p_srs_pdu->resourceType;
+    p_ul_srs_chan->nTsrs = p_srs_pdu->tSrs;
+    p_ul_srs_chan->nToffset = p_srs_pdu->tOffset;
+    p_ul_srs_chan->nToffset = p_srs_pdu->tOffset;
+    p_ul_srs_chan->nNrofRxRU = p_phy_instance->phy_config.n_nr_of_rx_ant;
+
+    p_stats->iapi_stats.iapi_ul_tti_srs_pdus++;
+}
+
+ /** @ingroup group_source_api_p7_fapi2phy_proc
+ *
+ *  @param[in]  p_fapi_req Pointer to FAPI UL_TTI.request structure.
+ *  @param[in]  p_ia_ul_config_req Pointer to IAPI UL_TTI.request structure.
+ *  
+ *  @return     Returns ::SUCCESS and ::FAILURE.
+ *
+ *  @description
+ *  This function converts FAPI UL_TTI.request to IAPI UL_Config.request
+ *  structure.
+ *
+**/
+uint8_t nr5g_fapi_ul_tti_req_to_phy_translation(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    fapi_ul_tti_req_t * p_fapi_req,
+    PULConfigRequestStruct p_ia_ul_config_req)
+{
+    uint8_t i, j, num_group_id = 0;
+    uint8_t num_fapi_pdus, num_groups, num_ue = 0;
+    uint16_t frame_no;
+    uint8_t slot_no;
+
+    fapi_ul_tti_req_pdu_t *p_fapi_ul_tti_req_pdu;
+    fapi_ue_info_t *p_fapi_ue_grp_info;
+    ULSCHPDUStruct *p_ul_data_chan;
+    ULCCHUCIPDUStruct *p_ul_ctrl_chan;
+    SRSPDUStruct *p_ul_srs_chan;
+    PUSCHGroupInfoStruct *p_pusch_grp_info;
+    PDUStruct *p_pdu_head;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+    nr5g_fapi_stats_t *p_stats;
+    nr5g_fapi_pucch_resources_t pucch_resources[FAPI_MAX_NUM_PUCCH_PDU];
+
+    p_stats = &p_phy_instance->stats;
+
+    frame_no = p_ia_ul_config_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
+    slot_no = p_ia_ul_config_req->sSFN_Slot.nSlot = p_fapi_req->slot;
+    p_ia_ul_config_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
+
+    p_ul_slot_info =
+        &p_phy_instance->ul_slot_info[(slot_no % MAX_UL_SLOT_INFO_COUNT)];
+    nr5g_fapi_set_ul_slot_info(frame_no, slot_no, p_ul_slot_info);
+
+    num_fapi_pdus = p_ia_ul_config_req->nPDU = p_fapi_req->nPdus;
+    num_groups = p_ia_ul_config_req->nGroup = p_fapi_req->nGroup;
+    p_ia_ul_config_req->nUlsch = p_fapi_req->nUlsch;
+    p_ia_ul_config_req->nUlcch = p_fapi_req->nUlcch;
+    p_ia_ul_config_req->nRachPresent = p_fapi_req->rachPresent;
+    if (p_fapi_req->rachPresent) {
+        p_ul_slot_info->rach_presence = 1;
+        p_ul_slot_info->rach_info.phy_cell_id =
+            p_phy_instance->phy_config.phy_cell_id;
+    }
+    p_ia_ul_config_req->nUlsrs = 0;
+    for (i = 0; i < num_groups; i++) {
+        p_pusch_grp_info = &p_ia_ul_config_req->sPUSCHGroupInfoStruct[i];
+        p_fapi_ue_grp_info = &p_fapi_req->ueGrpInfo[i];
+        num_ue = p_pusch_grp_info->nUE = p_fapi_ue_grp_info->nUe;
+        for (j = 0; j < num_ue; j++) {
+            p_pusch_grp_info->nPduIdx[j] = p_fapi_ue_grp_info->pduIdx[j];
+        }
+    }
+    p_pdu_head =
+        (PDUStruct *) ((uint8_t *) p_ia_ul_config_req +
+        sizeof(ULConfigRequestStruct));
+
+    for (i = 0; i < num_fapi_pdus; i++) {
+        p_stats->fapi_stats.fapi_ul_tti_pdus++;
+        p_fapi_ul_tti_req_pdu = &p_fapi_req->pdus[i];
+
+        switch (p_fapi_ul_tti_req_pdu->pduType) {
+            case FAPI_PRACH_PDU_TYPE:
+                {
+                    p_ia_ul_config_req->nPDU--;
+                    p_stats->fapi_stats.fapi_ul_tti_prach_pdus++;
+                }
+                break;
+
+            case FAPI_PUSCH_PDU_TYPE:
+                {
+                    p_ul_data_chan = (ULSCHPDUStruct *) p_pdu_head;
+                    nr5g_fapi_pusch_to_phy_ulsch_translation(p_phy_instance,
+                        &p_ul_slot_info->pusch_info[p_ul_slot_info->num_ulsch],
+                        &p_fapi_ul_tti_req_pdu->pdu.pusch_pdu, p_ul_data_chan);
+                    p_ul_slot_info->num_ulsch++;
+                }
+                break;
+
+            case FAPI_PUCCH_PDU_TYPE:
+                {
+                    p_ul_ctrl_chan = (ULCCHUCIPDUStruct *) p_pdu_head;
+                    nr5g_fapi_pucch_to_phy_ulcch_uci_translation(p_phy_instance,
+                        &p_ul_slot_info->pucch_info[p_ul_slot_info->num_ulcch],
+                        &p_fapi_ul_tti_req_pdu->pdu.pucch_pdu, &num_group_id,
+                        pucch_resources, p_ul_ctrl_chan);
+                    p_ul_slot_info->num_ulcch++;
+                }
+                break;
+
+            case FAPI_SRS_PDU_TYPE:
+                {
+                    p_ia_ul_config_req->nUlsrs++;
+                    p_ul_srs_chan = (SRSPDUStruct *) p_pdu_head;
+                    nr5g_fapi_srs_to_phy_srs_translation(p_phy_instance,
+                        &p_fapi_ul_tti_req_pdu->pdu.srs_pdu,
+                        &p_ul_slot_info->srs_info[p_ul_slot_info->num_srs],
+                        p_ul_srs_chan);
+                    p_ul_slot_info->num_srs++;
+                }
+                break;
+
+            default:
+                {
+                    NR5G_FAPI_LOG(ERROR_LOG,
+                        ("[NR5G_FAPI] [UL_TTI.request] Unknown PDU Type :%d",
+                            p_fapi_ul_tti_req_pdu->pduType));
+                    return FAILURE;
+                }
+                break;
+        }
+        p_pdu_head =
+            (PDUStruct *) ((uint8_t *) p_pdu_head + p_pdu_head->nPDUSize);
+        p_stats->iapi_stats.iapi_ul_tti_pdus++;
+    }
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/framework/nr5g_fapi_framework.c b/fapi_5g/source/framework/nr5g_fapi_framework.c
new file mode 100644 (file)
index 0000000..2652797
--- /dev/null
@@ -0,0 +1,197 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#include "nr5g_fapi_framework.h"
+#include "nr5g_fapi_wls.h"
+#include "nr5g_fapi_fapi2mac_wls.h"
+#include "nr5g_fapi_fapi2phy_wls.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "gnb_l1_l2_api.h"
+#include "rte_memzone.h"
+#include "nr5g_fapi_memory.h"
+
+static nr5g_fapi_phy_ctx_t nr5g_fapi_phy_ctx;
+
+inline p_nr5g_fapi_phy_ctx_t nr5g_fapi_get_nr5g_fapi_phy_ctx(
+    )
+{
+    return &nr5g_fapi_phy_ctx;
+}
+
+uint8_t nr5g_fapi_dpdk_init(
+    p_nr5g_fapi_cfg_t p_cfg)
+{
+    printf("init dev name: %s\n", p_cfg->wls.device_name);
+    char *const file_prefix = basename(p_cfg->wls.device_name);
+    printf("init basename: %s\n", file_prefix);
+    char whitelist[32];
+    uint8_t i;
+
+    char *argv[] = { p_cfg->prgname, "--proc-type=secondary",
+        "--file-prefix", file_prefix, whitelist
+    };
+#if 0
+    char coremask[32];
+    char *argv[] = { p_cfg->prgname, coremask, "--proc-type=secondary",
+        "--file-prefix", file_prefix, whitelist
+    };
+    snprintf(coremask, 32, "-l %d,%d", p_cfg->mac2phy_worker.core_id,
+        p_cfg->phy2mac_worker.core_id);
+#endif
+    int argc = RTE_DIM(argv);
+
+    /* initialize EAL first */
+    snprintf(whitelist, 32, "-w %s", "0000:00:06.0");
+    printf("Calling rte_eal_init: ");
+    for (i = 0; i < RTE_DIM(argv); i++) {
+        printf("%s ", argv[i]);
+    }
+    printf("\n");
+
+    if (rte_eal_init(argc, argv) < 0)
+        rte_panic("Cannot init EAL\n");
+
+    return SUCCESS;
+}
+
+uint8_t nr5g_fapi_dpdk_wait(
+    p_nr5g_fapi_cfg_t p_cfg)
+{
+#if 0
+    uint32_t worker_core;
+    /* wait per-lcore */
+    RTE_LCORE_FOREACH_SLAVE(worker_core) {
+        if (rte_eal_wait_lcore(worker_core) < 0) {
+            return FAILURE;
+        }
+    }
+#else
+    pthread_join(p_cfg->mac2phy_thread_info.thread_id, NULL);
+    pthread_join(p_cfg->phy2mac_thread_info.thread_id, NULL);
+#endif
+    return SUCCESS;
+}
+
+void nr5g_fapi_set_ul_slot_info(
+    uint16_t frame_no,
+    uint8_t slot_no,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info)
+{
+    NR5G_FAPI_MEMSET(p_ul_slot_info, sizeof(nr5g_fapi_ul_slot_info_t), 0,
+        sizeof(nr5g_fapi_ul_slot_info_t));
+    p_ul_slot_info->cookie = frame_no;
+    p_ul_slot_info->slot_no = slot_no;
+}
+
+nr5g_fapi_ul_slot_info_t *nr5g_fapi_get_ul_slot_info(
+    uint16_t frame_no,
+    uint8_t slot_no,
+    p_nr5g_fapi_phy_instance_t p_phy_instance)
+{
+    uint8_t i;
+    nr5g_fapi_ul_slot_info_t *p_ul_slot_info;
+
+    for (i = 0; i < MAX_UL_SLOT_INFO_COUNT; i++) {
+        p_ul_slot_info = &p_phy_instance->ul_slot_info[i];
+        if ((slot_no == p_ul_slot_info->slot_no) &&
+            (frame_no == p_ul_slot_info->cookie)) {
+            return p_ul_slot_info;
+        }
+    }
+    return NULL;
+}
+
+uint8_t nr5g_fapi_framework_init(
+    p_nr5g_fapi_cfg_t p_cfg)
+{
+    uint8_t retval = FAILURE;
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx = nr5g_fapi_get_nr5g_fapi_phy_ctx();
+    p_nr5g_fapi_wls_context_t pwls;
+    pthread_attr_t *p_mac2phy_attr, *p_phy2mac_attr;
+    struct sched_param param;
+
+    nr5g_fapi_set_log_level(p_cfg->logger.level);
+    // Set up WLS
+    if (FAILURE == nr5g_fapi_wls_init(p_cfg)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[FAPI_INT] WLS init Failed"));
+        return FAILURE;
+    }
+    // First let's wait for the L1 and L2 to be present
+    while (retval) {
+        retval = nr5g_fapi_fapi2phy_wls_ready();
+    }
+    // Now the L2 is up so let's make sure that the L1 was started first
+    retval = FAILURE;
+    while (retval) {
+        retval = nr5g_fapi_fapi2mac_wls_ready();
+    }
+
+    usleep(1000000);
+    // Now that the L2 is up and has completed the Common Memory initialization
+    // the FT needs to initialize the FAPI2PHY buffers
+    pwls = nr5g_fapi_wls_context();
+    if (pwls) {
+        if (FAILURE == nr5g_fapi2Phy_wls_init(pwls)) {
+            return FAILURE;
+        }
+    } else {
+        return FAILURE;
+    }
+
+    p_phy_ctx->phy2mac_worker_core_id = p_cfg->phy2mac_worker.core_id;
+    p_phy_ctx->mac2phy_worker_core_id = p_cfg->mac2phy_worker.core_id;
+
+    p_phy2mac_attr = &p_cfg->phy2mac_thread_info.thread_attr;
+    pthread_attr_init(p_phy2mac_attr);
+    if (!pthread_attr_getschedparam(p_phy2mac_attr, &param)) {
+        param.sched_priority = p_cfg->phy2mac_worker.thread_priority;
+        pthread_attr_setschedparam(p_phy2mac_attr, &param);
+        pthread_attr_setschedpolicy(p_phy2mac_attr, SCHED_FIFO);
+    }
+
+    if (0 != pthread_create(&p_cfg->phy2mac_thread_info.thread_id,
+            p_phy2mac_attr, nr5g_fapi_phy2mac_thread_func, (void *)
+            p_phy_ctx)) {
+        printf("Error: Unable to create threads\n");
+        if (p_phy2mac_attr)
+            pthread_attr_destroy(p_phy2mac_attr);
+        return FAILURE;
+    }
+    pthread_setname_np(p_cfg->phy2mac_thread_info.thread_id,
+        "nr5g_fapi_phy2mac_thread");
+
+    p_mac2phy_attr = &p_cfg->mac2phy_thread_info.thread_attr;
+    pthread_attr_init(p_mac2phy_attr);
+    if (!pthread_attr_getschedparam(p_mac2phy_attr, &param)) {
+        param.sched_priority = p_cfg->mac2phy_worker.thread_priority;
+        pthread_attr_setschedparam(p_mac2phy_attr, &param);
+        pthread_attr_setschedpolicy(p_mac2phy_attr, SCHED_FIFO);
+    }
+
+    if (0 != pthread_create(&p_cfg->mac2phy_thread_info.thread_id,
+            p_mac2phy_attr, nr5g_fapi_mac2phy_thread_func, (void *)
+            p_phy_ctx)) {
+        printf("Error: Unable to create threads\n");
+        if (p_mac2phy_attr)
+            pthread_attr_destroy(p_mac2phy_attr);
+        return FAILURE;
+    }
+    pthread_setname_np(p_cfg->mac2phy_thread_info.thread_id,
+        "nr5g_fapi_mac2phy_thread");
+
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.c b/fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.c
new file mode 100644 (file)
index 0000000..bded93e
--- /dev/null
@@ -0,0 +1,384 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file has Shared Memory interface functions between FAPI and MAC 
+ *
+ **/
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_wls.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_wls.h"
+#include "nr5g_fapi_log.h"
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param data Pointer to validate
+ *
+ *  @return  TRUE If pointer is within valid shared WLS memory region
+ *           FALSE If pointer is out of valid shared WLS memory region
+ *
+ *  @description
+ *  This function validates pointer's in WLS shared memory region
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
+    void *data)
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    if ((unsigned long)data >= (unsigned long)p_wls_ctx->shmem &&
+        (unsigned long)data < ((unsigned long)p_wls_ctx->shmem +
+            p_wls_ctx->nPartitionMemSize)) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param void
+ *
+ *  @return  A pointer to WLS_HANDLE stucture
+ *
+ *  @description
+ *  This function returns the WLS instance
+ *
+**/
+//------------------------------------------------------------------------------
+static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
+    )
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+
+    return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param   void
+ *
+ *  @return  Pointer to the memory block
+ *
+ *  @description
+ *  This function allocates a block of memory from the pool
+ *
+**/
+//------------------------------------------------------------------------------
+void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
+    )
+{
+    uint64_t pa_block = 0;
+    void *p_va_block = NULL;
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2mac_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
+        return NULL;
+    }
+    pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
+    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2mac_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
+        return NULL;
+    }
+
+    if (!pa_block) {
+        //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
+        return NULL;
+    }
+    p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
+    return p_va_block;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
+ *  needed by the L2
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_wls_ready(
+    )
+{
+    int ret = SUCCESS;
+    ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param   void
+ *
+ *  @return  Number of blocks of APIs received
+ *
+ *  @description
+ *  This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
+ *  during runtime when L2 sends a API to L1 and then waits for response back.
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_wls_wait(
+    )
+{
+    int ret = SUCCESS;
+//    NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
+    ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function checks if this is the last message in this tti.
+ *
+**/
+//------------------------------------------------------------------------------
+static inline uint8_t is_msg_present(
+    uint16_t flags)
+{
+    return (!((flags & WLS_TF_FIN) || (flags == 0)));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer
+ *  to the linked list
+ *
+**/
+//------------------------------------------------------------------------------
+uint64_t *nr5g_fapi_fapi2mac_wls_get(
+    uint32_t * msg_size,
+    uint16_t * msg_type,
+    uint16_t * flags)
+{
+    uint64_t *data = NULL;
+    WLS_HANDLE h_wls;
+    uint32_t ms = 0;
+    uint16_t mt = 0, f = 0;
+
+    h_wls = nr5g_fapi_fapi2mac_wls_instance();
+    data = (uint64_t *) WLS_Get1(h_wls, &ms, &mt, &f);
+    *msg_size = ms, *msg_type = mt, *flags = f;
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][GET] %p size: %d "
+            "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
+
+    return data;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param[in]   ptr Pointer to the block to send
+ *  @param[in]   size Size of the block to send
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function sends a single block of API from PHY to MAC
+ *
+**/
+//------------------------------------------------------------------------------
+inline uint8_t nr5g_fapi_fapi2mac_wls_put(
+    p_fapi_api_queue_elem_t p_msg,
+    uint32_t msg_size,
+    uint16_t msg_type,
+    uint16_t flags)
+{
+    uint8_t ret = SUCCESS;
+
+    WLS_HANDLE h_mac_wls = nr5g_fapi_fapi2mac_wls_instance();
+    uint64_t pa = nr5g_fapi_wls_va_to_pa(h_mac_wls, (void *)p_msg);
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][PUT] %ld size: %d "
+            "type: %x flags: %x", pa, msg_size, msg_type, flags));
+
+    ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
+
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param[in]   p_list Pointer to the linked list head
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function sends a linked list of APIs from PHY to MAC.
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_wls_send(
+    p_fapi_api_queue_elem_t p_list_elem)
+{
+    uint8_t ret = SUCCESS;
+    p_fapi_api_queue_elem_t p_curr_msg = NULL;
+    fapi_msg_t *p_msg_header = NULL;
+    uint16_t flags = 0;
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+
+    p_curr_msg = p_list_elem;
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2mac_lock_send)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
+        return FAILURE;
+    }
+
+    if (p_curr_msg && p_curr_msg->p_next) {
+        flags = WLS_SG_FIRST;
+        if (p_curr_msg->msg_type == FAPI_MSG_HEADER_IND) {
+            if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
+                    p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
+                    FAPI_MSG_HEADER_IND, flags)) {
+                printf("Error\n");
+                if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                        fapi2mac_lock_send)) {
+                    NR5G_FAPI_LOG(ERROR_LOG,
+                        ("unable to unlock send pthread mutex"));
+                }
+                return FAILURE;
+            }
+            p_curr_msg = p_curr_msg->p_next;
+            flags = WLS_SG_NEXT;
+        }
+
+        while (p_curr_msg) {
+            // only batch mode
+            p_msg_header = (fapi_msg_t *) (p_curr_msg + 1);
+            if (p_curr_msg->p_next) {   // FIRST/NEXT
+                if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
+                        p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
+                        p_msg_header->msg_id, flags)) {
+                    printf("Error\n");
+                    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                            fapi2mac_lock_send)) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("unable to unlock send pthread mutex"));
+                    }
+                    return FAILURE;
+                }
+                p_curr_msg = p_curr_msg->p_next;
+            } else {            // LAST
+                flags = WLS_SG_LAST;
+                if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
+                        p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
+                        p_msg_header->msg_id, flags)) {
+                    printf("Error\n");
+                    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                            fapi2mac_lock_send)) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("unable to unlock send pthread mutex"));
+                    }
+                    return FAILURE;
+                }
+                p_curr_msg = NULL;
+            }
+            flags = WLS_SG_NEXT;
+        }
+    }
+
+    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2mac_lock_send)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
+        return FAILURE;
+    }
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer
+ *  to the linked list
+ *
+**/
+//------------------------------------------------------------------------------
+p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
+    )
+{
+    uint16_t msg_type = 0;
+    uint16_t flags = 0;
+    uint32_t msg_size = 0;
+    uint32_t num_elms = 0;
+    uint64_t *p_msg = NULL;
+    p_fapi_api_queue_elem_t p_qelm_list = NULL;
+    p_fapi_api_queue_elem_t p_qelm = NULL;
+    p_fapi_api_queue_elem_t p_tail_qelm = NULL;
+    WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
+
+    num_elms = nr5g_fapi_fapi2mac_wls_wait();
+    if (!num_elms)
+        return p_qelm_list;
+
+    do {
+        p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
+        if (p_msg) {
+            p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
+                (uint64_t) p_msg);
+            if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
+                printf("Error: Invalid Ptr\n");
+                continue;
+            }
+            p_qelm->p_next = NULL;
+            if (p_qelm_list) {
+                p_tail_qelm = p_qelm_list;
+                while (NULL != p_tail_qelm->p_next) {
+                    p_tail_qelm = p_tail_qelm->p_next;
+                }
+                p_tail_qelm->p_next = p_qelm;
+            } else {
+                p_qelm_list = p_qelm;
+            }
+        }
+        num_elms--;
+    } while (num_elms && is_msg_present(flags));
+
+    return p_qelm_list;
+}
diff --git a/fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.h b/fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.h
new file mode 100644 (file)
index 0000000..0a080b2
--- /dev/null
@@ -0,0 +1,45 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ *
+ * @file This file has definitions of Shared Memory interface functions between
+ * FAPI and PHY.
+ *
+ **/
+
+#ifndef _5G_FAPI_FAPI2MAC_WLS_H
+#define _5G_FAPI_FAPI2MAC_WLS_H
+
+#include "fapi_interface.h"
+
+uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
+    void *data);
+uint8_t nr5g_fapi_fapi2mac_wls_send(
+    p_fapi_api_queue_elem_t p_list_elem);
+p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
+    );
+
+uint8_t nr5g_fapi_fapi2mac_wls_ready(
+    );
+uint8_t nr5g_fapi_fapi2mac_wls_wait(
+    );
+
+void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
+    );
+
+#endif /*_5G_FAPI_FAPI2MAC_WLS_H*/
diff --git a/fapi_5g/source/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.c b/fapi_5g/source/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.c
new file mode 100644 (file)
index 0000000..02c8937
--- /dev/null
@@ -0,0 +1,509 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file has Shared Memory interface functions between FAPI and PHY
+ * @defgroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ **/
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_wls.h"
+#include "nr5g_fapi_fapi2phy_wls.h"
+#include "nr5g_fapi_log.h"
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param data Pointer to validate
+ *
+ *  @return  TRUE If pointer is within valid shared WLS memory region
+ *           FALSE If pointer is out of valid shared WLS memory region
+ *
+ *  @description
+ *  This function validates pointer's in WLS shared memory region
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2phy_is_valid_wls_ptr(
+    void *data)
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    if ((unsigned long)data >= (unsigned long)p_wls_ctx->pPartitionMemBase &&
+        (unsigned long)data < ((unsigned long)p_wls_ctx->pPartitionMemBase +
+            p_wls_ctx->nPartitionMemSize)) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param void
+ *
+ *  @return  A pointer to WLS_HANDLE stucture
+ *
+ *  @description
+ *  This function returns the WLS instance
+ *
+**/
+//------------------------------------------------------------------------------
+static inline WLS_HANDLE nr5g_fapi_fapi2phy_wls_instance(
+    )
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    return p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST];
+}
+
+//----------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer
+ *  to the linked list
+ *
+**/
+//----------------------------------------------------------------------------------
+inline uint64_t *nr5g_fapi_fapi2phy_wls_get(
+    uint32_t * msg_size,
+    uint16_t * msg_type,
+    uint16_t * flags)
+{
+    uint64_t *data = NULL;
+    WLS_HANDLE h_wls;
+    uint32_t ms = 0;
+    uint16_t mt = 0, f = 0;
+
+    h_wls = nr5g_fapi_fapi2phy_wls_instance();
+    data = (uint64_t *) WLS_Get(h_wls, &ms, &mt, &f);
+    *msg_size = ms, *msg_type = mt, *flags = f;
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2PHY WLS][GET] %p size: %d "
+            "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
+
+    return data;
+}
+
+//----------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[in]   p_msg Pointer to API block that needs to be sent to L1
+ *  @param[in]   msg_size Size of Message
+ *  @param[in]   msg_id Message Id
+ *  @param[in]   flags Special flags needed for WLS
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function adds a block of API from L2 to L1 which will be sent later
+ *
+**/
+//----------------------------------------------------------------------------------
+inline uint8_t nr5g_fapi_fapi2phy_wls_put(
+    uint64_t p_msg,
+    uint32_t msg_size,
+    uint16_t msg_type,
+    uint16_t flags)
+{
+    int ret = SUCCESS;
+    WLS_HANDLE h_phy_wls = nr5g_fapi_fapi2phy_wls_instance();
+    uint64_t pa = nr5g_fapi_wls_va_to_pa(h_phy_wls, (void *)p_msg);
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2PHY WLS][PUT] %ld size: %d "
+            "type: %x flags: %x", pa, msg_size, msg_type, flags));
+    ret = WLS_Put(h_phy_wls, pa, msg_size, msg_type, flags);
+
+    return ret;
+}
+
+//----------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
+ *  needed by the L2
+ *
+**/
+//----------------------------------------------------------------------------------
+inline uint8_t nr5g_fapi_fapi2phy_wls_ready(
+    )
+{
+    int ret = SUCCESS;
+    //NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for L1 to respond in WLS Ready"));
+    ret = WLS_Ready(nr5g_fapi_fapi2phy_wls_instance());
+    return ret;
+}
+
+//----------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param   void
+ *
+ *  @return  Number of blocks of APIs received
+ *
+ *  @description
+ *  This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
+ *  during runtime when L2 sends a API to L1 and then waits for response back.
+ *
+**/
+//----------------------------------------------------------------------------------
+inline uint8_t nr5g_fapi_fapi2phy_wls_wait(
+    )
+{
+    int ret = SUCCESS;
+//    NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for L1 to respond in WLS Wait"));
+    ret = WLS_Wait(nr5g_fapi_fapi2phy_wls_instance());
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function checks if this is the last message in this tti.
+ *
+**/
+//------------------------------------------------------------------------------
+static inline uint8_t is_msg_present(
+    uint16_t flags)
+{
+    return (!((flags & WLS_TF_FIN) || (flags == 0)));
+}
+
+//----------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer
+ *  to the linked list
+ *
+**/
+//----------------------------------------------------------------------------------
+PMAC2PHY_QUEUE_EL nr5g_fapi_fapi2phy_wls_recv(
+    )
+{
+    uint16_t msg_type = 0;
+    uint16_t flags = 0;
+    uint32_t msg_size = 0;
+    uint32_t num_elms = 0;
+    uint64_t *p_msg = NULL;
+    static uint32_t g_free_recv_idx = 0;
+    PMAC2PHY_QUEUE_EL p_qelm_list = NULL;
+    PMAC2PHY_QUEUE_EL p_qelm = NULL;
+    PMAC2PHY_QUEUE_EL p_tail_qelm = NULL;
+
+    num_elms = nr5g_fapi_fapi2phy_wls_wait();
+    if (!num_elms)
+        return p_qelm_list;
+
+    do {
+        p_msg = nr5g_fapi_fapi2phy_wls_get(&msg_size, &msg_type, &flags);
+        if (p_msg) {
+            WLS_HANDLE h_wls = nr5g_fapi_fapi2phy_wls_instance();
+            p_qelm = (PMAC2PHY_QUEUE_EL)
+                nr5g_fapi_wls_pa_to_va(h_wls, (uint64_t) p_msg);
+            if (nr5g_fapi_fapi2phy_is_valid_wls_ptr(p_qelm) == FALSE) {
+                printf("Error: Invalid Ptr\n");
+                continue;
+            }
+            p_qelm->pNext = NULL;
+            if (p_qelm_list) {
+                p_tail_qelm->pNext = p_qelm;
+                p_tail_qelm = p_qelm;
+            } else {
+                p_qelm_list = p_qelm;
+                p_tail_qelm = p_qelm;
+            }
+        }
+        num_elms--;
+    } while (num_elms && is_msg_present(flags));
+
+    if (p_qelm_list) {
+        wls_fapi_add_recv_apis_to_free(p_qelm_list, g_free_recv_idx);
+        g_free_recv_idx++;
+        if (g_free_recv_idx >= TO_FREE_SIZE) {
+            g_free_recv_idx = 0;
+        }
+        // Free 10 TTIs Later
+        wls_fapi_free_recv_free_list(g_free_recv_idx);
+
+        wls_fapi_add_blocks_to_ul();
+    }
+
+    return p_qelm_list;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[in]    p_msg_header Pointer to the TxSDuReq Message block
+ *  @param[out]   n_zbc_blocks Number of ZBC blocks
+ *
+ *  @return  1 if this block is a TxSduReq message. 0 else.
+ *
+ *  @description
+ *  This function checks if a block is a TxSduReq messages and counts the number
+ *  of ZBC blocks in this API
+ *
+**/
+//------------------------------------------------------------------------------
+int nr5g_fapi_fapi2phy_is_sdu_zbc_block(
+    void *p_msg,
+    int *num_zbc_blocks)
+{
+    PL1L2MessageHdr p_msg_header = (PL1L2MessageHdr) p_msg;
+    *num_zbc_blocks = 0;
+
+    if (p_msg_header->nMessageType == MSG_TYPE_PHY_TX_REQ) {
+        PTXRequestStruct p_dl_sdu_req = (PTXRequestStruct) p_msg_header;
+        PDLPDUDataStruct p_dl_pdu_data = (PDLPDUDataStruct) (p_dl_sdu_req + 1);
+        uint32_t i;
+        for (i = 0; i < p_dl_sdu_req->nPDU; i++) {
+            *num_zbc_blocks += (p_dl_pdu_data->nPduLen1 ? 1 : 0);
+            *num_zbc_blocks += (p_dl_pdu_data->nPduLen2 ? 1 : 0);
+            p_dl_pdu_data++;
+        }
+
+        if (*num_zbc_blocks) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+//----------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[in]   p_msg_header Pointer to the TxSduReq Message block
+ *  @param[in]   flags Special flags needed for WLS
+ *  @param[in]   n_zbc_blocks Number of ZBC blocks in list
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function adds all the ZBC blocks in a TXSDU Message and prepares them to
+ *  be sent to the L1
+ *
+**/
+//------------------------------------------------------------------------------
+uint32_t nr5g_fapi_fapi2phy_send_zbc_blocks(
+    void *p_msg,
+    uint16_t flags)
+{
+    PL1L2MessageHdr p_msg_header = (PL1L2MessageHdr) p_msg;
+    PTXRequestStruct p_dl_sdu_req = (PTXRequestStruct) p_msg_header;
+    PDLPDUDataStruct p_dl_pdu_data = (PDLPDUDataStruct) (p_dl_sdu_req + 1);
+    uint32_t i, j, is_last, is_last1, msg_type;
+    uint16_t list_flags = flags;
+
+    for (i = 0; i < p_dl_sdu_req->nPDU; i++) {
+        is_last = (i == (p_dl_sdu_req->nPDU - 1));
+        for (j = 0; j < MAX_DL_PER_UE_CODEWORD_NUM; j++) {
+            uint32_t pdu_len;
+            uint8_t *p_payload;
+            p_payload = NULL;
+            msg_type = 0;
+            if (j == 0) {
+                pdu_len = p_dl_pdu_data->nPduLen1;
+                p_payload = p_dl_pdu_data->pPayload1;
+                msg_type = MSG_PHY_ZBC_BLOCK0_REQ;
+            } else {
+                pdu_len = p_dl_pdu_data->nPduLen2;
+                p_payload = p_dl_pdu_data->pPayload2;
+                msg_type = MSG_PHY_ZBC_BLOCK1_REQ;
+            }
+
+            if (p_payload) {
+                is_last1 = (((j == 0) && (p_dl_pdu_data->pPayload2 == 0)) ||
+                    (j == (MAX_DL_PER_UE_CODEWORD_NUM - 1)));
+                if ((list_flags & WLS_TF_FIN) && is_last && is_last1) {
+                    flags = WLS_SG_LAST;
+                } else {
+                    flags = WLS_SG_NEXT;
+                }
+
+                WLS_HANDLE h_phy_wls = nr5g_fapi_fapi2phy_wls_instance();
+                if (WLS_Put(h_phy_wls, (uint64_t) p_payload, pdu_len, msg_type,
+                        flags) != SUCCESS) {
+                    printf("Error ZBC block 0x%016lx\n", (uint64_t) p_payload);
+                    return FAILURE;
+                }
+            }
+        }
+        p_dl_pdu_data++;
+    }
+
+    return SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[in]      A pointer to the phy instance
+ *  @param[in]      A data Pointer to the Linked list header
+ *
+ *  @return         0 if SUCCESS
+ *
+ *  @description    This function sends a list of APIs to the L1 via WLS
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2phy_wls_send(
+    void *data)
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    PMAC2PHY_QUEUE_EL p_curr_msg = NULL;
+    PL1L2MessageHdr p_msg_header;
+    uint16_t flags = 0;
+    uint8_t ret = SUCCESS;
+    int n_zbc_blocks = 0, is_zbc = 0, count = 0;
+    static uint32_t g_free_send_idx = 0;
+
+    p_curr_msg = (PMAC2PHY_QUEUE_EL) data;
+    wls_fapi_add_send_apis_to_free(p_curr_msg, g_free_send_idx);
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2phy_lock_send)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
+        return FAILURE;
+    }
+
+    if (p_curr_msg->pNext) {
+        flags = WLS_SG_FIRST;
+        while (p_curr_msg) {
+            // only batch mode
+            count++;
+            p_msg_header = (PL1L2MessageHdr) (p_curr_msg + 1);
+            if (p_curr_msg->pNext) {    // FIRST/NEXT list element
+                if (SUCCESS != nr5g_fapi_fapi2phy_wls_put((uint64_t) p_curr_msg,
+                        p_curr_msg->nMessageLen + sizeof(MAC2PHY_QUEUE_EL),
+                        p_msg_header->nMessageType, flags)) {
+                    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                            fapi2phy_lock_send)) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("unable to unlock send pthread mutex"));
+                    }
+                    return FAILURE;
+                }
+
+                if (nr5g_fapi_fapi2phy_is_sdu_zbc_block(p_msg_header, &n_zbc_blocks)) { // ZBC blocks
+                    if (nr5g_fapi_fapi2phy_send_zbc_blocks(p_msg_header,
+                            flags) != SUCCESS) {
+                        if (pthread_mutex_unlock((pthread_mutex_t *) &
+                                p_wls_ctx->fapi2phy_lock_send)) {
+                            NR5G_FAPI_LOG(ERROR_LOG,
+                                ("unable to unlock send pthread mutex"));
+                        }
+                        return FAILURE;
+                    }
+                }
+                p_curr_msg = p_curr_msg->pNext;
+            } else {            /* p_curr_msg->Next */
+                // LAST
+                flags = WLS_SG_LAST;
+                is_zbc = 0;
+                if (nr5g_fapi_fapi2phy_is_sdu_zbc_block(p_msg_header,
+                        &n_zbc_blocks)) {
+                    flags = WLS_SG_NEXT;
+                    is_zbc = 1;
+                }
+                if (nr5g_fapi_fapi2phy_wls_put((uint64_t) p_curr_msg,
+                        p_curr_msg->nMessageLen + sizeof(MAC2PHY_QUEUE_EL),
+                        p_msg_header->nMessageType, flags) != SUCCESS) {
+                    printf("Error\n");
+                    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                            fapi2phy_lock_send)) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("unable to unlock send pthread mutex"));
+                    }
+                    return FAILURE;
+                }
+
+                if (is_zbc) {   // ZBC blocks
+                    if (nr5g_fapi_fapi2phy_send_zbc_blocks(p_msg_header,
+                            WLS_SG_LAST) != SUCCESS) {
+                        printf("Error\n");
+                        if (pthread_mutex_unlock((pthread_mutex_t *) &
+                                p_wls_ctx->fapi2phy_lock_send)) {
+                            NR5G_FAPI_LOG(ERROR_LOG,
+                                ("unable to unlock send pthread mutex"));
+                        }
+                        return FAILURE;
+                    }
+                }
+                p_curr_msg = NULL;
+            }                   /* p_curr_msg->Next */
+            flags = WLS_SG_NEXT;
+        }
+    } else {                      // one block
+        count++;
+        if (nr5g_fapi_fapi2phy_is_sdu_zbc_block(p_curr_msg, &n_zbc_blocks)) {
+            printf("Error ZBC block cannot be only one in the list\n");
+            if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                    fapi2phy_lock_send)) {
+                NR5G_FAPI_LOG(ERROR_LOG,
+                    ("unable to unlock send pthread mutex"));
+            }
+            return FAILURE;
+        }
+
+        if (SUCCESS != nr5g_fapi_fapi2phy_wls_put((uint64_t) p_curr_msg,
+                p_curr_msg->nMessageLen + sizeof(MAC2PHY_QUEUE_EL),
+                p_curr_msg->nMessageType, flags)) {
+            printf("Error\n");
+            if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                    fapi2phy_lock_send)) {
+                NR5G_FAPI_LOG(ERROR_LOG,
+                    ("unable to unlock send pthread mutex"));
+            }
+            return FAILURE;
+        }
+    }
+
+    if (count > 1) {
+        g_free_send_idx++;
+        if (g_free_send_idx >= TO_FREE_SIZE)
+            g_free_send_idx = 0;
+
+        // Free 10 TTIs Later
+        wls_fapi_free_send_free_list(g_free_send_idx);
+    }
+
+    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2phy_lock_send)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
+        return FAILURE;
+    }
+    return ret;
+}
diff --git a/fapi_5g/source/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.h b/fapi_5g/source/framework/wls/fapi2phy/nr5g_fapi_fapi2phy_wls.h
new file mode 100644 (file)
index 0000000..36cf06a
--- /dev/null
@@ -0,0 +1,42 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ *
+ * @file This file has definitions of Shared Memory interface functions between
+ * FAPI and PHY.
+ *
+ **/
+
+#ifndef _NR5G_FAPI2PHY_WLS_H_
+#define _NR5G_FAPI2PHY_WLS_H_
+
+#include "gnb_l1_l2_api.h"
+
+uint8_t nr5g_fapi_fapi2phy_is_valid_wls_ptr(
+    void *data);
+uint8_t nr5g_fapi_fapi2phy_wls_send(
+    void *data);
+PMAC2PHY_QUEUE_EL nr5g_fapi_fapi2phy_wls_recv(
+    );
+
+inline uint8_t nr5g_fapi_fapi2phy_wls_ready(
+    );
+inline uint8_t nr5g_fapi_fapi2phy_wls_wait(
+    );
+
+#endif /*_NR5G_FAPI2PHY_WLS_H_*/
diff --git a/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.c b/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.c
new file mode 100644 (file)
index 0000000..2ae97b0
--- /dev/null
@@ -0,0 +1,915 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file has Shared Memory interface functions between FAPI and PHY
+ * @defgroup nr5g_fapi_source_framework_wls_lib_group
+ **/
+
+#include "nr5g_fapi_framework.h"
+#include "nr5g_fapi_internal.h"
+#include "nr5g_fapi_wls.h"
+#include "nr5g_fapi_config_loader.h"
+#include "nr5g_fapi_log.h"
+#include "nr5g_fapi_memory.h"
+
+nr5g_fapi_wls_context_t g_wls_ctx;
+
+static uint32_t g_to_free_send_list_cnt[TO_FREE_SIZE] = { 0 };
+static uint64_t g_to_free_send_list[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = { {0L} };
+static uint32_t g_to_free_recv_list_cnt[TO_FREE_SIZE] = { 0 };
+static uint64_t g_to_free_recv_list[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = { {0L} };
+
+static uint8_t alloc_track[ALLOC_TRACK_SIZE];
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param void
+ *
+ *  @return  A pointer to WLS Context stucture
+ *
+ *  @description
+ *  This function returns the WLS Context structure which has WLS related parameters
+ *
+**/
+//------------------------------------------------------------------------------
+inline p_nr5g_fapi_wls_context_t nr5g_fapi_wls_context(
+    )
+{
+    return &g_wls_ctx;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]   ptr Pointer to display
+ *  @param[in]   size Size of data
+ *
+ *  @return  void
+ *
+ *  @description
+ *  This function displays content of Buffer - Used for debugging
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_wls_show_data(
+    void *ptr,
+    uint32_t size)
+{
+    uint8_t *d = ptr;
+    int i;
+
+    for (i = 0; i < size; i++) {
+        if (!(i & 0xf))
+            printf("\n");
+        printf("%02x ", d[i]);
+    }
+    printf("\n");
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param   N/A
+ *
+ *  @return  N/A
+ *
+ *  @description
+ *  This function prints to the console FAPI stats
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_wls_print_stats(
+    void)
+{
+    p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
+    printf("          nTotalBlocks[%5d]  nAllocBlocks[%5d]  nFreeBlocks[%5d]\n",
+        pWls->nTotalBlocks, pWls->nAllocBlocks,
+        (pWls->nTotalBlocks - pWls->nAllocBlocks));
+    printf("        nTotalAllocCnt[%5d] nTotalFreeCnt[%5d]         Diff[%5d]\n",
+        pWls->nTotalAllocCnt, pWls->nTotalFreeCnt,
+        (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt));
+    uint32_t nFinalTotalDlBufAllocCnt = 0, nFinalTotalDlBufFreeCnt = 0, idx;
+
+//#define PRINTF_DEBUG(fmt, args...) //printf(fmt, ## args)
+#define PRINTF_DEBUG(fmt, args...)
+    PRINTF_DEBUG("\n");
+    PRINTF_DEBUG("\n        nDlBufAllocCnt: \n");
+    for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
+        nFinalTotalDlBufAllocCnt += pWls->nTotalDlBufAllocCnt[idx];
+        PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufAllocCnt[idx]);
+    }
+    PRINTF_DEBUG("\n");
+    PRINTF_DEBUG("\n         nDlBufFreeCnt: \n");
+    for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
+        nFinalTotalDlBufFreeCnt += pWls->nTotalDlBufFreeCnt[idx];
+        PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufFreeCnt[idx]);
+    }
+    PRINTF_DEBUG("\n\n");
+
+    printf("        nDlBufAllocCnt[%5d] nDlBufFreeCnt[%5d]         Diff[%5d]\n",
+        nFinalTotalDlBufAllocCnt, nFinalTotalDlBufFreeCnt,
+        (nFinalTotalDlBufAllocCnt - nFinalTotalDlBufFreeCnt));
+    printf
+        ("        nUlBufAllocCnt[%5d] nUlBufFreeCnt[%5d]         Diff[%5d]\n\n",
+        pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt,
+        (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]   ptr Address to convert
+ *
+ *  @return  Converted address
+ *
+ *  @description
+ *  This function converts Virtual Address to Physical Address
+ *
+**/
+//------------------------------------------------------------------------------
+uint64_t nr5g_fapi_wls_va_to_pa(
+    WLS_HANDLE h_wls,
+    void *ptr)
+{
+    return ((uint64_t) WLS_VA2PA(h_wls, ptr));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]   ptr Address to convert
+ *
+ *  @return  Converted address
+ *
+ *  @description
+ *  This function converts Physical Address to Virtual Address
+ *
+**/
+//------------------------------------------------------------------------------
+void *nr5g_fapi_wls_pa_to_va(
+    WLS_HANDLE h_wls,
+    uint64_t ptr)
+{
+    return ((void *)WLS_PA2VA(h_wls, ptr));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group 
+ *
+ *  @param   void
+ *
+ *  @return  Number of blocks added
+ *
+ *  @description
+ *  This function add WLS blocks to the L1 Array which will be used by L1 in 
+ *  every TTI to populate and send back APIs to the MAC
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t wls_fapi_add_blocks_to_ul(
+    void)
+{
+    int num_blocks = 0;
+    p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
+    WLS_HANDLE h_wls = pWls->h_wls[NR5G_FAPI2PHY_WLS_INST];
+
+    void *pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
+    if (!pMsg) {
+        return num_blocks;
+    }
+
+    /* allocate blocks for UL transmittion */
+    while (WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa(h_wls, pMsg)) > 0) {
+        num_blocks++;
+        pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
+        if (!pMsg)
+            break;
+    }
+
+    // free not enqueued block
+    if (pMsg) {
+        wls_fapi_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS);
+    }
+
+    return num_blocks;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param          A pointer to the phy instance table.
+ *
+ *  @return         0 if SUCCESS
+ *
+ *  @description    This function initializes WLS layer primitives and allocates
+ *                  memory needed to exchange APIs between FAPI and PHY.
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_wls_init(
+    p_nr5g_fapi_cfg_t cfg)
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    const char *dev_name = "wls";
+
+    if (p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST] &&
+        p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST]) {
+        // NR5G_FAPI_LOG(ERROR_LOG, ("WLS instance already opened!"));
+        return FAILURE;
+    }
+
+    p_wls_ctx->shmem_size = cfg->wls.shmem_size;
+    p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST] =
+        WLS_Open_Dual(dev_name /*"wls"cfg->wls.device_name */ ,
+        WLS_SLAVE_CLIENT,
+        cfg->wls.shmem_size, &p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]);
+    if ((NULL == p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]) &&
+        (NULL == p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST])) {
+        // NR5G_FAPI_LOG(ERROR_LOG,("[NR5G_FAPI_ WLS] WLS instance connected."));
+        return FAILURE;
+    }
+    // Issue WLS_Alloc() for FAPI2MAC
+    p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST],
+        p_wls_ctx->shmem_size);
+
+    if (NULL == p_wls_ctx->shmem) {
+        printf("Unable to alloc WLS Memory for FAPI2MAC\n");
+        return FAILURE;
+    }
+
+    p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST],
+        p_wls_ctx->shmem_size);
+    p_wls_ctx->pWlsMemBase = p_wls_ctx->shmem;
+    p_wls_ctx->nTotalMemorySize = p_wls_ctx->shmem_size;
+    if (NULL == p_wls_ctx->shmem) {
+        printf("Unable to alloc WLS Memory\n");
+        return FAILURE;
+    }
+
+    pthread_mutex_init((pthread_mutex_t *)
+            &p_wls_ctx->fapi2phy_lock_send, NULL);
+    pthread_mutex_init((pthread_mutex_t *)
+            &p_wls_ctx->fapi2phy_lock_alloc, NULL);
+    pthread_mutex_init((pthread_mutex_t *)
+            &p_wls_ctx->fapi2mac_lock_send, NULL);
+    pthread_mutex_init((pthread_mutex_t *)
+            &p_wls_ctx->fapi2mac_lock_alloc, NULL);
+    return SUCCESS;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]   pMemArray Pointer to WLS Memory Management Structure
+ *  @param[in]   pMemArrayMmeory pointer to flat buffer that was allocated
+ *  @param[in]   totalSize total size of flat buffer allocated
+ *  @param[in]   nBlockSize Size of each block that needs to be partitoned by the memory manager
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function creates memory blocks from a flat buffer which will be used for communication between FAPI and PHY
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_fapi_create_mem_array(
+    PWLS_FAPI_MEM_STRUCT pMemArray,
+    void *pMemArrayMemory,
+    uint32_t totalSize,
+    uint32_t nBlockSize)
+{
+
+    int numBlocks = totalSize / nBlockSize;
+    void **ptr;
+    uint32_t i;
+
+    printf
+        ("wls_fapi_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
+        pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
+
+    // Can't be less than pointer size
+    if (nBlockSize < sizeof(void *)) {
+        return FAILURE;
+    }
+    // Can't be less than one block
+    if (totalSize < sizeof(void *)) {
+        return FAILURE;
+    }
+
+    pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
+    pMemArray->pStorage = pMemArrayMemory;
+    pMemArray->pEndOfStorage =
+        ((unsigned long *)pMemArrayMemory) +
+        numBlocks * nBlockSize / sizeof(unsigned long);
+    pMemArray->nBlockSize = nBlockSize;
+    pMemArray->nBlockCount = numBlocks;
+
+    // Initialize single-linked list of free blocks;
+    ptr = (void **)pMemArrayMemory;
+    for (i = 0; i < pMemArray->nBlockCount; i++) {
+#ifdef MEMORY_CORRUPTION_DETECT
+        // Fill with some pattern
+        uint8_t *p = (uint8_t *) ptr;
+        uint32_t j;
+
+        p += (nBlockSize - 16);
+        for (j = 0; j < 16; j++) {
+            p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
+        }
+#endif
+
+        if (i == pMemArray->nBlockCount - 1) {
+            *ptr = NULL;        // End of list
+        } else {
+            // Points to the next block
+            *ptr = (void **)(((uint8_t *) ptr) + nBlockSize);
+            ptr += nBlockSize / sizeof(unsigned long);
+        }
+    }
+
+    NR5G_FAPI_MEMSET(alloc_track, sizeof(uint8_t) * ALLOC_TRACK_SIZE, 0,
+        sizeof(uint8_t) * ALLOC_TRACK_SIZE);
+
+    return SUCCESS;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]   pWls Pointer to the nr5g_fapi_wls_ctx structure
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function created a partition and blocks of WLS memory for API exchange between FAPI and PHY
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_fapi_create_partition(
+    p_nr5g_fapi_wls_context_t pWls)
+{
+#define WLS_HUGE_DEF_PAGE_SIZEA    0x40000000LL
+    static long hugePageSize = WLS_HUGE_DEF_PAGE_SIZEA;
+    //   NR5G_FAPI_MEMSET(pWls->pWlsMemBase , 0xCC, pWls->nTotalMemorySize);  // This is done by the Master Only
+    pWls->pPartitionMemBase =
+        (void *)(((uint8_t *) pWls->pWlsMemBase) + hugePageSize);
+    pWls->nPartitionMemSize = (pWls->nTotalMemorySize - hugePageSize);
+
+    pWls->nTotalBlocks = pWls->nPartitionMemSize / MSG_MAXSIZE;
+    return wls_fapi_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase,
+        pWls->nPartitionMemSize, MSG_MAXSIZE);
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]      A pointer to the FAPI Memory Structure (Initialized by L2)
+ *  @param[out]     ppBlock Pointer where the allocated memory block is stored     
+ *
+ *  @return         0 if SUCCESS
+ *
+ *  @description    This function allocates a memory block from the pool
+ *
+**/
+//------------------------------------------------------------------------------
+uint32_t wls_fapi_alloc_mem_array(
+    PWLS_FAPI_MEM_STRUCT pMemArray,
+    void **ppBlock)
+{
+    int idx;
+
+    if (pMemArray->ppFreeBlock == NULL) {
+        printf("wls_fapi_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
+        return FAILURE;
+    }
+    // FIXME: Remove after debugging
+    if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) ||
+        ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) {
+        printf
+            ("wls_fapi_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    pMemArray->ppFreeBlock =
+        (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+    *pMemArray->ppFreeBlock =
+        (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+
+    if ((*pMemArray->ppFreeBlock != NULL) &&
+        (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
+            ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) {
+        fprintf(stderr,
+            "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+            *pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    *ppBlock = (void *)pMemArray->ppFreeBlock;
+    pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock);
+
+    idx =
+        (((uint64_t) * ppBlock -
+            (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
+    if (alloc_track[idx]) {
+        printf
+            ("wls_fapi_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+            *pMemArray->ppFreeBlock);
+        return FAILURE;
+    } else {
+#ifdef MEMORY_CORRUPTION_DETECT
+        uint32_t nBlockSize = pMemArray->nBlockSize, i;
+        uint8_t *p = (uint8_t *) * ppBlock;
+
+        p += (nBlockSize - 16);
+        for (i = 0; i < 16; i++) {
+            p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
+        }
+#endif
+        alloc_track[idx] = 1;
+    }
+
+    //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
+
+    return SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]      A pointer to the FAPI Memory Structure (Initialized by L2)
+ *  @param[in]      pBlock Pointer where the allocated memory block is stored     
+ *
+ *  @return         0 if SUCCESS
+ *
+ *  @description    This function frees a WLS block of memory and adds 
+ *                  it back to the pool
+ *
+**/
+//------------------------------------------------------------------------------
+uint32_t wls_fapi_free_mem_array(
+    PWLS_FAPI_MEM_STRUCT pMemArray,
+    void *pBlock)
+{
+    int idx;
+    unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
+
+    pBlock = (void *)((unsigned long)pBlock & ~mask);
+
+    if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
+        printf
+            ("wls_fapi_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n",
+            pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage);
+        return FAILURE;
+    }
+
+    idx =
+        (int)(((uint64_t) pBlock -
+            (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
+
+    if (alloc_track[idx] == 0) {
+        printf
+            ("wls_fapi_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, pBlock);
+        return SUCCESS;
+    } else {
+#ifdef MEMORY_CORRUPTION_DETECT
+        uint32_t nBlockSize = pMemArray->nBlockSize, i;
+        uint8_t *p = (uint8_t *) pBlock;
+
+        p += (nBlockSize - 16);
+        for (i = 0; i < 16; i++) {
+            if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG) {
+                printf("ERROR: Corruption\n");
+                nr5g_fapi_wls_print_stats();
+                exit(-1);
+            }
+        }
+#endif
+        alloc_track[idx] = 0;
+    }
+
+    if (((void *)pMemArray->ppFreeBlock) == pBlock) {
+        // Simple protection against freeing of already freed block
+        return SUCCESS;
+    }
+    // FIXME: Remove after debugging
+    if ((pMemArray->ppFreeBlock != NULL)
+        && (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage)
+            || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))) {
+        printf
+            ("wls_fapi_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+    // FIXME: Remove after debugging
+    if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
+        printf("wls_fapi_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
+            pMemArray, pBlock);
+        return FAILURE;
+    }
+
+    *((void **)pBlock) =
+        (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+    pMemArray->ppFreeBlock =
+        (void **)((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
+
+    //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
+
+    return SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param          size (if 0 fixed size from pool)
+ *  @param          Number of locations
+ *
+ *  @return         0 if SUCCESS
+ *
+ *  @description    This function initializes WLS layer primitives and allocates
+ *                  memory needed to exchange APIs between FAPI and PHY.
+**/
+//------------------------------------------------------------------------------
+void *wls_fapi_alloc_buffer(
+    uint32_t size,
+    uint32_t loc)
+{
+    void *pBlock = NULL;
+    p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to get lock alloc pthread mutex"));
+        exit(-1);
+    }
+
+    if (wls_fapi_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS) {
+        printf("wls_fapi_alloc_buffer alloc error size[%d] loc[%d]\n", size,
+            loc);
+        nr5g_fapi_wls_print_stats();
+        exit(-1);
+    } else {
+        pWls->nAllocBlocks++;
+    }
+
+    //printf("----------------wls_fapi_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
+
+    //printf("[%p]\n", pBlock);
+
+    pWls->nTotalAllocCnt++;
+    if (loc < MAX_DL_BUF_LOCATIONS)
+        pWls->nTotalDlBufAllocCnt[loc]++;
+    else if (loc < MAX_UL_BUF_LOCATIONS)
+        pWls->nTotalUlBufAllocCnt++;
+
+    if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
+        exit(-1);
+    }
+
+    return pBlock;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]      *pMsg Pointer to free
+ *
+ *  @return         void
+ *
+ *  @descriptioni   This function frees a block of memory and adds it back to 
+ *                  the pool.
+ *
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_buffer(
+    void *pMsg,
+    uint32_t loc)
+{
+    p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
+        exit(-1);
+    }
+    //printf("----------------wls_fapi_free_buffer: buf[%p] loc[%d]\n", pMsg, loc);
+    if (wls_fapi_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS) {
+        pWls->nAllocBlocks--;
+    } else {
+        printf("wls_fapi_free_buffer Free error\n");
+        nr5g_fapi_wls_print_stats();
+        exit(-1);
+    }
+
+    pWls->nTotalFreeCnt++;
+    if (loc < MAX_DL_BUF_LOCATIONS)
+        pWls->nTotalDlBufFreeCnt[loc]++;
+    else if (loc < MAX_UL_BUF_LOCATIONS)
+        pWls->nTotalUlBufFreeCnt++;
+
+    if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
+        exit(-1);
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param          A pointer to a wls instance
+ *
+ *  @return         0 if SUCCESS
+ *
+ *  @description    This function initializes the WLS layer FAPI2PHY interface 
+ *                  primitives and allocates memory needed to exchange APIs 
+ *                  between FAPI and PHY.
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi2Phy_wls_init(
+    p_nr5g_fapi_wls_context_t pwls)
+{
+    int nBlocks = 0;
+    uint8_t retval = SUCCESS;
+
+    retval = wls_fapi_create_partition(pwls);
+    if ((nBlocks = wls_fapi_add_blocks_to_ul()) == 0) {
+        return FAILURE;
+    }
+
+    return retval;
+}
+
+uint8_t get_stats_location(
+    uint8_t msg_type)
+{
+    uint8_t loc;
+    switch (msg_type) {
+        case MSG_TYPE_PHY_CONFIG_REQ:
+            loc = MEM_STAT_CONFIG_REQ;
+            break;
+        case MSG_TYPE_PHY_START_REQ:
+            loc = MEM_STAT_START_REQ;
+            break;
+        case MSG_TYPE_PHY_STOP_REQ:
+            loc = MEM_STAT_STOP_REQ;
+            break;
+        case MSG_TYPE_PHY_SHUTDOWN_REQ:
+            loc = MEM_STAT_SHUTDOWN_REQ;
+            break;
+        case MSG_TYPE_PHY_DL_CONFIG_REQ:
+            loc = MEM_STAT_DL_CONFIG_REQ;
+            break;
+        case MSG_TYPE_PHY_UL_CONFIG_REQ:
+            loc = MEM_STAT_UL_CONFIG_REQ;
+            break;
+        case MSG_TYPE_PHY_UL_DCI_REQ:
+            loc = MEM_STAT_UL_DCI_REQ;
+            break;
+        case MSG_TYPE_PHY_TX_REQ:
+            loc = MEM_STAT_TX_REQ;
+            break;
+        case MSG_TYPE_PHY_DL_IQ_SAMPLES:
+            loc = MEM_STAT_DL_IQ_SAMPLES;
+            break;
+        case MSG_TYPE_PHY_UL_IQ_SAMPLES:
+            loc = MEM_STAT_UL_IQ_SAMPLES;
+            break;
+        default:
+            loc = MEM_STAT_DEFAULT;
+    }
+
+    return loc;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]      pListElem Pointer to List element header
+ *  @param[in]      idx Subframe Number
+ *
+ *  @return         Number of blocks freed
+ *
+ *  @description    This function Frees all the blocks in a List Element Linked
+ *                  List coming from L1 by storing them into an array to be 
+ *                  freed at a later point in time.
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_add_recv_apis_to_free(
+    PMAC2PHY_QUEUE_EL pListElem,
+    uint32_t idx)
+{
+    PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+    L1L2MessageHdr *p_msg_header = NULL;
+    PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL;
+    int count, i;
+    uint8_t *ptr = NULL;
+
+    WLS_HANDLE h_wls;
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    h_wls = p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST];
+
+    count = g_to_free_recv_list_cnt[idx];
+    pNextMsg = pListElem;
+    while (pNextMsg) {
+        if (count >= TOTAL_FREE_BLOCKS) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
+                    "\t\t\t\tlist index: %d list count: %d max list count: %d",
+                    __func__, idx, count, TOTAL_FREE_BLOCKS));
+            return;
+        }
+
+        g_to_free_recv_list[idx][count++] = (uint64_t) pNextMsg;
+        p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
+        if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) {
+            p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header;
+            for (i = 0; i < p_phy_rx_ulsch_ind->nUlsch; i++) {
+                ptr = p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i].pPayload;
+                ptr = (uint8_t *) nr5g_fapi_wls_pa_to_va(h_wls, (uint64_t) ptr);
+
+                if (ptr) {
+                    g_to_free_recv_list[idx][count++] = (uint64_t) ptr;
+                }
+            }
+        }
+        pNextMsg = pNextMsg->pNext;
+    }
+
+    g_to_free_recv_list[idx][count] = 0L;
+    g_to_free_recv_list_cnt[idx] = count;
+
+    NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group 
+ *
+ *  @param[in]      idx subframe Number
+ *
+ *  @return         Number of blocks freed
+ *
+ *  @description    This function frees all blocks that have been added to the 
+ *                  free array
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_recv_free_list(
+    uint32_t idx)
+{
+    PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+    int count = 0;
+
+    if (idx >= TO_FREE_SIZE) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx));
+        return;
+    }
+
+    pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count];
+    while (pNextMsg) {
+        wls_fapi_free_buffer(pNextMsg, MIN_UL_BUF_LOCATIONS);
+        g_to_free_recv_list[idx][count++] = 0L;
+        if (g_to_free_recv_list[idx][count])
+            pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count];
+        else
+            pNextMsg = 0L;
+    }
+
+    NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
+    g_to_free_recv_list_cnt[idx] = 0;
+
+    return;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ *  @param[in]      pListElem Pointer to List element header
+ *  @param[in]      idx Subframe Number
+ *
+ *  @return         Number of blocks freed
+ *
+ *  @description    This function Frees all the blocks in a List Element Linked
+ *                  List coming from L1 by storing them into an array to be 
+ *                  freed at a later point in time.
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_add_send_apis_to_free(
+    PMAC2PHY_QUEUE_EL pListElem,
+    uint32_t idx)
+{
+    PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+    L1L2MessageHdr *p_msg_header = NULL;
+    PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL;
+    int count, i;
+    uint8_t *ptr = NULL;
+
+    count = g_to_free_send_list_cnt[idx];
+    pNextMsg = pListElem;
+    while (pNextMsg) {
+        if (count >= TOTAL_FREE_BLOCKS) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
+                    "\t\t\t\tlist index: %d list count: %d max list count: %d",
+                    __func__, idx, count, TOTAL_FREE_BLOCKS));
+            return;
+        }
+
+        g_to_free_send_list[idx][count++] = (uint64_t) pNextMsg;
+        p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
+        if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) {
+            p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header;
+            for (i = 0; i < p_phy_rx_ulsch_ind->nUlsch; i++) {
+                ptr = p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i].pPayload;
+                if (ptr) {
+                    g_to_free_send_list[idx][count++] = (uint64_t) ptr;
+                }
+            }
+        }
+        pNextMsg = pNextMsg->pNext;
+    }
+
+    g_to_free_send_list[idx][count] = 0L;
+    g_to_free_send_list_cnt[idx] = count;
+
+    NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group 
+ *
+ *  @param[in]      idx subframe Number
+ *
+ *  @return         Number of blocks freed
+ *
+ *  @description    This function frees all blocks that have been added to the 
+ *                  free array
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_send_free_list(
+    uint32_t idx)
+{
+    PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+    L1L2MessageHdr *p_msg_header = NULL;
+    int count = 0, loc = 0;
+
+    if (idx >= TO_FREE_SIZE) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx));
+        return;
+    }
+
+    pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[idx][count];
+    while (pNextMsg) {
+        p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
+        loc = get_stats_location(p_msg_header->nMessageType);
+        wls_fapi_free_buffer(pNextMsg, loc);
+        g_to_free_send_list[idx][count++] = 0L;
+        if (g_to_free_send_list[idx][count])
+            pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[idx][count];
+        else
+            pNextMsg = 0L;
+    }
+
+    NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
+    g_to_free_send_list_cnt[idx] = 0;
+
+    return;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group 
+ *
+ *  @param[in]      idx subframe Number
+ *
+ *  @return         Number of blocks freed
+ *
+ *  @description    This function frees all blocks that have been added to the 
+ *                  free array
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_list_all(
+    void)
+{
+    uint32_t idx;
+
+    for (idx = 0; idx < TO_FREE_SIZE; idx++) {
+        wls_fapi_free_send_free_list(idx);
+        wls_fapi_free_recv_free_list(idx);
+    }
+
+    nr5g_fapi_wls_print_stats();
+}
diff --git a/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.h b/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.h
new file mode 100644 (file)
index 0000000..1b67be6
--- /dev/null
@@ -0,0 +1,149 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ *
+ * @file This file has definitions of Shared Memory interface functions between
+ * FAPI and PHY.
+ *
+ **/
+
+#ifndef _NR5G_FAPI_WLS_H_
+#define _NR5G_FAPI_WLS_H_
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "wls_lib.h"
+#include "gnb_l1_l2_api.h"
+
+typedef void *WLS_HANDLE;
+
+#define NUM_WLS_INSTANCES 2
+#define NR5G_FAPI2PHY_WLS_INST  0
+#define NR5G_FAPI2MAC_WLS_INST  1
+
+#define MAX_NUM_LOCATIONS          (16)
+
+#define MIN_DL_BUF_LOCATIONS        (0) /* Used for stats collection 0-10 */
+#define MAX_DL_BUF_LOCATIONS        (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS)  /* Used for stats collection 0-10 */
+#define MIN_UL_BUF_LOCATIONS        (MAX_DL_BUF_LOCATIONS)  /* Used for stats collection 0-10 */
+#define MAX_UL_BUF_LOCATIONS        (MIN_UL_BUF_LOCATIONS + MAX_NUM_LOCATIONS)
+
+#define TO_FREE_SIZE                        ( 10 )
+#define TOTAL_FREE_BLOCKS                   ( 50 * FAPI_MAX_PHY_INSTANCES)  /* To hold both send and recv blocks on PHY side wls */
+#define ALLOC_TRACK_SIZE                    ( 16384 )
+#define MSG_MAXSIZE                         (16*16384 )
+
+#define MEMORY_CORRUPTION_DETECT
+#define MEMORY_CORRUPTION_DETECT_FLAG       (0xAB)
+
+typedef enum wls_fapi_free_list_e {
+    WLS_FAPI_FREE_SEND_LIST = 0,
+    WLS_FAPI_FREE_RECV_LIST
+} wls_fapi_free_list_t;
+
+typedef struct wls_fapi_mem_array {
+    void **ppFreeBlock;
+    void *pStorage;
+    void *pEndOfStorage;
+    uint32_t nBlockSize;
+    uint32_t nBlockCount;
+} WLS_FAPI_MEM_STRUCT, *PWLS_FAPI_MEM_STRUCT;
+
+// WLS context structure
+typedef struct _nr5g_fapi_wls_context {
+    void *shmem;                // shared  memory region.
+    uint64_t shmem_size;        // shared  memory region size.
+    WLS_FAPI_MEM_STRUCT sWlsStruct;
+    WLS_HANDLE h_wls[NUM_WLS_INSTANCES];    // WLS context handle
+    void *pWlsMemBase;
+    uint32_t nTotalMemorySize;
+    uint32_t nTotalBlocks;
+    uint32_t nAllocBlocks;
+    uint32_t nTotalAllocCnt;
+    uint32_t nTotalFreeCnt;
+    uint32_t nTotalUlBufAllocCnt;
+    uint32_t nTotalUlBufFreeCnt;
+    uint32_t nTotalDlBufAllocCnt[MAX_DL_BUF_LOCATIONS];
+    uint32_t nTotalDlBufFreeCnt[MAX_DL_BUF_LOCATIONS];
+    uint32_t nPartitionMemSize;
+    void *pPartitionMemBase;
+    volatile pthread_mutex_t fapi2phy_lock_send;
+    volatile pthread_mutex_t fapi2phy_lock_alloc;
+    volatile pthread_mutex_t fapi2mac_lock_send;
+    volatile pthread_mutex_t fapi2mac_lock_alloc;
+} nr5g_fapi_wls_context_t, *p_nr5g_fapi_wls_context_t;
+
+extern nr5g_fapi_wls_context_t g_wls_ctx;
+
+inline p_nr5g_fapi_wls_context_t nr5g_fapi_wls_context(
+    );
+uint8_t nr5g_fapi_wls_init(
+    );
+uint8_t nr5g_fapi2Phy_wls_init(
+    p_nr5g_fapi_wls_context_t p_wls);
+
+uint8_t nr5g_fapi_wls_destroy(
+    WLS_HANDLE h_wls);
+void *wls_fapi_alloc_buffer(
+    uint32_t size,
+    uint32_t loc);
+void wls_fapi_free_buffer(
+    void *pMsg,
+    uint32_t loc);
+uint32_t wls_fapi_create_mem_array(
+    PWLS_FAPI_MEM_STRUCT pMemArray,
+    void *pMemArrayMemory,
+    uint32_t totalSize,
+    uint32_t nBlockSize);
+uint32_t wls_fapi_alloc_mem_array(
+    PWLS_FAPI_MEM_STRUCT pMemArray,
+    void **ppBlock);
+uint32_t wls_fapi_free_mem_array(
+    PWLS_FAPI_MEM_STRUCT pMemArray,
+    void *pBlock);
+uint64_t nr5g_fapi_wls_va_to_pa(
+    WLS_HANDLE h_wls,
+    void *ptr);
+void *nr5g_fapi_wls_pa_to_va(
+    WLS_HANDLE h_wls,
+    uint64_t ptr);
+uint8_t wls_fapi_add_blocks_to_ul(
+    void);
+void nr5g_fapi_wls_show_data(
+    void *ptr,
+    uint32_t size);
+int32_t wls_fapi_sdu_zbc_block_add_to_free(
+    void *pMsgHeaderHead,
+    int count,
+    uint64_t * pToFreeList);
+void wls_fapi_free_list_all(
+    void);
+void nr5g_fapi_wls_print_stats(
+    void);
+
+void wls_fapi_add_send_apis_to_free(
+    PMAC2PHY_QUEUE_EL pListElem,
+    uint32_t idx);
+void wls_fapi_free_send_free_list(
+    uint32_t idx);
+void wls_fapi_add_recv_apis_to_free(
+    PMAC2PHY_QUEUE_EL pListElem,
+    uint32_t idx);
+void wls_fapi_free_recv_free_list(
+    uint32_t idx);
+#endif /*_NR5G_FAPI_WLS_H_*/
diff --git a/fapi_5g/source/framework/workers/nr5g_fapi_mac2phy_thread.c b/fapi_5g/source/framework/workers/nr5g_fapi_mac2phy_thread.c
new file mode 100644 (file)
index 0000000..2c7de23
--- /dev/null
@@ -0,0 +1,296 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_mac2phy_thread.h"
+#include "nr5g_fapi_fapi2mac_wls.h"
+#include "nr5g_fapi_fapi2phy_api.h"
+#include "nr5g_fapi_fapi2phy_p5_proc.h"
+#include "nr5g_fapi_fapi2phy_p7_proc.h"
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
+ *
+ *  @param[in,out]   void
+ *
+ *  @return none
+ *
+ *  @description
+ *  DOXYGEN_TO_DO
+ *
+**/
+//------------------------------------------------------------------------------
+void *nr5g_fapi_mac2phy_thread_func(
+    void *config)
+{
+    cpu_set_t cpuset;
+    pthread_t thread;
+    p_fapi_api_queue_elem_t p_msg_list = NULL;
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx = (p_nr5g_fapi_phy_ctx_t) config;
+
+    NR5G_FAPI_LOG(INFO_LOG, ("[MAC2PHY] Thread %s launched LWP:%ld on "
+            "Core: %d\n", __func__, pthread_self(),
+            p_phy_ctx->mac2phy_worker_core_id));
+
+    thread = p_phy_ctx->mac2phy_tid = pthread_self();
+    CPU_ZERO(&cpuset);
+    CPU_SET(p_phy_ctx->mac2phy_worker_core_id, &cpuset);
+    pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+
+    usleep(1000);
+    while (!p_phy_ctx->process_exit) {
+        p_msg_list = nr5g_fapi_fapi2mac_wls_recv();
+        if (p_msg_list)
+            nr5g_fapi_mac2phy_api_recv_handler(config, p_msg_list);
+    }
+    pthread_exit(NULL);
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
+ *
+ *  @param[in,out]   void
+ *
+ *  @return none
+ *
+ *  @description
+ *  DOXYGEN_TO_DO
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_mac2phy_api_recv_handler(
+    void *config,
+    p_fapi_api_queue_elem_t p_msg_list)
+{
+    p_fapi_api_queue_elem_t p_per_carr_api_list = NULL;
+    p_fapi_api_queue_elem_t p_prev_elm = NULL;
+    fapi_msg_t *p_fapi_msg = NULL;
+    p_fapi_msg_header_t p_fapi_msg_header = NULL;
+
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx = NULL;
+    p_nr5g_fapi_phy_instance_t p_phy_instance = NULL;
+    uint8_t num_apis = 0;
+    uint8_t phy_id = 0;
+
+    NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] %s:", __func__));
+    p_phy_ctx = (p_nr5g_fapi_phy_ctx_t) config;
+    while (p_msg_list) {
+        p_per_carr_api_list = p_msg_list;
+        p_fapi_msg_header = (fapi_msg_header_t *) (p_per_carr_api_list + 1);
+        num_apis = p_fapi_msg_header->num_msg;
+        phy_id = p_fapi_msg_header->handle;
+
+        if (num_apis > 0 && p_msg_list->p_next) {   // likely
+            p_per_carr_api_list = p_per_carr_api_list->p_next;
+            p_msg_list = p_per_carr_api_list;
+            NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] PHY_ID: %d NUM APIs: %d\n",
+                    phy_id, num_apis));
+        } else {                // unlikely
+            // skip to next carrier list. since current fapi message hearder
+            // has no apis
+            if (p_msg_list->p_next) {
+                NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] No APIs for PHY_ID: %d."
+                        " Skip...\n", phy_id));
+                p_msg_list = p_msg_list->p_next;
+                continue;
+            } else {
+                NR5G_FAPI_LOG(ERROR_LOG, ("[MAC2PHY] PHY_ID: %d NUM APIs: %d\n",
+                        phy_id, num_apis));
+                return;
+            }
+        }
+
+        // walk through the list and disconnet per carrier apis
+        if (p_msg_list->p_next) {
+            p_prev_elm = p_msg_list;
+            while (p_msg_list) {
+                if (FAPI_MSG_HEADER_IND == p_msg_list->msg_type) {
+                    p_prev_elm->p_next = NULL;
+                    break;
+                }
+                p_prev_elm = p_msg_list;
+                p_msg_list = p_msg_list->p_next;
+            }
+        } else {
+            p_msg_list = NULL;
+        }
+
+        if (phy_id > FAPI_MAX_PHY_INSTANCES) {
+            NR5G_FAPI_LOG(ERROR_LOG, ("[MAC2PHY]: Invalid Phy Id: %d\n",
+                    phy_id));
+            continue;
+        }
+
+        if (p_per_carr_api_list) {
+            p_fapi_msg = (fapi_msg_t *) (p_per_carr_api_list + 1);
+            if ((p_fapi_msg->msg_id != FAPI_VENDOR_EXT_UL_IQ_SAMPLES)) {
+                p_phy_instance = &p_phy_ctx->phy_instance[phy_id];
+                if (FAPI_STATE_IDLE == p_phy_instance->state) {
+                    if (p_fapi_msg->msg_id != FAPI_CONFIG_REQUEST) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("CONFIG.request is not received "
+                                "for %d PHY Instance\n", phy_id));
+                        continue;
+                    }
+                    p_phy_instance->phy_id = phy_id;
+                }
+            }
+            nr5g_fapi_mac2phy_api_processing_handler(p_phy_instance,
+                p_per_carr_api_list);
+            p_per_carr_api_list = NULL;
+        }
+    }
+    // Send to PHY
+    NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] Send to PHY.."));
+    nr5g_fapi_fapi2phy_send_api_list();
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
+ *
+ *  @param[in,out]   void
+ *
+ *  @return none
+ *
+ *  @description
+ *  DOXYGEN_TO_DO
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_mac2phy_api_processing_handler(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    p_fapi_api_queue_elem_t p_msg_list)
+{
+    uint16_t msg_type;
+    p_fapi_api_queue_elem_t p_vendor_elm = NULL;
+    p_fapi_api_queue_elem_t p_prev_elm = NULL;
+    p_fapi_api_queue_elem_t p_curr_elm = NULL;
+    p_fapi_api_queue_elem_t p_tx_data_elm = NULL;
+    p_fapi_api_queue_elem_t p_tx_data_pdu_list = NULL;
+    p_fapi_api_queue_elem_t p_tx_data_pdu_list_tail = NULL;
+    fapi_msg_t *p_fapi_msg = NULL;
+    fapi_vendor_msg_t *p_vendor_msg = NULL;
+
+    // Get vendor body if present
+    p_prev_elm = p_vendor_elm = p_msg_list;
+    while (p_vendor_elm) {
+        p_fapi_msg = (fapi_msg_t *) (p_vendor_elm + 1);
+        if (p_fapi_msg->msg_id == FAPI_VENDOR_MESSAGE) {
+            if (p_prev_elm == p_vendor_elm) {
+                NR5G_FAPI_LOG(ERROR_LOG,
+                    ("[MAC2PHY] Received only Vendor Message"));
+                return;
+            }
+            p_vendor_msg = (fapi_vendor_msg_t *) p_fapi_msg;
+            NR5G_FAPI_LOG(TRACE_LOG, ("[MAC2PHY] Vendor Msg: %p\n",
+                    p_vendor_msg));
+            // disconnect the vendor element from the api list
+            p_prev_elm->p_next = NULL;
+            break;
+        }
+        p_prev_elm = p_vendor_elm;
+        p_vendor_elm = p_vendor_elm->p_next;
+    }
+
+    // split the tx_data_request pdus
+    p_curr_elm = p_msg_list;
+    while (p_curr_elm) {
+        msg_type = p_curr_elm->msg_type;
+        if (msg_type == FAPI_TX_DATA_REQUEST) {
+            p_tx_data_elm = p_curr_elm;
+        } else if (msg_type == FAPI_MSG_PHY_ZBC_BLOCK_REQ) {
+            if (p_tx_data_pdu_list) {
+                p_tx_data_pdu_list_tail->p_next = p_curr_elm;
+                p_tx_data_pdu_list_tail = p_tx_data_pdu_list_tail->p_next;
+            } else {
+                p_tx_data_pdu_list_tail = p_tx_data_pdu_list = p_curr_elm;
+            }
+        } else {
+        }
+        p_curr_elm = p_curr_elm->p_next;
+    }
+
+    if (p_tx_data_pdu_list && p_tx_data_elm) {
+        p_tx_data_elm->p_tx_data_elm_list = p_tx_data_pdu_list;
+        p_tx_data_elm->p_next = NULL;
+    }
+    // Walk through the API list
+    while (p_msg_list) {
+        p_fapi_msg = (fapi_msg_t *) (p_msg_list + 1);
+        switch (p_fapi_msg->msg_id) {
+                /*  P5 Vendor Message Processing */
+#ifdef DEBUG_MODE
+            case FAPI_VENDOR_EXT_UL_IQ_SAMPLES:
+                nr5g_fapi_ul_iq_samples_request(
+                    (fapi_vendor_ext_iq_samples_req_t *) p_fapi_msg);
+                break;
+
+            case FAPI_VENDOR_EXT_DL_IQ_SAMPLES:
+                nr5g_fapi_dl_iq_samples_request(
+                    (fapi_vendor_ext_iq_samples_req_t *) p_fapi_msg);
+                break;
+
+#endif
+            case FAPI_VENDOR_EXT_SHUTDOWN_REQUEST:
+                nr5g_fapi_shutdown_request(p_phy_instance,
+                    (fapi_vendor_ext_shutdown_req_t *) p_fapi_msg);
+                break;
+
+                /*  P5 Message Processing */
+            case FAPI_CONFIG_REQUEST:
+                nr5g_fapi_config_request(p_phy_instance, (fapi_config_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                break;
+
+            case FAPI_START_REQUEST:
+                nr5g_fapi_start_request(p_phy_instance, (fapi_start_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                break;
+
+            case FAPI_STOP_REQUEST:
+                nr5g_fapi_stop_request(p_phy_instance, (fapi_stop_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                break;
+
+                /*  P7 Message Processing */
+            case FAPI_DL_TTI_REQUEST:
+                nr5g_fapi_dl_tti_request(p_phy_instance, (fapi_dl_tti_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                break;
+
+            case FAPI_UL_TTI_REQUEST:
+                nr5g_fapi_ul_tti_request(p_phy_instance, (fapi_ul_tti_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                break;
+
+            case FAPI_UL_DCI_REQUEST:
+                nr5g_fapi_ul_dci_request(p_phy_instance, (fapi_ul_dci_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                break;
+
+            case FAPI_TX_DATA_REQUEST:
+                nr5g_fapi_tx_data_request(p_phy_instance, (fapi_tx_data_req_t *)
+                    p_fapi_msg, p_vendor_msg);
+                p_msg_list->p_tx_data_elm_list = NULL;
+                break;
+
+            default:
+                break;
+        }
+        p_msg_list = p_msg_list->p_next;
+    }
+}
diff --git a/fapi_5g/source/framework/workers/nr5g_fapi_mac2phy_thread.h b/fapi_5g/source/framework/workers/nr5g_fapi_mac2phy_thread.h
new file mode 100644 (file)
index 0000000..fcde6e2
--- /dev/null
@@ -0,0 +1,32 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifndef _NR5G_FAPI_MAC2PHY_THREAD_H_
+#define _NR5G_FAPI_MAC2PHY_THREAD_H_
+
+#include "nr5g_fapi_framework.h"
+#include "fapi_interface.h"
+
+void nr5g_fapi_mac2phy_api_recv_handler(
+    void *config,
+    p_fapi_api_queue_elem_t p_msg_list);
+
+void nr5g_fapi_mac2phy_api_processing_handler(
+    p_nr5g_fapi_phy_instance_t p_phy_instance,
+    p_fapi_api_queue_elem_t p_msg_list);
+
+#endif
diff --git a/fapi_5g/source/framework/workers/nr5g_fapi_phy2mac_thread.c b/fapi_5g/source/framework/workers/nr5g_fapi_phy2mac_thread.c
new file mode 100644 (file)
index 0000000..0cf650b
--- /dev/null
@@ -0,0 +1,198 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#include "nr5g_fapi_framework.h"
+#include "nr5g_fapi_fapi2phy_wls.h"
+#include "nr5g_fapi_phy2mac_thread.h"
+#include "nr5g_fapi_fapi2mac_api.h"
+#include "nr5g_fapi_fapi2mac_p5_proc.h"
+#include "nr5g_fapi_fapi2mac_p7_proc.h"
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_workers_phy2mac_group
+ *
+ *  @param[in,out]   void
+ *
+ *  @return none
+ *
+ *  @description
+ *  DOXYGEN_TO_DO
+ *
+**/
+//------------------------------------------------------------------------------
+void *nr5g_fapi_phy2mac_thread_func(
+    void *config)
+{
+    cpu_set_t cpuset;
+    pthread_t thread;
+    PMAC2PHY_QUEUE_EL p_msg_list = NULL;
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx = (p_nr5g_fapi_phy_ctx_t) config;
+
+    NR5G_FAPI_LOG(INFO_LOG, ("[PHY2MAC] Thread %s launched LWP:%ld on "
+            "Core: %d\n", __func__, pthread_self(),
+            p_phy_ctx->phy2mac_worker_core_id));
+
+    thread = p_phy_ctx->phy2mac_tid = pthread_self();
+    CPU_ZERO(&cpuset);
+    CPU_SET(p_phy_ctx->phy2mac_worker_core_id, &cpuset);
+    pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+
+    usleep(1000);
+    while (!p_phy_ctx->process_exit) {
+        p_msg_list = nr5g_fapi_fapi2phy_wls_recv();
+        if (p_msg_list)
+            nr5g_fapi_phy2mac_api_recv_handler(config, p_msg_list);
+
+        nr5g_fapi_fapi2mac_send_api_list();
+    }
+    pthread_exit(NULL);
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_workers_mac2phy_group
+ *
+ *  @param[in,out]   void
+ *
+ *  @return none
+ *
+ *  @description
+ *  DOXYGEN_TO_DO
+ *
+**/
+//------------------------------------------------------------------------------
+void nr5g_fapi_phy2mac_api_recv_handler(
+    void *config,
+    PMAC2PHY_QUEUE_EL p_msg_list)
+{
+    PMAC2PHY_QUEUE_EL p_curr_msg;
+    PL1L2MessageHdr p_msg_header = NULL;
+
+    NR5G_FAPI_LOG(TRACE_LOG, ("[PHY2MAC] %s:", __func__));
+
+    nr5g_fapi_message_header((p_nr5g_fapi_phy_ctx_t) config);
+
+    p_curr_msg = (PMAC2PHY_QUEUE_EL) p_msg_list;
+    while (p_curr_msg) {
+        p_msg_header = (PL1L2MessageHdr) (p_curr_msg + 1);
+        switch (p_msg_header->nMessageType) {
+                /*  P5 Vendor Message Processing */
+#ifdef DEBUG_MODE
+            case MSG_TYPE_PHY_DL_IQ_SAMPLES:
+                {
+                    nr5g_fapi_dl_iq_samples_response((p_nr5g_fapi_phy_ctx_t)
+                        config, (PADD_REMOVE_BBU_CORES) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_UL_IQ_SAMPLES:
+                {
+                    nr5g_fapi_ul_iq_samples_response((p_nr5g_fapi_phy_ctx_t)
+                        config, (PADD_REMOVE_BBU_CORES) p_msg_header);
+                }
+                break;
+#endif
+            case MSG_TYPE_PHY_SHUTDOWN_RESP:
+                {
+                    nr5g_fapi_shutdown_response((p_nr5g_fapi_phy_ctx_t) config,
+                        (PSHUTDOWNRESPONSEStruct) p_msg_header);
+                }
+                break;
+
+                /*  P5 Message Processing */
+            case MSG_TYPE_PHY_CONFIG_RESP:
+                {
+                    nr5g_fapi_config_response((p_nr5g_fapi_phy_ctx_t) config,
+                        (PCONFIGRESPONSEStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_START_RESP:
+                {
+                    nr5g_fapi_start_resp((p_nr5g_fapi_phy_ctx_t) config,
+                        (PSTARTRESPONSEStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_STOP_RESP:
+                {
+                    nr5g_fapi_stop_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PSTOPRESPONSEStruct) p_msg_header);
+                }
+                break;
+
+                /*  P7 Message Processing */
+            case MSG_TYPE_PHY_RX_ULSCH_IND:
+                {
+                    nr5g_fapi_rx_data_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PRXULSCHIndicationStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_RX_ULSCH_UCI_IND:
+                {
+                    //Not Supported
+                }
+                break;
+
+            case MSG_TYPE_PHY_CRC_IND:
+                {
+                    nr5g_fapi_crc_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PCRCIndicationStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_UCI_IND:
+                {
+                    nr5g_fapi_uci_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PRXUCIIndicationStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_RX_RACH_IND:
+                {
+                    nr5g_fapi_rach_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PRXRACHIndicationStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_RX_SRS_IND:
+                {
+                    nr5g_fapi_srs_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PRXSRSIndicationStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_SLOT_IND:
+                {
+                    nr5g_fapi_slot_indication((p_nr5g_fapi_phy_ctx_t) config,
+                        (PSlotIndicationStruct) p_msg_header);
+                }
+                break;
+
+            case MSG_TYPE_PHY_ERR_IND:
+                {
+                }
+                break;
+
+            default:
+                printf("%s: Unknown Message type: %x\n", __func__,
+                    p_msg_header->nMessageType);
+                break;
+        }
+        p_curr_msg = p_curr_msg->pNext;
+    }
+}
diff --git a/fapi_5g/source/framework/workers/nr5g_fapi_phy2mac_thread.h b/fapi_5g/source/framework/workers/nr5g_fapi_phy2mac_thread.h
new file mode 100644 (file)
index 0000000..79e20b3
--- /dev/null
@@ -0,0 +1,27 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifndef _NR5G_FAPI_PHY2MAC_THREAD_H_
+#define _NR5G_FAPI_PHY2MAC_THREAD_H_
+
+#include "gnb_l1_l2_api.h"
+
+void nr5g_fapi_phy2mac_api_recv_handler(
+    void *config,
+    PMAC2PHY_QUEUE_EL p_msg_list);
+
+#endif
diff --git a/fapi_5g/source/include/nr5g_fapi_args.h b/fapi_5g/source/include/nr5g_fapi_args.h
new file mode 100644 (file)
index 0000000..91cff53
--- /dev/null
@@ -0,0 +1,29 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifndef NR5G_FAPI_ARGS_H_
+#define NR5G_FAPI_ARGS_H_
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_dpdk.h"
+
+const char *nr5g_fapi_parse_args(
+    int argc,
+    char **argv);
+
+#endif                          // NR5G_FAPI_ARGS_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_cmd.h b/fapi_5g/source/include/nr5g_fapi_cmd.h
new file mode 100644 (file)
index 0000000..fe2d1f0
--- /dev/null
@@ -0,0 +1,30 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file consist of fapi logging macro.
+ *
+ **/
+
+#ifndef NR5G_FAPI_CMD_H_
+#define NR5G_FAPI_CMD_H_
+
+void nr5g_fapi_cmgr(
+    void *config);
+
+#endif                          // NR5G_FAPI_CMD_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_common_types.h b/fapi_5g/source/include/nr5g_fapi_common_types.h
new file mode 100644 (file)
index 0000000..9b8a279
--- /dev/null
@@ -0,0 +1,53 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifndef _NR5G_FAPI_COMMON_TYPES_H_
+#define _NR5G_FAPI_COMMON_TYPES_H_
+
+#ifndef TRUE
+/** TRUE = 1 */
+#define TRUE 1
+#endif                          /* #ifndef TRUE */
+
+#ifndef FALSE
+/** FALSE = 0 */
+#define FALSE 0
+#endif                          /* #ifndef FALSE */
+
+#ifndef SUCCESS
+/** SUCCESS = 0 */
+#define SUCCESS     0
+#endif                          /* #ifndef SUCCESS */
+
+#ifndef FAILURE
+/** FAILURE = 1 */
+#define FAILURE     1
+#endif                          /* #ifndef FAILURE */
+
+#define RUP512B(x) (((x)+511)&(~511))
+#define RUP256B(x) (((x)+255)&(~255))
+#define RUP128B(x) (((x)+127)&(~127))
+#define RUP64B(x) (((x)+63)&(~63))
+#define RUP32B(x) (((x)+31)&(~31))
+#define RUP16B(x) (((x)+15)&(~15))
+#define RUP8B(x)  (((x)+7)&(~7))
+#define RUP4B(x)  (((x)+3)&(~3))
+#define RUP2B(x)  (((x)+1)&(~1))
+
+#define UNUSED(x) (void)(x)
+
+#endif                          // _NR5G_FAPI_COMMON_TYPES_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_config_loader.h b/fapi_5g/source/include/nr5g_fapi_config_loader.h
new file mode 100644 (file)
index 0000000..a4cd10a
--- /dev/null
@@ -0,0 +1,69 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file consist of FAPI internal functions.
+ *
+ **/
+
+#ifndef NR5G_FAPI_CONFIG_LOADER_H_
+#define NR5G_FAPI_CONFIG_LOADER_H_
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_dpdk.h"
+#include "nr5g_fapi_log.h"
+
+#define NR5G_FAPI_DEVICE_NAME_LEN   512
+
+typedef struct _nr5g_fapi_thread_info {
+    pthread_t thread_id;        /* ID returned by pthread_create() */
+    pthread_attr_t thread_attr;
+} nr5g_fapi_thread_info_t;
+
+typedef struct _nr5g_fapi_config_worker_cfg {
+    uint8_t core_id;
+    uint8_t thread_priority;
+    uint8_t thread_sched_policy;
+} nr5g_fapi_config_worker_cfg_t;
+
+typedef struct _nr5g_fapi_config_wls_cfg {
+    char device_name[NR5G_FAPI_DEVICE_NAME_LEN];
+    uint64_t shmem_size;
+} nr5g_fapi_config_wls_cfg_t;
+
+typedef struct _nr5g_fapi_config_log_cfg {
+    nr5g_fapi_log_types_t level;
+} nr5g_fapi_config_log_cfg_t;
+
+typedef struct _nr5g_fapi_cfg {
+    char *prgname;
+    nr5g_fapi_config_worker_cfg_t mac2phy_worker;
+    nr5g_fapi_config_worker_cfg_t phy2mac_worker;
+    nr5g_fapi_config_worker_cfg_t urllc_worker;
+    nr5g_fapi_config_wls_cfg_t wls;
+    nr5g_fapi_config_log_cfg_t logger;
+    nr5g_fapi_thread_info_t mac2phy_thread_info;
+    nr5g_fapi_thread_info_t phy2mac_thread_info;
+} nr5g_fapi_cfg_t, *p_nr5g_fapi_cfg_t;
+
+p_nr5g_fapi_cfg_t nr5g_fapi_config_loader(
+    char *prgname,
+    const char *cfg_fname);
+
+#endif                          // NR5G_FAPI_CONFIG_LOADER_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_dpdk.h b/fapi_5g/source/include/nr5g_fapi_dpdk.h
new file mode 100644 (file)
index 0000000..81e65c8
--- /dev/null
@@ -0,0 +1,30 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifndef NR5G_FAPI_DPDK_H_
+#define NR5G_FAPI_DPDK_H_
+
+#include <rte_eal.h>
+#include <rte_cfgfile.h>
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_launch.h>
+#include <rte_memcpy.h>
+#endif                          // NR5G_FAPI_DPDK_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_framework.h b/fapi_5g/source/include/nr5g_fapi_framework.h
new file mode 100644 (file)
index 0000000..fea31bf
--- /dev/null
@@ -0,0 +1,219 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file consist of FAPI internal functions.
+ *
+ **/
+
+#ifndef _NR5G_FAPI_FRAMEWORK_H_
+#define _NR5G_FAPI_FRAMEWORK_H_
+
+#include <fcntl.h>
+#include "fapi_interface.h"
+#include "nr5g_fapi_log.h"
+#include "nr5g_fapi_internal.h"
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_config_loader.h"
+
+// FAPI CONFIG.request parameters
+typedef struct _nr5g_fapi_phy_config {
+    uint8_t n_nr_of_rx_ant;
+    uint16_t phy_cell_id;
+} nr5g_fapi_phy_config_t, *pnr5g_fapi_phy_config_t;
+
+typedef struct _nr5g_fapi_rach_info {
+    uint16_t phy_cell_id;
+} nr5g_fapi_rach_info_t;
+
+typedef struct _nr5g_fapi_srs_info {
+    uint32_t handle;
+} nr5g_fapi_srs_info_t;
+
+typedef struct _nr5g_fapi_pusch_info {
+    uint32_t handle;
+    uint8_t harq_process_id;
+    uint8_t ul_cqi;
+    uint16_t timing_advance;
+} nr5g_fapi_pusch_info_t;
+
+typedef struct _nr5g_fapi_pucch_info {
+    uint32_t handle;
+    uint8_t pucch_format;
+} nr5g_fapi_pucch_info_t;
+
+typedef struct _nr5g_fapi_ul_slot_info {
+    uint16_t cookie;            //set this to frame_no at UL_TTI.Request and compare the 
+    //same during uplink indications. 
+    uint8_t slot_no;
+    uint8_t num_ulsch;
+    uint8_t num_ulcch;
+    uint8_t num_srs;
+    uint8_t rach_presence;
+    nr5g_fapi_rach_info_t rach_info;    //Only One RACH PDU will be reported for RACH.Indication message  
+    nr5g_fapi_srs_info_t srs_info[FAPI_MAX_NUMBER_SRS_PDUS_PER_SLOT];
+    nr5g_fapi_pucch_info_t pucch_info[FAPI_MAX_NUMBER_UCI_PDUS_PER_SLOT];
+    nr5g_fapi_pusch_info_t pusch_info[FAPI_MAX_NUMBER_OF_ULSCH_PDUS_PER_SLOT];
+} nr5g_fapi_ul_slot_info_t;
+
+typedef struct _nr5g_fapi_stats_info_t {
+    uint8_t fapi_param_req;
+    uint8_t fapi_param_res;
+    uint8_t fapi_config_req;
+    uint8_t fapi_config_res;
+    uint8_t fapi_start_req;
+    uint8_t fapi_stop_req;
+    uint8_t fapi_stop_ind;
+    uint8_t fapi_vendor_msg;
+    uint8_t fapi_vext_shutdown_req;
+    uint8_t fapi_vext_shutdown_res;
+#ifdef DEBUG_MODE
+    uint8_t fapi_vext_start_res;
+#endif
+    uint64_t fapi_dl_tti_req;
+    uint64_t fapi_ul_tti_req;
+    uint64_t fapi_ul_dci_req;
+    uint64_t fapi_tx_data_req;
+
+    uint64_t fapi_slot_ind;
+    uint64_t fapi_error_ind;
+    uint64_t fapi_crc_ind;
+    uint64_t fapi_rx_data_ind;
+    uint64_t fapi_uci_ind;
+    uint64_t fapi_srs_ind;
+    uint64_t fapi_rach_ind;
+
+    uint64_t fapi_dl_tti_pdus;
+    uint64_t fapi_dl_tti_pdcch_pdus;
+    uint64_t fapi_dl_tti_pdsch_pdus;
+    uint64_t fapi_dl_tti_csi_rs_pdus;
+    uint64_t fapi_dl_tti_ssb_pdus;
+
+    uint64_t fapi_ul_dci_pdus;
+
+    uint64_t fapi_ul_tti_pdus;
+    uint64_t fapi_ul_tti_prach_pdus;
+    uint64_t fapi_ul_tti_pusch_pdus;
+    uint64_t fapi_ul_tti_pucch_pdus;
+    uint64_t fapi_ul_tti_srs_pdus;
+    uint64_t fapi_crc_ind_pdus;
+    uint64_t fapi_rx_data_ind_pdus;
+    uint64_t fapi_uci_ind_pdus;
+    uint64_t fapi_srs_ind_pdus;
+    uint64_t fapi_rach_ind_pdus;
+} nr5g_fapi_stats_info_t;
+
+typedef struct _nr5g_iapi_stats_info_t {
+    uint8_t iapi_param_req;
+    uint8_t iapi_param_res;
+    uint8_t iapi_config_req;
+    uint8_t iapi_config_res;
+    uint8_t iapi_start_req;
+    uint8_t iapi_start_res;
+    uint8_t iapi_stop_req;
+    uint8_t iapi_stop_ind;
+    uint8_t iapi_shutdown_req;
+    uint8_t iapi_shutdown_res;
+    uint64_t iapi_dl_config_req;
+    uint64_t iapi_ul_config_req;
+    uint64_t iapi_ul_dci_req;
+    uint64_t iapi_tx_req;
+
+    uint64_t iapi_slot_ind;
+    uint64_t iapi_error_ind;
+    uint64_t iapi_crc_ind;
+    uint64_t iapi_rx_data_ind;
+    uint64_t iapi_uci_ind;
+    uint64_t iapi_srs_ind;
+    uint64_t iapi_rach_ind;
+
+    uint64_t iapi_dl_tti_pdus;
+    uint64_t iapi_dl_tti_pdcch_pdus;
+    uint64_t iapi_dl_tti_pdsch_pdus;
+    uint64_t iapi_dl_tti_csi_rs_pdus;
+    uint64_t iapi_dl_tti_ssb_pdus;
+
+    uint64_t iapi_ul_dci_pdus;
+
+    uint64_t iapi_ul_tti_pdus;
+    uint64_t iapi_ul_tti_prach_pdus;
+    uint64_t iapi_ul_tti_pusch_pdus;
+    uint64_t iapi_ul_tti_pucch_pdus;
+    uint64_t iapi_ul_tti_srs_pdus;
+    uint64_t iapi_crc_ind_pdus;
+    uint64_t iapi_rx_data_ind_pdus;
+    uint64_t iapi_uci_ind_pdus;
+    uint64_t iapi_srs_ind_pdus;
+    uint64_t iapi_rach_preambles;
+} nr5g_iapi_stats_info_t;
+
+typedef struct _nr5g_fapi_stats_t {
+    nr5g_fapi_stats_info_t fapi_stats;
+    nr5g_iapi_stats_info_t iapi_stats;
+} nr5g_fapi_stats_t;
+
+// FAPI phy instance structure
+typedef struct _nr5g_fapi_phy_instance {
+    uint8_t phy_id;
+    uint8_t shutdown_retries;
+    uint32_t shutdown_test_type;
+    fapi_states_t state;        // FAPI state
+    nr5g_fapi_phy_config_t phy_config;  // place holder to store,
+    // parameters from config request
+    nr5g_fapi_stats_t stats;
+    nr5g_fapi_ul_slot_info_t ul_slot_info[MAX_UL_SLOT_INFO_COUNT];
+} nr5g_fapi_phy_instance_t, *p_nr5g_fapi_phy_instance_t;
+
+// Phy Context
+typedef struct _nr5g_fapi_phy_context {
+    uint8_t num_phy_instance;
+    uint8_t mac2phy_worker_core_id;
+    uint8_t phy2mac_worker_core_id;
+    pthread_t phy2mac_tid;
+    pthread_t mac2phy_tid;
+    uint64_t process_exit;
+    nr5g_fapi_phy_instance_t phy_instance[FAPI_MAX_PHY_INSTANCES];
+} nr5g_fapi_phy_ctx_t, *p_nr5g_fapi_phy_ctx_t;
+
+// Function Declarations
+inline p_nr5g_fapi_phy_ctx_t nr5g_fapi_get_nr5g_fapi_phy_ctx(
+    );
+uint8_t nr5g_fapi_framework_init(
+    );
+uint8_t nr5g_fapi_framework_stop(
+    );
+uint8_t nr5g_fapi_framework_finish(
+    );
+uint8_t nr5g_fapi_dpdk_init(
+    p_nr5g_fapi_cfg_t cfg);
+uint8_t nr5g_fapi_dpdk_wait(
+    p_nr5g_fapi_cfg_t cfg);
+void *nr5g_fapi_phy2mac_thread_func(
+    void *config);
+void *nr5g_fapi_mac2phy_thread_func(
+    void *config);
+nr5g_fapi_ul_slot_info_t *nr5g_fapi_get_ul_slot_info(
+    uint16_t frame_no,
+    uint8_t slot_no,
+    p_nr5g_fapi_phy_instance_t p_phy_instance);
+void nr5g_fapi_set_ul_slot_info(
+    uint16_t frame_no,
+    uint8_t slot_no,
+    nr5g_fapi_ul_slot_info_t * p_ul_slot_info);
+#endif                          // _NR5G_FAPI_FRAMEWORK_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_internal.h b/fapi_5g/source/include/nr5g_fapi_internal.h
new file mode 100644 (file)
index 0000000..211c152
--- /dev/null
@@ -0,0 +1,717 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+/**
+ * @file
+ * This file consist of FAPI configuration APIs macros, structure typedefs and
+ * prototypes.
+ *
+ **/
+
+#ifndef _NR5G_FAPI_INTELNAL_H_
+#define _NR5G_FAPI_INTELNAL_H_
+
+#include "fapi_interface.h"
+#include "nr5g_fapi_common_types.h"
+
+#define RELEASE_15 0x0001
+
+#define  MAX_UL_SLOT_INFO_COUNT                      10 //Maximum no of Slots for which UL_TTI.request info has to
+#define  FAPI_MAX_NUM_PUSCH_PDU                     255 //as per Table 3-44
+#define  FAPI_MAX_NUM_PUCCH_PDU                     255 //as per Table 3-44
+#define  FAPI_MAX_NUM_SRS_PDU                       255 //as per Table 3-73
+#define  FAPI_MAX_NUM_RACH_PDU                      255 //as per Table 3-74
+
+// Updated per 5G FAPI    
+typedef enum {
+    FAPI_UL_TTI_REQ_PRACH_PDU_TYPE = 0,
+    FAPI_UL_TTI_REQ_PUSCH_PDU_TYPE,
+    FAPI_UL_TTI_REQ_PUCCH_PDU_TYPE,
+    FAPI_UL_TTI_REQ_SRS_PDU_TYPE
+} fapiULTtiReqPduType_e;
+
+// Updated per 5G FAPI
+typedef enum {
+    FAPI_UCI_IND_ON_PUSCH_PDU_TYPE = 0,
+    FAPI_UCI_IND_ON_PUCCH_FMT_0_1_PDU_TYPE,
+    FAPI_UCI_IND_ON_PUCCH_FMT_2_3_4_PDU_TYPE
+} fapiUciIndPdu_Type_e;
+
+// CRC
+enum {
+    FAPI_CRC_CORRECT = 0,
+    FAPI_CRC_ERROR = 1
+};
+
+// Release/Features support
+typedef enum {
+    FAPI_NOT_SUPPORTED = 0,
+    FAPI_SUPPORTED,
+} fapiSupport_t;
+
+// FAPI States
+/**
+ * FAPI state is maintained per fapi instance. If FAPI messages are received in
+ * wrong state an ERROR.indication message will be sent by FAPI.
+ */
+typedef enum _fapi_states {
+    FAPI_STATE_IDLE = 0,
+    FAPI_STATE_CONFIGURED,
+    FAPI_STATE_RUNNING
+} fapi_states_t;
+
+// Information of optional and mandatory status for a TLV
+typedef enum {
+    FAPI_IDLE_STATE_ONLY_OPTIONAL = 0,
+    FAPI_IDLE_STATE_ONLY_MANDATORY,
+    FAPI_IDLE_AND_CONFIGURED_STATES_OPTIONAL,
+    FAPI_IDLE_STATE_MANDATORY_CONFIGURED_STATE_OPTIONAL,
+    FAPI_IDLE_CONFIGURED_AND_RUNNING_STATES_OPTIONAL,
+    FAPI_IDLE_STATE_MANDATORY_CONFIGURED_AND_RUNNING_STATES_OPTIONAL
+} fapiTlvStatus_t;
+
+// PARAMETERS INFORMATION
+#define FAPI_NORMAL_CYCLIC_PREFIX_MASK              0x01
+#define FAPI_EXTENDED_CYCLIC_PREFIX_MASK            0x02
+
+// In 5G FAPI FrameDuplexType as part of Cell Configuration
+typedef enum _fapi_duplex_ {
+    FAPI_TDD = 0,
+    FAPI_FDD
+} fapi_duplex_e;
+
+// Subcarrier spacing information
+#define FAPI_15KHZ_MASK                             0x01
+#define FAPI_30KHZ_MASK                             0x02
+#define FAPI_60KHZ_MASK                             0x04
+#define FAPI_120KHZ_MASK                            0x08
+
+// Bandwitdth information
+#define FAPI_5MHZ_BW_MASK                           0x0001
+#define FAPI_10MHZ_BW_MASK                          0x0002
+#define FAPI_15MHZ_BW_MASK                          0x0004
+#define FAPI_20MHZ_BW_MASK                          0x0010
+#define FAPI_40MHZ_BW_MASK                          0x0020
+#define FAPI_50MHZ_BW_MASK                          0x0040
+#define FAPI_60MHZ_BW_MASK                          0x0080
+#define FAPI_70MHZ_BW_MASK                          0x0100
+#define FAPI_80MHZ_BW_MASK                          0x0200
+#define FAPI_90MHZ_BW_MASK                          0x0400
+#define FAPI_100MHZ_BW_MASK                         0x0800
+#define FAPI_200MHZ_BW_MASK                         0x1000
+#define FAPI_400MHZ_BW_MASK                         0x2000
+
+// PDCCH Information
+#define FAPI_CCE_MAPPING_INTERLEAVED_MASK           0x01
+#define FAPI_CCE_MAPPING_NONINTERLVD_MASK           0x02
+// Upper Bound for PDCCH Channels per Slot
+#define FAPI_MAX_PDCCHS_PER_SLOT_MASK               0xff
+
+// PUCCH Information
+#define FAPI_FORMAT_0_MASK                          0x01
+#define FAPI_FORMAT_1_MASK                          0x02
+#define FAPI_FORMAT_2_MASK                          0x04
+#define FAPI_FORMAT_3_MASK                          0x08
+#define FAPI_FORMAT_4_MASK                          0x10
+// Upper Bound for PUCCH Channels per Slot
+#define FAPI_MAX_PUCCHS_PER_SLOT_MASK               0xff
+
+// PDSCH Information
+#define FAPI_PDSCH_MAPPING_TYPE_A_MASK              0x01
+#define FAPI_PDSCH_MAPPING_TYPE_B_MASK              0x02
+#define FAPI_PDSCH_ALLOC_TYPE_0_MASK                0x01
+#define FAPI_PDSCH_ALLOC_TYPE_1_MASK                0x02
+#define FAPI_PDSCH_VRB_TO_PRB_MAP_NON_INTLV_MASK    0x01
+#define FAPI_PDSCH_VRB_TO_PRB_MAP_INTLVD_MASK       0x02
+#define FAPI_PDSCH_DMRS_CONFIG_TYPE_1_MASK          0x01
+#define FAPI_PDSCH_DMRS_CONFIG_TYPE_2_MASK          0x02
+#define FAPI_PDSCH_DMRS_MAX_LENGTH_1                0
+#define FAPI_PDSCH_DMRS_MAX_LENGTH_2                1
+#define FAPI_DMRS_ADDITIONAL_POS_0_MASK             0x01
+#define FAPI_DMRS_ADDITIONAL_POS_1_MASK             0x02
+#define FAPI_DMRS_ADDITIONAL_POS_2_MASK             0x04
+#define FAPI_DMRS_ADDITIONAL_POS_3_MASK             0x08
+// Upper Limit for PDSCHS TBs per Slot
+#define FAPI_MAX_PDSCHS_TBS_PER_SLOT_MASK           0xff
+#define FAPI_MAX_NUMBERMIMO_LAYERS_PDSCH            2
+
+#define FAPI_MAX_PHY_INSTANCES                      12
+
+typedef enum modulationOrder {
+    FAPI_QPSK = 0,
+    FAPI_16QAM,
+    FAPI_64QAM,
+    FAPI_256QAM
+} fapiModOrder_t;
+
+#define FAPI_MAX_MUMIMO_USERS_MASK                  0xff
+
+// PUSCH Parameters
+#define FAPI_PUSCH_MAPPING_TYPE_A_MASK              0x01
+#define FAPI_PUSCH_MAPPING_TYPE_B_MASK              0x02
+#define FAPI_PUSCH_ALLOC_TYPE_0_MASK                0x01
+#define FAPI_PUSCH_ALLOC_TYPE_1_MASK                0x02
+#define FAPI_PUSCH_VRB_TO_PRB_MAP_NON_INTLV_MASK    0x01
+#define FAPI_PUSCH_VRB_TO_PRB_MAP_INTLVD_MASK       0x02
+#define FAPI_PUSCH_DMRS_CONFIG_TYPE_1_MASK          0x01
+#define FAPI_PUSCH_DMRS_CONFIG_TYPE_2_MASK          0x02
+#define FAPI_PUSCH_DMRS_MAX_LENGTH_1                0
+#define FAPI_PUSCH_DMRS_MAX_LENGTH_2                1
+// Upper limit for PUSCHMAXPTRSPORTS
+#define FAPI_PUSCH_MAX_PTRS_PORTS_UB                2
+//Upper Limit for PDSCHS TBs per Slot
+#define FAPI_MAX_PUSCHS_TBS_PER_SLOT_MASK           0xff
+
+typedef enum aggregationFactor {
+    FAPI_PUSCH_AGG_FACTOR_1 = 0,
+    FAPI_PUSCH_AGG_FACTOR_2,
+    FAPI_PUSCH_AGG_FACTOR_4,
+    FAPI_PUSCH_AGG_FACTOR_8
+} fapiPuschAggFactor_t;
+
+// PRACH Parameters
+#define FAPI_PRACH_LF_FORMAT_0_MASK                 0x01
+#define FAPI_PRACH_LF_FORMAT_1_MASK                 0x02
+#define FAPI_PRACH_LF_FORMAT_2_MASK                 0x04
+#define FAPI_PRACH_LF_FORMAT_3_MASK                 0x08
+
+#define FAPI_PRACH_SF_FORMAT_A1_MASK                0x01
+#define FAPI_PRACH_SF_FORMAT_A2_MASK                0x02
+#define FAPI_PRACH_SF_FORMAT_A3_MASK                0x04
+#define FAPI_PRACH_SF_FORMAT_B1_MASK                0x08
+#define FAPI_PRACH_SF_FORMAT_B2_MASK                0x10
+#define FAPI_PRACH_SF_FORMAT_B3_MASK                0x20
+#define FAPI_PRACH_SF_FORMAT_B4_MASK                0x40
+#define FAPI_PRACH_SF_FORMAT_C0_MASK                0x80
+#define FAPI_PRACH_SF_FORMAT_C2_MASK                0x100
+
+typedef enum prachMaxOccasionsPerSlot {
+    FAPI_MAX_PRACH_FD_OCC_IN_A_SLOT_1 = 0,
+    FAPI_MAX_PRACH_FD_OCC_IN_A_SLOT_2,
+    FAPI_MAX_PRACH_FD_OCC_IN_A_SLOT_4,
+    FAPI_MAX_PRACH_FD_OCC_IN_A_SLOT_8
+} fapi_prachMaxFdOccasionsPerSlot_t;
+
+// Measurement Parameters
+#define FAPI_RSSI_REPORT_IN_DBM_MASK                0x01
+#define FAPI_RSSI_REPORT_IN_DBFS_MASK               0x02
+
+// CONFIGURATION INFORMATION CARRIER CONFIGURATION BANDWIDTH
+#define FAPI_BANDWIDTH_5_MHZ                          5
+#define FAPI_BANDWIDTH_10_MHZ                        10
+#define FAPI_BANDWIDTH_15_MHZ                        15
+#define FAPI_BANDWIDTH_20_MHZ                        20
+#define FAPI_BANDWIDTH_25_MHZ                        25
+#define FAPI_BANDWIDTH_30_MHZ                        30
+#define FAPI_BANDWIDTH_40_MHZ                        40
+#define FAPI_BANDWIDTH_50_MHZ                        50
+#define FAPI_BANDWIDTH_60_MHZ                        60
+#define FAPI_BANDWIDTH_70_MHZ                        70
+#define FAPI_BANDWIDTH_80_MHZ                        80
+#define FAPI_BANDWIDTH_90_MHZ                        90
+#define FAPI_BANDWIDTH_100_MHZ                      100
+#define FAPI_BANDWIDTH_200_MHZ                      200
+#define FAPI_BANDWIDTH_400_MHZ                      400
+
+#define FAPI_SUBCARRIER_SPACING_15                  0
+#define FAPI_SUBCARRIER_SPACING_30                  1
+#define FAPI_SUBCARRIER_SPACING_60                  2
+#define FAPI_SUBCARRIER_SPACING_120                 3
+
+#define FAPI_FFT_SIZE_512                          512
+#define FAPI_FFT_SIZE_1024                         1024
+#define FAPI_FFT_SIZE_2048                         2048
+#define FAPI_FFT_SIZE_4096                         4096
+// Frequency needs to track 38.104 Section 5.2 and 38.211 Section 5.3.1
+// Lower Bound KHz
+#define FAPI_MIN_FREQUENCY_PT_A                     450000
+// Upper Bound KHz
+#define FAPI_MAX_FREQUENCY_PT_A                     52600000
+// dlk0, ulk0 per 38.211 Section 5.3.1
+// Upper Bound
+#define FAPI_K0_MAX                                 23699
+// dlGridSize, ulGridSize per 38.211 Section 4.4.2
+// Upper Bound
+#define FAPI_GRIDSIZE_MAX                           275
+// Number of Transmit Antennas
+// Define upper mask based on variable type
+#define FAPI_NUM_ANT_MASK                           0xffff
+// CELL CONFIGURATION
+// Physical Cell ID from 38.211 Section 7.4.2.1
+// Upper Bound
+#define FAPI_MAX_CELL_ID                            1007
+// SSB CONFIGURATION
+// SSB POWER RANGE in dBm
+#define FAPI_SS_PBCH_LOWEST_POWER                   -60
+#define FAPI_SS_PBCH_MAX_POWER                      50
+// BCH PAYLOAD  for 5G the MAC always generates the BCH Payload
+#define FAPI_BCH_PAYLOAD_GEN_BY_MAC                 0
+#define FAPI_BCH_PAYLOAD_WITH_PHY_GEN_TIMING        1
+#define FAPI_BCH_PAYLOAD_ENTIRELY_GEN_BY_PHY        2
+// ScsCommon
+#define FAPI_SCSCOMMON_MASK                         0x03
+// PRACH CONFIGURATION
+#define FAPI_PRACH_LONG_SEQUENCE                    0
+#define FAPI_PRACH_SHORT_SEQUENCE                   1
+#define FAPI_PRACH_SUBC_SPACING_MAX                 4
+// Restricted Set Configuration
+#define FAPI_PRACH_RESTRICTED_SET_UNRESTRICTED      0
+#define FAPI_PRACH_RESTRICTED_SET_TYPE_A            1
+#define FAPI_PRACH_RESTRICTED_SET_TYPE_B            2
+// Root Sequence Index
+// Upper Bound
+#define FAPI_PRACH_ROOT_SEQ_INDEX_MAX               837
+// k1
+// Upper Bound
+#define FAPI_K1_UPPER_BOUND                         272
+// PRACH Zero Corr Configuration
+// Upper Bound
+#define FAPI_PRACHZEROCORRCONF_MASK                 0x0f
+// Number of Unused Root Sequences Mask
+#define FAPI_UNUSEDROOTSEQUENCES_MASK               0x0f
+// SSBPERRACH
+typedef enum {
+    FAPI_SSB_PER_RACH_1_OVER_8 = 0,
+    FAPI_SSB_PER_RACH_1_OVER_4,
+    FAPI_SSB_PER_RACH_1_OVER_2,
+    FAPI_SSB_PER_RACH_1,
+    FAPI_SSB_PER_RACH_2,
+    FAPI_SSB_PER_RACH_4,
+    FAPI_SSB_PER_RACH_8,
+    FAPI_SSB_PER_RACH_16
+} fapiSsbPerRach_t;
+
+typedef enum {
+    FAPI_PUCCH_FORMAT_TYPE_0 = 0,
+    FAPI_PUCCH_FORMAT_TYPE_1,
+    FAPI_PUCCH_FORMAT_TYPE_2,
+    FAPI_PUCCH_FORMAT_TYPE_3,
+    FAPI_PUCCH_FORMAT_TYPE_4,
+} nr5g_fapi_uci_format_t;
+
+typedef struct {
+    uint8_t group_id;
+    uint16_t initial_cyclic_shift;
+    uint8_t nr_of_symbols;
+    uint8_t start_symbol_index;
+    uint8_t time_domain_occ_idx;
+} nr5g_fapi_pucch_resources_t;
+// SSB Table
+// Ssb Offset Point A max
+#define FAPI_SSB_OFFSET_POINTA_MAX                  2199
+// betaPSS  i.e. PSS EPRE to SSS EPRE in a SS/PBCH Block per 38.213 Section 4.1
+#define FAPI_BETAPSS_0_DB                           0
+#define FAPI_BETAPSS_3_DB                           1
+// SSB Period in ms
+#define FAPI_SSB_PERIOD_5_MS                        0
+#define FAPI_SSB_PERIOD_10_MS                       1
+#define FAPI_SSB_PERIOD_20_MS                       2
+#define FAPI_SSB_PERIOD_40_MS                       3
+#define FAPI_SSB_PERIOD_80_MS                       4
+#define FAPI_SSB_PERIOD_160_MS                      5
+// Ssb Subcarrier Offset    per 38.211 Section 7.4.3.1
+// SsbSubcarrierOffset mask
+#define FAPI_SSB_SUBCARRIER_OFFSET_MASK             0x1f
+// MIB PAYLOAD MASK
+#define MIB_PAYLOAD_MASK                            0xfff0
+// BEAM ID MASK
+#define FAPI_BEAM_ID_MASK                           0x3f
+// TDD Table
+// TDD Period
+#define FAPI_TDD_PERIOD_0_P_5_MS                        0
+#define FAPI_TDD_PERIOD_0_P_625_MS                      1
+#define FAPI_TDD_PERIOD_1_MS                            2
+#define FAPI_TDD_PERIOD_1_P_25_MS                       3
+#define FAPI_TDD_PERIOD_2_MS                            4
+#define FAPI_TDD_PERIOD_2_P_5_MS                        5
+#define FAPI_TDD_PERIOD_5_MS                            6
+#define FAPI_TDD_PERIOD_10_MS                           7
+// Slot Configuration
+#define FAPI_DL_SLOT                                    0
+#define FAPI_UL_SLOT                                    1
+#define FAPI_GUARD_SLOT                                 2
+// Measurement configuration
+#define FAPI_NO_RSSI_REPORTING                          0
+#define FAPI_RSSI_REPORTED_IN_DBM                       1
+#define FAPI_RSSI_REPORTED_IN_DBFS                      2
+// Error Indication
+#define FAPI_SFN_MASK                                   0x03ff
+// Status and Error Codes for either .response or ERROR.indication
+// Updated per 5g FAPI Table 3-31
+typedef enum {
+    MSG_OK = 0,
+    MSG_INVALID_STATE,
+    MSG_INVALID_CONFIG,
+    SFN_OUT_OF_SYNC,
+    MSG_SLOT_ERR,
+    MSG_BCH_MISSING,
+    MSG_INVALID_SFN,
+    MSG_UL_DCI_ERR,
+    MSG_TX_ERR
+} fapiStatusAndErrorCodes_e;
+
+ // Digital Beam Table (DBT) PDU
+ // Number of Digital Beam Mask
+ // Number of TX RUS Mask
+ // Beam Index Mask
+ // Digital Beam Index weights Real and Imaginary Mask
+
+ // Precoding Matrix (PM) PDU
+ // Precoding Matrix ID Mask
+ // Number of Layers Mask
+ // Number of Antenna Ports at the precoder output Mask
+ // Precoder Weights Real and Imaginary Mask
+#define FAPI_U16_MASK                                  0xffff
+
+ // Slot Indication
+
+#define FAPI_SLOT_MAX_VALUE                            159
+
+ // DL_TTI.request
+ // nPDUS mask
+ // nGroup mask
+#define FAPI_U8_MASK                                   0xff
+
+typedef enum {
+    FAPI_DL_TTI_REQ_PDCCH_PDU_TYPE = 0,
+    FAPI_DL_TTI_REQ_PDSCH_PDU_TYPE,
+    FAPI_DL_TTI_REQ_CSI_RS_PDU_TYPE,
+    FAPI_DL_TTI_REQ_SSB_PDU_TYPE
+} fapiDlTtiReqPduType_e;
+
+// nUe
+// Define Maximum number of Ues per Group
+#define FAPI_MAX_NUMBER_OF_UES_PER_GROUP                12
+
+// PDCCH PDU
+#define FAPI_BWPSIZE_MAX                                275
+#define FAPI_BWPSIZE_START_MAX                          274
+#define FAPI_SUBCARRIER_SPACING_MAX                     4
+#define FAPI_CYCLIC_PREFIX_NORMAL                       0
+#define FAPI_CYCLIC_PREFIX_EXTENDED                     1
+#define FAPI_MAX_SYMBOL_START_INDEX                     13
+
+#define FAPI_CORESET_DURATION_1_SYMBOL                  1
+#define FAPI_CORESET_DURATION_2_SYMBOLS                 2
+#define FAPI_CORESET_DURATION_3_SYMBOLS                 3
+
+#define FAPI_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED       0
+#define FAPI_CCE_REG_MAPPING_TYPE_INTERLEAVED           1
+#define FAPI_REG_BUNDLE_SIZE_2                          2
+#define FAPI_REG_BUNDLE_SIZE_3                          3
+#define FAPI_REG_BUNDLE_SIZE_6                          6
+
+#define FAPI_INTERLEAVER_SIZE_2                         2
+#define FAPI_INTERLEAVER_SIZE_3                         3
+#define FAPI_INTERLEAVER_SIZE_6                         6
+
+#define FAPI_CORESET_TYPE_0_CONF_BY_PBCH_OR_SIB1        0
+#define FAPI_CORESET_TYPE_1                             1
+
+#define FAPI_PREC_GRANULARITY_SAME_AS_REG_BUNDLE        0
+#define FAPI_PREC_GRANULARITY_ALL_CONTIG_RBS            1
+
+#define FAPI_CCE_INDEX_MAX                              135
+#define FAPI_PDCCH_AGG_LEVEL_1                          1
+#define FAPI_PDCCH_AGG_LEVEL_2                          2
+#define FAPI_PDCCH_AGG_LEVEL_4                          4
+#define FAPI_PDCCH_AGG_LEVEL_8                          8
+#define FAPI_PDCCH_AGG_LEVEL_16                         16
+
+#define FAPI_BETA_PDCCH_1_0_MAX                         17
+
+#define FAPI_POWER_CTRL_OFF_SS_MINUS_3_DB               0
+#define FAPI_POWER_CTRL_OFF_SS_0_DB                     1
+#define FAPI_POWER_CTRL_OFF_SS_3_DB                     2
+#define FAPI_POWER_CTRL_OFF_SS_6_DB                     3
+
+#define FAPI_MAX_NUMBER_OF_CODEWORDS                    2
+
+#define FAPI_MAX_MCS_INDEX                              31
+#define FAPI_MCS_INDEX_MASK                             0x1f
+
+#define FAPI_MCS_TABLE_NOT_QAM_256                      0
+#define FAPI_MCS_TABLE_QAM_256                          1
+#define FAPI_MCS_TABLE_QAM_64_LOW_SE                    2
+
+#define FAPI_REDUNDANCY_INDEX_MASK                      0x03
+#define FAPI_MAX_DL_LAYERS                              8
+#define FAPI_MAX_UL_LAYERS                              4
+//#define FAPI_MAX_DMRS_PORTS                             12
+#define FAPI_MAX_DMRS_PORTS                             MAX_DL_PER_UE_DMRS_PORT_NUM
+#define FAPI_MAX_PTRS_PORTS                             12
+
+#define FAPI_TRANSMISSION_SCHEME_1                      1
+
+#define FAPI_REF_POINT_FOR_PDSCH_DMRS_AT_PT_A           0
+#define FAPI_REF_POINT_FOR_PDSCH_DMRS_AT_LOWEST_ALLOC   1
+
+#define FAPI_DL_DMRS_SYMB_POS_MASK                      0x3fff
+
+#define FAPI_MAX_DMRS_CDM_GRPS_WO_DATA                  3
+
+#define FAPI_DMRS_PORTS_MASK                            0x0fff
+
+#define FAPI_RES_ALLOC_TYPE_0                           0
+#define FAPI_RES_ALLOC_TYPE_1                           1
+
+#define FAPI_VRB_TO_PRB_MAP_NON_INTERLVD                0
+#define FAPI_VRB_TO_PRB_MAP_INTERLVD_RB_SIZE_2          1
+#define FAPI_VRB_TO_PRB_MAP_INTERLVD_RB_SIZE_4          2
+
+#define FAPI_MAX_START_SYMBOL_INDEX                     13
+#define FAPI_MAX_NR_OF_SYMBOLS                          14
+#define FAPI_PTRS_PORT_INDEX_MASK                       0x3f
+#define FAPI_PTRS_TIME_DENSITY_1                        0
+#define FAPI_PTRS_TIME_DENSITY_2                        1
+#define FAPI_PTRS_TIME_DENSITY_4                        2
+#define FAPI_PTRS_FREQ_DENSITY_2                        0
+#define FAPI_PTRS_FREQ_DENSITY_4                        1
+#define FAPI_PTRS_RE_OFFSET_MASK                        0x03
+#define FAPI_EPRE_RATIO_PDSCH_PTRS_MASK                 0x03
+// PDSCH Power Control Offset
+#define FAPI_PWR_CTRL_OFFSET_MINUS_8_DB                 0
+#define FAPI_PWR_CTRL_OFFSET_MINUS_7_DB                 1
+#define FAPI_PWR_CTRL_OFFSET_MINUS_6_DB                 2
+#define FAPI_PWR_CTRL_OFFSET_MINUS_5_DB                 3
+#define FAPI_PWR_CTRL_OFFSET_MINUS_4_DB                 4
+#define FAPI_PWR_CTRL_OFFSET_MINUS_3_DB                 5
+#define FAPI_PWR_CTRL_OFFSET_MINUS_2_DB                 6
+#define FAPI_PWR_CTRL_OFFSET_MINUS_1_DB                 7
+#define FAPI_PWR_CTRL_OFFSET_0_DB                       8
+#define FAPI_PWR_CTRL_OFFSET_1_DB                       9
+#define FAPI_PWR_CTRL_OFFSET_2_DB                       10
+#define FAPI_PWR_CTRL_OFFSET_3_DB                       11
+#define FAPI_PWR_CTRL_OFFSET_4_DB                       12
+#define FAPI_PWR_CTRL_OFFSET_5_DB                       13
+#define FAPI_PWR_CTRL_OFFSET_6_DB                       14
+#define FAPI_PWR_CTRL_OFFSET_7_DB                       15
+#define FAPI_PWR_CTRL_OFFSET_8_DB                       16
+#define FAPI_PWR_CTRL_OFFSET_9_DB                       17
+#define FAPI_PWR_CTRL_OFFSET_10_DB                      18
+#define FAPI_PWR_CTRL_OFFSET_11_DB                      19
+#define FAPI_PWR_CTRL_OFFSET_12_DB                      20
+#define FAPI_PWR_CTRL_OFFSET_13_DB                      21
+#define FAPI_PWR_CTRL_OFFSET_14_DB                      22
+#define FAPI_PWR_CTRL_OFFSET_15_DB                      23
+// Power Control Offset SS
+#define FAPI_PWR_CTRL_OFFSET_SS_MINUS_3_DB              0
+#define FAPI_PWR_CTRL_OFFSET_SS_0_DB                    1
+#define FAPI_PWR_CTRL_OFFSET_SS_3_DB                    2
+#define FAPI_PWR_CTRL_OFFSET_SS_6_DB                    3
+// CSI Type
+#define FAPI_CSI_TRS                                    0
+#define FAPI_CSI_NON_ZERO_POWER                         1
+#define FAPI_CSI_ZERO_POWER                             2
+// Row entry into CSI Resource Location Table
+#define FAPI_CSIRLT_ROW_MAX_VALUE                       18
+#define FAPI_CSI_FREQ_DOMAIN_MASK                       0x0fff
+#define FAPI_CSI_SYMB_L1_MIN                            2
+#define FAPI_CSI_SYMB_L1_MAX                            12
+// CDM Type
+#define FAPI_CDM_TYPE_NO_CDM                            0
+#define FAPI_CDM_TYPE_FD_CDM                            1
+#define FAPI_CDM_TYPE_CDM4_FD2_TD2                      2
+#define FAPI_CDM_TYPE_CDM8_FD2_TD4                      3
+// Frequency Density
+#define FAPI_FD_DOT5_EVEN_RB                            0
+#define FAPI_FD_DOT5_ODD_RB                             1
+#define FAPI_FD_ONE                                     2
+#define FAPI_FD_THREE                                   3
+
+// SSB
+#define FAPI_SSB_BLOCK_INDEX_MASK                       0x3f
+#define FAPI_SSB_SC_OFFSET_MASK                         0x1f
+
+// UL TTI REQUEST
+#define FAPI_MAX_NUM_UE_GROUPS_INCLUDED                 8
+#define FAPI__MAX_NUM_UE_IN_GROUP                       6
+// PRACH PDU
+#define FAPI_MAX_NUM_PRACH_OCAS                         7
+// PRACH FORMAT
+#define FAPI_PRACH_FORMAT_A1                            0
+#define FAPI_PRACH_FORMAT_A2                            1
+#define FAPI_PRACH_FORMAT_A3                            2
+#define FAPI_PRACH_FORMAT_B1                            3
+#define FAPI_PRACH_FORMAT_B2                            4
+#define FAPI_PRACH_FORMAT_B3                            5
+#define FAPI_PRACH_FORMAT_B4                            6
+#define FAPI_PRACH_FORMAT_C0                            7
+#define FAPI_PRACH_FORMAT_C2                            8
+
+#define FAPI_MAX_PRACH_FD_OCCASION_INDEX                7
+#define FAPI_MAX_ZC_ZONE_CONFIG_NUMBER                  419
+
+// PUSCH PDU
+#define FAPI_PUSCH_BIT_DATA_PRESENT_MASK                0x0001
+#define FAPI_PUSCH_UCI_DATA_PRESENT_MASK                0x0002
+#define FAPI_PUSCH_PTRS_INCLUDED_FR2_MASK               0x0004
+#define FAPI_PUSCH_DFTS_OFDM_TX_MASK                    0x0008
+
+#define FAPI_MAX_QAM_MOD_ORDER                          8
+#define FAPI_MCS_INDEX_MASK                             0x1f
+
+#define FAPI_MCS_TABLE_NOT_QAM256                       0
+#define FAPI_MCS_TABLE_QAM256                           1
+#define FAPI_MCS_TABLE_QAM64_LOWSE                      2
+#define FAPI_MCS_TABLE_NOT_QAM256_W_XFRM_PRECOD         3
+#define FAPI_MCS_TABLE_QAM64_LOWSE_W_XFRM_PRECOD        4
+#define FAPI_PUSCH_MAX_NUM_LAYERS                       4
+// DMRS
+#define FAPI_UL_DMRS_SYMB_POS_MASK                      0x3fff
+#define FAPI_UL_DMRS_CONFIG_TYPE_1                      0
+#define FAPI_UL_DMRS_CONFIG_TYPE_2                      1
+#define FAPI_MAX_DMRS_CDM_GRPS_NO_DATA                  3
+#define FAPI_UL_DMRS_PORTS_MASK                         0x07ff
+#define FAPI_UL_TX_DIRECT_CURR_LOCATION_MAX             3299
+#define FAPI_UL_TX_DIRECT_CURR_LOC_OUTSIDE_CARRIER      3300
+#define FAPI_UL_TX_DIRECT_CURR_LOC_UNDETERMINED         3301
+// PUSCH DATA
+#define FAPI_RV_INDEX_MASK                              0x03
+#define FAPI_HARQ_PROCESS_ID_MASK                       0x0f
+// PUSCH UCI INFO
+#define FAPI_HARQ_ACK_CSI_PX_BIT_LEN_SMALL_BLOCK_MAX    11
+#define FAPI_HARQ_ACK_CSI_PX_BIT_LEN_POLAR_MAX          1706
+// ALPHA SCALING
+#define FAPI_ALPHA_SCALE_0_5                            0
+#define FAPI_ALPHA_SCALE_0_65                           1
+#define FAPI_ALPHA_SCALE_0_8                            2
+#define FAPI_ALPHA_SCALE_1_0                            3
+// BETA OFFSET HARQ ACK
+#define FAPI_BETA_OFFSET_HARQ_ACK_MAX                   15
+#define FAPI_BETA_OFFSET_CSIX_MAX                       18
+
+// PUSCH PTRS INFORMATION 38.212 Section 7.3.1.1.2
+#define FAPI_MAX_NUMBER_PTRS_PORT_INDEX                 11  // 0..11
+// UL PTRS POWER 5G FAPI Table 3-49
+#define FAPI_UL_PTRS_PWR_0_DB                           0
+#define FAPI_UL_PTRS_PWR_3_DB                           1
+#define FAPI_UL_PTRS_PWR_4_77_DB                        2
+#define FAPI_UL_PTRS_PWR_6_DB                           3
+// DFTSOFDM INFO 5g FAPI Table 3-50
+#define FAPI_MAX_LOW_PAPR_GROUP_NUMBER                  29  // 0..29
+#define FAPI_MAX_LOW_PAPR_SEQ_NUMBER                    87  // 3*LOW_PAPR_GRP_NUM
+#define FAPI_MAX_UL PTRS_SAMP_DENSITY                   8
+#define FAPI_MAX_UL_PTRS_TD_XFRM_PRECOD                 4
+
+// PUCCH PDU Table 3-51
+#define FAPI_MAX_PUCCH_FORMAT_TYPE                      4
+#define FAPI_MULTI_SLOT_TX_IND_NO_MULTI_SLOT            0
+#define FAPI_MULTI_SLOT_TX_IND_TX_START                 1
+#define FAPI_MULTI_SLOT_TX_IND_TX_CONT                  2
+#define FAPI_MULTI_SLOT_TX_IND_TX_END                   3
+#define FAPI_MAX_NUM_PRB_FOR_A_PUCCH                    16
+#define FAPI_MAX_PUCCH_DUR_F0_AND_F2                    2
+#define FAPI_MIN_PUCCH_DUR_F1_F3_F4                     4
+#define FAPI_MAX_PUCCH_DUR_F1_F3_F4                     14
+#define FAPI_MAX_INIT_CYCLIC_SHIFT_F0_F1_F3_F4          11
+#define FAPI_MAX_OCC_INDEX_F1                           6
+#define FAPI_MAX_PRE_DFT_OCC_IDX_F4                     3
+#define FAPI_MAX_PRE_DFT_OCC_LEN_F4                     4
+#define FAPI_MAX_DMRS_CYC_SHIFT_F4                      9
+#define FAPI_BIT_LEN_HARQ_PL_ZERO                       0
+#define FAPI_BIT_LEN_HARQ_PL_F0_F1_2_BITS               1
+#define FAPI_BIT_LEN_HARQ_PL_F2_F3_F4_1706_BITS         2
+#define FAPI_BIT_LEN_CSI_PX_PL_NO_CSI                   0
+#define FAPI_BIT_LEN_CSI_PX_PL_1706_BITS                1
+
+// SRS PDU
+#define FAPI_1_SRS_ANT_PORT                             0
+#define FAPI_2_SRS_ANT_PORTS                            1
+#define FAPI_4_SRS_ANT_PORTS                            2
+#define FAPI_SRS_NO_REPETITIONS                         0
+#define FAPI_SRS_2_REPETITIONS                          2
+#define FAPI_SRS_4_REPETITIONS                          4
+#define FAPI_SRS_CONFIG_INDEX_MASK                      0x3f
+#define FAPI_SRS_BW_INDEX_MASK                          0x03
+#define FAPI_TX_COMB_SIZE_2                             0
+#define FAPI_TX_COMB_SIZE_4                             1
+#define FAPI_MAX_SRS_FREQ_POSITION                      67
+#define FAPI_MAX_SRS_FD_SHIFT                           268
+#define FAPI_SRS_FREQ_HOPPING_MASK                      0x03
+#define FAPI_SRS_NO_HOPPING                             0
+#define FAPI_SRS_GRP_OR_SEQ_HOPPING                     1
+#define FAPI_SRS_SEQ_HOPPING                            2
+#define FAPI_SRS_RES_ALLOC_APERIODIC                    0
+#define FAPI_SRS_RES_ALLOC_SEMI_PERSISTENT              1
+#define FAPI_SRS_RES_ALLOC_PERIODIC                     2
+#define FAPI_MAX_LSOT_OFFSET_VALUE                      2559
+
+// RX_DATA Indication
+#define FAPI_UL_CQI_INVALID                             255
+#define FAPI_TIMING_ADVANCE_INVALID                     0xffff
+#define FAPI_MAX_TIMING_ADVANCE                         63
+#define FAPI_MAX_RSSI                                   1280
+
+// RACH Indication
+#define FAPI_RACH_FREQ_INDEX_MAX                        7
+#define FAPI_RACH_DETECTED_PREAMBLES_MASK               0x3f
+#define FAPI_RACH_TIMING_ADVANCE_MAX                    3846
+#define FAPI_RACH_PREAMBLE_POWER_INVALID                0xffffffff
+#define FAPI_RACH_PREAMBLE_TIMING_ADVANCE_INVALID       0xffff
+#define FAPI_RACH_PREAMBLE_POWER_MAX                    170000
+
+// SR, HARQ, and CSI Part 1/2 PDUs Table 3-66
+#define FAPI_SR_MASK                                    0x01
+#define FAPI_HARQ_MASK                                  0x02
+#define FAPI_CSI_PART1                                  0x04
+#define FAPI_CSI_PART2                                  0x08
+#define FAPI_PUCCH_FORMAT2                              0
+#define FAPI_PUCCH_FORMAT3                              1
+#define FAPI_PUCCH_FORMAT4                              2
+#define FAPI_PUCCH_FORMAT_MASK                          0x03
+
+// SR PDU For Format 0 or 1 Table 3-67
+#define FAPI_SR_CONFIDENCE_LEVEL_GOOD                   0
+#define FAPI_SR_CONFIDENCE_LEVEL_BAD                    1
+#define FAPI_SR_CONFIDENCE_LEVEL_INVALID                0xff
+
+// HARQ PDU for Format 0 or 1 Table 3-68
+#define FAPI_HARQ_VALUE_PASS                            0
+#define FAPI_HARQ_VALUE_FAIL                            1
+#define FAPI_HARQ_VALUE_NOT_PRESENT                     2
+
+// SR PDU for Format 2,3 or 4 Table 3-69
+#define FAPI_SR_PAYLOAD_MAX                             1
+
+// HARQ PDU for Format 2,3 or 4 Table 3-70
+#define FAPI_HARQ_CRC_PASS                              0
+#define FAPI_HARQ_CRC_FAIL                              1
+#define FAPI_HARQ_CRC_NOT_PRESENT                       2
+#define FAPI_HARQ_PAYLOAD_MAX                           214
+
+// CSI Part 1 PDU Table 3-71 and 3-72
+#define FAPI_CSI_PARTX_CRC_PASS                         0
+#define FAPI_CSI_PARTX_CRC_FAIL                         1
+#define FAPI_CSI_PARTX_CRC_NOT_PRESENT                  2
+#define FAPI_CSI_PARTX_PAYLOAD_MAX                      214
+
+typedef enum {
+    MEM_STAT_CONFIG_REQ = 0,
+    MEM_STAT_START_REQ,
+    MEM_STAT_STOP_REQ,
+    MEM_STAT_SHUTDOWN_REQ,
+    MEM_STAT_DL_CONFIG_REQ,
+    MEM_STAT_UL_CONFIG_REQ,
+    MEM_STAT_UL_DCI_REQ,
+    MEM_STAT_TX_REQ,
+    MEM_STAT_DL_IQ_SAMPLES,
+    MEM_STAT_UL_IQ_SAMPLES,
+    MEM_STAT_DEFAULT,
+} _mem_stats_for_dl;
+
+#endif                          //_NR5G_FAPI_INTELNAL_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_log.h b/fapi_5g/source/include/nr5g_fapi_log.h
new file mode 100644 (file)
index 0000000..8c0a037
--- /dev/null
@@ -0,0 +1,79 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file consist of fapi logging macro.
+ *
+ **/
+
+#ifndef NR5G_FAPI_LOG_H_
+#define NR5G_FAPI_LOG_H_
+
+#define NR5G_FAPI_STATS_FNAME "FapiStats.txt"
+
+typedef enum _nr5g_fapi_log_types_t {
+    INFO_LOG = 0,
+    DEBUG_LOG,
+    ERROR_LOG,
+    TRACE_LOG,
+    HEXDUMP_LOG,
+    NONE_LOG                    // default
+} nr5g_fapi_log_types_t;
+
+extern nr5g_fapi_log_types_t nr5g_fapi_log_level_g;
+// get_logger_type_str is utility function, returns logging lever string.
+char *get_logger_type_str(
+    nr5g_fapi_log_types_t e);
+
+void nr5g_fapi_set_log_level(
+    nr5g_fapi_log_types_t new_level);
+
+nr5g_fapi_log_types_t nr5g_fapi_get_log_level(
+    );
+
+// NR5G_FAPI__LOG utility Macro for logging.
+#define NR5G_FAPI_LOG(TYPE, MSG) do { \
+    if(TYPE == ERROR_LOG) { \
+        printf("[NR5G_FAPI][%s]", get_logger_type_str(TYPE)); \
+        printf MSG ;\
+        printf("\n");\
+    }   \
+    else \
+    { \
+        if(nr5g_fapi_log_level_g == NONE_LOG) { \
+        }   \
+        else if(TYPE <= nr5g_fapi_log_level_g) { \
+            printf("[NR5G_FAPI][%s]", get_logger_type_str(TYPE)); \
+            printf MSG ;\
+            printf("\n");\
+        }   \
+        else if(TYPE <= nr5g_fapi_log_level_g && TYPE == DEBUG_LOG) { \
+            printf("[NR5G_FAPI][%s]", get_logger_type_str(TYPE)); \
+            printf MSG ;\
+            printf("\n");\
+        }   \
+        else if(TYPE == nr5g_fapi_log_level_g && TYPE == TRACE_LOG) { \
+            printf("[NR5G_FAPI][%s]", get_logger_type_str(TYPE)); \
+            printf MSG ;\
+            printf("\n");\
+        }   \
+        else {}\
+    } \
+} while(0)
+
+#endif                          // NR5G_FAPI_LOG_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_memory.h b/fapi_5g/source/include/nr5g_fapi_memory.h
new file mode 100644 (file)
index 0000000..0b877df
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file consist of fapi memory macro.
+ *
+ **/
+
+#ifndef NR5G_FAPI_MEM_H_
+#define NR5G_FAPI_MEM_H_
+
+#define NR5G_FAPI_MEMCPY(d, x, s, n) nr5g_fapi_memcpy_bound_check(d, x, s, n)
+#define NR5G_FAPI_MEMSET(s, x, c, n) nr5g_fapi_memset_bound_check(s, x, c, n)
+#define NR5G_FAPI_STRCPY(d, x, s, n) nr5g_fapi_strcpy_bound_check(d, x, s, n)
+
+inline uint8_t nr5g_fapi_memcpy_bound_check(
+    void *d,
+    size_t x,
+    const void *s,
+    size_t n);
+inline uint8_t nr5g_fapi_memset_bound_check(
+    void *s,
+    size_t x,
+    const int32_t c,
+    size_t n);
+inline uint8_t nr5g_fapi_strcpy_bound_check(
+    char *d,
+    size_t x,
+    const char *s,
+    size_t n);
+
+#endif                          // NR5G_FAPI_MEM_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_stats.h b/fapi_5g/source/include/nr5g_fapi_stats.h
new file mode 100644 (file)
index 0000000..41e0516
--- /dev/null
@@ -0,0 +1,41 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file consist of fapi logging macro.
+ *
+ **/
+
+#ifndef NR5G_FAPI_STATS_H_
+#define NR5G_FAPI_STATS_H_
+
+#include<sys/stat.h>
+#include <fcntl.h>
+#include<stdint.h>
+#include<stdio.h>
+#include "nr5g_fapi_framework.h"
+
+void nr5g_fapi_print_phy_instance_stats(
+    p_nr5g_fapi_phy_instance_t p_phy_instance);
+inline int nr5g_fapi_check_for_file_link(
+    char *fname);
+inline int nr5g_fapi_change_file_permission(
+    int fd,
+    mode_t mode);
+
+#endif                          // NR5G_FAPI_STATS_H_
diff --git a/fapi_5g/source/include/nr5g_fapi_std.h b/fapi_5g/source/include/nr5g_fapi_std.h
new file mode 100644 (file)
index 0000000..c4ac117
--- /dev/null
@@ -0,0 +1,36 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifndef _NR5G_FAPI_STD_H_
+#define _NR5G_FAPI_STD_H_
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sched.h>
+#include <unistd.h>
+#include <string.h>
+#include <math.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/stat.h>
+//#include <sys/types.h>
+
+#endif
diff --git a/fapi_5g/source/nr5g_fapi.c b/fapi_5g/source/nr5g_fapi.c
new file mode 100644 (file)
index 0000000..bfcb606
--- /dev/null
@@ -0,0 +1,59 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#include <pthread.h>
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_args.h"
+#include "nr5g_fapi_config_loader.h"
+#include "nr5g_fapi_dpdk.h"
+#include "nr5g_fapi_framework.h"
+#include "nr5g_fapi_cmd.h"
+
+int main(
+    int argc,
+    char **argv)
+{
+    const char *config_file = NULL;
+    p_nr5g_fapi_cfg_t config = NULL;
+
+    if (NULL == (config_file = nr5g_fapi_parse_args(argc, argv))) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("Config file parsing error"));
+        exit(1);
+    }
+
+    if (NULL == (config = nr5g_fapi_config_loader(argv[0], config_file))) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("Config file loading error"));
+        exit(1);
+    }
+
+    nr5g_fapi_dpdk_init(config);
+
+    if (FAILURE == nr5g_fapi_framework_init(config)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("ORAN_5G_FAPI init failed"));
+        exit(1);
+    }
+    NR5G_FAPI_LOG(INFO_LOG, ("ORAN_5G_FAPI init successful"));
+
+    nr5g_fapi_cmgr((void *)config);
+    nr5g_fapi_dpdk_wait(config);
+    pthread_attr_destroy(&config->phy2mac_thread_info.thread_attr);
+    pthread_attr_destroy(&config->mac2phy_thread_info.thread_attr);
+    free(config);
+    return 0;
+}
diff --git a/fapi_5g/source/utils/nr5g_fapi_args.c b/fapi_5g/source/utils/nr5g_fapi_args.c
new file mode 100644 (file)
index 0000000..552f472
--- /dev/null
@@ -0,0 +1,83 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#include "nr5g_fapi_args.h"
+#include <stddef.h>
+#include <getopt.h>
+
+static const char usage[] =
+    "                                                                               \n"
+    "    %s <APP PARAMS>                                                            \n"
+    "                                                                               \n"
+    "Application mandatory parameters:                                              \n"
+    "    --cfg FILE : configuration to load                                         \n"
+    "                                                                               \n"
+    "    --f FILE   : configuration to load                                         \n";
+
+/* display usage */
+static void nr5g_fapi_usage(
+    const char *prgname)
+{
+    printf(usage, prgname);
+}
+
+const char *nr5g_fapi_parse_args(
+    int argc,
+    char **argv)
+{
+    int opt;
+    int option_index;
+    const char *optname;
+    char *cfg_file = NULL;
+    char *prgname = argv[0];
+
+    static struct option lgopts[] = {
+        {"cfg", 1, 0, 0},
+        {NULL, 0, 0, 0}
+    };
+
+    while ((opt = getopt_long(argc, argv, "f", lgopts, &option_index)) != EOF) {
+        switch (opt) {
+            case 'f':
+                printf("short opts");
+                cfg_file = optarg;
+                break;
+
+                /* long options */
+            case 0:
+                printf("long opts");
+                optname = lgopts[option_index].name;
+                if (0 == strcmp(optname, "cfg")) {
+                    cfg_file = optarg;
+                }
+                break;
+
+            default:
+                nr5g_fapi_usage(prgname);
+                printf("in default");
+                return NULL;
+        }
+    }
+
+    if (cfg_file)
+        printf("config file: %s\n", cfg_file);
+    else
+        nr5g_fapi_usage(prgname);
+
+    return cfg_file;
+}
diff --git a/fapi_5g/source/utils/nr5g_fapi_cmd.c b/fapi_5g/source/utils/nr5g_fapi_cmd.c
new file mode 100644 (file)
index 0000000..6181ac9
--- /dev/null
@@ -0,0 +1,222 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @brief This file has the command line interface for the testmac application
+ * @file nr5g_fapi_cmd.c
+ * @ingroup group_source_utils
+ * @author Intel Corporation
+ **/
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_framework.h"
+#include "nr5g_fapi_wls.h"
+
+#define NUM_CMDS 5
+#define CMD_SIZE 32
+#define ORAN_5G_FAPI_LOGO "ORAN_5G_FAPI>"
+
+enum {
+    NR5G_FAPI_CMGR_HELP = 0,
+    NR5G_FAPI_CMGR_EXIT,
+    NR5G_FAPI_CMGR_VERS,
+    NR5G_FAPI_CMGR_WLS_STATS,
+    NR5G_FAPI_CMGR_NULL,
+};
+
+static char nr5g_fapi_cmd_registry[NUM_CMDS][CMD_SIZE] = {
+    {"help"}, {"exit"}, {"version"}, {"show wls stats"}
+};
+
+static char *nr5g_fapi_cmgr_char_get(
+    void)
+{
+    static char str[CMD_SIZE + 2];
+    int ch, n = 0;
+
+    while ((ch = getchar()) != EOF && n < CMD_SIZE && ch != '\n') {
+        str[n] = ch;
+        ++n;
+    }
+
+    if (n > 0 && n < CMD_SIZE) {
+        str[n] = (char)0;
+        return str;
+    } else {
+        return NULL;
+    }
+}
+
+static int nr5g_fapi_cmgr_type(
+    char *cmd)
+{
+    int len = 0, i;
+    for (i = 0; i < NUM_CMDS; i++) {
+        nr5g_fapi_cmd_registry[i][sizeof(nr5g_fapi_cmd_registry[i]) - 1] = 0;
+        len = strlen(nr5g_fapi_cmd_registry[i]);
+        if (len < CMD_SIZE) {
+            if (!strncmp(cmd, nr5g_fapi_cmd_registry[i], len)) {
+                return i;
+            }
+        }
+    }
+
+    return NR5G_FAPI_CMGR_NULL;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   paramc Number of command line parameters
+ *  @param[in]   params Pointer to structure that has the command line parameter
+ *  @param[in]   *cmd_param Pointer to additional parameters
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function prints the oran_5g_fapi version to the oran_5g_fapi console
+ *
+**/
+//-------------------------------------------------------------------------------------------
+static void nr5g_fapi_cmd_print_version(
+    )
+{
+    //printf("\n ORAN_5G_FAPI Version: \n");
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   paramc Number of command line parameters
+ *  @param[in]   params Pointer to structure that has the command line parameter
+ *  @param[in]   *cmd_param Pointer to additional parameters
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function exits the testmac application
+ *
+**/
+//-------------------------------------------------------------------------------------------
+static void nr5g_fapi_cmd_exit(
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx)
+{
+    p_phy_ctx->process_exit = 0;
+    printf("Exitting App...\n");
+    exit(0);
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   paramc Number of command line parameters
+ *  @param[in]   params Pointer to structure that has the command line parameter
+ *  @param[in]   *cmd_param Pointer to additional parameters
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function lists all the pre-registered function and associated commands on screen.
+ *  The commands are sorted alphabetically.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+static void nr5g_fapi_cmd_help(
+    )
+{
+
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   paramc Number of command line parameters
+ *  @param[in]   params Pointer to structure that has the command line parameter
+ *  @param[in]   *cmd_param Pointer to additional parameters
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function lists all the pre-registered function and associated commands on screen.
+ *  The commands are sorted alphabetically.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+static void nr5g_fapi_cmd_wls_stats(
+    )
+{
+    nr5g_fapi_wls_print_stats();
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function initializes all the pre-defined commands with associated functions for the testmac
+ *  application. It iscalled on system bootup
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void nr5g_fapi_cmgr(
+    void *config)
+{
+    static int process_exit = 1;
+    char *cmd;
+    int cmd_type;
+    UNUSED(config);
+    //p_nr5g_fapi_cfg_t cfg = (p_nr5g_fapi_cfg_t) config; // start up config
+    p_nr5g_fapi_phy_ctx_t p_phy_ctx = nr5g_fapi_get_nr5g_fapi_phy_ctx();
+
+    fflush(stdout);
+    printf("\n");
+    while (process_exit) {
+        printf("%s", ORAN_5G_FAPI_LOGO);
+
+        cmd = nr5g_fapi_cmgr_char_get();
+        if (!cmd)
+            continue;
+
+        cmd_type = nr5g_fapi_cmgr_type(cmd);
+        switch (cmd_type) {
+            case NR5G_FAPI_CMGR_VERS:
+                nr5g_fapi_cmd_print_version();
+
+                break;
+            case NR5G_FAPI_CMGR_HELP:
+                nr5g_fapi_cmd_help();
+                break;
+
+            case NR5G_FAPI_CMGR_EXIT:
+                nr5g_fapi_cmd_exit(p_phy_ctx);
+                break;
+
+            case NR5G_FAPI_CMGR_WLS_STATS:
+                nr5g_fapi_cmd_wls_stats();
+                break;
+
+            case NR5G_FAPI_CMGR_NULL:
+            default:
+                printf("Warning: command (%s) not present\n", cmd);
+                break;
+        }
+    }
+}
diff --git a/fapi_5g/source/utils/nr5g_fapi_config_loader.c b/fapi_5g/source/utils/nr5g_fapi_config_loader.c
new file mode 100644 (file)
index 0000000..2aa684b
--- /dev/null
@@ -0,0 +1,192 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#include "nr5g_fapi_config_loader.h"
+#include "nr5g_fapi_dpdk.h"
+#include "sched.h"
+
+#define NR5G_FAPI_MAX_SHMSIZE (2126512128)
+char *fgets_s(
+    char *string,
+    size_t len,
+    FILE * fp);
+
+p_nr5g_fapi_cfg_t nr5g_fapi_config_loader(
+    char *prgname,
+    const char *cfg_fname)
+{
+    struct rte_cfgfile *cfg_file;
+    p_nr5g_fapi_cfg_t cfg;
+    const char *entry;
+    size_t dev_name_len;
+    unsigned int num_cpus = 0;
+    char check_core_count[255], *max_core;
+    FILE *fp = NULL;
+
+    if (cfg_fname == NULL) {
+        printf("Error: Configuration filename was not passed.");
+        return NULL;
+    }
+
+    cfg_file = rte_cfgfile_load(cfg_fname, 0);
+    if (cfg_file == NULL) {
+        printf("Error: Cofiguration file loading failed.");
+        return NULL;
+    }
+
+    cfg = (p_nr5g_fapi_cfg_t) calloc(1, sizeof(nr5g_fapi_cfg_t));
+    if (!cfg) {
+        printf("Error: not enough memory in the system");
+        return NULL;
+    }
+    cfg->prgname = prgname;
+    fp = popen("cat /proc/cpuinfo | grep processor | wc -l", "r");
+    if (NULL == fp) {
+        printf("Error: In getting maximum number of lcores in the system.");
+        free(cfg);
+        return NULL;
+    }
+    max_core = fgets_s(check_core_count, 255, fp);
+    if (NULL == max_core) {
+        printf("Error: In getting maximum number of lcores in the system.");
+        free(cfg);
+        pclose(fp);
+        return NULL;
+    }
+    num_cpus = atoi(max_core);
+    entry = rte_cfgfile_get_entry(cfg_file, "MAC2PHY_WORKER", "core_id");
+    if (entry) {
+        cfg->mac2phy_worker.core_id = (uint8_t) atoi(entry);
+        if (cfg->mac2phy_worker.core_id >= (uint8_t) num_cpus) {
+            printf("Core Id is not in the range 0 to %d: configured: %d\n",
+                num_cpus, cfg->mac2phy_worker.core_id);
+            exit(-1);
+        }
+    }
+
+    entry =
+        rte_cfgfile_get_entry(cfg_file, "MAC2PHY_WORKER", "thread_sched_policy");
+    if (entry) {
+        cfg->mac2phy_worker.thread_sched_policy = (uint8_t) atoi(entry);
+        if (cfg->mac2phy_worker.thread_sched_policy != SCHED_FIFO &&
+            cfg->mac2phy_worker.thread_sched_policy != SCHED_RR) {
+            printf("Thread Poicy valid range is Schedule Policy [0: SCHED_FIFO"
+                " 1: SCHED_RR]: configured: %d\n",
+                cfg->mac2phy_worker.thread_sched_policy);
+            exit(-1);
+        }
+    }
+
+    int min_prio =
+        sched_get_priority_min(cfg->mac2phy_worker.thread_sched_policy);
+    int max_prio =
+        sched_get_priority_max(cfg->mac2phy_worker.thread_sched_policy);
+    entry =
+        rte_cfgfile_get_entry(cfg_file, "MAC2PHY_WORKER", "thread_priority");
+    if (entry) {
+        cfg->mac2phy_worker.thread_priority = (uint8_t) atoi(entry);
+        if (cfg->mac2phy_worker.thread_priority < min_prio &&
+            cfg->mac2phy_worker.thread_priority > max_prio) {
+            printf("Thread priority valid range is %d to %d: configured: %d\n",
+                min_prio, max_prio, cfg->mac2phy_worker.thread_priority);
+            exit(-1);
+        }
+    }
+
+    entry = rte_cfgfile_get_entry(cfg_file, "PHY2MAC_WORKER", "core_id");
+    if (entry) {
+        cfg->phy2mac_worker.core_id = (uint8_t) atoi(entry);
+        if (cfg->phy2mac_worker.core_id >= (uint8_t) num_cpus) {
+            printf("Core Id is not in the range 0 to %d configured: %d\n",
+                num_cpus, cfg->phy2mac_worker.core_id);
+            exit(-1);
+        }
+    }
+
+    entry =
+        rte_cfgfile_get_entry(cfg_file, "PHY2MAC_WORKER", "thread_sched_policy");
+    if (entry) {
+        cfg->phy2mac_worker.thread_sched_policy = (uint8_t) atoi(entry);
+        if (cfg->phy2mac_worker.thread_sched_policy != SCHED_FIFO &&
+            cfg->phy2mac_worker.thread_sched_policy != SCHED_RR) {
+            printf("Thread Poicy valid range is Schedule Policy [0: SCHED_FIFO"
+                " 1: SCHED_RR] configured: %d\n",
+                cfg->phy2mac_worker.thread_sched_policy);
+            exit(-1);
+        }
+    }
+
+    entry =
+        rte_cfgfile_get_entry(cfg_file, "PHY2MAC_WORKER", "thread_priority");
+    if (entry) {
+        cfg->phy2mac_worker.thread_priority = (uint8_t) atoi(entry);
+        if (cfg->phy2mac_worker.thread_priority < min_prio &&
+            cfg->phy2mac_worker.thread_priority > max_prio) {
+            printf("Thread priority valid range is %d to %d configured: %d\n",
+                min_prio, max_prio, cfg->phy2mac_worker.thread_priority);
+            exit(-1);
+        }
+    }
+
+    entry = rte_cfgfile_get_entry(cfg_file, "WLS_CFG", "device_name");
+    if (entry) {
+        dev_name_len = (strlen(entry) > (NR5G_FAPI_DEVICE_NAME_LEN)) ?
+            (NR5G_FAPI_DEVICE_NAME_LEN) : strlen(entry);
+        rte_strlcpy(cfg->wls.device_name, entry, dev_name_len + 1);
+    }
+
+    entry = rte_cfgfile_get_entry(cfg_file, "WLS_CFG", "shmem_size");
+    if (entry) {
+        cfg->wls.shmem_size = (uint64_t) atoll(entry);
+        if (cfg->wls.shmem_size > NR5G_FAPI_MAX_SHMSIZE) {
+            printf("The memory range cannot exceed %d", NR5G_FAPI_MAX_SHMSIZE);
+            exit(-1);
+        }
+    }
+
+    entry = rte_cfgfile_get_entry(cfg_file, "LOGGER", "level");
+    if (entry) {
+        if (!strcmp(entry, "info"))
+            cfg->logger.level = INFO_LOG;
+        else if (!strcmp(entry, "debug"))
+            cfg->logger.level = DEBUG_LOG;
+        else if (!strcmp(entry, "error"))
+            cfg->logger.level = ERROR_LOG;
+        else if (!strcmp(entry, "trace"))
+            cfg->logger.level = TRACE_LOG;
+        else if (!strcmp(entry, "hexdump"))
+            cfg->logger.level = HEXDUMP_LOG;
+        else
+            cfg->logger.level = NONE_LOG;
+    }
+
+    pclose(fp);
+
+    return cfg;
+}
+
+char *fgets_s(
+    char *string,
+    size_t len,
+    FILE * fp)
+{
+    if (fgets(string, len, fp) != 0) {
+        string[strcspn(string, "\n")] = '\0';
+        return string;
+    }
+    return 0;
+}
diff --git a/fapi_5g/source/utils/nr5g_fapi_log.c b/fapi_5g/source/utils/nr5g_fapi_log.c
new file mode 100644 (file)
index 0000000..1d44055
--- /dev/null
@@ -0,0 +1,98 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file defines all the functions used for logging. 
+ *
+ **/
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_log.h"
+
+nr5g_fapi_log_types_t nr5g_fapi_log_level_g;
+
+//------------------------------------------------------------------------------
+/** @ingroup        group_lte_source_phy_api
+ *
+ *  @param[in]      FAPI log level
+ *
+ *  @return         String of log type
+ *
+ *  @description    The returns log level sring
+ *
+ **/
+//------------------------------------------------------------------------------
+char *get_logger_type_str(
+    nr5g_fapi_log_types_t e)
+{
+    switch (e) {
+        case INFO_LOG:
+            return ("INFO_LOG");
+
+        case DEBUG_LOG:
+            return ("DEBUG_LOG");
+
+        case ERROR_LOG:
+            return ("ERROR_LOG");
+
+        case TRACE_LOG:
+            return ("TRACE_LOG");
+
+        case HEXDUMP_LOG:
+            return ("HEXDUMP_LOG");
+
+        default:
+            printf("Log Error Type\n");
+            return ("");
+            //case NONE: Should never be reached.
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup        group_lte_source_phy_api
+ *
+ *  @param[in]      log level
+ *
+ *  @return         void
+ *
+ *  @description    The function sets log level
+ *
+ **/
+//------------------------------------------------------------------------------
+void nr5g_fapi_set_log_level(
+    nr5g_fapi_log_types_t new_level)
+{
+    nr5g_fapi_log_level_g = new_level;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup        group_lte_source_phy_api
+ *
+ *  @param[in]      void
+ *
+ *  @return         Log level
+ *
+ *  @description    The function returns log level.
+ *
+ **/
+//------------------------------------------------------------------------------
+nr5g_fapi_log_types_t nr5g_fapi_get_log_level(
+    )
+{
+    return nr5g_fapi_log_level_g;
+}
+
diff --git a/fapi_5g/source/utils/nr5g_fapi_memory.c b/fapi_5g/source/utils/nr5g_fapi_memory.c
new file mode 100644 (file)
index 0000000..fd14581
--- /dev/null
@@ -0,0 +1,113 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file defines all the functions used for 
+ * memory operations. 
+ *
+ **/
+
+#include <rte_memcpy.h>
+#include <string.h>
+#include "nr5g_fapi_wls.h"
+
+inline uint8_t nr5g_fapi_memcpy_bound_check(
+    void *d,
+    size_t x,
+    const void *s,
+    size_t n)
+{
+    // Memory block size and destination/source boundary check
+    if ((n >= (MSG_MAXSIZE)) || (n > x)) {
+        printf
+            ("[MEMCPY FAILED] %s : %d : max block size: %d, memcpy dst size: %ld, memcpy src size: %ld\n",
+            __func__, __LINE__, MSG_MAXSIZE, x, n);
+        return FAILURE;
+    }
+    // Overlap check: source pointer overruns destination pointer
+    if ((char *)s < (char *)d) {
+        if ((((char *)s + x) >= (char *)d) || (((char *)s + n) >= (char *)d)) {
+            printf("[MEMCPY FAILED] %s : %d : max block size: %d, \
+                    memcpy dst size: %ld, strcpy src size: %ld, \
+                    Source pointer %p overlaps into destination pointer %p\n", __func__, __LINE__, MSG_MAXSIZE, x, n, s, d);
+            return FAILURE;
+        }
+    }
+    // Overlap check: destination pointer overruns source pointer
+    if ((char *)d < (char *)s) {
+        if ((((char *)d + x) >= (char *)s) || (((char *)d + n) >= (char *)s)) {
+            printf("[MEMCPY FAILED] %s : %d : max block size: %d, \
+                    memcpy dst size: %ld, strcpy src size: %ld, \
+                    Destination pointer %p overlaps into source pointer %p\n", __func__, __LINE__, MSG_MAXSIZE, x, n, d, s);
+            return FAILURE;
+        }
+    }
+    rte_memcpy(d, s, n);
+    return SUCCESS;
+}
+
+inline uint8_t nr5g_fapi_memset_bound_check(
+    void *s,
+    size_t x,
+    int32_t c,
+    size_t n)
+{
+    // Memory block size and destination/source boundary check
+    if ((n >= MSG_MAXSIZE) || (n > x)) {
+        printf
+            ("[MEMSET FAILED] %s : %d : max block size: %d, memset dst size: %ld, memset src size: %ld\n",
+            __func__, __LINE__, MSG_MAXSIZE, x, n);
+        return FAILURE;
+    }
+    memset(s, c, n);
+    return SUCCESS;
+}
+
+inline uint8_t nr5g_fapi_strcpy_bound_check(
+    char *d,
+    size_t x,
+    const char *s,
+    size_t n)
+{
+    // Memory block size and destination/source boundary check
+    if ((n >= MSG_MAXSIZE) || (n > x)) {
+        printf("[STRNCPY FAILED] %s : %d : max block size: %d, \
+            strcpy dst size: %ld, strcpy src size: %ld\n", __func__, __LINE__, MSG_MAXSIZE, x, n);
+        return FAILURE;
+    }
+    // Overlap check: source pointer overruns destination pointer
+    if ((char *)s < (char *)d) {
+        if ((((char *)s + x) >= (char *)d) || (((char *)s + n) >= (char *)d)) {
+            printf("[STRNCPY FAILED] %s : %d : max block size: %d, \
+                    strcpy dst size: %ld, strcpy src size: %ld, \
+                    Source pointer %p overlaps into destination pointer %p\n", __func__, __LINE__, MSG_MAXSIZE, x, n, s, d);
+            return FAILURE;
+        }
+    }
+    // Overlap check: destination pointer overruns source pointer
+    if ((char *)d < (char *)s) {
+        if ((((char *)d + x) >= (char *)s) || (((char *)d + n) >= (char *)s)) {
+            printf("[STRNCPY FAILED] %s : %d : max block size: %d, \
+                    strcpy dst size: %ld, strcpy src size: %ld, \
+                    Destination pointer %p overlaps into source pointer %p\n", __func__, __LINE__, MSG_MAXSIZE, x, n, d, s);
+            return FAILURE;
+        }
+    }
+    strncpy(d, s, n);
+    return SUCCESS;
+}
diff --git a/fapi_5g/source/utils/nr5g_fapi_stats.c b/fapi_5g/source/utils/nr5g_fapi_stats.c
new file mode 100644 (file)
index 0000000..e3bae5d
--- /dev/null
@@ -0,0 +1,212 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file defines all the functions used for statistics. 
+ *
+ **/
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_stats.h"
+#include "nr5g_fapi_log.h"
+
+#define NR5G_FAPI_STATS_FNAME_LEN   64
+
+void nr5g_fapi_print_phy_instance_stats(
+    p_nr5g_fapi_phy_instance_t p_phy_instance)
+{
+    int fd = 0, ret_val;
+    FILE *fp = NULL;
+    enum { FILE_MODE = 0666 };
+    nr5g_fapi_stats_t *p_stats;
+    char *fname = NULL, stats_fname[NR5G_FAPI_STATS_FNAME_LEN];
+#ifdef DEBUG_MODE
+    uint32_t test_num;
+    uint32_t test_type;
+    char test_type_str[][8] = { {"DL"}, {"UL"}, {"FD"} };
+#endif
+
+    if (NULL == p_phy_instance) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI][STATS] Invalid "
+                "phy instance"));
+        return;
+    }
+#ifdef DEBUG_MODE
+    if (p_phy_instance->shutdown_test_type) {
+        test_num = p_phy_instance->shutdown_test_type & 0xFFFFFFF;
+        test_type = p_phy_instance->shutdown_test_type >> 28;
+        snprintf(stats_fname, NR5G_FAPI_STATS_FNAME_LEN,
+            "FapiStats_%s_%d.txt", test_type_str[test_type], test_num);
+        fname = stats_fname;
+    }
+#endif
+
+    if (!fname)
+        fname = NR5G_FAPI_STATS_FNAME;
+
+    ret_val = remove(fname);
+    if ((-1 == ret_val) && (ENOENT != errno)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("File %s delete not successful errno %d",
+                fname, errno));
+        perror("[Error] ");
+        return;
+    }
+
+    fd = open(fname, O_RDWR | O_CREAT | O_EXCL);
+    if (-1 == fd) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("Failed to open the file %s\n", fname));
+        perror("[Error] ");
+        return;
+    }
+
+    fp = fdopen(fd, "w");
+    if (NULL == fp) {
+        NR5G_FAPI_LOG(ERROR_LOG,
+            ("Failed to open the file %s from file descriptor\n", fname));
+        perror("[Error] ");
+
+        if (-1 == close(fd)) {
+            NR5G_FAPI_LOG(ERROR_LOG,
+                ("Failed to close the descriptor for file %s\n", fname));
+            perror("[Error] ");
+        }
+        return;
+    }
+
+    p_stats = &p_phy_instance->stats;
+    fprintf(fp, "5GNR FAPI instance statistics PhyId: %u\n",
+        p_phy_instance->phy_id);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "ParamReq",
+        p_stats->fapi_stats.fapi_param_req, 14, "ConfigReq",
+        p_stats->fapi_stats.fapi_config_req);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "StartReq",
+        p_stats->fapi_stats.fapi_start_req, 14, "StopReq",
+        p_stats->fapi_stats.fapi_stop_req);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "ParamResp",
+        p_stats->fapi_stats.fapi_param_res, 14, "ConfigResp",
+        p_stats->fapi_stats.fapi_config_res);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "stopInd",
+        p_stats->fapi_stats.fapi_stop_ind, 14, "vendorMsg",
+        p_stats->fapi_stats.fapi_vendor_msg);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReq",
+        p_stats->fapi_stats.fapi_dl_tti_req, 14, "ULTTIReq",
+        p_stats->fapi_stats.fapi_ul_tti_req);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "TxDataReq",
+        p_stats->fapi_stats.fapi_tx_data_req, 14, "ErrorInd",
+        p_stats->fapi_stats.fapi_error_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "ULDciReq",
+        p_stats->fapi_stats.fapi_ul_dci_req, 14, "SlotInd",
+        p_stats->fapi_stats.fapi_slot_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "CrcInd",
+        p_stats->fapi_stats.fapi_crc_ind, 14, "RxDataInd",
+        p_stats->fapi_stats.fapi_rx_data_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "UciInd",
+        p_stats->fapi_stats.fapi_uci_ind, 14, "SrsInd",
+        p_stats->fapi_stats.fapi_srs_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %u\n", 14, "RachInd",
+        p_stats->fapi_stats.fapi_rach_ind, 14, "ShutdownReq",
+        p_stats->fapi_stats.fapi_vext_shutdown_req);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %lu\n", 14, "ShutdownRes",
+        p_stats->fapi_stats.fapi_vext_shutdown_res, 14, "ULTTIReqPdus",
+        p_stats->fapi_stats.fapi_ul_tti_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "ULTTIReqPrach",
+        p_stats->fapi_stats.fapi_ul_tti_prach_pdus, 14, "ULTTIReqPusch",
+        p_stats->fapi_stats.fapi_ul_tti_pusch_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "ULTTIReqPucch",
+        p_stats->fapi_stats.fapi_ul_tti_pucch_pdus, 14, "ULTTIReqSrs",
+        p_stats->fapi_stats.fapi_ul_tti_srs_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReqPdus",
+        p_stats->fapi_stats.fapi_dl_tti_pdus, 14, "DLTTIReqPdsch",
+        p_stats->fapi_stats.fapi_dl_tti_pdsch_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReqPdcch",
+        p_stats->fapi_stats.fapi_dl_tti_pdcch_pdus, 14, "DLTTIReqSsb",
+        p_stats->fapi_stats.fapi_dl_tti_ssb_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReqCsiRs",
+        p_stats->fapi_stats.fapi_dl_tti_csi_rs_pdus, 14, "ULDCIReqPdus",
+        p_stats->fapi_stats.fapi_ul_dci_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "CrcIndPdus",
+        p_stats->fapi_stats.fapi_crc_ind_pdus, 14, "RxDataPdus",
+        p_stats->fapi_stats.fapi_rx_data_ind_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "UciIndPdus",
+        p_stats->fapi_stats.fapi_uci_ind_pdus, 14, "SrsIndPdus",
+        p_stats->fapi_stats.fapi_srs_ind_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t\n", 14, "RachPdus",
+        p_stats->fapi_stats.fapi_rach_ind_pdus);
+    fprintf(fp, "\n\n");
+
+    fprintf(fp, "5GNR L1 instance statistics PhyId: %u\n",
+        p_phy_instance->phy_id);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "ParamReq",
+        p_stats->iapi_stats.iapi_param_req, 14, "ConfigReq",
+        p_stats->iapi_stats.iapi_config_req);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "StartReq",
+        p_stats->iapi_stats.iapi_start_req, 14, "StopReq",
+        p_stats->iapi_stats.iapi_stop_req);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %u\n", 14, "StartRes",
+        p_stats->iapi_stats.iapi_start_res, 14, "StopInd",
+        p_stats->iapi_stats.iapi_stop_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DlConfigReq",
+        p_stats->iapi_stats.iapi_dl_config_req, 14, "UlConfigReq",
+        p_stats->iapi_stats.iapi_ul_config_req);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "TxReq",
+        p_stats->iapi_stats.iapi_tx_req, 14, "ErrorInd",
+        p_stats->iapi_stats.iapi_error_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "UlDciReq",
+        p_stats->iapi_stats.iapi_ul_dci_req, 14, "SlotInd",
+        p_stats->iapi_stats.iapi_slot_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "CrcInd",
+        p_stats->iapi_stats.iapi_crc_ind, 14, "RxDataInd",
+        p_stats->iapi_stats.iapi_rx_data_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "UciInd",
+        p_stats->iapi_stats.iapi_uci_ind, 14, "SrsInd",
+        p_stats->iapi_stats.iapi_srs_ind);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %u\n", 14, "RACHInd",
+        p_stats->iapi_stats.iapi_rach_ind, 14, "ShutdownReq",
+        p_stats->iapi_stats.iapi_shutdown_req);
+    fprintf(fp, "%*s: %u\t\t\t%*s: %lu\n", 14, "ShutdownRes",
+        p_stats->iapi_stats.iapi_shutdown_res, 14, "ULTTIReqPdus",
+        p_stats->iapi_stats.iapi_ul_tti_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "ULTTIReqPrach",
+        p_stats->iapi_stats.iapi_ul_tti_prach_pdus, 14, "ULTTIReqPusch",
+        p_stats->iapi_stats.iapi_ul_tti_pusch_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "ULTTIReqPucch",
+        p_stats->iapi_stats.iapi_ul_tti_pucch_pdus, 14, "ULTTIReqSrs",
+        p_stats->iapi_stats.iapi_ul_tti_srs_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReqPdus",
+        p_stats->iapi_stats.iapi_dl_tti_pdus, 14, "DLTTIReqPdsch",
+        p_stats->iapi_stats.iapi_dl_tti_pdsch_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReqPdcch",
+        p_stats->iapi_stats.iapi_dl_tti_pdcch_pdus, 14, "DLTTIReqSsb",
+        p_stats->iapi_stats.iapi_dl_tti_ssb_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "DLTTIReqCsiRs",
+        p_stats->iapi_stats.iapi_dl_tti_csi_rs_pdus, 14, "ULDCIReqPdus",
+        p_stats->iapi_stats.iapi_ul_dci_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "CrcIndPdus",
+        p_stats->iapi_stats.iapi_crc_ind_pdus, 14, "RxDataPdus",
+        p_stats->iapi_stats.iapi_rx_data_ind_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t%*s: %lu\n", 14, "UciIndPdus",
+        p_stats->iapi_stats.iapi_uci_ind_pdus, 14, "SrsIndPdus",
+        p_stats->iapi_stats.iapi_srs_ind_pdus);
+    fprintf(fp, "%*s: %lu\t\t\t\n", 14, "RachPreambles",
+        p_stats->iapi_stats.iapi_rach_preambles);
+    fprintf(fp, "\n");
+    if (EOF == fclose(fp)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("Unable to close the file\n"));
+    }
+    close(fd);
+}
+
index 62c370f..b8ef62b 100644 (file)
@@ -1,6 +1,21 @@
-###############################################################################
-# <COPYRIGHT_TAG>
-###############################################################################
+#/******************************************************************************
+#*
+#*   Copyright (c) 2019 Intel.
+#*
+#*   Licensed under the Apache License, Version 2.0 (the "License");
+#*   you may not use this file except in compliance with the License.
+#*   You may obtain a copy of the License at
+#*
+#*       http://www.apache.org/licenses/LICENSE-2.0
+#*
+#*   Unless required by applicable law or agreed to in writing, software
+#*   distributed under the License is distributed on an "AS IS" BASIS,
+#*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#*   See the License for the specific language governing permissions and
+#*   limitations under the License.
+#*
+#*******************************************************************************/
+
 
 .SUFFIXES: .o .c .s .i .cpp
 
diff --git a/wls_lib/Makefile b/wls_lib/Makefile
new file mode 100644 (file)
index 0000000..865c618
--- /dev/null
@@ -0,0 +1,69 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+ifdef DPDK_WLS
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-icc
+RTE_OUTPUT = ${PWD}
+
+include $(RTE_SDK)/mk/rte.vars.mk
+SRCS-y := wls_lib_dpdk.c syslib.c
+SHARED = libwls.so
+#CFLAGS +=-Wall -wd9 -DDPDK_WLS
+CFLAGS +=-Wall -DDPDK_WLS -fstack-protector
+EXTRA_CFLAGS +=-g
+include $(RTE_SDK)/mk/rte.extshared.mk
+
+else
+
+obj-m := wls.o
+wls-objs :=syslib.o \
+          wls_drv.o
+
+INSTALL_MOD_DIR ?=/lib/modules/`uname -r`/updates/drivers/intel/wls
+cmd_depmod = /sbin/depmod -a
+EXTRA_CFLAGS +=-g -Wall
+SRC := $(shell pwd)
+
+all:
+       $(MAKE) -C $(KERNEL_SRC) $(EXTRA_CFLAGS) M=$(SRC)
+
+modules_install:
+       $(MAKE) -C $(KERNEL_SRC) $(EXTRA_CFLAGS) M=$(SRC) modules_install
+
+wls_lib.o: wls_lib.c
+       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D_GNU_SOURCE -g  -fPIC -o $@ -c $<
+
+syslib_user.o: syslib.c
+       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -g  -fPIC -o $@ -c $<
+
+libwls.so: wls_lib.o syslib_user.o
+       $(CC) $(LDFLAGS) -g -shared -fPIC -Wl,-soname,libwls.so -o $@ wls_lib.o syslib_user.o
+
+install:
+       [ -d "${INSTALL_MOD_DIR}" ] || mkdir -p ${INSTALL_MOD_DIR}
+       cp ./wls.ko ${INSTALL_MOD_DIR}
+       $(call cmd_depmod)
+clean:
+       rm -f *.o *~ core .depend .*.cmd *.ko *.so *.mod.c
+       rm -f Module.markers Module.symvers modules.order
+       rm -rf .tmp_versions Modules.symvers
+endif
diff --git a/wls_lib/build.sh b/wls_lib/build.sh
new file mode 100644 (file)
index 0000000..30a0c2a
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+#
+#  File: build.sh
+#        Build script to comapile kernel module, library and test application.
+#
+
+#if [ "$1" = "dpdk_wls" ]; then
+    echo "Building dpdk based wls library" 
+    make DPDK_WLS=1 ${*:2}
+    cd testapp
+    make DPDK_WLS=1 ${*:2}
+#else
+#    echo "Building driver based wls library" 
+#    make -C /lib/modules/`uname -r`/build  M=$PWD $*
+#    make libwls.so $*
+#    cd testapp
+#    make $*
+#fi
diff --git a/wls_lib/syslib.c b/wls_lib/syslib.c
new file mode 100644 (file)
index 0000000..3bedeed
--- /dev/null
@@ -0,0 +1,408 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+#ifdef __KERNEL__
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "syslib.h"
+#include "wls.h"
+
+#ifdef __KERNEL__
+#ifdef _DEBUG_
+#define PRINT_DEBUG(format, args...)            \
+do {                                          \
+    printk(KERN_INFO "wls debug: " format,##args); \
+}while(0)
+#else
+#define PRINT_DEBUG(x, args...)  do { } while(0)
+#endif
+#else
+#ifdef _DEBUG_
+#define PRINT_DEBUG(x, args...)  printf("wls_lib debug: "x, ## args);
+#else
+#define PRINT_DEBUG(x, args...)  do { } while(0)
+#endif
+#endif
+
+
+
+#define SFL_memcpy  memcpy
+/******************************************************************************
+*                                                                             *
+*     Generic fast queue that operates with pointers (derived from ICC)       *
+*                                                                             *
+******************************************************************************/
+
+int    SFL_WlsEnqueue(PFASTQUEUE pq, U64 pData, wls_us_addr_conv change_addr, void* hWls)
+{
+       U32 put = pq->put;
+       U32 new_put = put + 1;
+
+    PRINT_DEBUG("off %lx put %d get %d  size %d storage %lx\n",(unsigned long)pq - (unsigned long) hWls,  pq->put, pq->get, pq->size, pq->pStorage);
+
+       if (new_put >= pq->size)
+               new_put = 0;
+
+       if (new_put != pq->get)
+       { // the queue is not full
+
+        U64*  pLocalStorage = (U64*) pq->pStorage; // kernel VA
+        if (change_addr)
+             pLocalStorage = (U64*)change_addr(hWls, (U64)pq->pStorage); // user VA
+
+        PRINT_DEBUG("pLocalStorage %lx\n", (U64)pLocalStorage);
+
+               pLocalStorage[put] = pData;
+
+               DSB();
+               pq->put = new_put;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+
+U64 SFL_WlsDequeue(PFASTQUEUE pq,
+    wls_us_addr_conv change_addr,
+    void *hWls)
+{
+       U64 p;
+    U32   get = pq->get;
+
+       if ((pq->put - get) != 0)
+       {
+        U64* pLocalStorage = (U64*) pq->pStorage; // kernel VA
+
+        DSB();
+        if (change_addr)
+            pLocalStorage = (U64 *)change_addr(hWls, (U64)pLocalStorage); //convert to user VA
+
+               p =  pLocalStorage[get++];
+               if (get >= pq->size)
+                       get = 0;
+
+               pq->get = get;
+               return p;
+       }
+       return 0;
+}
+
+/*
+int    SFL_Enqueue_NoSync(PFASTQUEUE pq, PVOID pData)
+{
+       U32 put = pq->put;
+       U32 new_put = put + 1;
+       if (new_put >= pq->size)
+               new_put = 0;
+
+       if (new_put != pq->get)
+       { // the queue is not full
+               pq->pStorage[ put ] = pData;
+               pq->put = new_put;
+               return TRUE;
+       }
+       return FALSE;
+}*/
+
+/*
+PVOID SFL_Dequeue_NoSync(PFASTQUEUE pq)
+{
+       PVOID p;
+       U32   get = pq->get;
+
+       if ((pq->put - get) != 0)
+       {
+               p = pq->pStorage[get++];
+               if (get >= pq->size)
+                       get = 0;
+               pq->get = get;
+               return p;
+       }
+       return NULL;
+}*/
+
+void SFL_DefQueue(PFASTQUEUE pq, void *pStorage, int StorageSize)
+{
+       memset( (void*) pq, 0x00, sizeof( FASTQUEUE) );
+       // always define storage as U64 []
+       pq->size = StorageSize >> 3;
+       pq->pStorage = (U64)pStorage;
+
+    PRINT_DEBUG("put %d get %d  size %d pq->pStorage %lx\n",pq->put, pq->get, pq->size, pq->pStorage);
+
+}
+
+static U32 sfl_SafeQueueLevel(U32 put, U32 get, U32 size)
+{
+       U32 nItems;
+
+       if (put >= get)
+               nItems = put - get;
+       else
+               nItems = size + put - get;
+
+       return nItems;
+}
+
+U32 WLS_GetNumItemsInTheQueue(PWLS_MSG_QUEUE fpq)
+{
+       return sfl_SafeQueueLevel(fpq->put, fpq->get, fpq->size);
+}
+
+U32 SFL_GetNumItemsInTheQueue(FASTQUEUE *fpq)
+{
+       return sfl_SafeQueueLevel(fpq->put, fpq->get, fpq->size);
+}
+
+/*
+
+U32 SFL_Queue_BatchRead( PFASTQUEUE pq, unsigned long *pDestArr, U32 Count)
+{
+       if (Count)
+       {
+               U32 write_index = 0;
+               U32 nReads = 0;
+               //U32 iMask = SFL_IDisable();
+               U32 put = pq->put; // fetch the put atomicly (as app may change it!)
+               U32 get = pq->get; // cache the volatile "get index"
+
+               //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+               if ( (nReads = sfl_SafeQueueLevel(put, get, pq->size)) < Count )
+                       Count = nReads;
+               else
+                       nReads = Count;
+
+               if (Count >= pq->size - get)
+               {
+                       U32 n = pq->size - get;
+                       SFL_memcpy( pDestArr, &pq->pStorage[get], sizeof(pDestArr[0]) * n);
+                       get = 0;
+                       Count -= n;
+                       write_index += n;
+               }
+
+               if (Count)
+               {
+                       SFL_memcpy( &pDestArr[write_index], &pq->pStorage[get], sizeof(pDestArr[0]) * Count);
+                       get += Count;
+               }
+
+               DSB();
+               pq->get = get;
+
+               //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+               //SFL_IControl(iMask);
+
+               return nReads;
+       }
+       return FALSE;
+}
+
+
+// the routine does not keep the fifo order (it is used to take items away from the queue)
+U32 SFL_Queue_BatchUnload(PFASTQUEUE pq, unsigned long* pDestArr, U32 Count)
+{
+       if (Count)
+       {
+               U32 write_index = 0;
+               U32 nReads = 0;
+               //U32 iMask = SFL_IDisable();
+               U32 put = pq->put; // lets cache the volatile "put index"
+               U32 get = pq->get; // fetch the get index atomicly (as app may change it)
+
+               //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+               nReads = sfl_SafeQueueLevel(put, get, pq->size);
+               if (nReads)
+                       nReads -= 1; // decrement is used to cover the case when a reader already started reading from head
+
+               if ( nReads < Count )
+                       Count = nReads;
+               else
+                       nReads = Count;
+
+               if (!put)
+                       put = pq->size;
+
+               if (Count >= put)
+               {
+                       U32 n = put;
+                       SFL_memcpy( pDestArr, &pq->pStorage[0], sizeof(pDestArr[0]) * n);
+                       put = pq->size;
+                       Count -= n;
+                       write_index += n;
+               }
+
+               if (Count)
+               {
+                       put -= Count;
+                       SFL_memcpy( &pDestArr[write_index], &pq->pStorage[put], sizeof(pDestArr[0]) * Count);
+               }
+
+               if (put >= pq->size)
+                       put = 0;
+
+               DSB();
+               pq->put = put;
+
+               //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+               //SFL_IControl(iMask);
+
+               return nReads;
+       }
+       return FALSE;
+}
+
+
+U32 SFL_Queue_BatchWrite( PFASTQUEUE pq, unsigned long *pSrcArr, U32 Count)
+{
+
+       U32 nWrites = Count;
+
+       if (Count)
+       {
+               U32 read_index = 0;
+               U32 put = pq->put;
+               //U32 iMask = SFL_IDisable();
+
+               if (pq->size - put <= Count)
+               {
+                       U32 n = pq->size - put;
+                       SFL_memcpy( &pq->pStorage[put], pSrcArr, sizeof(pSrcArr[0]) * n);
+                       put = 0;
+                       Count -= n;
+                       read_index += n;
+               }
+
+               if (Count)
+               {
+                       SFL_memcpy( &pq->pStorage[put], &pSrcArr[read_index], sizeof(pSrcArr[0]) * Count);
+                       put += Count;
+               }
+
+               DSB();
+               pq->put = put;
+
+               //SFL_IControl(iMask);
+               return nWrites;
+       }
+       return 0;
+}
+*/
+void WLS_MsgDefineQueue(
+       PWLS_MSG_QUEUE pq,
+       PWLS_MSG_HANDLE pStorage,
+       U32 size,
+       U32 sema)
+{
+       memset( pq, 0x00, sizeof(WLS_MSG_QUEUE));
+       pq->pStorage = (U64) pStorage;
+       pq->get = 0;
+       pq->put = 0;
+       pq->size = size; // number of items
+       pq->sema = sema;
+}
+
+U32 WLS_MsgEnqueue(
+       PWLS_MSG_QUEUE pq,
+    U64   pIaPaMsg,
+    U32   MsgSize,
+    U16   TypeID,
+    U16   flags,
+    wls_us_addr_conv change_addr,
+    void *hWls)
+{
+       U32 rc = 0;
+       // below is protected section.
+       U32 put = pq->put;
+       U32 put_new = put + 1;
+
+       if (put_new >= pq->size)
+               put_new = 0;
+
+       if (put_new != pq->get)
+       {
+        PWLS_MSG_HANDLE pLocalStorage = (PWLS_MSG_HANDLE)pq->pStorage; // kernel VA
+        PWLS_MSG_HANDLE pItem;
+
+        PRINT_DEBUG("Kernel VA pq->pStorage %lx put [%d] %d %d\n", pq->pStorage, put_new, pq->get, pq->size);
+
+        if (change_addr)
+            pLocalStorage = (PWLS_MSG_HANDLE)change_addr(hWls, (U64)pq->pStorage);
+
+        pItem = &pLocalStorage[put];
+
+               pItem->pIaPaMsg = pIaPaMsg;
+               pItem->MsgSize  = MsgSize;
+               pItem->TypeID   = TypeID;
+               pItem->flags    = flags;
+               DSB();
+               pq->put = put_new;
+               rc = 1;
+       }
+
+       return rc;
+}
+
+int WLS_MsgDequeue(
+       PWLS_MSG_QUEUE pq,
+       PWLS_MSG_HANDLE pDestItem,
+       wls_us_addr_conv change_addr,
+       void *hWls)
+{
+       int retval = FALSE;
+       U32 get = pq->get;
+    PWLS_MSG_HANDLE pLocalStorage;
+
+       if (!pDestItem)
+               return retval;
+
+    if (get >= pq->size)
+    {
+
+        PRINT_DEBUG("error WLS_MsgDequeue get %d size %d\n", get, pq->size);
+
+        return retval;
+    }
+
+    pLocalStorage = (PWLS_MSG_HANDLE) pq->pStorage; // kernel VA
+    PRINT_DEBUG("WLS_MsgDequeue with pq->pStorage %lX\n",pq->pStorage);
+    if (pq->put != get)
+       {
+
+        DSB();
+        if (change_addr)
+            pLocalStorage = (PWLS_MSG_HANDLE)change_addr(hWls, (U64) pq->pStorage); //convert to user VA
+
+               *pDestItem = pLocalStorage[get];
+
+               if (++get == pq->size)
+                       get = 0;
+
+               pq->get = get;
+               retval = TRUE;
+       }
+
+       return retval;
+}
diff --git a/wls_lib/syslib.h b/wls_lib/syslib.h
new file mode 100644 (file)
index 0000000..1b52470
--- /dev/null
@@ -0,0 +1,131 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef __SYSLIB_H__
+#define __SYSLIB_H__
+
+typedef unsigned char  U8;      /* unsigned 8-bit  integer */
+typedef unsigned short U16;     /* unsigned 16-bit integer */
+typedef unsigned int   U32;     /* unsigned 32-bit integer */
+#ifdef __x86_64__
+typedef unsigned long  U64;     /* unsigned 64-bit integer */
+#else
+typedef unsigned long long  U64;     /* unsigned 64-bit integer */
+#endif
+
+typedef volatile unsigned char  V8;
+typedef volatile unsigned short V16;
+typedef volatile unsigned int   V32;
+typedef volatile unsigned long  V4;
+
+typedef signed char  S8;         /* 8-bit  signed integer */
+typedef signed short S16;       /* 16-bit signed integer */
+typedef signed int   S32;        /* 32-bit signed integer */
+
+#ifdef __x86_64__
+typedef signed long  S64;          /* unsigned 64-bit integer */
+#else
+typedef signed long long  S64;     /* unsigned 64-bit integer */
+#endif
+
+#ifndef _PVOID_
+#define _PVOID_
+typedef void *PVOID;
+#endif
+
+typedef U64 (*wls_us_addr_conv)(void*, U64);
+
+
+#define K                      1024
+#define M                      (K*K)
+#define KHZ         1000
+#define MHZ         (KHZ * KHZ)
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef NULL
+#define NULL ((PVOID)(0))
+#endif
+#define HANDLE PVOID
+
+#ifdef __KERNEL__
+#define DSB()  smp_mb()
+#define DMB()  smp_wmb()
+#else
+#define        DSB()  __asm__ __volatile__("mfence": : :"memory")
+#define        DMB()  __asm__ __volatile__("sfence": : :"memory")
+#endif
+
+typedef struct tagWLS_MSG_HANDLE
+{
+    U64   pIaPaMsg;
+    U32   pWlsPaMsg;
+    U32   MsgSize;
+    U16   TypeID;         // used to identify destination
+    U16   flags;
+    U32   res1;
+} WLS_MSG_HANDLE, *PWLS_MSG_HANDLE; /* 4 x QW */
+
+typedef struct tagFASTQUEUE {
+    U64 pStorage;
+       U32 BlockSize;
+       U32 sema;
+       V32 get;
+       V32 put;
+       U32 size;
+    U32 res;
+} FASTQUEUE, *PFASTQUEUE;
+
+typedef struct tagWLS_MSG_QUEUE {
+    U64 pStorage;
+       U32 sema;
+       V32 get;
+       V32 put;
+       U32 size;
+} WLS_MSG_QUEUE, *PWLS_MSG_QUEUE;
+
+#define COUNT(some_array) ( sizeof(some_array)/sizeof((some_array)[0]) )
+
+void SFL_DefQueue(PFASTQUEUE pq, void *pStorage, int StorageSize);
+int    SFL_WlsEnqueue(PFASTQUEUE pq, U64 pData, wls_us_addr_conv change_addr, void* hWls);
+int    SFL_Enqueue_NoSync(PFASTQUEUE pq, PVOID pData);
+U64 SFL_WlsDequeue(PFASTQUEUE pq, wls_us_addr_conv change_addr, void *hWls);
+
+PVOID SFL_Dequeue_NoSync(PFASTQUEUE pq);
+U32 SFL_Queue_BatchRead( PFASTQUEUE pq, unsigned long *pDestArr, U32 Count);
+U32 SFL_Queue_BatchWrite( PFASTQUEUE pq, unsigned long *pSrcArr, U32 Count);
+
+void WLS_MsgDefineQueue(PWLS_MSG_QUEUE pq, PWLS_MSG_HANDLE pStorage, U32 size, U32 sema);
+U32 WLS_MsgEnqueue(PWLS_MSG_QUEUE pq, U64  pIaPaMsg, U32 MsgSize, U16 TypeID, U16   flags, wls_us_addr_conv change_addr, void* h);
+int WLS_MsgDequeue(PWLS_MSG_QUEUE pq, PWLS_MSG_HANDLE pDestItem, wls_us_addr_conv change_addr, void *hWls);
+U32 WLS_GetNumItemsInTheQueue(PWLS_MSG_QUEUE fpq);
+U32 SFL_GetNumItemsInTheQueue(FASTQUEUE *fpq);
+
+
+
+
+
+#endif // __SYSLIB_H__
+
+
diff --git a/wls_lib/test/bin/fapi/fapi.sh b/wls_lib/test/bin/fapi/fapi.sh
new file mode 100644 (file)
index 0000000..d5a72fa
--- /dev/null
@@ -0,0 +1,30 @@
+#######################################################################
+#
+# <COPYRIGHT_TAG>
+#
+#######################################################################
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DIR_WIRELESS_WLS
+
+MACHINE_TYPE=`uname -m`
+
+if [ ${MACHINE_TYPE} == 'x86_64' ]; then
+
+       ulimit -c unlimited
+       echo 1 > /proc/sys/kernel/core_uses_pid
+
+       sysctl -w kernel.sched_rt_runtime_us=-1
+       sysctl -w kernel.shmmax=2147483648
+       sysctl -w kernel.shmall=2147483648
+       chkconfig --level 12345 irqbalance off
+       echo 0 > /proc/sys/kernel/nmi_watchdog
+       echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress
+
+fi
+
+echo start WLS PHY Process
+if [ "$1" = "-g" ]; then
+    shift
+    taskset -c 16 gdb-ia --args ./fapi_app $@
+else
+    taskset -c 16 ./fapi_app $@
+fi
diff --git a/wls_lib/test/bin/mac/mac.sh b/wls_lib/test/bin/mac/mac.sh
new file mode 100644 (file)
index 0000000..9b0b4e4
--- /dev/null
@@ -0,0 +1,31 @@
+#######################################################################
+#
+# <COPYRIGHT_TAG>
+#
+#######################################################################
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DIR_WIRELESS_WLS
+
+MACHINE_TYPE=`uname -m`
+
+if [ ${MACHINE_TYPE} == 'x86_64' ]; then
+
+       ulimit -c unlimited
+       echo 1 > /proc/sys/kernel/core_uses_pid
+
+       sysctl -w kernel.sched_rt_runtime_us=-1
+       sysctl -w kernel.shmmax=2147483648
+       sysctl -w kernel.shmall=2147483648
+       chkconfig --level 12345 irqbalance off
+       echo 0 > /proc/sys/kernel/nmi_watchdog
+       echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress
+
+fi
+
+echo start WLS PHY Process
+if [ "$1" = "-g" ]; then
+    shift
+    taskset -c 17 gdb-ia --args ./mac_app $@
+else
+    taskset -c 17 ./mac_app $@
+fi
+
diff --git a/wls_lib/test/bin/phy/phy.sh b/wls_lib/test/bin/phy/phy.sh
new file mode 100644 (file)
index 0000000..41c1ea8
--- /dev/null
@@ -0,0 +1,30 @@
+#######################################################################
+#
+# <COPYRIGHT_TAG>
+#
+#######################################################################
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DIR_WIRELESS_WLS
+
+MACHINE_TYPE=`uname -m`
+
+if [ ${MACHINE_TYPE} == 'x86_64' ]; then
+
+       ulimit -c unlimited
+       echo 1 > /proc/sys/kernel/core_uses_pid
+
+       sysctl -w kernel.sched_rt_runtime_us=-1
+       sysctl -w kernel.shmmax=2147483648
+       sysctl -w kernel.shmall=2147483648
+       chkconfig --level 12345 irqbalance off
+       echo 0 > /proc/sys/kernel/nmi_watchdog
+       echo 1 > /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress
+
+fi
+
+echo start WLS PHY Process
+if [ "$1" = "-g" ]; then
+    shift
+    taskset -c 15 gdb-ia --args ./phy_app $@
+else
+    taskset -c 15 ./phy_app $@
+fi
diff --git a/wls_lib/test/build.sh b/wls_lib/test/build.sh
new file mode 100644 (file)
index 0000000..2f4e455
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+make -C ./mac --no-print-directory -f ./makefile $* PLATFORM=X86_64BIT
+make -C ./fapi --no-print-directory -f ./makefile $* PLATFORM=X86_64BIT
+make -C ./phy --no-print-directory -f ./makefile $* PLATFORM=X86_64BIT
diff --git a/wls_lib/test/build/fapi/dep_file b/wls_lib/test/build/fapi/dep_file
new file mode 100644 (file)
index 0000000..d72bb47
--- /dev/null
@@ -0,0 +1,27 @@
+../build/fapi//home/Luis/Integration/oran_wls_lib/test/fapi/fapi_main.o: \
+ /home/Luis/Integration/oran_wls_lib/test/fapi/fapi_main.c \
+ /usr/include/stdc-predef.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_eal.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_config.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_compat.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_common.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_per_lcore.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_bus.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_log.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_dev.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_pci_dev_feature_defs.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_cfgfile.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_string_fns.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_lcore.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_launch.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_debug.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_branch_prediction.h \
+ /home/Luis/Integration/oran_wls_lib/wls.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_atomic.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/generic/rte_atomic.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_atomic_64.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_memzone.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_memory.h \
+ /home/Luis/Integration/oran_wls_lib/ttypes.h \
+ /home/Luis/Integration/oran_wls_lib/syslib.h \
+ /home/Luis/Integration/oran_wls_lib/wls_lib.h
diff --git a/wls_lib/test/build/mac/dep_file b/wls_lib/test/build/mac/dep_file
new file mode 100644 (file)
index 0000000..31f7627
--- /dev/null
@@ -0,0 +1,34 @@
+../build/mac//home/Luis/Integration/oran_wls_lib/test/mac/mac_main.o: \
+ /home/Luis/Integration/oran_wls_lib/test/mac/mac_main.c \
+ /usr/include/stdc-predef.h /home/Luis/Integration/oran_wls_lib/wls_lib.h \
+ /home/Luis/Integration/oran_wls_lib/test/mac/mac_wls.h \
+ /home/Luis/Integration/oran_5g_fapi/include/fapi_interface.h
+../build/mac//home/Luis/Integration/oran_wls_lib/test/mac/mac_wls.o: \
+ /home/Luis/Integration/oran_wls_lib/test/mac/mac_wls.c \
+ /usr/include/stdc-predef.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_eal.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_config.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_compat.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_common.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_per_lcore.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_bus.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_log.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_dev.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_pci_dev_feature_defs.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_cfgfile.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_string_fns.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_lcore.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_launch.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_debug.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_branch_prediction.h \
+ /home/Luis/Integration/oran_wls_lib/wls.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_atomic.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/generic/rte_atomic.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_atomic_64.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_memzone.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_memory.h \
+ /home/Luis/Integration/oran_wls_lib/ttypes.h \
+ /home/Luis/Integration/oran_wls_lib/syslib.h \
+ /home/Luis/Integration/oran_wls_lib/wls_lib.h \
+ /home/Luis/Integration/oran_wls_lib/test/mac/mac_wls.h \
+ /home/Luis/Integration/oran_5g_fapi/include/fapi_interface.h
diff --git a/wls_lib/test/build/phy/dep_file b/wls_lib/test/build/phy/dep_file
new file mode 100644 (file)
index 0000000..7a11259
--- /dev/null
@@ -0,0 +1,19 @@
+../build/phy//home/Luis/Integration/oran_wls_lib/test/phy/phy_main.o: \
+ /home/Luis/Integration/oran_wls_lib/test/phy/phy_main.c \
+ /usr/include/stdc-predef.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_eal.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_config.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_compat.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_common.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_per_lcore.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_bus.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_log.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_dev.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_pci_dev_feature_defs.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_cfgfile.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_string_fns.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_lcore.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_launch.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_debug.h \
+ /home/samuelwo/dpdk-18.08/x86_64-native-linuxapp-icc/include/rte_branch_prediction.h \
+ /home/Luis/Integration/oran_wls_lib/wls_lib.h
diff --git a/wls_lib/test/fapi/fapi_main.c b/wls_lib/test/fapi/fapi_main.c
new file mode 100644 (file)
index 0000000..7c1a14a
--- /dev/null
@@ -0,0 +1,649 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @brief This file is test FAPI wls lib main process
+ * @file fapi_main.c
+ * @ingroup group_testfapiwls
+ * @author Intel Corporation
+ **/
+
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_cfgfile.h>
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_launch.h>
+
+#define DPDK_WLS
+#include "wls.h"
+#include "wls_lib.h"
+
+#define NR5G_FAPI2PHY_WLS_INST 0
+#define NR5G_FAPI2MAC_WLS_INST 1
+#define SUCCESS 0
+#define FAILURE 1
+#define WLS_TEST_DEV_NAME "wls"
+#define WLS_TEST_MSG_ID   1
+#define WLS_TEST_MSG_SIZE 100
+#define WLS_TEST_MEM_SIZE 2126512128 
+#define ALLOC_TRACK_SIZE 16384
+#define MIN_UL_BUF_LOCATIONS 50
+#define MIN_DL_BUF_LOCATIONS 50
+#define MAX_UL_BUF_LOCATIONS 50
+#define MAX_DL_BUF_LOCATIONS 50
+#define NUM_WLS_INSTANCES 2
+#define WLS_HUGE_DEF_PAGE_SIZEA    0x40000000LL
+#define MSG_MAXSIZE1 (16*16384)
+#define NUM_TEST_MSGS   16
+
+
+
+
+typedef void* WLS_HANDLE;
+typedef struct wls_fapi_mem_array
+{
+    void **ppFreeBlock;
+    void *pStorage;
+    void *pEndOfStorage;
+    uint32_t nBlockSize;
+    uint32_t nBlockCount;
+} WLS_FAPI_MEM_STRUCT, *PWLS_FAPI_MEM_STRUCT;
+
+// WLS context structure
+typedef struct _nr5g_fapi_wls_context {
+    void        *shmem;       // shared  memory region.
+    uint64_t    shmem_size;   // shared  memory region size.
+    WLS_FAPI_MEM_STRUCT sWlsStruct;
+    WLS_HANDLE  h_wls[NUM_WLS_INSTANCES]; // WLS context handle
+    void *pWlsMemBase;
+    uint32_t nTotalMemorySize;
+    uint32_t nTotalBlocks;
+    uint32_t nAllocBlocks;
+    uint32_t nTotalAllocCnt;
+    uint32_t nTotalFreeCnt;
+    uint32_t nTotalUlBufAllocCnt;
+    uint32_t nTotalUlBufFreeCnt;
+    uint32_t nTotalDlBufAllocCnt;
+    uint32_t nTotalDlBufFreeCnt;
+    uint32_t nPartitionMemSize;
+    void     *pPartitionMemBase;
+    volatile pthread_mutex_t lock;
+    volatile pthread_mutex_t lock_alloc;
+} nr5g_fapi_wls_context_t, *p_nr5g_fapi_wls_context_t;
+
+nr5g_fapi_wls_context_t  g_wls_ctx;
+typedef void* WLS_HANDLE;
+static uint8_t alloc_track[ALLOC_TRACK_SIZE];
+void *g_shmem;
+uint32_t g_shmem_size=0;
+uint32_t g_nTotalAllocCnt=0;
+uint32_t g_nAllocBlocks=0;
+uint32_t gwls_fapi_ready=0;
+WLS_FAPI_MEM_STRUCT g_MemArray;
+nr5g_fapi_wls_context_t  g_wls_ctx;
+uint32_t g_nTotalDlBufAllocCnt=0;
+uint32_t g_nTotalUlBufAllocCnt=0;
+
+wls_us_ctx_t gphy_wls;
+wls_us_ctx_t gfapi_wls;
+
+WLS_HANDLE   g_phy_wls = &gphy_wls;
+WLS_HANDLE   g_fapi_wls = &gfapi_wls;
+
+uint8_t    fapi_dpdk_init(void);
+uint8_t    fapi_wls_init(const char *dev_name, unsigned long long mem_size);
+uint64_t   fapi_mac_recv();
+uint8_t    fapi_phy_send();
+uint64_t   fapi_phy_recv();
+uint8_t    fapi_mac_send();
+uint8_t    fapi2Phy_wls_init(p_nr5g_fapi_wls_context_t pwls);
+uint8_t wls_fapi_create_partition(p_nr5g_fapi_wls_context_t pWls);
+uint32_t wls_fapi_alloc_mem_array(PWLS_FAPI_MEM_STRUCT pMemArray, void **ppBlock);
+uint32_t wls_fapi_create_mem_array(PWLS_FAPI_MEM_STRUCT pMemArray, void *pMemArrayMemory, uint32_t totalSize, uint32_t nBlockSize);
+
+uint64_t nr5g_fapi_wls_va_to_pa(WLS_HANDLE h_wls, void *ptr)
+{
+    return ((uint64_t)WLS_VA2PA(h_wls, ptr));
+}
+
+inline p_nr5g_fapi_wls_context_t nr5g_fapi_wls_context()
+{
+    return &g_wls_ctx;
+}
+
+static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance()
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+
+    return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
+}
+
+static inline WLS_HANDLE nr5g_fapi_fapi2phy_wls_instance()
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    return p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST];
+}
+void *wls_fapi_alloc_buffer(uint32_t size, uint32_t loc)
+{
+    void *pBlock = NULL;
+    p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
+    PWLS_FAPI_MEM_STRUCT pMemArray = &pWls->sWlsStruct;
+
+    pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
+
+    if (wls_fapi_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS)
+    {
+        printf("wls_fapi_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc);
+
+        exit(-1);
+    }
+    else
+    {
+        pWls->nAllocBlocks++;
+    }
+
+    //printf("----------------wls_fapi_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
+
+    //printf("[%p]\n", pBlock);
+
+    pWls->nTotalAllocCnt++;
+    if (loc < MAX_DL_BUF_LOCATIONS)
+        pWls->nTotalDlBufAllocCnt++;
+    else if (loc < MAX_UL_BUF_LOCATIONS)
+        pWls->nTotalUlBufAllocCnt++;
+
+    pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
+    return pBlock;
+}
+
+uint32_t wls_fapi_create_mem_array(PWLS_FAPI_MEM_STRUCT pMemArray, void *pMemArrayMemory, uint32_t totalSize, uint32_t nBlockSize)
+{
+
+    int numBlocks = totalSize / nBlockSize;
+    void **ptr;
+    uint32_t i;
+
+    printf("wls_fapi_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
+        pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
+
+    // Can't be less than pointer size
+    if (nBlockSize < sizeof(void *))
+    {
+        return FAILURE;
+    }
+
+    // Can't be less than one block
+    if (totalSize < sizeof(void *))
+    {
+        return FAILURE;
+    }
+
+    pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
+    pMemArray->pStorage = pMemArrayMemory;
+    pMemArray->pEndOfStorage = ((unsigned long*)pMemArrayMemory) + numBlocks * nBlockSize / sizeof(unsigned long);
+    pMemArray->nBlockSize = nBlockSize;
+    pMemArray->nBlockCount = numBlocks;
+
+    // Initialize single-linked list of free blocks;
+    ptr = (void **)pMemArrayMemory;
+    for (i = 0; i < pMemArray->nBlockCount; i++)
+    {
+#ifdef MEMORY_CORRUPTION_DETECT
+        // Fill with some pattern
+        uint8_t *p = (uint8_t *)ptr;
+        uint32_t j;
+
+        p += (nBlockSize - 16);
+        for (j = 0; j < 16; j++)
+        {
+            p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
+        }
+#endif
+
+        if (i == pMemArray->nBlockCount - 1)
+        {
+            *ptr = NULL;      // End of list
+        }
+        else
+        {
+            // Points to the next block
+            *ptr = (void **)(((uint8_t*)ptr) + nBlockSize);
+            ptr += nBlockSize / sizeof(unsigned long);
+        }
+    }
+
+    memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE);
+
+    return SUCCESS;
+}
+
+uint32_t wls_fapi_alloc_mem_array(PWLS_FAPI_MEM_STRUCT pMemArray, void **ppBlock)
+{
+    int idx;
+
+    if (pMemArray->ppFreeBlock == NULL)
+    {
+        printf("wls_fapi_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
+        return FAILURE;
+    }
+
+    // FIXME: Remove after debugging
+    if (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage) ||
+        ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))
+    {
+        printf("wls_fapi_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
+                pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+    *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+
+    if ((*pMemArray->ppFreeBlock != NULL) &&
+        (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
+        ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage)))
+    {
+        fprintf(stderr, "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+                pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+                *pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    *ppBlock = (void *) pMemArray->ppFreeBlock;
+    pMemArray->ppFreeBlock = (void **) (*pMemArray->ppFreeBlock);
+
+    idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
+    if (alloc_track[idx])
+    {
+        printf("wls_fapi_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+            *pMemArray->ppFreeBlock);
+    }
+    else
+    {
+#ifdef MEMORY_CORRUPTION_DETECT
+        uint32_t nBlockSize = pMemArray->nBlockSize, i;
+        uint8_t *p = (uint8_t *)*ppBlock;
+
+        p += (nBlockSize - 16);
+        for (i = 0; i < 16; i++)
+        {
+            p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
+        }
+#endif
+        alloc_track[idx] = 1;
+    }
+
+    //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
+
+    return SUCCESS;
+}
+
+
+
+uint8_t wls_fapi_create_partition(p_nr5g_fapi_wls_context_t pWls)
+{
+static long hugePageSize = WLS_HUGE_DEF_PAGE_SIZEA;
+     void *pPartitionMemBase;
+     uint32_t nPartitionMemSize;
+     uint32_t nTotalBlocks;
+     
+    pWls->pPartitionMemBase = pWls->pWlsMemBase + hugePageSize;
+    pWls->nPartitionMemSize = (pWls->nTotalMemorySize - hugePageSize);
+
+    pWls->nTotalBlocks = pWls->nPartitionMemSize / MSG_MAXSIZE1;
+
+    return wls_fapi_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, pWls->nPartitionMemSize, MSG_MAXSIZE1);
+}
+
+uint8_t nr5g_fapi2Phy_wls_init(p_nr5g_fapi_wls_context_t pWls)
+{
+    int nBlocks = 0;
+    uint8_t retval = SUCCESS;
+
+
+    WLS_HANDLE h_wls =         pWls->h_wls[NR5G_FAPI2PHY_WLS_INST];
+    pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL);
+    pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL);
+
+    pWls->nTotalAllocCnt = 0;
+    pWls->nTotalFreeCnt = 0;
+    pWls->nTotalUlBufAllocCnt = 0;
+    pWls->nTotalUlBufFreeCnt = 0;
+    pWls->nTotalDlBufAllocCnt = 0;
+    pWls->nTotalDlBufFreeCnt = 0;
+    // Need to add wls_fapi_create_partition
+    retval = wls_fapi_create_partition(pWls);
+    if (retval == SUCCESS)
+    {  
+       gwls_fapi_ready = 1;
+       nBlocks = WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa( h_wls, wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+2)));
+       printf("WLS_EnqueueBlock [%d]\n", nBlocks);
+       // Allocate Blocks for UL Transmission
+       while(WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa(h_wls,wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+3))))
+       {
+         nBlocks++;
+       }
+       printf ("fapi2Phy UL Buffer Allocation completed\n");
+    }
+    else
+    {
+       printf ("can't create WLS FAPI2PHY partition \n");
+       return FAILURE;
+    }
+    return retval;
+}
+
+uint8_t nr5g_fapi_fapi2mac_wls_ready()
+{
+    int ret = SUCCESS;
+    ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
+    return ret;
+}
+
+
+inline uint8_t nr5g_fapi_fapi2phy_wls_ready()
+{
+    int ret = SUCCESS;
+    //NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for L1 to respond in WLS Ready"));
+    ret = WLS_Ready(nr5g_fapi_fapi2phy_wls_instance());
+    return ret;
+}
+
+int main()
+{
+    uint8_t ret;
+    uint64_t p_msg;
+    uint8_t retval= FAILURE;
+    p_nr5g_fapi_wls_context_t pwls;
+
+    // DPDK init
+    ret = fapi_dpdk_init();
+    if (ret)
+    {
+        printf("\n[FAPI] DPDK Init - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[FAPI] DPDK Init - Done\n");
+
+    // WLS init
+    ret = fapi_wls_init(WLS_TEST_DEV_NAME, WLS_TEST_MEM_SIZE);
+    if(ret)
+    {
+        printf("\n[FAPI] WLS Init - Failed\n");
+        return FAILURE;
+    }
+    // Need to check for L1 and L2 started before attempting partition creation
+    // First let's wait for the L1 and L2 to be present
+    while (retval)
+    {
+       retval = nr5g_fapi_fapi2phy_wls_ready();
+    }
+    // Now the L2 is up so let's make sure that the L1 was started first
+    retval=FAILURE;
+    while (retval)
+    {
+       retval = nr5g_fapi_fapi2mac_wls_ready();
+    }
+    // Now that the L2 is up and has completed the Common Memory initialization the FT needs to initialize the FAPI2PHY buffers
+    pwls = nr5g_fapi_wls_context();
+    usleep(1000000);
+    ret = nr5g_fapi2Phy_wls_init(pwls);
+    if(ret)
+    {
+        printf("\n[FAPI] 2Phy WLS Init - Failed\n");
+        return FAILURE;
+    }
+    
+    printf("\n[FAPI] WLS Init - Done\n");
+
+    // Receive from MAC WLS
+    p_msg = fapi_mac_recv();
+    if (!p_msg)
+    {
+        printf("\n[FAPI] Receive from MAC - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[FAPI] Receive from MAC - Done\n");
+
+    // Sent to PHY WLS
+    ret = fapi_phy_send();
+    if (ret)
+    {
+        printf("\n[FAPI] Send to PHY - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[FAPI] Send to PHY - Done\n");
+
+    // Receive from PHY WLS
+    p_msg = fapi_phy_recv();
+    if (!p_msg)
+    {
+        printf("\n[FAPI] Receive from PHY - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[FAPI] Receive from PHY - Done\n");
+
+    // Sent to MAC WLS
+    ret = fapi_mac_send();
+    if (ret)
+    {
+        printf("\n[FAPI] Send to MAC - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[FAPI] Send to MAC - Done\n");
+
+
+    printf("\n[FAPI] Exiting...\n");
+
+    return SUCCESS;
+}
+
+uint8_t fapi_dpdk_init(void)
+{
+    char whitelist[32];
+    uint8_t i;
+
+    char *argv[] = {"fapi_app", "--proc-type=secondary",
+        "--file-prefix", "wls", whitelist};
+    
+    int argc = RTE_DIM(argv);
+
+    /* initialize EAL first */
+    sprintf(whitelist, "-w %s",  "0000:00:06.0");
+    printf("[FAPI] Calling rte_eal_init: ");
+
+    for (i = 0; i < RTE_DIM(argv); i++)
+    {
+        printf("%s ", argv[i]);
+    }
+    printf("\n");
+
+    if (rte_eal_init(argc, argv) < 0)
+        rte_panic("Cannot init EAL\n");
+
+    return SUCCESS;
+}
+
+uint8_t fapi_wls_init(const char *dev_name, unsigned long long mem_size)
+{
+    uint8_t *pMemZone;
+    static const struct rte_memzone *mng_memzone;
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();    
+    wls_drv_ctx_t *pDrv_ctx;
+
+    p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST] =
+     WLS_Open_Dual(dev_name, WLS_SLAVE_CLIENT, mem_size, &p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]);
+    if((NULL == p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]) && 
+            (NULL == p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST]))
+    {
+        return FAILURE;
+    }
+    g_shmem_size = mem_size;
+    p_wls_ctx->shmem_size = mem_size;
+    // Issue WLS_Alloc() for FAPI2MAC
+    p_wls_ctx->shmem = WLS_Alloc(
+            p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST],
+            p_wls_ctx->shmem_size);
+
+    if (NULL == p_wls_ctx->shmem)
+    {
+        printf("Unable to alloc WLS Memory for FAPI2MAC\n");
+        return FAILURE;
+    }            
+    p_wls_ctx->shmem = WLS_Alloc(
+            p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST],
+            p_wls_ctx->shmem_size);
+    p_wls_ctx->pWlsMemBase = p_wls_ctx->shmem;
+    p_wls_ctx->nTotalMemorySize = p_wls_ctx->shmem_size;
+    if (NULL == p_wls_ctx->shmem)
+    {
+        printf("Unable to alloc WLS Memory for FAPI2PHY\n");
+        return FAILURE;
+    }
+    
+    return SUCCESS;
+}    
+    
+
+uint64_t fapi_mac_recv()
+{
+    uint8_t  num_blks = 0;
+    uint64_t p_msg;
+    uint32_t msg_size;
+    uint16_t msg_id;
+    uint16_t flags;
+    uint32_t i;
+    WLS_HANDLE wls= nr5g_fapi_fapi2mac_wls_instance();
+    
+    for (i=0; i < NUM_TEST_MSGS; i++)
+    {
+    num_blks = WLS_Wait1(wls);
+    
+    if (num_blks)
+    {
+        p_msg = WLS_Get1(wls, &msg_size, &msg_id, &flags);
+    }
+    else
+    {
+        printf("\n[FAPI] FAPI2MAC WLS wait returned 0 blocks\n");
+    }
+               if (p_msg)
+               {
+                       printf("\n[FAPI] Receive from MAC Msg  %d-\n", i);
+         }
+    }            
+    return p_msg;
+}
+
+uint8_t fapi_phy_send()
+{
+    uint64_t pa_block = 0;
+    uint8_t ret = FAILURE;
+    uint32_t i;
+    WLS_HANDLE wls = nr5g_fapi_fapi2mac_wls_instance();
+    WLS_HANDLE wlsp = nr5g_fapi_fapi2phy_wls_instance();
+    
+    for (i=0; i < NUM_TEST_MSGS; i++)
+    {
+    pa_block = (uint64_t) WLS_DequeueBlock((void*) wls);
+    if (!pa_block)
+    {
+        printf("\n[FAPI] FAPI2MAC WLS Dequeue block error %d\n",i);
+        return FAILURE;
+    }
+
+       ret = WLS_Put(wlsp, pa_block, WLS_TEST_MSG_SIZE, WLS_TEST_MSG_ID, (i== (NUM_TEST_MSGS-1))? WLS_TF_FIN:0);
+      if (ret)
+       {
+        printf("\n[FAPI] Send to PHY %d- Failed\n",i);
+        return FAILURE;
+       }
+       else
+       {
+               printf("\n[FAPI] Send to PHY %d done \n",i);
+       }
+    }
+    return ret;
+}
+
+uint64_t fapi_phy_recv()
+{
+    uint8_t  num_blks = 0;
+    uint64_t p_msg;
+    uint32_t msg_size;
+    uint16_t msg_id;
+    uint16_t flags;
+    uint32_t i=0;
+    WLS_HANDLE wls = nr5g_fapi_fapi2phy_wls_instance();
+    
+    while (1)
+    {
+    num_blks = WLS_Wait(wls);
+    printf("WLS_Wait returns %d\n",num_blks);
+    
+    if (num_blks)
+    {
+        p_msg = WLS_Get(wls, &msg_size, &msg_id, &flags);
+        printf("\n[FAPI] FAPI2PHY Received Block %d \n", i);
+        i++;
+        if (flags & WLS_TF_FIN)
+        {
+               return p_msg;
+        }
+    }
+    else
+    {
+        printf("\n[FAPI] FAPI2MAC WLS wait returned 0 blocks\n");
+    }
+    }
+    return p_msg;
+}
+
+uint8_t fapi_mac_send()
+{
+    uint64_t pa_block = 0;
+    uint8_t ret = FAILURE;
+    uint32_t i;
+    WLS_HANDLE wls = nr5g_fapi_fapi2mac_wls_instance();
+    WLS_HANDLE wlsp = nr5g_fapi_fapi2phy_wls_instance();
+    
+    for (i=0; i < NUM_TEST_MSGS; i++)
+    {
+    pa_block = (uint64_t) WLS_DequeueBlock((void*) wlsp);
+    if (!pa_block)
+    {
+        printf("\n[FAPI] FAPI2MAC WLS Dequeue block %d error\n",i);
+        return FAILURE;
+    }
+
+       ret = WLS_Put1(wls, pa_block, WLS_TEST_MSG_SIZE, WLS_TEST_MSG_ID, (i== (NUM_TEST_MSGS-1))? WLS_TF_FIN:0);
+       printf("\n[FAPI] FAPI2MAC WLS Put1 block %d\n",i);
+    }
+    return ret;
+}
diff --git a/wls_lib/test/fapi/makefile b/wls_lib/test/fapi/makefile
new file mode 100644 (file)
index 0000000..655de05
--- /dev/null
@@ -0,0 +1,162 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+.SUFFIXES: .o .c .s .i .cpp
+
+# Makefile to build Testfapi application
+
+##############################################################
+#  Tools configuration
+##############################################################
+CC := icc
+CPP := icpc
+AS := as
+AR := ar
+LD := icc
+OBJDUMP := objdump
+
+ifeq ($(SHELL),cmd.exe)
+MD := mkdir.exe -p
+RM := rm.exe -rf
+else
+MD := mkdir -p
+RM := rm -rf
+endif
+
+##############################################################
+# TARGET
+##############################################################
+ifeq ($(RTE_TARGET),)
+    RTE_TARGET :=x86_64-native-linuxapp-icc
+endif
+##############################################################
+# DPDK
+##############################################################
+ifeq ($(RTE_SDK),)
+$(info Please make sure RTE_SDK points to DPDK folder (current version of DPDK is 18.08))
+    RTE_SDK := /opt/dpdk-18.08
+endif
+
+##############################################################
+# Projects folders
+##############################################################
+WLSDIR            := $(DIR_WIRELESS_WLS)
+BUILDDIR          := ../build/fapi
+SRCDIR            := $(CURDIR)
+
+wls_fapi_app_dep_file = $(BUILDDIR)/dep_file
+
+APP := ../bin/fapi/fapi_app
+
+INC := \
+ $(WLSDIR) \
+ $(SRCDIR) \
+ $(RTE_SDK)/$(RTE_TARGET)/include \
+
+INC := $(addprefix -I,$(INC))
+DEFS := USE_WO_LOCK _GNU_SOURCE NR5G
+
+ifneq ($(PRINTDBG),)
+DEFS := $(DEFS) PRINTF_DBG_OK
+endif
+
+ifeq ($(DEBUG_MODE),true)
+DEFS := $(DEFS) DEBUG_MODE
+endif
+
+DEFS := $(addprefix -D,$(DEFS))
+
+CFLAGS := -g -Wall -wd9 -Wno-deprecated-declarations -Wimplicit-function-declaration -fasm-blocks $(DEFS) $(INC)
+
+ifeq ($(PRINTDBG),)
+CFLAGS := $(CFLAGS) -Werror
+endif
+
+RTE_LIBS := -L$(RTE_SDK)/$(RTE_TARGET)/lib -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lrte_ethdev -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_pci -Wl,-lrte_net -Wl,-lrte_eal -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ring -Wl,-lrt -Wl,-lm -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
+LDFLAGS := -g -Wl,-lrt -Wl,-lpthread -Wl,-lhugetlbfs -Wl,-lm -Wl,-lnuma -L $(WLSDIR) -lwls
+
+LINUX_WLS_FAPI_APP_SRC := \
+       $(SRCDIR)/fapi_main.c \
+
+OBJS := $(LINUX_WLS_FAPI_APP_SRC:.c=.o)
+
+PROJECT_OBJ_DIR = $(BUILDDIR)
+
+OBJS := $(addprefix $(PROJECT_OBJ_DIR)/,$(OBJS))
+
+DIRLIST := $(sort $(dir $(OBJS)))
+
+CC_DEPS := $(addprefix __dep__,$(LINUX_WLS_FAPI_APP_SRC))
+
+GEN_DEP :=
+ifeq ($(wildcard $(wls_fapi_app_dep_file)),)
+GEN_DEP := regenerate_dep
+endif
+
+.PHONY: $(APP)
+$(APP): $(DIRLIST) echo_options $(GEN_DEP) $(OBJS)
+       @echo [LD] $(APP)
+       @$(CC) -o $(APP) $(OBJS) $(RTE_LIBS) $(LDFLAGS)
+#      $(OBJDUMP) -d $(APP) > $(APP).asm
+
+.PHONY : echo_options
+echo_options:
+       @echo [CFLAGS]  $(CFLAGS)
+       @echo [LDFAGS]  $(LDFLAGS)
+
+
+ifneq ($(wildcard $(wls_fapi_app_dep_file)),)
+include $(wls_fapi_app_dep_file)
+endif
+
+$(DIRLIST) :
+       -@$(MD) $@
+
+.PHONY : regenerate_dep
+regenerate_dep : clean_dep echo_regeenrate_dep  $(CC_DEPS)
+
+.PHONY: clean_dep
+clean_dep:
+       $(RM) $(wls_fapi_app_dep_file)
+
+.PHONY : echo_regeenrate_dep
+echo_regeenrate_dep:
+       @echo regenerating dep files
+
+
+.PHONY : CC_DEPS
+$(CC_DEPS):
+       @$(CC) -MM $(subst __dep__,,$@) -MT $(addprefix $(PROJECT_OBJ_DIR)/,$(patsubst %.c,%.o,$(subst __dep__,,$@))) $(CFLAGS) >> $(wls_fapi_app_dep_file)
+
+$(OBJS) : $(PROJECT_OBJ_DIR)/%.o: %.c
+       @echo [CC]    $(subst $(PROJECT_OBJ_DIR)/,,$@)
+       @$(CC) -c $(CFLAGS) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@))
+
+
+.PHONY: xclean
+xclean : clean_dep
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+       @$(RM) $(BUILDDIR)
+
+.PHONY: clean
+clean :
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+
diff --git a/wls_lib/test/mac/mac_main.c b/wls_lib/test/mac/mac_main.c
new file mode 100644 (file)
index 0000000..4d6c902
--- /dev/null
@@ -0,0 +1,78 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @brief This file is test MAC wls lib main process
+ * @file mac_main.c
+ * @ingroup group_testmacwls
+ * @author Intel Corporation
+ **/
+
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "wls_lib.h"
+#include "mac_wls.h"
+
+#define WLS_TEST_DEV_NAME "wls"
+#define WLS_TEST_MSG_ID   1
+#define WLS_TEST_MSG_SIZE 100
+#define WLS_TEST_MEM_SIZE 2126512128 
+
+#define N_MAC_MSGS   16
+
+int main()
+{
+    p_fapi_api_queue_elem_t p_list_elem;
+    unsigned int ret;
+    unsigned int n= N_MAC_MSGS; 
+    unsigned int i;
+
+    // DPDK init
+    ret = mac_dpdk_init();
+    if (ret)
+    {
+        printf("\n[MAC] DPDK Init - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[MAC] DPDK Init - Done\n");
+
+    wls_mac_init(WLS_TEST_DEV_NAME, WLS_TEST_MEM_SIZE);
+    printf("\n[MAC] WLS Init - Done\n");
+
+    for (i=0; i< N_MAC_MSGS; i++)
+    {
+    p_list_elem = wls_mac_create_elem(WLS_TEST_MSG_ID, WLS_TEST_MSG_SIZE, 1, 0);
+      printf("\n[MAC] MAC Create Element %d- Done\n", i);
+
+    if(p_list_elem)
+    {
+        wls_mac_send_msg_to_phy((void *)p_list_elem);
+               printf("\n[MAC] Send to FAPI %d- Done\n",i);
+       }
+    }
+
+    // Receive from FAPI WLS
+    wls_mac_rx_task();
+
+    printf("\n[MAC] Exiting...\n");
+
+    return SUCCESS;
+}
+
diff --git a/wls_lib/test/mac/mac_wls.c b/wls_lib/test/mac/mac_wls.c
new file mode 100644 (file)
index 0000000..3f69884
--- /dev/null
@@ -0,0 +1,1322 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @brief This file has Shared Memory interface functions between MAC and PHY
+ * @file testmac_wls.c
+ * @ingroup group_testmac
+ * @author Intel Corporation
+ **/
+
+
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rte_eal.h>
+#include <rte_cfgfile.h>
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_launch.h>
+
+#define DPDK_WLS
+#include "wls.h"
+#include "wls_lib.h"
+#include "mac_wls.h"
+//#include "phy_printf.h"
+//#include "aux_sys.h"
+//#include "aux_timer.h"
+//#include "mlog_lnx.h"
+
+//#include "nr5g_testmac_config_test.h"
+//#include "nr5g_testmac_mac_phy_api_proc.h"
+
+
+#define MSG_MAXSIZE                         ( 16384 * 16 )
+
+
+#define TO_FREE_SIZE                        ( 10 )
+#define TOTAL_FREE_BLOCKS                   ( 50 * 12)
+#define ALLOC_TRACK_SIZE                    ( 16384 )
+
+#define MEMORY_CORRUPTION_DETECT
+#define MEMORY_CORRUPTION_DETECT_FLAG       (0xAB)
+
+typedef struct wls_mac_mem_array
+{
+    void **ppFreeBlock;
+    void *pStorage;
+    void *pEndOfStorage;
+    uint32_t nBlockSize;
+    uint32_t nBlockCount;
+} WLS_MAC_MEM_SRUCT, *PWLS_MAC_MEM_SRUCT;
+
+typedef struct wls_mac_ctx
+{
+    void *hWls;
+    void *pWlsMemBase;
+    WLS_MAC_MEM_SRUCT sWlsStruct;
+
+    uint32_t nTotalMemorySize;
+    uint32_t nTotalBlocks;
+    uint32_t nAllocBlocks;
+    uint32_t nTotalAllocCnt;
+    uint32_t nTotalFreeCnt;
+    uint32_t nTotalUlBufAllocCnt;
+    uint32_t nTotalUlBufFreeCnt;
+    uint32_t nTotalDlBufAllocCnt;
+    uint32_t nTotalDlBufFreeCnt;
+//  Support for FAPI Translator
+    uint32_t nPartitionMemSize;
+    void     *pPartitionMemBase;
+
+    volatile pthread_mutex_t lock;
+    volatile pthread_mutex_t lock_alloc;
+} WLS_MAC_CTX, *PWLS_MAC_CTX;
+
+static pthread_t *pwls_testmac_thread = NULL;
+static WLS_MAC_CTX wls_mac_iface;
+static int gwls_mac_ready = 0;
+static pid_t gwls_pid = 0;
+static uint32_t gToFreeListCnt[TO_FREE_SIZE] = {0};
+static uint64_t gpToFreeList[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = {{0L}};
+static uint8_t alloc_track[ALLOC_TRACK_SIZE];
+static uint64_t gTotalTick = 0, gUsedTick = 0;
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   ptr Pointer to display
+ *  @param[in]   size Size of data
+ *
+ *  @return  void
+ *
+ *  @description
+ *  This function displays content of Buffer - Used for debugging
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void wls_mac_show_data(void* ptr, uint32_t size)
+{
+    uint8_t *d = ptr;
+    int i;
+
+    for(i = 0; i < size; i++)
+    {
+        if ( !(i & 0xf) )
+            printf("\n");
+        printf("%02x ", d[i]);
+    }
+    printf("\n");
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param void
+ *
+ *  @return  Pointer to WLS_MAC_CTX stucture
+ *
+ *  @description
+ *  This function returns the WLS Local structure which has WLS related parameters
+ *
+**/
+//-------------------------------------------------------------------------------------------
+static PWLS_MAC_CTX wls_mac_get_ctx(void)
+{
+    return &wls_mac_iface;
+}
+
+void wls_mac_print_stats(void)
+{
+    PWLS_MAC_CTX pWls = wls_mac_get_ctx();
+
+    printf("wls_mac_free_list_all:\n");
+    printf("        nTotalBlocks[%d] nAllocBlocks[%d] nFreeBlocks[%d]\n", pWls->nTotalBlocks, pWls->nAllocBlocks, (pWls->nTotalBlocks- pWls->nAllocBlocks));
+    printf("        nTotalAllocCnt[%d] nTotalFreeCnt[%d] Diff[%d]\n", pWls->nTotalAllocCnt, pWls->nTotalFreeCnt, (pWls->nTotalAllocCnt- pWls->nTotalFreeCnt));
+    printf("        nDlBufAllocCnt[%d] nDlBufFreeCnt[%d] Diff[%d]\n", pWls->nTotalDlBufAllocCnt, pWls->nTotalDlBufFreeCnt, (pWls->nTotalDlBufAllocCnt- pWls->nTotalDlBufFreeCnt));
+    printf("        nUlBufAllocCnt[%d] nUlBufFreeCnt[%d] Diff[%d]\n\n", pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt, (pWls->nTotalUlBufAllocCnt- pWls->nTotalUlBufFreeCnt));
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   ptr Address to convert
+ *
+ *  @return  Converted address
+ *
+ *  @description
+ *  This function converts Virtual Address to Physical Address
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint64_t wls_mac_va_to_pa(void *ptr)
+{
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    uint64_t ret = (uint64_t)WLS_VA2PA(pWls->hWls, ptr);
+
+    //printf("wls_mac_va_to_pa: %p ->%p\n", ptr, (void*)ret);
+
+    return ret;
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   ptr Address to convert
+ *
+ *  @return  Converted address
+ *
+ *  @description
+ *  This function converts Physical Address to Virtual Address
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void *wls_mac_pa_to_va(uint64_t ptr)
+{
+    PWLS_MAC_CTX pWls = wls_mac_get_ctx();
+    void *ret = WLS_PA2VA(pWls->hWls, ptr);
+
+    //printf("wls_mac_pa_to_va: %p -> %p\n", (void*)ptr, ret);
+
+    return ret;
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pMemArray Pointer to WLS Memory management structure
+ *  @param[in]   pMemArrayMemory Pointer to flat buffer that was allocated
+ *  @param[in]   totalSize Total Size of flat buffer allocated
+ *  @param[in]   nBlockSize Size of each block that needs to be partitioned by memory manager
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function creates memory blocks from a flat buffer which will be used for communciation
+ *  between MAC and PHY
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray,
+                              void *pMemArrayMemory,
+                              uint32_t totalSize, uint32_t nBlockSize)
+{
+    int numBlocks = totalSize / nBlockSize;
+    void **ptr;
+    uint32_t i;
+
+    printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
+        pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
+
+    // Can't be less than pointer size
+    if (nBlockSize < sizeof(void *))
+    {
+        return FAILURE;
+    }
+
+    // Can't be less than one block
+    if (totalSize < sizeof(void *))
+    {
+        return FAILURE;
+    }
+
+    pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
+    pMemArray->pStorage = pMemArrayMemory;
+    pMemArray->pEndOfStorage = ((unsigned long*)pMemArrayMemory) + numBlocks * nBlockSize / sizeof(unsigned long);
+    pMemArray->nBlockSize = nBlockSize;
+    pMemArray->nBlockCount = numBlocks;
+
+    // Initialize single-linked list of free blocks;
+    ptr = (void **)pMemArrayMemory;
+    for (i = 0; i < pMemArray->nBlockCount; i++)
+    {
+#ifdef MEMORY_CORRUPTION_DETECT
+        // Fill with some pattern
+        uint8_t *p = (uint8_t *)ptr;
+        uint32_t j;
+
+        p += (nBlockSize - 16);
+        for (j = 0; j < 16; j++)
+        {
+            p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
+        }
+#endif
+
+        if (i == pMemArray->nBlockCount - 1)
+        {
+            *ptr = NULL;      // End of list
+        }
+        else
+        {
+            // Points to the next block
+            *ptr = (void **)(((uint8_t*)ptr) + nBlockSize);
+            ptr += nBlockSize / sizeof(unsigned long);
+        }
+    }
+
+    memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE);
+
+    return SUCCESS;
+}
+
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]    pMemArray Pointer to WLS Memory management structure
+ *  @param[out]   ppBlock Pointer where allocated memory block is stored
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function allocated a memory block from pool
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock)
+{
+    int idx;
+
+    if (pMemArray->ppFreeBlock == NULL)
+    {
+        printf("wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
+        return FAILURE;
+    }
+
+    // FIXME: Remove after debugging
+    if (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage) ||
+        ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))
+    {
+        printf("wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
+                pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+    *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+
+    if ((*pMemArray->ppFreeBlock != NULL) &&
+        (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
+        ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage)))
+    {
+        fprintf(stderr, "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+                pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+                *pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    *ppBlock = (void *) pMemArray->ppFreeBlock;
+    pMemArray->ppFreeBlock = (void **) (*pMemArray->ppFreeBlock);
+
+    idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
+    if (alloc_track[idx])
+    {
+        printf("wls_mac_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+            *pMemArray->ppFreeBlock);
+    }
+    else
+    {
+#ifdef MEMORY_CORRUPTION_DETECT
+        uint32_t nBlockSize = pMemArray->nBlockSize, i;
+        uint8_t *p = (uint8_t *)*ppBlock;
+
+        p += (nBlockSize - 16);
+        for (i = 0; i < 16; i++)
+        {
+            p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
+        }
+#endif
+        alloc_track[idx] = 1;
+    }
+
+    //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
+
+    return SUCCESS;
+}
+
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pMemArray Pointer to WLS Memory management structure
+ *  @param[in]   pBlock Pointer to block that needs to be added back to pool
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function frees a WLS block of memory and adds it back to the pool
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_free_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pBlock)
+{
+    int idx;
+    unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
+
+    pBlock = (void *)((unsigned long)pBlock & ~mask);
+
+    if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage))
+    {
+        printf("wls_mac_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n",
+               pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage);
+
+        return FAILURE;
+    }
+
+    idx = (int)(((uint64_t)pBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
+
+    if (alloc_track[idx] == 0)
+    {
+        printf("wls_mac_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
+            pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
+            pBlock);
+
+        return SUCCESS;
+
+    }
+    else
+    {
+#ifdef MEMORY_CORRUPTION_DETECT
+        uint32_t nBlockSize = pMemArray->nBlockSize, i;
+        uint8_t *p = (uint8_t *)pBlock;
+
+        p += (nBlockSize - 16);
+        for (i = 0; i < 16; i++)
+        {
+            if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG)
+            {
+                printf("ERROR: Corruption\n");
+                wls_mac_print_stats();
+                exit(-1);
+            }
+        }
+#endif
+        alloc_track[idx] = 0;
+    }
+
+    if (((void *) pMemArray->ppFreeBlock) == pBlock)
+    {
+        // Simple protection against freeing of already freed block
+        return SUCCESS;
+    }
+
+    // FIXME: Remove after debugging
+    if ((pMemArray->ppFreeBlock != NULL)
+        && (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage)
+        || ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)))
+    {
+        printf("wls_mac_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
+                pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
+        return FAILURE;
+    }
+
+    // FIXME: Remove after debugging
+    if ((pBlock < pMemArray->pStorage) ||
+        (pBlock >= pMemArray->pEndOfStorage))
+    {
+        printf("wls_mac_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
+                pMemArray, pBlock);
+        return FAILURE;
+    }
+
+    *((void **)pBlock) = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
+    pMemArray->ppFreeBlock = (void **) ((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
+
+    //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
+
+    return SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  Pointer to the memory block
+ *
+ *  @description
+ *  This function allocates a block of memory from the pool
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void *wls_mac_alloc_buffer(uint32_t size, uint32_t loc)
+{
+    void *pBlock = NULL;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
+
+    pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
+
+    if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS)
+    {
+        printf("wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc);
+        wls_mac_print_stats();
+        exit(-1);
+    }
+    else
+    {
+        pWls->nAllocBlocks++;
+    }
+
+    //printf("----------------wls_mac_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
+
+    //printf("[%p]\n", pBlock);
+
+    pWls->nTotalAllocCnt++;
+    if (loc < MAX_DL_BUF_LOCATIONS)
+        pWls->nTotalDlBufAllocCnt++;
+    else if (loc < MAX_UL_BUF_LOCATIONS)
+        pWls->nTotalUlBufAllocCnt++;
+
+    pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
+
+    return pBlock;
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   *pMsg Pointer to free
+ *
+ *  @return  void
+ *
+ *  @description
+ *  This function frees a block of memory and adds it back to the pool
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void wls_mac_free_buffer(void *pMsg, uint32_t loc)
+{
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
+
+    pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
+
+    //printf("----------------wls_mac_free_buffer: buf[%p] loc[%d]\n", pMsg, loc);
+    if (wls_mac_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS)
+    {
+        pWls->nAllocBlocks--;
+    }
+    else
+    {
+        printf("wls_mac_free_buffer Free error\n");
+        wls_mac_print_stats();
+        exit(-1);
+    }
+
+    pWls->nTotalFreeCnt++;
+    if (loc < MAX_DL_BUF_LOCATIONS)
+        pWls->nTotalDlBufFreeCnt++;
+    else if (loc < MAX_UL_BUF_LOCATIONS)
+        pWls->nTotalUlBufFreeCnt++;
+
+    pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  Number of free blocks
+ *
+ *  @description
+ *  This function queries the number of free blocks in the system
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_num_free_blocks(void)
+{
+    PWLS_MAC_CTX pWls = wls_mac_get_ctx();
+
+    return (pWls->nTotalBlocks- pWls->nAllocBlocks);
+}
+
+
+
+void wls_mac_free_list_all(void)
+{
+    PWLS_MAC_CTX pWls = wls_mac_get_ctx();
+    uint32_t idx;
+
+    for (idx = 0; idx < TO_FREE_SIZE; idx++)
+    {
+        wls_mac_free_list(idx);
+    }
+
+    wls_mac_print_stats();
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pWls Pointer to the WLS_MAC_CTX structure
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function created a partition and blocks of WLS memory for API exchange between MAC and PHY
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_create_partition(PWLS_MAC_CTX pWls)
+{
+    memset(pWls->pWlsMemBase, 0xCC, pWls->nTotalMemorySize);
+    pWls->pPartitionMemBase = pWls->pWlsMemBase;
+    pWls->nPartitionMemSize = pWls->nTotalMemorySize/2;
+    pWls->nTotalBlocks = pWls->nTotalMemorySize / MSG_MAXSIZE;
+    return wls_mac_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, pWls->nPartitionMemSize, MSG_MAXSIZE);
+}
+
+
+
+static volatile int gWlsMacPrintThreadInfo = 0;
+
+void wls_mac_print_thread_info(void)
+{
+    gWlsMacPrintThreadInfo = 1;
+
+    return;
+}
+
+void wls_mac_get_time_stats(uint64_t *pTotal, uint64_t *pUsed, uint32_t nClear)
+{
+    *pTotal = gTotalTick;
+    *pUsed = gUsedTick;
+
+    if (nClear)
+    {
+        gTotalTick = 0;
+        gUsedTick = 0;
+    }
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pMsgHeader Pointer to TxSdu Message Block
+ *  @param[in]   count Location in Free List Array
+ *  @param[in]   pToFreeList Array where all the blocks to free are stored
+ *
+ *  @return  New Location in free list array
+ *
+ *  @description
+ *  This function adds all the messages in a subframe coming from L1 to L2 to a free array to be
+ *  freed back to the queue at a later point in time.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_sdu_zbc_block_add_to_free(void* pMsgHeaderHead, int count, uint64_t *pToFreeList)
+{
+    fapi_msg_t *p_fapi_msg = (fapi_msg_t *) pMsgHeaderHead;
+
+    if (p_fapi_msg->msg_id == FAPI_TX_DATA_REQUEST)
+    {
+        fapi_tx_data_req_t *p_tx_data_req =  (fapi_tx_data_req_t *) p_fapi_msg;
+        p_fapi_api_queue_elem_t p_list_elm = ((p_fapi_api_queue_elem_t) p_tx_data_req) - 1;
+        p_fapi_api_queue_elem_t p_sdu_elm = p_list_elm->p_tx_data_elm_list;
+        while(p_sdu_elm)
+        {
+            if (count < TOTAL_FREE_BLOCKS)
+            {
+                pToFreeList[count++] = (uint64_t) p_sdu_elm;
+            }
+            else
+            {
+                printf("wls_mac_sdu_zbc_block_add_to_free: ERROR: Reached max Number of Free Blocks\n");
+                return count;
+            }
+            p_sdu_elm = p_sdu_elm->p_next;
+        }
+    }
+
+    return count;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pListElem Pointer to List element header
+ *  @param[in]   idx Subframe Number
+ *
+ *  @return  Number of blocks freed
+ *
+ *  @description
+ *  This function Frees all the blocks in a List Element Linked List coming from L1 by storing
+ *  them into an array to be freed at a later point in time.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_add_to_free(p_fapi_api_queue_elem_t pListElem, uint32_t idx)
+{
+    p_fapi_api_queue_elem_t pNextMsg = NULL;
+    void* pMsgHeader;
+    int count = gToFreeListCnt[idx], nZbcBlocks;
+
+    pNextMsg = pListElem;
+
+    while (pNextMsg)
+    {
+        if (count < TOTAL_FREE_BLOCKS)
+        {
+            gpToFreeList[idx][count] = (uint64_t)pNextMsg;
+        }
+        else
+        {
+            printf("wls_mac_add_to_free: ERROR: Reached max Number of Free Blocks\n");
+            return count;
+        }
+
+        if (pNextMsg->msg_type != FAPI_MSG_HEADER_IND)
+        {
+            pMsgHeader = (void *) (pNextMsg + 1);
+            count++;
+            count = wls_mac_sdu_zbc_block_add_to_free(pMsgHeader, count, gpToFreeList[idx]);
+        }
+
+        if (pNextMsg->p_next)
+        {
+            pNextMsg = (p_fapi_api_queue_elem_t)(pNextMsg->p_next);
+        }
+        else
+        {
+            pNextMsg = 0;
+        }
+    }
+
+    gpToFreeList[idx][count] = 0L;
+    gToFreeListCnt[idx] = count;
+
+    printf("To Free %d\n", count);
+
+    return count;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   idx subframe Number
+ *
+ *  @return  Number of blocks freed
+ *
+ *  @description
+ *  This function frees all blocks that have been added to the free array
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_free_list(uint32_t idx)
+{
+    p_fapi_api_queue_elem_t pNextMsg = NULL;
+    int count = 0;
+
+    if(idx >= TO_FREE_SIZE){
+        printf("Error idx %d\n", idx);
+        return 0;
+    }
+
+    pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
+
+    while (pNextMsg)
+    {
+        wls_mac_free_buffer(pNextMsg, MIN_DL_BUF_LOCATIONS+0);
+        gpToFreeList[idx][count] = (uint64_t) NULL;
+        count++;
+        if (gpToFreeList[idx][count])
+            pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
+        else
+            pNextMsg = 0;
+    }
+
+    printf("Free %d\n", count);
+    gToFreeListCnt[idx] = 0;
+
+    return count;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
+ *  needed by the L2
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_ready(void)
+{
+    int ret = 0;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    ret = WLS_Ready(pWls->hWls);
+
+    return ret;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  Number of blocks of APIs received
+ *
+ *  @description
+ *  This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
+ *  during runtime when L2 sends a API to L1 and then waits for response back.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_wait(void)
+{
+    int ret = 0;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+
+    ret = WLS_Wait(pWls->hWls);
+
+    return ret;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer to the linked list
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_recv(uint64_t *data, uint16_t *nFlags)
+{
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    uint32_t msgSize = 0;
+    uint16_t msgType = 0;
+
+    *data = WLS_Get(pWls->hWls, &msgSize, &msgType, nFlags);
+
+    return msgSize;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pMsg Pointer to API block that needs to be sent to L1
+ *  @param[in]   MsgSize Size of Message
+ *  @param[in]   MsgTypeID Message Id
+ *  @param[in]   Flags Special Flags needed for WLS
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function adds a block of API from L2 to L1 which will be sent later
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_put(uint64_t pMsg, uint32_t MsgSize, uint16_t MsgTypeID, uint16_t Flags)
+{
+    int ret = 0;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+
+    //printf("wls_mac_put: %p size: %d type: %d nFlags: %d\n", (void*)pMsg, MsgSize, MsgTypeID, Flags);
+    //  wls_mac_show_data((void*)wls_alloc_buffer(pMsg), MsgSize);
+    ret = WLS_Put(pWls->hWls, pMsg, MsgSize, MsgTypeID, Flags);
+
+    return ret;
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   pMsgHeader Pointer to the TxSduReq Message block
+ *  @param[in]   nFlags Special nFlags needed for WLS
+ *  @param[in]   nZbcBlocks Number of ZBC blocks in list
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function adds all the ZBC blocks in a TXSDU Message and prepares them to be sent to the L1
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_send_zbc_blocks(void *pMsgHeaderHead, uint16_t nFlags, int *nZbcBlocks, uint32_t nFlagsUrllc)
+{
+    fapi_tx_data_req_t *p_tx_data_req = (fapi_tx_data_req_t *) pMsgHeaderHead;
+    p_fapi_api_queue_elem_t p_list_elm = ((p_fapi_api_queue_elem_t) p_tx_data_req) - 1;
+    p_list_elm = p_list_elm->p_tx_data_elm_list;
+
+    int ret = 0;
+    uint8_t nMsgType;
+    uint32_t isLast, nPduLen;
+    uint16_t list_flags = nFlags;
+    void *pPayload = NULL;
+
+    printf("wls_mac_put ZBC blocks: %d\n", nFlags);
+
+    while (p_list_elm)
+    {
+        nPduLen = p_list_elm->msg_len + sizeof(fapi_api_queue_elem_t);
+        pPayload = (void *) p_list_elm;
+        nMsgType = FAPI_MSG_PHY_ZBC_BLOCK_REQ;
+
+        if (p_list_elm->p_next)
+            isLast = 0;
+        else
+            isLast = 1;
+
+        if ((list_flags & WLS_TF_FIN) && isLast)
+            nFlags = WLS_SG_LAST; // TXSDU.req was last block in the list hence ZBC block is last
+        else
+            nFlags = WLS_SG_NEXT; // more blocks in the list
+
+        printf("wls_mac_put 0x%016lx  msg type: %x nFlags %x\n", (uint64_t) pPayload, nMsgType, nFlags);
+        ret = wls_mac_put((uint64_t) pPayload, nPduLen, nMsgType, nFlags);
+        if (ret != 0)
+        {
+            printf("Error ZBC block 0x%016lx\n", (uint64_t) pPayload);
+            return FAILURE;
+        }
+        p_list_elm = p_list_elm->p_next;
+    }
+
+    return SUCCESS;
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]    pMsgHeader Pointer to the TxSDuReq Message block
+ *  @param[out]   nZbcBlocks Number of ZBC blocks
+ *
+ *  @return  1 if this block is a TxSduReq message. 0 else.
+ *
+ *  @description
+ *  This function checks if a block is a TxSduReq messages and counts the number of ZBC blocks in this
+ *  API
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_is_sdu_zbc_block(void* pMsgHeaderHead, int *nZbcBlocks)
+{
+    fapi_tx_data_req_t *p_tx_data_req = (fapi_tx_data_req_t *) pMsgHeaderHead;
+    p_fapi_api_queue_elem_t p_list_elm = 
+        ((p_fapi_api_queue_elem_t) p_tx_data_req) - 1;
+    *nZbcBlocks = 0;
+
+    if (p_tx_data_req->header.msg_id == FAPI_TX_DATA_REQUEST &&
+            p_list_elm->p_tx_data_elm_list)
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   data Pointer to the Linked list header
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function sends a list of APIs to the L1
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_send_msg_to_phy(void *data)
+{
+    uint32_t  ret = SUCCESS;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
+    p_fapi_api_queue_elem_t pCurrMsg = NULL;
+    p_fapi_api_queue_elem_t pListElem = NULL;
+    static uint32_t idx = 0;
+
+    fapi_msg_t *pMsgHeader;
+    uint16_t nFlags;
+    int nZbcBlocks = 0, isZbc = 0, count = 0;
+
+    printf("wls_mac_send_msg_to_phy\n");
+    printf("data (0x%lX) sending to phy...\n", (unsigned long)data);
+
+    pthread_mutex_lock((pthread_mutex_t *)&pWls->lock);
+
+    if (gwls_mac_ready)
+    {
+        pListElem = (p_fapi_api_queue_elem_t)data;
+        wls_mac_add_to_free(pListElem, idx);
+        count++;
+
+
+        ret = wls_mac_put(wls_mac_va_to_pa(pListElem),
+                pListElem->msg_len + sizeof(fapi_api_queue_elem_t),
+                pMsgHeader->msg_id, nFlags);
+        if (ret != 0)
+        {
+            printf("Error\n");
+            pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
+            return FAILURE;
+        }
+    }
+
+    pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
+    return ret;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  Number of blocks added
+ *
+ *  @description
+ *  This function add WLS blocks to the L1 Array which will be used by L1 in every TTI to
+ *  populate and send back APIs to the MAC
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int wls_mac_add_blocks_to_ul(void)
+{
+    int ret = 0;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+
+    void *pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+0);
+
+    if(pMsg)
+    {
+        /* allocate blocks for UL transmittion */
+        while(WLS_EnqueueBlock(pWls->hWls,(uint64_t)wls_mac_va_to_pa(pMsg)))
+        {
+            ret++;
+            pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+1);
+            if(WLS_EnqueueBlock(pWls->hWls,(uint64_t)wls_mac_va_to_pa(pMsg)))
+            {
+                ret++;
+                pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+1);
+            }
+
+            if(!pMsg)
+                break;
+        }
+
+        // free not enqueued block
+        if(pMsg)
+        {
+            wls_mac_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS+3);
+        }
+    }
+
+    return ret;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param[in]   data Thread Local Context Structure Pointer
+ *
+ *  @return  NULL
+ *
+ *  @description
+ *  This is the WLS Receiver thread that is created at Testmac Init and is responsible for receiving
+ *  APIs from L1 to MAC
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void *wls_mac_rx_task()
+{
+    void*    buffer_va = 0;
+    uint64_t      buffer_pa = 0;
+    uint32_t get,i, rc = 0;
+
+    uint32_t size  = 0;
+    uint64_t tWake = 0, tWakePrev = 0, tSleep = 0;
+    uint16_t nFlags;
+    p_fapi_api_queue_elem_t pElm   = NULL;
+    p_fapi_api_queue_elem_t pFirst = NULL;
+    p_fapi_api_queue_elem_t pPrev  = NULL;
+
+
+    usleep(1000);
+
+    wls_mac_ready();
+
+    while (1)
+    {
+        get = wls_mac_wait();
+
+        if (get == 0)
+        {
+            continue;
+        }
+        printf("Got %d messages from FAPI Translator\n", get);
+        while(get--)
+        {
+            size =  wls_mac_recv((uint64_t *)&buffer_pa, &nFlags);
+            buffer_va =  wls_mac_pa_to_va(buffer_pa);
+            pElm = (p_fapi_api_queue_elem_t) buffer_va;
+
+
+            if (pFirst == NULL)
+                pFirst = pElm;
+
+            if (nFlags != WLS_TF_FIN)
+            {
+                wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pElm, i);
+                i++;
+                                               }
+            if(pPrev)
+                pPrev->p_next = pElm;
+
+            pPrev = pElm;
+
+            if ((nFlags & WLS_TF_FIN))
+            {
+                // send to MAC
+                if (pPrev)
+                {
+                    pPrev->p_next =  NULL;
+                }
+
+                wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pFirst, i);
+
+                pFirst= NULL;
+                pPrev = NULL;
+                return NULL;
+            }
+            else
+            {
+            }
+        }
+        wls_mac_add_blocks_to_ul();
+
+    }
+
+    return NULL;
+}
+
+void wls_mac_print_recv_list(p_fapi_api_queue_elem_t list, uint32_t i)
+{
+    printf("\nMAC received response %d from FAPI\n",i);
+}
+
+p_fapi_api_queue_elem_t wls_mac_create_elem(uint16_t num_msg, uint32_t align_offset, uint32_t msg_type, uint32_t n_loc)
+{
+    p_fapi_api_queue_elem_t p_list_elem;
+
+    p_list_elem = (p_fapi_api_queue_elem_t)wls_mac_alloc_buffer(num_msg * align_offset + sizeof(fapi_api_queue_elem_t), n_loc);
+
+    //Fill header for link list of API messages
+    if (p_list_elem)
+    {
+        p_list_elem->msg_type = (uint8_t)msg_type;
+        p_list_elem->num_message_in_block = 1;
+        p_list_elem->align_offset = (uint16_t)align_offset;
+        p_list_elem->msg_len = num_msg * align_offset;
+        p_list_elem->p_next = NULL;
+    }
+
+    return p_list_elem;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function initialized the WLS threads for the Testmac and allocates memory needed to
+ *  exchange APIs between MAC and PHY
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_init(char * wls_device_name, uint64_t nTotalMemorySize)
+{
+    uint32_t ret = FAILURE;
+    PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
+    uint8_t *pMemZone;
+    static const struct rte_memzone *mng_memzone;
+    wls_drv_ctx_t *pDrv_ctx;
+
+    sleep(1);
+
+    pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL);
+    pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL);
+
+    pWls->nTotalAllocCnt = 0;
+    pWls->nTotalFreeCnt = 0;
+    pWls->nTotalUlBufAllocCnt = 0;
+    pWls->nTotalUlBufFreeCnt = 0;
+    pWls->nTotalDlBufAllocCnt = 0;
+    pWls->nTotalDlBufFreeCnt = 0;
+
+    pWls->hWls = WLS_Open(wls_device_name, WLS_MASTER_CLIENT, nTotalMemorySize);
+    if (pWls->hWls)
+    {
+        /* allocate chuck of memory */
+        pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nTotalMemorySize);
+        if (pWls->pWlsMemBase)
+        {
+            pWls->nTotalMemorySize = (uint32_t) nTotalMemorySize;
+
+            ret = wls_mac_create_partition(pWls);
+
+            if (ret == SUCCESS)
+            {
+                int nBlocks = 0;
+                gwls_mac_ready = 1;
+
+                nBlocks = WLS_EnqueueBlock(pWls->hWls, wls_mac_va_to_pa(wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+2)));
+                /* allocate blocks for UL transmition */
+                while(WLS_EnqueueBlock(pWls->hWls, wls_mac_va_to_pa(wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+3))))
+                {
+                    nBlocks++;
+                }
+
+                printf("WLS inited ok [%d]\n\n", nBlocks);
+            }
+            else
+            {
+                printf("can't create WLS Partition");
+                return FAILURE;
+            }
+
+        }
+        else
+        {
+            printf("can't allocate WLS memory");
+            return FAILURE;
+        }
+    }
+    else
+    {
+        printf("can't open WLS instance");
+        return FAILURE;
+    }
+
+    return SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_testmac
+ *
+ *  @param   void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function destroys the WLS layer for the testmac and de-allocates any memory used
+ *
+**/
+//-------------------------------------------------------------------------------------------
+uint32_t wls_mac_destroy(void)
+{
+    PWLS_MAC_CTX pWls = wls_mac_get_ctx();
+
+    if (pwls_testmac_thread)
+    {
+        pthread_cancel(*pwls_testmac_thread);
+
+        free(pwls_testmac_thread);
+        pwls_testmac_thread = NULL;
+
+        if(pWls->pWlsMemBase)
+        {
+            WLS_Free(pWls->hWls, pWls->pWlsMemBase);
+        }
+
+        WLS_Close(pWls->hWls);
+        printf("wls_mac_rx_task:          [PID: %6d]... Stopping\n", gwls_pid);
+    }
+
+    return SUCCESS;
+}
+
+uint8_t mac_dpdk_init()
+{
+    uint8_t retval;
+    char whitelist[32];
+    uint8_t i;
+
+    char *argv[] = {"mac_app", "--proc-type=secondary",
+        "--file-prefix", "wls", whitelist};
+    
+    int argc = RTE_DIM(argv);
+
+    /* initialize EAL first */
+    sprintf(whitelist, "-w %s",  "0000:00:06.0");
+    printf("[MAC] Calling rte_eal_init: ");
+
+    for (i = 0; i < RTE_DIM(argv); i++)
+    {
+        printf("%s ", argv[i]);
+    }
+    printf("\n");
+
+    if (rte_eal_init(argc, argv) < 0)
+        rte_panic("Cannot init EAL\n");
+
+    return SUCCESS;
+}
diff --git a/wls_lib/test/mac/mac_wls.h b/wls_lib/test/mac/mac_wls.h
new file mode 100644 (file)
index 0000000..59a0855
--- /dev/null
@@ -0,0 +1,77 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @brief This file has Shared Memory interface functions between MAC and PHY
+ * @file testmac_wls.h
+ * @ingroup group_testmac
+ * @author Intel Corporation
+ **/
+
+#ifndef _TESTMAC_WLS_H_
+#define _TESTMAC_WLS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#include "common_typedef.h"
+#include "fapi_interface.h"
+
+#define SUCCESS 0
+#define FAILURE 1
+
+#define MAX_NUM_LOCATIONS           (50)
+
+#define MIN_DL_BUF_LOCATIONS        (0)                                             /* Used for stats collection 0-49 */
+#define MIN_UL_BUF_LOCATIONS        (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS)      /* Used for stats collection 50-99 */
+
+#define MAX_DL_BUF_LOCATIONS        (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS)          /* Used for stats collection 0-49 */
+#define MAX_UL_BUF_LOCATIONS        (MIN_UL_BUF_LOCATIONS + MAX_NUM_LOCATIONS)          /* Used for stats collection 50-99 */
+
+typedef struct tagZBC_LIST_ITEM
+{
+    uint64_t pMsg;
+    uint32_t MsgSize;
+} ZBC_LIST_ITEM, *PZBC_LIST_ITEM;
+
+
+uint32_t wls_mac_init(char * wls_device_name, uint64_t nWlsMemorySize);
+void wls_mac_print_thread_info(void);
+uint32_t wls_mac_destroy(void);
+void *wls_mac_alloc_buffer(uint32_t size, uint32_t loc);
+uint32_t wls_mac_send_msg_to_phy(void *data);
+uint64_t wls_mac_va_to_pa(void *ptr);
+void *wls_mac_pa_to_va(uint64_t ptr);
+void wls_mac_free_buffer(void *pMsg, uint32_t loc);
+void wls_mac_get_time_stats(uint64_t *pTotal, uint64_t *pUsed, uint32_t nClear);
+void wls_mac_free_list_all(void);
+int wls_mac_free_list(uint32_t idx);
+p_fapi_api_queue_elem_t wls_mac_create_elem(uint16_t num_msg, uint32_t align_offset, uint32_t msg_type, uint32_t n_loc);
+void wls_mac_print_recv_list(p_fapi_api_queue_elem_t list, uint32_t i);
+uint8_t mac_dpdk_init();
+void *wls_mac_rx_task();
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* #ifndef _TESTMAC_WLS_H_ */
+
+
diff --git a/wls_lib/test/mac/makefile b/wls_lib/test/mac/makefile
new file mode 100644 (file)
index 0000000..b6ba703
--- /dev/null
@@ -0,0 +1,172 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+.SUFFIXES: .o .c .s .i .cpp
+
+# Makefile to build TestMac application
+
+##############################################################
+#  Tools configuration
+##############################################################
+CC := icc
+CPP := icpc
+AS := as
+AR := ar
+LD := icc
+OBJDUMP := objdump
+
+ifeq ($(SHELL),cmd.exe)
+MD := mkdir.exe -p
+RM := rm.exe -rf
+else
+MD := mkdir -p
+RM := rm -rf
+endif
+
+##############################################################
+# TARGET
+##############################################################
+ifeq ($(RTE_TARGET),)
+    RTE_TARGET :=x86_64-native-linuxapp-icc
+endif
+##############################################################
+# DPDK
+##############################################################
+ifeq ($(RTE_SDK),)
+$(info Please make sure RTE_SDK points to DPDK folder (current version of DPDK is 18.08))
+    RTE_SDK := /opt/dpdk-18.08
+endif
+
+##############################################################
+# Projects folders
+##############################################################
+ORANDIR                  := $(DIR_WIRELESS_ORAN)
+WLSDIR            := $(DIR_WIRELESS_WLS)
+BUILDDIR          := ../build/mac
+SRCDIR            := $(CURDIR)
+
+wls_mac_app_dep_file = $(BUILDDIR)/dep_file
+
+APP := ../bin/mac/mac_app
+
+INC := \
+ $(WLSDIR) \
+ $(SRCDIR) \
+ $(RTE_SDK)/$(RTE_TARGET)/include \
+ $(ORANDIR)/include \
+ $(ORANDIR) \
+ #$(FLEXRANDIR)/source/nr5g/api \
+ #$(FLEXRANDIR)/source/common \
+
+INC := $(addprefix -I,$(INC))
+DEFS := USE_WO_LOCK _GNU_SOURCE NR5G 
+
+ifneq ($(PRINTDBG),)
+DEFS := $(DEFS) PRINTF_DBG_OK
+endif
+
+ifeq ($(DEBUG_MODE),true)
+DEFS := $(DEFS) DEBUG_MODE
+endif
+
+DEFS := $(addprefix -D,$(DEFS))
+
+CFLAGS := -g -Wall -wd9 -Wno-deprecated-declarations -Wimplicit-function-declaration -fasm-blocks $(DEFS) $(INC)
+
+ifeq ($(PRINTDBG),)
+CFLAGS := $(CFLAGS) -Werror
+endif
+
+RTE_LIBS := -L$(RTE_SDK)/$(RTE_TARGET)/lib -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lrte_ethdev -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_pci -Wl,-lrte_net -Wl,-lrte_eal -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ring -Wl,-lrt -Wl,-lm -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
+LDFLAGS := -g  -Wl,-lrt -Wl,-lpthread -Wl,-lhugetlbfs -Wl,-lm -Wl,-lnuma -L $(WLSDIR) -lwls
+
+LINUX_WLS_MAC_APP_SRC := \
+       $(SRCDIR)/mac_main.c \
+       $(SRCDIR)/mac_wls.c \
+
+OBJS := $(LINUX_WLS_MAC_APP_SRC:.c=.o)
+
+PROJECT_OBJ_DIR = $(BUILDDIR)
+
+OBJS := $(addprefix $(PROJECT_OBJ_DIR)/,$(OBJS))
+
+DIRLIST := $(sort $(dir $(OBJS)))
+
+CC_DEPS := $(addprefix __dep__,$(LINUX_WLS_MAC_APP_SRC))
+
+GEN_DEP :=
+ifeq ($(wildcard $(wls_mac_app_dep_file)),)
+GEN_DEP := regenerate_dep
+endif
+
+.PHONY: $(APP)
+$(APP): $(DIRLIST) echo_options $(GEN_DEP) $(OBJS)
+       @echo [LD] $(APP)
+       @$(CC) -o $(APP) $(OBJS) $(RTE_LIBS) $(LDFLAGS)
+#      $(OBJDUMP) -d $(APP) > $(APP).asm
+
+.PHONY : echo_options
+echo_options:
+       @echo [CFLAGS]  $(CFLAGS)
+       @echo [LDFAGS]  $(LDFLAGS)
+
+
+ifneq ($(wildcard $(wls_mac_app_dep_file)),)
+include $(wls_mac_app_dep_file)
+endif
+
+$(DIRLIST) :
+       -@$(MD) $@
+
+.PHONY : regenerate_dep
+regenerate_dep : clean_dep echo_regeenrate_dep  $(CC_DEPS)
+
+.PHONY: clean_dep
+clean_dep:
+       $(RM) $(wls_mac_app_dep_file)
+
+.PHONY : echo_regeenrate_dep
+echo_regeenrate_dep:
+       @echo regenerating dep files
+
+
+.PHONY : CC_DEPS
+$(CC_DEPS):
+       @$(CC) -MM $(subst __dep__,,$@) -MT $(addprefix $(PROJECT_OBJ_DIR)/,$(patsubst %.c,%.o,$(subst __dep__,,$@))) $(CFLAGS) >> $(wls_mac_app_dep_file)
+
+$(OBJS) : $(PROJECT_OBJ_DIR)/%.o: %.c
+       @echo [CC]    $(subst $(PROJECT_OBJ_DIR)/,,$@)
+       @echo "";echo $@
+       @echo "";echo $(subst $(PROJECT_OBJ_DIR)/,,$@)
+       @echo "";echo $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@))
+       @echo ""
+       $(CC) -c $(CFLAGS) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@))
+
+
+.PHONY: xclean
+xclean : clean_dep
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+       @$(RM) $(BUILDDIR)
+
+.PHONY: clean
+clean :
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+
diff --git a/wls_lib/test/phy/makefile b/wls_lib/test/phy/makefile
new file mode 100644 (file)
index 0000000..f18d9d2
--- /dev/null
@@ -0,0 +1,162 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+.SUFFIXES: .o .c .s .i .cpp
+
+# Makefile to build Testphy application
+
+##############################################################
+#  Tools configuration
+##############################################################
+CC := icc
+CPP := icpc
+AS := as
+AR := ar
+LD := icc
+OBJDUMP := objdump
+
+ifeq ($(SHELL),cmd.exe)
+MD := mkdir.exe -p
+RM := rm.exe -rf
+else
+MD := mkdir -p
+RM := rm -rf
+endif
+
+##############################################################
+# TARGET
+##############################################################
+ifeq ($(RTE_TARGET),)
+    RTE_TARGET :=x86_64-native-linuxapp-icc
+endif
+##############################################################
+# DPDK
+##############################################################
+ifeq ($(RTE_SDK),)
+$(info Please make sure RTE_SDK points to DPDK folder (current version of DPDK is 18.08))
+    RTE_SDK := /opt/dpdk-18.08
+endif
+
+##############################################################
+# Projects folders
+##############################################################
+WLSDIR            := $(DIR_WIRELESS_WLS)
+BUILDDIR          := ../build/phy
+SRCDIR            := $(CURDIR)
+
+wls_phy_app_dep_file = $(BUILDDIR)/dep_file
+
+APP := ../bin/phy/phy_app
+
+INC := \
+ $(WLSDIR) \
+ $(SRCDIR) \
+ $(RTE_SDK)/$(RTE_TARGET)/include \
+
+INC := $(addprefix -I,$(INC))
+DEFS := USE_WO_LOCK _GNU_SOURCE NR5G
+
+ifneq ($(PRINTDBG),)
+DEFS := $(DEFS) PRINTF_DBG_OK
+endif
+
+ifeq ($(DEBUG_MODE),true)
+DEFS := $(DEFS) DEBUG_MODE
+endif
+
+DEFS := $(addprefix -D,$(DEFS))
+
+CFLAGS := -g -Wall -wd9 -Wno-deprecated-declarations -Wimplicit-function-declaration -fasm-blocks $(DEFS) $(INC)
+
+ifeq ($(PRINTDBG),)
+CFLAGS := $(CFLAGS) -Werror
+endif
+
+RTE_LIBS := -L$(RTE_SDK)/$(RTE_TARGET)/lib -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lrte_ethdev -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_pci -Wl,-lrte_net -Wl,-lrte_eal -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ring -Wl,-lrt -Wl,-lm -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
+LDFLAGS := -g -Wl,-lrt -Wl,-lpthread -Wl,-lhugetlbfs -Wl,-lm -Wl,-lnuma -L $(WLSDIR) -lwls
+
+LINUX_WLS_PHY_APP_SRC := \
+       $(SRCDIR)/phy_main.c \
+
+OBJS := $(LINUX_WLS_PHY_APP_SRC:.c=.o)
+
+PROJECT_OBJ_DIR = $(BUILDDIR)
+
+OBJS := $(addprefix $(PROJECT_OBJ_DIR)/,$(OBJS))
+
+DIRLIST := $(sort $(dir $(OBJS)))
+
+CC_DEPS := $(addprefix __dep__,$(LINUX_WLS_PHY_APP_SRC))
+
+GEN_DEP :=
+ifeq ($(wildcard $(wls_phy_app_dep_file)),)
+GEN_DEP := regenerate_dep
+endif
+
+.PHONY: $(APP)
+$(APP): $(DIRLIST) echo_options $(GEN_DEP) $(OBJS)
+       @echo [LD] $(APP)
+       @$(CC) -o $(APP) $(OBJS) $(RTE_LIBS) $(LDFLAGS)
+#      $(OBJDUMP) -d $(APP) > $(APP).asm
+
+.PHONY : echo_options
+echo_options:
+       @echo [CFLAGS]  $(CFLAGS)
+       @echo [LDFAGS]  $(LDFLAGS)
+
+
+ifneq ($(wildcard $(wls_phy_app_dep_file)),)
+include $(wls_phy_app_dep_file)
+endif
+
+$(DIRLIST) :
+       -@$(MD) $@
+
+.PHONY : regenerate_dep
+regenerate_dep : clean_dep echo_regeenrate_dep  $(CC_DEPS)
+
+.PHONY: clean_dep
+clean_dep:
+       $(RM) $(wls_phy_app_dep_file)
+
+.PHONY : echo_regeenrate_dep
+echo_regeenrate_dep:
+       @echo regenerating dep files
+
+
+.PHONY : CC_DEPS
+$(CC_DEPS):
+       @$(CC) -MM $(subst __dep__,,$@) -MT $(addprefix $(PROJECT_OBJ_DIR)/,$(patsubst %.c,%.o,$(subst __dep__,,$@))) $(CFLAGS) >> $(wls_phy_app_dep_file)
+
+$(OBJS) : $(PROJECT_OBJ_DIR)/%.o: %.c
+       @echo [CC]    $(subst $(PROJECT_OBJ_DIR)/,,$@)
+       @$(CC) -c $(CFLAGS) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@))
+
+
+.PHONY: xclean
+xclean : clean_dep
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+       @$(RM) $(BUILDDIR)
+
+.PHONY: clean
+clean :
+       @$(RM) $(OBJS)
+       @$(RM) $(APP)
+
diff --git a/wls_lib/test/phy/phy_main.c b/wls_lib/test/phy/phy_main.c
new file mode 100644 (file)
index 0000000..cf3dd61
--- /dev/null
@@ -0,0 +1,217 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @brief This file is test PHY wls lib main process
+ * @file phy_main.c
+ * @ingroup group_testphywls
+ * @author Intel Corporation
+ **/
+
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_eal.h>
+#include <rte_cfgfile.h>
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_launch.h>
+
+#include "wls_lib.h"
+
+#define SUCCESS 0
+#define FAILURE 1
+#define WLS_TEST_DEV_NAME "wls"
+#define WLS_TEST_MSG_ID   1
+#define WLS_TEST_MSG_SIZE 100
+#define WLS_TEST_MEM_SIZE 2126512128
+#define NUM_PHY_MSGS  16
+
+typedef void* WLS_HANDLE;
+void *g_shmem;
+uint64_t g_shmem_size;
+
+WLS_HANDLE  g_fapi_wls, g_phy_wls;
+
+uint8_t    phy_dpdk_init(void);
+uint8_t    phy_wls_init(const char *dev_name, unsigned long long mem_size);
+uint64_t   phy_fapi_recv();
+uint8_t    phy_fapi_send();
+
+int main()
+{
+    int64_t ret;
+    uint64_t p_msg;
+
+    // DPDK init
+    ret = phy_dpdk_init();
+    if (ret)
+    {
+        printf("\n[PHY] DPDK Init - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[PHY] DPDK Init - Done\n");
+
+    // WLS init
+    ret = phy_wls_init(WLS_TEST_DEV_NAME, WLS_TEST_MEM_SIZE);
+    if(ret)
+    {
+        printf("\n[PHY] WLS Init - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[PHY] WLS Init - Done\n");
+
+    // Receive from MAC WLS
+    p_msg = phy_fapi_recv();
+    if (!p_msg)
+    {
+        printf("\n[PHY] Receive from FAPI - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[PHY] Receive from FAPI - Done\n");
+
+    // Sent to PHY WLS
+    ret = phy_fapi_send();
+    if (ret)
+    {
+        printf("\n[PHY] Send to FAPI - Failed\n");
+        return FAILURE;
+    }
+    printf("\n[PHY] Send to FAPI - Done\n");
+
+    printf("\n[PHY] Exiting...\n");
+
+    return SUCCESS;
+}
+
+uint8_t phy_dpdk_init(void)
+{
+    char whitelist[32];
+    uint8_t i;
+
+    char *argv[] = {"phy_app", "--proc-type=primary",
+        "--file-prefix", "wls", whitelist};
+    
+    int argc = RTE_DIM(argv);
+
+    /* initialize EAL first */
+    sprintf(whitelist, "-w %s",  "0000:00:06.0");
+    printf("[PHY] Calling rte_eal_init: ");
+
+    for (i = 0; i < RTE_DIM(argv); i++)
+    {
+        printf("%s ", argv[i]);
+    }
+    printf("\n");
+
+    if (rte_eal_init(argc, argv) < 0)
+        rte_panic("Cannot init EAL\n");
+
+    return SUCCESS;
+}
+
+uint8_t phy_wls_init(const char *dev_name, unsigned long long mem_size)
+{
+    g_phy_wls = WLS_Open(dev_name, WLS_SLAVE_CLIENT, mem_size);
+    if(NULL == g_phy_wls)
+    {
+        return FAILURE;
+    }
+    g_shmem_size = mem_size;
+
+    g_shmem = WLS_Alloc(g_phy_wls, g_shmem_size);
+    if (NULL == g_shmem)
+    {
+        printf("Unable to alloc WLS Memory\n");
+        return FAILURE;
+    }
+    return SUCCESS;
+}
+
+uint64_t phy_fapi_recv()
+{
+    uint8_t  num_blks = 0;
+    uint64_t p_msg;
+    uint32_t msg_size;
+    uint16_t msg_id;
+    uint16_t flags;
+       uint32_t i=0;
+
+               
+       while (1)
+       {
+    num_blks = WLS_Wait(g_phy_wls);
+            printf("WLS_Wait returns %d blocks\n",num_blks);
+    
+    if (num_blks)
+    {
+        p_msg = WLS_Get(g_phy_wls, &msg_size, &msg_id, &flags);
+                       if (p_msg)
+                       {
+                               printf("\n[PHY] FAPI2PHY WLS Received Block %d\n",i);
+                               i++;
+    }
+    else
+    {
+                            printf("\n[PHY] FAPI2PHY WLS Get Error for msg %d\n",i);
+                            break;
+                   }
+                if (flags & WLS_TF_FIN)
+                {
+                    return p_msg;
+                }
+               }
+               else
+               {
+                       printf("\n[PHY] FAPI2PHY WLS wait returned 0 blocks exiting \n");
+                       return FAILURE;
+               }
+       
+    }
+    return p_msg;
+}
+
+uint8_t phy_fapi_send()
+{
+    uint64_t pa_block = 0;
+    uint8_t ret = FAILURE;
+    uint32_t i;
+    
+    for (i=0 ; i < NUM_PHY_MSGS; i++)
+    {
+
+    pa_block = (uint64_t) WLS_DequeueBlock((void*) g_phy_wls);
+    if (!pa_block)
+    {
+               printf("\n[PHY] FAPI2PHY WLS Dequeue block %d error\n",i);
+        return FAILURE;
+    }
+
+       ret = WLS_Put(g_phy_wls, pa_block, WLS_TEST_MSG_SIZE, WLS_TEST_MSG_ID, (i== (NUM_PHY_MSGS-1))? WLS_TF_FIN:0);
+       printf("\n[PHY] FAPI2PHY WLS Put Msg %d \n",i);
+       if (ret)
+       {
+               printf("\n[PHY] FAPI2PHY WLS Put Msg Error %d \n",i);
+      }
+    }
+    return ret;
+}
diff --git a/wls_lib/testapp/Makefile b/wls_lib/testapp/Makefile
new file mode 100644 (file)
index 0000000..6fcd6f6
--- /dev/null
@@ -0,0 +1,61 @@
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+ifdef DPDK_WLS
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-icc
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = wls_test
+
+LDFLAGS += -L../.. -l wls -lpthread -lhugetlbfs
+
+# all source are stored in SRCS-y
+SRCS-y := pool.c testapp.c
+
+CFLAGS += $(WERROR_FLAGS) -I../.. -DDPDK_WLS
+EXTRA_CFLAGS += -g
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+else
+
+#EXTRA_CFLAGS +=-g -Wall -wd9 -I../
+EXTRA_CFLAGS +=-g -Wall -I../
+LDFLAGS += -L../ -lwls
+
+# all source are stored in SRCS-y
+SRCS-y := pool.c testapp.c
+wls_test: testapp.o pool.o
+       $(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ testapp.o pool.o -L . -l wls -l pthread -l hugetlbfs
+
+CFLAGS += $(WERROR_FLAGS) -g -I../../
+testapp.o: testapp.c
+       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
+
+pool.o: pool.c
+       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $<
+
+clean:
+       rm -f *.o wls_test
+endif
diff --git a/wls_lib/testapp/pool.c b/wls_lib/testapp/pool.c
new file mode 100644 (file)
index 0000000..015c03b
--- /dev/null
@@ -0,0 +1,189 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#endif
+#include <string.h>
+#include <pthread.h>
+#include "pool.h"
+
+/*static void pool_mutex_destroy(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_destroy(pMutex);
+}*/
+
+static void pool_mutex_init(pthread_mutex_t* pMutex)
+{
+   pthread_mutexattr_t prior;
+   pthread_mutexattr_init(&prior);
+   pthread_mutexattr_setprotocol(&prior, PTHREAD_PRIO_INHERIT);
+   pthread_mutex_init(pMutex, &prior);
+   pthread_mutexattr_destroy(&prior);
+}
+
+static void pool_mutex_lock(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_lock(pMutex);
+}
+
+static void pool_mutex_unlock(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_unlock(pMutex);
+}
+
+
+unsigned int PoolInit (PPOOL pPool, void * pStorage, unsigned int nBlockNum, unsigned int nBlockSize, unsigned long long* pFreePtr, unsigned long long* pUsedPtr)
+{
+    unsigned int i;
+
+    memset (pPool, 0, sizeof (*pPool));
+
+#ifdef __KERNEL__
+    mutex_init(&pPool->lock);
+#else
+    pool_mutex_init(&pPool->lock);
+#endif
+
+    pPool->StoragePtr = (unsigned char*)pStorage;
+    pPool->BlockSize  = nBlockSize;
+    pPool->BlockNum   = nBlockNum;
+
+    pPool->FreePtr = pFreePtr;
+    pPool->UsedPtr = pUsedPtr;
+
+    // to put the indexes to the free storage
+
+    i = 0;
+
+    while (i < nBlockNum)
+    {
+        PoolFree (pPool, pPool->StoragePtr + (pPool->BlockSize * i));
+        i++;
+    }
+
+    return 0;
+}
+
+void* PoolAlloc(PPOOL pPool)
+{
+    unsigned long long nIndex;
+    void* ret  = NULL;
+
+#ifdef __KERNEL__
+    mutex_lock(&pPool->lock);
+#else
+    pool_mutex_lock(&pPool->lock);
+#endif
+
+    if (pPool->FreeGet == pPool->FreePut){
+#ifdef __KERNEL__
+        mutex_unlock(&pPool->lock);
+#else
+        pool_mutex_unlock(&pPool->lock);
+#endif
+        return ret;
+    }
+
+    nIndex = pPool->FreePtr[pPool->FreeGet++];
+
+    if (pPool->FreeGet >= (pPool->BlockNum+1))
+        pPool->FreeGet = 0;
+
+    ret = pPool->StoragePtr + (pPool->BlockSize * nIndex);
+
+#ifdef __KERNEL__
+    mutex_unlock(&pPool->lock);
+#else
+    pool_mutex_unlock(&pPool->lock);
+#endif
+
+    return ret;
+}
+
+unsigned int PoolFree(PPOOL pPool, void * pBlock)
+{
+    unsigned long long index;
+
+#ifdef __KERNEL__
+    mutex_lock(&pPool->lock);
+#else
+    pool_mutex_lock(&pPool->lock);
+#endif
+
+    index = (U64)((U64)pBlock - (U64)pPool->StoragePtr) / pPool->BlockSize;
+
+    pPool->FreePtr [pPool->FreePut ++] = index;
+
+    if (pPool->FreePut >= (pPool->BlockNum+1))
+        pPool->FreePut = 0;
+
+#ifdef __KERNEL__
+    mutex_unlock(&pPool->lock);
+#else
+    pool_mutex_unlock(&pPool->lock);
+#endif
+
+    return 1;
+}
+
+unsigned int PoolGetFreeNum(PPOOL pPool)
+{
+    unsigned int nCount;
+
+    if (pPool==NULL)
+        return 0;
+
+    if (pPool->FreePut >= pPool->FreeGet)
+    {
+        nCount = pPool->FreePut - pPool->FreeGet;
+    }
+    else
+    {
+        // the queue size is bigger on one element than a partition
+        // to prevent data loss
+
+        nCount = (pPool->BlockNum+1) - (pPool->FreeGet - pPool->FreePut);
+    }
+
+    return nCount;
+}
+
+unsigned int PoolGetAllocNum(PPOOL pPool)
+{
+    unsigned int nCount;
+
+    if (pPool==NULL)
+        return 0;
+
+    if (pPool->UsedPut >= pPool->UsedGet)
+    {
+        nCount = pPool->UsedPut - pPool->UsedGet;
+    }
+    else
+    {
+        // the queue size is bigger on one element than a partition
+        // to prevent data loss
+
+        nCount = (pPool->BlockNum+1) - (pPool->UsedGet - pPool->UsedPut);
+    }
+
+    return nCount;
+}
+
diff --git a/wls_lib/testapp/pool.h b/wls_lib/testapp/pool.h
new file mode 100644 (file)
index 0000000..bb1863e
--- /dev/null
@@ -0,0 +1,56 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef _POOL_API_H_
+#define _POOL_API_H_
+
+#ifdef __KERNEL__
+#include <linux/mutex.h>
+#endif
+#include <pthread.h>
+#include "ttypes.h"
+
+
+typedef struct _POOL_
+{
+    unsigned char*      StoragePtr;     // The pointer to the storage where blocks are located
+    unsigned int      BlockNum;       // The number of blocks in storage
+    unsigned int      BlockSize;      // The size of block in bytes
+
+    unsigned long long*     FreePtr;        // The pointer to the storage with free object indexes
+    volatile unsigned long long     FreePut;        // PUT index used to put the new item to 'free' storage
+    volatile unsigned long long     FreeGet;        // GET index used to get the new free item from 'free' storage
+
+    unsigned long long*     UsedPtr;        // The pointer to the storage with 'Used' object indexes
+    volatile unsigned long long     UsedPut;        // PUT index used to put the new item to 'already used' storage
+    volatile unsigned long long     UsedGet;        // GET index used to get the item from 'already used' storage
+#ifdef __KERNEL__
+    struct mutex lock;
+#else
+    pthread_mutex_t lock;
+#endif
+}POOL, *PPOOL;
+
+
+unsigned int PoolInit (PPOOL pPool, void * pStorage, unsigned int nBlockNum, unsigned int nBlockSize, unsigned long long* pFreePtr, unsigned long long* pUsedPtr);
+void*  PoolAlloc(PPOOL pPool);
+unsigned int PoolFree(PPOOL pPool, void * pBlock);
+unsigned int PoolGetFreeNum(PPOOL pPool);
+unsigned int PoolGetAllocNum(PPOOL pPool);
+
+#endif //_POOL_API_H_
diff --git a/wls_lib/testapp/testapp.c b/wls_lib/testapp/testapp.c
new file mode 100644 (file)
index 0000000..1bd9a84
--- /dev/null
@@ -0,0 +1,1486 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * WLS interface test application
+ * (contains functional unit tests and diagnostics to test wls
+ *  supported by WLS interface)
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>   // for printf
+#include <string.h>  // for memset
+#include <signal.h>  // for SIGINT
+#include <unistd.h>  // for usleep
+#include <stdlib.h>  // for rand
+#include <getopt.h>  // for getopt
+#include <sys/time.h>
+#include <pthread.h>
+#include <sched.h>
+#include "ttypes.h"
+#include "wls_lib.h"
+#include "pool.h"
+
+#define HANDLE PVOID
+
+
+#define K                      1024
+#define M                      (K*K)
+
+#define   DEFAULT_TEST_MEMORY_SIZE      256*M
+#define   DEFAUTL_TEST_BLOCK_SIZE       16*K
+
+#define   DEFAULT_MESSAGE_COUNT_PER_MS  10
+#define   DEFAULT_MAX_MESSAGE_SIZE      2000
+#define   DEFUALT_MIN_MESSAGE_SIZE      100
+
+#define   APP_QUEUE_SIZE   255   /* number of elements each queue of the WLS  being registered will have */
+#define   MAX_MESSAGES  1000   /* per ms */
+
+
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef enum {
+    APP_TC_SANITY_TEST = 0,
+} APP_TEST_CASES;
+
+typedef struct tagAPP_PARAMS {
+    char *wls_dev_name;
+    int aff_core;
+    int test_id;
+    int rx_id;
+    int tx_id;
+    int n_messages;
+    int max_size;
+    int min_size;
+    int interface_count;
+    U8 master;
+    U8 debug;
+    U8 crc;
+    U8 trusted;
+} APP_PARAMS, *PAPP_PARAMS;
+
+typedef struct tagAPP_MESSAGE {
+    U32 id;
+} APP_MESSAGE, *PAPP_MESSAGE;
+
+typedef struct tagAPP_CONTEXT {
+    V32 ExitStatus;
+    HANDLE hWls;
+
+    U32 master;
+
+    PVOID shm_memory;
+
+    POOL Pool; // The pool descriptor
+    void* PoolStrPtr; // The pool storage pointer to keep indexes
+
+    U16 RxID;
+    U16 TxID;
+
+    U16 nInterfaces; // number of RX identifiers used by the APP
+    //
+    U16 InitQueueSize; // for invalid messages test (to trigger WLS  blocking)
+
+    //
+    U32 MsgPerMs;
+    U32 MaxMsgSize;
+    U32 MinMsgSize;
+
+    U32 TxCnt;
+    U32 RxCnt;
+
+    U64 nTxMsgs; // Messages transmitted
+    U64 nTxOctets; // Octets transmitted
+    U64 nRxMsgs; // Messages received
+    U64 nRxOcters; // Octets received
+    U64 Cycles; // number of 1ms cycles
+
+    int AppSanityMsgSize; // 4 or 8 depending on CRC feature
+    U8 Debug; // when TRUE app cycle is 1 sec, otherwise 1ms
+    U8 TrustedDataSource; // for trusted data sources ICC service removes msg validity checking.
+
+    void (*Receive)(HANDLE h);
+    void (*Transmit)(HANDLE h);
+
+    void (*ThreadReceive)(HANDLE h);
+    void (*ThreadTransmit)(HANDLE h);
+
+    int (*wls_put)(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
+    unsigned long long (*wls_get)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
+    unsigned long long (*wls_wget)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
+
+    U8 *pLastRx; // used for scatter-gather test
+    U32 LastRxSize; // used for scatter-gather test
+
+    U32 *pServiceBuffer;
+
+    U32 TxMsgCnt;
+    PVOID TxMessages[MAX_MESSAGES];
+    U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes
+    int core;
+
+} APP_CONTEXT, *PAPP_CONTEXT;
+
+APP_CONTEXT AppContext;
+
+static int pool_alloc = 0;
+static int pool_free = 0;
+
+static void ShowData(void* ptr, unsigned int size)
+{
+    U8 *d = ptr;
+    unsigned int i;
+
+    for (i = 0; i < size; i++) {
+        if (!(i & 0xf))
+            printf("\n");
+        printf("%02x ", d[i]);
+    }
+    printf("\n");
+}
+
+static void App_SigExitCallback(int signum)
+{
+    (void) signum;
+    AppContext.ExitStatus = TRUE;
+}
+
+static void* WlsVaToPa(void * ptr)
+{
+    PAPP_CONTEXT pCtx = &AppContext;
+    return (void*) WLS_VA2PA(pCtx->hWls, ptr);
+}
+
+static void* WlsPaToVa(void * ptr)
+{
+    PAPP_CONTEXT pCtx = &AppContext;
+    return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
+}
+
+static void* App_Alloc(void* h, unsigned long size)
+{
+    (void) h;
+    (void) size;
+    void * retval = NULL;
+    if (AppContext.master) {
+        retval = PoolAlloc(&(AppContext.Pool));
+        //printf("pPool->FreeGet  %d == pPool->FreePut %d\n", AppContext.Pool.FreeGet, AppContext.Pool.FreePut);
+    } else {
+        retval = (void*) WLS_DequeueBlock(AppContext.hWls);
+        if (retval)
+            retval = (void*) WlsPaToVa(retval);
+        else
+            printf("WLS_DequeueBlock returned null\n");
+    }
+
+    if (retval == NULL) {
+        printf("no memory %d %d\n", pool_alloc, pool_free);
+        exit(-1);
+    } else
+        pool_alloc++;
+
+    return retval;
+}
+
+static int App_Free(void* h, void* pMsg)
+{
+    (void) h;
+    if (AppContext.master)
+        if (pMsg) {
+            pool_free++;
+            return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1);
+        } else {
+            printf("Free Null pointer\n");
+            exit(-1);
+        } else
+        return 0;
+}
+
+static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize)
+{
+    int ret = 0;
+    unsigned long long* pUsed;
+    unsigned long long* pFree;
+    PAPP_CONTEXT pCtx = &AppContext;
+    U32 nBlocksSlave = 0;
+
+    U32 nElmNum = size / BlockSize - 1;
+
+    // We need to allocate the memory for indexes and to initialize the
+    // pool descriptor, (x+1) is used to prevent queues overflow
+
+    pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long));
+
+    if (pCtx->PoolStrPtr == NULL)
+        return -1;
+
+    pFree = (unsigned long long*) pCtx->PoolStrPtr;
+    pUsed = pFree + (nElmNum + 1);
+
+    ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed);
+
+    if (ret == 0) {
+
+        if (AppContext.master) {
+            int res = TRUE;
+            /* allocate blocks for Slave to Master transmittion */
+            while (res) {
+                void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
+                if (pBlock) {
+                    res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
+                    if (res)
+                        nBlocksSlave++;
+                    else
+                        App_Free(AppContext.hWls, pBlock);
+                } else
+                    res = FALSE;
+            }
+            printf("Slave has %d free blocks\n", nBlocksSlave);
+        }
+    }
+
+    return ret;
+}
+
+/********************************/
+
+#define FAST_CRC16    1
+
+#if (FAST_CRC16)
+const U8 mb_table_level1[] = {
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+};
+
+const U8 mb_table_level2[] = {
+    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,
+    0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
+    0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
+    0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
+    0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
+    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
+    0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
+    0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
+    0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
+    0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
+    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,
+    0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
+    0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,
+    0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
+    0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
+    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
+    0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,
+    0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
+    0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
+    0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
+    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
+    0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
+    0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,
+    0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
+    0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
+    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
+    0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
+    0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
+    0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,
+    0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
+    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
+    0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
+};
+
+#if 0
+// big endian CPU
+
+U16
+crc16(U16 crc, U8 data)
+{
+    U8 index;
+    U8 crc_Low = crc & 0xFF;
+    U8 crc_High = crc >> 8;
+
+    index = (crc_High ^ data) & 0xFF;
+    crc_High = crc_Low ^ mb_table_level1[ index ];
+    crc_Low = mb_table_level2[ index ];
+
+    return (crc_High << 8) | crc_Low;
+}
+#else
+// little endian CPU
+#if 0
+static U16 CRC16_Update(U16 crc, U8 data)
+{
+    U8 index;
+    U8 crc_High = crc >> 8;
+    U8 crc_Low = crc & 0xFF;
+
+    index = crc_Low ^ data;
+    crc_Low = crc_High ^ mb_table_level1[ index ];
+    crc_High = mb_table_level2[ index ];
+
+    return (crc_High << 8) | crc_Low;
+}
+#endif
+#endif
+
+#if 0
+/***********************************************
+ * CRC16  polynomial : X16 + X15 + X2 + 1       *
+ * FAST CRC16 routine                           *
+ * ---> pData - msg to be protected             *
+ * ---> size - msg size in bytes                *
+ * ---> aCRC - initializer (0xFFFF for 1st page)*
+ * <--- crc16                                   *
+ ***********************************************/
+static U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
+{
+
+    if (!size)
+        return aCRC;
+    else {
+        U8 index;
+        U8 crc_High = aCRC >> 8;
+        U8 crc_Low = aCRC & 0xFF;
+
+        do {
+            index = crc_Low ^ *pData++;
+            crc_Low = crc_High ^ mb_table_level1[ index ];
+            crc_High = mb_table_level2[ index ];
+        } while (--size);
+
+        return (crc_High << 8) | crc_Low;
+    }
+}
+#endif
+
+#else // SLOW (canonic CRC16 calculation)
+
+/***********************************************
+ * CRC16  polynomial : X16 + X15 + X2 + 1       *
+ * ---> pData - msg to be protected             *
+ * ---> size - msg size in bytes                *
+ * ---> aCRC - initializer (0xFFFF for 1st page)*
+ * <--- crc16                                   *
+ ***********************************************/
+U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
+{
+    U8 i, tmp;
+
+    if (!size)
+        return aCRC;
+
+    do {
+        aCRC ^= *pData++;
+        for (i = 0; i < 8; i++) {
+            tmp = aCRC & 0x01;
+            aCRC >>= 1;
+            if (tmp) {
+                aCRC ^= CRC16_DIVISOR;
+            }
+        }
+    } while (--size);
+    return aCRC;
+}
+
+#endif // FAST_CRC16
+
+
+#define CRC32_INIT_VAL  0xFFFFFFFF
+#define CRC32_DIVISOR   0xA0000001
+
+static U32 ICC_CRC32(U8 *pData, U32 size)
+{
+    U32 retval = CRC32_INIT_VAL;
+    U8 i, tmp;
+
+    if (!size)
+        return CRC32_INIT_VAL; // mean CRC error
+    do {
+        retval ^= *pData++;
+        for (i = 8; i > 0; --i) {
+            tmp = retval & 0x01;
+            retval >>= 1;
+            if (tmp) {
+                retval ^= CRC32_DIVISOR;
+            }
+        }
+    } while (--size);
+    return retval;
+}
+
+#if 0
+
+static U16 ICC_CRC16(U8 *pData, U16 size)
+{
+#define CRC16_ERROR (0xffff)
+    return CRC16_NoInit(CRC16_ERROR, pData, size); // use 0xFFFF as first initializer
+}
+#endif
+
+static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
+{
+    U8 *p;
+    U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg);
+
+    if (pMsgVa == 0)
+    {
+        return 0;
+    }
+    p = (U8 *) pMsgVa;
+#if 1
+    U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc));
+    // CRC32
+    p[MsgSize - 4] = (crc >> 0) & 0xff;
+    p[MsgSize - 3] = (crc >> 8) & 0xff;
+    p[MsgSize - 2] = (crc >> 16) & 0xff;
+    p[MsgSize - 1] = (crc >> 24) & 0xff;
+#else
+    U16 crc = ICC_CRC16((U8 *) pMsg, MsgSize - sizeof (crc));
+    // CRC16
+    p[MsgSize - 2] = (crc >> 0) & 0xff;
+    p[MsgSize - 1] = (crc >> 8) & 0xff;
+#endif
+
+    return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags);
+}
+
+static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags);
+    U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
+
+    if (pMsg) {
+        U32 size = *MsgSize;
+#if 1
+        U32 crc = ICC_CRC32((U8*) pMsg, size);
+#else
+        U16 crc = ICC_CRC16((U8*) pMsg, size);
+#endif
+
+        if (crc != 0) {
+            printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
+            ShowData((U8*) pMsg, size);
+        }
+    }
+    return pMsgPa;
+}
+
+static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags);
+    U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
+
+    if (pMsg) {
+        U32 size = *MsgSize;
+#if 1
+        U32 crc = ICC_CRC32((U8*) pMsg, size);
+#else
+        U16 crc = ICC_CRC16((U8*) pMsg, size);
+#endif
+
+        if (crc != 0) {
+            printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
+            ShowData((U8*) pMsg, size);
+        }
+    }
+    return pMsgPa;
+}
+
+static void CreateMessage(PAPP_MESSAGE p, U32 size)
+{
+    (void) size;
+    p->id = AppContext.TxCnt++;
+}
+
+static void CheckMessage(PAPP_MESSAGE p, U32 size)
+{
+    if (AppContext.RxCnt && p->id != AppContext.RxCnt) {
+        //             char buf[8*K];
+        printf("rx message(id_%llu)_%lx error expected_%lu, received_%lu\n", (long long) AppContext.nRxMsgs, (U64) p, (long) AppContext.RxCnt, (long) p->id);
+        ShowData(p, size);
+        //             if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf)))
+        //             printf("%s", buf);
+    }
+
+    AppContext.RxCnt = p->id;
+    AppContext.RxCnt += 1;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_AllocMultiple
+ * @brief used to allocate multiple blocks of the same size from the WLS
+ *
+ * @param[h]  hWls - app thread WLS  handle
+ * @param[o]  pMsgs - ptr to beginning of array of points to allocated blocks
+ * @param[o]  pMsgSizes - array to write size for each allocated blocks
+ * @param[i]  nMsgs - number of blocks to allocate
+ * @return    U32 - number of allocated blocks
+ *
+ * @description
+ *    The routine is used allocate multiple blocks from the ICC service,
+ * the blocks are supposed to be same size blocks, satisfying
+ * appContext.MaxMsgSize parameter.
+ *    In case the service is unable to provide requested number of blocks,
+ * smaller count is allocated. The routine returns actual number of allocated
+ * blocks
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs)
+{
+    unsigned n = 0;
+    unsigned i, j;
+
+    memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs);
+
+    while (nMsgs--) {
+        pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize);
+        pMsgSizes[n] = AppContext.MaxMsgSize;
+        if (!pMsgs[n]) {
+            printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs);
+            break;
+        }
+        n += 1;
+    }
+
+    // check for duplicated pointers
+    for (i = 0; i < n; i++) {
+        for (j = i + 1; j < n; j++) {
+            if (pMsgs[i] == pMsgs[j]) {
+                printf("duplicated pointer %p (msg_id1_%u, msg_id2_%u)\n", pMsgs[i], i, j);
+                break;
+            }
+        }
+    }
+
+    return n;
+    //ShowData(TxMessages, sizeof(TxMessages));
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_SanityTestTransmitter
+ * @brief transmitter of default test case (0).
+ *
+ * @param[h]  hWls - app thread WLS  handle
+ * @return    void
+ *
+ * @description
+ *    The routine is used in test case 0 (non-blocking sanity unit test)
+ * The transmitter does allocate multiple blocks of the same size from the ICC
+ * service. Then it fills each block with incremental counter and transfers
+ * to other application specified by parameter TxID.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_SanityTestTransmitter(HANDLE hWls)
+{
+    U8 *pMsg;
+    unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs);
+    unsigned fn = n;
+    unsigned cnt = 0;
+    unsigned k = 0;
+    unsigned alloc = n;
+
+    // lets transmit some message for test
+    while (n--) {
+        pMsg = AppContext.TxMessages[cnt++];
+        if (pMsg) {
+            U32 size = (rand() % AppContext.MaxMsgSize);
+
+            if (size < AppContext.MinMsgSize)
+                size = AppContext.MinMsgSize;
+
+            memset(pMsg, cnt, size);
+            CreateMessage((PAPP_MESSAGE) pMsg, size);
+            if ((AppContext.wls_put(hWls, (U64) WlsVaToPa(pMsg), size, AppContext.TxID, 0) != 0)) {
+                printf("could not send the message_%p\n", pMsg);
+                break;
+            } else {
+                k++;
+            }
+            AppContext.nTxOctets += size;
+            AppContext.nTxMsgs += 1;
+        }
+    }
+
+    if (alloc != k)
+        printf("inorrect sent %d alloc %d \n", k, alloc);
+
+    cnt = 0;
+    while (fn--) {
+        pMsg = AppContext.TxMessages[cnt++];
+        if (pMsg) {
+            if (App_Free(hWls, pMsg) != 0)
+                printf("could not release the message_%p\n", pMsg);
+        } else
+            printf("pMsg is NULL [%d]\n", cnt);
+    }
+    if (cnt != k) {
+        printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt);
+        AppContext.ExitStatus = 1;
+    }
+}
+
+#if 0
+/**
+ *******************************************************************************
+ *
+ * @fn    app_ScatterGatherTransmitter
+ * @brief transmitter of default test case (15/16).
+ *
+ * @param[h]  hWls - app thread WLS  handle
+ * @return    void
+ *
+ * @description
+ *    The routine is used in test case 0 (non-blocking sanity unit test)
+ * The transmitter does allocate multiple blocks of the same size from the ICC
+ * service. Then it fills each block with incremental counter and transfers
+ * to other application specified by parameter TxID.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_ScatterGatherTransmitter(HANDLE hWls)
+{
+       U8 *pMsg;
+       unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs + 2);
+       unsigned i, cnt = 0, flags = 0;
+       U8 *p, *pOriginMsg = (U8 *)App_Alloc(hWls, AppContext.MaxMsgSize);
+       unsigned TotalSize = 0;
+
+    unsigned fn  = n;
+    unsigned k = 0;
+    unsigned alloc = n;
+
+       if (!pOriginMsg) {
+               printf("No memory for App_Alloc()\n");
+               return;
+       }
+
+       flags = rand() & 0xff;
+
+       for(i = 0; i < AppContext.MaxMsgSize; i++)
+               pOriginMsg[i] = (flags + i) & 0xff;
+
+       // scatter original message among several blocks
+       for(i = 0; i < n; i++)
+       {
+               U32 size = (rand() % (AppContext.MaxMsgSize / n));
+
+               if (size < AppContext.MinMsgSize)
+                       size = AppContext.MinMsgSize;
+
+               TotalSize += size;
+               AppContext.TxMessageSizes[i] = size;
+               //printf("size%d=%lu\n", i, size);
+       }
+
+       // adjust size of the last block
+       if (TotalSize < AppContext.MaxMsgSize)
+       {
+               AppContext.TxMessageSizes[n - 1] += AppContext.MaxMsgSize - TotalSize;
+       }
+       else if (TotalSize > AppContext.MaxMsgSize)
+       {
+               printf("error: size of the scatted blocks exceeding size of the original message\n");
+       }
+
+       p = pOriginMsg;
+       for(i = 0; i < n; i++)
+       {
+               // copy data into the scattered blocks
+               pMsg = AppContext.TxMessages[i];
+               memcpy(pMsg, p, AppContext.TxMessageSizes[i]);
+               p += AppContext.TxMessageSizes[i];
+       }
+
+       // transmit original message first
+       if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pOriginMsg), AppContext.MaxMsgSize, AppContext.TxID, 0) != 0)
+       {
+               printf("could not send the message_%p\n", pOriginMsg);
+               if (App_Free(hWls, pOriginMsg) != 0)
+                       printf("could not release the message_%p\n", pOriginMsg);
+       }
+       else
+       {
+               AppContext.nTxOctets += AppContext.MaxMsgSize;
+               AppContext.nTxMsgs += 1;
+       }
+
+    if(pOriginMsg){
+        if (App_Free(hWls, pOriginMsg) != 0)
+            printf("could not release the message_%p\n", pMsg);
+    }
+    else
+        printf("pOriginMsg is NULL \n");
+
+       // transmit scattered messages following their creation order
+       while (n--)
+       {
+               pMsg = AppContext.TxMessages[cnt];
+               if (!cnt)
+                       flags = WLS_SG_FIRST;
+               else if (n == 0)
+                       flags = WLS_SG_LAST;
+               else
+                       flags = WLS_SG_NEXT;
+
+               if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pMsg), AppContext.TxMessageSizes[cnt], AppContext.TxID, flags) != 0)
+               {
+                       printf("could not send the message_%p\n", pMsg);
+                       if (App_Free(hWls, pMsg) != 0)
+                               printf("could not release the message_%p\n", pMsg);
+               }
+        else
+            k++;
+
+               AppContext.nTxOctets += AppContext.TxMessageSizes[cnt];
+               AppContext.nTxMsgs += 1;
+               cnt++;
+       }
+    if(alloc != k)
+        printf("inorrect sent %d alloc %d \n", k, alloc);
+
+    cnt = 0;
+    while (fn--)
+    {
+        pMsg = AppContext.TxMessages[cnt++];
+        if(pMsg){
+            if (App_Free(hWls, pMsg) != 0)
+                printf("could not release the message_%p\n", pMsg);
+        }
+        else
+            printf("pMsg is NULL [%d]\n", cnt);
+    }
+    if(cnt != k)
+        printf("inorrect free sent %d free %d \n", k, cnt);
+}
+#endif
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_SanityTestReceiver
+ * @brief default sanity checking receiver used in multiple tests.
+ *
+ * @param[h]  hWls - app thread WLS  handle
+ * @return    void
+ *
+ * @description
+ *    The routine takes received messages and checks the sanity incremental
+ * counter to confirm the order. In case the counter does not correspond to
+ * expected counter (misordered message or incorrect message) an error is
+ * printed to STDOUT.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_SanityTestReceiver(HANDLE hWls)
+{
+    (void) hWls;
+    U32 MsgSize;
+    U8 *pMsg;
+    U8 *pMsgPa;
+    U8 *pMsgVa;
+    U8 TempBuf[16 * K];
+    unsigned short MsgTypeID;
+    unsigned short Flags;
+    U32 nBlocksSlave = 0;
+
+    // handle RX receiver
+    while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) {
+        pMsgVa = (U8 *) WlsPaToVa(pMsgPa);
+
+        if (pMsgVa == NULL) {
+            printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa);
+            continue;
+        }
+
+        pMsg = pMsgVa;
+
+        if (((U64) pMsg & 0x3) == 0) {
+            // aligned message
+            CheckMessage((PAPP_MESSAGE) pMsg, MsgSize);
+        } else {
+            // misaligned message
+            printf("Unaligned message\n");
+            MsgSize = (MsgSize > sizeof (TempBuf)) ? sizeof (TempBuf) : MsgSize;
+            memcpy(TempBuf, pMsg, MsgSize);
+            // handle received message
+            CheckMessage((PAPP_MESSAGE) TempBuf, MsgSize);
+        }
+        App_Free(AppContext.hWls, pMsg);
+        AppContext.nRxOcters += MsgSize;
+        AppContext.nRxMsgs += 1;
+
+        if (AppContext.master) {
+            int res = TRUE;
+            /* allocate blocks for Slave to Master transmittion */
+            while (res) {
+                void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
+                if (pBlock) {
+                    res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
+                    if (res)
+                        nBlocksSlave++;
+                    else
+                        App_Free(AppContext.hWls, pBlock);
+                } else
+                    res = FALSE;
+            }
+        }
+
+    }
+}
+
+#if 0
+/**
+ *******************************************************************************
+ *
+ * @fn    app_ScatterGatherReceiver
+ * @brief scatter gather test receiver
+ *
+ * @param[h]  hWls - app thread WLS  handle
+ * @return    void
+ *
+ * @description
+ *    The routine takes received messages and checks the sanity incremental
+ * counter to confirm the order. In case the counter does not correspond to
+ * expected counter (misordered message or incorrect message) an error is
+ * printed to STDOUT.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_ScatterGatherReceiver(HANDLE hWls)
+{
+        (void)hWls;
+       U32 MsgSize;
+       U8  *pMsg;
+    U8  *pMsgPa;
+    U8  *pMsgVa;
+       U32 size;
+       U8 err = 0;
+    unsigned short MsgTypeID;
+    unsigned short Flags;
+
+       // handle RX receiver
+       while ((pMsgPa = (U8*) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)
+       {
+        pMsgVa = (U8  *)WlsPaToVa(pMsgPa);
+
+        pMsg = pMsgVa;
+
+               AppContext.nRxOcters += MsgSize;
+               AppContext.nRxMsgs += 1;
+
+               if (!AppContext.pLastRx)
+               {
+                       AppContext.pLastRx = pMsg;
+                       AppContext.LastRxSize = MsgSize;
+               }
+               else // compare with received and release both
+               {
+                       U32 i;
+                       if (AppContext.LastRxSize != MsgSize)
+                               printf("received wrong size, unsync? try to re-run app both clusters\n");
+
+                       size = MsgSize;
+                       if (size > AppContext.LastRxSize)
+                               size = AppContext.LastRxSize;
+
+                       for(i = 0; i < size; i++)
+                       {
+                               if (pMsg[i] != AppContext.pLastRx[i])
+                               {
+                                       // error content doesn't match
+                                       err = TRUE;
+                                       break;
+                               }
+                       }
+
+                       if (err)
+                       {
+                               printf("content verification failed, scatter-gather test FAIL\n");
+                               // terminate
+                               AppContext.Receive = NULL;
+                               AppContext.Transmit = NULL;
+                               App_Free(AppContext.hWls, pMsg);
+                               App_Free(AppContext.hWls, AppContext.pLastRx);
+                               return;
+                       }
+
+                       App_Free(AppContext.hWls, pMsg);
+                       App_Free(AppContext.hWls, AppContext.pLastRx);
+                       AppContext.pLastRx = NULL;
+               }
+
+       }
+}
+
+
+
+static U32 app_GetTime(void)
+{
+       struct timeval tv;
+       U32 time_ms = 0;
+       if (gettimeofday(&tv, NULL) == 0)
+               time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+       return time_ms;
+}
+#endif
+
+/******************************************************************************
+ *                                                                             *
+ *                       Application common routines                           *
+ *                                                                             *
+ ******************************************************************************/
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_UpdateStatistics
+ * @brief is used to update RX and TX statistics
+ *
+ * @param[n]  void
+ * @return    void
+ *
+ * @description
+ *    The routine prints out the statistics of received and transmitted
+ * messages.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+
+static void app_UpdateStatistics(void)
+{
+    AppContext.Cycles += 1;
+
+    if (AppContext.Debug || AppContext.Cycles % 1000 == 0) {
+        printf("Rx(id_%u) (%llu) - (%llu KiB)\n", AppContext.RxID, (long long) AppContext.nRxMsgs, (long long) AppContext.nRxOcters >> 10);
+        printf("Tx(id_%u) (%llu) - (%llu KiB)\n", AppContext.TxID, (long long) AppContext.nTxMsgs, (long long) AppContext.nTxOctets >> 10);
+    }
+
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_Help
+ * @brief prints app help content
+ *
+ * @param[n]  void
+ * @return    void
+ *
+ * @description
+ *    The routine is used to print help content to stdout.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_Help(void)
+{
+    char help_content[] =  \
+                       "WLS test application\n\n"\
+                       "Usage: testapp [-c <test>] [-r <rxid>] [-t <txid>] [-n <msgcount>]\n\n"\
+                       "supports the following parameters:\n\n"
+                        "-c | --testcase <test number>     0 - default sanity test\n"\
+                       "                                  1 - misaligned pointers test\n"\
+                       "                                  2 - aligned 4 pointers test\n"\
+                       "                                  3 - random pools test\n"\
+                       "                                  4 - ping-pong (ZBC test)\n"\
+                       "                                  5 - invalid messages test\n\n"\
+                       "--trusted                    switches WLS  to trusted mode\n"\
+                       "-r | --rxid <id>             used to specify RxTypeID\n"\
+                       "-t | --txid <id>             used to specify TxTypeID\n"\
+                       "-n | --msgcount <count>      used to specify number of messages per timeframe\n"\
+                       "-l | --minsize  <size>       specifies MIN message size in bytes\n"\
+                       "-s | --maxsize  <size>       specifies MAX message size in bytes\n"\
+                       "--crc                        enables CRC generation and checking\n"\
+                       "--debug                      increases sleep interval to 1 second\n"\
+                       "-m | --master                set predefined rxid and txid\n";
+
+    printf("%s", help_content);
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_ParseArgs
+ * @brief is used to parse incoming app args
+ *
+ * @param[i]  argc - app arg count
+ * @param[i]  argv - array of args
+ * @param[o]  params - app startup params filled basing on args parse
+ * @return    number of parsed args
+ *
+ * @description
+ *    The routine is parse input args and convert them into app startup params
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params)
+{
+    int c;
+    int *pInt;
+    int cnt = 0;
+
+    struct option long_options[] = {
+        {"wlsdev", required_argument, 0, 'w'},
+        {"affinity", required_argument, 0, 'a'},
+        {"testcase", required_argument, 0, 'c'},
+        {"rxid", required_argument, 0, 'r'},
+        {"txid", required_argument, 0, 't'},
+        {"msgcount", required_argument, 0, 'n'},
+        {"maxsize", required_argument, 0, 's'},
+        {"minsize", required_argument, 0, 'l'},
+        {"master", no_argument, 0, 'm'},
+        {"debug", no_argument, 0, 'd'}, /* slow down the app cycle from 1ms to 1s*/
+        {"icount", required_argument, 0, 'i'},
+        {"crc", no_argument, 0, 1},
+        {"trusted", no_argument, 0, 2},
+        {"help", no_argument, 0, 'h'},
+        {0, 0, 0, 0}
+    };
+
+    memset(params, 0, sizeof (*params));
+
+    // set default values here
+    params->interface_count = 1;
+
+    while (1) {
+        //int this_option_optind = optind ? optind : 1;
+        int option_index = 0;
+
+        c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index);
+
+        if (c == -1)
+            break;
+
+        cnt += 1;
+        pInt = NULL;
+
+        switch (c) {
+            case 'a': // test Case selection
+                pInt = &params->aff_core;
+                break;
+            case 'c': // test Case selection
+                pInt = &params->test_id;
+                break;
+            case 'r': // rx id selection
+                pInt = &params->rx_id;
+                break;
+            case 't': // tx id selection
+                pInt = &params->tx_id;
+                break;
+            case 's': // select message size
+                pInt = &params->max_size;
+                break;
+            case 'l': // select message size
+                pInt = &params->min_size;
+                break;
+            case 'n': // select number of messages
+                pInt = &params->n_messages;
+                break;
+            case 'i': // select number of interfaces to register
+                pInt = &params->interface_count;
+                break;
+            case 'm':
+                params->master = TRUE;
+                break;
+            case 'd':
+                params->debug = TRUE;
+                break;
+            case 'w':
+                params->wls_dev_name = optarg;
+                break;
+            case 'h':
+                app_Help();
+                exit(0);
+            case 2:
+                params->trusted = TRUE;
+                break;
+            case 1: // crc checking enabled
+                params->crc = TRUE;
+                break;
+        }
+
+        if (pInt && optarg) {
+            // get int arg
+            if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
+                sscanf(optarg, "%x", (unsigned *) pInt);
+            } else {
+                *pInt = atoi(optarg);
+            }
+        }
+    }
+    return cnt;
+}
+
+static int app_set_affinity(int coreNum)
+{
+    cpu_set_t cpuset;
+    int i, rc;
+
+    /* set main thread affinity mask to CPU7 */
+
+    CPU_ZERO(&cpuset);
+    CPU_SET(coreNum, &cpuset);
+
+    rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
+    if (rc) {
+        perror("pthread_setaffinity_np failed");
+        printf("pthread_setaffinity_np failed: %d", rc);
+    }
+
+    /* check the actual affinity mask assigned to the thread */
+
+    CPU_ZERO(&cpuset);
+
+    rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
+
+    if (rc) {
+        perror("pthread_getaffinity_np failed");
+        printf("pthread_getaffinity_np failed: %d", rc);
+    }
+
+    printf("set affinity: ");
+    for (i = 0; i < CPU_SETSIZE; i++)
+        if (CPU_ISSET(i, &cpuset))
+            printf("    CPU %d\n", i);
+
+    if (!CPU_ISSET(coreNum, &cpuset)) {
+        printf("affinity failed");
+    }
+
+    /**
+       A new thread created by pthread_create(3) inherits a copy of its
+       creator's CPU affinity mask. */
+
+    return rc;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_ApplyParams
+ * @brief is used to apply application startup parameters
+ *
+ * @param[i]  params - app startup params
+ * @return    void
+ *
+ * @description
+ *    The applies startup parameters
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_ApplyParams(PAPP_PARAMS params)
+{
+    // apply parameters
+    printf("selected test case %d - ", params->test_id);
+    switch (params->test_id) {
+        case APP_TC_SANITY_TEST:
+        default:
+            printf("NON-BLOCKING SANITY TEST\n");
+            AppContext.Receive = app_SanityTestReceiver;
+            AppContext.Transmit = app_SanityTestTransmitter;
+            break;
+    }
+
+    AppContext.wls_put = WLS_Put;
+    AppContext.wls_get = WLS_Get;
+    AppContext.wls_wget = WLS_WGet;
+
+    AppContext.MsgPerMs = DEFAULT_MESSAGE_COUNT_PER_MS;
+    AppContext.MaxMsgSize = DEFAULT_MAX_MESSAGE_SIZE;
+    AppContext.MinMsgSize = DEFUALT_MIN_MESSAGE_SIZE;
+    AppContext.AppSanityMsgSize = sizeof (APP_MESSAGE);
+
+    if (params->master) {
+        printf("WLS test app (supposed to run as MEMORY MASTER)\n");
+        AppContext.master = TRUE;
+        AppContext.RxID = 1;
+        AppContext.TxID = 2;
+    } else {
+        AppContext.master = FALSE;
+        AppContext.RxID = 2;
+        AppContext.TxID = 1;
+    }
+
+    if (params->rx_id)
+        AppContext.RxID = params->rx_id;
+
+    if (params->tx_id)
+        AppContext.TxID = params->tx_id;
+
+    if (params->n_messages && params->n_messages < MAX_MESSAGES)
+        AppContext.MsgPerMs = params->n_messages;
+
+    if (params->min_size && params->min_size >= 4)
+        AppContext.MinMsgSize = params->min_size;
+
+    // default is 1 RX interface
+    printf("if count = %u\n", params->interface_count);
+    AppContext.nInterfaces = 1;
+    if (params->interface_count == 0) {
+        printf("WLS test app started as simple data source, no RX ID will be specified\n");
+        AppContext.nInterfaces = 0;
+        AppContext.RxID = 0; // override RxID
+    } else if (params->interface_count <= 7) {
+        AppContext.nInterfaces = params->interface_count;
+    }
+
+
+    AppContext.TrustedDataSource = params->trusted;
+
+    if (params->crc) {
+        if (AppContext.MinMsgSize < 8)
+            AppContext.MinMsgSize = 8;
+
+        AppContext.wls_put = app_PutMessageCRC;
+        AppContext.wls_get = app_GetMessageCRC;
+        AppContext.wls_wget = app_WGetMessageCRC;
+
+        AppContext.AppSanityMsgSize += 4; // + sizeof CRC
+    }
+
+    if (params->max_size && params->max_size <= 16 * K)
+        AppContext.MaxMsgSize = params->max_size;
+
+    if (params->max_size < params->min_size)
+        params->max_size = params->min_size;
+
+    AppContext.Debug = params->debug;
+
+    if (params->aff_core) {
+        AppContext.core = params->aff_core;
+        app_set_affinity(AppContext.core);
+    }
+
+    printf("The application started with:\n");
+    printf("Core ................ %d\n", AppContext.core);
+    printf("Rx interface count .. %d\n", AppContext.nInterfaces);
+    printf("RxID ................ %d\n", AppContext.RxID);
+    printf("TxID ................ %d\n", AppContext.TxID);
+    if (AppContext.Debug)
+        printf("Generating .......... %lu Messages per second (DEBUG MODE)\n", (long) AppContext.MsgPerMs);
+    else
+        printf("Generating .......... %lu Messages per ms\n", (long) AppContext.MsgPerMs);
+    printf("Max Message Size .... %lu bytes\n", (long) AppContext.MaxMsgSize);
+    printf("Min Message Size .... %lu bytes\n", (long) AppContext.MinMsgSize);
+    printf("Number of threads ... 1\n");
+    printf("CRC checking ........ ");
+    if (params->crc)
+        printf("ENABLED\n");
+    else
+        printf("DISABLED\n");
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    app_ReleaseAllocatedBuffers
+ * @brief releases ICC buffers allocated by the application
+ *
+ * @param[n]  void
+ * @return    void
+ *
+ * @description
+ *    In process of making some tests when signal to close the application
+ * happens the app may keep some allocated buffers from the ICC pools. This
+ * routine does release these buffers back to ICC.
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ******************************************************************************/
+static void app_ReleaseAllocatedBuffers(void)
+{
+    if (AppContext.TxMsgCnt && AppContext.master)
+        do {
+            AppContext.TxMsgCnt -= 1;
+            App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]);
+        } while (AppContext.TxMsgCnt != 0);
+}
+
+/**
+ *******************************************************************************
+ *
+ * @fn    main
+ * @brief ICC test application main routine
+ *
+ * @param[n]  void
+ * @return    void
+ *
+ * @description
+ *    Contains logic of the test (one RX/TX thread)
+ *
+ * @references
+ * MS-111070-SP
+ *
+ * @ingroup icc_service_unit_test
+ *
+ ****************************************************************************/
+int main(int argc, char* argv[])
+{
+    int retval = 0;
+    APP_PARAMS params;
+
+    signal(SIGINT, App_SigExitCallback);
+
+    memset(&AppContext, 0, sizeof (AppContext));
+    memset(&params, 0, sizeof (params));
+
+#ifdef DPDK_WLS
+    int ret = rte_eal_init(argc, argv);
+    if (ret < 0)
+        rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+    argc -= ret;
+    argv += ret;
+#endif
+
+    app_ParseArgs(argc, argv, &params);
+    app_ApplyParams(&params);
+
+    AppContext.InitQueueSize = APP_QUEUE_SIZE;
+
+    AppContext.hWls = WLS_Open(params.wls_dev_name, AppContext.master, DEFAULT_TEST_MEMORY_SIZE);
+
+    if (!AppContext.hWls) {
+        printf("could not register WLS client\n");
+        return 1;
+    } else {
+        printf("WLS has been registered\n");
+    }
+
+    AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE);
+
+    if (AppContext.shm_memory == NULL) {
+        if (AppContext.master)
+            printf("could not create WLS shared memory\n");
+        else
+            printf("could not attach WLS shared memory\n");
+
+        return -1;
+    }
+
+    if (AppContext.master) {
+        if (App_MemoryInit(AppContext.shm_memory, DEFAULT_TEST_MEMORY_SIZE, DEFAUTL_TEST_BLOCK_SIZE) != 0) {
+            WLS_Free(AppContext.hWls, AppContext.shm_memory);
+            WLS_Close(AppContext.hWls);
+            exit(1);
+        }
+
+    }
+
+    // APPLICATION MAIN LOOP
+    while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit)) {
+        if (AppContext.Receive)
+            AppContext.Receive(AppContext.hWls);
+
+        if (AppContext.Debug)
+            //usleep(10000); // 1 sec delay
+            sleep(1); // 1 sec delay
+        else
+            usleep(1000); // 1 ms delay
+
+        if (AppContext.Transmit)
+            AppContext.Transmit(AppContext.hWls);
+
+        app_UpdateStatistics();
+    }
+
+    app_ReleaseAllocatedBuffers();
+    printf("deregistering WLS  (TxTotal_%llu, RxTotal_%llu)\n", (long long) AppContext.nTxMsgs, (long long) AppContext.nRxMsgs);
+    WLS_Free(AppContext.hWls, AppContext.shm_memory);
+    WLS_Close(AppContext.hWls);
+    return retval;
+}
diff --git a/wls_lib/testapp/wls_test.sh b/wls_lib/testapp/wls_test.sh
new file mode 100644 (file)
index 0000000..79f154f
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/bash
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+
+COREMASK=2
+SECONDARY=1
+FPREFIX="wls"
+DPDK_WLS=0
+
+while getopts ":mpa:w:" opt; do
+  case ${opt} in
+    m )
+      SECONDARY=0
+      ;;
+    a )
+      COREMASK=$((1 << $OPTARG))
+      ;;
+    : )
+      echo "Invalid option: $OPTARG requires a core number"
+      exit 1
+      ;;
+    w )
+      #replace / with _ for dpdk file prefix
+      FPREFIX=${OPTARG////_}
+      ;;
+    : )
+      echo "Invalid option: $OPTARG requires dev wls path"
+      exit 1
+      ;;
+    p )
+      DPDK_WLS=1
+      ;;
+  esac
+done
+
+wlsTestBinary="wls_test"
+if [ $DPDK_WLS -eq 1 ]; then
+    if [ $SECONDARY -eq 0 ]; then
+        wlsTestBinary="build/wls_test -c $COREMASK -n 4 "
+        wlsTestBinary+="--file-prefix=$FPREFIX --socket-mem=3072 --"
+    else
+        wlsTestBinary="build/wls_test -c $COREMASK -n 4 "
+        wlsTestBinary+="--proc-type=secondary --file-prefix=$FPREFIX --"
+    fi
+fi
+
+ulimit -c unlimited
+
+export RTE_WLS=$PWD/..
+
+MACHINE_TYPE=`uname -m`
+
+if [ ${MACHINE_TYPE} == 'x86_64' ]; then
+    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RTE_WLS
+
+    grep Huge /proc/meminfo
+
+    ulimit -c unlimited
+    echo 1 > /proc/sys/kernel/core_uses_pid
+    sysctl -w kernel.sched_rt_runtime_us=-1
+    for c in $(ls -d /sys/devices/system/cpu/cpu[0-9]*); do echo performance >$c/cpufreq/scaling_governor; done
+    sysctl -w kernel.shmmax=2147483648
+    sysctl -w kernel.shmall=2147483648
+fi
+
+wlsCmd="./${wlsTestBinary} $*"
+echo "Running... ${wlsCmd}"
+
+eval $wlsCmd
+
+exit 0
diff --git a/wls_lib/ttypes.h b/wls_lib/ttypes.h
new file mode 100644 (file)
index 0000000..4130efc
--- /dev/null
@@ -0,0 +1,195 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef __TTYPES_H__
+#define __TTYPES_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef TRUE
+#define TRUE    1
+#endif /*TRUE*/
+
+#ifndef FALSE
+#define FALSE   0
+#endif /*FALSE*/
+
+#ifndef NULL
+#define NULL   (void*)0
+#endif /*NULL*/
+
+/************************************************************************/
+/*     SINT64, SINT32, SINT16 and SINT8 definition                      */
+/************************************************************************/
+#ifndef _SINT64_
+#define _SINT64_
+typedef long long SINT64, *PSINT64;
+#endif /*_SINT64_*/
+
+#ifndef _SINT32_
+#define _SINT32_
+typedef int SINT32, *PSINT32;
+#endif /*_SINT32_*/
+
+#ifndef _SINT16_
+#define _SINT16_
+typedef short SINT16, *PSINT16;
+#endif /*_SINT16_*/
+
+#ifndef _SINT8_
+#define _SINT8_
+typedef char SINT8, *PSINT8;
+#endif /*_SINT8_*/
+
+#ifndef _PVOID_
+#define _PVOID_
+typedef void *PVOID;
+#endif /*_PVOID_*/
+
+#ifndef _BOOL_
+#define _BOOL_
+typedef unsigned char BOOL;
+#endif /*_BOOL_*/
+
+#ifndef _U8_
+typedef unsigned char  U8;      /* unsigned 8-bit  integer */
+#define _U8_
+#endif
+
+#ifndef _U16_
+typedef unsigned short U16;     /* unsigned 16-bit integer */
+#define _U16_
+#endif
+
+#ifndef _U32_
+typedef unsigned int   U32;     /* unsigned 32-bit integer */
+#define _U32_
+#endif
+
+#ifndef _U64_
+#ifdef __x86_64__
+typedef unsigned long  U64;     /* unsigned 64-bit integer */
+#else
+typedef unsigned long long  U64;     /* unsigned 64-bit integer */
+#endif
+#define _U64_
+#endif
+
+#ifndef _V8_
+typedef volatile unsigned char  V8;
+#define _V8_
+#endif
+
+#ifndef _V16_
+typedef volatile unsigned short V16;
+#define _V16_
+#endif
+
+#ifndef _V32_
+typedef volatile unsigned int  V32;
+#define _V32_
+#endif
+
+#ifndef _S8_
+typedef signed char  S8;         /* 8-bit  signed integer */
+#define _S8_
+#endif
+
+#ifndef _S16_
+typedef signed short S16;       /* 16-bit signed integer */
+#define _S16_
+#endif
+
+#ifndef _S32_
+typedef signed int   S32;        /* 32-bit signed integer */
+#define _S32_
+#endif
+
+#ifndef _S64_
+#ifdef __x86_64__
+typedef signed long  S64;          /* unsigned 64-bit integer */
+#else
+typedef signed long long  S64;     /* unsigned 64-bit integer */
+#endif
+#define _S64_
+#endif
+
+#ifndef _PVOID_
+#define _PVOID_
+typedef void *PVOID;
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+#define CONV_ENDIAN_32(v) ((v & 0xff) << 24 | (v >> 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8));
+
+
+#ifndef MAX
+#define MAX(x, y) ((x) >= (y) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define MIN(x, y) ((x) <= (y) ? (x) : (y))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+typedef void (*VOIDCB)(void);
+
+typedef void (*CALLBACK)(PVOID);
+
+#define BCTRL_LEN_MASK      0x0000FFFF
+#define BCTRL_BLAST_MASK    0x00010000
+
+#define DMAFCTRL_IRQEN      0x00000001
+#define DMAFCTRL_INBOFF     0x0000FFF0
+
+#define ARRAY_COUNT(v)      (sizeof(v)/sizeof(v[0]))
+
+#ifndef ROUND
+#define ROUND(x, dx)  (((x) + ((dx) - 1) ) & ~((dx) - 1))
+#endif
+
+#define REG32CLR(addr, clr_mask) ( REG32(addr) = REG32(addr) & (~(clr_mask)) )
+#define REG32SET(addr, set_mask) ( REG32(addr) = REG32(addr) | (set_mask) )
+#define REG32UPD(addr, clr_mask, set_mask) ( REG32(addr) = (REG32(addr) & (~(clr_mask))) | (set_mask) )
+
+// Standard function return types
+#ifndef _RESULTCODE_
+#define _RESULTCODE_
+typedef unsigned int RESULTCODE;
+#endif
+
+typedef unsigned int RETURNVALUE;
+
+#define SUCCESS                     0
+#define FAILURE                     1
+#define EXPIRED                     2       // Not an error - wait operation expired
+#define RESTART                     3       // Not an error - indicate we need to restart process
+
+//#define _DEBUG_
+
+#endif /*__SYSTYPES_H__ */
+
diff --git a/wls_lib/wls.h b/wls_lib/wls.h
new file mode 100644 (file)
index 0000000..d711a62
--- /dev/null
@@ -0,0 +1,352 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef __WLS_H__
+#define __WLS_H__
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#define MODNAME (KBUILD_MODNAME)
+#else /* __KERNEL__ */
+#include <sys/ioctl.h>
+#include <stdint.h>
+
+#ifdef DPDK_WLS
+#include <semaphore.h>
+#include <rte_common.h>
+#include <rte_atomic.h>
+#include <rte_memzone.h>
+#endif /* DPDK_WLS */
+
+#endif
+#include "ttypes.h"
+#include "syslib.h"
+
+#define WLS_PRINT(format, args...) printk(format, ##args)
+#define WLS_ERROR(format, args...) printk(KERN_ERR "wls err: " format,##args)
+
+#ifdef _DEBUG_
+#define WLS_DEBUG(format, args...)            \
+do {                                          \
+    printk(KERN_INFO "wls debug: " format,##args); \
+}while(0)
+#else /*_DEBUG_*/
+#define WLS_DEBUG(format, args...) do { } while(0)
+#endif /*_DEBUG_*/
+
+/******************************************************************************
+*                        Module error codes                                   *
+******************************************************************************/
+#define WLS_RC_MDMA_ID_ERROR                (-1)
+#define WLS_RC_MDMA_TASK_ERROR              (-2)
+#define WLS_RC_ALLOC_DELAY_MEM_ERROR        (-3)
+#define WLS_RC_ALLOC_BAR_MEM_ERROR          (-4)
+#define WLS_RC_ALLOC_TAR_MEM_ERROR          (-5)
+#define WLS_RC_PARAM_SIZE_ERROR             (-6)
+#define WLS_RC_WLS_HEAP_ALLOC_ERROR         (-7)
+#define WLS_RC_IRQ_ALLOC_ERROR              (-8)
+#define WLS_RC_DMA_ALLOC_ERROR              (-9)
+#define WLS_RC_TRANSACTION_ERROR            (-10)
+#define WLS_RC_PHY_CTX_ERROR                (-11)
+#define WLS_RC_KERNEL_HEAP_ALLOC_ERROR      (-12)
+#define WLS_RC_CONFIGURATION_ERROR          (-13)
+#define WLS_RC_THREAD_CREATION_ERROR        (-14)
+
+#define WLS_IOC_MAGIC 'W'
+#define WLS_IOC_OPEN         _IOWR(WLS_IOC_MAGIC, WLS_IOC_OPEN_NO,         uint64_t)
+#define WLS_IOC_CLOSE        _IOWR(WLS_IOC_MAGIC, WLS_IOC_CLOSE_NO,        uint64_t)
+#define WLS_IOC_PUT          _IOWR(WLS_IOC_MAGIC, WLS_IOC_PUT_NO,          uint64_t)
+#define WLS_IOC_EVENT        _IOWR(WLS_IOC_MAGIC, WLS_IOC_EVENT_NO,        uint64_t)
+#define WLS_IOC_WAIT         _IOWR(WLS_IOC_MAGIC, WLS_IOC_WAIT_NO,         uint64_t)
+#define WLS_IOC_WAKE_UP      _IOWR(WLS_IOC_MAGIC, WLS_IOC_WAKE_UP_NO,      uint64_t)
+#define WLS_IOC_CONNECT      _IOWR(WLS_IOC_MAGIC, WLS_IOC_CONNECT_NO,      uint64_t)
+#define WLS_IOC_FILL         _IOWR(WLS_IOC_MAGIC, WLS_IOC_FILL_NO,         uint64_t)
+
+enum {
+    WLS_IOC_OPEN_NO = 1,
+    WLS_IOC_CLOSE_NO,
+    WLS_IOC_PUT_NO,
+    WLS_IOC_EVENT_NO,
+    WLS_IOC_WAIT_NO,
+    WLS_IOC_WAKE_UP_NO,
+    WLS_IOC_CONNECT_NO,
+    WLS_IOC_FILL_NO,
+    WLS_IOC_COUNT,
+};
+
+enum {
+    WLS_FILL_PUSH = 1,
+    WLS_FILL_PULL,
+    WLS_FILL_MAX,
+};
+
+
+#define WLS_US_CLIENTS_MAX 64
+
+#define CACHE_LINE_SIZE 64                  /**< Cache line size. */
+#define CACHE_LINE_MASK (CACHE_LINE_SIZE-1) /**< Cache line mask. */
+
+#define CACHE_LINE_ROUNDUP(size) \
+    (CACHE_LINE_SIZE * ((size + CACHE_LINE_SIZE - 1) / CACHE_LINE_SIZE))
+
+#define DMA_ALIGNMENT_SIZE     256L
+
+// To make DMA we make sure that block starts on 256 bytes boundary
+#define DMA_ALIGNMENT_ROUNDUP(size) \
+    (DMA_ALIGNMENT_SIZE * ((size + DMA_ALIGNMENT_SIZE - 1) / DMA_ALIGNMENT_SIZE))
+
+/**< Return the first cache-aligned value greater or equal to size. */
+
+/**
+ * Force alignment to cache line.
+ */
+#define __wls_cache_aligned __attribute__((__aligned__(CACHE_LINE_SIZE)))
+
+#define WLS_HUGE_DEF_PAGE_SIZE                0x40000000LL
+#define WLS_IS_ONE_HUGE_PAGE(ptr, size, hp_size)  ((((unsigned long long)ptr & (~(hp_size - 1)))\
+        == (((unsigned long long)ptr + size - 1) & (~(hp_size - 1)))) ? 1 : 0)
+
+typedef struct hugepage_tabl_s
+{
+    union {
+        void     *pageVa;
+        uint64_t padding_pageVa;
+    };
+    uint64_t pagePa;
+}hugepage_tabl_t;
+
+#define DMA_MAP_MAX_BLOCK_SIZE 64*1024
+#define MAX_N_HUGE_PAGES 512
+#define UL_FREE_BLOCK_QUEUE_SIZE  384
+
+#define WLS_GET_QUEUE_N_ELEMENTS  384
+#define WLS_PUT_QUEUE_N_ELEMENTS  384
+
+#ifdef DPDK_WLS
+#define WLS_DEV_SHM_NAME_LEN      RTE_MEMZONE_NAMESIZE
+#else
+#define WLS_DEV_SHM_NAME_LEN          256
+#endif
+
+#define FIFO_LEN 384
+
+typedef struct wls_wait_req_s {
+    uint64_t wls_us_kernel_va;
+    uint64_t start_time;
+    uint64_t ctx;
+    uint64_t action;
+    uint64_t nMsg;
+}wls_wait_req_t;
+
+#ifdef DPDK_WLS
+typedef struct wls_sema_priv_s
+{
+    sem_t                     sem;
+    rte_atomic16_t            is_irq;
+    wls_wait_req_t            drv_block[FIFO_LEN];
+    volatile unsigned int     drv_block_put;
+    volatile unsigned int     drv_block_get;
+} wls_sema_priv_t;
+
+typedef struct wls_us_priv_s
+{
+    wls_sema_priv_t   sema;
+    U8                NeedToWakeUp;
+    U8                isWait;
+    volatile V32      pid;
+} wls_us_priv_t;
+
+#endif
+
+typedef struct wls_us_ctx_s
+{
+    union {
+       void *      wls_us_user_space_va;
+       uint64_t    padding_wls_us_user_space_va;
+    };
+
+    uint64_t       wls_us_kernel_va;
+
+    uint64_t       wls_us_pa;
+
+    uint32_t       wls_us_ctx_size;
+    uint32_t       HugePageSize;
+
+    union {
+        void*      alloc_buffer;
+        uint64_t   padding_alloc_buffer;
+    };
+
+    hugepage_tabl_t    hugepageTbl [MAX_N_HUGE_PAGES];
+
+    FASTQUEUE          ul_free_block_pq;
+    uint64_t           ul_free_block_storage[UL_FREE_BLOCK_QUEUE_SIZE * sizeof(uint64_t)];
+
+    WLS_MSG_QUEUE  get_queue;
+    WLS_MSG_HANDLE get_storage[WLS_GET_QUEUE_N_ELEMENTS];
+
+    WLS_MSG_QUEUE  put_queue;
+    WLS_MSG_HANDLE put_storage[WLS_PUT_QUEUE_N_ELEMENTS];
+
+    uint64_t           freePtrList[UL_FREE_BLOCK_QUEUE_SIZE * sizeof(uint64_t)];
+    uint32_t          freeListIndex;
+    uint32_t         dualMode;
+
+    // dst userspace context address (kernel va)
+    uint64_t    dst_kernel_va;
+    // dst userspace context address (local user sapce va)
+
+    volatile uint64_t    dst_user_va;
+    // dst userspace context address (local user sapce va)
+    volatile uint64_t    dst_pa;
+
+    uint32_t  alloc_size;
+#ifdef DPDK_WLS
+    wls_us_priv_t wls_us_private;
+#else
+    HANDLE wls_us_private;
+#endif
+    uint32_t  mode;
+    uint32_t  secmode;
+    char wls_dev_name[WLS_DEV_SHM_NAME_LEN];
+    char wls_shm_name[WLS_DEV_SHM_NAME_LEN];
+}wls_us_ctx_t;
+
+
+
+typedef struct wls_fill_req_s {
+    uint64_t wls_us_kernel_va;
+    uint64_t ctx;
+    uint64_t action;
+    uint64_t nMsg;
+}wls_fill_req_t;
+
+typedef struct wls_connect_req_s {
+    uint64_t wls_us_kernel_va;
+}wls_connect_req_t;
+
+#ifdef __KERNEL__
+
+typedef struct wls_sema_priv_s
+{
+    wait_queue_head_t         queue;
+    atomic_t                  is_irq;
+    wls_wait_req_t            drv_block[FIFO_LEN];
+    volatile unsigned int     drv_block_put;
+    volatile unsigned int     drv_block_get;
+}wls_sema_priv_t;
+
+typedef struct wls_drv_ctx_s
+{
+    uint32_t            init_mask;
+    uint32_t            us_ctx_cout;
+    wls_us_ctx_t*       p_wls_us_ctx[WLS_US_CLIENTS_MAX];
+    wls_us_ctx_t*       p_wls_us_pa_ctx[WLS_US_CLIENTS_MAX];
+    uint32_t            nWlsClients;
+}wls_drv_ctx_t;
+
+#elif defined DPDK_WLS
+
+typedef struct wls_drv_ctx_s
+{
+    uint32_t            init_mask;
+    uint32_t            us_ctx_cout;
+    wls_us_ctx_t        p_wls_us_ctx[WLS_US_CLIENTS_MAX];
+    wls_us_ctx_t        p_wls_us_pa_ctx[WLS_US_CLIENTS_MAX];
+    uint32_t            nWlsClients;
+    pthread_mutex_t mng_mutex;
+}wls_drv_ctx_t;
+
+#endif
+typedef struct wls_open_req_s {
+    uint64_t  ctx;
+    uint64_t  ctx_pa;
+    uint32_t  size;
+}wls_open_req_t;
+
+typedef struct wls_close_req_s {
+    uint64_t  ctx;
+    uint64_t  ctx_pa;
+    uint32_t  size;
+}wls_close_req_t;
+
+typedef enum wls_events_num_s {
+    WLS_EVENT_IA_READY = 0,
+    WLS_EVENT_IA_STOP,
+    WLS_EVENT_IA_ERROR,
+    WLS_EVENT_MAX
+}wls_events_num_t;
+
+typedef struct wls_event_req_s {
+    uint64_t wls_us_kernel_va;
+    uint64_t event_to_wls;
+    uint64_t event_param;
+}wls_event_req_t;
+
+typedef struct wls_put_req_s {
+    uint64_t wls_us_kernel_va;
+}wls_put_req_t;
+
+typedef struct wls_wake_up_req_s {
+    uint64_t wls_us_kernel_va;
+    uint32_t id;
+    uint64_t ctx;
+}wls_wake_up_req_t;
+
+
+#define SYS_CPU_CLOCK              (2300000000L)
+#define CLOCK_PER_MS               (SYS_CPU_CLOCK/1000)
+#define CLOCK_PER_US               (SYS_CPU_CLOCK/1000000)
+
+static inline uint64_t
+wls_rdtsc(void)
+{
+    union {
+        uint64_t tsc_64;
+        struct {
+            uint32_t lo_32;
+            uint32_t hi_32;
+        };
+    } tsc;
+
+    asm volatile("rdtsc" :
+             "=a" (tsc.lo_32),
+             "=d" (tsc.hi_32));
+    return tsc.tsc_64;
+}
+
+static inline uint64_t rdtsc_ticks_diff(unsigned long curr, unsigned long prev)
+{
+    if (curr >= prev)
+        return (unsigned long)(curr - prev);
+    else
+        return (unsigned long)(0xFFFFFFFFFFFFFFFF - prev + curr);
+}
+
+void  wls_show_data(void* ptr, unsigned int size);
+void *wls_get_sh_ctx(void);
+void *wls_get_sh_ctx_pa(void);
+
+#endif /* __WLS_H__*/
+
diff --git a/wls_lib/wls_debug.h b/wls_lib/wls_debug.h
new file mode 100644 (file)
index 0000000..98cb4e6
--- /dev/null
@@ -0,0 +1,38 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef __WLS_DEBUG_H__
+#define __WLS_DEBUG_H__
+
+#include <linux/types.h>
+
+/* mlog specific defenitions */
+
+#define PID_WLS_DRV_IOC_WAIT_WAKE_UP           77000
+#define PID_WLS_DRV_IOC_WAIT_WAKE_ENTRY        77001
+#define PID_WLS_DRV_IOC_PUT                    77002
+#define PID_WLS_DRV_ISR                        77003
+#define PID_WLS_DRV_IOC_FILL                   77004
+
+#define MLOG_VAR_MSG_BLOCK                     0xDEAD7000
+#define MLOG_VAR_MSG_TIME_SYNC                 0xDEAD7001
+#define MLOG_VAR_MSG_COPY_THREAD                   0xDEAD7002
+
+
+#endif /* __WLS_DEBUG_H__*/
+
diff --git a/wls_lib/wls_drv.c b/wls_lib/wls_drv.c
new file mode 100644 (file)
index 0000000..8b7543c
--- /dev/null
@@ -0,0 +1,856 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+
+#include "wls.h"
+#include "wls_drv.h"
+#include "wls_debug.h"
+
+#if defined(_MLOG_TRACE_)
+#include "mlog.h"
+#endif
+
+#define WLS_VERSION_X           0
+#define WLS_VERSION_Y           0
+#define WLS_VERSION_Z           3
+#define WLS_VERSION_RESERVED    0
+#define WLS_DRV_VERSION        ((WLS_VERSION_X << 24) | (WLS_VERSION_Y << 16) | (WLS_VERSION_Z << 8) | WLS_VERSION_RESERVED)
+
+#define WLS_DRV_VERSION_FORMAT "%d.%d.%d"
+#define WLS_DEV_DEVICE_FORMAT "wls%d"
+
+
+#define WLS_SEMA_COUNT 32
+#define WLS_MAX_CLIENTS 8
+
+
+typedef struct wls_us_priv_s
+{
+    wls_sema_priv_t   sema;
+
+    U8                NeedToWakeUp;
+    U8                isWait;
+
+    U32               pid;
+} wls_us_priv_t;
+
+char wls_driver_name[] = "wls";
+char wls_driver_version[10];
+char wls_dev_device_name[10];
+
+static long wls_ioctl(struct file * filp, unsigned int cmd, unsigned long arg);
+static int  wls_open(struct inode * inode, struct file * filp);
+static int  wls_release(struct inode * inode, struct file * filp);
+static int  wls_mmap(struct file * filp, struct vm_area_struct * vma);
+static int  wls_wait(wls_sema_priv_t *priv, unsigned long arg);
+static int  wls_wake_up_user_thread(char *buf, wls_sema_priv_t *semap);
+
+static struct file_operations wls_fops = {
+    .owner = THIS_MODULE,
+    .open = wls_open,
+    .release = wls_release,
+    .unlocked_ioctl = wls_ioctl,
+    .compat_ioctl = wls_ioctl,
+    .mmap = wls_mmap,
+};
+
+static struct wls_dev_t*  wls_dev[WLS_MAX_CLIENTS];
+static wls_drv_ctx_t    wls_drv_ctx[WLS_MAX_CLIENTS];
+
+static struct class * wls_class;
+
+/**********************************************************************
+*                      Module Parameters                              *
+**********************************************************************/
+int     wlsMaxClients               = 1;
+
+
+/**********************************************************************/
+module_param(wlsMaxClients,             int, S_IRUSR);
+
+/**********************************************************************/
+
+static wls_drv_ctx_t * wls_get_ctx(unsigned int id)
+{
+    if(id < WLS_MAX_CLIENTS)
+        return &wls_drv_ctx[id];
+    else
+        return NULL;
+}
+
+int wls_wake_up_user_thread(char *buf, wls_sema_priv_t *semap)
+{
+    if (likely(atomic_read(&semap->is_irq) < FIFO_LEN)) {
+        unsigned int put = semap->drv_block_put + 1;
+        if (put >= FIFO_LEN)
+            put = 0;
+        //copy data from user
+        memcpy(&semap->drv_block[put], buf, sizeof(wls_wait_req_t));
+
+        semap->drv_block_put = put;
+        atomic_inc(&semap->is_irq);
+#ifdef DEBUG
+        printk(KERN_INFO "[wls]:PUT: put=%d get=%d T=%lu is_irq=%d\n",
+               semap->drv_block_put, semap->drv_block_get,
+               semap->drv_block[put].start_time , atomic_read(&semap->is_irq));
+#endif /* DEBUG */
+        wake_up_interruptible(&semap->queue);
+    }
+
+    return 0;
+}
+
+void wls_show_data(void* ptr, unsigned int size)
+{
+    unsigned char *d = ptr;
+    int i;
+
+    for(i = 0; i < size; i++)
+    {
+        if ( !(i & 0xf) )
+            printk("\n");
+        printk("%02x ", d[i]);
+    }
+    printk("\n");
+}
+
+static int wls_open(struct inode * inode, struct file * filp)
+{
+    if((MINOR(inode->i_rdev ) >= 0) && (MINOR(inode->i_rdev) < wlsMaxClients) && (MINOR(inode->i_rdev ) < WLS_MAX_CLIENTS)){
+        filp->private_data = (void *)wls_dev[MINOR(inode->i_rdev)];
+        WLS_DEBUG("wls_open [%d] priv: 0x%p",MINOR(inode->i_rdev), filp->private_data);
+        WLS_DEBUG("wls_open PID [%d] ", current->pid);
+    } else {
+        WLS_ERROR("wls_open PID [%d] incorrect  inode->i_rdev %d", current->pid, MINOR(inode->i_rdev));
+    }
+
+    return 0;
+}
+
+static int wls_release(struct inode * inode, struct file * filp)
+{
+    struct wls_dev_t* wls_loc = NULL;
+    wls_us_ctx_t*     pUsCtx   = NULL;
+    wls_us_priv_t*    pUs_priv = NULL;
+    wls_drv_ctx_t*    pDrv_ctx = NULL;
+    int i = 0;
+
+    WLS_DEBUG("priv: 0x%p", filp->private_data);
+    WLS_DEBUG("wls_release PID [%d] ",current->pid);
+
+    if((MINOR(inode->i_rdev ) >= 0) && (MINOR(inode->i_rdev) < wlsMaxClients) && (MINOR(inode->i_rdev ) < WLS_MAX_CLIENTS)){
+        if (filp->private_data != NULL) {
+            wls_loc = (struct wls_dev_t*)filp->private_data;
+            if((void *)wls_dev[MINOR(inode->i_rdev)] == (void *)wls_loc){
+                pDrv_ctx = (wls_drv_ctx_t*)wls_loc->pWlsDrvCtx;
+                if(pDrv_ctx){
+                    for(i = 0; i < 2; i++ ){
+                        pUsCtx =  (wls_us_ctx_t*)pDrv_ctx->p_wls_us_ctx[i];
+                        if(pUsCtx){
+                            wls_us_ctx_t* dst = (wls_us_ctx_t*)pUsCtx->dst_kernel_va;
+                            wls_wait_req_t drv_block;
+                            if(dst){
+                                wls_us_priv_t* pDstPriv = (wls_us_priv_t*)dst->wls_us_private;
+                                if(pDstPriv){
+                                    drv_block.start_time = wls_rdtsc();
+                                    pDstPriv->NeedToWakeUp = 1;
+                                    wls_wake_up_user_thread((char *)&drv_block, &pDstPriv->sema);
+                                }
+                            }
+                            //un-link ctx
+                            pDrv_ctx->p_wls_us_ctx[i]->dst_kernel_va = (uint64_t)0;
+                            pDrv_ctx->p_wls_us_ctx[i]->dst_user_va = (uint64_t)0;
+                            pDrv_ctx->p_wls_us_ctx[i]->dst_pa = (uint64_t)0;
+                        }
+                    }
+
+                    for(i = 0; i < 2; i++ ){
+                        pUsCtx =  (wls_us_ctx_t*)pDrv_ctx->p_wls_us_ctx[i];
+
+                        if(pUsCtx){
+                            pUs_priv = (wls_us_priv_t*)pUsCtx->wls_us_private;
+                            if(pUs_priv){
+                                if(pUs_priv->pid == current->pid){
+                                    if (pUs_priv->isWait == 0){
+                                            pUsCtx->wls_us_private = NULL;
+                                            kfree(pUs_priv);
+                                            pDrv_ctx->p_wls_us_ctx[i]    = NULL;
+                                            dma_free_coherent(wls_loc->device, sizeof(wls_us_ctx_t),(void*)pUsCtx, (long)pDrv_ctx->p_wls_us_pa_ctx[i]);
+                                            pDrv_ctx->p_wls_us_pa_ctx[i] = NULL;
+                                            pDrv_ctx->nWlsClients--;
+                                    } else {
+                                        WLS_PRINT("Wait is in process\n");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            filp->private_data = NULL;
+        }
+    } else {
+        WLS_ERROR("wls_release PID [%d] incorrect  inode->i_rdev %d", current->pid, MINOR(inode->i_rdev));
+    }
+
+    return 0;
+}
+
+static int wls_wait(wls_sema_priv_t *priv, unsigned long arg)
+{
+    char __user *buf = (char __user *)arg;
+
+    if (!likely(atomic_read(&priv->is_irq))) {
+        if (unlikely(wait_event_interruptible(priv->queue, atomic_read(&priv->is_irq)))) {
+            return -ERESTARTSYS;
+        }
+    }
+
+    atomic_dec(&priv->is_irq);
+
+    if (priv->drv_block_put != priv->drv_block_get) {
+        unsigned int get = priv->drv_block_get + 1;
+
+        if (get >= FIFO_LEN)
+            get = 0;
+
+        if (copy_to_user(buf, &priv->drv_block[get], sizeof(wls_wait_req_t))) {
+            return -EFAULT;
+        }
+
+        priv->drv_block_get = get;
+
+#ifdef DEBUG
+        printk(KERN_INFO "[wls]:GET: put=%d get=%d T=%lu is_irq=%d\n",
+               priv->drv_block_put, priv->drv_block_get,
+               priv->drv_block[get].start_time, atomic_read(&priv->is_irq));
+#endif /* DEBUG */
+
+    } else {
+#ifdef DEBUG
+        printk(KERN_ERR "[wls]: wrong computation of queueing\n");
+#endif /* DEBUG */
+    }
+
+    return 0;
+}
+
+static unsigned wls_is_us_opened(wls_open_req_t *param)
+{
+    // TODO: add check
+
+        return 0;
+}
+
+wls_us_ctx_t *wls_create_us_ctx(wls_open_req_t *param, struct wls_dev_t * wls_loc)
+{
+    wls_us_ctx_t*     pUsCtx = NULL;
+    wls_drv_ctx_t*    pDrv_ctx =  wls_loc->pWlsDrvCtx;
+
+    // check if instance already registered
+    if(wls_is_us_opened(param))
+        goto err0;
+
+    // allocate memory for shared portion
+    pUsCtx = (wls_us_ctx_t*)dma_alloc_coherent(NULL, param->size, (dma_addr_t *)&param->ctx_pa, GFP_KERNEL);
+    WLS_DEBUG("wls_create_us_ctx: pUsCtx  0x%016lx\n", (unsigned long)pUsCtx);
+    if (pUsCtx){
+        // allocate memory for private
+        wls_us_priv_t *pUs_priv = kmalloc(sizeof(wls_us_priv_t), GFP_KERNEL);
+
+        if(pUs_priv == NULL)
+            goto err1;
+        // init shared
+        memset (pUsCtx, 0, sizeof(wls_us_ctx_t));
+
+        SFL_DefQueue(&pUsCtx->ul_free_block_pq, pUsCtx->ul_free_block_storage, UL_FREE_BLOCK_QUEUE_SIZE * sizeof(void*));
+        WLS_PRINT("ul free: off %lx\n",((U64) &pUsCtx->ul_free_block_pq -(U64)pUsCtx));
+
+        WLS_MsgDefineQueue(&pUsCtx->get_queue, pUsCtx->get_storage, WLS_GET_QUEUE_N_ELEMENTS, 0);
+        WLS_PRINT("get_queue: off %lx\n",((U64) &pUsCtx->get_queue -(U64)pUsCtx));
+
+        WLS_MsgDefineQueue(&pUsCtx->put_queue, pUsCtx->put_storage, WLS_PUT_QUEUE_N_ELEMENTS, 0);
+        WLS_PRINT("put_queue: off %lx\n",((U64) &pUsCtx->put_queue -(U64)pUsCtx));
+
+        // init private
+        memset (pUs_priv, 0, sizeof(wls_us_priv_t));
+        init_waitqueue_head(&pUs_priv->sema.queue);
+        atomic_set(&pUs_priv->sema.is_irq, 0);
+
+        pUs_priv->pid = current->pid;
+
+        pUsCtx->wls_us_private = pUs_priv;
+        WLS_DEBUG("wls_create_us_ctx: pUsCtx->wls_us_private 0x%016lx\n", (unsigned long)pUsCtx->wls_us_private);
+    } else
+        goto err0;
+
+    pDrv_ctx->p_wls_us_ctx[pDrv_ctx->nWlsClients]      = pUsCtx;
+    pDrv_ctx->p_wls_us_pa_ctx[pDrv_ctx->nWlsClients++] = (wls_us_ctx_t*)param->ctx_pa;
+
+    if(pDrv_ctx->p_wls_us_ctx[0] && pDrv_ctx->p_wls_us_ctx[1])
+    {
+        //link ctx
+        pDrv_ctx->p_wls_us_ctx[0]->dst_kernel_va = (uint64_t)pDrv_ctx->p_wls_us_ctx[1];
+        pDrv_ctx->p_wls_us_ctx[0]->dst_pa        = (uint64_t) pDrv_ctx->p_wls_us_pa_ctx[1];
+
+        pDrv_ctx->p_wls_us_ctx[1]->dst_kernel_va = (uint64_t)pDrv_ctx->p_wls_us_ctx[0];
+        pDrv_ctx->p_wls_us_ctx[1]->dst_pa        = (uint64_t) pDrv_ctx->p_wls_us_pa_ctx[0];
+
+        pDrv_ctx->p_wls_us_ctx[0]->dst_kernel_va = (uint64_t)pDrv_ctx->p_wls_us_ctx[1];
+        pDrv_ctx->p_wls_us_ctx[0]->dst_pa        = (uint64_t) pDrv_ctx->p_wls_us_pa_ctx[1];
+        pDrv_ctx->p_wls_us_ctx[1]->dst_kernel_va = (uint64_t)pDrv_ctx->p_wls_us_ctx[0];
+        pDrv_ctx->p_wls_us_ctx[1]->dst_pa        = (uint64_t) pDrv_ctx->p_wls_us_pa_ctx[0];
+
+        WLS_DEBUG("link: 0 <-> 1: 0: 0x%016lx 1: 0x%016lx\n", (long unsigned int)pDrv_ctx->p_wls_us_ctx[0]->dst_kernel_va,
+                                                              (long unsigned int)pDrv_ctx->p_wls_us_ctx[1]->dst_kernel_va);
+    }
+
+    return pUsCtx;
+
+//err2:
+    kfree(pUsCtx->wls_us_private);
+err1:
+    dma_free_coherent(wls_loc->device, param->size, pUsCtx, param->ctx_pa);
+err0:
+    return NULL;
+}
+
+
+int wls_destroy_us_ctx(wls_close_req_t *param,     struct wls_dev_t * wls_prv)
+{
+    wls_us_ctx_t*  pUsCtx   = NULL;
+    wls_us_priv_t* pUs_priv = NULL;
+
+    wls_drv_ctx_t*    pDrv_ctx =  wls_prv->pWlsDrvCtx;
+
+    if(pDrv_ctx->p_wls_us_ctx[0] && pDrv_ctx->p_wls_us_ctx[1])
+    {
+        //link ctx
+        pDrv_ctx->p_wls_us_ctx[0]->dst_kernel_va = (uint64_t)0;
+        pDrv_ctx->p_wls_us_ctx[1]->dst_kernel_va = (uint64_t)0;
+        pDrv_ctx->p_wls_us_ctx[0]->dst_user_va = (uint64_t)0;
+        pDrv_ctx->p_wls_us_ctx[1]->dst_user_va = (uint64_t)0;
+        pDrv_ctx->p_wls_us_ctx[0]->dst_pa = (uint64_t)0;
+        pDrv_ctx->p_wls_us_ctx[1]->dst_pa = (uint64_t)0;
+
+        WLS_DEBUG("un-link: 0 <-> 1: 0: 0x%016lx 1: 0x%016lx\n", (long unsigned int)pDrv_ctx->p_wls_us_ctx[0]->dst_kernel_va,
+                                                                 (long unsigned int)pDrv_ctx->p_wls_us_ctx[1]->dst_kernel_va);
+    }
+
+    pUsCtx =  (wls_us_ctx_t*)param->ctx;
+
+    if(pUsCtx){
+        pUs_priv = (wls_us_priv_t*)pUsCtx->wls_us_private;
+        if(pUs_priv){
+            if (pUs_priv->isWait == 0){
+
+                pUsCtx->wls_us_private = NULL;
+                kfree(pUs_priv);
+                if(param->ctx_pa){
+                    if( pDrv_ctx->p_wls_us_ctx[0] == pUsCtx){
+                        pDrv_ctx->p_wls_us_ctx[0]    = NULL;
+                        pDrv_ctx->p_wls_us_pa_ctx[0] = NULL;
+                    } else {
+                        pDrv_ctx->p_wls_us_ctx[1]    = NULL;
+                        pDrv_ctx->p_wls_us_pa_ctx[1] = NULL;
+                    }
+                    pDrv_ctx->nWlsClients--;
+                    dma_free_coherent(wls_prv->device, param->size, pUsCtx, param->ctx_pa);
+                }else{
+                    WLS_ERROR("param->ctx_pa is NULL\n");
+                }
+            } else
+                WLS_PRINT("Wait is in process\n");
+        }
+    }
+
+    return 0;
+}
+
+static int wls_process_wait(wls_us_ctx_t* pUsCtx)
+{
+    int n = WLS_GetNumItemsInTheQueue(&pUsCtx->get_queue);
+
+    return n;
+}
+
+static int wls_process_put(wls_us_ctx_t *src, wls_us_ctx_t *dst)
+{
+    int ret = 0;
+    WLS_MSG_HANDLE hMsg;
+    int n = 0;
+
+    wls_us_priv_t* pDstPriv    =  NULL;
+    wls_wait_req_t drv_block;
+
+    WLS_DEBUG("offset get_queue %lx\n",(U64)&src->get_queue - (U64)src);
+
+    n = WLS_GetNumItemsInTheQueue(&src->put_queue);
+
+    while(n--)
+    {
+        if (WLS_MsgDequeue(&src->put_queue, &hMsg, NULL, (void*)src))
+        {
+           WLS_DEBUG("WLS_Get %lx %d type %d\n",(U64) hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID);
+           if(WLS_MsgEnqueue(&dst->get_queue, hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID, hMsg.flags, NULL,  (void*)dst) == FALSE){ // try to send
+               if(WLS_MsgEnqueue(&src->put_queue, hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID, hMsg.flags, NULL, (void*)src) == FALSE){ // return back
+                   WLS_ERROR("wls_process_put: Cannot return block to back to queue \n");
+                   ret = -1;
+               }
+               break;
+           }
+        }
+        else{
+            ret = -1;
+            break;
+        }
+
+    }
+
+    if(dst->wls_us_private){
+        pDstPriv = (wls_us_priv_t*)dst->wls_us_private;
+
+        drv_block.start_time = wls_rdtsc();
+        pDstPriv->NeedToWakeUp = 1;
+        wls_wake_up_user_thread((char *)&drv_block, &pDstPriv->sema);
+    }
+    else
+        ret = -1;
+
+    return ret;
+}
+
+static long wls_ioctl(struct file * filp, unsigned int cmd, unsigned long arg)
+{
+    struct wls_dev_t * wls_prv = (struct wls_dev_t *)filp->private_data;
+    void __user * to = (void __user *)arg;
+    const void __user * from = (const void __user *)arg;
+    long ret = 0;
+
+    WLS_DEBUG("wls_ioctl PID [%d] ", current->pid);
+
+    if (_IOC_TYPE(cmd) != WLS_IOC_MAGIC) {
+        return -ENOTTY;
+    }
+
+    if (_IOC_NR(cmd) >= WLS_IOC_COUNT) {
+        return -ENOTTY;
+    }
+
+    switch (cmd) {
+        case WLS_IOC_OPEN: {
+            wls_open_req_t param;
+
+            WLS_DEBUG("WLS_IOC_OPEN wls_us_ctx_t %ld\n", sizeof(wls_us_ctx_t));
+            ret = copy_from_user((void *)&param, from, sizeof(param));
+            if (ret != 0) {
+                WLS_ERROR("could not copy %lu bytes from user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+
+            if (sizeof(wls_drv_ctx_t) >= param.size){
+                WLS_ERROR("incorrect size %lu > %u\n", sizeof(wls_drv_ctx_t), param.size);
+                ret = -1;
+                break;
+            }
+
+            param.ctx = (uint64_t)wls_create_us_ctx(&param, wls_prv);
+            if (param.ctx == 0) {
+                WLS_ERROR("could not copy %lu bytes to  user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+
+            WLS_DEBUG("WLS_IOC_OPEN: kva %lx pa %lx sz [%d]\n", (long unsigned int)param.ctx, (long unsigned int)param.ctx_pa, param.size);
+
+            ret = copy_to_user(to, (const void *)&param, sizeof(wls_open_req_t));
+            if (ret != 0) {
+                WLS_ERROR("could not copy %lu bytes to  user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+        } break;
+        case WLS_IOC_CLOSE: {
+            wls_close_req_t param;
+
+            ret = copy_from_user((void *)&param, from, sizeof(param));
+            if (ret != 0) {
+                WLS_ERROR("could not copy %lu bytes from user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+            WLS_DEBUG("WLS_IOC_CLOSE: kva %lx pa %lx sz [%d]\n", (long unsigned int)param.ctx,  (long unsigned int)param.ctx_pa, param.size);
+
+            ret = wls_destroy_us_ctx(&param, wls_prv);
+
+            if (ret != 0) {
+                WLS_ERROR("could not copy %lu bytes from user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+        } break;
+        case WLS_IOC_PUT: {
+            wls_put_req_t param;
+            wls_us_ctx_t*  pUsCtx   = NULL;
+
+#if defined(_MLOG_TRACE_)
+            unsigned long t = MLOG_GETTICK();
+#endif
+            ret = copy_from_user((void *)&param, from, sizeof(param));
+            if (ret != 0) {
+                WLS_ERROR("could not copy %lu bytes from user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+
+            pUsCtx = (wls_us_ctx_t*)param.wls_us_kernel_va;
+            if (pUsCtx == NULL) {
+                WLS_ERROR("Transaction failed %ld\n", (unsigned long)ret);
+                break;
+            }
+
+            if(pUsCtx->dst_kernel_va)
+                ret = wls_process_put(pUsCtx, (wls_us_ctx_t*)pUsCtx->dst_kernel_va);
+
+            if (ret != 0) {
+                WLS_ERROR("Transaction failed %ld\n", (unsigned long)ret);
+                break;
+            }
+
+            /* clean up for next time */
+#if defined(_MLOG_TRACE_)
+            MLogTask(PID_WLS_DRV_IOC_PUT, t, MLOG_GETTICK());
+#endif
+        } break;
+        case WLS_IOC_EVENT: {
+            wls_event_req_t param;
+
+            ret = copy_from_user((void *)&param, from, sizeof(param));
+
+            if (ret != 0) {
+                WLS_ERROR("Event %ld failed %ld\n", (unsigned long)param.event_to_wls,
+                            (unsigned long)ret);
+                break;
+            }
+        }break;
+        case WLS_IOC_WAIT: {
+            wls_wait_req_t param;
+            wls_us_ctx_t*  pUsCtx  =  NULL;
+            wls_us_priv_t* pUsPriv =  NULL;
+#if defined(_MLOG_TRACE_)
+            unsigned long t = MLOG_GETTICK();
+            MLogTask(PID_WLS_DRV_IOC_WAIT_WAKE_ENTRY, t, 1250+t);
+#endif
+            ret = copy_from_user((void *)&param, from, sizeof(param));
+            if (ret != 0) {
+                WLS_ERROR("Wait failed %ld\n", (unsigned long)ret);
+                break;
+            }
+
+            WLS_DEBUG("Wait pUsCtx 0x%016lx\n", (unsigned long)param.wls_us_kernel_va);
+            pUsCtx  = (wls_us_ctx_t*)  param.wls_us_kernel_va;
+            if(pUsCtx == NULL) {
+                ret = -EINVAL;
+                WLS_ERROR("Wait failed on User context %ld\n", (unsigned long)ret);
+                break;
+            }
+
+            pUsPriv = (wls_us_priv_t*) pUsCtx->wls_us_private;
+            WLS_DEBUG("Wait pUsPriv 0x%016lx\n", (unsigned long)pUsPriv);
+
+            if(pUsPriv == NULL) {
+                ret = -EINVAL;
+                WLS_ERROR("Wait failed %ld\n", (unsigned long)ret);
+                break;
+            }
+            pUsPriv->isWait = 1;
+            wls_wait(&pUsPriv->sema, (unsigned long)from);
+            pUsPriv->isWait = 0;
+            memset(&param, 0, sizeof(wls_wait_req_t));
+            param.nMsg = wls_process_wait(pUsCtx);
+
+#if defined(_MLOG_TRACE_)
+            t = MLOG_GETTICK();
+#endif
+            ret = copy_to_user(to, (const void *)&param, sizeof(wls_wait_req_t));
+            if (ret != 0) {
+                WLS_ERROR("could not copy %lu bytes to  user 0x%08lx",
+                            (unsigned long)ret, (unsigned long)from);
+                break;
+            }
+#if defined(_MLOG_TRACE_)
+            MLogTask(PID_WLS_DRV_IOC_WAIT_WAKE_UP, t, MLOG_GETTICK());
+#endif
+        } break;
+        case WLS_IOC_WAKE_UP: {
+            wls_wait_req_t param;
+            wls_us_ctx_t*  pUsCtx  =  NULL;
+            wls_us_priv_t* pUsPriv =  NULL;
+            wls_wait_req_t drv_block;
+
+            ret = copy_from_user((void *)&param, from, sizeof(param));
+            if (ret != 0) {
+              WLS_ERROR("WLS_IOC_WAKE_UP failed %ld\n",
+                          (unsigned long)ret);
+              break;
+            }
+
+            WLS_DEBUG("Wait pUsCtx 0x%016lx\n", (unsigned long)param.wls_us_kernel_va);
+            pUsCtx  = (wls_us_ctx_t*)  param.wls_us_kernel_va;
+            if(pUsCtx == NULL) {
+                ret = -EINVAL;
+                WLS_ERROR("Wait failed on User context %ld\n", (unsigned long)ret);
+                break;
+            }
+
+            pUsPriv = (wls_us_priv_t*) pUsCtx->wls_us_private;
+            WLS_DEBUG("Wait pUsPriv 0x%016lx\n", (unsigned long)pUsPriv);
+
+            if(pUsPriv == NULL) {
+                ret = -EINVAL;
+                WLS_ERROR("Wait failed %ld\n", (unsigned long)ret);
+                break;
+            }
+
+            drv_block.start_time = wls_rdtsc();
+            wls_wake_up_user_thread((char *)&drv_block, &pUsPriv->sema);
+        } break;
+        case WLS_IOC_CONNECT: {
+          wls_connect_req_t param;
+          wls_us_priv_t* pUsPriv    =  NULL;
+          wls_wait_req_t drv_block;
+
+          ret = copy_from_user((void *)&param, from, sizeof(param));
+          if (ret != 0) {
+              WLS_ERROR("WLS_IOC_WAKE_UP failed %ld\n",
+                          (unsigned long)ret);
+              break;
+          }
+
+          pUsPriv = (wls_us_priv_t*)param.wls_us_kernel_va;
+          drv_block.start_time = wls_rdtsc();
+          wls_wake_up_user_thread((char *)&drv_block, &pUsPriv->sema);
+        } break;
+        default:{
+            WLS_ERROR("unknown ioctl cmd: '0x%08x'", cmd);
+            BUG();
+        } break;
+    }
+
+    if (ret != 0) {
+        WLS_ERROR("cmd_%x failed: %ld", cmd, ret);
+    }
+
+    return ret;
+}
+
+static int wls_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+    struct wls_dev_t * wls = (struct wls_dev_t *)filp->private_data;
+
+    WLS_DEBUG("priv: 0x%p", filp->private_data);
+    WLS_DEBUG("WLS_mmap : mmap function called \n");
+    WLS_DEBUG("vma->start =%lx\n",vma->vm_start);
+    WLS_DEBUG("vma->end =%lx\n",vma->vm_end);
+
+    // non cached
+//    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+    WLS_DEBUG("vma->pgoff =%lx\n",vma->vm_pgoff);
+
+    if (wls == NULL) {
+        WLS_ERROR("WLS is NULL");
+        return -EIO;
+    }
+
+    return  remap_pfn_range(vma,vma->vm_start,vma->vm_pgoff,vma->vm_end-vma->vm_start,\
+                            vma->vm_page_prot);
+}
+
+static int __init wls_init(void)
+{
+    struct wls_dev_t* wls_dev_loc = NULL;
+    int res = 0;
+    dev_t dev_no = 0;
+    int minor_no = 0;
+    int dev_cnt = 0;
+
+    memset(&wls_dev[0], 0, sizeof(struct wls_dev_t*) * WLS_MAX_CLIENTS);
+
+    snprintf(wls_driver_version, 10, WLS_DRV_VERSION_FORMAT, WLS_VERSION_X, WLS_VERSION_Y, WLS_VERSION_Z);
+
+    WLS_PRINT("Intel(R) Wireless Subsystem Communication interface - %s\n", wls_driver_version);
+    WLS_PRINT("Copyright(c) 2014 Intel Corporation.\n");
+    //WLS_PRINT("Build: Date: %s Time: %s\n", __DATE__, __TIME__);
+
+    if ((wlsMaxClients > WLS_MAX_CLIENTS) || (wlsMaxClients < 1))
+    {
+        WLS_ERROR("Invalid wlsMaxClients %d\n", wlsMaxClients);
+        wlsMaxClients = 1;
+    }
+    for (dev_cnt = 0; dev_cnt < wlsMaxClients; dev_cnt++){
+        wls_dev_loc  = (struct wls_dev_t *)kzalloc(sizeof(struct wls_dev_t), GFP_KERNEL);
+        WLS_DEBUG("wls_dev_loc %d %p", dev_cnt, wls_dev_loc);
+
+        if (wls_dev_loc == NULL) {
+            WLS_ERROR("no free memory (wanted %ld bytes)", sizeof(struct wls_dev_t));
+            res = -ENOMEM;
+            goto err0;
+        }
+        wls_dev[dev_cnt] = wls_dev_loc;
+        WLS_DEBUG("wls_init [%d]: 0x%p",dev_cnt, wls_dev[dev_cnt]);
+    }
+
+    res = alloc_chrdev_region(&dev_no, minor_no, wlsMaxClients, MODNAME);
+    if (res < 0) {
+        WLS_ERROR("failed alloc char dev region: %d", res);
+        goto err0;
+    }
+
+    wls_class = class_create(THIS_MODULE, wls_driver_name);
+
+    wls_dev_loc =  wls_dev[0];
+    wls_dev_loc->dev_no = dev_no;
+
+    cdev_init(&wls_dev_loc->cdev, &wls_fops);
+    wls_dev_loc->cdev.owner = THIS_MODULE;
+    wls_dev_loc->cdev.ops = &wls_fops;
+    res = cdev_add(&wls_dev_loc->cdev, dev_no, wlsMaxClients);
+
+    if (res) {
+        WLS_ERROR("failed add char dev: %d", res);
+        res = -1;
+        goto err2;
+    }
+
+    if (IS_ERR((void *)wls_class)) {
+        WLS_ERROR("failed create class");
+        res = -EIO;
+        goto err1;
+    }
+
+    for (dev_cnt = 0; dev_cnt < wlsMaxClients; dev_cnt++){
+        wls_dev_loc  = wls_dev[dev_cnt];
+        if (wls_dev_loc == NULL ) {
+            WLS_ERROR("wls_dev_loc is NULL");
+            goto err2;
+        }
+
+        if(wlsMaxClients > 1){
+            snprintf(wls_dev_device_name, 10, WLS_DEV_DEVICE_FORMAT, dev_cnt);
+        } else {
+            snprintf(wls_dev_device_name, 10, "%s", MODNAME);
+        }
+
+        wls_dev_loc->dev_no = MKDEV(MAJOR(dev_no), dev_cnt);
+        wls_dev_loc->device = device_create(wls_class, NULL, wls_dev_loc->dev_no, NULL, wls_dev_device_name);
+
+        if (IS_ERR((void *)wls_dev_loc->device)) {
+            WLS_ERROR("failed create / device");
+            res = -2;
+            goto err2;
+        }
+
+        dev_info(wls_dev_loc->device, "Device: %s\n", wls_dev_device_name);
+        mutex_init(&wls_dev_loc->lock);
+
+        wls_dev_loc->pWlsDrvCtx = wls_get_ctx(dev_cnt);
+
+        if (wls_dev_loc->pWlsDrvCtx ==  NULL) {
+            WLS_ERROR("failed wls_get_ctx(%d)", dev_cnt);
+            res = -3;
+            goto err2;
+        }
+
+        //return res;
+//        dev_no++;
+        continue;
+    }
+    WLS_PRINT("init %d /dev/wlsX communication devices [0-%d]\n", dev_cnt, dev_cnt-1);
+    return res;
+
+    err2:
+         for (dev_cnt = 0; dev_cnt < wlsMaxClients; dev_cnt++){
+            wls_dev_loc  = wls_dev[dev_cnt];
+            if(wls_dev_loc){
+                device_destroy(wls_class, wls_dev_loc->dev_no);
+                cdev_del(&wls_dev_loc->cdev);
+            }
+         }
+        class_destroy(wls_class);
+    err1:
+        unregister_chrdev_region(wls_dev[0]->dev_no, wlsMaxClients);
+    err0:
+        for (dev_cnt = 0; dev_cnt < wlsMaxClients; dev_cnt++){
+            if(wls_dev[dev_cnt]){
+                kfree(wls_dev[dev_cnt]);
+                wls_dev[dev_cnt] = NULL;
+            }
+        }
+
+        WLS_ERROR("init failed");
+        return -1;
+}
+
+static void __exit wls_exit(void)
+{
+    struct wls_dev_t* wls_dev_loc = NULL;
+    int dev_cnt = 0;
+
+    if (wls_dev[0]) {
+        for (dev_cnt = 0; dev_cnt < wlsMaxClients; dev_cnt++){
+            wls_dev_loc  = wls_dev[dev_cnt];
+            device_destroy(wls_class, wls_dev_loc->dev_no);
+        }
+        wls_dev_loc =  wls_dev[0];
+
+        cdev_del(&wls_dev_loc->cdev);
+        class_destroy(wls_class);
+
+        unregister_chrdev_region(wls_dev[0]->dev_no, wlsMaxClients);
+
+        for (dev_cnt = 0; dev_cnt < wlsMaxClients; dev_cnt++){
+            if(wls_dev[dev_cnt]){
+                kfree(wls_dev[dev_cnt]);
+                wls_dev[dev_cnt] = NULL;
+            }
+        }
+    }
+
+    WLS_PRINT("Intel(R) Wireless Subsystem Communication interface - %s was removed\n", wls_driver_version);
+}
+
+MODULE_DESCRIPTION("Wirelsess Sybsytem Communication interface");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("WLS_DRV_VERSION_FORMAT");
+
+module_init(wls_init);
+module_exit(wls_exit);
diff --git a/wls_lib/wls_drv.h b/wls_lib/wls_drv.h
new file mode 100644 (file)
index 0000000..24af067
--- /dev/null
@@ -0,0 +1,44 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef __WLS_DRV_H__
+#define __WLS_DRV_H__
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include "ttypes.h"
+
+struct wls_dev_t {
+    struct mutex lock;
+    dev_t dev_no;
+    struct class * class;
+    struct device * device;
+    struct cdev cdev;
+    wait_queue_head_t queue;
+    atomic_t qwake;
+    struct task_struct * thread;
+    wls_drv_ctx_t* pWlsDrvCtx;
+};
+
+#endif /* __WLS_DRC_H__*/
+
diff --git a/wls_lib/wls_lib.c b/wls_lib/wls_lib.c
new file mode 100644 (file)
index 0000000..83c82ff
--- /dev/null
@@ -0,0 +1,836 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include "ttypes.h"
+#include "wls_lib.h"
+#include "wls.h"
+#include "syslib.h"
+
+#define WLS_MAP_SHM 1
+
+#define WLS_PHY_SHM_FILE_NAME "/tmp/phyappshm"
+
+#define HUGE_PAGE_FILE_NAME "/mnt/huge/page"
+
+#define DIV_ROUND_OFFSET(X,Y) ( X/Y + ((X%Y)?1:0) )
+
+#define WLS_LIB_USER_SPACE_CTX_SIZE DMA_MAP_MAX_BLOCK_SIZE
+
+#define PLIB_ERR(x, args...)   printf("wls_lib: "x, ## args);
+#define PLIB_INFO(x, args...)  printf("wls_lib: "x, ## args);
+
+#ifdef _DEBUG_
+#define PLIB_DEBUG(x, args...)  printf("wls_lib debug: "x, ## args);
+#else
+#define PLIB_DEBUG(x, args...)  do { } while(0)
+#endif
+
+#ifdef __x86_64__
+#define WLS_LIB_MMAP mmap
+#else
+#define WLS_LIB_MMAP mmap64
+#endif
+
+extern int gethugepagesizes(long pagesizes[], int n_elem);
+extern int hugetlbfs_unlinked_fd(void);
+
+
+static pthread_mutex_t wls_put_lock;
+static pthread_mutex_t wls_get_lock;
+
+static int           wls_dev_fd =  0;
+static wls_us_ctx_t* wls_us_ctx =  NULL;
+
+static uint64_t wls_kernel_va_to_user_va(void *pWls_us, uint64_t ptr);
+
+int ipc_file = 0;
+
+static int wls_VirtToPhys(void* virtAddr, uint64_t* physAddr)
+{
+    int          mapFd;
+    uint64_t     page;
+    unsigned int pageSize;
+    unsigned long virtualPageNumber;
+
+    mapFd = open ("/proc/self/pagemap" , O_RDONLY );
+    if (mapFd < 0 )
+    {
+        PLIB_ERR("Could't open pagemap file\n");
+        return -1;
+    }
+
+    /*get standard page size*/
+    pageSize = getpagesize();
+
+    virtualPageNumber = (unsigned long) virtAddr / pageSize ;
+
+    lseek(mapFd , virtualPageNumber * sizeof(uint64_t) , SEEK_SET );
+
+    if(read(mapFd ,&page , sizeof(uint64_t)) < 0 )
+    {
+        close(mapFd);
+        PLIB_ERR("Could't read pagemap file\n");
+        return -1;
+    }
+
+    *physAddr = (( page & 0x007fffffffffffffULL ) * pageSize );
+
+    close(mapFd);
+
+    return 0;
+}
+
+static void wls_mutex_destroy(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_destroy(pMutex);
+}
+
+static void wls_mutex_init(pthread_mutex_t* pMutex)
+{
+   pthread_mutexattr_t prior;
+   pthread_mutexattr_init(&prior);
+   pthread_mutexattr_setprotocol(&prior, PTHREAD_PRIO_INHERIT);
+   pthread_mutex_init(pMutex, &prior);
+   pthread_mutexattr_destroy(&prior);
+}
+
+static void wls_mutex_lock(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_lock(pMutex);
+}
+
+static void wls_mutex_unlock(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_unlock(pMutex);
+}
+
+static uint64_t wls_kernel_va_to_user_va(void *pWls_us, uint64_t ptr)
+{
+    unsigned long ret = 0;
+    wls_us_ctx_t* pUs = (wls_us_ctx_t*)pWls_us;
+
+    uint64_t kva = (uint64_t) pUs->wls_us_kernel_va;
+    uint64_t uva = (uint64_t) pUs->wls_us_user_space_va;
+
+    ret = (uva + (ptr - kva));
+
+    PLIB_DEBUG("kva %lx to uva %lx [offset %d]\n",kva, ret, (kva - ret));
+    return ret;
+}
+
+static uint64_t wls_kernel_va_to_user_va_dest(void *pWls_us, uint64_t ptr)
+{
+    unsigned long ret = 0;
+    wls_us_ctx_t* pUs = (wls_us_ctx_t*)pWls_us;
+
+    uint64_t kva = (uint64_t) pUs->dst_kernel_va;
+    uint64_t uva = (uint64_t) pUs->dst_user_va;
+
+    ret = (uva + (ptr - kva));
+
+    PLIB_DEBUG("kva %lx to uva %lx [offset %d]\n",kva, ret, (kva - ret));
+    return ret;
+}
+
+
+void* WLS_Open(const char *ifacename, unsigned int mode, unsigned long long nWlsMemorySize)
+{
+    wls_us_ctx_t*  pWls_us = NULL;
+    unsigned int   ret = 0;
+    wls_open_req_t params;
+    int i, len;
+    char temp[WLS_DEV_SHM_NAME_LEN];
+
+#ifdef __x86_64__
+    params.ctx  = 64L;
+#else
+    params.ctx  = 32L;
+#endif
+
+    params.ctx_pa = 0;
+    params.size   = WLS_LIB_USER_SPACE_CTX_SIZE;
+
+    if(sizeof(wls_us_ctx_t) >= 64*1024){
+        PLIB_ERR("WLS_Open %ld \n", sizeof(wls_us_ctx_t));
+        return NULL;
+    }
+
+    if (!wls_us_ctx) {
+        PLIB_INFO("Open %s 0x%08lx\n", ifacename, WLS_IOC_OPEN);
+
+        if ((wls_dev_fd = open(ifacename, O_RDWR | O_SYNC)) < 0){
+            PLIB_ERR("Open filed [%d]\n", wls_dev_fd);
+            return NULL;
+        }
+        /* allocate block in shared space */
+        if((ret = ioctl(wls_dev_fd, WLS_IOC_OPEN, &params)) < 0) {
+            PLIB_ERR("Open filed [%d]\n", ret);
+            return NULL;
+        }
+
+        PLIB_DEBUG("params: kernel va 0x%016llx pa 0x%016llx size %ld\n",
+           params.ctx, params.ctx_pa, params.size);
+
+        if (params.ctx_pa) {
+            /* remap to user space the same block */
+            pWls_us = (wls_us_ctx_t*) WLS_LIB_MMAP(NULL,
+                                      params.size,
+                                      PROT_READ|PROT_WRITE ,
+                                      MAP_SHARED,
+                                      wls_dev_fd,
+                                      params.ctx_pa);
+
+            if( pWls_us == MAP_FAILED ){
+                PLIB_ERR("mmap has failed (%d:%s) 0x%016lx [size %d]\n", errno, strerror(errno),params.ctx_pa, params.size);
+                return NULL;
+            }
+
+            PLIB_DEBUG("Local: pWls_us 0x%016p\n", pWls_us);
+
+            PLIB_DEBUG("size wls_us_ctx_t %d\n", sizeof(wls_us_ctx_t));
+            PLIB_DEBUG("    ul free  : off 0x%016lx\n",((unsigned long) &pWls_us->ul_free_block_pq -(unsigned long)pWls_us));
+            PLIB_DEBUG("    get_queue: off 0x%016lx\n",((unsigned long) &pWls_us->get_queue -(unsigned long)pWls_us));
+            PLIB_DEBUG("    put_queue: off 0x%016lx\n",((unsigned long) &pWls_us->put_queue -(unsigned long)pWls_us));
+
+            //memset(pWls_us, 0, params.size);
+
+            pWls_us->padding_wls_us_user_space_va = 0LL;
+
+            pWls_us->wls_us_user_space_va = pWls_us;
+
+            pWls_us->wls_us_kernel_va = (uint64_t) params.ctx;
+            pWls_us->wls_us_pa        = (uint64_t) params.ctx_pa;
+            pWls_us->wls_us_ctx_size  =  params.size;
+
+            PLIB_INFO("User Space Lib Context: us va 0x%016lx kernel va 0x%016lx pa 0x%016lx size %d \n",
+                (uintptr_t)pWls_us->wls_us_user_space_va,
+                pWls_us->wls_us_kernel_va,
+                pWls_us->wls_us_pa,
+                pWls_us->wls_us_ctx_size);
+
+            wls_mutex_init(&wls_put_lock);
+            wls_mutex_init(&wls_get_lock);
+
+            pWls_us->mode = mode;
+            PLIB_INFO("\nMode %d\n", pWls_us->mode);
+
+            PLIB_INFO("\nWLS device %s [%d]\n", ifacename, (int)strlen(ifacename));
+            strncpy(temp, ifacename, WLS_DEV_SHM_NAME_LEN - 1);
+            len = strlen(ifacename);
+            if (len < WLS_DEV_SHM_NAME_LEN - 1)
+                strncpy(pWls_us->wls_dev_name, temp, len);
+            else
+                strncpy(pWls_us->wls_dev_name, temp, WLS_DEV_SHM_NAME_LEN - 1);
+            for(i = 0; i < MIN(strlen(pWls_us->wls_dev_name),WLS_DEV_SHM_NAME_LEN); i++)
+                if(pWls_us->wls_dev_name[i] != '/')
+                    pWls_us->wls_shm_name[i] = pWls_us->wls_dev_name[i];
+                else
+                    pWls_us->wls_shm_name[i] = '_';
+
+            wls_us_ctx = pWls_us;
+        }
+        else {
+            PLIB_ERR("Open filed: incorrect allocation \n");
+            return NULL;
+        }
+    }
+
+    return wls_us_ctx;
+}
+
+int WLS_Ready(void* h)
+{
+    int ret = 0;
+    wls_event_req_t params;
+
+    if (!wls_us_ctx || !wls_dev_fd){
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    params.event_to_wls =  WLS_EVENT_IA_READY;
+    params.event_param = 0;
+
+    /* free block in shared space */
+    if((ret = ioctl(wls_dev_fd, WLS_IOC_EVENT, &params)) < 0) {
+        PLIB_ERR("Event filed [%d]\n", ret);
+        return ret;
+    }
+
+    return 0;
+}
+
+int WLS_Close(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*)h;
+    wls_close_req_t params;
+    int ret = 0;
+
+    if (!wls_us_ctx || !wls_dev_fd){
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    if ((unsigned long)pWls_us !=  (unsigned long )wls_us_ctx){
+        PLIB_ERR("Incorret handle %lx [expected %lx]\n", (unsigned long)pWls_us, (unsigned long )wls_us_ctx);
+        return -1;
+    }
+
+    params.ctx    = pWls_us->wls_us_kernel_va;
+    params.ctx_pa = pWls_us->wls_us_pa;
+    params.size   = pWls_us->wls_us_ctx_size;
+
+    /* free block in shared space */
+    if((ret = ioctl(wls_dev_fd, WLS_IOC_CLOSE, &params)) < 0) {
+        PLIB_ERR("Close filed [%d]\n", ret);
+        return 0;
+    }
+
+    /* unmap to user space */
+    munmap(pWls_us, pWls_us->wls_us_ctx_size);
+
+    wls_mutex_destroy(&wls_put_lock);
+    wls_mutex_destroy(&wls_get_lock);
+
+    close(wls_dev_fd);
+
+    wls_us_ctx = NULL;
+    wls_dev_fd = 0;
+
+    return 0;
+}
+
+
+void* WLS_Alloc(void* h, unsigned int size)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+
+    long          pageSize[1];
+    long          hugePageSize;
+    long          nHugePage;
+
+    hugepage_tabl_t*  pHugePageTlb = &pWls_us->hugepageTbl[0];
+
+    void*  pvirtAddr = NULL;
+    int    count;
+    int    fd;
+
+    char shm_file_name[256];
+
+    fd = hugetlbfs_unlinked_fd();
+
+    if (fd < 0)
+        PLIB_ERR("Unable to open temp file in hugetlbfs (%s)", strerror(errno));
+
+    gethugepagesizes(pageSize,1);
+    hugePageSize = pageSize[0];
+
+    PLIB_INFO("hugePageSize on the system is %ld\n", hugePageSize);
+
+    /* calculate total number of hugepages */
+    nHugePage =  DIV_ROUND_OFFSET(size, hugePageSize);
+
+    if (nHugePage >= MAX_N_HUGE_PAGES){
+        PLIB_INFO("not enough hugepages: need %ld  system has %d\n", nHugePage,  MAX_N_HUGE_PAGES);
+        return NULL;
+    }
+
+    if(pHugePageTlb == NULL )
+    {
+        PLIB_INFO("Table memory allocation failed\n");
+        return NULL;
+    }
+
+#if WLS_MAP_SHM
+{
+    snprintf(shm_file_name, WLS_DEV_SHM_NAME_LEN, "%s_%s", WLS_PHY_SHM_FILE_NAME, pWls_us->wls_shm_name);
+    PLIB_INFO("shm open %s\n", shm_file_name);
+    ipc_file = open(shm_file_name, O_CREAT); // | O_EXCL  maybe sometimes in future.. ;-)
+    if(ipc_file == -1){
+        PLIB_ERR("open  failed (%s)\n", strerror(errno) );
+        return NULL;
+    }
+
+    key_t  key = ftok(shm_file_name, '4');
+    int shm_handle = shmget(key, size, SHM_HUGETLB|SHM_R|SHM_W);
+    if(shm_handle == -1){
+         PLIB_INFO("Create shared memory\n");
+         shm_handle = shmget(key, size, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
+    }
+    else
+        PLIB_INFO("Attach to shared memory\n");
+
+    if(shm_handle == -1){
+        PLIB_ERR("shmget has failed (%s) [size %ld]\n", strerror(errno), nHugePage * hugePageSize);
+        return NULL;
+    }
+
+    pvirtAddr = shmat(shm_handle, 0, /*SHM_RND*/0);
+}
+#else
+    /* Allocate required number of pages */
+    pvirtAddr = mmap(0,(nHugePage * hugePageSize), (PROT_READ|PROT_WRITE), MAP_SHARED, fd,0);
+#endif
+    if(pvirtAddr == MAP_FAILED )
+    {
+        PLIB_ERR("mmap has failed (%s) [size %ld]\n", strerror(errno), nHugePage * hugePageSize);
+        return NULL;
+    }
+
+    PLIB_INFO("pvirtAddr  0x%016lx\n", (unsigned long)pvirtAddr);
+
+    for(count = 0 ; count < nHugePage ; count++ )
+    {
+        /*Incremented virtual address to next hugepage to create table*/
+        pHugePageTlb[count].pageVa =  ((unsigned char*)pvirtAddr + \
+                                                ( count * hugePageSize ));
+        /*Creating dummy page fault in process for each page
+                                                inorder to get pagemap*/
+        *(unsigned char*)pHugePageTlb[count].pageVa = 1;
+
+        if(wls_VirtToPhys((uint64_t*) pHugePageTlb[count].pageVa,
+                    &pHugePageTlb[count].pagePa ) == -1)
+        {
+            munmap(pvirtAddr, (nHugePage * hugePageSize));
+            PLIB_ERR("Virtual to physical conversion failed\n");
+            return NULL;
+        }
+
+        //PLIB_INFO("id %d va 0x%016p pa 0x%016llx [%ld]\n", count, (uintptr_t)pHugePageTlb[count].pageVa, (uint64_t) pHugePageTlb[count].pagePa, hugePageSize);
+    }
+
+    PLIB_INFO("WLS_Alloc: 0x%016lx [%d]\n", (unsigned long)pvirtAddr, size);
+
+    close(fd);
+
+    pWls_us->HugePageSize = (uint32_t)hugePageSize;
+    pWls_us->alloc_buffer = pvirtAddr;
+    pWls_us->alloc_size   = (uint32_t)(nHugePage * hugePageSize);
+
+    if (pWls_us->mode == WLS_MASTER_CLIENT){
+        wls_us_ctx_t* pWls_usRem = NULL;
+        PLIB_INFO("Connecting to remote peer ...\n");
+        while (pWls_us->dst_pa == 0) // wait for slave
+                       ;
+
+        /* remap to user space the same block */
+        pWls_usRem = (wls_us_ctx_t*) WLS_LIB_MMAP(NULL,
+                                  sizeof(wls_us_ctx_t),
+                                  PROT_READ|PROT_WRITE ,
+                                  MAP_SHARED,
+                                  wls_dev_fd,
+                                  pWls_us->dst_pa);
+
+        if( pWls_us == MAP_FAILED ){
+            PLIB_ERR("mmap has failed (%d:%s) 0x%016lx \n", errno, strerror(errno),pWls_us->dst_pa);
+            return NULL;
+        }
+
+        PLIB_INFO("Remote: pWls_us 0x%p\n", pWls_usRem);
+
+        PLIB_INFO("size wls_us_ctx_t %ld\n", sizeof(wls_us_ctx_t));
+        PLIB_INFO("    ul free  : off 0x%016lx\n",((unsigned long) &pWls_usRem->ul_free_block_pq -(unsigned long)pWls_usRem));
+        PLIB_INFO("    get_queue: off 0x%016lx\n",((unsigned long) &pWls_usRem->get_queue -(unsigned long)pWls_usRem));
+        PLIB_INFO("    put_queue: off 0x%016lx\n",((unsigned long) &pWls_usRem->put_queue -(unsigned long)pWls_usRem));
+
+        pWls_us->dst_user_va = (uint64_t) pWls_usRem  ;
+    }
+
+
+    return pvirtAddr;
+}
+
+int WLS_Free(void* h, PVOID pMsg)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+
+    if ((unsigned long)pMsg != (unsigned long)pWls_us->alloc_buffer) {
+        PLIB_ERR("incorrect pMsg %lx [expected %lx]\n", (unsigned long)pMsg ,(unsigned long)pWls_us->alloc_buffer);
+        return -1;
+    }
+
+    if (pWls_us->mode == WLS_MASTER_CLIENT){
+        if(pWls_us->dst_user_va){
+            munmap((void*)pWls_us->dst_user_va, sizeof(wls_us_ctx_t));
+            pWls_us->dst_user_va = 0;
+        }
+    }
+
+    PLIB_DEBUG("WLS_Free 0x%016lx", (unsigned long)pMsg);
+#if WLS_MAP_SHM
+    shmdt(pMsg);
+    close (ipc_file);
+#else
+    munmap(pMsg, pWls_us->alloc_size);
+#endif
+
+
+
+    return 0;
+}
+
+int WLS_Put(void* h, unsigned long long  pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+    int ret = 0;
+
+    if ((unsigned long)h != (unsigned long)wls_us_ctx) {
+        PLIB_ERR("Incorrect user space context %lx [%lx]\n", (unsigned long)h, (unsigned long)wls_us_ctx);
+        return -1;
+    }
+
+    if(!WLS_IS_ONE_HUGE_PAGE(pMsg, MsgSize, WLS_HUGE_DEF_PAGE_SIZE)) {
+        PLIB_ERR("WLS_Put input error: buffer is crossing 2MB page boundary 0x%016llx size %ld\n", pMsg, (unsigned long)MsgSize);
+    }
+
+    wls_mutex_lock(&wls_put_lock);
+
+    if ((WLS_FLAGS_MASK & Flags)){ // multi block transaction
+        if (Flags & WLS_TF_SYN){
+            PLIB_DEBUG("WLS_SG_FIRST\n");
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags,  wls_kernel_va_to_user_va, (void*)pWls_us))
+            {
+               PLIB_DEBUG("WLS_Get %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID);
+            }
+        } else if ((Flags & WLS_TF_SCATTER_GATHER) && !(Flags & WLS_TF_SYN) && !(Flags & WLS_TF_FIN)){
+            PLIB_DEBUG("WLS_SG_NEXT\n");
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags,  wls_kernel_va_to_user_va, (void*)pWls_us))
+            {
+               PLIB_DEBUG("WLS_Put %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID);
+            }
+        } else if (Flags & WLS_TF_FIN) {
+            wls_put_req_t params;
+            PLIB_DEBUG("WLS_SG_LAST\n");
+            params.wls_us_kernel_va = pWls_us->wls_us_kernel_va;
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags,  wls_kernel_va_to_user_va, (void*)pWls_us))
+            {
+               PLIB_DEBUG("WLS_Put %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID);
+            }
+
+            PLIB_DEBUG("List: call WLS_IOC_PUT\n");
+            if((ret = ioctl(wls_dev_fd, WLS_IOC_PUT, &params)) < 0) {
+                PLIB_ERR("Put filed [%d]\n", ret);
+                wls_mutex_unlock(&wls_put_lock);
+                return -1;
+            }
+        } else
+            PLIB_ERR("unsaported flags %x\n", WLS_FLAGS_MASK & Flags);
+    } else {  // one block transaction
+        wls_put_req_t params;
+        params.wls_us_kernel_va = pWls_us->wls_us_kernel_va;
+        if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags,  wls_kernel_va_to_user_va, (void*)pWls_us))
+        {
+           PLIB_DEBUG("WLS_Put %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID);
+        }
+
+        PLIB_DEBUG("One block: call WLS_IOC_PUT\n");
+        if((ret = ioctl(wls_dev_fd, WLS_IOC_PUT, &params)) < 0) {
+            PLIB_ERR("Put filed [%d]\n", ret);
+            wls_mutex_unlock(&wls_put_lock);
+            return -1;
+        }
+    }
+    wls_mutex_unlock(&wls_put_lock);
+
+    return 0;
+}
+
+int WLS_Check(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+
+    if ((unsigned long)h != (unsigned long)wls_us_ctx) {
+        PLIB_ERR("Incorrect user space context %lx [%lx]\n", (unsigned long)h, (unsigned long)wls_us_ctx);
+        return 0;
+    }
+
+    PLIB_DEBUG("offset get_queue %lx\n",(U64)&pWls_us->get_queue - (U64)pWls_us);
+
+    return WLS_GetNumItemsInTheQueue(&pWls_us->get_queue);
+}
+
+
+unsigned long long WLS_Get(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+    WLS_MSG_HANDLE hMsg;
+    uint64_t pMsg = NULL;
+
+    if ((unsigned long)h != (unsigned long)wls_us_ctx) {
+        PLIB_ERR("Incorrect user space context %lx [%lx]\n", (unsigned long)h, (unsigned long)wls_us_ctx);
+        return 0;
+    }
+
+    PLIB_DEBUG("offset get_queue %lx\n",(U64)&pWls_us->get_queue - (U64)pWls_us);
+    wls_mutex_lock(&wls_get_lock);
+
+    if (WLS_MsgDequeue(&pWls_us->get_queue, &hMsg, wls_kernel_va_to_user_va, (void*)pWls_us))
+    {
+       PLIB_DEBUG("WLS_Get %lx %d type %d\n",(U64) hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID);
+       pMsg         = hMsg.pIaPaMsg;
+       *MsgSize     = hMsg.MsgSize;
+       *MsgTypeID   = hMsg.TypeID;
+       *Flags       = hMsg.flags;
+    }
+
+    wls_mutex_unlock(&wls_get_lock);
+
+    return pMsg;
+}
+
+int   WLS_WakeUp(void* h)
+{
+    int ret;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+    wls_wake_up_req_t params;
+
+    if (!wls_us_ctx || !wls_dev_fd){
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    params.ctx              = (uint64_t)pWls_us;
+    params.wls_us_kernel_va = (uint64_t)pWls_us->wls_us_kernel_va;
+
+    PLIB_DEBUG("WLS_WakeUp\n");
+
+    if((ret = ioctl(wls_dev_fd, WLS_IOC_WAKE_UP, &params)) < 0) {
+        PLIB_ERR("Wake Up filed [%d]\n", ret);
+        return ret;
+    }
+
+    return 0;
+}
+
+int   WLS_Wait(void* h)
+{
+    int ret;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+    wls_wait_req_t params;
+
+    if (!wls_us_ctx || !wls_dev_fd){
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    params.ctx              = (uint64_t)pWls_us;
+    params.wls_us_kernel_va = (uint64_t)pWls_us->wls_us_kernel_va;
+    params.action           =  0;
+    params.nMsg             =  0;
+
+    PLIB_DEBUG("WLS_Wait\n");
+
+    if((ret = ioctl(wls_dev_fd, WLS_IOC_WAIT, &params)) < 0) {
+        PLIB_ERR("Wait filed [%d]\n", ret);
+        return ret;
+    }
+
+    return params.nMsg;
+}
+
+unsigned long long  WLS_WGet(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    uint64_t pRxMsg = WLS_Get(h, MsgSize, MsgTypeID, Flags);
+
+    if (pRxMsg)
+        return pRxMsg;
+
+    WLS_Wait(h);
+    return WLS_Get(h, MsgSize, MsgTypeID, Flags);
+}
+
+unsigned long long  WLS_VA2PA(void* h, PVOID pMsg)
+{
+    uint64_t      ret = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+
+    unsigned long    alloc_base;
+    hugepage_tabl_t* pHugePageTlb;
+    uint64_t    hugePageBase;
+    uint64_t    hugePageOffet;
+    unsigned int     count = 0;
+
+    uint64_t    HugePageMask = ((unsigned long)pWls_us->HugePageSize - 1);
+
+    if(pWls_us->alloc_buffer == NULL){
+        PLIB_ERR("WLS_VA2PA: nothing was allocated [%ld]\n", ret);
+        return  (uint64_t)ret;
+    }
+
+    alloc_base     = (unsigned long)pWls_us->alloc_buffer;
+
+    pHugePageTlb   = &pWls_us->hugepageTbl[0];
+
+    hugePageBase   = (uint64_t)pMsg & ~HugePageMask;
+    hugePageOffet  = (uint64_t)pMsg & HugePageMask;
+
+    count          = (hugePageBase - alloc_base) / pWls_us->HugePageSize;
+
+    PLIB_DEBUG("WLS_VA2PA %lx base %llx off %llx  count %d\n", (unsigned long)pMsg,
+        (uint64_t)hugePageBase, (uint64_t)hugePageOffet, count);
+
+    ret = pHugePageTlb[count].pagePa + hugePageOffet;
+
+    return (uint64_t) ret;
+}
+
+void* WLS_PA2VA(void* h, unsigned long long  pMsg)
+{
+    unsigned long    ret = NULL;
+    wls_us_ctx_t*    pWls_us = (wls_us_ctx_t* )h;
+
+    hugepage_tabl_t* pHugePageTlb;
+    uint64_t         hugePageBase;
+    uint64_t         hugePageOffet;
+    unsigned int     count;
+    int              i;
+    uint64_t         HugePageMask = ((uint64_t)pWls_us->HugePageSize - 1);
+
+    if(pWls_us->alloc_buffer == NULL){
+        PLIB_ERR("WLS_PA2VA: nothing was allocated [%ld]\n", ret);
+        return  (void*)ret;
+    }
+
+    pHugePageTlb   = &pWls_us->hugepageTbl[0];
+
+    hugePageBase   = (uint64_t)pMsg & ~HugePageMask;
+    hugePageOffet  = (uint64_t)pMsg &  HugePageMask;
+
+    count          = pWls_us->alloc_size / pWls_us->HugePageSize;
+
+    PLIB_DEBUG("WLS_PA2VA %llx base %llx off %llx  count %d\n", (uint64_t)pMsg,
+        (uint64_t)hugePageBase, (uint64_t)hugePageOffet, count);
+
+    for (i = 0; i < count; i++) {
+        if (pHugePageTlb[i].pagePa == hugePageBase)
+        {
+            ret = (unsigned long)pHugePageTlb[i].pageVa;
+            ret += hugePageOffet;
+            return  (void*)ret;
+        }
+    }
+
+    return (void*) (ret);
+}
+
+int WLS_EnqueueBlock(void* h, unsigned long long pMsg)
+{
+    int ret = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+
+    if (!wls_us_ctx || !wls_dev_fd){
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    if(pWls_us->mode == WLS_SLAVE_CLIENT){
+        PLIB_ERR("Slave doesn't support memory allocation\n");
+        return -1;
+    }
+
+    if(pMsg == 0){
+        PLIB_ERR("WLS_EnqueueBlock: Null\n");
+        return -1;
+    }
+
+    if(pWls_us->dst_kernel_va){
+        if (pWls_us->dst_user_va)
+        {
+            wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t* )pWls_us->dst_user_va;
+            ret = SFL_WlsEnqueue(&pDstWls_us->ul_free_block_pq, pMsg, wls_kernel_va_to_user_va_dest, pWls_us);
+            if(ret == 1){
+                unsigned long* ptr = (unsigned long*)WLS_PA2VA(pWls_us, pMsg);
+                if(ptr){
+                    *ptr = 0xFFFFFFFFFFFFFFFF;
+                }
+            }
+        }
+        else
+            ret = -1;
+    }
+    else
+        ret = -1;
+
+    PLIB_DEBUG("SFL_WlsEnqueue %d\n", ret);
+    return ret;
+}
+
+unsigned long long WLS_DequeueBlock(void* h)
+{
+    unsigned long long retval = NULL;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+
+    if(pWls_us->mode == WLS_SLAVE_CLIENT){
+        // local
+        retval = SFL_WlsDequeue(&pWls_us->ul_free_block_pq, wls_kernel_va_to_user_va, h );
+    } else if(pWls_us->dst_kernel_va) {
+        // remote
+        if (pWls_us->dst_user_va)
+        {
+            wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t* )pWls_us->dst_user_va;
+            retval = SFL_WlsDequeue(&pDstWls_us->ul_free_block_pq, wls_kernel_va_to_user_va_dest, pWls_us);
+            if(retval){
+                unsigned long* ptr = (unsigned long*)WLS_PA2VA(pWls_us, retval);
+                if(ptr){
+                    if(*ptr != 0xFFFFFFFFFFFFFFFF){
+                        PLIB_ERR("WLS_EnqueueBlock: incorrect content pa: 0x%016lx: 0x%016lx\n", (unsigned long)retval, *ptr);
+                    }
+                }
+            }
+        }
+    }
+
+    return retval;
+}
+
+int WLS_NumBlocks(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h;
+    int n = 0;
+
+    if(pWls_us->mode == WLS_SLAVE_CLIENT){
+        // local
+        n = SFL_GetNumItemsInTheQueue(&pWls_us->ul_free_block_pq);
+    } else if(pWls_us->dst_kernel_va) {
+        // remote
+        if (pWls_us->dst_user_va)
+        {
+            wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t* )pWls_us->dst_user_va;
+            n = SFL_GetNumItemsInTheQueue(&pDstWls_us->ul_free_block_pq);
+        }
+    }
+
+    return n;
+}
+
+
diff --git a/wls_lib/wls_lib.h b/wls_lib/wls_lib.h
new file mode 100644 (file)
index 0000000..e38ea43
--- /dev/null
@@ -0,0 +1,482 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#ifndef _WLS_LIB_H_
+#define _WLS_LIB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** WLS driver client operates as slave in terms of management of shared memory */
+#define WLS_SLAVE_CLIENT   0
+/** WLS driver client operates as master in terms of management of shared memory */
+#define WLS_MASTER_CLIENT  1
+/** WLS Open Dual Options */
+#define WLS_SEC_NA     0
+#define WLS_SEC_MASTER 1
+/** WLS Open Dual enabled */
+#define WLS_SINGLE_MODE 0
+#define WLS_DUAL_MODE   1
+
+
+/* definitions PUT/GET Flags */
+#define WLS_TF_SCATTER_GATHER  (1 << 15)
+#define WLS_TF_URLLC           (1 << 10)
+#define WLS_TF_SYN             (1 << 9)
+#define WLS_TF_FIN             (1 << 8)
+#define WLS_FLAGS_MASK         (0xFF00)
+
+/** First block in Scatter/Gather sequence of blocks */
+#define WLS_SG_FIRST               (WLS_TF_SCATTER_GATHER | WLS_TF_SYN)
+/** Next block in Scatter/Gather sequence of blocks */
+#define WLS_SG_NEXT                (WLS_TF_SCATTER_GATHER)
+/** Last block in Scatter/Gather sequence of blocks */
+#define WLS_SG_LAST                (WLS_TF_SCATTER_GATHER | WLS_TF_FIN)
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   ifacename - pointer to string with device driver name (/dev/wls)
+ *  @param[in]   modef     - mode of operation (Master or Slave)
+ *
+ *  @return  pointer to WLS handle
+ *
+ *  @description
+ *  Function opens the WLS interface and registers as instance in the kernel space driver.
+ *  Control section of shared memory is mapped to application memory.
+ *  pointer (handle) of WLS interface is returned for future use by WLS functions
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void* WLS_Open(const char *ifacename, unsigned int mode, unsigned long long nWlsMemorySize);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   ifacename - pointer to string with device driver name (/dev/wls)
+ *  @param[in]   modef     - mode of operation (Master or Slave)
+ *
+ *  @return  pointer to second WLS handle while first WLS_handle is returned to the argument handle1 location
+ *
+ *  @description
+ *  Function opens the WLS interface and registers two instances in the kernel space driver.
+ *  Control section of shared memory is mapped to application memory.
+ *  pointer (handle) of WLS interface is returned for future use by WLS functions
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void* WLS_Open_Dual(const char *ifacename, unsigned int mode, unsigned long long nWlsMemorySize, void** handle1);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h - handle of WLS interface to close
+ *
+ *  @return  0 - in case of success
+ *
+ *  @description
+ *  Function closes the WLS interface and deregisters as instance in the kernel space driver.
+ *  Control section of shared memory is unmapped form user space application
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Close(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h - handle of second WLS interface within same app to close
+ *
+ *  @return  0 - in case of success
+ *
+ *  @description
+ *  Function closes a second WLS interface open from a same process and deregisters as instance in the kernel space driver.
+ *  Control section of shared memory is unmapped form user space application
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Close1(void* h);
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h - handle of WLS interface to check status
+ *
+ *  @return  1 - in case of success
+ *
+ *  @description
+ *  Function checks state of remote peer of WLS interface and returns 1 if remote peer is available
+ *  (one to one connection is established)
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Ready(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h - handle of second WLS interface within the same app to check status
+ *
+ *  @return  1 - in case of success
+ *
+ *  @description
+ *  Function checks state of remote peer of WLS interface and returns 1 if remote peer is available
+ *  (one to one connection is established)
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Ready1(void* h);
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h    - handle of WLS interface
+ *  @param[in]   size - size of memory block to allocate
+ *
+ *  @return  void*    - pointer to allocated memory block or NULL if no memory available
+ *
+ *  @description
+ *  Function allocates memory block for data exchange shared memory. Memory block is backed
+ *  by huge pages.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+void* WLS_Alloc(void* h, unsigned int size);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*  @param[in]   pMsg - pointer to WLS memory
+*
+*  @return  0 - if operation is successful
+*
+*  @description
+*  Function frees memory block for data exchange shared memory. Memory block is backed
+*  by huge pages
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Free(void* h, void* pMsg);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h    - handle of WLS interface
+ *  @param[in]   pMsg - pointer to memory block (physical address) with data to be transfered to remote peer.
+ *                      pointer should belong to WLS memory allocated via WLS_Alloc()
+ *  @param[in]   MsgSize - size of memory block to send (should be less than 2 MB)
+ *  @param[in]   MsgTypeID - application specific identifier of message type
+ *  @param[in]   Flags - Scatter/Gather flag if memory block has multiple chunks
+ *
+ *  @return  0 - if successful
+ *          -1 - if error
+ *
+ *  @description
+ *  Function puts memory block (or group of blocks) allocated from WLS memory into interface
+ *  for transfer to remote peer.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Put(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h    - handle of second WLS interface within same app
+ *  @param[in]   pMsg - pointer to memory block (physical address) with data to be transfered to remote peer.
+ *                      pointer should belong to WLS memory allocated via WLS_Alloc()
+ *  @param[in]   MsgSize - size of memory block to send (should be less than 2 MB)
+ *  @param[in]   MsgTypeID - application specific identifier of message type
+ *  @param[in]   Flags - Scatter/Gather flag if memory block has multiple chunks
+ *
+ *  @return  0 - if successful
+ *          -1 - if error
+ *
+ *  @description
+ *  Function puts memory block (or group of blocks) allocated from WLS memory into interface
+ *  for transfer to remote peer.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Put1(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h    - handle of WLS interface
+ *
+ *  @return  number of blocks available
+ *
+ *  @description
+ *  Function checks if there are memory blocks with data from remote peer and returns number of blocks
+ *  available for "get" operation
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Check(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+ *
+ *  @param[in]   h    - handle of second WLS interface within same app
+ *
+ *  @return  number of blocks available
+ *
+ *  @description
+ *  Function checks if there are memory blocks with data from remote peer and returns number of blocks
+ *  available for "get" operation
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Check1(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*  @param[in]   *MsgSize - pointer to set size of memory block
+*  @param[in]   *MsgTypeID - pointer to application specific identifier of message type
+*  @param[in]   *Flags - pointer to Scatter/Gather flag if memory block has multiple chunks
+*
+*  @return  pointer to memory block (physical address) with data received from remote peer
+*           NULL -  if error
+*
+*  @description
+*  Function gets memory block from interface received from remote peer. Function is non-blocking
+*  operation and returns NULL if no blocks available
+*
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long long WLS_Get(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of second WLS interface within same app
+*  @param[in]   *MsgSize - pointer to set size of memory block
+*  @param[in]   *MsgTypeID - pointer to application specific identifier of message type
+*  @param[in]   *Flags - pointer to Scatter/Gather flag if memory block has multiple chunks
+*
+*  @return  pointer to memory block (physical address) with data received from remote peer
+*           NULL -  if error
+*
+*  @description
+*  Function gets memory block from interface received from remote peer. Function is non-blocking
+*  operation and returns NULL if no blocks available
+*
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long long WLS_Get1(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*
+*  @return  number of blocks available for get
+*
+*  @description
+*  Function waits for new memory block from remote peer. Function is blocking call and returns number
+*  of blocks received.
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Wait(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle second of WLS interface within same app
+*
+*  @return  number of blocks available for get
+*
+*  @description
+*  Function waits for new memory block from remote peer. Function is blocking call and returns number
+*  of blocks received.
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_Wait1(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*
+*  @return  0 - if successful
+*
+*  @description
+*  Function performs "wakeup" notification to remote peer to unblock "wait" operations pending
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_WakeUp(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of second  WLS interface within same app
+*
+*  @return  0 - if successful
+*
+*  @description
+*  Function performs "wakeup" notification to remote peer to unblock "wait" operations pending
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_WakeUp1(void* h);
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*  @param[in]   *MsgSize - pointer to set size of memory block
+*  @param[in]   *MsgTypeID - pointer to application specific identifier of message type
+*  @param[in]   *Flags - pointer to Scatter/Gather flag if memory block has multiple chunks
+*
+*  @return  pointer to memory block (physical address) with data received from remote peer
+*           NULL -  if error
+*
+*  @description
+*  Function gets memory block from interface received from remote peer. Function is blocking
+*  operation and waits till next memory block from remote peer.
+*
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long long WLS_WGet(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of second WLS interface within the same app
+*  @param[in]   *MsgSize - pointer to set size of memory block
+*  @param[in]   *MsgTypeID - pointer to application specific identifier of message type
+*  @param[in]   *Flags - pointer to Scatter/Gather flag if memory block has multiple chunks
+*
+*  @return  pointer to memory block (physical address) with data received from remote peer
+*           NULL -  if error
+*
+*  @description
+*  Function gets memory block from interface received from remote peer. Function is blocking
+*  operation and waits till next memory block from remote peer.
+*
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long long WLS_WGet1(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*  @param[in]   pMsg - virtual address of WLS memory block.
+*
+*  @return  physical address of WLS memory block
+*           NULL - if error
+*
+*  @description
+*  Function converts virtual address (VA) to physical address (PA)
+*
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long long WLS_VA2PA(void* h, void* pMsg);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*  @param[in]   pMsg - physical address of WLS memory block.
+*
+*  @return  virtual address of WLS memory block
+*           NULL - if error
+*
+*  @description
+*  Function converts physical address (PA) to virtual address (VA)
+*
+**/
+//-------------------------------------------------------------------------------------------
+void* WLS_PA2VA(void* h, unsigned long long pMsg);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*  @param[in]   pMsg - physical address of WLS memory block.
+*
+*  @return  0 - if successful
+*          -1 - if error
+*
+*  @description
+*  Function is used by master to provide memory blocks to slave for next slave to master transfer
+*  of data.
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_EnqueueBlock(void* h, unsigned long long pMsg);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    -- handle of second WLS interface within the same app
+*  @param[in]   pMsg - physical address of WLS memory block.
+*
+*  @return  0 - if successful
+*          -1 - if error
+*
+*  @description
+*  Function is used by master to provide memory blocks to slave for next slave to master transfer
+*  of data.
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_EnqueueBlock1(void* h, unsigned long long pMsg);
+
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*
+*  @return  0   - pointer (physical address) of WLS memory block
+*          NULL - if error
+*
+*  @description
+*  Function is used by master and slave to get block from master to slave queue of available memory
+*  blocks.
+*
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long long WLS_DequeueBlock(void* h);
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup wls_mod
+*
+*  @param[in]   h    - handle of WLS interface
+*
+*  @return  number of blocks in slave to master queue
+*
+*  @description
+*  Function returns number of current available block provided by master for new transfer
+*  of data from slave.
+*
+**/
+//-------------------------------------------------------------------------------------------
+int WLS_NumBlocks(void* h);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_WLS_LIB_H_
diff --git a/wls_lib/wls_lib_dpdk.c b/wls_lib/wls_lib_dpdk.c
new file mode 100644 (file)
index 0000000..f05b12c
--- /dev/null
@@ -0,0 +1,1343 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_branch_prediction.h>
+
+#include "ttypes.h"
+#include "wls_lib.h"
+#include "wls.h"
+#include "syslib.h"
+
+#define WLS_MAP_SHM 1
+
+#define WLS_PHY_SHM_FILE_NAME "hp_"
+
+#define HUGE_PAGE_FILE_NAME "/mnt/huge/page"
+
+#define DIV_ROUND_OFFSET(X,Y) ( X/Y + ((X%Y)?1:0) )
+
+#define WLS_LIB_USER_SPACE_CTX_SIZE DMA_MAP_MAX_BLOCK_SIZE
+
+#define PLIB_ERR(x, args...)   printf("wls_lib: "x, ## args);
+#define PLIB_INFO(x, args...)  printf("wls_lib: "x, ## args);
+
+#ifdef _DEBUG_
+#define PLIB_DEBUG(x, args...)  printf("wls_lib debug: "x, ## args);
+#else
+#define PLIB_DEBUG(x, args...)  do { } while(0)
+#endif
+
+extern int gethugepagesizes(long pagesizes[], int n_elem);
+
+
+static uint32_t get_hugepagesz_flag(uint64_t hugepage_sz)
+{
+    unsigned size_flag = 0;
+
+    switch (hugepage_sz) {
+        case RTE_PGSIZE_256K:
+            size_flag = RTE_MEMZONE_256KB;
+            break;
+        case RTE_PGSIZE_2M:
+            size_flag = RTE_MEMZONE_2MB;
+            break;
+        case RTE_PGSIZE_16M:
+            size_flag = RTE_MEMZONE_16MB;
+            break;
+        case RTE_PGSIZE_256M:
+            size_flag = RTE_MEMZONE_256MB;
+            break;
+        case RTE_PGSIZE_512M:
+            size_flag = RTE_MEMZONE_512MB;
+            break;
+        case RTE_PGSIZE_1G:
+            size_flag = RTE_MEMZONE_1GB;
+            break;
+        case RTE_PGSIZE_4G:
+            size_flag = RTE_MEMZONE_4GB;
+            break;
+        case RTE_PGSIZE_16G:
+            size_flag = RTE_MEMZONE_16GB;
+            break;
+        default:
+            PLIB_INFO("Unknown hugepage size %lu\n", hugepage_sz);
+            break;
+    }
+    return size_flag;
+}
+
+static pthread_mutex_t wls_put_lock;
+static pthread_mutex_t wls_get_lock;
+static pthread_mutex_t wls_put_lock1;
+static pthread_mutex_t wls_get_lock1;
+
+static wls_us_ctx_t* wls_us_ctx = NULL;
+static wls_us_ctx_t* wls_us_ctx1 = NULL;
+static const struct rte_memzone *hp_memzone = NULL;
+static long hugePageSize = WLS_HUGE_DEF_PAGE_SIZE;
+static uint64_t gWlsMemorySize = 0;
+
+static inline int wls_check_ctx(void *h)
+{
+    if (h != wls_us_ctx) {
+        PLIB_ERR("Incorrect user space context\n");
+        return -1;
+    }
+    return 0;
+}
+
+static inline int wls_check_ctx1(void *h)
+{
+    if (h != wls_us_ctx1) {
+        PLIB_ERR("Incorrect user space context1\n");
+        return -1;
+    }
+    return 0;
+}
+
+static int wls_VirtToPhys(const void* virtAddr, uint64_t* physAddr)
+{
+    int mapFd;
+    uint64_t page;
+    unsigned int pageSize;
+    unsigned long virtualPageNumber;
+
+    mapFd = open("/proc/self/pagemap", O_RDONLY);
+    if (mapFd < 0) {
+        PLIB_ERR("Could't open pagemap file\n");
+        return -1;
+    }
+
+    /*get standard page size*/
+    pageSize = getpagesize();
+
+    virtualPageNumber = (unsigned long) virtAddr / pageSize;
+
+    lseek(mapFd, virtualPageNumber * sizeof (uint64_t), SEEK_SET);
+
+    if (read(mapFd, &page, sizeof (uint64_t)) < 0) {
+        close(mapFd);
+        PLIB_ERR("Could't read pagemap file\n");
+        return -1;
+    }
+
+    *physAddr = ((page & 0x007fffffffffffffULL) * pageSize);
+
+    close(mapFd);
+
+    return 0;
+}
+
+static void wls_mutex_destroy(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_destroy(pMutex);
+}
+
+static void wls_mutex_init(pthread_mutex_t* pMutex)
+{
+    pthread_mutexattr_t prior;
+    pthread_mutexattr_init(&prior);
+    pthread_mutexattr_setprotocol(&prior, PTHREAD_PRIO_INHERIT);
+    pthread_mutex_init(pMutex, &prior);
+    pthread_mutexattr_destroy(&prior);
+}
+
+static void wls_mutex_lock(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_lock(pMutex);
+}
+
+static void wls_mutex_unlock(pthread_mutex_t* pMutex)
+{
+    pthread_mutex_unlock(pMutex);
+}
+
+static int wls_initialize(const char *ifacename, uint64_t nWlsMemorySize)
+{
+    int ret;
+    pthread_mutexattr_t attr;
+
+    uint64_t nSize = nWlsMemorySize + sizeof(wls_drv_ctx_t);
+    uint8_t *pMemZone;
+    const struct rte_memzone *mng_ctx_memzone;
+    wls_drv_ctx_t *mng_ctx;
+
+    mng_ctx_memzone = rte_memzone_reserve_aligned(ifacename, nSize, rte_socket_id(), get_hugepagesz_flag(hugePageSize), hugePageSize);
+    if (mng_ctx_memzone == NULL) {
+        PLIB_ERR("Cannot reserve memory zone[%s]: %s\n", ifacename, rte_strerror(rte_errno));
+        return -1;
+    }
+
+    pMemZone = ((uint8_t *)mng_ctx_memzone->addr) + nWlsMemorySize;
+    memset(pMemZone, 0, sizeof(wls_drv_ctx_t));
+    mng_ctx = (wls_drv_ctx_t *)pMemZone;
+
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+    if (ret = pthread_mutex_init(&mng_ctx->mng_mutex, &attr)) {
+        PLIB_ERR("Failed to initialize mng_mutex %d\n", ret);
+        pthread_mutexattr_destroy(&attr);
+        return ret;
+    }
+    pthread_mutexattr_destroy(&attr);
+    PLIB_DEBUG("Run wls_initialized\n");
+    return 0;
+}
+
+static wls_us_ctx_t* wls_create_us_ctx(wls_drv_ctx_t *pDrv_ctx)
+{
+    int idx;
+
+    wls_mutex_lock(&pDrv_ctx->mng_mutex);
+
+    if (unlikely(pDrv_ctx->nWlsClients >= WLS_US_CLIENTS_MAX)) {
+        PLIB_ERR("Maximum number of clients reached");
+        wls_mutex_unlock(&pDrv_ctx->mng_mutex);
+        return NULL;
+    }
+
+    wls_us_ctx_t *pUsCtx = &pDrv_ctx->p_wls_us_ctx[pDrv_ctx->nWlsClients];
+    wls_us_priv_t *pUs_priv = &pUsCtx->wls_us_private;
+
+    PLIB_DEBUG("wls_create_us_ctx for %d client\n", pDrv_ctx->nWlsClients);
+    memset(pUsCtx, 0, sizeof (wls_us_ctx_t));
+
+    SFL_DefQueue(&pUsCtx->ul_free_block_pq, pUsCtx->ul_free_block_storage,
+        UL_FREE_BLOCK_QUEUE_SIZE * sizeof (void*));
+    WLS_MsgDefineQueue(&pUsCtx->get_queue, pUsCtx->get_storage, WLS_GET_QUEUE_N_ELEMENTS, 0);
+    WLS_MsgDefineQueue(&pUsCtx->put_queue, pUsCtx->put_storage, WLS_PUT_QUEUE_N_ELEMENTS, 0);
+
+    memset(pUs_priv, 0, sizeof (wls_us_priv_t));
+    if (sem_init(&pUs_priv->sema.sem, 1, 0)) {
+        PLIB_ERR("Failed to initialize semaphore %s\n", strerror(errno));
+        memset(pUsCtx, 0, sizeof (wls_us_ctx_t));
+        wls_mutex_unlock(&pDrv_ctx->mng_mutex);
+        return NULL;
+    }
+    rte_atomic16_init(&pUs_priv->sema.is_irq);
+
+    idx = pDrv_ctx->nWlsClients;
+    pDrv_ctx->p_wls_us_ctx[idx].dst_user_va = (uint64_t) & pDrv_ctx->p_wls_us_ctx[idx ^ 1];
+    PLIB_INFO("link: %d <-> %d\n", idx, idx ^ 1);
+
+    pUs_priv->pid = getpid();
+    pDrv_ctx->nWlsClients++;
+
+    wls_mutex_unlock(&pDrv_ctx->mng_mutex);
+    return pUsCtx;
+}
+
+static int wls_destroy_us_ctx(wls_us_ctx_t *pUsCtx, wls_drv_ctx_t *pDrv_ctx)
+{
+    wls_us_priv_t* pUs_priv = NULL;
+
+    wls_mutex_lock(&pDrv_ctx->mng_mutex);
+    if (pDrv_ctx->p_wls_us_ctx[0].wls_us_private.pid
+        && pDrv_ctx->p_wls_us_ctx[1].wls_us_private.pid) {
+        PLIB_INFO("un-link: 0 <-> 1\n");
+        pDrv_ctx->p_wls_us_ctx[0].dst_user_va = 0ULL;
+        pDrv_ctx->p_wls_us_ctx[1].dst_user_va = 0ULL;
+    }
+
+
+    if (pUsCtx) {
+        pUs_priv = (wls_us_priv_t*) & pUsCtx->wls_us_private;
+        if (pUs_priv) {
+            sem_destroy(&pUs_priv->sema.sem);
+            memset(pUsCtx, 0, sizeof (wls_us_ctx_t));
+            pDrv_ctx->nWlsClients--;
+        }
+    }
+
+    wls_mutex_unlock(&pDrv_ctx->mng_mutex);
+    return 0;
+}
+
+static int wls_destroy_us_ctx1(wls_us_ctx_t *pUsCtx, wls_drv_ctx_t *pDrv_ctx)
+{
+    wls_us_priv_t* pUs_priv = NULL;
+
+    wls_mutex_lock(&pDrv_ctx->mng_mutex);
+    if (pDrv_ctx->p_wls_us_ctx[2].wls_us_private.pid
+        && pDrv_ctx->p_wls_us_ctx[3].wls_us_private.pid) {
+        PLIB_INFO("un-link: 2 <-> 3\n");
+        pDrv_ctx->p_wls_us_ctx[2].dst_user_va = 0ULL;
+        pDrv_ctx->p_wls_us_ctx[3].dst_user_va = 0ULL;
+    }
+
+
+    if (pUsCtx) {
+        pUs_priv = (wls_us_priv_t*) & pUsCtx->wls_us_private;
+        if (pUs_priv) {
+            sem_destroy(&pUs_priv->sema.sem);
+            memset(pUsCtx, 0, sizeof (wls_us_ctx_t));
+            pDrv_ctx->nWlsClients--;
+        }
+    }
+
+    wls_mutex_unlock(&pDrv_ctx->mng_mutex);
+    return 0;
+}
+
+static int wls_wake_up_user_thread(char *buf, wls_sema_priv_t *semap)
+{
+    if (unlikely(rte_atomic16_read(&semap->is_irq) >= FIFO_LEN))
+        return 0;
+
+    unsigned int put = semap->drv_block_put + 1;
+    if (put >= FIFO_LEN)
+        put = 0;
+    memcpy(&semap->drv_block[put], buf, sizeof (wls_wait_req_t));
+    semap->drv_block_put = put;
+    rte_atomic16_inc(&semap->is_irq);
+    PLIB_DEBUG("PUT: put=%d get=%d T=%lu is_irq=%d\n",
+            semap->drv_block_put, semap->drv_block_get,
+            semap->drv_block[put].start_time, rte_atomic16_read(&semap->is_irq));
+    sem_post(&semap->sem);
+    return 0;
+}
+
+static int wls_process_put(wls_us_ctx_t *src, wls_us_ctx_t *dst)
+{
+    int ret = 0;
+    WLS_MSG_HANDLE hMsg;
+    int n = 0;
+
+    wls_us_priv_t* pDstPriv = NULL;
+    wls_wait_req_t drv_block;
+
+    if (NULL == src || NULL == dst) {
+        PLIB_DEBUG("Bad input addresses\n");
+        return -1;
+    }
+
+    n = WLS_GetNumItemsInTheQueue(&src->put_queue);
+
+    while (n--) {
+        if (WLS_MsgDequeue(&src->put_queue, &hMsg, NULL, (void*) src) == FALSE) {
+            PLIB_ERR("WLS_MsgDequeue src failed\n");
+            ret = -1;
+            break;
+        }
+        PLIB_DEBUG("WLS_Get %lx %d type %d\n", (U64) hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID);
+        if (WLS_MsgEnqueue(&dst->get_queue, hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID,
+                hMsg.flags, NULL, (void*) dst) == FALSE) { // try to send
+            if (WLS_MsgEnqueue(&src->put_queue, hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID,
+                    hMsg.flags, NULL, (void*) src) == FALSE) { // return back
+                PLIB_ERR("wls_process_put: Cannot return block to back to queue \n");
+                ret = -1;
+            }
+            break;
+        }
+    }
+
+    if (dst->wls_us_private.pid) {
+        pDstPriv = (wls_us_priv_t*) & dst->wls_us_private;
+
+        drv_block.start_time = wls_rdtsc();
+        pDstPriv->NeedToWakeUp = 1;
+        wls_wake_up_user_thread((char *) &drv_block, &pDstPriv->sema);
+    } else
+        ret = -1;
+
+    return ret;
+}
+
+static int wls_process_wakeup(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int ret = 0;
+    wls_wait_req_t drv_block;
+    if (wls_check_ctx(h))
+        return -1;
+    if (!pWls_us->wls_us_private.pid) {
+        PLIB_ERR("wakeup failed");
+        return -1;
+    }
+    drv_block.start_time = wls_rdtsc();
+    wls_wake_up_user_thread((char *) &drv_block, &pWls_us->wls_us_private.sema);
+
+    return ret;
+}
+
+static int wls_process_wakeup1(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int ret = 0;
+    wls_wait_req_t drv_block;
+    if (wls_check_ctx1(h))
+        return -1;
+    if (!pWls_us->wls_us_private.pid) {
+        PLIB_ERR("wakeup failed");
+        return -1;
+    }
+    drv_block.start_time = wls_rdtsc();
+    wls_wake_up_user_thread((char *) &drv_block, &pWls_us->wls_us_private.sema);
+
+    return ret;
+}
+
+static int wls_wait(wls_sema_priv_t *priv)
+{
+    if (!rte_atomic16_read(&priv->is_irq)) {
+        if (sem_wait(&priv->sem) || !rte_atomic16_read(&priv->is_irq)) {
+            return -1;
+        }
+    }
+
+    rte_atomic16_dec(&priv->is_irq);
+
+    if (priv->drv_block_put != priv->drv_block_get) {
+        unsigned int get = priv->drv_block_get + 1;
+
+        if (get >= FIFO_LEN)
+            get = 0;
+
+        priv->drv_block_get = get;
+
+        PLIB_DEBUG("GET: put=%d get=%d T=%lu is_irq=%d\n",
+                priv->drv_block_put, priv->drv_block_get,
+                priv->drv_block[get].start_time, rte_atomic16_read(&priv->is_irq));
+    } else {
+        PLIB_DEBUG("[wrong computation of queueing\n");
+    }
+
+    return 0;
+}
+
+static int wls_process_wait(void* h)
+{
+    wls_us_ctx_t* pUsCtx = (wls_us_ctx_t*) h;
+
+    if (wls_check_ctx(h))
+        return -1;
+
+    if (pUsCtx == NULL) {
+        PLIB_ERR("Wait failed on User context");
+        return -1;
+    }
+
+
+    if (!pUsCtx->wls_us_private.pid) {
+        PLIB_ERR("Wait failed");
+        return -1;
+    }
+    pUsCtx->wls_us_private.isWait = 1;
+    wls_wait(&pUsCtx->wls_us_private.sema);
+    pUsCtx->wls_us_private.isWait = 0;
+    return WLS_GetNumItemsInTheQueue(&pUsCtx->get_queue);
+}
+
+static int wls_process_wait1(void* h)
+{
+    wls_us_ctx_t* pUsCtx = (wls_us_ctx_t*) h;
+
+    if (wls_check_ctx1(h))
+        return -1;
+
+    if (pUsCtx == NULL) {
+        PLIB_ERR("Wait failed on User context");
+        return -1;
+    }
+
+
+    if (!pUsCtx->wls_us_private.pid) {
+        PLIB_ERR("Wait failed");
+        return -1;
+    }
+    pUsCtx->wls_us_private.isWait = 1;
+    wls_wait(&pUsCtx->wls_us_private.sema);
+    pUsCtx->wls_us_private.isWait = 0;
+    return WLS_GetNumItemsInTheQueue(&pUsCtx->get_queue);
+}
+
+
+void* WLS_Open(const char *ifacename, unsigned int mode, unsigned long long nWlsMemorySize)
+{
+    wls_us_ctx_t* pWls_us = NULL;
+    int i, len;
+    char temp[WLS_DEV_SHM_NAME_LEN] = {0};
+    uint8_t *pMemZone;
+
+    gethugepagesizes(&hugePageSize, 1);
+
+    if (wls_us_ctx)
+        return wls_us_ctx;
+
+    strncpy(temp, ifacename, WLS_DEV_SHM_NAME_LEN - 1);
+    PLIB_INFO("Open %s (DPDK memzone)\n", temp);
+
+    static const struct rte_memzone *mng_memzone;
+    mng_memzone = rte_memzone_lookup(temp);
+    if ((mng_memzone == NULL)&&(RTE_PROC_PRIMARY==rte_eal_process_type())) {
+        wls_initialize(temp, nWlsMemorySize);
+    }
+
+    mng_memzone = rte_memzone_lookup(temp);
+    if (mng_memzone == NULL) {
+        PLIB_ERR("Cannot initialize wls shared memory: %s\n", temp);
+        return NULL;
+    }
+
+    pMemZone = ((uint8_t *)mng_memzone->addr) + nWlsMemorySize;
+
+    PLIB_INFO("WLS_Open %p\n", pMemZone);
+    if ((pWls_us = wls_create_us_ctx((wls_drv_ctx_t *)pMemZone)) == NULL) {
+        PLIB_ERR("WLS_Open failed to create context\n");
+        return NULL;
+    }
+
+    PLIB_DEBUG("Local: pWls_us %p\n", pWls_us);
+
+    pWls_us->padding_wls_us_user_space_va = 0LL;
+    pWls_us->wls_us_user_space_va = pWls_us;
+    pWls_us->wls_us_ctx_size = sizeof (*pWls_us);
+    gWlsMemorySize = nWlsMemorySize;
+
+    wls_mutex_init(&wls_put_lock);
+    wls_mutex_init(&wls_get_lock);
+
+    pWls_us->mode = mode;
+    pWls_us->secmode = WLS_SEC_NA;
+    pWls_us->dualMode = WLS_SINGLE_MODE;
+    PLIB_INFO("Mode %d\n", pWls_us->mode);
+
+    PLIB_INFO("WLS shared management memzone: %s\n", temp);
+    strncpy(pWls_us->wls_dev_name, temp, WLS_DEV_SHM_NAME_LEN - 1);
+    wls_us_ctx = pWls_us;
+
+    return wls_us_ctx;
+}
+
+void* WLS_Open_Dual(const char *ifacename, unsigned int mode, unsigned long long nWlsMemorySize, void** handle1)
+{
+    wls_us_ctx_t* pWls_us = NULL;
+    wls_us_ctx_t* pWls_us1 = NULL;
+    int i, len;
+    char temp[WLS_DEV_SHM_NAME_LEN] = {0};
+    uint8_t *pMemZone;
+
+    gethugepagesizes(&hugePageSize, 1);
+
+    if (wls_us_ctx)
+        return wls_us_ctx;
+
+    strncpy(temp, ifacename, WLS_DEV_SHM_NAME_LEN - 1);
+    PLIB_INFO("Open %s (DPDK memzone)\n", temp);
+
+    static const struct rte_memzone *mng_memzone;
+    mng_memzone = rte_memzone_lookup(temp);
+    if ((mng_memzone == NULL)&&(RTE_PROC_PRIMARY==rte_eal_process_type())) {
+        wls_initialize(temp, nWlsMemorySize);
+    }
+
+    mng_memzone = rte_memzone_lookup(temp);
+    if (mng_memzone == NULL) {
+        PLIB_ERR("Cannot initialize wls shared memory: %s\n", temp);
+        return NULL;
+    }
+
+    pMemZone = ((uint8_t *)mng_memzone->addr) + nWlsMemorySize;
+    PLIB_INFO("nWlsMemorySize is %llu\n", nWlsMemorySize);
+    PLIB_INFO("WLS_Open Dual 1 %p\n", pMemZone);
+     if ((pWls_us = wls_create_us_ctx((wls_drv_ctx_t *)pMemZone)) == NULL) {
+        PLIB_ERR("WLS_Open Dual 1 failed to create context\n");
+        return NULL;
+     }
+     else
+     {    
+        PLIB_DEBUG("Local: pWls_us %p\n", pWls_us);
+        pWls_us->padding_wls_us_user_space_va = 0LL;
+        pWls_us->wls_us_user_space_va = pWls_us;
+        pWls_us->wls_us_ctx_size = sizeof (*pWls_us);
+        gWlsMemorySize = nWlsMemorySize;
+
+        wls_mutex_init(&wls_put_lock);
+        wls_mutex_init(&wls_get_lock);
+
+        pWls_us->mode = mode;
+        pWls_us->secmode = WLS_SEC_MASTER;
+        pWls_us->dualMode = WLS_DUAL_MODE;
+        PLIB_INFO("Mode %d SecMode %d \n", pWls_us->mode, pWls_us->secmode);
+
+        PLIB_INFO("WLS shared management memzone 1: %s\n", temp);
+        strncpy(pWls_us->wls_dev_name, temp, WLS_DEV_SHM_NAME_LEN - 1);
+        wls_us_ctx = pWls_us;
+           PLIB_INFO("pWLs_us is %p\n", wls_us_ctx);
+           *handle1 = pWls_us;  // Now the first context is for L1-FT_iapi
+     }
+     
+     // Create second context to support the second wls shared memory interface
+     if ((pWls_us1 = wls_create_us_ctx((wls_drv_ctx_t *)pMemZone)) == NULL) {
+        PLIB_ERR("WLS_Open Dual failed to create context 1\n");
+        return NULL;
+     }
+     else
+     {
+        PLIB_DEBUG("Local: pWls_us1 %p\n", pWls_us1);
+        pWls_us1->padding_wls_us_user_space_va = 0LL;
+        pWls_us1->wls_us_user_space_va = pWls_us1;
+        pWls_us1->wls_us_ctx_size = sizeof (*pWls_us1);
+        gWlsMemorySize = nWlsMemorySize;
+
+        wls_mutex_init(&wls_put_lock1);
+        wls_mutex_init(&wls_get_lock1);
+
+        pWls_us1->mode = mode;
+        pWls_us1->secmode = WLS_SEC_NA;
+        PLIB_INFO("Mode %d Secmode %d\n", pWls_us1->mode, pWls_us1->secmode);
+
+        PLIB_INFO("WLS shared management memzone 2: %s\n", temp);
+        strncpy(pWls_us1->wls_dev_name, temp, WLS_DEV_SHM_NAME_LEN - 1);
+       wls_us_ctx1 = pWls_us1; // Now the second context is for the L2-FT_fapi
+           PLIB_INFO("pWLs_us1 is %p\n", wls_us_ctx1);
+
+     }
+
+    return wls_us_ctx1; // returning second context preserves the L2 legacy code
+}
+
+int WLS_Ready(void* h)
+{
+    wls_us_ctx_t *pWls_us = (wls_us_ctx_t*) h;
+    wls_us_ctx_t *pWls_usRem = (wls_us_ctx_t*) pWls_us->dst_user_va;
+
+    if (!wls_us_ctx) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    if (pWls_usRem->wls_us_private.pid) {
+        return 0;
+    }
+    return -1;
+}
+
+int WLS_Ready1(void* h)
+{
+    wls_us_ctx_t *pWls_us = (wls_us_ctx_t*) h;
+    wls_us_ctx_t *pWls_usRem = (wls_us_ctx_t*) pWls_us->dst_user_va;
+
+    if (!wls_us_ctx1) {
+        PLIB_ERR("Library was not opened for Context 1\n");
+        return -1;
+    }
+
+    if (pWls_usRem->wls_us_private.pid) {
+        return 0;
+    }
+    return -1;
+}
+
+int WLS_Close(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int ret = 0;
+    uint8_t *pMemZone;
+    wls_drv_ctx_t *pDrv_ctx;
+
+    if (!wls_us_ctx) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    if (wls_check_ctx(h))
+        return -1;
+
+    static const struct rte_memzone *mng_memzone;
+    mng_memzone = rte_memzone_lookup(pWls_us->wls_dev_name);
+    if (mng_memzone == NULL) {
+        PLIB_ERR("Cannot find mng memzone: %s %s\n",
+                    pWls_us->wls_dev_name, rte_strerror(rte_errno));
+        return -1;
+    }
+
+    pMemZone = ((uint8_t *)mng_memzone->addr) + gWlsMemorySize;
+    pDrv_ctx = (wls_drv_ctx_t *)pMemZone;
+
+    PLIB_INFO("WLS_Close\n");
+    if ((ret = wls_destroy_us_ctx(pWls_us, pDrv_ctx)) < 0) {
+        PLIB_ERR("Close failed [%d]\n", ret);
+        return ret;
+    }
+
+    wls_mutex_destroy(&wls_put_lock);
+    wls_mutex_destroy(&wls_get_lock);
+
+    wls_us_ctx = NULL;
+
+    if (0 == pDrv_ctx->nWlsClients) {
+        wls_mutex_destroy(&pDrv_ctx->mng_mutex);
+        rte_memzone_free(mng_memzone);
+    }
+    return 0;
+}
+
+int WLS_Close1(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int ret = 0;
+    uint8_t *pMemZone;
+    wls_drv_ctx_t *pDrv_ctx;
+
+    if (!wls_us_ctx1) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    if (wls_check_ctx1(h))
+        return -1;
+
+    static const struct rte_memzone *mng_memzone;
+    mng_memzone = rte_memzone_lookup(pWls_us->wls_dev_name);
+    if (mng_memzone == NULL) {
+        PLIB_ERR("Cannot find mng memzone: %s %s\n",
+                    pWls_us->wls_dev_name, rte_strerror(rte_errno));
+        return -1;
+    }
+
+    pMemZone = ((uint8_t *)mng_memzone->addr) + gWlsMemorySize;
+    pDrv_ctx = (wls_drv_ctx_t *)pMemZone;
+
+    PLIB_INFO("WLS_Close1\n");
+    if ((ret = wls_destroy_us_ctx1(pWls_us, pDrv_ctx)) < 0) {
+        PLIB_ERR("Close failed [%d]\n", ret);
+        return ret;
+    }
+
+    wls_mutex_destroy(&wls_put_lock1);
+    wls_mutex_destroy(&wls_get_lock1);
+
+    wls_us_ctx1 = NULL;
+
+    if (0 == pDrv_ctx->nWlsClients) {
+        wls_mutex_destroy(&pDrv_ctx->mng_mutex);
+        rte_memzone_free(mng_memzone);
+    }
+    return 0;
+}
+
+void* WLS_Alloc(void* h, unsigned int size)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    static const struct rte_memzone *mng_memzone;
+    long nHugePage;
+    void *pvirtAddr = NULL;
+    int count;
+
+    if ((NULL != hp_memzone)&&(pWls_us->dualMode != WLS_DUAL_MODE)) {
+        PLIB_ERR("Memory zone already reserved\n");
+        return hp_memzone->addr;
+    }
+
+    hugepage_tabl_t* pHugePageTlb = &pWls_us->hugepageTbl[0];
+    hugepage_tabl_t* pHugePageTlb1 = &pWls_us->hugepageTbl[1];
+    hugepage_tabl_t* pHugePageTlb2 = &pWls_us->hugepageTbl[2];
+
+    PLIB_INFO("hugePageSize on the system is %ld\n", hugePageSize);
+
+    /* calculate total number of hugepages */
+    nHugePage = DIV_ROUND_OFFSET(size, hugePageSize);
+
+    if (nHugePage >= MAX_N_HUGE_PAGES) {
+        PLIB_INFO("not enough hugepages: need %ld  system has %d\n", nHugePage, MAX_N_HUGE_PAGES);
+        return NULL;
+    }
+
+    mng_memzone = rte_memzone_lookup(pWls_us->wls_dev_name);
+    if (mng_memzone == NULL) {
+        PLIB_ERR("Cannot initialize wls shared memory: %s\n", pWls_us->wls_dev_name);
+        return NULL;
+    }
+
+    hp_memzone = (struct rte_memzone *)mng_memzone;
+    pvirtAddr = (void *)hp_memzone->addr;
+    PLIB_DEBUG("pvirtAddr is %p\n", pvirtAddr);
+    if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+        memset(pvirtAddr, 0, sizeof (wls_drv_ctx_t));
+    }
+
+    for (count = 0; count < nHugePage; count++) {
+        /*Increment virtual address to next hugepage to create table*/
+        pHugePageTlb[count].pageVa = ((unsigned char*) pvirtAddr + \
+                                                (count * hugePageSize));
+        /*Creating dummy page fault in process for each page
+                                                inorder to get pagemap*/
+        *(unsigned char*) pHugePageTlb[count].pageVa = 1;
+
+        if (wls_VirtToPhys((uint64_t*) pHugePageTlb[count].pageVa,
+                &pHugePageTlb[count].pagePa) == -1) {
+            PLIB_ERR("Virtual to physical conversion failed\n");
+            return NULL;
+        }
+    }
+
+    PLIB_DEBUG("count is %d, pHugePageTlb->pageVa is %p  pHugePageTlb1->pageVa is %p  pHugePageTlb2->pageVa is %p\n",count, pHugePageTlb->pageVa, pHugePageTlb1->pageVa, pHugePageTlb2->pageVa);
+    PLIB_INFO("WLS_Alloc [%d] bytes\n", size);
+
+    pWls_us->HugePageSize = (uint32_t) hugePageSize;
+    pWls_us->alloc_buffer = pvirtAddr;
+    pWls_us->alloc_size = (uint32_t) (nHugePage * hugePageSize);
+
+    if ((pWls_us->mode == WLS_MASTER_CLIENT)||(pWls_us->secmode == WLS_SEC_MASTER)) {
+        wls_us_ctx_t *pWls_usRem = (wls_us_ctx_t*) pWls_us->dst_user_va;
+        PLIB_INFO("Connecting to remote peer ...\n");
+        while (pWls_usRem->wls_us_private.pid == 0) { // wait for slave
+        }
+
+        PLIB_INFO("Connected to remote peer\n");
+        pWls_us->dst_user_va = (uint64_t) pWls_usRem;
+    }
+    return pvirtAddr;
+}
+
+int WLS_Free(void* h, PVOID pMsg)
+{
+    static const struct rte_memzone *mng_memzone;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    wls_drv_ctx_t *pDrv_ctx;
+
+    mng_memzone = rte_memzone_lookup(pWls_us->wls_dev_name);
+    if (mng_memzone == NULL) {
+        PLIB_ERR("Cannot find mng memzone: %s %s\n",
+                    pWls_us->wls_dev_name, rte_strerror(rte_errno));
+        return -1;
+    }
+    pDrv_ctx = mng_memzone->addr;
+
+    if (pMsg !=  pWls_us->alloc_buffer) {
+        PLIB_ERR("incorrect pMsg %p [expected %p]\n", pMsg, pWls_us->alloc_buffer);
+        return -1;
+    }
+
+    if ((pWls_us->mode == WLS_MASTER_CLIENT)||(pWls_us->mode == WLS_SEC_MASTER)) {
+        if (pWls_us->dst_user_va) {
+            pWls_us->dst_user_va = 0;
+        }
+    }
+
+    PLIB_DEBUG("WLS_Free %s\n", shm_name);
+    if ( (1 == pDrv_ctx->nWlsClients) && hp_memzone)
+        hp_memzone = NULL;
+    return 0;
+}
+
+int WLS_Put(void *h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int ret = 0;
+
+    if (wls_check_ctx(h))
+        return -1;
+
+    if (!WLS_IS_ONE_HUGE_PAGE(pMsg, MsgSize, hugePageSize)) {
+        PLIB_ERR("WLS_Put input error: buffer is crossing 2MB page boundary %lx size %u\n",
+                (U64) pMsg, MsgSize);
+    }
+
+    wls_mutex_lock(&wls_put_lock);
+
+    if ((WLS_FLAGS_MASK & Flags)) { // multi block transaction
+        if (Flags & WLS_TF_SYN) {
+            PLIB_DEBUG("WLS_SG_FIRST\n");
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                    Flags, NULL, (void*) pWls_us)) {
+                PLIB_DEBUG("WLS_Get %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+            }
+        } else if ((Flags & WLS_TF_SCATTER_GATHER)
+                    && !(Flags & WLS_TF_SYN)
+                    && !(Flags & WLS_TF_FIN)) {
+            PLIB_DEBUG("WLS_SG_NEXT\n");
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                    Flags, NULL, (void*) pWls_us)) {
+                PLIB_DEBUG("WLS_Put %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+            }
+        } else if (Flags & WLS_TF_FIN) {
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                    Flags, NULL, (void*) pWls_us)) {
+                PLIB_DEBUG("WLS_Put %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+            }
+
+            PLIB_DEBUG("List: call wls_process_put\n");
+            if (pWls_us->dst_user_va) {
+                if ((ret = wls_process_put(pWls_us, (wls_us_ctx_t*) pWls_us->dst_user_va)) < 0) {
+                    PLIB_ERR("Put failed [%d]\n", ret);
+                    wls_mutex_unlock(&wls_put_lock);
+                    return -1;
+                }
+            }
+        } else
+            PLIB_ERR("unsaported flags %x\n", WLS_FLAGS_MASK & Flags);
+    } else { // one block transaction
+        if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                Flags, NULL, (void*) pWls_us)) {
+            PLIB_DEBUG("WLS_Put %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+        }
+
+        PLIB_DEBUG("One block: call wls_process_put\n");
+        if (likely(pWls_us->dst_user_va)) {
+            if ((ret = wls_process_put(pWls_us, (wls_us_ctx_t*) pWls_us->dst_user_va)) < 0) {
+                PLIB_ERR("Put failed [%d]\n", ret);
+                wls_mutex_unlock(&wls_put_lock);
+                return -1;
+            }
+        } else {
+            PLIB_ERR("Destination address is empty\n");
+            wls_mutex_unlock(&wls_put_lock);
+            return -1;
+        }
+    }
+    wls_mutex_unlock(&wls_put_lock);
+
+    return 0;
+}
+
+int WLS_Put1(void *h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int ret = 0;
+
+    if (wls_check_ctx1(h))
+        return -1;
+
+    if (!WLS_IS_ONE_HUGE_PAGE(pMsg, MsgSize, hugePageSize)) {
+        PLIB_ERR("WLS_Put input error: buffer is crossing 2MB page boundary %lx size %u\n",
+                (U64) pMsg, MsgSize);
+    }
+
+    wls_mutex_lock(&wls_put_lock1);
+
+    if ((WLS_FLAGS_MASK & Flags)) { // multi block transaction
+        if (Flags & WLS_TF_SYN) {
+            PLIB_DEBUG("WLS_SG_FIRST\n");
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                    Flags, NULL, (void*) pWls_us)) {
+                PLIB_DEBUG("WLS_Get %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+            }
+        } else if ((Flags & WLS_TF_SCATTER_GATHER)
+                    && !(Flags & WLS_TF_SYN)
+                    && !(Flags & WLS_TF_FIN)) {
+            PLIB_DEBUG("WLS_SG_NEXT\n");
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                    Flags, NULL, (void*) pWls_us)) {
+                PLIB_DEBUG("WLS_Put %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+            }
+        } else if (Flags & WLS_TF_FIN) {
+            if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                    Flags, NULL, (void*) pWls_us)) {
+                PLIB_DEBUG("WLS_Put %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+            }
+
+            PLIB_DEBUG("List: call wls_process_put\n");
+            if (pWls_us->dst_user_va) {
+                if ((ret = wls_process_put(pWls_us, (wls_us_ctx_t*) pWls_us->dst_user_va)) < 0) {
+                    PLIB_ERR("Put failed [%d]\n", ret);
+                    wls_mutex_unlock(&wls_put_lock1);
+                    return -1;
+                }
+            }
+        } else
+            PLIB_ERR("unsupported flags %x\n", WLS_FLAGS_MASK & Flags);
+    } else { // one block transaction
+        if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID,
+                Flags, NULL, (void*) pWls_us)) {
+            PLIB_DEBUG("WLS_Put %lx %d type %d\n", (U64) pMsg, MsgSize, MsgTypeID);
+        }
+
+        PLIB_DEBUG("One block: call wls_process_put\n");
+        if (likely(pWls_us->dst_user_va)) {
+            if ((ret = wls_process_put(pWls_us, (wls_us_ctx_t*) pWls_us->dst_user_va)) < 0) {
+                PLIB_ERR("Put failed [%d]\n", ret);
+                wls_mutex_unlock(&wls_put_lock1);
+                return -1;
+            }
+        } else {
+            PLIB_ERR("Destination address is empty\n");
+            wls_mutex_unlock(&wls_put_lock1);
+            return -1;
+        }
+    }
+    wls_mutex_unlock(&wls_put_lock1);
+
+    return 0;
+}
+
+int WLS_Check(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if (wls_check_ctx(h))
+        return 0;
+
+    return WLS_GetNumItemsInTheQueue(&pWls_us->get_queue);
+}
+
+int WLS_Check1(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if (wls_check_ctx1(h))
+        return 0;
+
+    return WLS_GetNumItemsInTheQueue(&pWls_us->get_queue);
+}
+
+unsigned long long WLS_Get(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    WLS_MSG_HANDLE hMsg;
+    uint64_t pMsg = (uint64_t) NULL;
+
+    if (wls_check_ctx(h))
+    {
+       PLIB_ERR("WLS_Get fails wls_check_ctx\n");
+        return 0;
+    }
+
+    wls_mutex_lock(&wls_get_lock);
+
+    if (WLS_MsgDequeue(&pWls_us->get_queue, &hMsg, NULL, (void*) pWls_us)) {
+        PLIB_DEBUG("WLS_Get %lx %d type %d\n", (U64) hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID);
+        pMsg = hMsg.pIaPaMsg;
+        *MsgSize = hMsg.MsgSize;
+        *MsgTypeID = hMsg.TypeID;
+        *Flags = hMsg.flags;
+    }
+
+    wls_mutex_unlock(&wls_get_lock);
+
+    return pMsg;
+}
+
+unsigned long long WLS_Get1(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    WLS_MSG_HANDLE hMsg;
+    uint64_t pMsg = (uint64_t) NULL;
+
+    if (wls_check_ctx1(h))
+        return 0;
+
+    wls_mutex_lock(&wls_get_lock1);
+
+    if (WLS_MsgDequeue(&pWls_us->get_queue, &hMsg, NULL, (void*) pWls_us)) {
+        PLIB_DEBUG("WLS_Get %lx %d type %d\n", (U64) hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID);
+        pMsg = hMsg.pIaPaMsg;
+        *MsgSize = hMsg.MsgSize;
+        *MsgTypeID = hMsg.TypeID;
+        *Flags = hMsg.flags;
+    }
+
+    wls_mutex_unlock(&wls_get_lock1);
+
+    return pMsg;
+}
+
+int WLS_WakeUp(void* h)
+{
+    if (!wls_us_ctx) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+    if (wls_check_ctx(h))
+        return -1;
+
+    PLIB_DEBUG("WLS_WakeUp\n");
+
+    return wls_process_wakeup(h);
+
+
+    return 0;
+}
+
+int WLS_WakeUp1(void* h)
+{
+    if (!wls_us_ctx1) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+    if (wls_check_ctx1(h))
+        return -1;
+
+    PLIB_DEBUG("WLS_WakeUp1\n");
+
+    return wls_process_wakeup1(h);
+
+
+    return 0;
+}
+
+int WLS_Wait(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if (!wls_us_ctx || (wls_us_ctx != pWls_us)) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    return wls_process_wait(h);
+}
+
+int WLS_Wait1(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if (!wls_us_ctx1 || (wls_us_ctx1 != pWls_us)) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+    return wls_process_wait1(h);
+}
+
+unsigned long long WLS_WGet(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    uint64_t pRxMsg = WLS_Get(h, MsgSize, MsgTypeID, Flags);
+
+    if (pRxMsg)
+        return pRxMsg;
+
+    WLS_Wait(h);
+    return WLS_Get(h, MsgSize, MsgTypeID, Flags);
+}
+
+unsigned long long WLS_WGet1(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
+{
+    uint64_t pRxMsg = WLS_Get1(h, MsgSize, MsgTypeID, Flags);
+
+    if (pRxMsg)
+        return pRxMsg;
+
+    WLS_Wait1(h);
+    return WLS_Get1(h, MsgSize, MsgTypeID, Flags);
+}
+
+unsigned long long WLS_VA2PA(void* h, PVOID pMsg)
+{
+    uint64_t ret = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    unsigned long alloc_base;
+    hugepage_tabl_t* pHugePageTlb;
+    uint64_t hugePageBase;
+    uint64_t hugePageOffet;
+    unsigned int count = 0;
+
+    uint64_t HugePageMask = ((unsigned long) pWls_us->HugePageSize - 1);
+    if (pWls_us->alloc_buffer == NULL) {
+        PLIB_ERR("WLS_VA2PA: nothing was allocated [%ld]\n", ret);
+        return (uint64_t) ret;
+    }
+
+    alloc_base = (unsigned long) pWls_us->alloc_buffer;
+
+    pHugePageTlb = &pWls_us->hugepageTbl[0];
+
+    hugePageBase = (uint64_t) pMsg & ~HugePageMask;
+    hugePageOffet = (uint64_t) pMsg & HugePageMask;
+
+    count = (hugePageBase - alloc_base) / pWls_us->HugePageSize;
+    PLIB_DEBUG("WLS_VA2PA %lx base %llx off %llx  count %u\n", (unsigned long) pMsg,
+            (uint64_t) hugePageBase, (uint64_t) hugePageOffet, count);
+
+    ret = pHugePageTlb[count].pagePa + hugePageOffet;
+
+    //printf("       WLS_VA2PA: %p -> %p   HugePageSize[%d] HugePageMask[%p] count[%d] pagePa[%p] hugePageBase[%p] alloc_buffer[%p] hugePageOffet[%lld]\n",
+    //    pMsg, (void*)ret, pWls_us->HugePageSize, (void*)HugePageMask, count, (void*)pHugePageTlb[count].pagePa, (void*)hugePageBase, pWls_us->alloc_buffer, hugePageOffet);
+
+    return (uint64_t) ret;
+}
+
+void* WLS_PA2VA(void* h, unsigned long long pMsg)
+{
+    unsigned long ret = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    hugepage_tabl_t* pHugePageTlb;
+    uint64_t hugePageBase;
+    uint64_t hugePageOffet;
+    unsigned int count;
+    int i;
+    uint64_t HugePageMask = ((uint64_t) pWls_us->HugePageSize - 1);
+
+    if (pWls_us->alloc_buffer == NULL) {
+        PLIB_ERR("WLS_PA2VA: nothing was allocated [%ld]\n", ret);
+        return (void*) ret;
+    }
+
+    pHugePageTlb = &pWls_us->hugepageTbl[0];
+
+    hugePageBase = (uint64_t) pMsg & ~HugePageMask;
+    hugePageOffet = (uint64_t) pMsg & HugePageMask;
+
+    count = pWls_us->alloc_size / pWls_us->HugePageSize;
+
+    PLIB_DEBUG("WLS_PA2VA %llx base %llx off %llx  count %d\n", (uint64_t) pMsg,
+            (uint64_t) hugePageBase, (uint64_t) hugePageOffet, count);
+
+    for (i = 0; i < count; i++) {
+        if (pHugePageTlb[i].pagePa == hugePageBase) {
+            ret = (unsigned long) pHugePageTlb[i].pageVa;
+            ret += hugePageOffet;
+            return (void*) ret;
+        }
+    }
+
+    //printf("       WLS_VA2PA: %p -> %p   HugePageSize[%d] HugePageMask[%p] count[%d] pagePa[%p] hugePageBase[%p] alloc_buffer[%p] hugePageOffet[%lld]\n",
+    //    (void*)pMsg, (void*)ret, pWls_us->HugePageSize, (void*)HugePageMask, count, (void*)pHugePageTlb[count].pagePa, (void*)hugePageBase, pWls_us->alloc_buffer, hugePageOffet);
+
+    return (void*) (ret);
+}
+
+int WLS_EnqueueBlock(void* h, unsigned long long pMsg)
+{
+    int ret = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if (!wls_us_ctx) {
+        PLIB_ERR("Library was not opened\n");
+        return -1;
+    }
+
+
+    if (pMsg == 0) {
+        PLIB_ERR("WLS_EnqueueBlock: Null\n");
+        return -1;
+    }
+
+    if (pWls_us->dst_user_va) {
+        wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t*) pWls_us->dst_user_va;
+        ret = SFL_WlsEnqueue(&pDstWls_us->ul_free_block_pq, pMsg, NULL, pWls_us);
+        if (ret == 1) {
+            unsigned long* ptr = (unsigned long*) WLS_PA2VA(pWls_us, pMsg);
+            if (ptr) {
+                *ptr = 0xFFFFFFFFFFFFFFFF;
+            }
+        }
+    } else
+        ret = -1;
+
+    PLIB_DEBUG("SFL_WlsEnqueue %d\n", ret);
+    return ret;
+}
+
+int WLS_EnqueueBlock1(void* h, unsigned long long pMsg)
+{
+    int ret = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if (!wls_us_ctx1) {
+        PLIB_ERR("Library was not opened for a second context\n");
+        return -1;
+    }
+
+    if (pWls_us->mode == WLS_SLAVE_CLIENT) {
+        PLIB_ERR("Slave doesn't support memory allocation\n");
+        return -1;
+    }
+
+    if (pMsg == 0) {
+        PLIB_ERR("WLS_EnqueueBlock: Null\n");
+        return -1;
+    }
+
+    if (pWls_us->dst_user_va) {
+        wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t*) pWls_us->dst_user_va;
+        ret = SFL_WlsEnqueue(&pDstWls_us->ul_free_block_pq, pMsg, NULL, pWls_us);
+        if (ret == 1) {
+            unsigned long* ptr = (unsigned long*) WLS_PA2VA(pWls_us, pMsg);
+            if (ptr) {
+                *ptr = 0xFFFFFFFFFFFFFFFF;
+            }
+        }
+    } else
+        ret = -1;
+
+    PLIB_DEBUG("SFL_WlsEnqueue %d\n", ret);
+    return ret;
+}
+
+
+unsigned long long WLS_DequeueBlock(void* h)
+{
+    unsigned long long retval = 0;
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+
+    if ((pWls_us->mode == WLS_SLAVE_CLIENT)&&(pWls_us->secmode==WLS_SEC_NA))
+    {
+        // local
+        return SFL_WlsDequeue(&pWls_us->ul_free_block_pq, NULL, h);
+    }    
+    if (!pWls_us->dst_user_va)
+    {
+        return retval;
+    }
+        // remote
+    wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t*) pWls_us->dst_user_va;
+    retval = SFL_WlsDequeue(&pDstWls_us->ul_free_block_pq, NULL, pDstWls_us);
+    if (retval) {
+        unsigned long* ptr = (unsigned long*) WLS_PA2VA(pWls_us, retval);
+        if (ptr) {
+            if (*ptr != 0xFFFFFFFFFFFFFFFF) {
+                PLIB_ERR("WLS_EnqueueBlock: incorrect content pa: 0x%016lx: 0x%016lx\n",
+                         (unsigned long) retval, *ptr);
+            }
+        }
+    }
+
+    return retval;
+}
+
+int WLS_NumBlocks(void* h)
+{
+    wls_us_ctx_t* pWls_us = (wls_us_ctx_t*) h;
+    int n = 0;
+
+    if (pWls_us->mode == WLS_SLAVE_CLIENT) {
+        // local
+        n = SFL_GetNumItemsInTheQueue(&pWls_us->ul_free_block_pq);
+    } else if (pWls_us->dst_user_va) {
+        // remote
+        wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t*) pWls_us->dst_user_va;
+        n = SFL_GetNumItemsInTheQueue(&pDstWls_us->ul_free_block_pq);
+    }
+
+    return n;
+}
diff --git a/wls_lib/wls_start.sh b/wls_lib/wls_start.sh
new file mode 100644 (file)
index 0000000..66ae2e6
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/bash
+###############################################################################
+#
+#   Copyright (c) 2019 Intel.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+###############################################################################
+#
+#  File: wls_start.sh
+#        Test script to load wls module.
+#
+
+export RTE_WLS=`pwd`
+
+#
+# Unloads wls.ko.
+#
+remove_wls_module()
+{
+    echo "Unloading WLS module"
+    /sbin/lsmod | grep -s wls > /dev/null
+    if [ $? -eq 0 ] ; then
+        sudo /sbin/rmmod wls
+    fi
+}
+
+#
+# Loads new wls.ko
+#
+load_wls_module()
+{
+    if [ ! -f $RTE_WLS/wls.ko ];then
+        echo "## ERROR: Folder does not have the WLS Kernel Module."
+        echo "       To fix, please try to rebuild WLS"
+        return
+    fi
+
+    remove_wls_module
+
+    /sbin/lsmod | grep -s wls > /dev/null
+    if [ $? -eq        1 ] ; then
+        if [ -f /lib/modules/$(uname -r)/updates/drivers/intel/wls/wls.ko ] ; then
+            echo "Loading WLS module"
+            sudo /sbin/modprobe wls wlsMaxClients=4
+       else
+           echo "No module. WLS is not istalled? do 'make install'"
+        fi
+    fi
+}
+
+load_wls_module
+
+
+