[][openwrt][mt7988][crypto][EIP197 DDK Porting]
[Description]
Add eip197 DDK(Driver Development Kit) and firmware
to eip197 package(crypto-eip)
eip197 DDK v5.6.1
eip197b-iew firmware v3.5
[Release-log]
N/A
Change-Id: I662327ecfbdac69742bf0b50362d7c28fc06372b
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7895272
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/slad/adapter_global_eip74.c b/package-21.02/kernel/crypto-eip/src/ddk/slad/adapter_global_eip74.c
new file mode 100644
index 0000000..f31fa52
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/slad/adapter_global_eip74.c
@@ -0,0 +1,630 @@
+/* api_global_eip74.c
+ *
+ * Deterministic Random Bit Generator (EIP-74) Global Control Initialization
+ * Adapter. The EIP-74 is used to generate pseudo-random IVs for outbound
+ * operations in CBC mode.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2017-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "api_global_eip74.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Configuration.
+#include "c_adapter_eip74.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h" // bool, uint8_t
+
+// memcpy
+#include "clib.h"
+
+// EIP-73 Driver Library.
+#include "eip74.h"
+
+#include "device_types.h" // Device_Handle_t
+#include "device_mgmt.h" // Device_find
+
+// Logging API
+#include "log.h" // Log_*, LOG_*
+
+// Adapter interrupts API
+#include "adapter_interrupts.h" // Adapter_Interrupt_*
+
+// Runtime Power Management Device Macros API
+#include "rpm_device_macros.h" // RPM_*
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+/* Put all adapter local variables in one structure */
+static struct {
+ EIP74_IOArea_t IOArea;
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ GlobalControl74_NotifyFunction_t Notify_CBFunc;
+#endif
+#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
+ GlobalControl74_Configuration_t CachedConfig;
+ bool fInitialized;
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ bool fInterruptEnabled;
+#endif
+#endif
+} EIP74State;
+
+
+static const GlobalControl74_Capabilities_t Global_CapabilitiesString =
+{
+ "EIP-74 v_._p_"// szTextDescription
+};
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74Lib_Init
+ */
+static GlobalControl74_Error_t
+GlobalControl74Lib_Init(
+ const GlobalControl74_Configuration_t * const Configuration_p,
+ const uint8_t * const Entropy_p);
+
+
+#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
+/*----------------------------------------------------------------------------
+ * GlobalControl74Lib_Resune
+ */
+static int
+GlobalControl74Lib_Resune(
+ void *p)
+{
+ uint8_t Entropy[48];
+ IDENTIFIER_NOT_USED(p);
+ if (EIP74State.fInitialized)
+ {
+ /* Note we should add fresh random data here */
+ ZEROINIT(Entropy);
+ if (GlobalControl74Lib_Init(&EIP74State.CachedConfig, Entropy) !=
+ GLOBAL_CONTROL_EIP74_NO_ERROR)
+ {
+ return -1;
+ }
+
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ if (EIP74State.fInitialized && EIP74State.fInterruptEnabled)
+ {
+ Adapter_Interrupt_Disable(ADAPTER_EIP74_ERR_IRQ, 0);
+ Adapter_Interrupt_Disable(ADAPTER_EIP74_RES_IRQ, 0);
+ }
+#endif
+ }
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74Lib_Suspend
+ */
+static int
+GlobalControl74Lib_Suspend(
+ void *p)
+{
+ IDENTIFIER_NOT_USED(p);
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ if (EIP74State.fInitialized && EIP74State.fInterruptEnabled)
+ {
+ Adapter_Interrupt_Disable(ADAPTER_EIP74_ERR_IRQ, 0);
+ Adapter_Interrupt_Disable(ADAPTER_EIP74_RES_IRQ, 0);
+ }
+#endif
+ return 0;
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74Lib_CopyKeyMat
+ *
+ * Copy a key represented as a byte array into a word array..
+ *
+ * Destination_p (input)
+ * Destination (word-aligned) of the word array
+ *
+ * Source_p (input)
+ * Source (byte aligned) of the data.
+ *
+ * KeyByteCount (input)
+ * Size of the key in bytes.
+ *
+ * Destination_p is allowed to be a null pointer, in which case no key
+ * will be written.
+ */
+static void
+GlobalControl74Lib_CopyKeyMat(
+ uint32_t * const Destination_p,
+ const uint8_t * const Source_p,
+ const unsigned int KeyByteCount)
+{
+ uint32_t *dst = Destination_p;
+ const uint8_t *src = Source_p;
+ unsigned int i,j;
+ uint32_t w;
+ if (Destination_p == NULL)
+ return;
+ for(i=0; i < KeyByteCount / sizeof(uint32_t); i++)
+ {
+ w=0;
+ for(j=0; j<sizeof(uint32_t); j++)
+ w=(w<<8)|(*src++);
+ *dst++ = w;
+ }
+}
+
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+/*----------------------------------------------------------------------------
+ * GlobalControl74_InterruptHandlerNotify
+ */
+static void
+GlobalControl74_InterruptHandlerNotify(
+ const int nIRQ,
+ const unsigned int flags)
+{
+ GlobalControl74_NotifyFunction_t CB_Func = EIP74State.Notify_CBFunc;
+
+ IDENTIFIER_NOT_USED(nIRQ);
+ IDENTIFIER_NOT_USED(flags);
+
+ LOG_INFO("GlobalControl74_InterruptHandlerNotify\n");
+#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
+ EIP74State.fInterruptEnabled = true;
+#endif
+
+ EIP74State.Notify_CBFunc = NULL;
+ if (CB_Func != NULL)
+ {
+ LOG_INFO("\t Invoking callback\n");
+ CB_Func();
+ }
+}
+#endif
+/*----------------------------------------------------------------------------
+ * GlobalControl74Lib_Init
+ *
+ * This function performs the initialization of the EIP-74 Deterministic
+ * Random Bit Generator.
+ *
+ * Note: the Device was already found and the IOArea is already initialized.
+ *
+ * Configuration_p (input)
+ * Configuration parameters of the DRBG.
+ *
+ * Entropy_p (input)
+ * Pointer to a string of exactly 48 bytes that serves as the entropy.
+ * to initialize the DRBG.
+ *
+ * Return value
+ * GLOBAL_CONTROL_EIP74_NO_ERROR : initialization performed successfully
+ * GLOBAL_CONTROL_EIP74_ERROR_INTERNAL : initialization failed
+ */
+static GlobalControl74_Error_t
+GlobalControl74Lib_Init(
+ const GlobalControl74_Configuration_t * const Configuration_p,
+ const uint8_t * const Entropy_p)
+{
+ EIP74_Error_t Rc;
+ EIP74_Configuration_t Conf;
+ unsigned LoopCounter = ADAPTER_EIP74_RESET_MAX_RETRIES;
+ uint32_t Entropy[12];
+
+ Rc = EIP74_Reset(&EIP74State.IOArea);
+ do
+ {
+ if (Rc == EIP74_BUSY_RETRY_LATER)
+ {
+ LoopCounter--;
+ if (LoopCounter == 0)
+ {
+ LOG_CRIT("%s EIP74 reset timed out\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+ Rc = EIP74_Reset_IsDone(&EIP74State.IOArea);
+ }
+ else if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 reset error\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+ } while (Rc != EIP74_NO_ERROR);
+
+ if (Configuration_p->GenerateBlockSize == 0)
+ {
+ Conf.GenerateBlockSize = ADAPTER_EIP74_GEN_BLK_SIZE;
+ }
+ else
+ {
+ Conf.GenerateBlockSize = Configuration_p->GenerateBlockSize;
+ }
+
+ if (Configuration_p->ReseedThr == 0)
+ {
+ Conf.ReseedThr = ADAPTER_EIP74_RESEED_THR;
+ }
+ else
+ {
+ Conf.ReseedThr = Configuration_p->ReseedThr;
+ }
+
+ if (Configuration_p->ReseedThrEarly == 0)
+ {
+ Conf.ReseedThrEarly = ADAPTER_EIP74_RESEED_THR_EARLY;
+ }
+ else
+ {
+ Conf.ReseedThrEarly = Configuration_p->ReseedThrEarly;
+ }
+
+ Rc = EIP74_Configure(&EIP74State.IOArea, &Conf);
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 could not be configured\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+
+ GlobalControl74Lib_CopyKeyMat(Entropy, Entropy_p, 48);
+
+ Rc = EIP74_Instantiate(&EIP74State.IOArea, Entropy, Configuration_p->fStuckOut);
+
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 could not be instantiated\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74_Capabilities_Get
+ */
+void
+GlobalControl74_Capabilities_Get(
+ GlobalControl74_Capabilities_t * const Capabilities_p)
+{
+ Device_Handle_t Device;
+ uint8_t Versions[3];
+ LOG_INFO("\n\t\t\t GlobalControl74_Capabilities_Get\n");
+
+ memcpy(Capabilities_p, &Global_CapabilitiesString,
+ sizeof(Global_CapabilitiesString));
+
+ Device = Device_Find(ADAPTER_EIP74_DEVICE_NAME);
+ if (Device == NULL)
+ {
+ LOG_CRIT("%s EIP74 Device not found\n",__func__);
+ return;
+ }
+
+ {
+ EIP74_Capabilities_t Capabilities;
+ EIP74_Error_t Rc;
+
+ if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_SYNC) != RPM_SUCCESS)
+ return;
+
+ Rc = EIP74_HWRevision_Get(Device, &Capabilities);
+
+ (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_ASYNC);
+
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74_Capaboilities_Get() failed\n",__func__);
+ return;
+ }
+
+ Log_FormattedMessage(
+ "EIP74 options: Nof Clients=%u Nof AESCores=%u\n"
+ "\t\tAESSpeed=%u FIFODepth=%u\n",
+ Capabilities.HW_Options.ClientCount,
+ Capabilities.HW_Options.AESCoreCount,
+ Capabilities.HW_Options.AESSpeed,
+ Capabilities.HW_Options.FIFODepth);
+
+
+ Versions[0] = Capabilities.HW_Revision.MajHWRevision;
+ Versions[1] = Capabilities.HW_Revision.MinHWRevision;
+ Versions[2] = Capabilities.HW_Revision.HWPatchLevel;
+ }
+
+ {
+ char * p = Capabilities_p->szTextDescription;
+ int VerIndex = 0;
+ int i = 0;
+
+ while(p[i])
+ {
+ if (p[i] == '_' && VerIndex < 3)
+ {
+ if (Versions[VerIndex] > 9)
+ p[i] = '?';
+ else
+ p[i] = '0' + Versions[VerIndex];
+
+ VerIndex++;
+ }
+
+ i++;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74_Init
+ */
+GlobalControl74_Error_t
+GlobalControl74_Init(
+ const GlobalControl74_Configuration_t * const Configuration_p,
+ const uint8_t * const Entropy_p)
+{
+ EIP74_Error_t Rc;
+ Device_Handle_t Device;
+
+ LOG_INFO("\n\t\t\t GlobalControl74_Init\n");
+
+ Device = Device_Find(ADAPTER_EIP74_DEVICE_NAME);
+ if (Device == NULL)
+ {
+ LOG_CRIT("%s EIP74 Device not found\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_NOT_IMPLEMENTED;
+ }
+
+
+ Rc = EIP74_Init(&EIP74State.IOArea, Device);
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 could not be initialized\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (RPM_DEVICE_INIT_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ GlobalControl74Lib_Suspend,
+ GlobalControl74Lib_Resume) != RPM_SUCCESS)
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+
+ if (GlobalControl74Lib_Init(Configuration_p,Entropy_p) !=
+ GLOBAL_CONTROL_EIP74_NO_ERROR)
+ {
+ (void)RPM_DEVICE_INIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
+
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+
+
+#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
+ EIP74State.fInitialized = true;
+ EIP74State.CachedConfig = *Configuration_p;
+#endif
+ (void)RPM_DEVICE_INIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
+
+
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ Adapter_Interrupt_SetHandler(ADAPTER_EIP74_ERR_IRQ,
+ GlobalControl74_InterruptHandlerNotify);
+ Adapter_Interrupt_SetHandler(ADAPTER_EIP74_RES_IRQ,
+ GlobalControl74_InterruptHandlerNotify);
+#endif
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74_UnInit
+ */
+GlobalControl74_Error_t
+GlobalControl74_UnInit(void)
+{
+ EIP74_Error_t Rc;
+ unsigned LoopCounter = ADAPTER_EIP74_RESET_MAX_RETRIES;
+
+ LOG_INFO("\n\t\t\t GlobalControl74_UnInit\n");
+
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ Adapter_Interrupt_SetHandler(ADAPTER_EIP74_ERR_IRQ, NULL);
+ Adapter_Interrupt_SetHandler(ADAPTER_EIP74_RES_IRQ, NULL);
+ Adapter_Interrupt_Disable(ADAPTER_EIP74_ERR_IRQ, 0);
+ Adapter_Interrupt_Disable(ADAPTER_EIP74_RES_IRQ, 0);
+#endif
+ (void)RPM_DEVICE_UNINIT_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID, false);
+
+ Rc = EIP74_Reset(&EIP74State.IOArea);
+ do
+ {
+ if (Rc == EIP74_BUSY_RETRY_LATER)
+ {
+ LoopCounter--;
+ if (LoopCounter == 0)
+ {
+ LOG_CRIT("%s EIP74 reset timed out\n",__func__);
+ (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+ Rc = EIP74_Reset_IsDone(&EIP74State.IOArea);
+ }
+ else if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 reset error\n",__func__);
+ (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
+
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+ } while (Rc != EIP74_NO_ERROR);
+ (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
+
+#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
+ EIP74State.fInitialized = false;
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+ EIP74State.fInterruptEnabled = false;
+#endif
+#endif
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74_Reseed
+ */
+GlobalControl74_Error_t
+GlobalControl74_Reseed(
+ const uint8_t * const Entropy_p)
+{
+ EIP74_Error_t Rc;
+ uint32_t Entropy[12];
+ LOG_INFO("\n\t\t\t GlobalControl74_Reseed\n");
+
+
+ GlobalControl74Lib_CopyKeyMat(Entropy, Entropy_p, 48);
+
+ if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_SYNC) != RPM_SUCCESS)
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+
+ Rc = EIP74_Reseed(&EIP74State.IOArea, Entropy);
+
+ (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_ASYNC);
+
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 could not be reseeded\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74_Status_Get
+ */
+GlobalControl74_Error_t
+GlobalControl74_Status_Get(
+ GlobalControl74_Status_t * const Status_p)
+{
+ EIP74_Error_t Rc;
+ EIP74_Status_t Status;
+ LOG_INFO("\n\t\t\t GlobalControl74_Status_Get\n");
+
+ if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_SYNC) != RPM_SUCCESS)
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+
+ Rc = EIP74_Status_Get(&EIP74State.IOArea, &Status);
+
+ (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_ASYNC);
+
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 status could not be read\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+
+ Status_p->GenerateBlockCount = Status.GenerateBlockCount;
+ Status_p->fStuckOut = Status.fStuckOut;
+ Status_p->fNotInitialized = Status.fNotInitialized;
+ Status_p->fReseedError = Status.fReseedError;
+ Status_p->fReseedWarning = Status.fReseedWarning;
+ Status_p->fInstantiated = Status.fInstantiated;
+ Status_p->AvailableCount = Status.AvailableCount;
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+
+/*----------------------------------------------------------------------------
+ * GlobalControl74_Clear
+ */
+GlobalControl74_Error_t
+GlobalControl74_Clear(void)
+{
+ EIP74_Error_t Rc;
+ LOG_INFO("\n\t\t\t GlobalControl74_Clear\n");
+
+ if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_SYNC) != RPM_SUCCESS)
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+
+ Rc = EIP74_Clear(&EIP74State.IOArea);
+
+ (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
+ RPM_FLAG_ASYNC);
+
+ if (Rc != EIP74_NO_ERROR)
+ {
+ LOG_CRIT("%s EIP74 could not be cleared\n",__func__);
+ return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
+ }
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+
+
+#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
+/*----------------------------------------------------------------------------
+ * GlobalControl74_Notify_Request
+ */
+GlobalControl74_Error_t
+GlobalControl74_Notify_Request(
+ GlobalControl74_NotifyFunction_t CBFunc_p)
+{
+ LOG_INFO("\n\t\t\t GlobalControl74_Notify_Request\n");
+ IDENTIFIER_NOT_USED(CBFunc_p);
+
+ EIP74State.Notify_CBFunc = CBFunc_p;
+ if (CBFunc_p != NULL)
+ {
+ Adapter_Interrupt_Enable(ADAPTER_EIP74_ERR_IRQ, 0);
+ Adapter_Interrupt_Enable(ADAPTER_EIP74_RES_IRQ, 0);
+#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
+ EIP74State.fInterruptEnabled = true;
+#endif
+ }
+
+ return GLOBAL_CONTROL_EIP74_NO_ERROR;
+}
+#endif
+
+
+/* end of file adapter_global_eip74.c */