ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/services/dxslic/api_lib/src/dxs_access.c b/marvell/services/dxslic/api_lib/src/dxs_access.c
new file mode 100644
index 0000000..d17d4ea
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_access.c
@@ -0,0 +1,577 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_access.c
+   Implementation of low level access functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdio.h>
+#include <semaphore.h>
+
+#include "dxs_lib.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_spi.h"
+#include "dxs_access.h"
+#include "dxs_init.h"
+#ifdef EVENT_LOGGER_DEBUG
+#include <sys/ioctl.h>
+#endif
+
+#include "dxslic_spi.h"
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/* SPI header length in bytes */
+#define DXS_SPI_HDR_LENGTH    2  /* in bytes */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+#if 0
+//debug
+static int32_t dxs_spi_write(
+                        int fd,
+                        uint8_t offset,
+                        uint16_t *pbuf,
+                        uint32_t len);
+
+static int32_t dxs_spi_read(
+                        int fd,
+                        uint8_t offset,
+                        uint16_t *pbuf,
+                        uint32_t len);
+
+#endif
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+#ifdef EVENT_LOGGER_DEBUG
+static void dxs_el_trace_reg_wr(DXS_DEVICE_t *pDev,
+                                int32_t reg_offset,
+                                uint16_t *reg_data,
+                                int32_t data_count)
+{
+   EL_IoctlAddLog_t stLog;
+   stLog.nLogType = EL_LOG_TYPE_REG_WR;
+   stLog.nOrygLogType = EL_MAX_LOG_TYPE;
+   stLog.nDevType = DXS_LIB_DEV_TYPE;
+   stLog.nDevNum = pDev->nDevNum;
+   stLog.nChNum = 0;
+   stLog.uLogDetails.stReg_Wr.nReg_offset = (reg_offset);
+   stLog.uLogDetails.stReg_Wr.pReg_data = (uint8_t  *)(reg_data);
+   stLog.uLogDetails.stReg_Wr.nDataLength = (data_count);
+   stLog.uLogDetails.stReg_Wr.nCount = (data_count);
+   ioctl(pDev->el_fd, EL_ADD_LOG, (int32_t)&stLog);
+}
+
+static void dxs_el_trace_reg_rd(DXS_DEVICE_t *pDev,
+                                int32_t reg_offset,
+                                uint16_t  *reg_data,
+                                int32_t data_count)
+{
+   EL_IoctlAddLog_t stLog;
+   stLog.nLogType = EL_LOG_TYPE_REG_RD;
+   stLog.nOrygLogType = EL_MAX_LOG_TYPE;
+   stLog.nDevType = DXS_LIB_DEV_TYPE;
+   stLog.nDevNum = pDev->nDevNum;
+   stLog.nChNum = 0;
+   stLog.uLogDetails.stReg_Rd.nReg_offset = (reg_offset);
+   stLog.uLogDetails.stReg_Rd.pReg_data = (uint8_t  *)(reg_data);
+   stLog.uLogDetails.stReg_Rd.nDataLength = (data_count);
+   stLog.uLogDetails.stReg_Rd.nCount = (data_count);
+   ioctl(pDev->el_fd, EL_ADD_LOG, (int32_t)&stLog);
+}
+#endif
+
+static uint32_t dxs_spi_max_frag_size_get()
+{
+   DXS_DEVICE_t *pDev = dxs_get_dev(0);
+
+   return (pDev->access == DXS_ACCESS_CSI) ?
+             SPI_MAX_BUFF_SIZE_CSI : SPI_MAXBYTES_SIZE;
+}
+
+/**
+   Write a value to one chip register.
+
+   \param  pDev         Pointer to device struct.
+   \param  offset       Register offset (address).
+   \param  pValue       16-bit word value to write.
+
+   \return
+   Error code from dxs_spi_write().
+*/
+int32_t DXS_RegWrite(   DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t nValue)
+{
+   int32_t ret;
+
+   if (pDev->access == DXS_ACCESS_CSI)
+   {
+      uint16_t tmp[2];
+
+      tmp[0] = tmp[1] = nValue;
+      ret = dxs_spi_write(pDev->spidev, offset, tmp, sizeof(tmp));
+   }
+   else
+   {
+      uint16_t tmp = nValue;
+
+      ret = dxs_spi_write(pDev->spidev, offset, &tmp, 2);
+   }
+
+#ifdef EVENT_LOGGER_DEBUG
+   dxs_el_trace_reg_wr(pDev, offset, &nValue, 2);
+#endif
+
+   /* fprintf (stderr, "[rw] %02X: %04X\n", offset, tmp); */
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Read a value from one chip register.
+
+   \param  pDev         Pointer to device struct.
+   \param  offset       Register offset (address).
+   \param  pValue       Pointer to variable where to return
+                        the 16-bit word value.
+
+   \return
+   Error code from dxs_spi_read().
+*/
+int32_t DXS_RegRead(    DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue)
+{
+   int32_t ret;
+
+   if (pDev->access == DXS_ACCESS_CSI)
+   {
+      uint16_t tmp[2];
+
+      ret = dxs_spi_read(pDev->spidev, offset, tmp, sizeof(tmp));
+      *pValue = tmp[1];
+   }
+   else
+   {
+      ret = dxs_spi_read(pDev->spidev, offset, pValue, 2);
+   }
+
+#ifdef EVENT_LOGGER_DEBUG
+    dxs_el_trace_reg_rd(pDev, offset, pValue, 2);
+#endif
+
+   /* fprintf (stderr, "[rr] %02X: %04X\n", offset, *pValue); */
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Write multiple consecutive chip registers.
+
+   \param  pDev         Pointer to device struct.
+   \param  offset       Register offset (address).
+   \param  pValue       Pointer to array with 16-bit word values to write.
+   \param  count        Number of 16-bit words to write.
+
+   \return
+   Error code from dxs_spi_write().
+*/
+int32_t DXS_RegWriteMulti(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *nValue,
+                        uint8_t count)
+{
+   int32_t ret;
+
+   ret = dxs_spi_write(pDev->spidev, offset, nValue, (2*count));
+
+#ifdef EVENT_LOGGER_DEBUG
+   dxs_el_trace_reg_wr(pDev, offset, nValue, (2*count));
+#endif
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Read multiple consecutive chip registers.
+
+   \param  pDev         Pointer to device struct.
+   \param  offset       Register offset (address).
+   \param  pValue       Pointer to array where to return the 16-bit word values.
+   \param  count        Number of 16-bit words to read.
+
+   \return
+   Error code from dxs_spi_read().
+*/
+int32_t DXS_RegReadMulti(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue,
+                        uint8_t count)
+{
+   int32_t ret;
+
+   ret = dxs_spi_read(pDev->spidev, offset, pValue, (2*count));
+
+#ifdef EVENT_LOGGER_DEBUG
+    dxs_el_trace_reg_rd(pDev, offset, pValue, (2*count));
+#endif
+
+   DXS_RETURN(ret);
+}
+
+
+/* ************************ endianess correct copy ****************************/
+
+/**
+   Copy a 16-bit-word buffer into a byte buffer respecting the endianess.
+
+   Odd and even offsets and length are handled by this function.
+   In place copy is possible but otherwise the buffers must not overlap.
+
+   \param  pBbuf        Pointer to byte buffer. (Destination)
+   \param  pWbuf        Pointer to 16-bit-word buffer. (Source)
+   \param  nWoffset     Offset in bytes within the source buffer.
+   \param  nB           Number of bytes to be copied.
+*/
+void DXS_cpw2b (        uint8_t *pBbuf,
+                        const uint16_t * const pWbuf,
+                        const uint32_t nWoffset,
+                        const uint32_t nB)
+{
+   uint32_t i;
+   uint16_t nWord;
+
+   for (i = 0; i < nB; i++)
+   {
+      nWord = pWbuf[(nWoffset + i) >> 1];
+      pBbuf[i] = (uint8_t)
+                 ((((nWoffset+i) % 2) ? nWord : nWord >> 8) & 0xFF);
+   }
+}
+
+/**
+   Copy a byte buffer into a 16-bit-word buffer respecting the endianness.
+
+   In place copy is possible but otherwise the buffers must not overlap.
+   When an odd number of bytes is to be copied the missing byte in the
+   16-bit-word is filled with zero.
+
+   \param  pWbuf        Word buffer.
+   \param  pBbuf        Byte buffer.
+   \param  nB           Number of Bytes to be copied.
+*/
+void DXS_cpb2w (        uint16_t *pWbuf,
+                        const uint8_t * const pBbuf,
+                        uint32_t nB)
+{
+   uint32_t         i;
+   uint16_t         nWord;
+
+   for (i=0; i < nB; i+=2)
+   {
+      /* Copy each byte separately into the word buffer. Make sure that when
+         an index out of range is addressed zero is copied instead. */
+      nWord  = (uint16_t)pBbuf[i+0] << 8;
+      if ((i+1) < nB)
+      {
+         /* LSB is only added when index is within range. */
+         nWord |= (uint16_t)pBbuf[i+1];
+      }
+      pWbuf[i>>1] = nWord;
+   }
+}
+
+
+/**
+   Copy a byte buffer into a 32-bit-word buffer respecting the endianness.
+
+   In place copy is possible but otherwise the buffers must not overlap.
+   When an odd number of bytes is to be copied the missing bytes in the
+   32-bit-word is filled with zero.
+
+   \param  pWbuf       Word buffer.
+   \param  pBbuf        Byte buffer.
+   \param  nB           Number of Bytes to be copied.
+*/
+void DXS_cpb2dw (       uint32_t *pWbuf,
+                        const uint8_t * const pBbuf,
+                        uint32_t nB)
+{
+   uint32_t         i;
+   uint32_t         nWord;
+
+   for (i=0; i < nB; i+=4)
+   {
+      /* Copy each byte separately into the word buffer. Make sure that when
+         an index out of range is addressed zero is copied instead. */
+      nWord  = (uint32_t)pBbuf[i+0] << 24;
+      if ((i+1) < nB)
+         nWord |= (uint32_t)pBbuf[i+1] << 16;
+      if ((i+2) < nB)
+         nWord |= (uint32_t)pBbuf[i+2] << 8;
+      if ((i+3) < nB)
+         nWord |= (uint32_t)pBbuf[i+3];
+      pWbuf[i>>2] = nWord;
+   }
+}
+
+/***************************** SPI bus adaption ******************************/
+
+/**
+   Write a number of bytes to a given DXS register using SPI.
+
+   If the length of the data exceeds the SPI_MAXBYTES_SIZE this function
+   fragments the data into multiple blocks and calls the SPI write interface
+   repeatedly until all data is transmitted.
+
+   \param  fd           Filedescriptor of the SPI driver.
+   \param  offset       DXS register address.
+   \param  pbuf         Pointer to buffer with data to be written.
+   \param  len          Number of bytes to write.
+
+   \return
+   DXS_statusOk or error code.
+*/
+int32_t dxs_spi_write(int fd, uint8_t offset, uint16_t *pbuf, uint32_t len)
+{
+   uint8_t   tx_buf[SPI_MAXBYTES_SIZE];
+   uint32_t  tx_buf_length,
+             written,
+             fragment_length;
+   int32_t   ret = DXS_statusOk;
+
+   uint32_t  max_frag_sz = dxs_spi_max_frag_size_get();
+
+   /* TODO: len and offset assertion */
+   /* TODO: setup SPI */
+
+   /* This variable counts the number of bytes already written. */
+   written = 0;
+   /* Build SPI header (16-bit word) */
+#if SPI_IOC_WR_BITS_PER_WORD_8BITS
+   /* SPI_IOC_WR_BITS_PER_WORD is 8bits */
+   tx_buf[0] = 0x7E;
+   tx_buf[1] = offset;
+
+   if (offset == DXS_REG_CSI_M_CFG || offset == DXS_REG_CSI_M_STAT)
+   {
+      tx_buf[1] <<= 1;
+   }
+#else
+   /* SPI_IOC_WR_BITS_PER_WORD is 16bits */
+   tx_buf[0] = offset;
+   tx_buf[1] = 0x7E;
+
+   if (offset == DXS_REG_CSI_M_CFG || offset == DXS_REG_CSI_M_STAT)
+   {
+      tx_buf[0] <<= 1;
+   }
+#endif
+
+   /* The tx_buf now contains the SPI header. */
+   tx_buf_length = DXS_SPI_HDR_LENGTH;
+
+   while ((ret == DXS_statusOk) && (written < len))
+   {
+      /* Calculate the amount of payload bytes that can be sent during one
+         write call. */
+      fragment_length = len - written; /* remaining bytes to transfer */
+      if (fragment_length > (max_frag_sz - tx_buf_length))
+      {
+         /* Limit the transfer to the maximum the SPI can transmit. */
+         fragment_length = (max_frag_sz - tx_buf_length);
+      }
+#if SPI_IOC_WR_BITS_PER_WORD_8BITS
+      /* SPI_IOC_WR_BITS_PER_WORD is 8bits */
+
+      /* Copy the payload into the write buffer with correct endianess. */
+      DXS_cpw2b(tx_buf+tx_buf_length, pbuf, written, fragment_length);
+#else
+      /* SPI_IOC_WR_BITS_PER_WORD is 16bits */
+      memcpy(tx_buf+tx_buf_length, (uint8_t *)pbuf+written, fragment_length);
+#endif
+      /* Increment by the number of payload bytes written. */
+      tx_buf_length += fragment_length;
+      written += fragment_length;
+
+      /* Access SPI for writing (rx buffer is NULL). */
+      ret = dxs_spi_linux_read_write(fd, tx_buf, NULL, tx_buf_length);
+      /* ret is evaluated before the next iteration. */
+
+      /* Preserve and reuse the SPI header for the next fragment. */
+      tx_buf_length = DXS_SPI_HDR_LENGTH;
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Read a number of bytes from a given DXS register using SPI.
+
+   If the length of the data to be read exceeds the SPI_MAXBYTES_SIZE this
+   function calls the SPI read function repeatedly until all data is read
+   and reassembles the data in the return buffer.
+
+   \param  fd           Filedescriptor of the SPI driver.
+   \param  offset       DXS register address.
+   \param  pbuf         Pointer to buffer where to return the data.
+   \param  len          Number of bytes to be read.
+
+   \return
+   DXS_statusOk or error code.
+*/
+int32_t dxs_spi_read(int fd, uint8_t offset, uint16_t *pbuf, uint32_t len)
+{
+   uint8_t   tx_buf[SPI_MAXBYTES_SIZE] = {0},
+             rx_buf[SPI_MAXBYTES_SIZE] = {0};
+   uint32_t  tx_buf_length,
+             read,
+             fragment_length;
+   int32_t   ret = DXS_statusOk;
+
+   uint32_t  max_frag_sz = dxs_spi_max_frag_size_get();
+
+   /* TODO: len and offset assertion */
+   /* TODO: setup SPI */
+
+   /* tx_buf is the buffer for writing the read request. Because SPI in general
+      is full duplex the complete buffer is set to zero to avoid sending random
+      data after the SPI header that we set below. */
+   /* Build SPI header (16-bit word) */
+#if SPI_IOC_WR_BITS_PER_WORD_8BITS
+   /* SPI_IOC_WR_BITS_PER_WORD is 8bits */
+   tx_buf[0] = 0xBE;
+   tx_buf[1] = offset;
+
+   if (offset == DXS_REG_CSI_M_CFG || offset == DXS_REG_CSI_M_STAT)
+   {
+      tx_buf[1] <<= 1;
+   }
+#else
+   /* SPI_IOC_WR_BITS_PER_WORD is 16bits */
+   tx_buf[0] = offset;
+   tx_buf[1] = 0xBE;
+
+   if (offset == DXS_REG_CSI_M_CFG || offset == DXS_REG_CSI_M_STAT)
+   {
+      tx_buf[0] <<= 1;
+   }
+#endif
+
+   /* The tx_buf contains now the SPI header. */
+   tx_buf_length = DXS_SPI_HDR_LENGTH;
+
+   /* Loop while more data needs to be read. */
+   for (read = 0; (ret == DXS_statusOk) && (read < len); read += fragment_length)
+   {
+      /* Calculate the amount of payload bytes that can be read during one
+         read call. */
+      fragment_length = len - read; /* remaining bytes to read */
+      if (fragment_length > (max_frag_sz - tx_buf_length))
+      {
+         /* Limit the transfer to the maximum the SPI can transmit. */
+         fragment_length = (max_frag_sz - tx_buf_length);
+      }
+
+      /* Access SPI for writing and reading. */
+      ret = dxs_spi_linux_read_write(fd, tx_buf, rx_buf,
+                                     tx_buf_length + fragment_length);
+      if (ret == DXS_statusOk)
+      {
+#if SPI_IOC_WR_BITS_PER_WORD_8BITS
+         /* SPI_IOC_WR_BITS_PER_WORD is 8bits */
+
+         /* Copy the byte buffer into the 16-bit-word buffer respecting
+            the endianess. */
+         DXS_cpb2w (pbuf + (read/2),
+                    rx_buf + DXS_SPI_HDR_LENGTH, fragment_length);
+#else
+         /* SPI_IOC_WR_BITS_PER_WORD is 16bits */
+         memcpy((uint8_t *)pbuf+read, rx_buf + DXS_SPI_HDR_LENGTH, fragment_length);
+#endif
+      }
+
+      /* ret is evaluated before the next iteration. */
+   }
+
+   DXS_RETURN(ret);
+}
+
+
+/**
+   Return the number of payload bytes that can be transferred over SPI
+   without being fragmented into multiple SPI transfers.
+
+   \return
+   Maximum number of bytes for a single SPI transfer.
+*/
+uint32_t DXS_spi_blocksize_get(DXS_DEVICE_t *pDev)
+{
+   return (pDev->access == DXS_ACCESS_CSI) ?
+            (SPI_MAX_BUFF_SIZE_CSI - DXS_SPI_HDR_LENGTH) :
+            (SPI_MAXBYTES_SIZE - DXS_SPI_HDR_LENGTH);
+}
+
+/**
+   Get device interrupt status.
+
+   \return
+      none
+*/
+void DXS_StatusGet(DXS_DEVICE_t *pDev)
+{
+   uint16_t nRegInt1 = 0, nRegInt2 = 0;
+
+   if (pDev->flags & DXS_DEV_ACCESS_INITIALIZED)
+   {
+      DXS_RegRead(pDev, DXS_REG_INT1, &nRegInt1);
+      if (nRegInt1 & DXS_REG_INT1_ERR)
+      {
+         DXS_RegRead(pDev, DXS_REG_INT2, &nRegInt2);
+         if (nRegInt2 & DXS_REG_INT2_CBO_UFL)
+         {
+            fprintf (stderr, "Out-Box Underflow, dev%d\n", pDev->nDevNum);
+            /* acknowledge the interrupt */
+            DXS_RegWrite(pDev, DXS_REG_INT2, nRegInt2);
+         }
+         if (nRegInt2 & DXS_REG_INT2_CBI_OFL)
+         {
+            fprintf (stderr, "In-Box Overflow, dev%d\n", pDev->nDevNum);
+            /* acknowledge the interrupt */
+            DXS_RegWrite(pDev, DXS_REG_INT2, nRegInt2);
+         }
+      }
+
+      /* new data in the outbox */
+      if ((nRegInt1 & DXS_REG_INT1_CBO_RDY) &&
+          (pDev->flags & DXS_DEV_OBX_HND_INITIALIZED))
+         sem_post(&pDev->obxSemaphore);
+   }
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_access.h b/marvell/services/dxslic/api_lib/src/dxs_access.h
new file mode 100644
index 0000000..90854f3
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_access.h
@@ -0,0 +1,151 @@
+#ifndef __DXS_ACCESS_H__
+#define __DXS_ACCESS_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_access.h
+   Low level access macros and functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+#include <stdio.h>
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* Define the maximum number of bytes that the SPI interface can transfer with
+   one call to the interface.
+   This driver will fragment all data during read or write transfer into pieces
+   no larger than the value given here. To avoid overhead due to fragmentation
+   use the maximum value the SPI interface can support.
+   Possible values are calculated by (2+4*n) with n=1,2, ...
+   The minimum possible value is 6 bytes. There is no upper limit but values
+   larger than 34 bytes are never used by the DXS driver. */
+#define SPI_MAXBYTES_SIZE     30
+#define SPI_MAX_BUFF_SIZE_CSI 6
+
+#define DXS_REG_CFG       0x06
+#define DXS_REG_IEN1      0x08
+#define DXS_REG_STAT1     0x0C
+#define DXS_REG_INT1      0x10
+#define DXS_REG_IEN2      0x0A
+#define DXS_REG_STAT2     0x0E
+#define DXS_REG_INT2      0x12
+#define DXS_REG_DATA      0x14
+#define DXS_REG_LEN       0x18
+#define DXS_REG_CMD       0x1C
+#define DXS_REG_BCFG      0x20
+#define DXS_REG_BINF      0x24
+/* CSI Master registers */
+#define DXS_REG_CSI_M_CFG  0x30
+#define DXS_REG_CSI_M_STAT 0x31
+#define DXS_REG_CSI_M_CFG_PAUSE_DEFAULT   3
+#define DXS_REG_CSI_M_CFG_PDEMUX  (1 << 10)
+
+#define DXS_REG_CFG_RST_MASK        0x0080
+#define DXS_REG_CFG_RST_RSTCORE     (0x1 << 7)
+#define DXS_REG_CFG_8BIT_EN         (0x1 << 2)
+#define DXS_REG_CFG_SC_MD           (0x1 << 1)
+
+#define DXS_REG_BCFG_ASC_MASK       0x00FF
+#define DXS_REG_BCFG_ASC_ROM        0x0
+#define DXS_REG_BCFG_ASC_SPI        0x3
+
+#define DXS_REG_BINF_BOOTSTATE_MASK 0x00FF
+
+#define DXS_REG_INT1_ERR            1
+#define DXS_REG_INT1_CBO_RDY        (1 << 11)
+
+#define DXS_REG_INT2_CBO_UFL        (1 << 9)
+#define DXS_REG_INT2_CBI_OFL        (1 << 8)
+
+/*******************************************************************************
+ * HOST Interrupt Enable 1 Register
+ ******************************************************************************/
+/* Reset value */
+#define DXS_REG_IEN1_RESET          0x0000
+/* Out-Box Ready Interrupt (11) */
+#define DXS_REG_IEN1_OBX_RDY        (0x1 << 11)
+/* In-Box Empty Interrupt Mask (9) */
+#define DXS_REG_IEN1_IBX_EMP        (0x1 << 9)
+/* Error Interrupt Mask (0) */
+#define DXS_REG_IEN1_ERR            (0x1)
+
+/*******************************************************************************
+ * HOST Interrupt Enable 2 Register
+ ******************************************************************************/
+/* Reset value */
+#define DXS_REG_IEN2_RESET          0x0000
+/* Out-Box Underflow Interrupt (9) */
+#define DXS_REG_IEN2_OBX_UFL        (0x1 << 9)
+/* In-Box Overflow Interrupt (8) */
+#define DXS_REG_IEN2_IBX_OFL        (0x1 << 8)
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t DXS_RegWrite(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t nValue);
+
+extern int32_t DXS_RegRead(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue);
+
+extern int32_t DXS_RegWriteMulti(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *nValue,
+                        uint8_t count);
+
+extern int32_t DXS_RegReadMulti(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue,
+                        uint8_t count);
+
+extern void DXS_cpw2b ( uint8_t *pBbuf,
+                        const uint16_t * const pWbuf,
+                        const uint32_t nWoffset,
+                        const uint32_t nB);
+
+extern void DXS_cpb2w ( uint16_t *pWbuf,
+                        const uint8_t * const pBbuf,
+                        uint32_t nB);
+extern void DXS_cpb2dw ( uint32_t *pWbuf,
+                        const uint8_t * const pBbuf,
+                        uint32_t nB);
+extern uint32_t DXS_spi_blocksize_get(DXS_DEVICE_t *pDev);
+extern void DXS_StatusGet(DXS_DEVICE_t *pDev);
+
+extern int32_t dxs_spi_write(
+                        int fd,
+                        uint8_t offset,
+                        uint16_t *pbuf,
+                        uint32_t len);
+
+extern int32_t dxs_spi_read(
+                        int fd,
+                        uint8_t offset,
+                        uint16_t *pbuf,
+                        uint32_t len);
+#endif /* __DXS_ACCESS_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_api.c b/marvell/services/dxslic/api_lib/src/dxs_api.c
new file mode 100644
index 0000000..0b58fbd
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_api.c
@@ -0,0 +1,2056 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_api.c
+   This file contains the function prototypes specific to the DXS library
+   interface and is used by applications.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs.h"
+#include "dxs_init.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_config.h"
+#include "dxs_bbd.h"
+#include "dxs_wait.h"
+#include "dxs_sdd.h"
+#include "dxs_gpio.h"
+#include "dxs_cid.h"
+#include "dxs_pcm.h"
+#include "dxs_dwld.h"
+#include "dxs_sig.h"
+#include "dxs_debug_api.h"
+#include "dxs_event.h"
+#include "dxs_dcdc_hw.h"
+#include "dxs_ring.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_DEV_CTX_GET                               \
+   do {                                               \
+      pDev = dxs_get_dev(dxs);                        \
+      if (pDev == NULL) {                             \
+         DXS_ERROR_PUSH(DXS_statusDevNotFound);       \
+         return DXS_statusDevNotFound;                \
+      }                                               \
+   } while(0)
+
+#define DXS_DEV_INIT_VALIDATE                         \
+   do {                                               \
+      if (!(pDev->flags & DXS_DEV_INITIALIZED)) {     \
+         DXS_ERROR_PUSH(DXS_statusDevNotInitialized); \
+         return DXS_statusDevNotInitialized;          \
+      }                                               \
+   } while(0)
+
+#define DXS_CH_CTX_GET                                \
+   do {                                               \
+      if (line >= pDev->nChannels) {                  \
+         DXS_ERROR_PUSH(DXS_statusChannelNotFound);   \
+         return DXS_statusChannelNotFound;            \
+      }                                               \
+      pCh = &pDev->pChannel[line];                    \
+      if (pCh == NULL){                               \
+         DXS_ERROR_PUSH(DXS_statusChannelNotFound);   \
+         return DXS_statusChannelNotFound;            \
+      }                                               \
+   } while(0)
+
+#define DXS_API_EXIT(ret)                             \
+   do {                                               \
+      if (ret != DXS_statusOk) {                      \
+         DXS_ERROR_PUSH(ret);                         \
+      }                                               \
+      return ret;                                     \
+   } while(0)
+
+#define DXS_DEV_API_ENTRY     \
+   do {                       \
+      DXS_DEV_CTX_GET;        \
+      DXS_ERROR_RESET;        \
+      DXS_DEV_INIT_VALIDATE;  \
+   } while(0)
+
+#define DXS_CH_API_ENTRY      \
+   do {                       \
+      DXS_DEV_API_ENTRY;      \
+      DXS_CH_CTX_GET;         \
+   } while(0)
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+/**
+   DXS Device Init
+
+   \param dxs        - device number
+   \param chipSelect - CS number
+   \param irqNumber  - IRQ line number
+   \param dcdcType   - DCDC variant handled by DXS_DCDC_Var_t type
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsInit(uint8_t dxs, uint8_t chipSelect, int32_t irqNumber,
+                     uint8_t dcdcType, uint8_t acc_mode)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_CTX_GET;
+   DXS_ERROR_RESET;
+
+   ret = dxs_init(pDev, chipSelect, irqNumber, dcdcType, acc_mode, dxs);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS Device Exit
+
+   \param dxs        - device number
+
+   \return
+   - DXS_statusOk
+*/
+int32_t DxsExit(uint8_t dxs)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_exit(pDev);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS BBD Download
+
+   \param dxs     - channel number
+   \param pBbd    - pointer to BBD data
+   \param nBytes  - BBD data size
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsBBD(uint8_t dxs, uint8_t line, uint8_t *pBbd, uint32_t nBytes)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = dxs_bbd_download(pCh, pBbd, nBytes);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS PRAM Patch Download
+
+   \param dxs     - device number
+   \param pPatch  - pointer to PRAM patch data
+   \param nBytes  - PRAM patch data size
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsPatch(uint8_t dxs, uint8_t *pPatch, uint32_t nBytes)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = DXS_FW_Select(pDev, pPatch, nBytes);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS Firmware Capabilities Read
+
+   \param dxs   - device number
+   \param pCap  - pointer to DXS_Caps_t structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsCapabilitiesRead(uint8_t dxs, DXS_Caps_t *pCap)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_caps_read(pDev, pCap);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS Version Read
+
+   \param dxs      - device number
+   \param pVersion - pointer to DXS_Version_t structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsVersionRead(uint8_t dxs, DXS_Version_t *pVersion)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_vers_read(pDev, pVersion);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS Sleep Mode Enable
+
+   \param dxs   - device number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsSleepEnable(uint8_t dxs)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_sleep(pDev, 1);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DXS Sleep Mode Disable
+
+   \param dxs   - device number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsSleepDisable(uint8_t dxs)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_sleep(pDev, 0);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   PCM Interface Enable
+
+   \param dxs  - device number
+   \param xoff - transmit bit offset
+   \param dbl  - double bit clock
+   \param xs   - transmit slope
+   \param rs   - receive slope
+   \param drv0 - bit 0 drive length
+   \param sh   - shift control
+   \param roff - receive bit offset
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsPcmInterfaceEnable(uint8_t dxs, uint8_t xoff, uint8_t dbl,
+                              uint8_t xs, uint8_t rs, uint8_t drv0,
+                              uint8_t sh, uint8_t roff)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_pcm_if_config(pDev, xoff, dbl, xs, rs, drv0, sh, roff);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   PCM Channel Enable
+
+   \param dxs   - device number
+   \param line  - line number
+   \param wb    - wideband
+   \param wbtsc - wideband PCM time slot configuration
+   \param codec - codec
+   \param xts   - transmit highway time slot
+   \param rts   - receive highway time slot
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsPcmChannelEnable(uint8_t dxs, uint8_t line, uint8_t wb, uint8_t wbtsc,
+                         uint8_t codec, uint8_t xts, uint8_t rts)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = dxs_pcm_ch_act(pCh, wb, wbtsc, codec, xts, rts);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   PCM Channel Disable
+
+   \param dxs   - device number
+   \param line  - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsPcmChannelDisable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = dxs_pcm_ch_deact(pCh);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   PCM Channel Mute in RX direction
+
+   \param dxs   - device number
+   \param line  - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsPcmChannelMute(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = dxs_pcm_ch_mute(pCh, 1);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   PCM Channel Unmute in RX direction
+
+   \param dxs   - device number
+   \param line  - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsPcmChannelUnmute(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = dxs_pcm_ch_mute(pCh, 0);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Ring configuration
+
+   \param   dxs         - device number
+   \param   line        - line number
+   \param   waveForm    - waveform type
+   \param   crestFactor - crest factor
+   \param   frequency   - frequency
+   \param   amplitude   - amplitude
+   \param   dcOffset    - DC offset
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsRingConfig(uint8_t dxs, uint8_t line, uint8_t waveForm,
+                      uint8_t crestFactor, uint8_t frequency,
+                      uint16_t amplitude, uint16_t dcOffset)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_RingConfigAPI(pCh, waveForm, crestFactor, frequency,
+                                amplitude, dcOffset);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Message Waiting Lamp configuration
+
+   \param   dxs     - device number
+   \param   line    - line number
+   \param   voltage - voltage
+   \param   thresh  - threshold
+   \param   slope   - slope
+   \param   onTime  - on-time
+   \param   offTime - off-time
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsMwlConfig(uint8_t dxs, uint8_t line, uint8_t voltage, uint8_t thresh,
+                     uint16_t slope, uint16_t onTime, uint16_t offTime)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_MwlConfigAPI(pCh, voltage, thresh, slope, onTime, offTime);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Digital gain configuration
+
+   \param   dxs     - device number
+   \param   line    - line number
+   \param   usg     - upstream relative level setting
+   \param   dsg     - downstream relative level setting
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGainsSet(uint8_t dxs, uint8_t line, int16_t TxGain, int16_t RxGain)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_GainSet(pCh, TxGain, RxGain);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Digital gain readback
+
+   \param   dxs     - device number
+   \param   line    - line number
+   \param   pusg    - pointer to upstream relative level setting
+   \param   pdsg    - pointer to downstream relative level setting
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGainsGet(uint8_t dxs, uint8_t line, int16_t *pTxGain, int16_t *pRxGain)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_GainGet(pCh, pTxGain, pRxGain);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Line feeding mode set
+
+   \param   dxs     - device number
+   \param   line    - line number
+   \param   mode    - line feeding mode
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsLineModeSet(uint8_t dxs, uint8_t line, int mode)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   /* We need to signal that calibration was started by API */
+   if (mode == DXS_LINE_FEED_CALIBRATE)
+      (void) DXS_SDD_CalibrationInternalSet(pCh, 0);
+   ret = DXS_SDD_LineModeSet(pCh, mode);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Line feeding mode read
+
+   \param   dxs     - device number
+   \param   line    - line number
+   \param   pMode   - pointer to line feeding mode
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsLineModeGet(uint8_t dxs, uint8_t line, int *pMode)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_LineModeGet(pCh, pMode);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Read from DXS internal register
+      (requires --enable-debug-api)
+
+   \param   dxs     - device number
+   \param   offset  - register offset
+   \param   pValue  - pointer to value returned
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDebugRegRead16(uint8_t dxs, uint8_t offset, uint16_t *pValue)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   ret = dxs_reg_read (pDev, offset, pValue, 1);
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Write into DXS internal register
+      (requires --enable-debug-api)
+
+   \param   dxs     - device number
+   \param   offset  - register offset
+   \param   value   - value
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDebugRegWrite16(uint8_t dxs, uint8_t offset, uint16_t value)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+   uint16_t temp_value = value;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   ret = dxs_reg_write (pDev, offset, &temp_value, 1);
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Read from DXS internal register
+      (requires --enable-debug-api)
+
+   \param   dxs     - device number
+   \param   offset  - register offset
+   \param   pValue  - pointer to value returned
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDebugRegRead32(uint8_t dxs, uint8_t offset, uint32_t *pValue)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   ret = dxs_reg_read (pDev, offset, (uint16_t *)pValue, 2);
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Write into DXS internal register
+      (requires --enable-debug-api)
+
+   \param   dxs     - device number
+   \param   offset  - register offset
+   \param   value   - value
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDebugRegWrite32(uint8_t dxs, uint8_t offset, uint32_t value)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+   uint32_t temp_value = value;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   ret = dxs_reg_write (pDev, offset, (uint16_t *)&temp_value, 2);
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Read DXS firmware command
+      (requires --enable-debug-api)
+
+   \param   dxs     - device number
+   \param   hdr     - command header
+   \param   pLength - length of data
+   \param   pData   - pointer to read data into
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDebugCmdRead(uint8_t dxs, uint32_t hdr,
+                        uint8_t *pLength, uint32_t *pData)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   ret = dxs_cmd_read (pDev, hdr, pData, pLength);
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Write DXS firmware command
+      (requires --enable-debug-api)
+
+   \param   dxs    - device number
+   \param   length - the length of buffer
+   \param   pCmd   - pointer to buffer with command
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDebugCmdWrite(uint8_t dxs, uint8_t length, uint32_t *pCmd)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   ret = dxs_cmd_write (pDev, pCmd, length);
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+
+#if 0
+/*
+ * DxsDebugBBDGet()
+ *    requires --enable-debug-api
+ */
+int32_t DxsDebugBBDGet(uint8_t dxs, int nBuffer, uchar *pBbd, int *nByte)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_DEBUG_API
+   /* TODO: ret = dxs_bbd_get (pDev, pCmd, length); */
+#endif /* DXS_FEAT_DEBUG_API */
+
+   DXS_API_EXIT(ret);
+}
+#endif
+
+/**
+   Tone Configuration
+      (requires --enable-tg)
+
+   \param   dxs         - device number
+   \param   line        - line number
+   \param   level1      - level for frequency 1
+   \param   level2      - level for frequency 2
+   \param   freq1       - tone frequency 1
+   \param   freq2       - tone frequency 2
+   \param   amModulated - amplitude modulation flag
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsToneConfig(uint8_t dxs, uint8_t line, int16_t level1,
+                      int16_t level2, uint16_t freq1, uint16_t freq2,
+                      uint8_t amModulated)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_TG
+   ret = dxs_tone_config(pCh, level1, level2, freq1, freq2, amModulated, 1);
+#endif /* DXS_FEAT_TG */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Tone Playout Enable
+      (requires --enable-tg)
+
+   \param   dxs         - device number
+   \param   line        - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsToneEnable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_TG
+   ret = dxs_tone_start(pCh);
+#endif /* DXS_FEAT_TG */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Tone Playout Disable
+      (requires --enable-tg)
+
+   \param   dxs         - device number
+   \param   line        - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsToneDisable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_TG
+   ret = dxs_tone_stop(pCh);
+#endif /* DXS_FEAT_TG */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   CID Generator Coefficients update
+      (requires --enable-fsk)
+
+   \param   dxs       - device number
+   \param   line      - line number
+   \param   level     - CID send level
+   \param   seizure   - number of seizure bytes
+   \param   mark      - number of mark bits
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsFskConfig(uint8_t dxs, uint8_t line, int16_t level,
+                     uint16_t seizure, uint16_t mark)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_FSK
+   ret = DXS_FSK_Configure(pCh, level, seizure, mark);
+#endif /* DXS_FEAT_FSK */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   CID Generator Enable
+      (requires --enable-fsk)
+
+   \param   dxs         - device number
+   \param   line        - line number
+   \param   standard    - CID standard
+   \param   autodeact   - auto deactivation
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsFskEnable(uint8_t dxs, uint8_t line, uint8_t standard, uint8_t autodeact)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_FSK
+   ret = DXS_FSK_Enable(pCh, standard, autodeact);
+#endif /* DXS_FEAT_FSK */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   CID Generator Disable
+      (requires --enable-fsk)
+
+   \param   dxs         - device number
+   \param   line        - line number
+   \param   autodeact   - auto deactivation
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsFskDisable(uint8_t dxs, uint8_t line, uint8_t autodeact)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_FSK
+   ret = DXS_FSK_Disable(pCh, autodeact);
+#endif /* DXS_FEAT_FSK */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Send new data to the CID sender
+      (requires --enable-fsk)
+
+   \param   dxs        - device number
+   \param   line       - line number
+   \param   nByte      - data buffer size
+   \param   pByte      - pointer to data buffer
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsFskData(uint8_t dxs, uint8_t line, uint8_t nByte, uint8_t *pByte)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_FSK
+   ret = DXS_FSK_Data(pCh, nByte, pByte);
+#endif /* DXS_FEAT_FSK */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Enable UTD
+      (requires --enable-utd)
+
+   \param   dxs        - device number
+   \param   line       - line number
+   \param   tone_idx   - tone index
+   \param   direction  - detection direction
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsUtdEnable(uint8_t dxs, uint8_t line, uint16_t tone_idx,
+                     int direction)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+#ifdef DXS_FEAT_UTD
+   ret = DXS_SIG_UtdEnable(pCh, tone_idx, direction);
+#endif /* DXS_FEAT_UTD */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Disable UTD
+      (requires --enable-utd)
+
+   \param   dxs        - device number
+   \param   line       - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsUtdDisable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_UTD
+   ret = DXS_SIG_UtdDisable(pCh);
+#endif /* DXS_FEAT_UTD */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DTMF Receiver Coefficients
+      (requires --enable-dtmfd)
+
+   \param   dxs        - device number
+   \param   line       - line number
+   \param   level      - minimum signal level
+   \param   twist      - maximum allowed twist
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDtmfConfig(uint8_t dxs, uint8_t line, int16_t level, int16_t twist)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_DTMFD
+   ret = dxs_dtmf_config(pCh, level, twist);
+#endif /* DXS_FEAT_DTMFD */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DTMF Receiver Enable
+      (requires --enable-dtmfd)
+
+   \param   dxs        - device number
+   \param   line       - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDtmfEnable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_DTMFD
+   ret = dxs_dtmf_enable(pCh, 1);
+#endif /* DXS_FEAT_DTMFD */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   DTMF Receiver Disable
+      (requires --enable-dtmfd)
+
+   \param   dxs        - device number
+   \param   line       - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsDtmfDisable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_DTMFD
+   ret = dxs_dtmf_enable(pCh, 0);
+#endif /* DXS_FEAT_DTMFD */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Set GR-909 limits
+      (requires --enable-gr909)
+
+   \param   dxs        - device number
+   \param   line       - line number
+   \param   pGR909Conf - pointer to SDD GR909 configuration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGr909LimitsSet(uint8_t dxs, uint8_t line,
+                                                  DXS_GR909Config_t *pGR909Conf)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_GR909
+   ret = DXS_SDD_GR909LimitsSet(pCh, pGR909Conf);
+#endif /* DXS_FEAT_GR909 */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Get GR-909 limits
+      (requires --enable-gr909)
+
+   \param   dxs        - device number
+   \param   line       - line number
+   \param   pGR909Conf - pointer to SDD GR909 configuration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGr909LimitsGet(uint8_t dxs, uint8_t line,
+                                                  DXS_GR909Config_t *pGR909Conf)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_GR909
+   ret = DXS_SDD_GR909LimitsGet(pCh, pGR909Conf);
+#endif /* DXS_FEAT_GR909 */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Get GR-909 results
+      (requires --enable-gr909)
+
+   \param   dxs          - device number
+   \param   line         - line number
+   \param   pGR909Result - pointer to SDD GR909 result structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGr909ResultGet(uint8_t dxs, uint8_t line,
+                                                DXS_GR909Result_t *pGR909Result)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_GR909
+   ret = DXS_SDD_GR909ResultGet(pCh, pGR909Result);
+#endif /* DXS_FEAT_GR909 */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   GPIO port configuration
+      (requires --enable-gpio)
+
+   \param   dxs          - device number
+   \param   pGpioConf    - pointer to GPIO configuration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGpioPortConfig(uint8_t dxs, DXS_GpioConfig_t *pGpioConf)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_GPIO
+   ret = DXS_GPIO_Config(pDev, pGpioConf);
+#endif /* DXS_FEAT_GPIO */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   GPIO write
+      (requires --enable-gpio)
+
+   \param   dxs    - device number
+   \param   pin    - GPIO pin number
+   \param   val    - value
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGpioWrite(uint8_t dxs, uint8_t pin, uint8_t val)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_GPIO
+   ret = DXS_GPIO_Write(pDev, pin, val);
+#endif /* DXS_FEAT_GPIO */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   GPIO read
+      (requires --enable-gpio)
+
+   \param   dxs    - device number
+   \param   pin    - GPIO pin number
+   \param   *value - value
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsGpioRead(uint8_t dxs, uint8_t pin, uint8_t *value)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_DEV_API_ENTRY;
+
+#ifdef DXS_FEAT_GPIO
+   ret = DXS_GPIO_Read(pDev, pin, value);
+#endif /* DXS_FEAT_GPIO */
+
+   DXS_API_EXIT(ret);
+}
+
+
+/**
+   Read the results of calibration measurements.
+
+   \param   dxs          - device number
+   \param   line         - line number
+   \param   pCalibration - pointer to calibration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsCalibrationGet(uint8_t dxs, uint8_t line,
+   DXS_Calibration_t *pCalibration)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_CalibrationGet(pCh, pCalibration);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Write hardware configuration values.
+
+   \param   dxs          - device number
+   \param   line         - line number
+   \param   pCalibration - pointer to calibration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsCalibrationSet(uint8_t dxs, uint8_t line,
+   DXS_Calibration_t *pCalibration)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_CalibrationSet(pCh, pCalibration);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Sets the validation times for hook, pulse digit and flashhook.
+
+   \param   dxs          - device number
+   \param   line         - line number
+   \param   pTime        - type of validation setting, min and max time in
+                           milliseconds.
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsHookValTimeSet(uint8_t dxs, uint8_t line, DXS_HookValTime_t *pTime)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_HSM
+   ret = DXS_Dial_HookValTimeSet(pCh, pTime);
+#endif /* DXS_FEAT_HSM */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Get capacitance measurement result
+
+   \param   dxs          - device number
+   \param   line         - line number
+   \param   pCapacitance - pointer to capacitance measurement structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsCapMeasurementResultGet(uint8_t dxs, uint8_t line,
+                                                DXS_Capacitance_t *pCapacitance)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CAPMEAS
+   ret = DXS_SDD_CapMeasurementResultGet(pCh, 1, pCapacitance);
+#endif /* DXS_FEAT_CAPMEAS */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Get continuous measurements result
+
+   \param   dxs     - device number
+   \param   line    - line number
+   \param   pResult - pointer to continuous measurement structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsContMeasurementResultGet(uint8_t dxs, uint8_t line,
+                                  DXS_ContMeasurementResult_t *pResult)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_SDD_ContMeasurementResultGet(pCh, pResult);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Enable metering pulse. The pulse length can be programmed
+   with SDD_BasicConfig.
+      (requires --enable-metering)
+
+   \param   dxs     - device number
+   \param   line    - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsMeteringPulseEnable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_METERING
+   ret = DXS_SIG_MeterPulseEnable(pCh);
+#endif /* DXS_FEAT_METERING */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Disable metering pulse.
+      (requires --enable-metering)
+
+   \param   dxs     - device number
+   \param   line    - line number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsMeteringPulseDisable(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_METERING
+   ret = DXS_SIG_MeterPulseDisable(pCh);
+#endif /* DXS_FEAT_METERING */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Open Loop Calibration
+
+   \param   dxs                  - device number
+   \param   line                 - line number
+   \param   loops                - number of loops
+   \param   pOLCalibrationResult - pointer to Open Loop Calibration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsOpenLoopCalibration(uint8_t dxs, uint8_t line, uint8_t loops,
+                                      DXS_OLCalibration_t *pOLCalibrationResult)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+   ret = DXS_SDD_OLCalibration(pCh, loops, pOLCalibrationResult);
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to set the Open Loop Calibration configuration
+
+   \param   dxs             - device number
+   \param   line            - line number
+   \param   pOLCalibration  - pointer to Open Loop Calibration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsOpenLoopConfigSet(uint8_t dxs, uint8_t line,
+                                            DXS_OLCalibration_t *pOLCalibration)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+   ret = DXS_SDD_OLCalibrationConfigSet(pCh, pOLCalibration);
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to get the Open Loop Calibration configuration
+
+   \param   dxs             - device number
+   \param   line            - line number
+   \param   pOLCalibration  - pointer to Open Loop Calibration structure
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsOpenLoopConfigGet(uint8_t dxs, uint8_t line,
+                                            DXS_OLCalibration_t *pOLCalibration)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+   ret = DXS_SDD_OLCalibrationConfigGet(pCh, pOLCalibration);
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to start the ACLM measurement
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   aclm_mt  - ACLM measurment code
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsAcLmMeasurementStart(uint8_t dxs, uint8_t line,
+                                  DXS_ACLM_Measurement_t aclm_mt)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_ACMETER
+   ret = DXS_SDD_ACLM_Start(pCh, aclm_mt);
+#endif /* DXS_FEAT_ACMETER */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to retrieve the available ACLM measurement result number
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   aclm_mt  - ACLM measurment code
+   \param   pResNum  - ACLM result number (output)
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsAcLmMeasResNumGet(uint8_t dxs, uint8_t line,
+                                DXS_ACLM_Measurement_t aclm_mt,
+                                int32_t *pResNum)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_ACMETER
+   ret = DXS_SDD_ACLM_ResultGet(pCh,
+               aclm_mt, DXS_ACLM_RESULT_NUMBER, 0, pResNum);
+#endif /* DXS_FEAT_ACMETER */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to retrieve the argument of particular ACLM measurement index
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   aclm_mt  - ACLM measurment code
+   \param   index    - ACLM measurment index
+   \param   pResArg  - ACLM result argument (output)
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsAcLmMeasResArgGet(uint8_t dxs, uint8_t line,
+                           DXS_ACLM_Measurement_t aclm_mt,
+                           int32_t index, int32_t *pResArg)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_ACMETER
+   ret = DXS_SDD_ACLM_ResultGet(pCh,
+              aclm_mt, DXS_ACLM_RESULT_ARG, index, pResArg);
+#endif /* DXS_FEAT_ACMETER */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to retrieve the result value of particular ACLM measurement index
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   aclm_mt  - ACLM measurment code
+   \param   index    - ACLM measurment index
+   \param   pResArg  - ACLM result argument (output)
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsAcLmMeasResValGet(uint8_t dxs, uint8_t line,
+                             DXS_ACLM_Measurement_t aclm_mt,
+                             int32_t index, int32_t *pResVal)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_ACMETER
+   ret = DXS_SDD_ACLM_ResultGet(pCh,
+               aclm_mt, DXS_ACLM_RESULT_VALUE, index, pResVal);
+#endif /* DXS_FEAT_ACMETER */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to initialize CID interface for a channel
+
+   \param   dxs               - device number
+   \param   line              - line number
+   \param   std               - CID standard
+   \param   as                - CID alert signal
+   \param   fmt               - CID data format
+   \param   dtmf_ack_idx      - DTMF index for acknowledgment (type2)
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidInit (uint8_t dxs, uint8_t line, DXS_CID_Std_t std,
+                  DXS_CID_AS_t as, DXS_CID_DATA_FMT_t fmt, uint8_t dtmf_ack_idx)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_Init(pCh, std, as, fmt, dtmf_ack_idx);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to configure timers for a given CID standard.
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   std      - CID standard
+   \param   pTimers  - pointer to timer union
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidTimerConfig (uint8_t dxs, uint8_t line, DXS_CID_Std_t std,
+                             DXS_CID_Timers_t *pTimers)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_TimerConfig(pCh, std, pTimers);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to create (or update) the CID message per channel
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   msg_type - CID message type
+   \param   param    - CID message parameter
+   \param   pData    - pointer to char data of the parameter value
+   \param   length   - length of the data pointed by pData
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidMsgSetup(uint8_t dxs, uint8_t line, DXS_CID_MsgType_t msg_type,
+                         DXS_CID_MsgParam_t param, char *pData, uint8_t length)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_MsgUpdate(pCh, msg_type, param, pData, length);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to delete entirely the CID message per channel
+
+   \param   dxs      - device number
+   \param   line     - line number
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidMsgReset(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_MsgCleanup(pCh);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to start the playout of CID TypeI sequence
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   std      - CID standard
+   \param   as       - Alert signal
+   \param   fmt      - Data format
+   \param   msg_type - message type selected for playout
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidTypeIMsgStart(uint8_t dxs, uint8_t line,
+                               DXS_CID_MsgType_t msg_type)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_TypeI_Play(pCh, msg_type, DXS_CID_CALL_FROM_CID_API);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to start the playout of CID TypeII sequence
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   std      - CID standard
+   \param   as       - Alert signal
+   \param   fmt      - Data format
+   \param   msg_type - message type selected for playout
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidTypeIIMsgStart(uint8_t dxs, uint8_t line,
+                               DXS_CID_MsgType_t msg_type)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_TypeII_Play(pCh, msg_type);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to stop the playout of CID sequence
+
+   \param   dxs      - device number
+   \param   line     - line number
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsCidSeqStop(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret = DXS_statusFeatNotCompiledIn;
+
+   DXS_CH_API_ENTRY;
+
+#ifdef DXS_FEAT_CID
+   ret = DXS_CID_Stop(pCh);
+#endif /* DXS_FEAT_CID */
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to configure the ringing cadence
+
+   \param   dxs      - device number
+   \param   line     - line number
+   \param   pRC      - pointer to \ref DXS_RingCadence_t structure
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsRingCadenceInit(uint8_t dxs, uint8_t line, DXS_RingCadence_t *pRC)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_RING_CadenceInit(pCh, pRC);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to start the ringing cadence
+
+   \param   dxs      - device number
+   \param   line     - line number
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsRingCadenceStart(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_RING_CadenceStart(pCh);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Function to stop the ringing cadence
+
+   \param   dxs      - device number
+   \param   line     - line number
+
+   \return
+   - \ref DXS_status_t code
+*/
+int32_t DxsRingCadenceStop(uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_RING_CadenceStop(pCh);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Prevent ESD mode and line voltage drop
+   on PCM clock failure
+
+   \param   dxs    - device number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsClockFailLineFeedFreeze (uint8_t dxs)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = DXS_CfEsdSwitch(pDev, 0);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Allow ESD mode and line voltage drop
+   on PCM clock failure
+
+   \param   dxs    - device number
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsClockFailLineFeedUnFreeze (uint8_t dxs)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = DXS_CfEsdSwitch(pDev, 1);
+
+   DXS_API_EXIT(ret);
+}
+
+/* =================== MULTI-CHANNEL SHARED HW SUPPORT ====================== */
+
+/**
+   Configure the driver for the master channel.
+
+   \param   dxs      - device number
+   \param   line     - line number
+
+   \return
+   - DXS_statusOk
+   - DXS_statusDevNotFound
+   - DXS_statusDevNotInitialized
+   - DXS_statusChannelNotFound
+   - DXS_statusInvalidParam
+*/
+int32_t DxsSharedDcDcMasterSet (uint8_t dxs, uint8_t line)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_DCDC_HW_SharedDcDcMasterChSet(pCh);
+
+   DXS_API_EXIT(ret);
+}
+/* ========================================================================== */
+
+/* ===================== E V E N T   S U P P O R T ========================== */
+
+/**
+   Initialize Waiting List
+
+   \return
+   - waiting list instance
+*/
+DXS_WaitList_t DxsWaitListInit(void)
+{
+   return dxs_wl_init();
+}
+
+/**
+   Initialize Waiting List
+
+   \param   wl    - waiting list instance
+
+*/
+void DxsWaitListDestroy(DXS_WaitList_t wl)
+{
+   dxs_wl_destroy(wl);
+}
+
+/**
+   Add device to the waiting list
+
+   \param   dxs   - device number
+   \param   wl    - waiting list instance
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsWaitListDevAdd(uint8_t dxs, DXS_WaitList_t wl)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_wl_dev_add(pDev, wl);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Remove device from the waiting list
+
+   \param   dxs   - device number
+   \param   wl    - waiting list instance
+
+   \return
+   - DXS_statusOk or DXS_statusError
+*/
+int32_t DxsWaitListDevRemove(uint8_t dxs, DXS_WaitList_t wl)
+{
+   DXS_DEVICE_t *pDev;
+   int32_t ret;
+
+   DXS_DEV_API_ENTRY;
+
+   ret = dxs_wl_dev_remove(pDev, wl);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Wait on the Waiting List instance
+
+   \param   wl    - waiting list instance
+
+   \return
+   -  the first device number on the Waiting List
+               having non-empty event queue
+      or negative value in case of error
+*/
+int32_t DxsWaitForEvent(DXS_WaitList_t wl)
+{
+   return dxs_wait(wl);
+}
+
+/**
+   Read a single event from the device
+
+   \param   dxs    - device number
+   \param   pEvent - pointer to DXS_Event_t structure
+
+   \return
+   -  the remaining event count in device event queue
+      or negative value in case of error
+*/
+int32_t DxsEventGet(uint8_t dxs, DXS_Event_t *pEvent)
+{
+   DXS_DEVICE_t *pDev;
+
+   DXS_DEV_API_ENTRY;
+
+   /* no DXS_API_EXIT macro, as the function returns
+      the event count instead of a status code */
+
+   return dxs_event_get(pDev, pEvent);
+}
+
+/**
+   Enable dispatching of a particular event on a given line
+   to the application.
+
+   \param  dxs     Device number.
+   \param  line    Line number.
+   \param  event   Event id
+
+   \return
+   Return value according to \ref DXS_status_t.
+*/
+int32_t DxsEventEnable(uint8_t dxs, uint8_t line, DXS_Event_id_t event)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_EventEnable(pCh, event);
+
+   DXS_API_EXIT(ret);
+}
+
+/**
+   Disable dispatching of a particular event on a given line
+   to the application.
+
+   \param  dxs     Device number.
+   \param  line    Line number.
+   \param  event   Event id
+
+   \return
+   Return value according to \ref DXS_status_t.
+*/
+int32_t DxsEventDisable(uint8_t dxs, uint8_t line, DXS_Event_id_t event)
+{
+   DXS_DEVICE_t *pDev;
+   DXS_CHANNEL_t *pCh;
+   int32_t ret;
+
+   DXS_CH_API_ENTRY;
+
+   ret = DXS_EventDisable(pCh, event);
+
+   DXS_API_EXIT(ret);
+}
+
+/* ========================================================================== */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_bbd.c b/marvell/services/dxslic/api_lib/src/dxs_bbd.c
new file mode 100644
index 0000000..9638426
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_bbd.c
@@ -0,0 +1,530 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_bbd.c
+   Implementation of BBD functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdio.h>
+
+#include "dxs.h"
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_sdd.h"
+#include "dxs_sig.h"
+#include "dxs_init.h"
+#include "dxs_access.h"
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define BBD_MAGIC           0x21626264
+#define BBD_FAMILY_ID_DXS   0x44585321
+#define BBD_FAMILY_ID_DX8   0x44583821
+
+#define BBD_BLK_ID_MASTER   0x000a
+#define BBD_BLK_ID_CRAM     0x1001
+#define BBD_BLK_ID_CRAM2    0x1020
+#define BBD_BLK_ID_RING     0x1003
+#define BBD_BLK_ID_BASIC    0x1005
+#define BBD_BLK_ID_DCDC     0x1009
+#define BBD_BLK_ID_MWL      0x1008
+#define BBD_BLK_ID_UTD      0x1007
+#define BBD_BLK_ID_END      0x0000
+
+/** Reads 8bit value from big endian byte buffer */
+#define BBD_GET_VAL8(buf, pos, val8)  \
+            val8 = (buf)[(pos)]; (pos) +=1;
+
+/** Reads 16bit value from big endian byte buffer */
+#define BBD_GET_VAL16(buf, pos, val16) \
+            val16 = (((buf)[(pos)] << 8) |(buf)[(pos)+1]);\
+            (pos)   += 2;
+
+/** Reads 32bit value from big endian byte buffer */
+#define BBD_GET_VAL32(buf, pos, val32) \
+            val32 = (((buf)[(pos)] << 24) | ((buf)[(pos)+1] << 16) | \
+                     ((buf)[(pos)+2] << 8) | (buf)[(pos)+3]);\
+            (pos) += 4;
+
+/** Reads a complete bbd head, assuming given position is correct.*/
+#define BBD_GET_HEAD(buf, pos, head)\
+   do {\
+      BBD_GET_VAL16((buf), (pos), (head)->tag);\
+      BBD_GET_VAL16((buf), (pos), (head)->vers);\
+      BBD_GET_VAL32((buf), (pos), (head)->len);\
+   }while(0);
+
+/** Reads a complete master block exclusive head,
+    assuming given position is correct. */
+#define BBD_GET_MASTER(buf, pos, master)\
+   do {\
+      BBD_GET_VAL32((buf), (pos), (master)->magic);\
+      BBD_GET_VAL32((buf), (pos), (master)->family);\
+      BBD_GET_VAL8 ((buf), (pos), (master)->year);\
+      BBD_GET_VAL8 ((buf), (pos), (master)->month);\
+      BBD_GET_VAL8 ((buf), (pos), (master)->day);\
+      BBD_GET_VAL8 ((buf), (pos), (master)->padding);\
+   }while(0);
+
+/** Skip the actual block, assuming given position is correct */
+#define BBD_SKIP_BLOCK(pos, block_len)\
+            (pos) += (block_len);
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** BBD block header */
+struct bbd_block_header
+{
+   /** block id */
+   uint16_t tag;
+   /** block version */
+   uint16_t vers;
+   /** length */
+   uint32_t len;
+} __attribute__ ((packed));
+
+/** BBD block master */
+struct bbd_block_master
+{
+   uint32_t magic;
+   uint32_t family;
+   uint8_t  year;
+   uint8_t  month;
+   uint8_t  day;
+   uint8_t  padding;
+} __attribute__ ((packed));
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+/**
+   Function bbd_block_cram
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pHdr    - pointer to BBD block header structure
+   \param   pCram   - poiner to CRAM block data
+   \param   family  - value from master block
+
+   \return
+   - DXS_status_t
+*/
+static int32_t bbd_block_cram(DXS_CHANNEL_t *pCh, struct bbd_block_header *pHdr,
+   uint8_t *pCram, uint32_t family)
+{
+   uint16_t cram_offset, cmdLenBytes, pos = 0, cramLenWords;
+   int16_t words16;
+   uint8_t *pData;
+   int32_t ret = DXS_statusOk;
+   uint16_t paddingBytes;
+   uint8_t dest;
+   uint16_t blockOffset;
+
+   /* skip unsupported family block */
+   if (family != BBD_FAMILY_ID_DXS && family != BBD_FAMILY_ID_DX8)
+      return DXS_statusOk;
+
+   if (pHdr->tag == BBD_BLK_ID_CRAM2)
+      dest = 1;
+   else
+      dest = 0;
+
+   /* read offset */
+   DXS_cpb2w (&cram_offset, pCram, sizeof(uint16_t));
+
+   pData = pCram + sizeof(cram_offset);
+
+   /* data len in words16, minus len of offset_16 and crc_16 */
+   words16 = (pHdr->len - 2 * sizeof(uint16_t)) >> 1;
+
+   while (words16 > 0)
+   {
+      if (words16 > ((DXS_FW_SDD_Coeff_MAXLENGTH >> 1) - 1))
+         cmdLenBytes = DXS_FW_SDD_Coeff_MAXLENGTH;
+      else
+         cmdLenBytes = (words16 + 1) << 1;
+
+      paddingBytes = cmdLenBytes % sizeof(uint32_t);
+      cramLenWords = (cmdLenBytes >> 1) - 1;
+      blockOffset = cram_offset + (pos >> 1);
+
+      ret = DXS_SDD_CoeffBBD(pCh, dest, blockOffset, cramLenWords,
+                             &pData[pos], paddingBytes);
+
+      pos += (cmdLenBytes - 2);
+      words16 -= cramLenWords;
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function bbd_block_ring
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pHdr    - pointer to BBD block header structure
+   \param   pRing   - pointer to RING block data
+   \param   family  - value from master block
+
+   \return
+   - DXS_status_t
+*/
+static int32_t bbd_block_ring(DXS_CHANNEL_t *pCh,
+                              struct bbd_block_header *pHdr,
+                              uint8_t *pRing,
+                              uint32_t family)
+{
+   union DXS_FW_SDD_RingConfig_u ring = {0};
+   uint32_t len = pHdr->len;
+   int32_t ret;
+
+   /* skip unsupported family block */
+   if (family != BBD_FAMILY_ID_DXS && family != BBD_FAMILY_ID_DX8)
+      return DXS_statusOk;
+
+   DXS_cpb2dw(&ring.u32[0], pRing, len);
+
+   ret = DXS_SDD_RingConfigBBD(pCh, &ring.fwmsg);
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function bbd_block_basic
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pHdr    - pointer to BBD block header structure
+   \param   pBasic  - pointer to BASIC block data
+   \param   family  - value from master block
+
+   \return
+   - DXS_status_t
+*/
+static int32_t bbd_block_basic(DXS_CHANNEL_t *pCh,
+                               struct bbd_block_header *pHdr, uint8_t *pBasic,
+                               uint32_t family)
+{
+   union DXS_FW_SDD_BasicConfig_u basic = {0};
+   uint32_t len = pHdr->len;
+   int32_t ret;
+
+   /* skip unsupported family block */
+   if (family != BBD_FAMILY_ID_DXS && family != BBD_FAMILY_ID_DX8)
+      return DXS_statusOk;
+
+   DXS_cpb2dw(&basic.bc_data.data_u32[0], pBasic, len);
+
+   ret = DXS_SDD_BasicConfigBBD (pCh, &basic.bc_data);
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function bbd_block_dcdc
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pHdr    - pointer to BBD block header structure
+   \param   pDcdc   - pointer to DC/DC block data
+   \param   family  - value from master block
+
+   \return
+   - DXS_status_t
+*/
+static int32_t bbd_block_dcdc(DXS_CHANNEL_t *pCh,
+                              struct bbd_block_header *pHdr, uint8_t *pDcdc,
+                              uint32_t family)
+{
+   union DXS_FW_SDD_DcDcConfig_u dcdc_cfg = {0};
+   uint32_t len = pHdr->len;
+   int32_t ret = DXS_statusOk;
+
+   if (family == BBD_FAMILY_ID_DXS)
+   {
+      DXS_DCDC_Var_t dcdc_hw_bbd;
+
+      DXS_cpb2dw(&dcdc_cfg.dcdc_data.data_u32[0], pDcdc, len);
+      dcdc_hw_bbd = dcdc_cfg.fwmsg.DcDcHw;
+
+      /* sanity check */
+      if (dcdc_hw_bbd != DXS_DCDC_IBB12 &&
+          dcdc_hw_bbd != DXS_DCDC_CIBB12 &&
+          dcdc_hw_bbd != DXS_DCDC_IB12 &&
+          dcdc_hw_bbd != DXS_DCDC_BB48 &&
+          dcdc_hw_bbd != DXS_DCDC_CBB48 &&
+          dcdc_hw_bbd != DXS_DCDC_IFB12 &&
+          dcdc_hw_bbd != DXS_DCDC_CIFB12 &&
+          dcdc_hw_bbd != DXS_DCDC_IBGD12 &&
+          dcdc_hw_bbd != DXS_DCDC_IBVD3)
+      {
+         fprintf (stderr, "BBD: Unsupported DCDC HW option %d\n", dcdc_hw_bbd);
+         DXS_RETURN(DXS_statusBbdUnknownDcDcOpt);
+      }
+
+      /* check if DCDC HW matches the configured HW option */
+      if (dcdc_hw_bbd != pCh->pParent->dcdcType)
+      {
+         fprintf (stderr,
+                  "BBD: DCDC HW configuration mismatch: init=%d, bbd=%d\n",
+                  pCh->pParent->dcdcType, dcdc_hw_bbd);
+         DXS_RETURN(DXS_statusBbdDCDCHwCfgMismatch);
+      }
+
+      /* enable charge pump */
+      if (dcdc_hw_bbd == DXS_DCDC_IB12 || dcdc_hw_bbd == DXS_DCDC_IFB12 ||
+                       dcdc_hw_bbd == DXS_DCDC_CIFB12)
+      {
+         ret = DXS_ChargePumpSwitchOn(pCh->pParent);
+      }
+   }
+   else if (family == BBD_FAMILY_ID_DX8)
+   {
+      DXS_cpb2dw(&dcdc_cfg.dcdc_data.data_u32[0], pDcdc, len);
+
+      if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+      {
+         /* sanity check - not perfect due to missing DcDcHw field
+            in the command */
+         if (dcdc_cfg.dx8fwmsg.Res00 || dcdc_cfg.dx8fwmsg.Res01 ||
+                     dcdc_cfg.dx8fwmsg.Res02)
+         {
+            fprintf (stderr,
+                     "BBD: DCDC block does not match the declared HW: init=%d\n",
+                     pCh->pParent->dcdcType);
+            DXS_RETURN(DXS_statusBbdDCDCHwCfgMismatch);
+         }
+         /* enable charge pump */
+         ret = DXS_ChargePumpSwitchOn(pCh->pParent);
+      }
+   }
+   else
+   {
+      /* skip unsupported family block */
+      return DXS_statusOk;
+   }
+
+   if (ret == DXS_statusOk)
+      ret = DXS_SDD_DcDcConfigBBD(pCh, &dcdc_cfg.dcdc_data);
+
+   /* Set flag to start an automatic calibration after BBD download. */
+   if (ret == DXS_statusOk || ret == DXS_statusBbdDcDcReconfig)
+      (void) DXS_SDD_CalibrationNeededSet(pCh, 1);
+
+   /* It's not a real error for the entire BBD download */
+   if (ret == DXS_statusBbdDcDcReconfig)
+      ret = DXS_statusOk;
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function bbd_block_mwl
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pHdr    - pointer to BBD block header structure
+   \param   pMwl    - pointer to MWL block data
+   \param   family  - value from master block
+
+   \return
+   - DXS_status_t
+*/
+static int32_t bbd_block_mwl(DXS_CHANNEL_t *pCh, struct bbd_block_header *pHdr,
+   uint8_t *pMwl, uint32_t family)
+{
+   union DXS_FW_SDD_MwlConfig_u mwl = {0};
+   uint32_t len = pHdr->len;
+   int32_t ret;
+
+   /* skip unsupported family block */
+   if (family != BBD_FAMILY_ID_DXS && family != BBD_FAMILY_ID_DX8)
+      return DXS_statusOk;
+
+   DXS_cpb2dw(&mwl.u32[0], pMwl, len);
+
+   ret = DXS_SDD_MwlConfigBBD (pCh, &mwl.fwmsg);
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function bbd_block_utd
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pHdr    - pointer to BBD block header structure
+   \param   pUtd    - pointer to UTD block data
+   \param   family  - value from master block
+
+   \return
+   - DXS_status_t
+*/
+static int32_t bbd_block_utd(DXS_CHANNEL_t *pCh, struct bbd_block_header *pHdr,
+                                                  uint8_t *pUtd, uint32_t family)
+{
+#ifdef DXS_FEAT_UTD
+   union DXS_FW_SIG_UtdCoeff_u utd = {0};
+   uint32_t len = pHdr->len;
+   int32_t ret;
+   uint16_t unToneIdx;
+
+   /* skip unsupported family block */
+   if (family != BBD_FAMILY_ID_DXS && family != BBD_FAMILY_ID_DX8)
+      return DXS_statusOk;
+
+   /* Tone index */
+   DXS_cpb2w(&unToneIdx, pUtd, sizeof(uint16_t));
+   /* Tone coefficients */
+   DXS_cpb2dw(&utd.u32[0], pUtd + sizeof(uint16_t), len - sizeof(uint16_t));
+
+   ret = DXS_SIG_UtdCoeffUpdate(pCh, unToneIdx, &utd.fwmsg);
+
+   DXS_RETURN(ret);
+#else
+   return DXS_statusOk;
+#endif /* DXS_FEAT_UTD */
+}
+
+/**
+   Function dxs_bbd_download
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pBbd    - pointer to BBD data buffer
+   \param   nBytes  - size of BBD data buffer
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_bbd_download(DXS_CHANNEL_t *pCh, uint8_t *pBbd, uint32_t nBytes)
+{
+   struct bbd_block_header hdr = {0};
+   struct bbd_block_master master = {0};
+   int32_t ret = DXS_statusOk;
+   uint32_t byte_pos = 0;
+   uint8_t bCalibrationNeeded;
+
+   if (pCh==NULL || nBytes==0 || pBbd==NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   /* for ROM 1.0 devices the patch download is mandatory */
+   if (pCh->pParent->rom_mask_ver < 2 &&
+        !(pCh->pParent->flags & DXS_DEV_PRAM_PATCH_DOWNLOADED))
+   {
+      DXS_RETURN(DXS_statusPramPatchNotDownloaded);
+   }
+
+   pCh->flags &= ~DXS_CH_BBD_DOWNLOADED;
+
+   /* TODO: overall bbd file integrity check:
+               - summary block length matches nBytes
+               - DCDC HW option matches configuration
+               - unsupported blocks present */
+
+   while (byte_pos < nBytes)
+   {
+      BBD_GET_HEAD (pBbd, byte_pos, &hdr);
+
+      switch (hdr.tag)
+      {
+         case BBD_BLK_ID_MASTER:
+            {
+               BBD_GET_MASTER(pBbd, byte_pos, &master);
+               if (master.magic != BBD_MAGIC)
+               {
+                  /* invalid master block */
+                  DXS_RETURN(DXS_statusBbdMasterBlkInvalid);
+               }
+            }
+            break;
+
+         case BBD_BLK_ID_CRAM:
+         case BBD_BLK_ID_CRAM2:
+            ret = bbd_block_cram(pCh, &hdr, pBbd + byte_pos, master.family);
+            break;
+
+         case BBD_BLK_ID_RING:
+            ret = bbd_block_ring(pCh, &hdr, pBbd + byte_pos, master.family);
+            break;
+
+         case BBD_BLK_ID_BASIC:
+            ret = bbd_block_basic(pCh, &hdr, pBbd + byte_pos, master.family);
+            break;
+
+         case BBD_BLK_ID_DCDC:
+            ret = bbd_block_dcdc(pCh, &hdr, pBbd + byte_pos, master.family);
+            break;
+
+         case BBD_BLK_ID_MWL:
+            ret = bbd_block_mwl(pCh, &hdr, pBbd + byte_pos, master.family);
+            break;
+
+         case BBD_BLK_ID_UTD:
+            ret = bbd_block_utd(pCh, &hdr, pBbd + byte_pos, master.family);
+            break;
+
+         case BBD_BLK_ID_END:
+            /* do nothing */
+            break;
+
+         default:
+            {
+               fprintf (stderr,
+                  "Unknown unsupported block id 0x%04X in BBD at offset %lu.\n",
+                  hdr.tag, (unsigned long int)(byte_pos - sizeof(struct bbd_block_header)));
+                  DXS_RETURN(DXS_statusBbdUnknownBlk);
+            }
+      }
+
+      if (ret != DXS_statusOk)
+      {
+         DXS_RETURN(ret);
+      }
+
+      /* go to next block */
+      if (hdr.tag != BBD_BLK_ID_MASTER)
+         BBD_SKIP_BLOCK (byte_pos, hdr.len);
+   }
+
+   if (ret == DXS_statusOk)
+   {
+      pCh->flags |= DXS_CH_BBD_DOWNLOADED;
+       /* Do automatically a calibration on the channel on which the BBD was
+         downloaded to adapt to new coefficients. */
+      (void) DXS_SDD_CalibrationNeededGet(pCh, &bCalibrationNeeded);
+
+      if (bCalibrationNeeded == 1)
+      {
+         ret = DXS_SDD_Calibration(pCh);
+      }
+
+      if (ret != DXS_statusOk)
+      {
+         /* Automatic calibration failed. */
+         ret = DXS_statusAutomaticCalibrationFailed;
+      }
+   }
+
+   DXS_RETURN(ret);
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_bbd.h b/marvell/services/dxslic/api_lib/src/dxs_bbd.h
new file mode 100644
index 0000000..262e092
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_bbd.h
@@ -0,0 +1,38 @@
+#ifndef __DXS_BBD_H__
+#define __DXS_BBD_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_bbd.h
+   BBD functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t dxs_bbd_download(DXS_CHANNEL_t *pCh,
+                       uint8_t *pBbd, uint32_t nBytes);
+
+
+#endif /* __DXS_BBD_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_cid.c b/marvell/services/dxslic/api_lib/src/dxs_cid.c
new file mode 100644
index 0000000..d752141
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_cid.c
@@ -0,0 +1,3942 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+    \file dxs_cid.c
+    Implementation of Caller ID functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdlib.h>
+#include <time.h>
+#include <pthread.h>
+
+#include "dxs.h"
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_sdd.h"
+#include "dxs_sig.h"
+#include "dxs_event.h"
+#include "dxs_cid_fsk.h"
+#include "dxs_pcm.h"
+#include "dxs_cid.h"
+#include "dxs_ring.h"
+
+#ifdef DXS_FEAT_CID
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_CID_CTX_MAGIC            0x58434944 /* "XCID" */
+
+/* default FSK configuration */
+#define DXS_CID_FSK_LEVEL_DEFAULT    (-69) /* -6.9 dBm0 */
+#define DXS_CID_FSK_SEIZURE_DEFAULT  300
+#define DXS_CID_FSK_MARK_DEFAULT     180
+#define DXS_CID_FSK_AD_DEFAULT       1
+
+/* default SIN BT FSK mark bits */
+#define DXS_CID_FSK_BT_MARK_DEFAULT  80
+
+/* default ETSI type2 FSK mark bits */
+#define DXS_CID_FSK_ETSI_TYPE2_MARK_DEFAULT   80
+
+/* default TG configuration for DTAS */
+#define DXS_CID_DTAS_LEVEL1          (-138) /* -13.8 dBm0 */
+#define DXS_CID_DTAS_LEVEL2          (-138) /* -13.8 dBm0 */
+#define DXS_CID_DTAS_FREQ1           2130
+#define DXS_CID_DTAS_FREQ2           2750
+
+/* default ETSI timers */
+#define DXS_CID_ETSI_LONG_RING_MS           1000
+#define DXS_CID_ETSI_DTAS_MS                 100
+#define DXS_CID_ETSI_RPAS_MS                 200
+#define DXS_CID_ETSI_T0_DEFAULT              200
+#define DXS_CID_ETSI_T1_DEFAULT              200
+#define DXS_CID_ETSI_T2_DEFAULT              350
+#define DXS_CID_ETSI_T3_DEFAULT              650
+#define DXS_CID_ETSI_T4_DEFAULT              300
+#define DXS_CID_ETSI_T5_DEFAULT              700
+#define DXS_CID_ETSI_T6_DEFAULT              500
+#define DXS_CID_ETSI_T7_MAX                  700
+#define DXS_CID_ETSI_TYPE2_DTAS_MS            80
+#define DXS_CID_ETSI_TYPE2_T14_DEFAULT       160
+#define DXS_CID_ETSI_TYPE2_T10_DEFAULT        50
+#define DXS_CID_ETSI_TYPE2_T12_DEFAULT       100
+#define DXS_CID_ETSI_TYPE2_T13_DEFAULT        50
+#define DXS_CID_ETSI_TYPE2_T9_DEFAULT         50
+#define DXS_CID_ETSI_T0dtmf_DEFAULT          300
+#define DXS_CID_ETSI_Tdtmf_DEFAULT            60
+#define DXS_CID_ETSI_T2dtmf_DEFAULT          300
+
+/* default Telcordia timers */
+#define DXS_CID_TELCORDIA_LONG_RING_MS      2000
+#define DXS_CID_TELCORDIA_OSI_MS             250
+#define DXS_CID_TELCORDIA_T0_DEFAULT         700
+#define DXS_CID_TELCORDIA_T1_DEFAULT         400
+#define DXS_CID_TELCORDIA_T2_DEFAULT         300
+#define DXS_CID_TELCORDIA_TYPE2_OSI_MS         0
+#define DXS_CID_TELCORDIA_TYPE2_W_MS          60
+#define DXS_CID_TELCORDIA_TYPE2_X_MS           0
+#define DXS_CID_TELCORDIA_TYPE2_X1_MS         40
+#define DXS_CID_TELCORDIA_TYPE2_Y_MS          85
+#define DXS_CID_TELCORDIA_TYPE2_T1_MS        165
+#define DXS_CID_TELCORDIA_TYPE2_Q_MS         100
+#define DXS_CID_TELCORDIA_TYPE2_S_MS          80
+#define DXS_CID_TELCORDIA_T0dtmf_DEFAULT      300
+#define DXS_CID_TELCORDIA_Tdtmf_DEFAULT       60
+#define DXS_CID_TELCORDIA_T2dtmf_DEFAULT      300
+
+/* default SIN BT timers */
+#define DXS_CID_BT_DTAS_MS                   100
+#define DXS_CID_BT_T0_DEFAULT                120
+#define DXS_CID_BT_T1_DEFAULT                 55
+#define DXS_CID_BT_T2_DEFAULT                220
+#define DXS_CID_BT_TYPE2_DTAS_MS              85
+#define DXS_CID_BT_TYPE2_ACK_MS              150
+#define DXS_CID_BT_TYPE2_T0_DEFAULT           45
+#define DXS_CID_BT_TYPE2_T1_DEFAULT           80
+#define DXS_CID_BT_TYPE2_T2_DEFAULT           50
+
+/* default NTT timers */
+#define DXS_CID_NTT_CARON_MS                 500
+#define DXS_CID_NTT_CAROFF_MS                500
+#define DXS_CID_NTT_T0_DEFAULT               100
+#define DXS_CID_NTT_T1_DEFAULT              6000
+#define DXS_CID_NTT_T2_DEFAULT               400
+#define DXS_CID_NTT_T3_DEFAULT              7000
+#define DXS_CID_NTT_T4_DEFAULT               300
+#define DXS_CID_NTT_TYPE2_AS1_MS             100
+#define DXS_CID_NTT_TYPE2_AS2_MS             100
+#define DXS_CID_NTT_TYPE2_AS_PAUSE_MS         50
+#define DXS_CID_NTT_TYPE2_T0_DEFAULT          45
+#define DXS_CID_NTT_TYPE2_T1_DEFAULT          80
+#define DXS_CID_NTT_TYPE2_T2_DEFAULT          50
+
+/* length of each CID message parameter */
+#define DXS_CID_MSG_PARAM_DATE_TIME_FIXLEN             8
+#define DXS_CID_MSG_PARAM_CALLING_LINE_ID_MAXLEN       20
+#define DXS_CID_MSG_PARAM_CALLED_LINE_ID_MAXLEN        20
+#define DXS_CID_MSG_PARAM_RA_CALLING_LINE_ID_FIXLEN    1
+#define DXS_CID_MSG_PARAM_CALLING_PARTY_NAME_MAXLEN    50
+#define DXS_CID_MSG_PARAM_RA_CALLING_PARTY_NAME_FIXLEN 1
+#define DXS_CID_MSG_PARAM_VI_FIXLEN                    1
+#define DXS_CID_MSG_PARAM_MSG_ID_FIXLEN                3
+#define DXS_CID_MSG_PARAM_LM_CLI_MAXLEN                20
+#define DXS_CID_MSG_PARAM_COMP_DATE_TIME_FIXLEN1       8
+#define DXS_CID_MSG_PARAM_COMP_DATE_TIME_FIXLEN2       10
+#define DXS_CID_MSG_PARAM_COMP_CALLING_LINE_ID_MAXLEN  20
+#define DXS_CID_MSG_PARAM_CALL_TYPE_FIXLEN             1
+#define DXS_CID_MSG_PARAM_FIRST_CALLED_LINE_ID_MAXLEN  20
+#define DXS_CID_MSG_PARAM_NUM_MESSAGES_FIXLEN          1
+#define DXS_CID_MSG_PARAM_TYPE_FWD_CALL_FIXLEN         1
+#define DXS_CID_MSG_PARAM_TYPE_CALLING_USER_FIXLEN     1
+#define DXS_CID_MSG_PARAM_REDIR_NUM_MAXLEN             20
+#define DXS_CID_MSG_PARAM_CHARGE_FIXLEN                14
+#define DXS_CID_MSG_PARAM_ADDON_CHARGE_FIXLEN          14
+#define DXS_CID_MSG_PARAM_DURA_CALL_FIXLEN             6
+#define DXS_CID_MSG_PARAM_NET_PROV_ID_MAXLEN           20
+#define DXS_CID_MSG_PARAM_CARRIER_ID_MAXLEN            20
+#define DXS_CID_MSG_PARAM_SEL_TERMINAL_FUNC_MAXLEN     21
+#define DXS_CID_MSG_PARAM_DISP_INFO_MAXLEN             253
+#define DXS_CID_MSG_PARAM_SERV_INFO_FIXLEN             1
+#define DXS_CID_MSG_PARAM_EXTENSION_FIXLEN             10
+
+/* length of SIN BT CID message parameter */
+#define DXS_CID_BT_MSG_PARAM_CALL_TYPE_FIXLEN             1
+#define DXS_CID_BT_MSG_PARAM_DATE_TIME_FIXLEN             8
+#define DXS_CID_BT_MSG_PARAM_CALLING_LINE_ID_MAXLEN       18
+#define DXS_CID_BT_MSG_PARAM_RA_CALLING_LINE_ID_FIXLEN    1
+#define DXS_CID_BT_MSG_PARAM_CALLED_LINE_ID_MAXLEN        18
+#define DXS_CID_BT_MSG_PARAM_RA_CALLING_PARTY_NAME_FIXLEN 1
+#define DXS_CID_BT_MSG_PARAM_CALLING_PARTY_NAME_MAXLEN    20
+#define DXS_CID_BT_MSG_PARAM_NUM_MESSAGES_FIXLEN          1
+
+/* length of NTT CID message parameter */
+#define DXS_CID_NTT_MSG_PARAM_CALLING_LINE_ID_MAXLEN      20
+#define DXS_CID_NTT_MSG_PARAM_RA_CALLING_LINE_ID_FIXLEN   1
+#define DXS_CID_NTT_MSG_PARAM_EXP_SIGNAL_FIXLEN           3
+
+/* reversed polarity flag */
+#define DXS_CID_LINE_MODE_POLARITY_FLAG_NORMAL            0x00
+#define DXS_CID_LINE_MODE_POLARITY_FLAG_REVERSED          0x10
+
+/* offhook/onhook state */
+#define DXS_CID_HOOK_STATE_ONHOOK                         0x1
+#define DXS_CID_HOOK_STATE_OFFHOOK                        0x2
+
+/* default TG configuration for NTT type2 alert tone */
+#define DXS_CID_NTT_TYPE2_ATONE_LEVEL1          (-138) /* -13.8 dBm0 */
+#define DXS_CID_NTT_TYPE2_ATONE_LEVEL2          (-138) /* -13.8 dBm0 */
+#define DXS_CID_NTT_TYPE2_ATONE_FREQ1           852
+#define DXS_CID_NTT_TYPE2_ATONE_FREQ2           1633
+#define DXS_CID_NTT_TYPE2_ATONE_FREQ3           941
+
+/* CID FSK messsage buffer's size */
+#define DXS_CID_FSK_MSG_BUF_MAX_LEN             258
+#define DXS_CID_FSK_BITS_PER_SEC                1200
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+struct __cid_msg_elem
+{
+   /* message type */
+   DXS_CID_MsgParam_t    type;
+   /* message data */
+   char                  *data;
+   /* length of message data */
+   uint16_t              len;
+   /* next message */
+   struct __cid_msg_elem *next;
+};
+typedef struct __cid_msg_elem  dxs_cid_message_t;
+
+/* CID resource context */
+typedef struct
+{
+   /* magic code */
+   uint32_t                magic;
+
+   /* CID standard */
+   DXS_CID_Std_t           std;
+   /* alert signal */
+   DXS_CID_AS_t            as;
+   /* data format */
+   DXS_CID_DATA_FMT_t      df;
+   /* DTMF index for acknowledgment (type2 only) */
+   uint8_t                 dtmf_ack_idx;
+
+   /* timers ETSI */
+   DXS_CID_ETSI_Timers_t   tm_etsi;
+   /* timers Telcordia */
+   DXS_CID_TELCORDIA_Timers_t  tm_tc;
+   /* timers BT */
+   DXS_CID_BT_Timers_t     tm_bt;
+   /* timers NTT */
+   DXS_CID_NTT_Timers_t    tm_ntt;
+
+   /* Call Set-up message */
+   dxs_cid_message_t      *msg_cs;
+   /* Message Waiting Indicator message */
+   dxs_cid_message_t      *msg_mwi;
+   /* Advice of Charge message */
+   dxs_cid_message_t      *msg_aoc;
+   /* Short Message Service */
+   dxs_cid_message_t      *msg_sms;
+   /* Number Display service */
+   dxs_cid_message_t      *msg_nd;
+
+   /* transmit data buffer */
+   uint8_t                xmit_buffer[DXS_CID_FSK_MSG_BUF_MAX_LEN];
+   /* transmit data buffer length */
+   uint16_t               xmit_length;
+
+   /* thread ID */
+   pthread_t              thrd;
+   /* sem ID */
+   sem_t                  sema;
+   /* thread status */
+   volatile uint32_t      complete;
+   /* thread return code */
+   int32_t                ret;
+
+   /* CID SM */
+   int32_t               (*cid_state)(void *arg);
+   /* timeout value for CID SM */
+   uint32_t              timeout;
+   /* parameter's length depends on CID standard */
+   uint8_t               (*len_check) (DXS_CID_MsgParam_t param, uint8_t length);
+   /* initial polarity before starting CID */
+   uint8_t               polarity_initial;
+   /* expected hook state flag for CID SM state */
+   uint8_t               hook_state_exp;
+   /* hook state */
+   volatile uint8_t      hook_state;
+   /* timestamp of onhook/offhook */
+   uint8_t               hook_timestamp;
+   /* hide off-hook during OSI for CID type2 */
+   volatile uint8_t      hook_block;
+   /* ACK detection for CID SM Type2 */
+   volatile uint8_t      ack_detect;
+   /* Unmute channel */
+   uint8_t               need_unmute;
+
+   /* supervisory timeout for CID NTT SM */
+   uint16_t              ntt_timeout;
+
+   /* calling instance (user API or Ringing SM) */
+   uint8_t               calling_instance;
+} DXS_CID_Ctx_t;
+
+/* CID resource array */
+static DXS_CID_Ctx_t cid_res[DXS_MAX_DEVICES * CH_PER_DEVICE] = {0};
+/* 0-9, * 10, # 11, A-D(a-d) 12-15 */
+typedef struct
+{
+  int16_t level1; 
+  int16_t level2; 
+  uint16_t freq1;
+  uint16_t freq2;
+} dtmf_t;
+static dtmf_t dtmf[16] = {{-9, -7, 941, 1336}, {-9, -7, 697, 1209}, {-9, -7, 697, 1336}, {-9, -7, 697, 1477}, 
+                          {-9, -7, 770, 1209}, {-9, -7, 770, 1336}, {-9, -7, 770, 1477}, {-9, -7, 852, 1209}, 
+                          {-9, -7, 852, 1336}, {-9, -7, 852, 1477}, {-9, -7, 941, 1209}, {-9, -7, 941, 1477}, 
+                          {-9, -7, 697, 1633}, {-9, -7, 770, 1633}, {-9, -7, 852, 1633}, {-9, -7, 941, 1633}, 
+                         };
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Get the message of a type
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+   \param   type   - message type
+
+   \return
+   - message pointer
+*/
+static dxs_cid_message_t *dxs_cid_message_get(DXS_CID_Ctx_t *pCid,
+                                         DXS_CID_MsgType_t type)
+{
+   dxs_cid_message_t *pMsg = NULL;
+
+   if (type == DXS_CID_MSG_TYPE_CS)
+      pMsg = pCid->msg_cs;
+   else if (type == DXS_CID_MSG_TYPE_MWI)
+      pMsg = pCid->msg_mwi;
+   else if (type == DXS_CID_MSG_TYPE_AOC)
+      pMsg = pCid->msg_aoc;
+   else if (type == DXS_CID_MSG_TYPE_SMS)
+      pMsg = pCid->msg_sms;
+   else if (type == DXS_CID_MSG_TYPE_ND)
+      pMsg = pCid->msg_nd;
+   /* other message types are not supported */
+
+   return pMsg;
+}
+
+/**
+   Set the message of a type
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+   \param   type   - message type
+   \param   pMsg   - message
+
+   \return
+   - none
+*/
+static void dxs_cid_message_set(DXS_CID_Ctx_t *pCid, DXS_CID_MsgType_t type,
+                                  dxs_cid_message_t *pMsg)
+{
+   if (type == DXS_CID_MSG_TYPE_CS)
+      pCid->msg_cs = pMsg;
+   else if (type == DXS_CID_MSG_TYPE_MWI)
+      pCid->msg_mwi = pMsg;
+   else if (type == DXS_CID_MSG_TYPE_AOC)
+      pCid->msg_aoc = pMsg;
+   else if (type == DXS_CID_MSG_TYPE_SMS)
+      pCid->msg_sms = pMsg;
+   else if (type == DXS_CID_MSG_TYPE_ND)
+      pCid->msg_nd = pMsg;
+   /* other message types are not supported */
+}
+
+/**
+   Vipe a CID message from CID context
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+   \param   type   - message type \ref DXS_CID_MsgType_t
+
+   \return
+   - DXS_status_t
+*/
+static void dxs_cid_msg_clear (DXS_CID_Ctx_t *pCid, DXS_CID_MsgType_t type)
+{
+   dxs_cid_message_t *pMsg = dxs_cid_message_get(pCid, type);
+
+   while (pMsg != NULL)
+   {
+      dxs_cid_message_t *p = pMsg;
+
+      /* free parameter value */
+      free(pMsg->data);
+      /* take next message */
+      pMsg = pMsg->next;
+      dxs_cid_message_set(pCid, type, pMsg);
+      /* free parameter */
+      free (p);
+   }
+}
+
+/**
+   Vipe all CID messages from CID context
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+
+   \return
+   - DXS_status_t
+*/
+static void dxs_cid_msg_clearall (DXS_CID_Ctx_t *pCid)
+{
+   dxs_cid_msg_clear (pCid, DXS_CID_MSG_TYPE_CS);
+   dxs_cid_msg_clear (pCid, DXS_CID_MSG_TYPE_MWI);
+   dxs_cid_msg_clear (pCid, DXS_CID_MSG_TYPE_AOC);
+   dxs_cid_msg_clear (pCid, DXS_CID_MSG_TYPE_SMS);
+   dxs_cid_msg_clear (pCid, DXS_CID_MSG_TYPE_ND);
+}
+
+/**
+   Function to set parity bit
+
+   \param   data_byte   - source data
+
+   \return
+   - uint8_t
+*/
+static uint8_t dxs_cid_parity_set(uint8_t data_byte)
+{
+   uint8_t i, ones_num = 0, tmpByte = data_byte;
+
+   /* check even parity for b7...b1 */
+   for (i = 0; i < 7; i++)
+   {
+      /* count number of ones */
+      if (tmpByte & 0x1)
+         ones_num ++;
+      tmpByte >>= 1;
+   }
+   /* set parity bit as MSB in case of odd num (i.e. lowest bit is set) */
+   if (ones_num & 0x1)
+      data_byte |= 0x80;
+
+   return data_byte;
+}
+
+/**
+   Calculate CRC for NTT FSK encoding.
+
+   \param  pCidBuf      CID data buffer.
+   \param  len          Buffer size in octets.
+
+   \return  calculated CRC
+
+   \remarks
+   \verbatim
+   1- The CRC16 for NTT FSK Buffer is generated with the polynom
+      X^16 + X^12 + X^5 + X^2 + X^0 (Hexadecimal: 0x8408)
+   2- The algorithm is:
+      a)initial value of CRC = 0x0000.
+      b)for each byte (from header to ETX)
+            compute the CRC with G(x) (CRC1)
+            CRC= CRC + CRC1
+   \endverbatim
+*/
+static uint16_t dxs_cid_crc_ntt(uint8_t *pCidBuf, uint8_t len)
+{
+   uint16_t crc = 0, tmp;
+   uint8_t i, j, byte;
+
+   for (i = 0; i < len; i++)
+   {
+      /* get reversed data byte */
+      byte = pCidBuf [i];
+      tmp   = (byte << 1);
+      for (j = 8; j > 0; j--)
+      {
+         tmp  >>= 1;
+         if ((tmp ^ crc) & 0x0001)
+            crc = (crc >> 1) ^ 0x8408;
+         else
+            crc >>= 1;
+      }
+   }
+   return crc;
+}
+
+/**
+   Prepare data buffer for DTMF transmit
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+   \param
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_cid_dtmf_buffer_prepare(DXS_CID_Ctx_t *pCid,
+                                            DXS_CID_MsgType_t msg_type)
+{
+   /*  prepare buffer for sending in DTMF */
+   dxs_cid_message_t *p, *pMsg = dxs_cid_message_get(pCid, msg_type);
+   uint16_t buffer_length = 0, pos = 2;
+
+   if (pMsg == NULL)
+   {
+      /* uninitialized message, return error */
+      DXS_RETURN(DXS_statusCidMsgNotInit);
+   }
+
+   p = pMsg;
+   /* calculate total length for an DTMF buffer */
+   while (p != NULL)
+   {
+      buffer_length += (p->len); 
+      p = p->next;
+   }
+   buffer_length += 2; /* length + pos in the head */
+
+   if (buffer_length > DXS_CID_FSK_MSG_BUF_MAX_LEN)
+   {
+      /* Message length is too high, return error */
+      DXS_RETURN(DXS_statusCidMsgLenWrong);
+    }
+
+   p = pMsg;
+   /* copy the parameters */
+   while (p != NULL)
+   {
+      uint8_t i;
+      {
+         for (i=0; i<p->len; i++)
+         { 
+             /* 0-9, * 10, # 11, A-D(a-d) 12-15 */
+             if ((p->data[i] >= 0x30) && (p->data[i] <= 0x39))
+                 pCid->xmit_buffer[pos++] = p->data[i] - 0x30;
+             else if (p->data[i] == 0x2A) /* * */
+                 pCid->xmit_buffer[pos++] = 10;
+             else if (p->data[i] == 0x23) /* # */
+                 pCid->xmit_buffer[pos++] = 11;
+             else if ((p->data[i] >= 0x41) && (p->data[i] <= 0x44))  /* A-D */
+                 pCid->xmit_buffer[pos++] = p->data[i] - 0x35;
+             else if ((p->data[i] >= 0x61) && (p->data[i] <= 0x64))  /* a-d */
+                 pCid->xmit_buffer[pos++] = p->data[i] - 0x55;
+         }
+      }
+
+      p = p->next;
+   }
+   /* set buffer length */
+   pCid->xmit_buffer[0] = pos - 2; /* length of data */
+   pCid->xmit_buffer[1] = 2; /* next data position, used when transmitting */
+   pCid->xmit_length = pos; /* total length includes the headerr */
+   /* printf("cid_prepare %d, %d, %d, %d, %d\n", pCid->xmit_length, pCid->xmit_buffer[0], pCid->xmit_buffer[1], pCid->xmit_buffer[2], pCid->xmit_buffer[3]); */
+   return DXS_statusOk; 
+    
+}
+
+/**
+   Prepare data buffer for FSK transmit
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+   \param
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_cid_fsk_buffer_prepare(DXS_CID_Ctx_t *pCid,
+                                            DXS_CID_MsgType_t msg_type)
+{
+   dxs_cid_message_t *p, *pMsg = dxs_cid_message_get(pCid, msg_type);
+   uint16_t buffer_length = 0, pos = 2, i;
+   uint8_t fsk_data_cksum = 0;
+
+   if (pMsg == NULL)
+   {
+      /* uninitialized message, return error */
+      DXS_RETURN(DXS_statusCidMsgNotInit);
+   }
+
+   p = pMsg;
+
+   /* calculate total length for an FSK buffer */
+   while (p != NULL)
+   {
+      buffer_length += (p->len + 2); /* + parameter code + length byte */
+      p = p->next;
+   }
+   buffer_length += 3; /* + message type code + total length byte + checksum */
+
+   if (buffer_length > DXS_CID_FSK_MSG_BUF_MAX_LEN)
+   {
+      /* Message length is too high, return error */
+      DXS_RETURN(DXS_statusCidMsgLenWrong);
+   }
+
+   pCid->xmit_buffer[0] = msg_type;
+   pCid->xmit_buffer[1] = buffer_length - 3;
+
+   p = pMsg;
+   /* copy the parameters */
+   while (p != NULL)
+   {
+      uint8_t i;
+
+      pCid->xmit_buffer[pos++] = p->type;
+      pCid->xmit_buffer[pos++] = p->len;
+
+#if 0
+      /* update date/time */
+      if (p->type == DXS_CID_MSG_PARAM_DATE_TIME)
+      {
+         struct tm tms = {0};
+         time_t rawtime = time(NULL);
+
+         localtime_r(&rawtime, &tms);
+
+         /* month */
+         pCid->xmit_buffer[pos++] = (tms.tm_mon + 1) / 10 + '0';
+         pCid->xmit_buffer[pos++] = (tms.tm_mon + 1) % 10 + '0';
+         /* day */
+         pCid->xmit_buffer[pos++] = tms.tm_mday / 10 + '0';
+         pCid->xmit_buffer[pos++] = tms.tm_mday % 10 + '0';
+         /* hour */
+         pCid->xmit_buffer[pos++] = tms.tm_hour / 10 + '0';
+         pCid->xmit_buffer[pos++] = tms.tm_hour % 10 + '0';
+         /* minute */
+         pCid->xmit_buffer[pos++] = tms.tm_min / 10 + '0';
+         pCid->xmit_buffer[pos++] = tms.tm_min % 10 + '0';
+      }
+      else
+#endif
+      {
+         for (i=0; i<p->len; i++)
+            pCid->xmit_buffer[pos++] = p->data[i];
+      }
+
+      p = p->next;
+   }
+
+   /* calculate checksum */
+   for (i=0; i<pos; i++)
+      fsk_data_cksum += pCid->xmit_buffer[i];
+
+   pCid->xmit_buffer[pos] = ~(fsk_data_cksum & 0xFF) + 1;
+
+   /* set buffer length */
+   pCid->xmit_length = buffer_length;
+
+   return DXS_statusOk;
+}
+
+/**
+   Prepare data buffer for FSK transmit (NTT standard)
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+   \param
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_cid_fsk_buffer_prepare_ntt(DXS_CID_Ctx_t *pCid,
+                                                     DXS_CID_MsgType_t msg_type)
+{
+   dxs_cid_message_t *p, *pMsg = dxs_cid_message_get(pCid, msg_type);
+
+   uint16_t buffer_length = 0, pos = 6, crc;
+
+   if (pMsg == NULL)
+   {
+      /* uninitialized message, return error */
+      DXS_RETURN(DXS_statusCidMsgNotInit);
+   }
+   p = pMsg;
+
+   /* calculate total length for an FSK buffer */
+   while (p != NULL)
+   {
+      buffer_length += (p->len + 2); /* + parameter code + length byte */
+      /* Increase buffer's size for DLE insertion */
+      if (p->len == 16)
+         buffer_length++;
+      p = p->next;
+   }
+   /* Increase buffer's size for DLE insertion */
+   if (buffer_length == 16)
+      buffer_length++;
+   /* + DLE+SOH+Header+DLE+STX+ServiceType+MessageLength+DLE+ETX+CRC(2) */
+   buffer_length += 11;
+
+   if (buffer_length > 128)
+   {
+      /* Message length is too high, return error */
+      DXS_RETURN(DXS_statusCidMsgLenWrong);
+   }
+
+   pCid->xmit_buffer[0] = 0x90; /* DLE (w parity)*/
+   pCid->xmit_buffer[1] = 0x81; /* SOH (w parity) */
+   pCid->xmit_buffer[2] = 0x87; /* Header (w parity) */
+   pCid->xmit_buffer[3] = 0x90; /* DLE (w parity)*/
+   pCid->xmit_buffer[4] = 0x82; /* STX (w parity)*/
+   pCid->xmit_buffer[5] = dxs_cid_parity_set(msg_type);
+   if (buffer_length == 28)
+   {
+      pCid->xmit_buffer[pos++] = 0x90; /* DLE (w parity)*/
+      pCid->xmit_buffer[pos++] = 0x90;
+   }
+   else
+      pCid->xmit_buffer[pos++] = dxs_cid_parity_set(buffer_length - 11);
+
+   p = pMsg;
+   /* copy the parameters */
+   while (p != NULL)
+   {
+      uint8_t i;
+
+      pCid->xmit_buffer[pos++] = dxs_cid_parity_set(p->type);
+      if (p->len == 16)
+         pCid->xmit_buffer[pos++] = 0x90; /* DLE (w parity)*/
+      pCid->xmit_buffer[pos++] = dxs_cid_parity_set(p->len);
+      for (i=0; i<p->len; i++)
+         pCid->xmit_buffer[pos++] = dxs_cid_parity_set(p->data[i]);
+
+      p = p->next;
+   }
+
+   /* Add control fields */
+   pCid->xmit_buffer[pos++] = 0x90; /* DLE (w parity)*/
+   pCid->xmit_buffer[pos++] = 0x03; /* ETX (w parity)*/
+
+   /* Add CRC (from HEADER to ETX) */
+   crc = dxs_cid_crc_ntt(&pCid->xmit_buffer[2], (uint8_t) pos - 2);
+   pCid->xmit_buffer[pos++] = (uint8_t) (crc & 0xFF);
+   pCid->xmit_buffer[pos] = (uint8_t) ((crc >> 8) & 0xFF);
+
+   /* set buffer length */
+   pCid->xmit_length = buffer_length;
+
+   return DXS_statusOk;
+}
+
+/**
+   Check ETSI message parameter length
+
+   \param   param  - message parameter
+   \param   length - message length
+
+   \return
+   - updated length
+*/
+static uint8_t dxs_cid_param_length_check_etsi(DXS_CID_MsgParam_t param,
+                                              uint8_t length)
+{
+   uint8_t updated_length = length;
+
+   switch (param)
+   {
+      case DXS_CID_MSG_PARAM_DATE_TIME:
+         updated_length = DXS_CID_MSG_PARAM_DATE_TIME_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALLING_LINE_ID:
+         if (updated_length > DXS_CID_MSG_PARAM_CALLING_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_CALLING_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALLED_LINE_ID:
+         if (updated_length > DXS_CID_MSG_PARAM_CALLED_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_CALLED_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_RA_CALLING_LINE_ID:
+         updated_length = DXS_CID_MSG_PARAM_RA_CALLING_LINE_ID_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALLING_PARTY_NAME:
+         if (updated_length > DXS_CID_MSG_PARAM_CALLING_PARTY_NAME_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_CALLING_PARTY_NAME_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_RA_CALLING_PARTY_NAME:
+         updated_length = DXS_CID_MSG_PARAM_RA_CALLING_PARTY_NAME_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_VI:
+         updated_length = DXS_CID_MSG_PARAM_VI_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_MSG_ID:
+         updated_length = DXS_CID_MSG_PARAM_MSG_ID_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_LM_CLI:
+         if (updated_length > DXS_CID_MSG_PARAM_LM_CLI_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_LM_CLI_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_COMP_DATE_TIME:
+         if (updated_length != DXS_CID_MSG_PARAM_COMP_DATE_TIME_FIXLEN1 &&
+                updated_length != DXS_CID_MSG_PARAM_COMP_DATE_TIME_FIXLEN2)
+            updated_length = DXS_CID_MSG_PARAM_COMP_DATE_TIME_FIXLEN2;
+         break;
+
+      case DXS_CID_MSG_PARAM_COMP_CALLING_LINE_ID:
+         if (updated_length > DXS_CID_MSG_PARAM_COMP_CALLING_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_COMP_CALLING_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALL_TYPE:
+         updated_length = DXS_CID_MSG_PARAM_CALL_TYPE_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_FIRST_CALLED_LINE_ID:
+         if (updated_length > DXS_CID_MSG_PARAM_FIRST_CALLED_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_FIRST_CALLED_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_NUM_MESSAGES:
+         updated_length = DXS_CID_MSG_PARAM_NUM_MESSAGES_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_TYPE_FWD_CALL:
+         updated_length = DXS_CID_MSG_PARAM_TYPE_FWD_CALL_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_TYPE_CALLING_USER:
+         updated_length = DXS_CID_MSG_PARAM_TYPE_CALLING_USER_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_REDIR_NUM:
+         if (updated_length > DXS_CID_MSG_PARAM_REDIR_NUM_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_REDIR_NUM_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CHARGE:
+         updated_length = DXS_CID_MSG_PARAM_CHARGE_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_ADDON_CHARGE:
+         updated_length = DXS_CID_MSG_PARAM_ADDON_CHARGE_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_DURA_CALL:
+         updated_length = DXS_CID_MSG_PARAM_DURA_CALL_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_NET_PROV_ID:
+         if (updated_length > DXS_CID_MSG_PARAM_NET_PROV_ID_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_NET_PROV_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CARRIER_ID:
+         if (updated_length > DXS_CID_MSG_PARAM_CARRIER_ID_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_CARRIER_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_SEL_TERMINAL_FUNC:
+         if (updated_length > DXS_CID_MSG_PARAM_SEL_TERMINAL_FUNC_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_SEL_TERMINAL_FUNC_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_DISP_INFO:
+         if (updated_length > DXS_CID_MSG_PARAM_DISP_INFO_MAXLEN)
+            updated_length = DXS_CID_MSG_PARAM_DISP_INFO_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_SERV_INFO:
+         updated_length = DXS_CID_MSG_PARAM_SERV_INFO_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_EXTENSION:
+         updated_length = DXS_CID_MSG_PARAM_EXTENSION_FIXLEN;
+         break;
+
+      default:
+         break;
+   }
+
+   return updated_length;
+}
+
+/**
+   Check SIN BT message parameter length
+
+   \param   param  - message parameter
+   \param   length - message length
+
+   \return
+   - updated length
+*/
+static uint8_t dxs_cid_param_length_check_bt(DXS_CID_MsgParam_t param,
+                                              uint8_t length)
+{
+   uint8_t updated_length = length;
+
+   switch (param)
+   {
+      case DXS_CID_MSG_PARAM_DATE_TIME:
+         updated_length = DXS_CID_BT_MSG_PARAM_DATE_TIME_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALLING_LINE_ID:
+         if (updated_length > DXS_CID_BT_MSG_PARAM_CALLING_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_BT_MSG_PARAM_CALLING_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALLED_LINE_ID:
+         if (updated_length > DXS_CID_BT_MSG_PARAM_CALLED_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_BT_MSG_PARAM_CALLED_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_RA_CALLING_LINE_ID:
+         updated_length = DXS_CID_BT_MSG_PARAM_RA_CALLING_LINE_ID_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALLING_PARTY_NAME:
+         if (updated_length > DXS_CID_BT_MSG_PARAM_CALLING_PARTY_NAME_MAXLEN)
+            updated_length = DXS_CID_BT_MSG_PARAM_CALLING_PARTY_NAME_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_RA_CALLING_PARTY_NAME:
+         updated_length = DXS_CID_BT_MSG_PARAM_RA_CALLING_PARTY_NAME_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_CALL_TYPE:
+         updated_length = DXS_CID_BT_MSG_PARAM_CALL_TYPE_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_NUM_MESSAGES:
+         updated_length = DXS_CID_BT_MSG_PARAM_NUM_MESSAGES_FIXLEN;
+         break;
+
+      default:
+         break;
+   }
+
+   return updated_length;
+}
+
+/**
+   Check NTT message parameter length
+
+   \param   param  - message parameter
+   \param   length - message length
+
+   \return
+   - updated length
+*/
+static uint8_t dxs_cid_param_length_check_ntt(DXS_CID_MsgParam_t param,
+                                              uint8_t length)
+{
+   uint8_t updated_length = length;
+
+   switch (param)
+   {
+      case DXS_CID_MSG_PARAM_CALLING_LINE_ID:
+         if (updated_length > DXS_CID_NTT_MSG_PARAM_CALLING_LINE_ID_MAXLEN)
+            updated_length = DXS_CID_NTT_MSG_PARAM_CALLING_LINE_ID_MAXLEN;
+         break;
+
+      case DXS_CID_MSG_PARAM_RA_CALLING_LINE_ID:
+         updated_length = DXS_CID_NTT_MSG_PARAM_RA_CALLING_LINE_ID_FIXLEN;
+         break;
+
+      case DXS_CID_MSG_NTT_EXP_SIGNAL:
+         updated_length = DXS_CID_NTT_MSG_PARAM_EXP_SIGNAL_FIXLEN;
+         break;
+
+      default:
+         break;
+   }
+
+   return updated_length;
+}
+
+/**
+   Check Telcordia message parameter length
+
+   \param   param  - message parameter
+   \param   length - message length
+
+   \return
+   - updated length
+*/
+static uint8_t dxs_cid_param_length_check_tc(DXS_CID_MsgParam_t param,
+                                              uint8_t length)
+{
+   uint8_t updated_length = length;
+
+   switch (param)
+   {
+      /* TODO */
+      default:
+         break;
+   }
+
+   return updated_length;
+}
+
+/**
+   Waiting function for a state machine
+
+   \param   pCid   - pointer to \ref DXS_CID_Ctx_t structure
+
+   \return
+   - DXS_status_t
+*/
+static void dxs_cid_wait (DXS_CID_Ctx_t *pCid)
+{
+   struct timespec ts = {0};
+
+   if (pCid->timeout == 0)
+      return;
+
+   /* wait */
+   clock_gettime (CLOCK_REALTIME, &ts);
+   if (!(pCid->timeout % 1000))
+   {
+      ts.tv_sec += pCid->timeout / 1000;
+   }
+   else
+   {
+      unsigned long ns;
+
+      ns = ts.tv_nsec + pCid->timeout * 1000 * 1000;
+      ts.tv_nsec = ns % (1000 * 1000 * 1000);
+      ts.tv_sec += ns / (1000 * 1000 * 1000);
+   }
+   sem_timedwait(&pCid->sema, &ts);
+}
+
+/* ========================================================================== */
+/*                                 CID SM                               */
+/* ========================================================================== */
+
+/* CID SM final state (success) */
+/**
+   dxs_cid_sm_fin
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_sm_fin(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   DXS_Event_t dxs_event = {0};
+
+   pCid->complete = 1;
+
+   /* Unmute channel */
+   if (pCid->need_unmute)
+   {
+      if (dxs_pcm_ch_mute(pCh, 0) == DXS_statusOk)
+         pCid->need_unmute = 0;
+   }
+
+   /* if called from ring SM, inform ring SM */
+   if (pCid->calling_instance == DXS_CID_CALL_FROM_RING_SM)
+   {
+      DXS_Ring_CidFinished(pCh);
+   }
+   else
+   {
+      /* inform the application */
+      dxs_event.dev = pCh->pParent->nDevNum;
+      dxs_event.ch = pCh->nCh;
+      dxs_event.id = DXS_EVENT_CID_SEQ_END;
+      DXS_EventDispatch(pCh->pParent, &dxs_event);
+   }
+   pthread_detach(pCid->thrd);
+   sem_post(&pCid->sema);
+   return DXS_statusOk;
+}
+
+/* CID SM final state (timeout) */
+/**
+   dxs_cid_sm_err_timeout
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_sm_err_timeout(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   DXS_Event_t dxs_event = {0};
+
+   pCid->complete = 1;
+
+   /* Unmute channel */
+   if (pCid->need_unmute)
+   {
+      if (dxs_pcm_ch_mute(pCh, 0) == DXS_statusOk)
+         pCid->need_unmute = 0;
+   }
+
+   /* inform application */
+   dxs_event.dev = pCh->pParent->nDevNum;
+   dxs_event.ch = pCh->nCh;
+   dxs_event.id = DXS_EVENT_CID_SEQ_ERROR;
+   dxs_event.data.cid_err = DXS_EVENT_CID_TIMEOUT;
+   DXS_EventDispatch(pCh->pParent, &dxs_event);
+
+   pthread_detach(pCid->thrd);
+   sem_post(&pCid->sema);
+   return DXS_statusOk;
+}
+
+/* CID SM final state (incorrect hook state) */
+/**
+   dxs_cid_sm_err_hook
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_sm_err_hook(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   DXS_Event_t dxs_event = {0};
+
+   pCid->complete = 1;
+
+   /* Attempt to stop FSK transmitter */
+   if (pCid->df == DXS_CID_DATA_FSK)
+      DXS_CID_FSK_Stop(pCh);
+   /* Attempt to stop tone */
+   dxs_tone_stop(pCh);
+   /* Restore active line mode */
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+   /* Unmute channel */
+   if (pCid->need_unmute)
+   {
+      if (dxs_pcm_ch_mute(pCh, 0) == DXS_statusOk)
+         pCid->need_unmute = 0;
+   }
+
+   /* inform application */
+   dxs_event.dev = pCh->pParent->nDevNum;
+   dxs_event.ch = pCh->nCh;
+   dxs_event.id = DXS_EVENT_CID_SEQ_ERROR;
+   dxs_event.data.cid_err = DXS_EVENT_CID_HOOK_STATE;
+   DXS_EventDispatch(pCh->pParent, &dxs_event);
+
+   pthread_detach(pCid->thrd);
+   sem_post(&pCid->sema);
+   return DXS_statusOk;
+}
+
+/* ========================================================================== */
+/*                                 ETSI protocol                              */
+/* ========================================================================== */
+
+/* CID SM states - ETSI */
+static int32_t dxs_cid_etsi_init(void *arg);
+static int32_t dxs_cid_etsi_dtas(void *arg);
+static int32_t dxs_cid_etsi_ring(void *arg);
+static int32_t dxs_cid_etsi_after_lr(void *arg);
+static int32_t dxs_cid_dtmf_off(void *arg);
+static int32_t dxs_cid_dtmf_on(void *arg);
+static int32_t dxs_cid_etsi_after_alert(void *arg);
+static int32_t dxs_cid_etsi_data_xmit(void *arg);
+static int32_t dxs_cid_etsi_after_data_xmit(void *arg);
+
+/**
+   dxs_cid_etsi_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_init(void *arg)
+{
+   int32_t ret = DXS_statusOk;
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->as == DXS_CID_AS_DTAS || pCid->as == DXS_CID_AS_LR_DTAS)
+   {
+      dxs_tone_config(pCh, DXS_CID_DTAS_LEVEL1,
+                           DXS_CID_DTAS_LEVEL2,
+                           DXS_CID_DTAS_FREQ1,
+                           DXS_CID_DTAS_FREQ2, 0, 0);
+   }
+
+   if (pCid->as == DXS_CID_AS_NONE)
+   {
+      ret = DXS_SDD_LineModeSet(pCh,
+                             DXS_LINE_FEED_RING_BURST ^ pCid->polarity_initial);
+      pCid->timeout = pCid->tm_etsi.lring;
+      pCid->cid_state = dxs_cid_etsi_ring;
+   }
+   else if (pCid->as == DXS_CID_AS_DTAS)
+   {
+      dxs_tone_start(pCh);
+      pCid->timeout = pCid->tm_etsi.dtas;
+      pCid->cid_state = dxs_cid_etsi_dtas;
+   }
+   else if (pCid->as == DXS_CID_AS_LR_DTAS)
+   {
+      DXS_SDD_LineModeSet(pCh,
+                          DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+      pCid->timeout = pCid->tm_etsi.T0;
+      pCid->cid_state = dxs_cid_etsi_after_lr;
+   }
+   else if (pCid->as == DXS_CID_AS_ETSI_DTMF)
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+      pCid->timeout = pCid->tm_etsi.T0dtmf;
+      pCid->cid_state = dxs_cid_etsi_after_alert;
+   }
+   else if (pCid->as == DXS_CID_AS_RPAS)
+   {
+      ret = DXS_SDD_LineModeSet(pCh,
+                             DXS_LINE_FEED_RING_BURST ^ pCid->polarity_initial);
+      pCid->timeout = pCid->tm_etsi.rpas;
+      pCid->cid_state = dxs_cid_etsi_ring;
+   }
+   return ret;
+}
+
+/**
+   dxs_cid_etsi_dtas
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_dtas(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+
+   if (pCid->as == DXS_CID_AS_DTAS)
+      pCid->timeout = pCid->tm_etsi.T4;
+   else if (pCid->as == DXS_CID_AS_LR_DTAS)
+      pCid->timeout = pCid->tm_etsi.T1;
+
+   pCid->cid_state = dxs_cid_etsi_after_alert;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_ring
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_ring(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+
+   if (pCid->as == DXS_CID_AS_NONE)
+      pCid->timeout = pCid->tm_etsi.T5;
+   else if (pCid->as == DXS_CID_AS_RPAS)
+      pCid->timeout = pCid->tm_etsi.T3;
+
+   pCid->cid_state = dxs_cid_etsi_after_alert;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_after_lr
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_after_lr(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_etsi.dtas;
+   pCid->cid_state = dxs_cid_etsi_dtas;
+   return DXS_statusOk;
+}
+
+/**
+ Silent betwee 2 DTMF digits
+
+  \param  arg
+
+  \return
+  - DXS_status_t
+*/
+
+int32_t dxs_cid_dtmf_off(void *arg)  //YanJC
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   /* stop DTMF tone */
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_etsi.Tdtmf; /*  */
+   pCid->cid_state = dxs_cid_dtmf_on;
+
+   return DXS_statusOk;
+}
+
+/**
+   Send next DTMF digit
+
+   \param  arg
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_cid_dtmf_on(void *arg)  //YanJC
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   uint8_t digi = pCid->xmit_buffer[pCid->xmit_buffer[1]];
+   if (pCid->xmit_length > pCid->xmit_buffer[1])
+   {
+      pCid->xmit_buffer[1] += 1;
+      /* send one digit */
+      dxs_tone_config(pCh, dtmf[digi].level1, dtmf[digi].level2, dtmf[digi].freq1, dtmf[digi].freq2, 0, 0);
+      dxs_tone_start(pCh); 
+      pCid->timeout = pCid->tm_etsi.Tdtmf; /*  */
+      pCid->cid_state = dxs_cid_dtmf_off;
+   }
+   else
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+      /* all digits over. */
+      pCid->timeout = pCid->tm_etsi.T2dtmf;
+      pCid->cid_state = dxs_cid_etsi_after_data_xmit;
+   }
+
+   return DXS_statusOk;
+}
+/**
+   dxs_cid_etsi_after_alert
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_after_alert(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->df == DXS_CID_DATA_FSK)
+   {
+      /* call FSK transmitter */
+      DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_ITU_T, 1, pCid->xmit_buffer,
+                            pCid->xmit_length);
+      pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+	    pCid->cid_state = dxs_cid_etsi_data_xmit;
+   }
+   else if (pCid->df == DXS_CID_DATA_DTMF)
+   {
+      /* call DTMF transmitter */
+      dxs_cid_dtmf_on((void *)pCh);
+   }
+   return DXS_statusOk;
+} 
+
+/**
+   dxs_cid_etsi_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->as == DXS_CID_AS_NONE)
+      pCid->timeout = pCid->tm_etsi.T6;
+   else
+      pCid->timeout = pCid->tm_etsi.T2;
+
+   pCid->cid_state = dxs_cid_etsi_after_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_after_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_after_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->as == DXS_CID_AS_LR_DTAS)
+   {
+      /* restore line polarity */
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+   }
+
+   pCid->timeout = 0;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* CID type2 SM states - ETSI */
+static int32_t dxs_cid_etsi_type2_init(void *arg);
+static int32_t dxs_cid_etsi_type2_silence(void *arg);
+static int32_t dxs_cid_etsi_type2_as(void *arg);
+static int32_t dxs_cid_etsi_type2_wait_ack(void *arg);
+static int32_t dxs_cid_etsi_type2_before_data_xmit(void *arg);
+static int32_t dxs_cid_etsi_type2_data_xmit(void *arg);
+
+/**
+   dxs_cid_etsi_type2_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_type2_init(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_config(pCh, DXS_CID_DTAS_LEVEL1,
+                           DXS_CID_DTAS_LEVEL2,
+                           DXS_CID_DTAS_FREQ1,
+                           DXS_CID_DTAS_FREQ2, 0, 0);
+
+   pCid->timeout = pCid->tm_etsi.t2_T10;
+   pCid->cid_state = dxs_cid_etsi_type2_silence;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_type2_silence
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_type2_silence(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_etsi.t2_dtas;
+   pCid->cid_state = dxs_cid_etsi_type2_as;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_type2_as
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_type2_as(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_etsi.t2_T14;
+   pCid->cid_state = dxs_cid_etsi_type2_wait_ack;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_type2_wait_ack
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_type2_wait_ack(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->ack_detect)
+   {
+      pCid->ack_detect = 0;
+      pCid->timeout = pCid->tm_etsi.t2_T12;
+      pCid->cid_state = dxs_cid_etsi_type2_before_data_xmit;
+   }
+   else
+   {
+      /* Go to timeout state */
+      pCid->timeout = pCid->tm_etsi.t2_T9;
+      pCid->cid_state = dxs_cid_sm_err_timeout;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_type2_before_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_type2_before_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* call FSK transmitter */
+   DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_ITU_T, 1, pCid->xmit_buffer,
+                         pCid->xmit_length);
+
+   pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+   pCid->cid_state = dxs_cid_etsi_type2_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_etsi_type2_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_etsi_type2_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->timeout = pCid->tm_etsi.t2_T13;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                               TELCORDIA protocol                           */
+/* ========================================================================== */
+
+/* CID SM states - Telcordia */
+static int32_t dxs_cid_tc_init(void *arg);
+static int32_t dxs_cid_tc_alert(void *arg);
+static int32_t dxs_cid_tc_after_alert(void *arg);
+static int32_t dxs_cid_tc_data_xmit(void *arg);
+static int32_t dxs_cid_dtmf_off_tc(void *arg);
+static int32_t dxs_cid_dtmf_on_tc(void *arg);
+/**
+   dxs_cid_tc_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_init(void *arg)
+{
+   int32_t ret = DXS_statusOk;
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->as == DXS_CID_AS_OSI)
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+      pCid->timeout = pCid->tm_tc.osi;
+   }
+   else if (pCid->as == DXS_CID_AS_TELCORDIA_DTMF)
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+      pCid->timeout = pCid->tm_tc.T0dtmf;
+      pCid->cid_state = dxs_cid_tc_after_alert;
+   }
+   else /* DXS_CID_AS_NONE */
+   {
+      ret = DXS_SDD_LineModeSet(pCh,
+                             DXS_LINE_FEED_RING_BURST ^ pCid->polarity_initial);
+      pCid->timeout = pCid->tm_tc.lring;
+   }
+   pCid->cid_state = dxs_cid_tc_alert;
+   return ret;
+}
+
+/**
+ Silent betwee 2 DTMF digits
+
+  \param  arg
+
+  \return
+  - DXS_status_t
+*/
+int32_t dxs_cid_dtmf_off_tc(void *arg)  
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   /* stop DTMF tone */
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_tc.Tdtmf; 
+   pCid->cid_state = dxs_cid_dtmf_on_tc;
+
+   return DXS_statusOk;
+}
+
+/**
+   Send next DTMF digit
+
+   \param  arg
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_cid_dtmf_on_tc(void *arg)  
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   uint8_t digi = pCid->xmit_buffer[pCid->xmit_buffer[1]];
+   if (pCid->xmit_length > pCid->xmit_buffer[1])
+   {
+      pCid->xmit_buffer[1] += 1;
+      /* send one digit */
+      dxs_tone_config(pCh, dtmf[digi].level1, dtmf[digi].level2, dtmf[digi].freq1, dtmf[digi].freq2, 0, 0);
+      dxs_tone_start(pCh); 
+      pCid->timeout = pCid->tm_tc.Tdtmf; 
+      pCid->cid_state = dxs_cid_dtmf_off_tc;
+   }
+   else
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+      /* all digits over. */
+      pCid->timeout = pCid->tm_tc.T2dtmf;
+      pCid->cid_state = dxs_cid_etsi_after_data_xmit;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_alert
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_alert(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+   if (pCid->as == DXS_CID_AS_OSI)
+      pCid->timeout = pCid->tm_tc.T1;
+   else /* DXS_CID_AS_NONE */
+      pCid->timeout = pCid->tm_tc.T0;
+   pCid->cid_state = dxs_cid_tc_after_alert;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_after_alert
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_after_alert(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->df == DXS_CID_DATA_FSK)
+   {
+      /* call FSK transmitter */
+      DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_BEL202, 1, pCid->xmit_buffer,
+                            pCid->xmit_length);
+      pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+      pCid->cid_state = dxs_cid_tc_data_xmit;            
+   }
+   else if (pCid->df == DXS_CID_DATA_DTMF)
+   {
+      /* call DTMF transmitter */
+      dxs_cid_dtmf_on_tc((void *)pCh);
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->timeout = pCid->tm_tc.T2;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+
+/* CID type2 SM states - Telcordia */
+static int32_t dxs_cid_tc_type2_init(void *arg);
+static int32_t dxs_cid_tc_type2_osi_first(void *arg);
+static int32_t dxs_cid_tc_type2_silence(void *arg);
+static int32_t dxs_cid_tc_type2_sas(void *arg);
+static int32_t dxs_cid_tc_type2_as_transition(void *arg);
+static int32_t dxs_cid_tc_type2_cas(void *arg);
+static int32_t dxs_cid_tc_type2_wait_ack(void *arg);
+static int32_t dxs_cid_tc_type2_before_data_xmit(void *arg);
+static int32_t dxs_cid_tc_type2_data_xmit(void *arg);
+static int32_t dxs_cid_tc_type2_osi_last(void *arg);
+
+/**
+   dxs_cid_tc_type2_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_init(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+
+
+   if (pCid->tm_tc.t2_osi)
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+      pCid->timeout = pCid->tm_tc.t2_osi;
+      pCid->cid_state = dxs_cid_tc_type2_osi_first;
+   }
+   else
+   {
+      pCid->timeout = pCid->tm_tc.t2_W;
+      pCid->cid_state = dxs_cid_tc_type2_silence;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_osi_first
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_osi_first(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->hook_block = 1;
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+   pCid->timeout = pCid->tm_tc.t2_W;
+   pCid->cid_state = dxs_cid_tc_type2_silence;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_silence
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_silence(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->hook_block = 0;
+   if (pCid->tm_tc.t2_X)
+      dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_tc.t2_X;
+   pCid->cid_state = dxs_cid_tc_type2_sas;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_sas
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_sas(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->tm_tc.t2_X)
+      dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_tc.t2_X1;
+   pCid->cid_state = dxs_cid_tc_type2_as_transition;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_as_transition
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_as_transition(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_config(pCh, DXS_CID_DTAS_LEVEL1,
+                        DXS_CID_DTAS_LEVEL2,
+                        DXS_CID_DTAS_FREQ1,
+                        DXS_CID_DTAS_FREQ2, 0, 0);
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_tc.t2_Y;
+   pCid->cid_state = dxs_cid_tc_type2_cas;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_cas
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_cas(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_tc.t2_T1;
+   pCid->cid_state = dxs_cid_tc_type2_wait_ack;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_wait_ack
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_wait_ack(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->ack_detect)
+   {
+      pCid->ack_detect = 0;
+      pCid->timeout = pCid->tm_tc.t2_Q;
+      pCid->cid_state = dxs_cid_tc_type2_before_data_xmit;
+   }
+   else
+   {
+      /* Go to timeout state */
+      pCid->timeout = 0;
+      pCid->cid_state = dxs_cid_sm_err_timeout;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_before_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_before_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* call FSK transmitter */
+   DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_BEL202, 1, pCid->xmit_buffer,
+                         pCid->xmit_length);
+
+   pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+   pCid->cid_state = dxs_cid_tc_type2_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->tm_tc.t2_osi)
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+      pCid->timeout = pCid->tm_tc.t2_osi;
+      pCid->cid_state = dxs_cid_tc_type2_osi_last;
+   }
+   else
+   {
+      pCid->timeout = pCid->tm_tc.t2_S;
+      pCid->cid_state = dxs_cid_sm_fin;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_tc_type2_osi_last
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_tc_type2_osi_last(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->hook_block = 1;
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+   pCid->timeout = pCid->tm_tc.t2_S;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                                  BT protocol                               */
+/* ========================================================================== */
+
+/* CID SM states - BT */
+static int32_t dxs_cid_bt_init(void *arg);
+static int32_t dxs_cid_bt_after_lr(void *arg);
+static int32_t dxs_cid_bt_dtas(void *arg);
+static int32_t dxs_cid_bt_after_alert(void *arg);
+static int32_t dxs_cid_bt_data_xmit(void *arg);
+static int32_t dxs_cid_bt_after_data_xmit(void *arg);
+
+/**
+   dxs_cid_bt_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_init(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_config(pCh, DXS_CID_DTAS_LEVEL1,
+                           DXS_CID_DTAS_LEVEL2,
+                           DXS_CID_DTAS_FREQ1,
+                           DXS_CID_DTAS_FREQ2, 0, 0);
+
+   DXS_SDD_LineModeSet(pCh,
+                          DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+   pCid->timeout = pCid->tm_bt.T0;
+   pCid->cid_state = dxs_cid_bt_after_lr;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_after_lr
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_after_lr(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_bt.dtas;
+   pCid->cid_state = dxs_cid_bt_dtas;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_dtas
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_dtas(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_bt.T1;
+   pCid->cid_state = dxs_cid_bt_after_alert;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_after_alert
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_after_alert(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* call FSK transmitter */
+   DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_ITU_T, 1, pCid->xmit_buffer,
+                         pCid->xmit_length);
+
+   pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+   pCid->cid_state = dxs_cid_bt_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->timeout = pCid->tm_bt.T2;
+   pCid->cid_state = dxs_cid_bt_after_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_after_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_after_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* restore line polarity */
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+
+   pCid->timeout = 0;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* CID type2 SM states - BT */
+static int32_t dxs_cid_bt_type2_init(void *arg);
+static int32_t dxs_cid_bt_type2_silence(void *arg);
+static int32_t dxs_cid_bt_type2_as(void *arg);
+static int32_t dxs_cid_bt_type2_wait_ack(void *arg);
+static int32_t dxs_cid_bt_type2_before_data_xmit(void *arg);
+static int32_t dxs_cid_bt_type2_data_xmit(void *arg);
+
+/**
+   dxs_cid_bt_type2_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_type2_init(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_config(pCh, DXS_CID_DTAS_LEVEL1,
+                           DXS_CID_DTAS_LEVEL2,
+                           DXS_CID_DTAS_FREQ1,
+                           DXS_CID_DTAS_FREQ2, 0, 0);
+
+   pCid->timeout = pCid->tm_bt.t2_T0;
+   pCid->cid_state = dxs_cid_bt_type2_silence;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_type2_silence
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_type2_silence(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_bt.t2_dtas;
+   pCid->cid_state = dxs_cid_bt_type2_as;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_type2_as
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_type2_as(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_bt.t2_ack;
+   pCid->cid_state = dxs_cid_bt_type2_wait_ack;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_type2_wait_ack
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_type2_wait_ack(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->ack_detect)
+   {
+      pCid->ack_detect = 0;
+      pCid->timeout = pCid->tm_bt.t2_T1;
+      pCid->cid_state = dxs_cid_bt_type2_before_data_xmit;
+   }
+   else
+   {
+      /* Go to timeout state */
+      pCid->timeout = 0;
+      pCid->cid_state = dxs_cid_sm_err_timeout;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_type2_before_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_type2_before_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* call FSK transmitter */
+   DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_ITU_T, 1, pCid->xmit_buffer,
+                         pCid->xmit_length);
+
+   pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+   pCid->cid_state = dxs_cid_bt_type2_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_bt_type2_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_bt_type2_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->timeout = pCid->tm_bt.t2_T2;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                                 NTT protocol                               */
+/* ========================================================================== */
+
+/* CID SM states - NTT */
+static int32_t dxs_cid_ntt_init(void *arg);
+static int32_t dxs_cid_ntt_car_off(void *arg);
+static int32_t dxs_cid_ntt_car_on(void *arg);
+static int32_t dxs_cid_ntt_timeout(void *arg);
+static int32_t dxs_cid_ntt_after_offhook(void *arg);
+static int32_t dxs_cid_ntt_data_xmit(void *arg);
+static int32_t dxs_cid_ntt_wait_onhook(void *arg);
+static int32_t dxs_cid_ntt_after_onhook(void *arg);
+
+/**
+   dxs_cid_ntt_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_init(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* set line feeding modes and proceed with SM */
+   DXS_SDD_LineModeSet(pCh,
+                          DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+   pCid->ntt_timeout = pCid->tm_ntt.T1;
+   pCid->timeout = pCid->tm_ntt.T0;
+   pCid->cid_state = dxs_cid_ntt_car_off;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_car_off
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_car_off(void *arg)
+{
+   int32_t ret = DXS_statusOk;
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->hook_state == DXS_CID_HOOK_STATE_OFFHOOK)
+   {
+      pCid->hook_state_exp = DXS_CID_HOOK_STATE_OFFHOOK;
+      pCid->cid_state = dxs_cid_ntt_after_offhook;
+      pCid->timeout = pCid->tm_ntt.T2;
+   }
+   else
+   {
+      pCid->hook_state_exp =
+                       (DXS_CID_HOOK_STATE_OFFHOOK | DXS_CID_HOOK_STATE_ONHOOK);
+      if (pCid->ntt_timeout <= pCid->tm_ntt.CARon)
+      {
+         /* Timeout - terminate CID */
+         pCid->timeout = 0;
+         pCid->cid_state = dxs_cid_ntt_timeout;
+      }
+      else
+      {
+         ret = DXS_SDD_LineModeSet(pCh,
+                         DXS_LINE_FEED_RINGING_REVPOL ^ pCid->polarity_initial);
+         pCid->ntt_timeout -= pCid->timeout;
+         pCid->timeout = pCid->tm_ntt.CARon;
+         pCid->cid_state = dxs_cid_ntt_car_on;
+      }
+   }
+   return ret;
+}
+
+/**
+   dxs_cid_ntt_car_on
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_car_on(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->hook_state == DXS_CID_HOOK_STATE_OFFHOOK)
+   {
+      pCid->hook_state_exp = DXS_CID_HOOK_STATE_OFFHOOK;
+      pCid->cid_state = dxs_cid_ntt_after_offhook;
+      pCid->timeout = pCid->tm_ntt.T2;
+   }
+   else
+   {
+      DXS_SDD_LineModeSet(pCh,
+                          DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+      if (pCid->ntt_timeout <= pCid->tm_ntt.CARoff)
+      {
+         /* Timeout - terminate CID */
+         pCid->timeout = 0;
+         pCid->cid_state = dxs_cid_ntt_timeout;
+      }
+      else
+      {
+         pCid->ntt_timeout -= pCid->timeout;
+         pCid->timeout = pCid->tm_ntt.CARoff;
+         pCid->cid_state = dxs_cid_ntt_car_off;
+      }
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_timeout
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_timeout(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+
+   pCid->timeout = 0;
+   pCid->cid_state = dxs_cid_sm_err_timeout;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_after_offhook
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_after_offhook(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_ITU_T, 1, pCid->xmit_buffer,
+                                                             pCid->xmit_length);
+   pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+   pCid->cid_state = dxs_cid_ntt_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* set any expected hook state to be able to report timeout if it occurs */
+   pCid->hook_state_exp =
+                       (DXS_CID_HOOK_STATE_OFFHOOK | DXS_CID_HOOK_STATE_ONHOOK);
+   pCid->timeout = pCid->tm_ntt.T3;
+   pCid->cid_state = dxs_cid_ntt_wait_onhook;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_wait_onhook
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_wait_onhook(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pCid->hook_state == DXS_CID_HOOK_STATE_ONHOOK)
+   {
+      pCid->timeout = pCid->tm_ntt.T4;
+      pCid->cid_state = dxs_cid_ntt_after_onhook;
+   }
+   else
+   {
+      /* Report previous off-hook event which was hidden by CID NTT */
+#ifndef DXS_FEAT_HSM
+      DXS_Event_t dxs_event = {0};
+
+      dxs_event.dev = pCh->pParent->nDevNum;
+      dxs_event.ch = pCh->nCh;
+      dxs_event.id = DXS_EVENT_FXS_OFFHOOK;
+      DXS_EventDispatch(pCh->pParent, &dxs_event);
+#else
+      DXS_Dial_HookEvent(pCh, 1, pCid->hook_timestamp);
+#endif
+      /* Go to timeout state */
+      pCid->timeout = 0;
+      pCid->cid_state = dxs_cid_ntt_timeout;
+   }
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_after_onhook
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_after_onhook(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* NTT defines that line polarity should be restored after real off-hook,
+      however we restore polarity right here so the demo application can switch to
+      RING_BURST without errors. This is the only purpose of this state -
+      restore polarity, otherwise this state can be removed. */
+   DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+   pCid->timeout = 0;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* CID type2 SM states - NTT */
+static int32_t dxs_cid_ntt_type2_init(void *arg);
+static int32_t dxs_cid_ntt_type2_silence(void *arg);
+static int32_t dxs_cid_ntt_type2_as_first(void *arg);
+static int32_t dxs_cid_ntt_type2_as_pause(void *arg);
+static int32_t dxs_cid_ntt_type2_as_second(void *arg);
+static int32_t dxs_cid_ntt_type2_before_data_xmit(void *arg);
+static int32_t dxs_cid_ntt_type2_data_xmit(void *arg);
+
+/**
+   dxs_cid_ntt_type2_init
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_init(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->timeout = pCid->tm_ntt.t2_T0;
+   pCid->cid_state = dxs_cid_ntt_type2_silence;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_type2_silence
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_silence(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_config(pCh, DXS_CID_NTT_TYPE2_ATONE_LEVEL1,
+                        DXS_CID_NTT_TYPE2_ATONE_LEVEL2,
+                        DXS_CID_NTT_TYPE2_ATONE_FREQ1,
+                        DXS_CID_NTT_TYPE2_ATONE_FREQ2, 0, 0);
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_ntt.t2_as_first;
+   pCid->cid_state = dxs_cid_ntt_type2_as_first;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_type2_as_first
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_as_first(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_ntt.t2_as_pause;
+   pCid->cid_state = dxs_cid_ntt_type2_as_pause;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_type2_as_pause
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_as_pause(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_config(pCh, DXS_CID_NTT_TYPE2_ATONE_LEVEL1,
+                        DXS_CID_NTT_TYPE2_ATONE_LEVEL2,
+                        DXS_CID_NTT_TYPE2_ATONE_FREQ3,
+                        DXS_CID_NTT_TYPE2_ATONE_FREQ2, 0, 0);
+   dxs_tone_start(pCh);
+   pCid->timeout = pCid->tm_ntt.t2_as_second;
+   pCid->cid_state = dxs_cid_ntt_type2_as_second;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_type2_as_second
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_as_second(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   dxs_tone_stop(pCh);
+   pCid->timeout = pCid->tm_ntt.t2_T1;
+   pCid->cid_state = dxs_cid_ntt_type2_before_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_type2_before_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_before_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* call FSK transmitter */
+   DXS_CID_FSK_Start(pCh, DXS_CID_FSK_V23_ITU_T, 1, pCid->xmit_buffer,
+                         pCid->xmit_length);
+
+   pCid->timeout = 6000; /* just some big value, TODO: reconfirm */
+   pCid->cid_state = dxs_cid_ntt_type2_data_xmit;
+   return DXS_statusOk;
+}
+
+/**
+   dxs_cid_ntt_type2_data_xmit
+
+   \param  arg
+
+   \return
+   - none
+*/
+static int32_t dxs_cid_ntt_type2_data_xmit(void *arg)
+{
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->timeout = pCid->tm_ntt.t2_T2;
+   pCid->cid_state = dxs_cid_sm_fin;
+   return DXS_statusOk;
+}
+
+/* ========================================================================== */
+
+/**
+   CID state machine execution thread
+
+   \param  arg
+
+   \return
+   - none
+*/
+static void *dxs_cid_thread (void *arg)
+{
+   int32_t err;
+   DXS_CHANNEL_t *pCh = (DXS_CHANNEL_t *)arg;
+   DXS_CID_Ctx_t *pCid =
+                     &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   sem_init(&pCid->sema, 0, 0);
+
+   pCid->complete = 0;
+   pCid->ret = DXS_statusOk;
+
+   while (!pCid->complete)
+   {
+      /* check hook state */
+      if (!(pCid->hook_state & pCid->hook_state_exp))
+         pCid->cid_state = dxs_cid_sm_err_hook;
+
+      /* action */
+      if ((err = pCid->cid_state((void *)pCh)) != DXS_statusOk)
+      {
+         pCid->complete = 1;
+         pCid->ret = err;
+
+         /* inform application on this particular error */
+         if (err == DXS_statusDcDcRingCapsExceeded)
+         {
+            DXS_Event_t dxs_event =
+            {
+               .dev = pCh->pParent->nDevNum,
+               .ch = pCh->nCh,
+               .id = DXS_EVENT_CID_SEQ_ERROR,
+               .data.cid_err = DXS_EVENT_CID_HW_RING_LIMIT
+            };
+            DXS_EventDispatch(pCh->pParent, &dxs_event);
+         }
+
+         /* Restore active line mode */
+         DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+         /* Unmute channel */
+         if (pCid->need_unmute)
+         {
+            if (dxs_pcm_ch_mute(pCh, 0) == DXS_statusOk)
+               pCid->need_unmute = 0;
+         }
+         pthread_detach(pCid->thrd);
+         break;
+      }
+
+      /* waiting */
+      dxs_cid_wait(pCid);
+   }
+   sem_destroy(&pCid->sema);
+   pthread_exit((void *)(&pCid->ret));
+}
+
+/**
+   Initialize CID context
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   std  - CID standard \ref DXS_CID_Std_t
+   \param   as   - alert signal \ref DXS_CID_AS_t
+   \param   fmt  - data format \ref DXS_CID_DATA_FMT_t
+   \param   dtmf_ack_idx  - dtmf index for acknowledgment (type2 only)
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_Init(DXS_CHANNEL_t *pCh, DXS_CID_Std_t std, DXS_CID_AS_t as,
+                                   DXS_CID_DATA_FMT_t fmt, uint8_t dtmf_ack_idx)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+      
+   /* Block if CID SM is running already */
+   if ((pCid->magic == DXS_CID_CTX_MAGIC) && (!pCid->complete))
+   {
+      DXS_RETURN(DXS_statusCidInProgress);
+   }
+
+   switch (std)
+   {
+      case DXS_CID_STD_BT:
+      {
+         if (as != DXS_CID_AS_LR_DTAS)
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         pCid->len_check = dxs_cid_param_length_check_bt;
+         break;
+      }
+
+      case DXS_CID_STD_NTT:
+      {
+         if (as != DXS_CID_AS_CAR)
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         pCid->len_check = dxs_cid_param_length_check_ntt;
+         break;
+      }
+
+      case DXS_CID_STD_ETSI:
+      {
+         if ((as == DXS_CID_AS_CAR) || (as == DXS_CID_AS_OSI))
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         pCid->len_check = dxs_cid_param_length_check_etsi;
+         break;
+      }
+
+      case DXS_CID_STD_TELCORDIA:
+      {
+         if ((as != DXS_CID_AS_NONE) && (as != DXS_CID_AS_OSI))
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         pCid->len_check = dxs_cid_param_length_check_tc;
+         break;
+      }
+
+      default:
+      {
+         DXS_RETURN(DXS_statusCidStdNotSupported);
+      }
+   }
+
+   switch (fmt)
+   {
+      case DXS_CID_DATA_FSK:
+      case DXS_CID_DATA_DTMF:
+         break;
+
+      default:
+      {
+         DXS_RETURN(DXS_statusInvalidParam);
+      }
+   }
+
+   /* refresh message containers */
+   dxs_cid_msg_clearall(pCid);
+
+   pCid->magic = DXS_CID_CTX_MAGIC;
+   pCid->complete = 1;
+   pCid->std = std;
+   pCid->as = as;
+   pCid->df = fmt;
+   pCid->dtmf_ack_idx = dtmf_ack_idx;
+
+   /* default timers for ETSI */
+   pCid->tm_etsi.lring = DXS_CID_ETSI_LONG_RING_MS;
+   pCid->tm_etsi.dtas = DXS_CID_ETSI_DTAS_MS;
+   pCid->tm_etsi.rpas = DXS_CID_ETSI_RPAS_MS;
+   pCid->tm_etsi.T0 = DXS_CID_ETSI_T0_DEFAULT;
+   pCid->tm_etsi.T1 = DXS_CID_ETSI_T1_DEFAULT;
+   pCid->tm_etsi.T2 = DXS_CID_ETSI_T2_DEFAULT;
+   pCid->tm_etsi.T3 = DXS_CID_ETSI_T3_DEFAULT;
+   pCid->tm_etsi.T4 = DXS_CID_ETSI_T4_DEFAULT;
+   pCid->tm_etsi.T5 = DXS_CID_ETSI_T5_DEFAULT;
+   pCid->tm_etsi.T6 = DXS_CID_ETSI_T6_DEFAULT;
+   pCid->tm_etsi.t2_dtas = DXS_CID_ETSI_TYPE2_DTAS_MS;
+   pCid->tm_etsi.t2_T14 = DXS_CID_ETSI_TYPE2_T14_DEFAULT;
+   pCid->tm_etsi.t2_T10 = DXS_CID_ETSI_TYPE2_T10_DEFAULT;
+   pCid->tm_etsi.t2_T12 = DXS_CID_ETSI_TYPE2_T12_DEFAULT;
+   pCid->tm_etsi.t2_T13 =  DXS_CID_ETSI_TYPE2_T13_DEFAULT;
+   pCid->tm_etsi.t2_T9 = DXS_CID_ETSI_TYPE2_T9_DEFAULT;
+   pCid->tm_etsi.T0dtmf = DXS_CID_ETSI_T0dtmf_DEFAULT;
+   pCid->tm_etsi.Tdtmf = DXS_CID_ETSI_Tdtmf_DEFAULT;
+   pCid->tm_etsi.T2dtmf = DXS_CID_ETSI_T2dtmf_DEFAULT;
+
+   /* default timers for Telcordia */
+   pCid->tm_tc.lring = DXS_CID_TELCORDIA_LONG_RING_MS;
+   pCid->tm_tc.osi = DXS_CID_TELCORDIA_OSI_MS;
+   pCid->tm_tc.T0 = DXS_CID_TELCORDIA_T0_DEFAULT;
+   pCid->tm_tc.T1 = DXS_CID_TELCORDIA_T1_DEFAULT;
+   pCid->tm_tc.T2 = DXS_CID_TELCORDIA_T2_DEFAULT;
+   pCid->tm_tc.t2_osi = DXS_CID_TELCORDIA_TYPE2_OSI_MS;
+   pCid->tm_tc.t2_W = DXS_CID_TELCORDIA_TYPE2_W_MS;
+   pCid->tm_tc.t2_X = DXS_CID_TELCORDIA_TYPE2_X_MS;
+   pCid->tm_tc.t2_X1 = DXS_CID_TELCORDIA_TYPE2_X1_MS;
+   pCid->tm_tc.t2_Y = DXS_CID_TELCORDIA_TYPE2_Y_MS;
+   pCid->tm_tc.t2_T1 = DXS_CID_TELCORDIA_TYPE2_T1_MS;
+   pCid->tm_tc.t2_Q = DXS_CID_TELCORDIA_TYPE2_Q_MS;
+   pCid->tm_tc.t2_S = DXS_CID_TELCORDIA_TYPE2_S_MS;
+   pCid->tm_tc.T0dtmf = DXS_CID_TELCORDIA_T0dtmf_DEFAULT;
+   pCid->tm_tc.Tdtmf = DXS_CID_TELCORDIA_Tdtmf_DEFAULT;
+   pCid->tm_tc.T2dtmf = DXS_CID_TELCORDIA_T2dtmf_DEFAULT;  
+
+   /* default timers for BT */
+   pCid->tm_bt.dtas = DXS_CID_BT_DTAS_MS;
+   pCid->tm_bt.T0 = DXS_CID_BT_T0_DEFAULT;
+   pCid->tm_bt.T1 = DXS_CID_BT_T1_DEFAULT;
+   pCid->tm_bt.T2 = DXS_CID_BT_T2_DEFAULT;
+   pCid->tm_bt.t2_dtas = DXS_CID_BT_TYPE2_DTAS_MS;
+   pCid->tm_bt.t2_ack = DXS_CID_BT_TYPE2_ACK_MS;
+   pCid->tm_bt.t2_T0 = DXS_CID_BT_TYPE2_T0_DEFAULT;
+   pCid->tm_bt.t2_T1 = DXS_CID_BT_TYPE2_T1_DEFAULT;
+   pCid->tm_bt.t2_T2 = DXS_CID_BT_TYPE2_T2_DEFAULT;
+
+   /* default timers for NTT */
+   pCid->tm_ntt.CARon = DXS_CID_NTT_CARON_MS;
+   pCid->tm_ntt.CARoff = DXS_CID_NTT_CAROFF_MS;
+   pCid->tm_ntt.T0 = DXS_CID_NTT_T0_DEFAULT;
+   pCid->tm_ntt.T1 = DXS_CID_NTT_T1_DEFAULT;
+   pCid->tm_ntt.T2 = DXS_CID_NTT_T2_DEFAULT;
+   pCid->tm_ntt.T3 = DXS_CID_NTT_T3_DEFAULT;
+   pCid->tm_ntt.T4 = DXS_CID_NTT_T4_DEFAULT;
+   pCid->tm_ntt.t2_as_first = DXS_CID_NTT_TYPE2_AS1_MS;
+   pCid->tm_ntt.t2_as_pause = DXS_CID_NTT_TYPE2_AS_PAUSE_MS;
+   pCid->tm_ntt.t2_as_second = DXS_CID_NTT_TYPE2_AS2_MS;
+   pCid->tm_ntt.t2_T0 = DXS_CID_NTT_TYPE2_T0_DEFAULT;
+   pCid->tm_ntt.t2_T1 = DXS_CID_NTT_TYPE2_T1_DEFAULT;
+   pCid->tm_ntt.t2_T2 = DXS_CID_NTT_TYPE2_T2_DEFAULT;
+
+   return DXS_statusOk;
+}
+
+/**
+   Timers configuration
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   std - CID standard \ref DXS_CID_Std_t
+   \param   pTimers - timer configuration \ref DXS_CID_Timers_t
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_TimerConfig(DXS_CHANNEL_t *pCh,
+                              DXS_CID_Std_t std, DXS_CID_Timers_t *pTimers)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* check if pCid is initialized */
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (std == DXS_CID_STD_ETSI)
+   {
+      pCid->tm_etsi.lring = pTimers->etsi.lring;
+      pCid->tm_etsi.dtas = pTimers->etsi.dtas;
+      pCid->tm_etsi.rpas = pTimers->etsi.rpas;
+      pCid->tm_etsi.T0 = pTimers->etsi.T0;
+      pCid->tm_etsi.T1 = pTimers->etsi.T1;
+      pCid->tm_etsi.T2 = pTimers->etsi.T2;
+      pCid->tm_etsi.T3 = pTimers->etsi.T3;
+      pCid->tm_etsi.T4 = pTimers->etsi.T4;
+      pCid->tm_etsi.T5 = pTimers->etsi.T5;
+      pCid->tm_etsi.T6 = pTimers->etsi.T6;
+      pCid->tm_etsi.t2_dtas = pTimers->etsi.t2_dtas;
+      pCid->tm_etsi.t2_T14 = pTimers->etsi.t2_T14;
+      pCid->tm_etsi.t2_T10 = pTimers->etsi.t2_T10;
+      pCid->tm_etsi.t2_T12 = pTimers->etsi.t2_T12;
+      pCid->tm_etsi.t2_T13 = pTimers->etsi.t2_T13;
+      pCid->tm_etsi.t2_T9 = pTimers->etsi.t2_T9;
+   }
+   else if (std == DXS_CID_STD_TELCORDIA)
+   {
+      pCid->tm_tc.lring = pTimers->tc.lring;
+      pCid->tm_tc.osi = pTimers->tc.osi;
+      pCid->tm_tc.T0 = pTimers->tc.T0;
+      pCid->tm_tc.T1 = pTimers->tc.T1;
+      pCid->tm_tc.T2 = pTimers->tc.T2;
+      pCid->tm_tc.t2_osi = pTimers->tc.t2_osi;
+      pCid->tm_tc.t2_W = pTimers->tc.t2_W;
+      pCid->tm_tc.t2_X = pTimers->tc.t2_X;
+      pCid->tm_tc.t2_X1 = pTimers->tc.t2_X1;
+      pCid->tm_tc.t2_Y = pTimers->tc.t2_Y;
+      pCid->tm_tc.t2_T1 = pTimers->tc.t2_T1;
+      pCid->tm_tc.t2_Q = pTimers->tc.t2_Q;
+      pCid->tm_tc.t2_S = pTimers->tc.t2_S;
+   }
+   else if (std == DXS_CID_STD_BT)
+   {
+      pCid->tm_bt.dtas = pTimers->bt.dtas;
+      pCid->tm_bt.T0 = pTimers->bt.T0;
+      pCid->tm_bt.T1 = pTimers->bt.T1;
+      pCid->tm_bt.T2 = pTimers->bt.T2;
+      pCid->tm_bt.t2_dtas = pTimers->bt.t2_dtas;
+      pCid->tm_bt.t2_ack = pTimers->bt.t2_ack;
+      pCid->tm_bt.t2_T0 = pTimers->bt.t2_T0;
+      pCid->tm_bt.t2_T1 = pTimers->bt.t2_T1;
+      pCid->tm_bt.t2_T2 = pTimers->bt.t2_T2;
+   }
+   else if (std == DXS_CID_STD_NTT)
+   {
+      pCid->tm_ntt.CARon = pTimers->ntt.CARon;
+      pCid->tm_ntt.CARoff = pTimers->ntt.CARoff;
+      pCid->tm_ntt.T0 = pTimers->ntt.T0;
+      pCid->tm_ntt.T1 = pTimers->ntt.T1;
+      pCid->tm_ntt.T2 = pTimers->ntt.T2;
+      pCid->tm_ntt.T3 = pTimers->ntt.T3;
+      pCid->tm_ntt.T4 = pTimers->ntt.T4;
+      pCid->tm_ntt.t2_as_first = pTimers->ntt.t2_as_first;
+      pCid->tm_ntt.t2_as_pause = pTimers->ntt.t2_as_pause;
+      pCid->tm_ntt.t2_as_second = pTimers->ntt.t2_as_second;
+      pCid->tm_ntt.t2_T0 = pTimers->ntt.t2_T0;
+      pCid->tm_ntt.t2_T1 = pTimers->ntt.t2_T1;
+      pCid->tm_ntt.t2_T2 = pTimers->ntt.t2_T2;
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Update CId message
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   msg_type - message type \ref DXS_CID_MsgType_t
+   \param   param - message parameter \ref DXS_CID_MsgParam_t
+   \param   pData - message parameter data
+   \param   length - message parameter data length
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_MsgUpdate(DXS_CHANNEL_t *pCh, DXS_CID_MsgType_t msg_type,
+                          DXS_CID_MsgParam_t param, char *pData, uint8_t length)
+{
+   uint32_t i, found = 0;
+   dxs_cid_message_t *pMsg, *p;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* check if pCid is initialized */
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   pMsg = dxs_cid_message_get(pCid, msg_type);
+
+   p = pMsg;
+
+   /* check if message parameter already exists */
+   while (p != NULL)
+   {
+      if (p->type == param)
+      {
+         found = 1;
+         break;
+      }
+      p = p->next;
+   }
+
+   if (found)
+   {
+      if (p->len != length)
+      {
+         p->data = realloc(p->data, length);
+         p->len = length;
+      }
+
+      if (pData != NULL)
+      {
+         for (i=0; i<length; i++)
+         {
+            if (p->data)
+               p->data[i] = *pData++;
+         }
+      }
+   }
+   else
+   {
+      dxs_cid_message_t *pMsgElem;
+      uint8_t updated_len = pCid->len_check(param, length);
+
+      /* allocate memory for the new element */
+      pMsgElem = calloc(1, sizeof(*pMsgElem));
+      if (pMsgElem == NULL)
+         return DXS_statusError;
+      pMsgElem->type = param;
+      /* update the length for malloc */
+      pMsgElem->data = malloc(updated_len);
+      if (pMsgElem->data == NULL)
+      {
+         free(pMsgElem);
+         return DXS_statusError;
+      }
+      if (pData != NULL)
+      {
+         for (i=0; i<updated_len; i++)
+            pMsgElem->data[i] = *pData++;
+      }
+      pMsgElem->len = updated_len;
+      pMsgElem->next = NULL;
+      /* add the new element to the bottom */
+      if (pMsg == NULL)
+      {
+         dxs_cid_message_set(pCid, msg_type, pMsgElem);
+      }
+      else
+      {
+         p = pMsg;
+
+         while (p->next != NULL)
+            p = p->next;
+
+         p->next = pMsgElem;
+      }
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Clean all messages in CID context
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_MsgCleanup(DXS_CHANNEL_t *pCh)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* check if pCid is initialized */
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* vipe all configured messages (if any) */
+   dxs_cid_msg_clearall(pCid);
+
+   return DXS_statusOk;
+}
+
+/**
+   Start CID TypeI message playout
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   msg_type - type of message to play \ref DXS_CID_MsgType_t
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_TypeI_Play(DXS_CHANNEL_t *pCh, DXS_CID_MsgType_t msg_type,
+                                       uint8_t calling_instance)
+{
+   int32_t ret, line_mode = 0;
+   pthread_attr_t cid_thread_attr;
+   struct sched_param cid_thread_param;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   uint16_t unMarkBits, unSeizureBits;
+
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!pCid->complete)
+   {
+      DXS_RETURN(DXS_statusCidInProgress);
+   }
+
+   pCid->calling_instance = calling_instance;
+
+   switch (pCid->std)
+   {
+      case DXS_CID_STD_BT:
+      {
+         if (pCid->as != DXS_CID_AS_LR_DTAS)
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         unMarkBits = DXS_CID_FSK_BT_MARK_DEFAULT;
+         unSeizureBits = DXS_CID_FSK_SEIZURE_DEFAULT;
+         pCid->cid_state = dxs_cid_bt_init;
+         break;
+      }
+
+      case DXS_CID_STD_NTT:
+      {
+         if (pCid->as != DXS_CID_AS_CAR)
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         unMarkBits = DXS_CID_FSK_MARK_DEFAULT;
+         unSeizureBits = 0;
+         pCid->cid_state = dxs_cid_ntt_init;
+         break;
+      }
+
+      case DXS_CID_STD_ETSI:
+      {
+         if ((pCid->as == DXS_CID_AS_CAR) || (pCid->as == DXS_CID_AS_OSI))
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         unMarkBits = DXS_CID_FSK_MARK_DEFAULT;
+         unSeizureBits = DXS_CID_FSK_SEIZURE_DEFAULT;
+         if (pCid->calling_instance == DXS_CID_CALL_FROM_RING_SM &&
+                 pCid->as == DXS_CID_AS_NONE)
+         {
+            pCid->cid_state = dxs_cid_etsi_ring;
+         }
+         else
+         {
+            pCid->cid_state = dxs_cid_etsi_init;
+         }
+         break;
+      }
+
+      case DXS_CID_STD_TELCORDIA:
+      {
+         if ((pCid->as != DXS_CID_AS_NONE) && (pCid->as != DXS_CID_AS_OSI))
+         {
+            DXS_RETURN(DXS_statusCidInvalidAlertSignal);
+         }
+         unMarkBits = DXS_CID_FSK_MARK_DEFAULT;
+         unSeizureBits = DXS_CID_FSK_SEIZURE_DEFAULT;
+
+         if (pCid->calling_instance == DXS_CID_CALL_FROM_RING_SM &&
+                 pCid->as == DXS_CID_AS_NONE)
+         {
+            pCid->cid_state = dxs_cid_tc_alert;
+         }
+         else
+         {
+            pCid->cid_state = dxs_cid_tc_init;
+         }
+         break;
+      }
+
+      default:
+      {
+         DXS_RETURN(DXS_statusCidStdNotSupported);
+      }
+   }
+
+   /* set expected hook state */
+   pCid->hook_state_exp = DXS_CID_HOOK_STATE_ONHOOK;
+   /* do not block off-hook events */
+   pCid->hook_block = 0;
+
+   /* prepare message for transmission */
+   if (pCid->df == DXS_CID_DATA_FSK)
+   {
+      if (pCid->std == DXS_CID_STD_NTT)
+         ret = dxs_cid_fsk_buffer_prepare_ntt(pCid, msg_type);
+      else
+      ret = dxs_cid_fsk_buffer_prepare(pCid, msg_type);
+      if (ret)
+      {
+         DXS_RETURN(ret);
+      }
+      DXS_FSK_Configure(pCh, DXS_CID_FSK_LEVEL_DEFAULT,
+                                                     unSeizureBits, unMarkBits);
+   }
+   else
+   {
+      dxs_cid_dtmf_buffer_prepare(pCid, msg_type);
+   }
+
+   /* Verify line mode and store the polarity */
+   ret = DXS_SDD_LineModeGet(pCh, &line_mode);
+   if (ret == DXS_statusOk)
+   {
+      switch (line_mode)
+      {
+         case DXS_LINE_FEED_STANDBY:
+            DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE);
+            pCid->polarity_initial = DXS_CID_LINE_MODE_POLARITY_FLAG_NORMAL;
+            break;
+         case DXS_LINE_FEED_ACTIVE:
+            pCid->polarity_initial = DXS_CID_LINE_MODE_POLARITY_FLAG_NORMAL;
+            break;
+         case DXS_LINE_FEED_ACTIVE_REVPOL:
+            pCid->polarity_initial = DXS_CID_LINE_MODE_POLARITY_FLAG_REVERSED;
+            break;
+         default:
+            /* Incorrect line feed mode */
+            DXS_RETURN(DXS_statusCidInvalidLineMode);
+            break;
+      }
+
+      /* TODO: verify that a telephone is on-hook */
+      /* Set on-hook */
+      pCid->hook_state = DXS_CID_HOOK_STATE_ONHOOK;
+
+      /* Set highest priority for CID thread handling */
+      pthread_attr_init(&cid_thread_attr);
+
+      cid_thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
+      pthread_attr_setschedparam(&cid_thread_attr, &cid_thread_param);
+
+      pthread_attr_setschedpolicy(&cid_thread_attr, SCHED_RR);
+
+      /* roll it */
+      if (pthread_create(&pCid->thrd, &cid_thread_attr, dxs_cid_thread, (void *)pCh))
+      {
+         pthread_attr_destroy(&cid_thread_attr);
+         DXS_RETURN(DXS_statusThreadCreatError);
+      }
+      pthread_attr_destroy(&cid_thread_attr);
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Start CID TypeII message playout
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   msg_type - type of message to play \ref DXS_CID_MsgType_t
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_TypeII_Play(DXS_CHANNEL_t *pCh, DXS_CID_MsgType_t msg_type)
+{
+   int32_t ret, line_mode = 0;
+   pthread_attr_t cid_thread_attr;
+   struct sched_param cid_thread_param;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   uint16_t unMarkBits, unSeizureBits;
+
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!pCid->complete)
+   {
+      DXS_RETURN(DXS_statusCidInProgress);
+   }
+
+   switch (pCid->std)
+   {
+      case DXS_CID_STD_BT:
+      {
+         unMarkBits = DXS_CID_FSK_BT_MARK_DEFAULT;
+         unSeizureBits = 0;
+         pCid->cid_state = dxs_cid_bt_type2_init;
+         break;
+      }
+
+      case DXS_CID_STD_NTT:
+      {
+         unMarkBits = DXS_CID_FSK_MARK_DEFAULT;
+         unSeizureBits = 0;
+         pCid->cid_state = dxs_cid_ntt_type2_init;
+         break;
+      }
+
+      case DXS_CID_STD_ETSI:
+      {
+         unMarkBits = DXS_CID_FSK_ETSI_TYPE2_MARK_DEFAULT;
+         unSeizureBits = 0;
+         pCid->cid_state = dxs_cid_etsi_type2_init;
+         break;
+      }
+
+      case DXS_CID_STD_TELCORDIA:
+      {
+         unMarkBits = DXS_CID_FSK_MARK_DEFAULT;
+         unSeizureBits = 0;
+         pCid->cid_state = dxs_cid_tc_type2_init;
+         break;
+      }
+
+      default:
+      {
+         DXS_RETURN(DXS_statusCidStdNotSupported);
+      }
+   }
+
+   /* set expected hook state */
+   pCid->hook_state_exp = DXS_CID_HOOK_STATE_OFFHOOK;
+   /* clear ACK detection */
+   pCid->ack_detect = 0;
+   /* do not block off-hook events */
+   pCid->hook_block = 0;
+
+   /* prepare message for transmission */
+   if (pCid->df == DXS_CID_DATA_FSK)
+   {
+      if (pCid->std == DXS_CID_STD_NTT)
+         ret = dxs_cid_fsk_buffer_prepare_ntt(pCid, msg_type);
+      else
+         ret = dxs_cid_fsk_buffer_prepare(pCid, msg_type);
+      if (ret)
+      {
+         DXS_RETURN(ret);
+      }
+      DXS_FSK_Configure(pCh, DXS_CID_FSK_LEVEL_DEFAULT,
+                                                     unSeizureBits, unMarkBits);
+   }
+   else
+   {
+      dxs_cid_dtmf_buffer_prepare(pCid, msg_type);
+   }
+
+   /* Verify line mode and store the polarity */
+   ret = DXS_SDD_LineModeGet(pCh, &line_mode);
+   if (ret == DXS_statusOk)
+   {
+      switch (line_mode)
+      {
+         case DXS_LINE_FEED_ACTIVE:
+            pCid->polarity_initial = DXS_CID_LINE_MODE_POLARITY_FLAG_NORMAL;
+            break;
+         case DXS_LINE_FEED_ACTIVE_REVPOL:
+            pCid->polarity_initial = DXS_CID_LINE_MODE_POLARITY_FLAG_REVERSED;
+            break;
+         default:
+            /* Incorrect line feed mode */
+            DXS_RETURN(DXS_statusCidInvalidLineMode);
+            break;
+      }
+
+      /* TODO: verify that a telephone is off-hook */
+      /* Set off-hook flag */
+      pCid->hook_state = DXS_CID_HOOK_STATE_OFFHOOK;
+
+      /* Mute PCM channel */
+      if (dxs_pcm_ch_mute(pCh, 1) == DXS_statusOk)
+         pCid->need_unmute = 1;
+
+      /* Set highest priority for CID thread handling */
+      pthread_attr_init(&cid_thread_attr);
+
+      cid_thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
+      pthread_attr_setschedparam(&cid_thread_attr, &cid_thread_param);
+
+      pthread_attr_setschedpolicy(&cid_thread_attr, SCHED_RR);
+
+      /* roll it */
+      if (pthread_create(&pCid->thrd, &cid_thread_attr, dxs_cid_thread, (void *)pCh))
+      {
+         pthread_attr_destroy(&cid_thread_attr);
+         DXS_RETURN(DXS_statusThreadCreatError);
+      }
+      pthread_attr_destroy(&cid_thread_attr);
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Stop CID state machine
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_Stop(DXS_CHANNEL_t *pCh)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   void    *ret_status;
+   int32_t err;
+
+   if (!pCid->complete)
+   {
+      pCid->complete = 1;
+
+      /* attempt to terminate all possible states of CID sequence */
+      if (pCid->cid_state == dxs_cid_ntt_car_on)
+      {
+         /* Special case, need to stop ringing with the corresponded polarity */
+         DXS_SDD_LineModeSet(pCh,
+                          DXS_LINE_FEED_ACTIVE_REVPOL ^ pCid->polarity_initial);
+      }
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+      DXS_CID_FSK_Stop(pCh);
+      dxs_tone_stop(pCh);
+      if (pCid->need_unmute)
+         dxs_pcm_ch_mute(pCh, 0);
+
+      sem_post(&pCid->sema);
+
+     /* wait for the thread to exit */
+     err = pthread_join (pCid->thrd, &ret_status);
+     if (err)
+     {
+        DXS_RETURN(DXS_statusThreadStopError);
+     }
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Handle DTMF tone
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   pEvent  - DXS_event_t data
+
+   \return
+   - uint_8
+*/
+uint8_t DXS_CID_EventDtmf(DXS_CHANNEL_t *pCh, DXS_Event_t *pEvent)
+{
+   uint8_t ret = 1;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (!pCid->complete)
+   {
+      if (pCid->std == DXS_CID_STD_BT)
+      {
+         /* Check if dtmf event should not be reported to the app */
+         if (pCid->cid_state == dxs_cid_bt_type2_wait_ack)
+         {
+            if (pEvent->data.dtmf.digit == pCid->dtmf_ack_idx)
+            {
+               /* Set ack flag and wake up */
+               pCid->ack_detect = 1;
+               sem_post(&pCid->sema);
+               ret = 0;
+            }
+         }
+      }
+      else if (pCid->std == DXS_CID_STD_TELCORDIA)
+      {
+         /* Check if dtmf event should not be reported to the app */
+         if (pCid->cid_state == dxs_cid_tc_type2_wait_ack)
+         {
+            if (pEvent->data.dtmf.digit == pCid->dtmf_ack_idx)
+            {
+               /* Set ack flag and wake up */
+               pCid->ack_detect = 1;
+               sem_post(&pCid->sema);
+               ret = 0;
+            }
+         }
+      }
+      else if (pCid->std == DXS_CID_STD_ETSI)
+      {
+         /* Check if dtmf event should not be reported to the app */
+         if (pCid->cid_state == dxs_cid_etsi_type2_wait_ack)
+         {
+            if (pEvent->data.dtmf.digit == pCid->dtmf_ack_idx)
+            {
+               /* Set ack flag and wake up */
+               pCid->ack_detect = 1;
+               sem_post(&pCid->sema);
+               ret = 0;
+            }
+         }
+      }
+   }
+
+   return ret;
+}
+
+/**
+   Handle off-hook
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   timestamp  - FW timestamp of hook event
+
+   \return
+   - uint_8
+*/
+uint8_t DXS_CID_EventOffhook(DXS_CHANNEL_t *pCh, uint16_t timestamp)
+{
+   uint8_t ret = 1;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if ((pCid->magic == DXS_CID_CTX_MAGIC) && (!pCid->complete))
+   {
+      if ((pCid->std == DXS_CID_STD_TELCORDIA) && (pCid->hook_block))
+      {
+         /* Hide first off-hook event at the end of OSI */
+         pCid->hook_block = 0;
+         ret = 0;
+      }
+      else
+      {
+         if (pCid->std == DXS_CID_STD_NTT)
+         {
+            /* Check if off-hook event should not be reported to the app */
+            if ((pCid->cid_state == dxs_cid_ntt_car_off) ||
+                                        (pCid->cid_state == dxs_cid_ntt_car_on))
+               ret = 0;
+         }
+
+         /* Set off-hook and wake up */
+         pCid->hook_state = DXS_CID_HOOK_STATE_OFFHOOK;
+         pCid->hook_timestamp = timestamp;
+         sem_post(&pCid->sema);
+      }
+   }
+
+   return ret;
+}
+
+#ifdef DXS_FEAT_HSM
+/**
+   Handle OPC for disabled
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - uint_8
+*/
+uint8_t DXS_CID_EventOpcDisabled(DXS_CHANNEL_t *pCh)
+{
+   uint8_t ret = 1;
+   DXS_CID_Ctx_t *pCid;
+
+   if (pCh != NULL)
+   {
+      if (pCh->pParent != NULL)
+      {
+         pCid = &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+         if ((pCid->magic == DXS_CID_CTX_MAGIC) && (!pCid->complete))
+         {
+            if ((pCid->std == DXS_CID_STD_TELCORDIA) &&
+                             ((pCid->cid_state == dxs_cid_tc_type2_osi_first) ||
+                              (pCid->cid_state == dxs_cid_tc_type2_osi_last)))
+            {
+               /* Do not report OPC to HSM */
+               ret = 0;
+            }
+         }
+      }
+   }
+
+   return ret;
+}
+#endif
+
+/**
+   Handle on-hook
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   timestamp  - FW timestamp of hook event
+
+   \return
+   - uint_8
+*/
+uint8_t DXS_CID_EventOnhook(DXS_CHANNEL_t *pCh, uint16_t timestamp)
+{
+   uint8_t ret = 1;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if ((pCid->magic == DXS_CID_CTX_MAGIC) && (!pCid->complete))
+   {
+      if (pCid->std == DXS_CID_STD_NTT)
+      {
+         /* Check if on-hook event should not be reported to the app */
+         if (pCid->cid_state == dxs_cid_ntt_wait_onhook)
+            ret = 0;
+      }
+
+      /* Set on-hook and wake up */
+      pCid->hook_state = DXS_CID_HOOK_STATE_ONHOOK;
+      pCid->hook_timestamp = timestamp;
+      sem_post(&pCid->sema);
+   }
+
+   return ret;
+}
+
+/**
+   Handle FSK transmit complete
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - none
+*/
+void DXS_CID_FSK_SendComplete(DXS_CHANNEL_t *pCh)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   sem_post(&pCid->sema);
+}
+
+/**
+   Handle FSK transmit error
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - none
+*/
+void DXS_CID_FSK_SendError(DXS_CHANNEL_t *pCh)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+   DXS_Event_t dxs_event = {0};
+   void    *ret_status;
+
+   if (!pCid->complete)
+   {
+       pCid->complete = 1;
+
+       /* attempt to terminate all possible states of CID sequence */
+       DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE ^ pCid->polarity_initial);
+       DXS_CID_FSK_Stop(pCh);
+       dxs_tone_stop(pCh);
+       if (pCid->need_unmute)
+          dxs_pcm_ch_mute(pCh, 0);
+
+       sem_post(&pCid->sema);
+
+       /* wait for the thread to exit */
+       pthread_join (pCid->thrd, &ret_status);
+   }
+
+   /* inform application */
+   dxs_event.dev = pCh->pParent->nDevNum;
+   dxs_event.ch = pCh->nCh;
+   dxs_event.id = DXS_EVENT_CID_SEQ_ERROR;
+   dxs_event.data.cid_err = DXS_EVENT_CID_FSK_BUF;
+   DXS_EventDispatch(pCh->pParent, &dxs_event);
+}
+
+/**
+   Cleanup CID context
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - none
+*/
+void DXS_CID_Cleanup(DXS_CHANNEL_t *pCh)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pCid->magic = 0;
+}
+
+/**
+   Get CID sequence length in units of 50ms
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   pLen - pointer to CID sequence length (output)
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_LengthBitsGet(DXS_CHANNEL_t *pCh, int32_t *pLen)
+{
+   int32_t cid_len_ms;
+   uint16_t fsk_buffer_bytes = 0;
+   dxs_cid_message_t *p, *pMsg;
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* check if pCid is initialized */
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   pMsg = dxs_cid_message_get(pCid, DXS_CID_MSG_TYPE_CS);
+
+   p = pMsg;
+   /* calculate total length for an FSK buffer */
+   while (p != NULL)
+   {
+      fsk_buffer_bytes += (p->len + 2); /* + parameter code + length byte */
+      p = p->next;
+   }
+   fsk_buffer_bytes += 3; /* + message type code + total length byte + checksum */
+
+   if (pCid->std == DXS_CID_STD_ETSI && pCid->as == DXS_CID_AS_NONE)
+   {
+      /* T5 + SEIZURE + MARK + FSK + T6 */
+      cid_len_ms = pCid->tm_etsi.T5 + pCid->tm_etsi.T6 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_MARK_DEFAULT +
+                    (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else if (pCid->std == DXS_CID_STD_ETSI && pCid->as == DXS_CID_AS_DTAS)
+   {
+      /* DTAS + T4 + SEIZ + MARK + FSK + T2 */
+      cid_len_ms = pCid->tm_etsi.dtas + pCid->tm_etsi.T4 + pCid->tm_etsi.T2 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_MARK_DEFAULT +
+                    (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else if (pCid->std == DXS_CID_STD_ETSI && pCid->as == DXS_CID_AS_RPAS)
+   {
+      /* RPAS + T3 + SEIZ + MARK + FSK + T2 */
+      cid_len_ms = pCid->tm_etsi.rpas + pCid->tm_etsi.T3 + pCid->tm_etsi.T2 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_MARK_DEFAULT +
+                    (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else if (pCid->std == DXS_CID_STD_ETSI && pCid->as == DXS_CID_AS_LR_DTAS)
+   {
+      /* assume LR=0 + T0 + DTAS + T1 + SEIZ + MARK + FSK + T2 */
+      cid_len_ms = pCid->tm_etsi.dtas +
+                   pCid->tm_etsi.T0 + pCid->tm_etsi.T1 + pCid->tm_etsi.T2 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_MARK_DEFAULT +
+                    (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else if (pCid->std == DXS_CID_STD_TELCORDIA && pCid->as == DXS_CID_AS_NONE)
+   {
+      /* T0 + SEIZURE + MARK + FSK + T2 */
+      cid_len_ms = pCid->tm_tc.T0 + pCid->tm_tc.T2 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_MARK_DEFAULT +
+                    (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else if (pCid->std == DXS_CID_STD_TELCORDIA && pCid->as == DXS_CID_AS_OSI)
+   {
+      /* assume DISABLED=0 + timer OSI + T1 + SEIZ + MARK + FSK + T2 */
+      cid_len_ms = pCid->tm_tc.osi + pCid->tm_tc.T1 + pCid->tm_tc.T2 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_MARK_DEFAULT +
+                    (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else if (pCid->std == DXS_CID_STD_BT && pCid->as == DXS_CID_AS_LR_DTAS)
+   {
+      /* assume LR=0 + T0 + DTAS + T1 + SEIZ + MARK + FSK + T2 */
+      cid_len_ms = pCid->tm_bt.T0 + pCid->tm_bt.dtas + pCid->tm_bt.T1 +
+                   pCid->tm_bt.T2 +
+                   (DXS_CID_FSK_SEIZURE_DEFAULT + DXS_CID_FSK_BT_MARK_DEFAULT +
+                     (fsk_buffer_bytes << 3)) * 1000 / DXS_CID_FSK_BITS_PER_SEC;
+   }
+   else
+   {
+      /* FIXME: NTT standard is
+          temporarily not supported */
+      *pLen = -1;
+      return DXS_statusOk;
+   }
+
+   *pLen = ((cid_len_ms + 25) / 50);
+   return DXS_statusOk;
+}
+
+/**
+   Get CID standard
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   pStd - pointer to CID standard (output)
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_StandardGet (DXS_CHANNEL_t *pCh, DXS_CID_Std_t *pStd)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* check if pCid is initialized */
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+   *pStd = pCid->std;
+   return DXS_statusOk;
+}
+
+/**
+   Get CID alert signal
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+   \param   pAsig - pointer to CID alert signal (output)
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_AlertSigGet (DXS_CHANNEL_t *pCh, DXS_CID_AS_t *pAsig)
+{
+   DXS_CID_Ctx_t *pCid =
+      &cid_res[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* check if pCid is initialized */
+   if (pCid->magic != DXS_CID_CTX_MAGIC)
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+   *pAsig = pCid->as;
+   return DXS_statusOk;
+}
+
+extern int SLICAPP_CID_Std;
+int32_t dxsapi_cid_fsk_etsi_type2 (uint8_t dxs, uint8_t line, char *cid_cli)
+{
+    int32_t ret = 0;
+
+    DXS_CID_Std_t std;
+    DXS_CID_AS_t as;
+    DXS_CID_DATA_FMT_t fmt;
+    uint8_t dtmf_ack_idx = 0;
+
+    struct tm tms = {0};
+    time_t rawtime;
+    uint8_t i = 0;
+    char timedate_buffer[8];
+    char cid_party_name[] = "CALLING";
+
+    /* select STD,  format, ack DTMF digit */
+    std = SLICAPP_CID_Std;
+    fmt = DXS_CID_DATA_FSK;
+    as = DXS_CID_AS_NONE;
+    dtmf_ack_idx = 31;           /* index DTMF digit */
+    ret = DxsCidInit(dxs, line, std, as, fmt, dtmf_ack_idx);
+
+    /* Prepare Call Setup message for device dev, channel line:
+    1) Add Calling Line ID parameter
+    2) Add Calling Party Name parameter
+    3) Add Date Time parameter */
+
+    ret = DxsCidMsgSetup(dxs, line,
+                         DXS_CID_MSG_TYPE_CS,
+                         DXS_CID_MSG_PARAM_CALLING_LINE_ID,
+                         cid_cli,
+                         strlen(cid_cli));
+
+    ret = DxsCidMsgSetup(dxs, line,
+                         DXS_CID_MSG_TYPE_CS,
+                         DXS_CID_MSG_PARAM_CALLING_PARTY_NAME,
+                         cid_party_name,
+                         strlen(cid_party_name));
+
+    /* Date and time */
+    rawtime = time(NULL);
+    localtime_r(&rawtime, &tms);
+    /* month */
+    timedate_buffer[i++] = (tms.tm_mon + 1) / 10 + '0';
+    timedate_buffer[i++] = (tms.tm_mon + 1) % 10 + '0';
+    /* day */
+    timedate_buffer[i++] = tms.tm_mday / 10 + '0';
+    timedate_buffer[i++] = tms.tm_mday % 10 + '0';
+    /* hour */
+    timedate_buffer[i++] = tms.tm_hour / 10 + '0';
+    timedate_buffer[i++] = tms.tm_hour % 10 + '0';
+    /* minute */
+    timedate_buffer[i++] = tms.tm_min / 10 + '0';
+    timedate_buffer[i++] = tms.tm_min % 10 + '0';
+
+    ret = DxsCidMsgSetup(dxs, line,
+                   DXS_CID_MSG_TYPE_CS,
+                   DXS_CID_MSG_PARAM_DATE_TIME,
+                   timedate_buffer,
+                   sizeof(timedate_buffer));
+    /* Transmit Type2 Call Setup message */
+    ret = DxsCidTypeIIMsgStart(dxs, line, DXS_CID_MSG_TYPE_CS);
+    return ret;
+}
+
+#endif /* DXS_FEAT_CID */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_cid.h b/marvell/services/dxslic/api_lib/src/dxs_cid.h
new file mode 100644
index 0000000..1bcbdec
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_cid.h
@@ -0,0 +1,67 @@
+#ifndef __DXS_CID_H__
+#define __DXS_CID_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_cid.h
+   Caller ID module interface declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_CID_CALL_FROM_CID_API   0
+#define DXS_CID_CALL_FROM_RING_SM   1
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* called from API */
+extern int32_t DXS_CID_Init(DXS_CHANNEL_t *pCh, DXS_CID_Std_t std,
+                 DXS_CID_AS_t as, DXS_CID_DATA_FMT_t fmt, uint8_t dtmf_ack_idx);
+extern void DXS_CID_Cleanup(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_CID_TimerConfig(DXS_CHANNEL_t *pCh, DXS_CID_Std_t std,
+                                     DXS_CID_Timers_t *pTimers);
+extern int32_t DXS_CID_MsgUpdate(DXS_CHANNEL_t *pCh,
+                                     DXS_CID_MsgType_t msg_type,
+                                     DXS_CID_MsgParam_t param, char *pData,
+                                     uint8_t length);
+extern int32_t DXS_CID_MsgCleanup(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_CID_TypeI_Play(DXS_CHANNEL_t *pCh,
+                                     DXS_CID_MsgType_t msg_type,
+                                     uint8_t calling_instance);
+extern int32_t DXS_CID_TypeII_Play(DXS_CHANNEL_t *pCh,
+                                     DXS_CID_MsgType_t msg_type);
+extern int32_t DXS_CID_Stop(DXS_CHANNEL_t *pCh);
+/* called from event handler */
+extern void DXS_CID_FSK_SendComplete(DXS_CHANNEL_t *pCh);
+extern void DXS_CID_FSK_SendError(DXS_CHANNEL_t *pCh);
+extern uint8_t DXS_CID_EventOnhook(DXS_CHANNEL_t *pCh, uint16_t timestamp);
+extern uint8_t DXS_CID_EventOffhook(DXS_CHANNEL_t *pCh, uint16_t timestamp);
+extern uint8_t DXS_CID_EventDtmf(DXS_CHANNEL_t *pCh, DXS_Event_t *pEvent);
+extern uint8_t DXS_CID_EventOpcDisabled(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_CID_LengthBitsGet(DXS_CHANNEL_t *pCh, int32_t *pLen);
+extern int32_t DXS_CID_StandardGet (DXS_CHANNEL_t *pCh, DXS_CID_Std_t *pStd);
+extern int32_t DXS_CID_AlertSigGet (DXS_CHANNEL_t *pCh, DXS_CID_AS_t *pAsig);
+extern int32_t dxsapi_cid_fsk_etsi_type2 (uint8_t dxs, uint8_t line, char *cid_cli);
+
+#endif /* __DXS_CID_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_cid_fsk.c b/marvell/services/dxslic/api_lib/src/dxs_cid_fsk.c
new file mode 100644
index 0000000..a226a7a
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_cid_fsk.c
@@ -0,0 +1,168 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_cid_fsk.c
+   FSK interface functions for CID state machine and event handler
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdlib.h>
+
+#include "dxs.h"
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_cid.h"
+#include "dxs_cid_fsk.h"
+#include "dxs_sig.h"
+
+#ifdef DXS_FEAT_CID
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_CID_FSK_MAX_FRAFMENT_SZ       27
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* FSK data buffer */
+typedef struct
+{
+   uint8_t *data;
+   uint16_t len;
+   uint16_t pos;
+} DXS_FSK_Buffer_t;
+
+/* FSK data buffers are as many as channels */
+static DXS_FSK_Buffer_t fsk_buffers[DXS_MAX_DEVICES * CH_PER_DEVICE] = {0};
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Retrieve the next data fragment size
+
+   \param   pBuf   - pointer to \ref DXS_FSK_Buffer_t structure
+
+   \return
+   - fragment size
+*/
+static uint16_t dxs_cid_fsk_fragment_size_get(DXS_FSK_Buffer_t *pBuf)
+{
+   uint16_t full_blocks = (pBuf->len - pBuf->pos) / DXS_CID_FSK_MAX_FRAFMENT_SZ;
+
+   if (full_blocks)
+      return DXS_CID_FSK_MAX_FRAFMENT_SZ;
+
+   return ((pBuf->len - pBuf->pos) % DXS_CID_FSK_MAX_FRAFMENT_SZ);
+}
+
+/**
+   Start the FSK state machine
+
+   \param   pCh     - pointer to \ref DXS_CHANNEL_t structure
+   \param   spec    - FSK spec (Bell202 or ITU-T)
+   \param   ad      - auto-deactivate flag
+   \param   pData   - data buffer
+   \param   len     - length of data buffer
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_FSK_Start (DXS_CHANNEL_t *pCh, int32_t spec, int32_t ad,
+                               uint8_t *pData, uint16_t len)
+{
+   DXS_FSK_Buffer_t *pBuf =
+     &fsk_buffers[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   /* prepare buffer */
+   pBuf->data = pData;
+   pBuf->len = len;
+   pBuf->pos = 0;
+
+   return DXS_FSK_Enable(pCh, spec, ad);
+}
+
+/**
+   Inform FSK state machine about device event
+
+   \param  pCh   - pointer to \ref DXS_CHANNEL_t structure
+   \param  event - event information from device
+
+   \return
+   - DXS_status_t
+*/
+void DXS_CID_FSK_EventInfo (DXS_CHANNEL_t *pCh, int32_t event)
+{
+   DXS_FSK_Buffer_t *pBuf =
+     &fsk_buffers[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   switch (event)
+   {
+      case DXS_CID_FSK_DATA_REQUEST:
+      {
+         uint8_t *p = &pBuf->data[pBuf->pos];
+         uint16_t fragment_sz = dxs_cid_fsk_fragment_size_get(pBuf);
+
+         if (fragment_sz > 0)
+         {
+            DXS_FSK_Data(pCh, fragment_sz, p);
+            pBuf->pos += fragment_sz;
+         }
+         else
+         {
+            DXS_FSK_Disable(pCh, 1);
+         }
+      }
+      break;
+
+      case DXS_CID_FSK_DATA_BUF:
+         /* usage is not clear, it looks like FW
+            sends up this event also after FSK deactivation with AD=1 */
+      break;
+
+      case DXS_CID_FSK_DATA_FINISH:
+      {
+         /* inform CID state machine */
+         DXS_CID_FSK_SendComplete(pCh);
+      }
+      break;
+
+      default:
+      {
+         /* inform CID state machine */
+         DXS_CID_FSK_SendError(pCh);
+      }
+   }
+}
+
+/**
+   Stop the FSK transmitter
+
+   \param pCh    - pointer to \ref DXS_CHANNEL_t structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CID_FSK_Stop(DXS_CHANNEL_t *pCh)
+{
+   /* disable FSK immediately */
+   return DXS_FSK_Disable(pCh, 0);
+}
+
+#endif /* DXS_FEAT_CID */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_cid_fsk.h b/marvell/services/dxslic/api_lib/src/dxs_cid_fsk.h
new file mode 100644
index 0000000..e64d4da
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_cid_fsk.h
@@ -0,0 +1,46 @@
+#ifndef __DXS_CID_FSK_H__
+#define __DXS_CID_FSK_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_cid_fsk.h
+   Caller ID FSK module interface declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* FSK spec options */
+#define DXS_CID_FSK_V23_BEL202   0
+#define DXS_CID_FSK_V23_ITU_T    1
+
+/* device events */
+#define DXS_CID_FSK_DATA_REQUEST 1
+#define DXS_CID_FSK_DATA_FINISH  2
+#define DXS_CID_FSK_DATA_BUF     3
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t DXS_CID_FSK_Start(DXS_CHANNEL_t *pCh, int32_t spec, int32_t ad,
+                                 uint8_t *pData, uint16_t len);
+extern int32_t DXS_CID_FSK_Stop(DXS_CHANNEL_t *pCh);
+extern void DXS_CID_FSK_EventInfo(DXS_CHANNEL_t *pCh, int32_t event);
+
+
+#endif /* __DXS_CID_FSK_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_dcdc_hw.c b/marvell/services/dxslic/api_lib/src/dxs_dcdc_hw.c
new file mode 100644
index 0000000..ad458ec
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_dcdc_hw.c
@@ -0,0 +1,419 @@
+/*******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, 2017, 2018 Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+*******************************************************************************/
+
+/**
+   \file dxs_dcdc_hw.c
+   Implementation of DXS DC/DC hardware specific limitations.
+   Example limitation:
+      \ref DXS_DCDC_IFB12CH8 can provide the ringing voltage
+      only for two channels at a time.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_config.h"
+#include "dxs_dcdc_hw.h"
+#include "dxs_error.h"
+#include "dxs_errno.h"
+#include "dxs_sdd.h"
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* total channel count */
+#define DXS_HW_CHANNELS                  (DXS_MAX_DEVICES * CH_PER_DEVICE)
+/* channels per DCDC */
+#define DXS_HW_CH_PER_DCDC               8
+/* maximum simultaneous ring bursts */
+#define DXS_MAX_SIMULTANEOUS_RINGS       2
+/* devices per DCDC */
+#define DXS_HW_DEV_PER_DCDC              (DXS_HW_CH_PER_DCDC / CH_PER_DEVICE)
+/* total DCDC count */
+#define DXS_HW_DCDC_COUNT                (DXS_HW_CHANNELS / DXS_HW_CH_PER_DCDC)
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+struct __dxs_hw_dcdc
+{
+   /*pthread_mutex_t mtx;*/
+   DXS_CHANNEL_t *pCh[DXS_HW_CH_PER_DCDC], *pChMaster;
+};
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static uint32_t init_channels = 0;
+static struct __dxs_hw_dcdc dcdc_hw[DXS_HW_DCDC_COUNT];
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Get the DCDC descriptor from channel
+
+   \param   pCh       - pointer to DXS channel structure
+   \return
+   - pointer to DCDC structure to which the channel belongs
+*/
+static struct __dxs_hw_dcdc *dxs_hw_get_dcdc (DXS_CHANNEL_t *pCh)
+{
+   struct __dxs_hw_dcdc *pDCDC;
+   uint8_t dcdc, ch;
+
+   for (dcdc=0, pDCDC=NULL; dcdc<DXS_HW_DCDC_COUNT && pDCDC==NULL; dcdc++)
+   {
+      for (ch=0; ch<DXS_HW_CH_PER_DCDC && pDCDC==NULL; ch++)
+      {
+         if (dcdc_hw[dcdc].pCh[ch] == pCh)
+            pDCDC = &dcdc_hw[dcdc];
+      }
+   }
+   return pDCDC;
+}
+
+/**
+   Add DXS channel to the DCDC channel table
+
+   \param   pCh       - pointer to DXS channel structure
+   \param   nDcDcNum  - DCDC number to which the channel belongs
+   \return  none
+*/
+static void dxs_hw_channel_add (DXS_CHANNEL_t *pCh, uint8_t nDcDcNum)
+{
+   uint8_t dcdc, ch, found;
+
+   if (!init_channels)
+   {
+      for (dcdc=0; dcdc<DXS_HW_DCDC_COUNT; dcdc++)
+      {
+         dcdc_hw[dcdc].pChMaster = NULL;
+         /*pthread_mutex_init(&dcdc_hw[dcdc].mtx, NULL);*/
+         for (ch=0; ch<DXS_HW_CH_PER_DCDC; ch++)
+            dcdc_hw[dcdc].pCh[ch] = NULL;
+      }
+   }
+   ++init_channels;
+
+   for (ch=0, found=0; ch<DXS_HW_CH_PER_DCDC && !found; ch++)
+   {
+      /* channel was already entered */
+      if (dcdc_hw[nDcDcNum].pCh[ch] == pCh)
+         break;
+
+      if (dcdc_hw[nDcDcNum].pCh[ch] == NULL)
+      {
+         found = 1;
+         dcdc_hw[nDcDcNum].pCh[ch] = pCh;
+      }
+   }
+}
+
+/**
+   Delete DXS channel from the DCDC channel table
+
+   \param   pCh    - pointer to DXS channel structure
+   \return  none
+*/
+static void dxs_hw_channel_delete (DXS_CHANNEL_t *pCh)
+{
+   uint8_t dcdc, ch, found;
+#if 0
+   int32_t err;
+#endif
+
+   for (dcdc=0, found=0; dcdc<DXS_HW_DCDC_COUNT && !found; dcdc++)
+   {
+      for (ch=0; ch<DXS_HW_CH_PER_DCDC && !found; ch++)
+      {
+         if (dcdc_hw[dcdc].pCh[ch] == pCh)
+         {
+            found = 1;
+            dcdc_hw[dcdc].pCh[ch] = NULL;
+         }
+      }
+   }
+
+   if (found)
+   {
+      --init_channels;
+      if (!init_channels)
+      {
+         for (dcdc=0; dcdc<DXS_HW_DCDC_COUNT; dcdc++)
+         {
+#if 0
+            err = pthread_mutex_unlock(&dcdc_hw[dcdc].mtx);
+            if (err != 0)
+              DXS_ERROR_PUSH(err);
+            err = pthread_mutex_destroy(&dcdc_hw[dcdc].mtx);
+            if (err != 0)
+              DXS_ERROR_PUSH(err);
+#endif
+            for (ch=0; ch<DXS_HW_CH_PER_DCDC; ch++)
+               dcdc_hw[dcdc].pCh[ch] = NULL;
+         }
+      }
+   }
+}
+
+/**
+   Check the DC/DC ringing capabilities
+
+   \param   pCh    - pointer to DXS channel structure
+   \return
+   DXS_statusOk - success
+   DXS_statusDcDcRingCapsExceeded - maximum allowed
+   simultaneous ringing capacity reached
+   DXS_statusNotInitResource - channel not initialized
+*/
+int32_t DXS_DCDC_HW_RingingCapsCheck (DXS_CHANNEL_t *pCh)
+{
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      struct __dxs_hw_dcdc *pDCDC;
+      uint8_t ch;
+
+      if ((pDCDC = dxs_hw_get_dcdc(pCh)) != NULL)
+      {
+         uint8_t ringing = 0;
+#if 0
+         int32_t err;
+
+         err = pthread_mutex_lock (&pDCDC->mtx);
+         if (err != 0)
+           DXS_ERROR_PUSH(err);
+#endif
+
+         for (ch=0; ch<DXS_HW_CH_PER_DCDC; ch++)
+            if (DXS_SDD_IsRingingUnprot(pDCDC->pCh[ch]))
+               ++ringing;
+
+#if 0
+         err = pthread_mutex_unlock (&pDCDC->mtx);
+         if (err != 0)
+           DXS_ERROR_PUSH(err);
+#endif
+
+         if (ringing >= DXS_MAX_SIMULTANEOUS_RINGS)
+         {
+            return DXS_statusDcDcRingCapsExceeded;
+         }
+      }
+      else
+      {
+         DXS_RETURN(DXS_statusNotInitResource);
+      }
+   }
+   return DXS_statusOk;
+}
+
+/**
+   Initialize DCDC HW channels
+
+   \param   pDev    - pointer to DXS device structure
+   \return  none
+*/
+void DXS_DCDC_HW_Init (DXS_DEVICE_t *pDev)
+{
+   if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      uint8_t ch = 0,
+              /* nDevNum must be contiguous for a DCDC */
+              dcdc = pDev->nDevNum/DXS_HW_DEV_PER_DCDC;
+
+      while (ch < pDev->nChannels)
+      {
+         DXS_CHANNEL_t *pCh = &pDev->pChannel[ch++];
+
+         dxs_hw_channel_add(pCh, dcdc);
+      }
+   }
+}
+
+/**
+   De-initialize DCDC HW channels
+
+   \param   pDev    - pointer to DXS device structure
+   \return  none
+*/
+void DXS_DCDC_HW_Exit (DXS_DEVICE_t *pDev)
+{
+   if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      uint8_t ch = 0;
+
+      while (ch < pDev->nChannels)
+      {
+         DXS_CHANNEL_t *pCh = &pDev->pChannel[ch++];
+
+         dxs_hw_channel_delete(pCh);
+      }
+   }
+}
+
+#if 0
+/**
+   Lock the DCDC resource
+
+   \param   pCh    - pointer to DXS channel structure
+   \return  none
+*/
+void DXS_DCDC_HW_Lock (DXS_CHANNEL_t *pCh)
+{
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      struct __dxs_hw_dcdc *pDCDC;
+      int32_t err;
+
+      if ((pDCDC = dxs_hw_get_dcdc(pCh)) != NULL)
+      {
+         err = pthread_mutex_lock (&pDCDC->mtx);
+         if (err != 0)
+           DXS_ERROR_PUSH(err);
+      }
+   }
+}
+
+/**
+   Unlock the DCDC resource
+
+   \param   pCh    - pointer to DXS channel structure
+   \return  none
+*/
+void DXS_DCDC_HW_UnLock (DXS_CHANNEL_t *pCh)
+{
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      struct __dxs_hw_dcdc *pDCDC;
+      int32_t err;
+
+      if ((pDCDC = dxs_hw_get_dcdc(pCh)) != NULL)
+      {
+         err = pthread_mutex_unlock (&pDCDC->mtx);
+         if (err != 0)
+           DXS_ERROR_PUSH(err);
+      }
+   }
+}
+#endif
+
+/**
+   Set the shared DC/DC master channel.
+
+   \param   pCh    - pointer to DXS channel structure
+   \return
+   - DXS_statusOk
+   - DXS_statusInvalidParam
+*/
+int32_t DXS_DCDC_HW_SharedDcDcMasterChSet (DXS_CHANNEL_t *pCh)
+{
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      struct __dxs_hw_dcdc *pDCDC;
+
+      if ((pDCDC = dxs_hw_get_dcdc(pCh)) != NULL)
+      {
+         if (pDCDC->pChMaster != NULL && pDCDC->pChMaster != pCh)
+         {
+            /* error msg: different channel was
+               already set as master */
+            DXS_RETURN(DXS_statusInvalidParam);
+         }
+         else if (pDCDC->pChMaster == NULL)
+            pDCDC->pChMaster = pCh;
+      }
+      else
+      {
+         DXS_RETURN(DXS_statusNotInitResource);
+      }
+   }
+   return DXS_statusOk;
+}
+
+/**
+   Get the master channel of a DC/DC to which the device belongs
+
+   \param   pDev      -   pointer to DXS device structure
+   \return
+   pointer to DXS master channel structure or NULL
+*/
+DXS_CHANNEL_t *DXS_DCDC_HW_SharedDcDcMasterChGetInt (DXS_DEVICE_t *pDev)
+{
+   if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      DXS_CHANNEL_t *pCh = &pDev->pChannel[0];
+      struct __dxs_hw_dcdc *pDCDC;
+
+      if ((pDCDC = dxs_hw_get_dcdc(pCh)) != NULL)
+         return pDCDC->pChMaster;
+   }
+   return NULL;
+}
+
+/**
+   Get the number of channels supported by the DC/DC
+   to which the pCh belongs
+
+   \param   pCh      -   pointer to DXS channel structure
+   \return
+   number of channels or 0 if the DC/DC is not covered
+*/
+uint8_t DXS_DCDC_HW_SharedDcDcChannelNumGet (DXS_CHANNEL_t *pCh)
+{
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+      return DXS_HW_CH_PER_DCDC;
+
+   return 0;
+}
+
+/**
+   Get the number of the DC/DC to which the pCh belongs
+
+   \param   pCh      -   pointer to DXS channel structure
+   \return
+   the number of the DC/DC or negative in case if pCh
+   was not found in any of the DC/DC
+*/
+int32_t DXS_DCDC_HW_SharedDcDcNumberGet (DXS_CHANNEL_t *pCh)
+{
+   int8_t dcdc, ch;
+
+   for (dcdc=0; dcdc<DXS_HW_DCDC_COUNT; dcdc++)
+   {
+      for (ch=0; ch<DXS_HW_CH_PER_DCDC; ch++)
+      {
+         if (dcdc_hw[dcdc].pCh[ch] == pCh)
+            return dcdc;
+      }
+   }
+   return -1;
+}
+
+/**
+   Get the DXS channel structure for the given DC/DC
+   number and channel offset
+
+   \param   dcdc   -   DC/DC number from 0
+   \param   ch     -   channel number from 0 within the DC/DC
+   \return
+   the DXS channel structure or NULL if the channel stucture
+   cannot be found in a given DC/DC
+*/
+DXS_CHANNEL_t *DXS_DCDC_HW_SharedDcDcChannelGet (uint8_t dcdc, uint8_t ch)
+{
+   if (dcdc >= DXS_HW_DCDC_COUNT || ch >= DXS_HW_CH_PER_DCDC)
+      return NULL;
+
+   return dcdc_hw[dcdc].pCh[ch];
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_dcdc_hw.h b/marvell/services/dxslic/api_lib/src/dxs_dcdc_hw.h
new file mode 100644
index 0000000..5bfbb25
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_dcdc_hw.h
@@ -0,0 +1,42 @@
+#ifndef __DXS_DCDC_HW_H__
+#define __DXS_DCDC_HW_H__
+/*******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, 2017, 2018 Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+*******************************************************************************/
+
+/**
+   \file dxs_dcdc_hw.h
+   API functions for handling of DC/DC hardware specific limitations.
+   Example limitation:
+      \ref DXS_DCDC_IFB12CH8 can provide the ringing voltage
+      only for two channels at a time.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs.h"
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t DXS_DCDC_HW_RingingCapsCheck (DXS_CHANNEL_t *);
+extern void DXS_DCDC_HW_Init (DXS_DEVICE_t *);
+extern void DXS_DCDC_HW_Exit (DXS_DEVICE_t *);
+extern void DXS_DCDC_HW_Lock (DXS_CHANNEL_t *);
+extern void DXS_DCDC_HW_UnLock (DXS_CHANNEL_t *);
+extern DXS_CHANNEL_t *DXS_DCDC_HW_SharedDcDcMasterChGetInt (DXS_DEVICE_t *pDev);
+extern int32_t DXS_DCDC_HW_SharedDcDcMasterChSet (DXS_CHANNEL_t *pCh);
+extern uint8_t DXS_DCDC_HW_SharedDcDcChannelNumGet (DXS_CHANNEL_t *pCh);
+extern int32_t DXS_DCDC_HW_SharedDcDcNumberGet (DXS_CHANNEL_t *pCh);
+extern DXS_CHANNEL_t* DXS_DCDC_HW_SharedDcDcChannelGet (uint8_t dcdc, uint8_t ch);
+
+#endif /* __DXS_DCDC_HW_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_debug_api.c b/marvell/services/dxslic/api_lib/src/dxs_debug_api.c
new file mode 100644
index 0000000..cda9144
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_debug_api.c
@@ -0,0 +1,175 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_debug_api.c
+   Implementation of debug API functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_access.h"
+#include "dxs_mbx.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+#ifdef DXS_FEAT_DEBUG_API
+
+/**
+   Function dxs_reg_read
+
+   \param   pDev     - pointer to DXS device structure
+   \param   offset   - offset
+   \param   pValue   - pointer to value
+   \param   count    - count
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_reg_read (  DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue,
+                        uint8_t count)
+{
+   int32_t ret, err;
+
+   err = pthread_mutex_lock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   ret = DXS_RegReadMulti(pDev, offset, pValue, count);
+
+   err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* TODO: howto handle error? */
+   return ret;
+}
+
+/**
+   Function dxs_reg_write
+
+   \param   pDev     - pointer to DXS device structure
+   \param   offset   - offset
+   \param   pValue   - pointer to value
+   \param   count    - count
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_reg_write ( DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue,
+                        uint8_t count)
+{
+   int32_t ret, err;
+
+   err = pthread_mutex_lock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   ret = DXS_RegWriteMulti(pDev, offset, pValue, count);
+
+   err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* TODO: howto handle error? */
+   return ret;
+}
+
+/**
+   Function dxs_cmd_read
+
+   \param   pDev    - pointer to DXS device structure
+   \param   hdr     - header
+   \param   pData   - pointer to command data
+   \param   pLength - pointer to length
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_cmd_read (  DXS_DEVICE_t *pDev,
+                        uint32_t hdr,
+                        uint32_t *pData,
+                        uint8_t *pLength)
+{
+   uint8_t cmd_length;
+   int32_t ret;
+
+   cmd_length = hdr & 0xFF;
+
+   if ((cmd_length > (0xFF-4)) || ((cmd_length+4) > *pLength))
+   {
+      DXS_RETURN(DXS_statusCmdLengthInvalid);
+   }
+
+   ret = CmdRead(pDev, &hdr, pData);
+
+   *pLength = 4 + cmd_length; /* including the size of the command header */
+   return ret;
+}
+
+/**
+   Function dxs_cmd_write
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pCmd    - pointer to command data
+   \param   length  - length
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_cmd_write ( DXS_DEVICE_t *pDev,
+                        uint32_t *pCmd,
+                        uint8_t length)
+{
+   uint8_t cmd_length;
+
+   if (length < 4)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   cmd_length = *pCmd & 0xFF;
+
+   if ((cmd_length > (0xFF-4)) || ((cmd_length+4) > length))
+   {
+      DXS_RETURN(DXS_statusCmdLengthInvalid);
+   }
+
+   return CmdWrite(pDev, pCmd);
+}
+
+#endif /* DXS_FEAT_DEBUG_API */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_debug_api.h b/marvell/services/dxslic/api_lib/src/dxs_debug_api.h
new file mode 100644
index 0000000..4aa2c89
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_debug_api.h
@@ -0,0 +1,57 @@
+#ifndef __DXS_DEBUG_API_H__
+#define __DXS_DEBUG_API_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_debug_api.h
+   Debug API functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t dxs_reg_read (
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue,
+                        uint8_t count);
+
+extern int32_t dxs_reg_write (
+                        DXS_DEVICE_t *pDev,
+                        uint8_t offset,
+                        uint16_t *pValue,
+                        uint8_t count);
+
+extern int32_t dxs_cmd_read (
+                        DXS_DEVICE_t *pDev,
+                        uint32_t hdr,
+                        uint32_t *pData,
+                        uint8_t *pLength);
+
+extern int32_t dxs_cmd_write (
+                        DXS_DEVICE_t *pDev,
+                        uint32_t *pCmd,
+                        uint8_t length);
+
+#endif /* __DXS_DEBUG_API_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_dwld.c b/marvell/services/dxslic/api_lib/src/dxs_dwld.c
new file mode 100644
index 0000000..1c615ce
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_dwld.c
@@ -0,0 +1,508 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_dwld.c
+   Implementation of download functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "dxs_lib.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_access.h"
+#include "dxs_init.h"
+#include "dxs_mbx.h"
+#include "dxs_pollint.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_PRAM_MAGIC_DXS1    0x44585331
+#define DXS_PRAM_MAGIC_DXS2    0x44585332
+
+#define DXS_ROM_MASK_1_0       1
+#define DXS_ROM_MASK_2_0       2
+
+#define DXS_CRC32_POLY         0xEDB88320
+#define DXS_SWAP32(a)   ((((a) >> 24) & 0xFF) | (((a) >> 8) & 0xFF00) | \
+                        (((a) & 0xFF00) << 8) | (((a) & 0xFF) << 24))
+
+/* FW download container header struct values */
+#define DXS_FW_TYPE_GLOBAL_V1   0xD0000001  /* type 0xD000, version 0x0001 */
+#define DXS_FW_GLOBAL_MAGIC     0x44585346  /* 'DXSF' character sequence */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+struct pram_footer
+{
+   /* version information */
+   uint32_t fw_vers;
+   /* unix compilation timestamp */
+   uint32_t timestamp;
+   /* 'DXS1' or 'DXS2' */
+   uint32_t magic;
+   /* image size */
+   uint32_t mem;
+   /* CRC32 */
+   uint32_t crc;
+};
+
+/* FW download container header (big endian) */
+struct fw_container_header
+{
+   /* Type and Version identifier */
+   uint32_t   nType;
+   /* Length of the payload following this header */
+   uint32_t   nLength;
+   /* MAGIC value for endianess checking */
+   uint32_t   nMagic;
+   /* Version, each of the 4 bytes represents a digit */
+   uint32_t   nVersion;
+   /* Epoch timestamp */
+   uint32_t   nTimestamp;
+   /* Offset of the DXS V11 FW within the payload section */
+   uint32_t   nDxsV11FwOffset;
+   /* Length of the DXS V11 FW within the payload section */
+   uint32_t   nDxsV11FwLength;
+   /* Offset of the DXS1 V12 FW within the payload section */
+   uint32_t   nDxs1V12FwOffset;
+   /* Length of the DXS1 V12 FW within the payload section */
+   uint32_t   nDxs1V12FwLength;
+   /* Offset of the DXS2 V12 FW within the payload section */
+   uint32_t   nDxs2V12FwOffset;
+   /* Length of the DXS2 V12 FW within the payload section */
+   uint32_t   nDxs2V12FwLength;
+};
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Update CRC32 checksum
+
+   \param   pData - data buffer
+   \param   len   - data buffer size in bytes
+   \param   prev  - previous CRC32 checksum (initial should be 0)
+
+   \return
+      Newly calculated CRC32 value
+*/
+static uint32_t dxs_crc32_le(const void *pData, size_t len, uint32_t prev)
+{
+   uint32_t crc = ~prev;
+   uint8_t *pByte = (uint8_t *)pData;
+   uint32_t j;
+
+   while (len--)
+   {
+      crc ^= (uint32_t) *pByte++;
+      for (j = 0; j < 8; j++)
+      {
+         if (crc & 1)
+            crc = (crc >> 1) ^ DXS_CRC32_POLY;
+         else
+            crc =  crc >> 1;
+      }
+   }
+   return ~crc;
+}
+
+/**
+   Verify PRAM image CRC checksum
+
+   \param   pData - pointer to image data
+   \param   size  - size of the image in bytes
+   \param   cksum - CRC checksum from image footer
+
+   \return
+      0 - verification failed
+      1 - verification passed
+*/
+static int32_t pram_cksum_verify(uint8_t *pData, uint32_t size, uint32_t ftr_cksum)
+{
+   uint32_t calc_cksum = 0, words32 = size/sizeof(uint32_t);
+
+   while (words32--)
+   {
+      int32_t i = 1;
+      /* make 32-bit word of 4 bytes */
+      uint32_t word = (*pData << 24)|(*(pData+1) << 16)|(*(pData+2) << 8)|(*(pData+3));
+
+      if (!(*((int8_t *)&i)))
+      {
+         /* to use LE CRC32 calculation on BE system -
+            swap bytes in a word */
+         word = DXS_SWAP32(word);
+      }
+
+      calc_cksum = dxs_crc32_le((void *)&word, sizeof(word), calc_cksum);
+      pData += sizeof(word);
+   }
+
+   if (calc_cksum == ftr_cksum)
+      return 1;
+
+   return 0;
+}
+
+/**
+   Read the footer from PRAM patch file
+
+   \param   pData   - pointer to PRAM image
+   \param   size    - size of the PRAM image
+   \param   f       - pointer to footer structure
+
+   \return
+   - none
+*/
+static void pram_footer_read(uint8_t *pData, uint32_t size,
+                                struct pram_footer *f)
+{
+   uint32_t offset = size - sizeof(*f), word, i;
+
+   for (i=0; i<(sizeof(*f)/sizeof(uint32_t)); i++)
+   {
+      word = 0;
+
+      word |= (uint32_t) (pData[offset++]) << 24;
+      word |= (uint32_t) (pData[offset++]) << 16;
+      word |= (uint32_t) (pData[offset++]) << 8;
+      word |= (uint32_t) (pData[offset++]);
+
+      *((uint32_t *)f + i) = word;
+   }
+}
+
+/**
+   Function dxs_fw_download
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pPatch  - pointer to data buffer
+   \param   nBytes  - size of the buffer
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_fw_download(DXS_DEVICE_t *pDev,
+                                  uint8_t *pPatch, uint32_t nBytes)
+{
+   int32_t  ret = DXS_statusOk;
+   uint16_t nDxsRegBootCfg = 0,
+            nDxsRegBootInfo = 0,
+            nDxsRegCfg  = 0;
+   struct pram_footer   ft;
+
+   /* read PRAM patch footer */
+   pram_footer_read(pPatch, nBytes, &ft);
+
+   /* if the image has a footer, verify the checksum */
+   if (ft.magic == DXS_PRAM_MAGIC_DXS1 || ft.magic == DXS_PRAM_MAGIC_DXS2)
+   {
+      /* do not pass the footer for checksum verification */
+      nBytes -= sizeof(struct pram_footer);
+
+      if (!pram_cksum_verify(pPatch, nBytes, ft.crc))
+      {
+         DXS_RETURN(DXS_statusPramPatchCksumError);
+      }
+
+      /* prepare image size for download -
+         minus one word of block delimiter */
+      nBytes -= sizeof(uint32_t);
+   }
+
+   /* stop polling timer */
+   if (pDev->irqNumber == -1)
+   {
+      dxs_polling_timer_stop();
+   }
+
+   /* Set the controller startup configuration in the Boot Configuration
+      Register to boot from HOST_DATA inbox. */
+   nDxsRegBootCfg = DXS_REG_BCFG_ASC_SPI;
+   ret = DXS_RegWrite(pDev, DXS_REG_BCFG, nDxsRegBootCfg);
+   if (ret != DXS_statusOk)
+   {
+      /* errmsg: Setting of boot configuration register failed. */
+      ret = DXS_statusSetBootCfgErr;
+   }
+
+   /* Reset controller to start the boot process from HOST_DATA inbox. */
+   if (ret == DXS_statusOk)
+   {
+      nDxsRegCfg = DXS_REG_CFG_RST_RSTCORE|DXS_REG_CFG_8BIT_EN;
+      ret = DXS_RegWrite(pDev, DXS_REG_CFG, nDxsRegCfg);
+      if (ret != DXS_statusOk)
+      {
+         /* errmsg: Controller reset failed. */
+         ret =  DXS_statusCtrlResErr;
+      }
+   }
+
+   /* setup waiting flag */
+   pDev->bWaitingInPatchDwld = 1;
+
+   /* Download firmware patch. */
+   if (ret == DXS_statusOk)
+   {
+      ret = DXS_DwldPatch (pDev, pPatch, nBytes);
+      if (ret != DXS_statusOk)
+      {
+         /* errmsg: Download of the firmware binary failed. */
+         ret = DXS_statusDwldBinErr;
+      }
+   }
+
+   /* Check success of the download by reading the boot info register. */
+   if (ret == DXS_statusOk)
+   {
+      uint8_t loop = 10;
+
+      while (loop > 0)
+      {
+         struct timespec ts = {0, 2000000}; /* 2 ms */
+
+         nanosleep(&ts, NULL);
+
+         /* read the boot state indication */
+         ret = DXS_RegRead(pDev, DXS_REG_BINF, &nDxsRegBootInfo);
+
+         if ((ret == DXS_statusOk) &&
+             ((nDxsRegBootInfo & DXS_REG_BINF_BOOTSTATE_MASK) >= 0x10))
+         {
+            break;
+         }
+
+         loop--;
+      }
+
+      if (loop == 0)
+      {
+         /* errmsg: Firmware download timeout. */
+         ret = DXS_statusFwDwldTimeout;
+      }
+   }
+
+   /* Set bootmode back to ROM in case a recovery is needed. */
+   if (ret == DXS_statusOk)
+   {
+      nDxsRegBootCfg = DXS_REG_BCFG_ASC_ROM;
+      ret = DXS_RegWrite(pDev, DXS_REG_BCFG, nDxsRegBootCfg);
+
+      if (ret != DXS_statusOk)
+      {
+         /* errmsg: Setting of boot configuration register failed. */
+         ret = DXS_statusSetBootCfgErr;
+      }
+   }
+
+   /* restart polling timer */
+   if (pDev->irqNumber == -1)
+   {
+      dxs_polling_timer_start();
+   }
+
+   /* handle special test mode */
+   if (pDev->irqNumber == 255)
+   {
+      sem_post(&pDev->obxSemaphore);
+   }
+
+   /* wait for boot finished event */
+   ret = sem_wait(&pDev->mtxPatchDwld);
+   if (ret)
+      DXS_RETURN(ret);
+
+   /* enable interrupt self-clearing */
+   if (ret == DXS_statusOk)
+   {
+      ret = DXS_RegRead(pDev, DXS_REG_CFG, &nDxsRegCfg);
+      if (ret == DXS_statusOk)
+      {
+         nDxsRegCfg |= DXS_REG_CFG_SC_MD;
+         ret = DXS_RegWrite(pDev, DXS_REG_CFG, nDxsRegCfg);
+         if (ret != DXS_statusOk)
+         {
+            ret = DXS_statusRegWriteError;
+         }
+      }
+      else
+      {
+         ret = DXS_statusRegReadError;
+      }
+   }
+
+   /* read caps and version from the device, mark caps and
+      version structures updated */
+   if (ret == DXS_statusOk)
+   {
+      ret = dxs_caps_vers_update(pDev);
+   }
+
+   /* set default clock failure handling */
+   if (ret == DXS_statusOk)
+   {
+      ret = DXS_CfEsdSwitch(pDev, 1);
+   }
+
+   if (ret == DXS_statusOk)
+   {
+      pDev->flags |= DXS_DEV_PRAM_PATCH_DOWNLOADED;
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function DXS_FW_Select
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pPatch  - pointer to data buffer (container)
+   \param   nBytes  - size of the buffer
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_FW_Select(DXS_DEVICE_t *pDev, uint8_t *pPatch, uint32_t nBytes)
+{
+   struct fw_container_header header;
+   struct fw_container_header *pHeaderNew = (struct fw_container_header*) pPatch;
+   uint32_t header_length = sizeof(header);
+   int32_t ret;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   int32_t i = 0;
+#endif
+
+   if ((pPatch == NULL) || (nBytes == 0) || (nBytes % 4) ||
+       (nBytes < header_length))
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   header = *pHeaderNew;
+
+   /* on LE systems - swap bytes in every 32-bit word
+      of the header */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   while (i < header_length/sizeof(uint32_t))
+   {
+      uint32_t *pWord = (uint32_t *)&header + i;
+
+      *pWord = DXS_SWAP32(*pWord);
+      i++;
+   }
+#endif
+
+   /* Process the container after verifying the header. */
+   if (header.nType == DXS_FW_TYPE_GLOBAL_V1 &&
+       header.nLength + header_length == nBytes &&
+       header.nMagic == DXS_FW_GLOBAL_MAGIC &&
+       header.nVersion != 0 &&
+       header.nTimestamp != 0 &&
+       header.nLength == header.nDxsV11FwLength +
+                          header.nDxs1V12FwLength +
+                          header.nDxs2V12FwLength)
+   {
+      uint8_t rom = 0, channels = 0;
+
+      DXS_DevInfoGet(pDev, &rom, &channels);
+
+      switch (rom)
+      {
+
+         case 1:
+            /* ROM 1.x.x */
+            if (header.nDxsV11FwLength > 0)
+            {
+               /* ROM 1.x.x devices are not allowed
+                  for some types of DCDC */
+               if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+               {
+                  DXS_RETURN(DXS_statusPramPatchDwldFail);
+               }
+
+               ret = dxs_fw_download(pDev,
+                               pPatch + header_length + header.nDxsV11FwOffset,
+                               header.nDxsV11FwLength);
+               if (ret != DXS_statusOk)
+               {
+                  DXS_RETURN(ret);
+               }
+            }
+            break;
+
+         case 2:
+            /* ROM 2.x.x */
+            switch (channels)
+            {
+            case 1:
+               /* DXS 1-channel device */
+               if (header.nDxs1V12FwLength > 0)
+               {
+                  ret = dxs_fw_download(pDev,
+                              pPatch + header_length + header.nDxs1V12FwOffset,
+                              header.nDxs1V12FwLength);
+                  if (ret != DXS_statusOk)
+                  {
+                     DXS_RETURN(ret);
+                  }
+               }
+               break;
+            case 2:
+               /* DXS 2-channel device */
+               if (header.nDxs2V12FwLength > 0)
+               {
+                  ret = dxs_fw_download(pDev,
+                              pPatch + header_length + header.nDxs2V12FwOffset,
+                              header.nDxs2V12FwLength);
+                  if (ret != DXS_statusOk)
+                  {
+                     DXS_RETURN(ret);
+                  }
+               }
+               break;
+            default:
+               DXS_RETURN(DXS_statusPramPatchDwldFail);
+               break;
+            }
+            break;
+
+         default:
+         {
+            DXS_RETURN(DXS_statusPramPatchDwldFail);
+         }
+      }
+   }
+   else
+   {
+      /* provided buffer has no header */
+      DXS_RETURN(DXS_statusPramPatchInvalid);
+   }
+
+   return DXS_statusOk;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_dwld.h b/marvell/services/dxslic/api_lib/src/dxs_dwld.h
new file mode 100644
index 0000000..8985a75
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_dwld.h
@@ -0,0 +1,39 @@
+#ifndef __DXS_DWLD_H__
+#define __DXS_DWLD_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_dwld.h
+   Download functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+extern int32_t DXS_FW_Select(DXS_DEVICE_t *pDev,
+                                 uint8_t *pPatch, uint32_t nBytes);
+
+
+#endif /* __DXS_DWLD_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_error.c b/marvell/services/dxslic/api_lib/src/dxs_error.c
new file mode 100644
index 0000000..9648c8b
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_error.c
@@ -0,0 +1,46 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_error.c
+   Implementation of error handling functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/* on success, "return" C statement is used */
+/* on error, RETURN_ERROR(code) macro is used */
+/*             - add code, file and line info to the stack */
+
+
+
diff --git a/marvell/services/dxslic/api_lib/src/dxs_error.h b/marvell/services/dxslic/api_lib/src/dxs_error.h
new file mode 100644
index 0000000..72c2015
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_error.h
@@ -0,0 +1,55 @@
+#ifndef __DXS_ERROR_H__
+#define __DXS_ERROR_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_error.h
+   Error handling functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdio.h>
+#include <dxs_errno.h>
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/* temporary */
+#define DXS_ERROR_PUSH(ret)                  \
+   do \
+   {\
+      fprintf(stderr, "ERROR code:%i (0x%02X) %s:%d\n", ret, ret, __FILE__, __LINE__); \
+   } while (0)
+
+#define DXS_RETURN(ret) \
+   do \
+   {\
+      if (ret != DXS_statusOk) {                \
+         DXS_ERROR_PUSH(ret);                   \
+      }                                         \
+      return ret; \
+   } while (0)
+
+/* TODO: fill in */
+#define DXS_ERROR_RESET
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+#endif /* __DXS_ERROR_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_event.c b/marvell/services/dxslic/api_lib/src/dxs_event.c
new file mode 100644
index 0000000..e62e332
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_event.c
@@ -0,0 +1,304 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_event.c
+   Implementation of event handling functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdio.h>
+#include <string.h>
+
+#include "dxs.h"
+#include "dxs_config.h"
+#include "dxs_mempool.h"
+#include "dxs_lib.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_wait.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_EVENTS_PER_DEVICE   10
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+/** memory placeholder for the events, all devices */
+static DXS_Event_t event_memory[DXS_MAX_DEVICES * DXS_EVENTS_PER_DEVICE];
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Function dxs_event_bit_set
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   ev      - event id
+
+   \return
+      none
+*/
+static void dxs_event_bit_set (DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
+{
+   /* the code assumes byte is 8 bits */
+   uint8_t bit = ev % (sizeof(uint32_t) << 3);
+   /* set event bit */
+   pCh->event_mask[ev/(sizeof(uint32_t) << 3)] |= (1UL << bit);
+}
+
+/**
+   Function dxs_event_bit_clear
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   ev      - event id
+
+   \return
+      none
+*/
+static void dxs_event_bit_clear (DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
+{
+   /* the code assumes byte is 8 bits */
+   uint8_t bit = ev % (sizeof(uint32_t) << 3);
+   /* clear event bit */
+   pCh->event_mask[ev/(sizeof(uint32_t) << 3)] &= ~(1UL << bit);
+}
+
+/**
+   Function dxs_event_bit_test
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   ev      - event id
+
+   \return
+      zero or non-zero value depending on bit setting
+*/
+static uint32_t dxs_event_bit_test (DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
+{
+   /* the code assumes byte is 8 bits */
+   uint8_t bit = ev % (sizeof(uint32_t) << 3);
+   return (pCh->event_mask[ev/(sizeof(uint32_t) << 3)] & (1UL << bit));
+}
+
+/**
+   Function dxs_event_pool_init
+
+   \param   pDev    - pointer to DXS device structure
+
+   \return
+      DXS_MPOOL_OK             success
+      DXS_MPOOL_PARAMS         invalid parameters
+      DXS_MPOOL_NOT_ENOUGH     not enough memory for a pool
+      DXS_MPOOL_NO_FREE_POOLS  cannot allocate a pool
+*/
+int32_t dxs_event_pool_init(DXS_DEVICE_t *pDev)
+{
+   if (pDev->nDevNum < DXS_MAX_DEVICES)
+   {
+      return mempool_init(&event_memory[pDev->nDevNum * DXS_EVENTS_PER_DEVICE],
+                          DXS_EVENTS_PER_DEVICE * sizeof (DXS_Event_t),
+                          DXS_EVENTS_PER_DEVICE, sizeof(DXS_Event_t),
+                          &pDev->event_pool);
+   }
+   else
+      return DXS_statusInvalidParam;
+}
+
+/**
+   Function dxs_event_pool_exit
+
+   \param   pDev    - pointer to DXS device structure
+
+*/
+void dxs_event_pool_exit(DXS_DEVICE_t *pDev)
+{
+   return mempool_destroy(pDev->event_pool);
+}
+
+/**
+   Function dxs_event_get
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pEvent  - pointer to event
+
+   \return
+   - the remaining element count of the fifo or DXS_statusError
+*/
+int32_t dxs_event_get(DXS_DEVICE_t *pDev, DXS_Event_t *pEvent)
+{
+   /*
+       1) get one event buffer out of the event fifo and memcopy to pEvent
+       2) return event buffer to the event buffer pool
+       3) return the remaining element count of the fifo
+    */
+   uint32_t size;
+   DXS_Event_t *pEvt;
+
+   if (0 < fifo_count(pDev->event_queue))
+   {
+      if (DXS_FIFO_OK == fifo_get(pDev->event_queue, (void **)(&pEvt), &size))
+      {
+         *pEvent=*pEvt;
+         mempool_put(pDev->event_pool, (void *)pEvt);
+      }
+      else
+      {
+         return DXS_statusError;
+      }
+   }
+
+   return fifo_count(pDev->event_queue);
+}
+
+/**
+   Function DXS_EventDispatch
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pEvent  - pointer to event
+
+*/
+void DXS_EventDispatch (DXS_DEVICE_t *pDev, DXS_Event_t *pEvent)
+{
+   DXS_Event_t *pEventBuffer;
+   DXS_CHANNEL_t *pCh = &pDev->pChannel[pEvent->ch];
+
+   /* check if the event is not masked */
+   if (!dxs_event_bit_test(pCh, pEvent->id))
+      return;
+
+   pEventBuffer = (DXS_Event_t *)mempool_get(pDev->event_pool);
+
+   if (pEventBuffer == NULL)
+   {
+      fprintf (stderr, "ERROR: Out of event memory. Event(id=%d) discarded.\n",
+               pEvent->id);
+      return;
+   }
+
+   /* copy event into the allocated buffer */
+   *pEventBuffer = *pEvent;
+
+   /* push the buffer to the event queue */
+   if (DXS_FIFO_OK == fifo_put(pDev->event_queue,
+                               (void *)pEventBuffer, sizeof (*pEventBuffer)))
+   {
+      /* wake up user task */
+      dxs_wakeup(pDev);
+   }
+   else
+   {
+      fprintf (stderr, "ERROR: Cannot enqueue event(dev=%d ch=%d id=%d), discarding...\n",
+                   pEventBuffer->dev, pEventBuffer->ch, pEventBuffer->id);
+      mempool_put(pDev->event_pool, (void *)pEventBuffer);
+   }
+}
+
+/**
+   Function DXS_EventEnable
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   ev     - event id
+
+   \return
+   value of \ref DXS_status_t
+*/
+int32_t DXS_EventEnable(DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
+{
+   if (ev <= DXS_EVENT_NONE || ev >= DXS_EVENT_MAX)
+   {
+      DXS_RETURN(DXS_statusEventEnableNotAllowed);
+   }
+   dxs_event_bit_set(pCh, ev);
+   return DXS_statusOk;
+}
+
+/**
+   Function DXS_EventDisable
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   ev     - event id
+
+   \return
+   value of \ref DXS_status_t
+*/
+int32_t DXS_EventDisable(DXS_CHANNEL_t *pCh, DXS_Event_id_t ev)
+{
+   if (ev <= DXS_EVENT_NONE || ev >= DXS_EVENT_MAX ||
+        /* error events cannot be disabled */
+        ev == DXS_EVENT_OVERTEMP || ev == DXS_EVENT_OVERTEMP_END ||
+        ev == DXS_EVENT_GROUND_FAULT || ev == DXS_EVENT_GROUND_FAULT_END ||
+        ev == DXS_EVENT_FAULT_FW_WATCHDOG ||
+        ev == DXS_EVENT_NLT_ABORT ||
+        ev == DXS_EVENT_DEBUG_CERR ||
+        ev == DXS_EVENT_CID_BUF_UNDERFLOW ||
+        ev == DXS_EVENT_CID_SEQ_ERROR)
+   {
+      DXS_RETURN(DXS_statusEventDisableNotAllowed);
+   }
+   dxs_event_bit_clear(pCh, ev);
+   return DXS_statusOk;
+}
+
+/**
+   Function DXS_EventMaskSetDefault
+
+   \param   pCh    - pointer to DXS channel structure
+
+   \return  none
+*/
+void DXS_EventMaskSetDefault(DXS_CHANNEL_t *pCh)
+{
+   /* events enabled by default: */
+   dxs_event_bit_set(pCh, DXS_EVENT_FXS_ONHOOK);
+   dxs_event_bit_set(pCh, DXS_EVENT_FXS_OFFHOOK);
+   dxs_event_bit_set(pCh, DXS_EVENT_FXS_FLASH);
+   dxs_event_bit_set(pCh, DXS_EVENT_NLT_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_NLT_ABORT);
+   dxs_event_bit_set(pCh, DXS_EVENT_PULSE_DIGIT);
+   dxs_event_bit_set(pCh, DXS_EVENT_PULSE_START);
+   dxs_event_bit_set(pCh, DXS_EVENT_DTMF_DIGIT);
+   dxs_event_bit_set(pCh, DXS_EVENT_CALIBRATION_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_METERING_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_OVERTEMP);
+   dxs_event_bit_set(pCh, DXS_EVENT_OVERTEMP_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_GROUND_FAULT);
+   dxs_event_bit_set(pCh, DXS_EVENT_GROUND_FAULT_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_TONE_DET_CPT);
+   dxs_event_bit_set(pCh, DXS_EVENT_TONE_DET_CPT_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_DEBUG_CERR);
+   dxs_event_bit_set(pCh, DXS_EVENT_CID_REQ_DATA);
+   dxs_event_bit_set(pCh, DXS_EVENT_CID_BUF_UNDERFLOW);
+   dxs_event_bit_set(pCh, DXS_EVENT_CID_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_CID_SEQ_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_CID_SEQ_ERROR);
+   dxs_event_bit_set(pCh, DXS_EVENT_GROUND_KEY);
+   dxs_event_bit_set(pCh, DXS_EVENT_GROUND_KEY_END);
+   dxs_event_bit_set(pCh, DXS_EVENT_FAULT_FW_WATCHDOG);
+   dxs_event_bit_set(pCh, DXS_EVENT_T2G_TIMER_EXPIRED);
+   /* events not enabled by default: */
+#if 0
+   dxs_event_bit_set(pCh, DXS_EVENT_FXS_RAW_ONHOOK);
+   dxs_event_bit_set(pCh, DXS_EVENT_FXS_RAW_OFFHOOK);
+#endif
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_event.h b/marvell/services/dxslic/api_lib/src/dxs_event.h
new file mode 100644
index 0000000..1b06fb6
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_event.h
@@ -0,0 +1,43 @@
+#ifndef __DXS_EVENT_H__
+#define __DXS_EVENT_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_event.h
+   Event handling functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+extern int32_t dxs_event_pool_init(DXS_DEVICE_t *pDev);
+extern int32_t dxs_event_get(DXS_DEVICE_t *pDev, DXS_Event_t *pEvent);
+
+extern void DXS_EventDispatch (DXS_DEVICE_t *pDev, DXS_Event_t *pEvent);
+extern void dxs_event_pool_exit(DXS_DEVICE_t *pDev);
+extern int32_t DXS_EventEnable(DXS_CHANNEL_t *pCh, DXS_Event_id_t ev);
+extern int32_t DXS_EventDisable(DXS_CHANNEL_t *pCh, DXS_Event_id_t ev);
+extern void DXS_EventMaskSetDefault(DXS_CHANNEL_t *pCh);
+#endif /* __DXS_EVENT_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_fifo.c b/marvell/services/dxslic/api_lib/src/dxs_fifo.c
new file mode 100644
index 0000000..d474ff6
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_fifo.c
@@ -0,0 +1,229 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_fifo.c
+   Implementation of DxS fifo functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdlib.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#include "dxs_config.h"
+#include "dxs_fifo.h"
+#include "dxs_error.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/* two fifos per device:
+   one for messages, one for command outbox data */
+#define FIFOS_PER_DEVICE      2
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+/** placeholder for the fifos */
+FIFO_t  dxs_fifos[DXS_MAX_DEVICES * FIFOS_PER_DEVICE];
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+/**
+   Function fifo_init
+
+   \param   elements    - elements
+
+   \return
+   - FIFO_t
+*/
+FIFO_t*  fifo_init (uint32_t elements)
+{
+   FIFO_t *p;
+   int idx;
+
+   for (idx=0; idx<(DXS_MAX_DEVICES * FIFOS_PER_DEVICE); idx++)
+   {
+      p = &dxs_fifos[idx];
+      if (!p->in_use)
+         break;
+   }
+   if (idx == (DXS_MAX_DEVICES * FIFOS_PER_DEVICE))
+   {
+      return NULL;
+   }
+
+   p->magic = DXS_FIFO_MAGIC_CODE;
+
+   if (elements > MAX_FIFO_SIZE)
+      elements = MAX_FIFO_SIZE;
+
+   p->fifo_size = elements;
+   p->count = p->wr_idx = p->rd_idx = 0;
+
+   pthread_mutex_init(&p->mtx, NULL);
+
+   p->in_use = 1;
+
+   return p;
+}
+
+/**
+   Function fifo_destroy
+
+   \param   fifo    - pointer to FIFO_t
+
+*/
+void fifo_destroy (FIFO_t *fifo)
+{
+   int err;
+   err = pthread_mutex_unlock(&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+   err = pthread_mutex_destroy(&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   fifo->in_use = 0;
+   fifo->magic = 0;
+}
+
+/**
+   Function fifo_flush
+
+   \param   fifo    - pointer to FIFO_t
+
+*/
+void fifo_flush (FIFO_t *fifo)
+{
+   int err;
+   err = pthread_mutex_lock (&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   fifo->count = fifo->wr_idx = fifo->rd_idx = 0;
+
+   err = pthread_mutex_unlock (&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+}
+
+/**
+   Function fifo_count
+
+   \param   fifo    - pointer to FIFO_t
+
+   \return
+   - uint32_t count
+*/
+uint32_t fifo_count (FIFO_t *fifo)
+{
+   return fifo->count;
+}
+
+/**
+   Function fifo_put
+
+   \param   fifo    - pointer to FIFO_t
+   \param   data    - pointer to data
+   \param   size    - size
+
+   \return
+      DXS_FIFO_INV
+      DXS_FIFO_FULL
+      DXS_FIFO_OK
+*/
+int32_t fifo_put (FIFO_t *fifo, void *data, uint32_t size)
+{
+   FIFO_Elem_t *p;
+   int err;
+
+   if (fifo->magic != DXS_FIFO_MAGIC_CODE)
+      return DXS_FIFO_INV;
+
+   if (fifo->count == fifo->fifo_size)
+      return DXS_FIFO_FULL;
+
+   err = pthread_mutex_lock (&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   p = &fifo->elem[fifo->wr_idx];
+
+   p->data = data;
+   p->size = size;
+   fifo->count++;
+
+   if (++fifo->wr_idx == fifo->fifo_size)
+      fifo->wr_idx = 0;
+
+   err = pthread_mutex_unlock (&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return DXS_FIFO_OK;
+}
+
+/**
+   Function fifo_get
+
+   \param   fifo    - pointer to FIFO_t
+   \param   data    - pointer to data
+   \param   size    - pointer size
+
+   \return
+      DXS_FIFO_INV
+      DXS_FIFO_EMPTY
+      DXS_FIFO_OK
+*/
+int32_t fifo_get (FIFO_t *fifo, void **data, uint32_t *size)
+{
+   FIFO_Elem_t *p;
+   int err;
+
+   if (fifo->magic != DXS_FIFO_MAGIC_CODE)
+      return DXS_FIFO_INV;
+
+   if (fifo->count == 0)
+      return DXS_FIFO_EMPTY;
+
+   err = pthread_mutex_lock (&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   p = &fifo->elem[fifo->rd_idx];
+
+   *data = p->data;
+   *size = p->size;
+   fifo->count--;
+
+   if (++fifo->rd_idx == fifo->fifo_size)
+      fifo->rd_idx = 0;
+
+   err = pthread_mutex_unlock (&fifo->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return DXS_FIFO_OK;
+}
+
diff --git a/marvell/services/dxslic/api_lib/src/dxs_fifo.h b/marvell/services/dxslic/api_lib/src/dxs_fifo.h
new file mode 100644
index 0000000..4a62d40
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_fifo.h
@@ -0,0 +1,77 @@
+#ifndef __DXS_FIFO_H__
+#define __DXS_FIFO_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_fifo.h
+   DxS fifo declarations.
+*/
+
+/*
+|               header                 |  elem 0  |  elem 1  |  elem 2  | ...
++------------+-------+--------+--------+---+------+---+------+---+------+-------
+| magic code | count | wr_idx | rd_idx | p | size | p | size | p | size | ...
++------------+-------+--------+--------+-+-+------+-+-+------+-+-+------+-------
+                                         |          |          |
+                                         V          V          V
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define MAX_FIFO_SIZE    200 /* in elements */
+#define DXS_FIFO_MAGIC_CODE   0x41464946
+/* return codes */
+#define DXS_FIFO_OK     0
+#define DXS_FIFO_FULL   (-1)
+#define DXS_FIFO_EMPTY  (-2)
+#define DXS_FIFO_INV    (-3)
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** FIFO_Elem_t */
+typedef struct
+{
+   void     *data;
+   uint32_t size;
+} FIFO_Elem_t;
+
+/** FIFO_t */
+typedef struct
+{
+   uint32_t           magic;
+   uint32_t           in_use;
+   uint32_t           fifo_size;
+   uint32_t           count;
+   uint32_t           wr_idx;
+   uint32_t           rd_idx;
+   pthread_mutex_t    mtx;
+   FIFO_Elem_t  elem[MAX_FIFO_SIZE];
+} FIFO_t;
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+FIFO_t*  fifo_init (uint32_t elememts);
+void     fifo_flush (FIFO_t *fifo);
+uint32_t fifo_count (FIFO_t *fifo);
+int32_t  fifo_put (FIFO_t *fifo, void *data, uint32_t size);
+int32_t  fifo_get (FIFO_t *fifo, void **data, uint32_t *size);
+
+extern void fifo_destroy (FIFO_t *fifo);
+
+#endif /* __DXS_FIFO_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_fw_cmd.h b/marvell/services/dxslic/api_lib/src/dxs_fw_cmd.h
new file mode 100644
index 0000000..8c2d1ab
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_fw_cmd.h
@@ -0,0 +1,576 @@
+#ifndef __DXS_FW_CMD_H__
+#define __DXS_FW_CMD_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_fw_cmd.h
+   This file contains the type definitions specific to the DXS
+   firmware commands.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_mbx.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/** Command header definition (big endian) */
+#define CMD_HEAD_BE         \
+   /* Read/Write */         \
+   uint32_t RW : 1;         \
+   /* Reserved */           \
+   uint32_t Res00 : 2;      \
+   /* Command */            \
+   uint32_t CMD : 5;        \
+   /* Reserved */           \
+   uint32_t Res01 : 4;      \
+   /* Channel */            \
+   uint32_t CHAN : 4;       \
+   /* Module */             \
+   uint32_t MOD : 3;        \
+   /* Command Sub-Mode */   \
+   uint32_t ECMD : 5;       \
+   /* Length of Message */  \
+   uint32_t LENGTH : 8
+
+/** Command header definition (little endian) */
+#define CMD_HEAD_LE         \
+   /* Length of Message */  \
+   uint32_t LENGTH : 8;     \
+   /* Command Sub-Mode */   \
+   uint32_t ECMD : 5;       \
+   /* Module */             \
+   uint32_t MOD : 3;        \
+   /* Channel */            \
+   uint32_t CHAN : 4;       \
+   /* Reserved */           \
+   uint32_t Res01 : 4;      \
+   /* Command */            \
+   uint32_t CMD : 5;        \
+   /* Reserved */           \
+   uint32_t Res00 : 2;      \
+   /* Read/Write */         \
+   uint32_t RW : 1
+
+#define CMD_EOP      6
+#define CMD_SDD      1
+
+#define MOD_EOP_GPIO 0
+#define MOD_SDD_PCM  0
+#define MOD_SIG_GEN  3
+#define MOD_SIG_DET  6
+#define MOD_SYS      7
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** DXS firmware command header type. */
+struct DXS_FW_Cmd_Header
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+#else
+   CMD_HEAD_LE;
+#endif
+} __attribute__ ((packed));
+
+/** This structure contains data specific to BBD basic config fw command. */
+struct DXS_FW_SDD_BasicConfig
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t  Res01 : 4;
+   /* DUP Time for Hook Debouncing in ACT Mode */
+   uint32_t ActiveDup : 4;
+   /* DUP Time for Hook Debouncing in GS Mode */
+   uint32_t GsDup : 4;
+   /* Reserved */
+   uint32_t Res02 : 4;
+   /* DUP Time for Ground Key Debouncing */
+   uint32_t GndkDup : 4;
+   /* Emergency Shut Down Debounce Time */
+   uint32_t EsdDup : 4;
+   /* Reserved */
+   uint32_t Res03 : 2;
+   /* Automatic Sense Bias Enable */
+   uint32_t AutoBiasEn : 1;
+   /* Reserved */
+   uint32_t Res04 : 5;
+   /* Reserved */
+   uint32_t Res05 : 4;
+   /* DC/DC Overhead Voltage */
+   uint32_t DcDcOvh : 4;
+   /* Reserved */
+   uint32_t Res06 : 5;
+   /* Standby Voltage */
+   uint32_t StbyVolt : 2;
+   /* Reserved */
+   uint32_t Res07 : 1;
+   /*  TTX Burst Length */
+   uint32_t TtxBurstLength : 16;
+   /* Current gain for PID regulator */
+   uint32_t DcPidGain : 16;
+   /* On-Hook Threshold in ACT Mode */
+   uint32_t ActOnhookThresh : 16;
+   /* Off-Hook Threshold in ACT Mode */
+   uint32_t ActOffhookThresh : 16;
+   /* Reserved */
+   uint32_t Res08 : 16;
+   /* Open Loop Voltage Limit */
+   uint32_t VoltageLimit : 16;
+   /* Closed Loop Current Limit */
+   uint32_t CurrentLimit : 16;
+#else
+   /* Reserved */
+   uint32_t Res04 : 5;
+   /* Automatic Sense Bias Enable */
+   uint32_t AutoBiasEn : 1;
+   /* Reserved */
+   uint32_t Res03 : 2;
+   /* Emergency Shut Down Debounce Time */
+   uint32_t EsdDup : 4;
+   /* DUP Time for Ground Key Debouncing */
+   uint32_t GndkDup : 4;
+   /* Reserved */
+   uint32_t Res02 : 4;
+   /* DUP Time for Hook Debouncing in GS Mode */
+   uint32_t GsDup : 4;
+   /* DUP Time for Hook Debouncing in ACT Mode */
+   uint32_t ActiveDup : 4;
+   /* Reserved */
+   uint32_t  Res01 : 4;
+   /*  TTX Burst Length */
+   uint32_t TtxBurstLength : 16;
+   /* Reserved */
+   uint32_t Res07 : 1;
+   /* Standby Voltage */
+   uint32_t StbyVolt : 2;
+   /* Reserved */
+   uint32_t Res06 : 5;
+   /* DC/DC Overhead Voltage */
+   uint32_t DcDcOvh : 4;
+   /* Reserved */
+   uint32_t Res05 : 4;
+   /* On-Hook Threshold in ACT Mode */
+   uint32_t ActOnhookThresh : 16;
+   /* Current gain for PID regulator */
+   uint32_t DcPidGain : 16;
+   /* Reserved */
+   uint32_t Res08 : 16;
+   /* Off-Hook Threshold in ACT Mode */
+   uint32_t ActOffhookThresh : 16;
+   /* Closed Loop Current Limit */
+   uint32_t CurrentLimit : 16;
+   /* Open Loop Voltage Limit */
+   uint32_t VoltageLimit : 16;
+#endif
+} __attribute__ ((packed));
+
+/** This structure contains data specific to
+    SDD_BasicConfig firmware command, IFB12CH8 family. */
+struct DXS_FW_DX8_SDD_BasicConfig
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t Res00 : 4;
+   /* DUP Time for Hook Debouncing in ACT Mode */
+   uint32_t ActiveDup : 4;
+   /* DUP Time for Hook Debouncing in GS Mode */
+   uint32_t GsDup : 4;
+   /* DUP Time for Hook Debouncing in Standby Mode */
+   uint32_t StbyDup : 4;
+   /* DUP Time for Ground Key Debouncing */
+   uint32_t GndkDup : 4;
+   /* Emergency Shut Down Debounce Time */
+   uint32_t EsdDup : 4;
+   /* Reserved */
+   uint32_t Res01 : 2;
+   /* Automatic Sense Bias Enable */
+   uint32_t AutoBiasEn : 1;
+   /* Reserved */
+   uint32_t Res02 : 5;
+   /* Standby Offhook Overhead Voltage */
+   uint32_t StbyOffhOvh : 4;
+   /* DC/DC Overhead Voltage */
+   uint32_t DcDcOvh : 4;
+   /* Reserved */
+   uint32_t Res03 : 8;
+   /* TTX Burst Length (not supported by DXC) */
+   uint32_t TtxBurstLength : 16;
+   /* Current gain for PID regulator */
+   uint32_t DcPidGain : 16;
+   /* On-Hook Threshold in ACT Mode */
+   uint32_t ActOnhookThresh : 16;
+   /* Off-Hook Threshold in ACT Mode */
+   uint32_t ActOffhookThresh : 16;
+   /* Voltage Threshold for Battery Switch */
+   uint32_t VoltageThresh : 16;
+   /* Open Loop Voltage Limit */
+   uint32_t VoltageLimit : 16;
+   /* Closed Loop Current Limit */
+   uint32_t CurrentLimit : 16;
+#else
+   /* Reserved */
+   uint32_t Res02 : 5;
+   /* Automatic Sense Bias Enable */
+   uint32_t AutoBiasEn : 1;
+   /* Reserved */
+   uint32_t Res01 : 2;
+   /* Emergency Shut Down Debounce Time */
+   uint32_t EsdDup : 4;
+   /* DUP Time for Ground Key Debouncing */
+   uint32_t GndkDup : 4;
+   /* DUP Time for Hook Debouncing in Standby Mode */
+   uint32_t StbyDup : 4;
+   /* DUP Time for Hook Debouncing in GS Mode */
+   uint32_t GsDup : 4;
+   /* DUP Time for Hook Debouncing in ACT Mode */
+   uint32_t ActiveDup : 4;
+   /* Reserved */
+   uint32_t Res00 : 4;
+   /* TTX Burst Length (not supported by DXC) */
+   uint32_t TtxBurstLength : 16;
+   /* Reserved */
+   uint32_t Res03 : 8;
+   /* DC/DC Overhead Voltage */
+   uint32_t DcDcOvh : 4;
+   /* Standby Offhook Overhead Voltage */
+   uint32_t StbyOffhOvh : 4;
+   /* On-Hook Threshold in ACT Mode */
+   uint32_t ActOnhookThresh : 16;
+   /* Current gain for PID regulator */
+   uint32_t DcPidGain : 16;
+   /* Voltage Threshold for Battery Switch */
+   uint32_t VoltageThresh : 16;
+   /* Off-Hook Threshold in ACT Mode */
+   uint32_t ActOffhookThresh : 16;
+   /* Closed Loop Current Limit */
+   uint32_t CurrentLimit : 16;
+   /* Open Loop Voltage Limit */
+   uint32_t VoltageLimit : 16;
+#endif
+} __attribute__ ((packed));
+
+struct DXS_basicConfigData{
+   uint32_t data_u32[sizeof(struct DXS_FW_SDD_BasicConfig)/sizeof(uint32_t)];
+} __attribute__ ((packed));
+
+/** Union for accessing data as uint32_t. */
+union DXS_FW_SDD_BasicConfig_u
+{
+   struct DXS_basicConfigData bc_data;
+   struct DXS_FW_SDD_BasicConfig  fwmsg;
+   struct DXS_FW_DX8_SDD_BasicConfig dx8fwmsg;
+};
+
+/** This structure contains data specific to ring config firmware command. */
+struct DXS_FW_SDD_RingConfig
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t Res02 : 2;
+   /* Ring Trip Type */
+   uint32_t RingTripType : 2;
+   /* Wave Form of Ringing Signal */
+   uint32_t WaveForm : 1;
+   /* Ring Crest Factor */
+   uint32_t CrestFact : 3;
+   /* Reserved */
+   uint32_t Res03 : 8;
+   /* Ringing Frequency */
+   uint32_t Frequency : 16;
+   /* Ringing Amplitude */
+   uint32_t Amplitude : 16;
+   /* Ringing Hook Threshold */
+   uint32_t Thresh : 16;
+   /* Ringing DC Offset */
+   uint32_t DcOffset : 16;
+   /* Maximum Ring Current */
+   uint32_t Imax : 16;
+   /* Ringing Regulation Coefficient */
+   uint32_t RegCoeff : 16;
+   /* Minimum Ringing Voltage (peak) */
+   uint32_t Vmin : 16;
+   /* Reserved */
+   uint32_t Res04 : 16;
+   /* Fast Hook Threshold */
+   uint32_t FastThresh : 16;
+#else
+   /* Ringing Frequency */
+   uint32_t Frequency : 16;
+   /* Reserved */
+   uint32_t Res03 : 8;
+   /* Ring Crest Factor */
+   uint32_t CrestFact : 3;
+   /* Wave Form of Ringing Signal */
+   uint32_t WaveForm : 1;
+   /* Ring Trip Type */
+   uint32_t RingTripType : 2;
+   /* Reserved */
+   uint32_t Res02 : 2;
+   /* Ringing Hook Threshold */
+   uint32_t Thresh : 16;
+   /* Ringing Amplitude */
+   uint32_t Amplitude : 16;
+   /* Maximum Ring Current */
+   uint32_t Imax : 16;
+   /* Ringing DC Offset */
+   uint32_t DcOffset : 16;
+   /* Minimum Ringing Voltage (peak) */
+   uint32_t Vmin : 16;
+   /* Ringing Regulation Coefficient */
+   uint32_t RegCoeff : 16;
+   /* Fast Hook Threshold */
+   uint32_t FastThresh : 16;
+   /* Reserved */
+   uint32_t Res04 : 16;
+#endif
+} __attribute__ ((packed));
+
+
+/** Union for acccessing data as uint32_t. */
+union DXS_FW_SDD_RingConfig_u
+{
+   uint32_t u32[sizeof(struct DXS_FW_SDD_RingConfig)/sizeof(uint32_t)];
+   struct DXS_FW_SDD_RingConfig  fwmsg;
+};
+
+/** This structure contains data specific to DC/DC config firmware command. */
+struct DXS_FW_SDD_DcDcConfig
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t Res00 : 4;
+   /* DC/DC Capacitance */
+   uint32_t DcDcCap : 4;
+   /* DC/DC Hardware Option */
+   uint32_t DcDcHw : 4;
+   /* Reserved */
+   uint32_t Res01 : 1;
+   /* DC/DC Switch Output Enable */
+   uint32_t DcDcSwEn : 1;
+   /* Combined Low Power Mode */
+   uint32_t CombLP : 1;
+   /* DC/DC Switch Output Inverted */
+   uint32_t DcDcSwInv : 1;
+   /* Power Value for Boost Calculation */
+   uint32_t P1 : 16;
+   /* DC/DC Maximum On Time of Switching Transistor */
+   uint32_t MaxOnTime : 8;
+   /* Maximum Frequency of DC/DC Converter */
+   uint32_t MaxFreq  : 8;
+   /* DC/DC On Time of Switching Transistor in STANDBY Mode */
+   uint32_t OnTimeStby : 8;
+   /* Maximum Frequency of DC/DC Converter in STANDBY Mode */
+   uint32_t MaxFreqStby : 8;
+#else
+   /* Power Value for Boost Calculation */
+   uint32_t P1 : 16;
+   /* DC/DC Switch Output Inverted */
+   uint32_t DcDcSwInv : 1;
+   /* Combined Low Power Mode */
+   uint32_t CombLP : 1;
+   /* DC/DC Switch Output Enable */
+   uint32_t DcDcSwEn : 1;
+   /* Reserved */
+   uint32_t Res01 : 1;
+   /* DC/DC Hardware Option */
+   uint32_t DcDcHw : 4;
+   /* DC/DC Capacitance */
+   uint32_t DcDcCap : 4;
+   /* Reserved */
+   uint32_t Res00 : 4;
+   /* Maximum Frequency of DC/DC Converter in STANDBY Mode */
+   uint32_t MaxFreqStby : 8;
+   /* DC/DC On Time of Switching Transistor in STANDBY Mode */
+   uint32_t OnTimeStby : 8;
+   /* Maximum Frequency of DC/DC Converter */
+   uint32_t MaxFreq  : 8;
+   /* DC/DC Maximum On Time of Switching Transistor */
+   uint32_t MaxOnTime : 8;
+#endif
+} __attribute__ ((packed));
+
+/** This structure contains data specific to
+    DC/DC config firmware command, IFB12CH8 family. */
+struct DXS_FW_DX8_SDD_DcDcConfig
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* DC/DC Minimum On Time of Switching Transistor */
+   uint32_t MinOnTime : 8;
+   /* Reserved */
+   uint32_t Res00 : 5;
+   /* DC/DC Switch Output Enable */
+   uint32_t DcDcSwEn : 1;
+   /* Reserved */
+   uint32_t Res01 : 1;
+   /* DC/DC Switch Output Inverted */
+   uint32_t DcDcSwInv : 1;
+   /* Reserved */
+   uint32_t Res02 : 16;
+   /* DC/DC Maximum On Time of Switching Transistor */
+   uint32_t MaxOnTime : 8;
+   /* Maximum Frequency of DC/DC Converter */
+   uint32_t MaxFreq : 8;
+   /* DC/DC Voltage */
+   uint32_t DcDcVoltage : 16;
+#else
+   /* Reserved */
+   uint32_t Res02 : 16;
+   /* DC/DC Switch Output Inverted */
+   uint32_t DcDcSwInv : 1;
+   /* Reserved */
+   uint32_t Res01 : 1;
+   /* DC/DC Switch Output Enable */
+   uint32_t DcDcSwEn : 1;
+   /* Reserved */
+   uint32_t Res00 : 5;
+   /* DC/DC Minimum On Time of Switching Transistor */
+   uint32_t MinOnTime : 8;
+   /* DC/DC Voltage */
+   uint32_t DcDcVoltage : 16;
+   /* Maximum Frequency of DC/DC Converter */
+   uint32_t MaxFreq : 8;
+   /* DC/DC Maximum On Time of Switching Transistor */
+   uint32_t MaxOnTime : 8;
+#endif
+} __attribute__ ((packed));
+
+struct DXS_DcDcConfigData
+{
+   uint32_t data_u32[sizeof(struct DXS_FW_SDD_DcDcConfig)/sizeof(uint32_t)];
+} __attribute__ ((packed));
+
+/** Union for acccessing data as uint32_t. */
+union DXS_FW_SDD_DcDcConfig_u
+{
+   struct DXS_DcDcConfigData dcdc_data;
+   struct DXS_FW_SDD_DcDcConfig  fwmsg;
+   struct DXS_FW_DX8_SDD_DcDcConfig dx8fwmsg;
+};
+
+/** This structure contains data specific to MWL config firmware command. */
+struct DXS_FW_SDD_MwlConfig
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Message Waiting Lamp Voltage */
+   uint32_t Voltage : 16;
+   /* Message Waiting Hook Threshold */
+   uint32_t Thresh : 16;
+   /* Message Waiting Slope */
+   uint32_t Slope : 16;
+   /* Message Waiting On-time (Lamp ON) */
+   uint32_t OnTime : 8;
+   /* Message Waiting Off-time (Lamp OFF) */
+   uint32_t OffTime :8;
+#else
+   /* Message Waiting Hook Threshold */
+   uint32_t Thresh : 16;
+   /* Message Waiting Lamp Voltage */
+   uint32_t Voltage : 16;
+   /* Message Waiting Off-time (Lamp OFF) */
+   uint32_t OffTime :8;
+   /* Message Waiting On-time (Lamp ON) */
+   uint32_t OnTime : 8;
+   /* Message Waiting Slope */
+   uint32_t Slope : 16;
+#endif
+} __attribute__ ((packed));
+
+/** Union for acccessing data as uint32_t. */
+union DXS_FW_SDD_MwlConfig_u
+{
+   uint32_t u32[sizeof(struct DXS_FW_SDD_MwlConfig)/sizeof(uint32_t)];
+   struct DXS_FW_SDD_MwlConfig  fwmsg;
+};
+
+/** This structure contains data specific to UTD coefficients fw command. */
+struct DXS_FW_SIG_UtdCoeff
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Bandwidth */
+   uint32_t BW : 16;
+   /* Center Frequency */
+   uint32_t CF : 16;
+   /* Noise Level */
+   uint32_t NLEV : 16;
+   /* Signal Level */
+   uint32_t SLEV : 16;
+   /* Delta Level */
+   uint32_t DLEV : 16;
+   /* Low Pass Coefficient */
+   uint32_t LPCOEFF : 16;
+   /* Data Upstream Persistence Counter */
+   uint32_t DUP : 8;
+   /* Reserved */
+   uint32_t Res02 : 24;
+#else
+   /* Center Frequency */
+   uint32_t CF : 16;
+   /* Bandwidth */
+   uint32_t BW : 16;
+   /* Signal Level */
+   uint32_t SLEV : 16;
+   /* Noise Level */
+   uint32_t NLEV : 16;
+   /* Low Pass Coefficient */
+   uint32_t LPCOEFF : 16;
+   /* Delta Level */
+   uint32_t DLEV : 16;
+   /* Reserved */
+   uint32_t Res02 : 24;
+   /* Data Upstream Persistence Counter */
+   uint32_t DUP : 8;
+#endif
+} __attribute__ ((packed));
+
+/** Union for acccessing data as uint32_t. */
+union DXS_FW_SIG_UtdCoeff_u
+{
+   uint32_t u32[sizeof(struct DXS_FW_SIG_UtdCoeff)/sizeof(uint32_t)];
+   struct DXS_FW_SIG_UtdCoeff  fwmsg;
+};
+#define COEF_SIZE_UINT_32 6
+/** This structure contains data specific to SDD coefficients fw command. */
+struct DXS_FW_SDD_Coeff
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Destination */
+   uint32_t Dest : 1;
+   /* Offset of Coefficient Block */
+   uint32_t BlockOffset : 10;
+   /* Length of Coefficient Block */
+   uint32_t BlockLength : 5;
+   /* Coefficient 0 */
+   uint32_t Coefficient0 : 16;
+#else
+   /* Coefficient 0 */
+   uint32_t Coefficient0 : 16;
+   /* Length of Coefficient Block */
+   uint32_t BlockLength : 5;
+   /* Offset of Coefficient Block */
+   uint32_t BlockOffset : 10;
+   /* Destination */
+   uint32_t Dest : 1;
+#endif
+   union
+   {
+      uint32_t Coefficients_32[COEF_SIZE_UINT_32];
+   };
+} __attribute__ ((packed));
+#define DXS_FW_SDD_Coeff_ECMD        13
+#define DXS_FW_SDD_Coeff_MAXLENGTH   28
+
+
+#endif /* __DXS_FW_CMD_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_gpio.c b/marvell/services/dxslic/api_lib/src/dxs_gpio.c
new file mode 100644
index 0000000..e33b77e
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_gpio.c
@@ -0,0 +1,324 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_gpio.c
+   Implementation of GPIO functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_config.h"
+
+#ifdef DXS_FEAT_GPIO
+
+#include "dxs.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** Data structure for GPIO configuration firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Reserved */
+   uint32_t Res02 : 4;
+   /** Enable GPIO Pull-up Resistor */
+   uint32_t GPIO_PULL_UP : 4;
+   /** Reserved */
+   uint32_t Res03 : 4;
+   /** Direction of GPIO Bits */
+   uint32_t GPIO_DIR : 4;
+   /** Reserved */
+   uint32_t Res04 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res04 : 16;
+   /** Direction of GPIO Bits */
+   uint32_t GPIO_DIR : 4;
+   /** Reserved */
+   uint32_t Res03 : 4;
+   /** Enable GPIO Pull-up Resistor */
+   uint32_t GPIO_PULL_UP : 4;
+   /** Reserved */
+   uint32_t Res02 : 4;
+#endif
+} __attribute__ ((packed)) DXS_FW_GPIO_Config_t;
+#define DXS_FW_GPIO_Config_ECMD     2
+#define DXS_FW_GPIO_Config_LENGTH   4
+
+/** Data structure for GPIO control firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Reserved */
+   uint32_t Res02 : 4;
+   /** Write Mask for GPIO */
+   uint32_t GPIO_WR_MSK : 4;
+   /** Reserved */
+   uint32_t Res03 : 4;
+   /** Value of GPIO Bits */
+   uint32_t GPIO_VAL : 4;
+   /** Reserved */
+   uint32_t Res04 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res04 : 16;
+   /** Value of GPIO Bits */
+   uint32_t GPIO_VAL : 4;
+   /** Reserved */
+   uint32_t Res03 : 4;
+   /** Write Mask for GPIO */
+   uint32_t GPIO_WR_MSK : 4;
+   /** Reserved */
+   uint32_t Res02 : 4;
+#endif
+} __attribute__ ((packed)) DXS_FW_GPIO_Data_t;
+#define DXS_FW_GPIO_Data_ECMD     3
+#define DXS_FW_GPIO_Data_LENGTH   4
+
+/** GPIO device resource structure */
+typedef struct
+{
+   /** status flag */
+   uint32_t         flag;
+#define GPIO_DEV_INITIALIZED    0x00000001
+#define GPIO_CTRL_CONFIGURED   0x80000000
+   /**  DXS_FW_GPIO_Config command */
+   DXS_FW_GPIO_Config_t       cfg;
+   /** DXS_FW_GPIO_Data command */
+   DXS_FW_GPIO_Data_t        data;
+} DXS_GPIO_Dev_Resource_t;
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static DXS_GPIO_Dev_Resource_t gpio_devs[DXS_MAX_DEVICES] = {0};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+/**
+   Function to initialize GPIO device resource
+
+   \param   devnum    - device number
+
+*/
+void *DXS_GPIO_DevInit(uint8_t devnum)
+{
+   DXS_GPIO_Dev_Resource_t *p;
+
+   if (devnum >= DXS_MAX_DEVICES)
+      return (void *)NULL;
+
+   p = &gpio_devs[devnum];
+
+   p->flag = 0;
+
+   p->cfg.CMD = CMD_EOP;
+   p->cfg.MOD = MOD_EOP_GPIO;
+   p->cfg.ECMD = DXS_FW_GPIO_Config_ECMD;
+   p->cfg.LENGTH = DXS_FW_GPIO_Config_LENGTH;
+
+   p->data.CMD = CMD_EOP;
+   p->data.MOD = MOD_EOP_GPIO;
+   p->data.ECMD = DXS_FW_GPIO_Data_ECMD;
+   p->data.LENGTH = DXS_FW_GPIO_Data_LENGTH;
+
+   p->flag |= GPIO_DEV_INITIALIZED;
+
+   return (void *)p;
+}
+
+/**
+   Function to configure GPIO
+
+   \param   pDev       - pointer to DXS device structure
+   \param   pGpioConf  - pointer to GPIO config structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_GPIO_Config(DXS_DEVICE_t *pDev, DXS_GpioConfig_t *pGpioConf)
+{
+   int32_t err = DXS_statusOk;
+   DXS_GPIO_Dev_Resource_t  *p;
+   uint8_t new_gpio_PU, new_gpio_dir, param_check;
+
+   if (pDev == NULL || pGpioConf == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_GPIO_Dev_Resource_t *)pDev->gpio;
+
+   if (!(p->flag & GPIO_DEV_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   param_check = (pGpioConf->gpio0_PU | pGpioConf->gpio1_PU |
+                  pGpioConf->gpio2_PU | pGpioConf->gpio3_PU |
+                  pGpioConf->gpio0_DIR | pGpioConf->gpio1_DIR |
+                  pGpioConf->gpio2_DIR | pGpioConf->gpio3_DIR);
+   if (param_check > 1)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   if (!(p->flag & GPIO_CTRL_CONFIGURED))
+   {
+      /* read configuration from the device */
+      err = DXS_CmdRead(pDev, (uint32_t *)&p->cfg, (uint32_t *)&p->cfg);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   /* Set the parameters */
+   new_gpio_PU = 0xF & (pGpioConf->gpio0_PU | (pGpioConf->gpio1_PU << 1) |
+                       (pGpioConf->gpio2_PU << 2) | (pGpioConf->gpio3_PU << 3));
+   new_gpio_dir = 0xF & (pGpioConf->gpio0_DIR | (pGpioConf->gpio1_DIR << 1) |
+                     (pGpioConf->gpio2_DIR << 2) | (pGpioConf->gpio3_DIR << 3));
+
+   if (new_gpio_PU != p->cfg.GPIO_PULL_UP || new_gpio_dir != p->cfg.GPIO_DIR)
+   {
+      /* write new values */
+      p->cfg.GPIO_PULL_UP = new_gpio_PU;
+      p->cfg.GPIO_DIR = new_gpio_dir;
+      err = CmdWrite(pDev, (uint32_t *)&p->cfg);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   p->flag |= GPIO_CTRL_CONFIGURED;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_GPIO_Write
+
+   \param   pDev       - pointer to DXS device structure
+   \param   pin        - pin number
+   \param   val        - value
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_GPIO_Write(DXS_DEVICE_t *pDev, uint8_t pin, uint8_t val)
+{
+   int32_t err = DXS_statusOk;
+   DXS_GPIO_Dev_Resource_t  *p;
+   uint8_t pin_mask;
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_GPIO_Dev_Resource_t *)pDev->gpio;
+
+   if (!(p->flag & GPIO_DEV_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!(p->flag & GPIO_CTRL_CONFIGURED))
+   {
+      /* GPIO port not configured yet */
+      DXS_RETURN(DXS_statusGpioNotConfigured);
+   }
+
+   pin_mask = 1 << pin;
+   /* If the specified pin is configured as input - return error */
+   if (p->cfg.GPIO_DIR & pin_mask)
+   {
+      DXS_RETURN(DXS_statusGpioWriteAccessIgnored);
+   }
+
+   /* Set the parameters */
+   p->data.GPIO_WR_MSK = ~pin_mask;
+   if (val)
+      p->data.GPIO_VAL = 0xF;
+   else
+      p->data.GPIO_VAL = 0;
+
+   /* write new values */
+   err = CmdWrite(pDev, (uint32_t *)&p->data);
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_GPIO_Read
+
+   \param   pDev       - pointer to DXS device structure
+   \param   pin        - pin number
+   \param   pVal       - pointer to value
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_GPIO_Read(DXS_DEVICE_t *pDev, uint8_t pin, uint8_t *pVal)
+{
+   int32_t err = DXS_statusOk;
+   DXS_GPIO_Dev_Resource_t  *p;
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_GPIO_Dev_Resource_t *)pDev->gpio;
+
+   if (!(p->flag & GPIO_DEV_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!(p->flag & GPIO_CTRL_CONFIGURED))
+   {
+      /* GPIO port not configured yet */
+      DXS_RETURN(DXS_statusGpioNotConfigured);
+   }
+
+   err = DXS_CmdRead(pDev, (uint32_t *)&p->data, (uint32_t *)&p->data);
+   if (err)
+   {
+      DXS_RETURN(err);
+   }
+
+   /* Set the parameters */
+   if (p->data.GPIO_VAL & (1 << pin))
+      *pVal = 1;
+   else
+      *pVal = 0;
+
+   DXS_RETURN(err);
+}
+#endif /* DXS_FEAT_GPIO */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_gpio.h b/marvell/services/dxslic/api_lib/src/dxs_gpio.h
new file mode 100644
index 0000000..d547aa7
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_gpio.h
@@ -0,0 +1,40 @@
+#ifndef __DXS_GPIO_H__
+#define __DXS_GPIO_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_gpio.h
+   GPIO functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern void *DXS_GPIO_DevInit(uint8_t dev);
+extern int32_t DXS_GPIO_Config(DXS_DEVICE_t *pDev, DXS_GpioConfig_t *pGpioConf);
+extern int32_t DXS_GPIO_Write(DXS_DEVICE_t *pDev, uint8_t pin, uint8_t val);
+extern int32_t DXS_GPIO_Read(DXS_DEVICE_t *pDev, uint8_t pin, uint8_t *pVal);
+
+#endif /* __DXS_GPIO_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_hsm.c b/marvell/services/dxslic/api_lib/src/dxs_hsm.c
new file mode 100644
index 0000000..c39778f
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_hsm.c
@@ -0,0 +1,804 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_hsm.c
+
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs.h"
+#include "dxs_error.h"
+#include "dxs_timer.h"
+#include "dxs_event.h"
+
+/* ============================= */
+/* Configuration                 */
+/* ============================= */
+/* Scatter the times used for timeout over the given period with the given
+   increment between each timer start. This can help to distribute the load
+   in systems with multiple devices when hook events happen on all lines in
+   parallel. The increment must be smaller than half the maximum time.
+   To use this option set DXS_DIAL_SCATTER_MAX to a positive time in ms and
+   DXS_DIAL_SCATTER_INC to a positive time in ms of maximum half the max time.
+   Using this option degrades the precision of the timeouts for the on-hook,
+   off-hook,  flash-holdoff and interdigit. The precision of the times for
+   flash and pulse detection will stay unaffected. */
+#define DXS_DIAL_SCATTER_MAX  0 /* ms */
+#define DXS_DIAL_SCATTER_INC  0 /* ms */
+#if (DXS_DIAL_SCATTER_MAX / 2) < DXS_DIAL_SCATTER_INC
+#error Configuration of DIAL_SCATTER incorrect
+#endif
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+#if (DXS_DIAL_SCATTER_MAX > 0)
+   #define DXS_DIAL_SCATTER_INCREASE           \
+      do {                                      \
+         nScatter += DXS_DIAL_SCATTER_INC;     \
+         if (nScatter > DXS_DIAL_SCATTER_MAX)  \
+            nScatter = 0;                       \
+      } while (0)
+#else
+   #define DXS_DIAL_SCATTER_INCREASE
+#endif
+
+#if 0
+//origin code
+#define DXS_MIN_FLASH                80
+#define DXS_MAX_FLASH               400
+#define DXS_MIN_FLASH_MAKE          200
+#define DXS_MIN_DIGIT_LOW            30
+#define DXS_MAX_DIGIT_LOW            80
+#define DXS_MIN_DIGIT_HIGH           30
+#define DXS_MAX_DIGIT_HIGH           80
+#define DXS_MIN_OFF_HOOK             40
+#define DXS_MIN_ON_HOOK             400
+#define DXS_MIN_INTERDIGIT          300
+#else
+#define DXS_MIN_FLASH               150
+#define DXS_MAX_FLASH               700
+#define DXS_MIN_FLASH_MAKE          400
+#define DXS_MIN_DIGIT_LOW            30
+#define DXS_MAX_DIGIT_LOW            80
+#define DXS_MIN_DIGIT_HIGH           30
+#define DXS_MAX_DIGIT_HIGH           80
+#define DXS_MIN_OFF_HOOK             40
+#define DXS_MIN_ON_HOOK             710
+#define DXS_MIN_INTERDIGIT          300
+#endif
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+#ifdef DXS_FEAT_HSM
+
+/**
+   Process an action in the state machines.
+
+   In this function the hook, digit and flash state machines are all handled
+   one after the other. The hook state machine needs to be the first because it
+   directly changes the on-hook/off-hook states of the other state machines.
+   This reduces the complexity of code of the other state machines.
+
+   \param  pChannel     Pointer to DXS channel structure.
+   \param  nAction      Action to be executed.
+   \param  nTime        If action is make or break this parameter holds the
+                        duration since the last hook event in milliseconds.
+                        If the action is timeout this parameter is unused.
+*/
+static void dxs_dial_Action(DXS_CHANNEL_t * pChannel,
+                        enum ACTION nAction,
+                        uint16_t nTime)
+{
+   DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
+   DXS_DEVICE_t *pDev = pChannel->pParent;
+   DXS_Event_t dxs_event;
+   int32_t bSendPulseEvent;
+   static uint32_t nScatter = 0; /* library global */
+
+#if 0 /* hook state machine tracing */
+   printf("  ACTION: %d  (hook %d, digit %d, flash %d) time %d\n", nAction,
+      pDXS_DialData->nHookState,
+      pDXS_DialData->nDigitState,
+      pDXS_DialData->nFlashState,
+      nTime);
+#endif
+
+   /* Handle the hook-state detection finite state machine. */
+   switch (pDXS_DialData->nHookState)
+   {
+   case HOOK_STATE_ONHOOK:
+      if (nAction == ACTION_MAKE)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_VALIDATE_OFFHOOK;
+         DXS_TimerSet(pDXS_DialData->HookTimerID,
+            pDXS_DialData->nTimeOffhook + nScatter, 0, 1);
+         DXS_DIAL_SCATTER_INCREASE;
+      }
+      break;
+
+   case HOOK_STATE_OFFHOOK:
+      if (nAction == ACTION_BREAK)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_VALIDATE_ONHOOK;
+         DXS_TimerSet(pDXS_DialData->HookTimerID,
+            pDXS_DialData->nTimeOnhook + nScatter, 0, 1);
+         DXS_DIAL_SCATTER_INCREASE;
+      }
+      break;
+
+   case HOOK_STATE_VALIDATE_OFFHOOK:
+      if (nAction == ACTION_BREAK)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
+         DXS_TimerStop(pDXS_DialData->HookTimerID);
+      }
+      else
+      if (nAction == ACTION_TIMEOUT_HOOK)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_OFFHOOK;
+         /* Attention: change of the digit and flash state machine data! */
+         pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
+         pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
+         pDXS_DialData->nPulseDigit = 0;
+         pDXS_DialData->bPulseStartSent = 0;
+         /* DXS event: off-hook */
+         dxs_event.dev = pDev->nDevNum;
+         dxs_event.ch = pChannel->nCh;
+         dxs_event.id = DXS_EVENT_FXS_OFFHOOK;
+         DXS_EventDispatch(pDev, &dxs_event);
+      }
+      break;
+
+   case HOOK_STATE_VALIDATE_ONHOOK:
+      if (nAction == ACTION_MAKE)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_OFFHOOK;
+         DXS_TimerStop(pDXS_DialData->HookTimerID);
+      }
+      else
+      if (nAction == ACTION_TIMEOUT_HOOK)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
+         /* Attention: change of the digit and flash state machine data! */
+         pDXS_DialData->nDigitState = DIGIT_STATE_ONHOOK;
+         pDXS_DialData->nFlashState = FLASH_STATE_ONHOOK;
+         /* TAPI event: on-hook */
+         dxs_event.dev = pDev->nDevNum;
+         dxs_event.ch = pChannel->nCh;
+         dxs_event.id = DXS_EVENT_FXS_ONHOOK;
+         DXS_EventDispatch(pDev, &dxs_event);
+      }
+      break;
+   }
+
+   /* Handle the pulse dialing detection finite state machine. */
+   /* Attention: the hook state machine above will do the transitions into and
+      out of the off-hook state. */
+   switch (pDXS_DialData->nDigitState)
+   {
+   case DIGIT_STATE_ONHOOK:
+      /* ignore all */
+      break;
+
+   case DIGIT_STATE_OFFHOOK:
+      if (nAction == ACTION_BREAK)
+         pDXS_DialData->nDigitState = DIGIT_STATE_VALIDATE_DIGIT_BREAK;
+      break;
+
+   case DIGIT_STATE_VALIDATE_DIGIT_BREAK:
+      if (nAction == ACTION_MAKE)
+      {
+         if ((nTime >= pDXS_DialData->nTimeDigitBreakMin) &&
+             (nTime <= pDXS_DialData->nTimeDigitBreakMax))
+         {
+            pDXS_DialData->nDigitState = DIGIT_STATE_VALIDATE_DIGIT_MAKE;
+            pDXS_DialData->nPulseDigit += 1;
+            DXS_TimerSet(pDXS_DialData->InterdigitTimerID,
+               pDXS_DialData->nTimeInterdigit + nScatter, 0, 1);
+            DXS_DIAL_SCATTER_INCREASE;
+            if ((pDXS_DialData->nPulseDigit == 1) &&
+                (pDXS_DialData->bPulseStartSent == 0))
+            {
+               /* report the first validated pulse dial break */
+               /* Use this to stop a dial tone right after the first pulse. */
+               dxs_event.dev = pDev->nDevNum;
+               dxs_event.ch = pChannel->nCh;
+               dxs_event.id = DXS_EVENT_PULSE_START;
+               DXS_EventDispatch(pDev, &dxs_event);
+               /* Do this only for the first pulse after off-hook or flash. */
+               pDXS_DialData->bPulseStartSent = 1;
+            }
+         }
+         else
+         {
+            pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
+            pDXS_DialData->nPulseDigit = 0;
+         }
+      }
+      break;
+
+   case DIGIT_STATE_VALIDATE_DIGIT_MAKE:
+      bSendPulseEvent = 0;
+      if (nAction == ACTION_BREAK)
+      {
+         pDXS_DialData->nDigitState = DIGIT_STATE_VALIDATE_DIGIT_BREAK;
+         DXS_TimerStop(pDXS_DialData->InterdigitTimerID);
+         if (nTime >= pDXS_DialData->nTimeInterdigit)
+         {
+            /* Accept also the time from the hook event for the inter-digit
+               timeout condition. */
+            bSendPulseEvent = 1;
+         }
+         else
+         if ((nTime < pDXS_DialData->nTimeDigitMakeMin) ||
+             (nTime > pDXS_DialData->nTimeDigitMakeMax))
+         {
+            pDXS_DialData->nPulseDigit = 0;
+         }
+      }
+      else
+      if (nAction == ACTION_TIMEOUT_INTERDIGIT)
+      {
+         pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
+         bSendPulseEvent = 1;
+      }
+      /* _no_ else here */
+      if (bSendPulseEvent)
+      {
+         if (pDXS_DialData->nPulseDigit <= 10)
+         {
+            /* TAPI event: digit */
+            dxs_event.dev = pDev->nDevNum;
+            dxs_event.ch = pChannel->nCh;
+            dxs_event.id = DXS_EVENT_PULSE_DIGIT;
+            dxs_event.data.pulse.digit = pDXS_DialData->nPulseDigit;
+            /* 10 pulses represent digit 0 which has TAPI code 0xB */
+            if (dxs_event.data.pulse.digit == 10)
+               dxs_event.data.pulse.digit = 0x0B;
+            DXS_EventDispatch(pDev, &dxs_event);
+         }
+         pDXS_DialData->nPulseDigit = 0;
+      }
+      break;
+   }
+
+   /* Handle the flash hook detection finite state machine. */
+   /* Attention: the hook state machine above will do the transitions into and
+      out of the off-hook state. */
+   switch (pDXS_DialData->nFlashState)
+   {
+   case FLASH_STATE_ONHOOK:
+      /* ignore all */
+      break;
+
+   case FLASH_STATE_OFFHOOK:
+      if (nAction == ACTION_BREAK)
+         pDXS_DialData->nFlashState = FLASH_STATE_VALIDATE_FLASH_BREAK;
+      break;
+
+   case FLASH_STATE_VALIDATE_FLASH_BREAK:
+      if (nAction == ACTION_MAKE)
+      {
+         if ((nTime >= pDXS_DialData->nTimeFlashBreakMin) &&
+             (nTime <= pDXS_DialData->nTimeFlashBreakMax))
+         {
+            pDXS_DialData->nFlashState = FLASH_STATE_VALIDATE_FLASH_HOLDOFF;
+            DXS_TimerSet(pDXS_DialData->FlashHoldoffTimerID,
+               pDXS_DialData->nTimeFlashHoldoff + nScatter, 0, 1);
+            DXS_DIAL_SCATTER_INCREASE;
+         }
+         else
+         {
+            pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
+         }
+      }
+      break;
+
+   case FLASH_STATE_VALIDATE_FLASH_HOLDOFF:
+      if (nAction == ACTION_BREAK)
+      {
+         pDXS_DialData->nFlashState = FLASH_STATE_VALIDATE_FLASH_BREAK;
+         DXS_TimerStop(pDXS_DialData->FlashHoldoffTimerID);
+      }
+      else
+      if (nAction == ACTION_TIMEOUT_FLASHHOLDOFF)
+      {
+         pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
+         pDXS_DialData->bPulseStartSent = 0;
+         /* TAPI event: flash */
+         dxs_event.dev = pDev->nDevNum;
+         dxs_event.ch = pChannel->nCh;
+         dxs_event.id = DXS_EVENT_FXS_FLASH;
+         DXS_EventDispatch(pDev, &dxs_event);
+      }
+      break;
+   }
+
+#if 0 /* hook state machine tracing */
+   printf("             (hook %d, digit %d, flash %d) digit %d\n",
+           pDXS_DialData->nHookState,
+           pDXS_DialData->nDigitState,
+           pDXS_DialData->nFlashState,
+           pDXS_DialData->nPulseDigit);
+#endif
+}
+
+
+/**
+   Hook state machine timer callback function.
+
+   \param  nArg         Argument of timer. This argument is a pointer to the
+                        DXS_CHANNEL_t structure.
+*/
+void dxs_dial_OnHookTimer(Timer_ID tm, void *arg)
+{
+   DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
+
+   dxs_dial_Action(pChannel, ACTION_TIMEOUT_HOOK, /*dummy*/0);
+   return;
+}
+
+
+/**
+   Inter-digit timer callback function.
+
+   \param  nArg         Argument of timer. This argument is a pointer to the
+                        DXS_CHANNEL_t structure.
+*/
+void dxs_dial_OnInterdigitTimer(Timer_ID tm, void *arg)
+{
+   DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
+
+   dxs_dial_Action(pChannel, ACTION_TIMEOUT_INTERDIGIT, /*dummy*/0);
+   return;
+}
+
+/**
+   Flash holdoff timer callback function.
+
+   \param  nArg         Argument of timer. This argument is a pointer to the
+                        DXS_CHANNEL_t structure.
+*/
+void dxs_dial_OnFlashHoldoffTimer(Timer_ID tm, void *arg)
+{
+   DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
+
+   dxs_dial_Action(pChannel, ACTION_TIMEOUT_FLASHHOLDOFF, /*dummy*/0);
+   return;
+}
+
+
+/**
+   Flash holdoff timer callback function.
+
+   \param  nArg         Argument of timer. This argument is a pointer to the
+                        DXS_CHANNEL_t structure.
+*/
+void dxs_dial_OnHookWindowTimer(Timer_ID tm, void *arg)
+{
+   DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
+   DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
+
+   pDXS_DialData->bHookWindow = 0;
+   return;
+}
+
+/**
+   Initialize the analog line state machines on the given channel.
+   Initialize the data structures and resources needed for the
+   hook state machine.
+
+   \param   pChannel    Pointer to DXS_CHANNEL_t structure.
+
+   \return
+     DXS_statusOk - if successful
+     DXS_statusTimerCreateError - timer creation failed
+
+   \remarks This function is not protected.
+*/
+int32_t DXS_Dial_Initialise_Unprot (DXS_CHANNEL_t *pChannel)
+{
+   DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
+   DXS_status_t ret = DXS_statusError;
+
+   if (pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED)
+      return DXS_statusOk;
+
+   /* set default values for the validation times */
+   pDXS_DialData->nTimeOnhook          = DXS_MIN_ON_HOOK;
+   pDXS_DialData->nTimeOffhook         = DXS_MIN_OFF_HOOK;
+   pDXS_DialData->nTimeInterdigit      = DXS_MIN_INTERDIGIT;
+   pDXS_DialData->nTimeFlashHoldoff    = DXS_MIN_FLASH_MAKE;
+   pDXS_DialData->nTimeDigitMakeMin    = DXS_MIN_DIGIT_HIGH;
+   pDXS_DialData->nTimeDigitMakeMax    = DXS_MAX_DIGIT_HIGH;
+   pDXS_DialData->nTimeDigitBreakMin   = DXS_MIN_DIGIT_LOW;
+   pDXS_DialData->nTimeDigitBreakMax   = DXS_MAX_DIGIT_LOW;
+   pDXS_DialData->nTimeFlashBreakMin   = DXS_MIN_FLASH;
+   pDXS_DialData->nTimeFlashBreakMax   = DXS_MAX_FLASH;
+
+   /* start all three HSMs in on-hook state */
+   pDXS_DialData->nHookState  = HOOK_STATE_ONHOOK;
+   pDXS_DialData->nDigitState = DIGIT_STATE_ONHOOK;
+   pDXS_DialData->nFlashState = FLASH_STATE_ONHOOK;
+   pDXS_DialData->nPulseDigit = 0;
+   pDXS_DialData->bPulseStartSent = 0;
+
+   /* create hook-state-machine validation timer */
+   pDXS_DialData->HookTimerID =
+            DXS_TimerCreate(dxs_dial_OnHookTimer, (void *)pChannel);
+   if (NULL == pDXS_DialData->HookTimerID)
+   {
+      perror("ERROR: Creation of hook-state-machine validation timer failed");
+      DXS_RETURN(ret);
+   }
+   /* create inter-digit timer */
+   pDXS_DialData->InterdigitTimerID =
+            DXS_TimerCreate(dxs_dial_OnInterdigitTimer, (void *)pChannel);
+   if (NULL == pDXS_DialData->InterdigitTimerID)
+   {
+      perror("ERROR: Creation of inter-digit timer failed");
+      DXS_Dial_Cleanup(pChannel);
+      DXS_RETURN(ret);
+   }
+   /* create flash holdoff timer */
+   pDXS_DialData->FlashHoldoffTimerID =
+            DXS_TimerCreate(dxs_dial_OnFlashHoldoffTimer, (void *)pChannel);
+   if (NULL == pDXS_DialData->FlashHoldoffTimerID)
+   {
+      perror("ERROR: Creation of flash holdoff timer failed");
+      DXS_Dial_Cleanup(pChannel);
+      DXS_RETURN(ret);
+   }
+   /* create hook event timestamp wraparound timer */
+   pDXS_DialData->HookWindowTimerId =
+            DXS_TimerCreate(dxs_dial_OnHookWindowTimer, (void *)pChannel);
+   if (NULL == pDXS_DialData->HookWindowTimerId)
+   {
+      perror("ERROR: Creation of hook event timestamp wraparound timer failed");
+      DXS_Dial_Cleanup(pChannel);
+      DXS_RETURN(ret);
+   }
+
+   pDXS_DialData->bHookWindow = 0;
+   pDXS_DialData->nLastHookEvtTimestamp = 0;
+   pDXS_DialData->nTimeOffhookBackup = 0;
+
+   pChannel->flags |= DXS_CH_DIAL_DATA_INITIALIZED;
+   return DXS_statusOk;
+}
+
+
+/**
+   Cleanup the analog line state machines on the given channel.
+
+   Free the resources needed for the hook state machine and
+   the ground-key state machine.
+
+   \param   pChannel    Pointer to DXS_CHANNEL_t structure.
+*/
+void DXS_Dial_Cleanup(DXS_CHANNEL_t *pChannel)
+{
+   DXS_DIAL_DATA_t  *pDXS_DialData  = &pChannel->DXS_DialData;
+
+   if (!(pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED))
+      return;
+   /* unconditionally delete all timers */
+   DXS_TimerDestroy(pDXS_DialData->HookTimerID);
+   DXS_TimerDestroy(pDXS_DialData->InterdigitTimerID);
+   DXS_TimerDestroy(pDXS_DialData->FlashHoldoffTimerID);
+   DXS_TimerDestroy(pDXS_DialData->HookWindowTimerId);
+   pChannel->flags &= ~DXS_CH_DIAL_DATA_INITIALIZED;
+}
+
+
+/**
+   Process hook events in the state machines.
+
+   \param  pChannel     Pointer to DXS_CHANNEL_t structure.
+   \param  bHookState   - 1:  make  (off-hook),
+                        - 0: break (on-hook)
+   \param  nTime        Duration since the last hook event in ms.
+*/
+void DXS_Dial_HookEvent (DXS_CHANNEL_t* pChannel,
+                        uint32_t bHookState,
+                        uint16_t nTime)
+{
+   /* make sure dial is initialised on this channel */
+   if (!(pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED))
+   {
+      /* silently ignore event - this case can happen during startup or
+         shutdown when an interrupt occurs but DXS_DialData is not initialized.
+         */
+      return;
+   }
+
+   nTime = DXS_Dial_ElapsedTimeSinceLastHook(pChannel, nTime);
+
+   /* Note: The hook events actually report a change between the make and break
+      status of the line. The action reports the new line status. This implies
+      that before this event the opposite line status was present and that the
+      time that is reported is the duration that this status was present.
+      Here make and break is used to make it clear that this is not the hook
+      status of the phone but the line state which will also change from
+      pulse dialing and flash hook. */
+   dxs_dial_Action(pChannel, bHookState ? ACTION_MAKE : ACTION_BREAK, nTime);
+
+   return;
+}
+
+
+/**
+   Set the given hook state unconditionally.
+
+   This is used after certain CID sequences which use hook for signaling
+   purposes. There the hook is not given to this state machine and so the
+   state needs to be corrected in case of an abort.
+
+   \param  pChannel     Pointer to DXS_CHANNEL_t structure.
+   \param  bHookState   - 1:  make  (off-hook),
+                        - 0: break (on-hook)
+*/
+void DXS_Dial_HookSet (DXS_CHANNEL_t *pChannel, int32_t bHookState)
+{
+   DXS_DIAL_DATA_t  *pDXS_DialData  = &pChannel->DXS_DialData;
+
+   /* make sure dial is initialised on this channel */
+   if (!(pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED))
+   {
+      /* silently ignore */
+      return;
+   }
+
+   /* Handle the hook-state detection finite state machine. */
+   switch(pDXS_DialData->nHookState)
+   {
+   case HOOK_STATE_OFFHOOK:
+      if (bHookState == 0)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
+         pDXS_DialData->nDigitState = DIGIT_STATE_ONHOOK;
+         pDXS_DialData->nFlashState = FLASH_STATE_ONHOOK;
+         /* Do not send a TAPI event here. */
+      }
+      break;
+
+   case HOOK_STATE_ONHOOK:
+      if (bHookState == 1)
+      {
+         pDXS_DialData->nHookState = HOOK_STATE_OFFHOOK;
+         pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
+         pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
+         pDXS_DialData->nPulseDigit = 0;
+         pDXS_DialData->bPulseStartSent = 0;
+         /* Do not send a TAPI event here. */
+      }
+      break;
+
+   default:
+      /* Do nothing in the validation states. */
+      break;
+   }
+
+   return;
+}
+
+
+/**
+   Overrides the user configured off-hook time.
+
+   This is used by the phone detection to set an off-hook time to suppress
+   transient hook events that can occur in the off-hook detection state.
+
+   \param  pChannel     Pointer to DXS_CHANNEL_t structure.
+   \param  nTime        DXS_DIAL_TIME_NORMAL for normal user configured
+                        value. All other values are used as off-hook time
+                        in milliseconds.
+   \remarks
+   The value 0 is invalid for the off-hook time. Here it is used as a marker.
+*/
+void DXS_Dial_OffhookTime_Override(DXS_CHANNEL_t *pChannel,
+                        uint32_t const nTime)
+{
+   DXS_DIAL_DATA_t  *pDXS_DialData  = &pChannel->DXS_DialData;
+
+   /* make sure that dial is initialised on this channel */
+   if (pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED)
+   {
+      if (nTime == DXS_DIAL_TIME_NORMAL)
+      {
+         if (pDXS_DialData->nTimeOffhookBackup != 0)
+         {
+            /* Restore the backed up time value. */
+            pDXS_DialData->nTimeOffhook = pDXS_DialData->nTimeOffhookBackup;
+            pDXS_DialData->nTimeOffhookBackup = 0;
+         }
+      }
+      else
+      {
+         /* Switch to override - backup time value and set from parameter. */
+         if (pDXS_DialData->nTimeOffhookBackup == 0)
+         {
+            pDXS_DialData->nTimeOffhookBackup = pDXS_DialData->nTimeOffhook;
+         }
+         pDXS_DialData->nTimeOffhook = nTime;
+      }
+   }
+}
+
+/**
+   Calculate the elapsed time since the last hook event.
+
+   This function is to be called with each hook event. It calculates the
+   elapsed time since the last hook event.
+
+   The DxS provides a timestamp with each FW event. However, this timestamp
+   has a wraparound after ~66 seconds. So an addtional timer is used to prevent
+   calculation after a wraparound. This function wraps the calculation and
+   also restarts the timer.
+
+   \param  pCh          Pointer to DxS channel structure.
+   \param  nCurrentTimestamp  Current timestamp value from the FW event.
+
+   \return
+   Elapsed time since the last hook event in 1 ms steps.
+   If the last event happened too long ago or dial is not initialised 0xFFFF is
+   returned.
+*/
+uint16_t DXS_Dial_ElapsedTimeSinceLastHook(DXS_CHANNEL_t *pChannel,
+   uint16_t nCurrentTimestamp)
+{
+   DXS_DIAL_DATA_t  *pDXS_DialData  = &pChannel->DXS_DialData;
+   uint16_t   elapsedTime;
+
+   if (pDXS_DialData->bHookWindow)
+   {
+      /* Calculate elapsed time since the saved timestamp. In case the 16-bit
+         counter had a wraparound since the saved timestamp the calculation
+         will still be correct because the calculation is done with 16-bit
+         unsigned data type. This will always result in the positive distance
+         between the two timestamps. */
+      elapsedTime = nCurrentTimestamp - pDXS_DialData->nLastHookEvtTimestamp;
+   }
+   else
+   {
+      elapsedTime = 0xFFFF;
+   }
+
+   /* Start timer, length of timer nominal 65000 ms. A random component is
+      added to distribute the expiration of the timers in systems with multiple
+      devices using polling where a lot of timers might be started in parallel.
+      This time needs to be below the wraparound of the HW timestamp. */
+   pDXS_DialData->bHookWindow = 1;
+   DXS_TimerSet(pDXS_DialData->HookWindowTimerId,
+      65000 + (nCurrentTimestamp & 0x00FF), 0, 1);
+   /* store the timestamp from this event */
+   pDXS_DialData->nLastHookEvtTimestamp = nCurrentTimestamp;
+
+   return elapsedTime;
+}
+
+
+/**
+   Sets the validation times for hook, pulse digit and flashhook.
+
+   \param   pChannel     - pointer to DXS channel structure
+   \param   pTime        - type of validation setting, min and max time in
+                           milliseconds.
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_Dial_HookValTimeSet(DXS_CHANNEL_t *pChannel,
+   DXS_HookValTime_t *pTime)
+{
+   DXS_DIAL_DATA_t  *pDXS_DialData  = &pChannel->DXS_DialData;
+
+   /* zero timer value is not allowed -- except for the flash holdoff time */
+   if ((pTime->nMinTime == 0) &&
+       (pTime->nType != DXS_HOOK_VT_FLASH_HOLDOFF_TIME))
+   {
+      DXS_RETURN(DXS_statusDialZeroParam);
+   }
+
+   /* For the times hook-off, hook-on, interdigit and flash holdoff just
+      the minimum time is relevant. So do not check the maximum time. */
+   if ((pTime->nType != DXS_HOOK_VT_HOOKOFF_TIME) &&
+       (pTime->nType != DXS_HOOK_VT_HOOKON_TIME) &&
+       (pTime->nType != DXS_HOOK_VT_INTERDIGIT_TIME) &&
+       (pTime->nType != DXS_HOOK_VT_FLASH_HOLDOFF_TIME))
+   {
+      /* check whether min timer value > max timer value */
+      if (pTime->nMinTime > pTime->nMaxTime)
+      {
+         DXS_RETURN(DXS_statusDialMaxMinParam);
+      }
+      /* Note: the max timer value cannot be 0 because min > 0 and
+         min <= max entails that max > 0. */
+   }
+
+   /* set the validation times */
+   switch (pTime->nType)
+   {
+      case DXS_HOOK_VT_HOOKOFF_TIME:
+         if (pDXS_DialData->nTimeOffhookBackup == 0)
+            pDXS_DialData->nTimeOffhook      = pTime->nMinTime;
+         else
+            pDXS_DialData->nTimeOffhookBackup= pTime->nMinTime;
+         break;
+
+      case DXS_HOOK_VT_HOOKON_TIME:
+         pDXS_DialData->nTimeOnhook          = pTime->nMinTime;
+         break;
+
+      case DXS_HOOK_VT_HOOKFLASH_TIME:
+         pDXS_DialData->nTimeFlashBreakMin   = pTime->nMinTime;
+         pDXS_DialData->nTimeFlashBreakMax   = pTime->nMaxTime;
+         break;
+
+      case DXS_HOOK_VT_DIGITLOW_TIME:
+         pDXS_DialData->nTimeDigitBreakMin   = pTime->nMinTime;
+         pDXS_DialData->nTimeDigitBreakMax   = pTime->nMaxTime;
+         break;
+
+      case DXS_HOOK_VT_DIGITHIGH_TIME:
+         pDXS_DialData->nTimeDigitMakeMin    = pTime->nMinTime;
+         pDXS_DialData->nTimeDigitMakeMax    = pTime->nMaxTime;
+         break;
+
+      case DXS_HOOK_VT_INTERDIGIT_TIME:
+         pDXS_DialData->nTimeInterdigit      = pTime->nMinTime;
+         break;
+
+      case DXS_HOOK_VT_FLASH_HOLDOFF_TIME:
+         pDXS_DialData->nTimeFlashHoldoff    = pTime->nMinTime;
+         break;
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Sets the nHookState to HOOK_STATE_ONHOOK.
+
+   \param   pChannel     - pointer to DXS channel structure
+
+*/
+extern void DXS_Dial_HookStateSetOnhook(DXS_CHANNEL_t *pChannel)
+{
+   DXS_DIAL_DATA_t *pDXS_DialData;
+
+   if (pChannel != NULL)
+   {
+      pDXS_DialData = &pChannel->DXS_DialData;
+      pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
+   }
+}
+#endif /* DXS_FEAT_HSM */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_hsm.h b/marvell/services/dxslic/api_lib/src/dxs_hsm.h
new file mode 100644
index 0000000..6564d32
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_hsm.h
@@ -0,0 +1,147 @@
+#ifndef __DXS_HSM_H__
+#define __DXS_HSM_H__
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_hsm.h
+
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+#include "dxs.h"
+#include "dxs_timer.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* Used as parameter to DXS_Dial_OffhookTime_Override(). */
+#define DXS_DIAL_TIME_NORMAL   0
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+struct DXS_DIAL_DATA;
+typedef struct DXS_DIAL_DATA DXS_DIAL_DATA_t;
+
+/** states of the hook-state detection finite state machine */
+enum HOOK_STATE
+{
+   /** phone is on-hook */
+   HOOK_STATE_ONHOOK,
+   /** make detected - wait for off-hook timeout */
+   HOOK_STATE_VALIDATE_OFFHOOK,
+   /** phone is off-hook */
+   HOOK_STATE_OFFHOOK,
+   /** break detected - wait for on-hook timeout */
+   HOOK_STATE_VALIDATE_ONHOOK
+};
+
+/** states of the pulse dialing detection finite state machine */
+enum DIGIT_STATE
+{
+   /** phone is on-hook */
+   DIGIT_STATE_ONHOOK,
+   /** phone is off-hook */
+   DIGIT_STATE_OFFHOOK,
+   /** wait for make to validate the digit break time */
+   DIGIT_STATE_VALIDATE_DIGIT_BREAK,
+   /** wait for break to validate the digit make time or inter-digit timeout */
+   DIGIT_STATE_VALIDATE_DIGIT_MAKE
+};
+
+/** states of the flash hook detection finite state machine */
+enum FLASH_STATE
+{
+   /** phone is on-hook */
+   FLASH_STATE_ONHOOK,
+   /** phone is off-hook */
+   FLASH_STATE_OFFHOOK,
+   /** wait for make to validate the flash break time */
+   FLASH_STATE_VALIDATE_FLASH_BREAK,
+   /** wait for flash holdoff timeout before reporting the flash event */
+   FLASH_STATE_VALIDATE_FLASH_HOLDOFF
+};
+
+/** actions to all state machines */
+enum ACTION
+{
+   /** make reported from analog line */
+   ACTION_MAKE,
+   /** break reported from analog line */
+   ACTION_BREAK,
+   /** timer expired */
+   ACTION_TIMEOUT_HOOK,
+   /** timer expired */
+   ACTION_TIMEOUT_INTERDIGIT,
+   /** timer expired */
+   ACTION_TIMEOUT_FLASHHOLDOFF
+};
+
+/** Data of the hook state machine. */
+struct DXS_DIAL_DATA
+{
+   /** state of the hook-state detection finite state machine */
+   enum HOOK_STATE         nHookState;
+   /** state of the pulse dialing detection finite state machine */
+   enum DIGIT_STATE        nDigitState;
+   /** state of the flash hook detection finite state machine */
+   enum FLASH_STATE        nFlashState;
+   /** timer for hook state machine timeouts */
+   Timer_ID            HookTimerID;
+   /** timer for the inter-digit timeout */
+   Timer_ID            InterdigitTimerID;
+   /** timer for the flash holdoff timeout */
+   Timer_ID            FlashHoldoffTimerID;
+   /** counter for the pulses of the pulse digit */
+   uint8_t                 nPulseDigit;
+   /* indicates that pulse start event was sent, reset by on-hook or
+    * flash-hook */
+   uint8_t                 bPulseStartSent;
+   /* validation times for all state machines */
+   uint32_t                nTimeOnhook,
+                           nTimeOffhook,
+                           nTimeOffhookBackup,
+                           nTimeInterdigit,
+                           nTimeFlashHoldoff,
+                           nTimeDigitMakeMin,
+                           nTimeDigitMakeMax,
+                           nTimeDigitBreakMin,
+                           nTimeDigitBreakMax,
+                           nTimeFlashBreakMin,
+                           nTimeFlashBreakMax;
+   /* elapsed time since last hook event */
+   uint16_t                nLastHookEvtTimestamp;
+   /* timer for hook event timestamp wraparound */
+   Timer_ID                HookWindowTimerId;
+   volatile uint8_t        bHookWindow;
+};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t DXS_Dial_Initialise_Unprot(DXS_CHANNEL_t *pChannel);
+extern void DXS_Dial_Cleanup(DXS_CHANNEL_t *pChannel);
+extern void DXS_Dial_HookEvent(DXS_CHANNEL_t* pChannel, uint32_t bHookState,
+   uint16_t nTime);
+extern void DXS_Dial_OffhookTime_Override(DXS_CHANNEL_t *pChannel,
+   uint32_t const nTime);
+extern uint16_t DXS_Dial_ElapsedTimeSinceLastHook(DXS_CHANNEL_t *pChannel,
+   uint16_t nCurrentTimestamp);
+extern int32_t DXS_Dial_HookValTimeSet(DXS_CHANNEL_t *pChannel,
+   DXS_HookValTime_t *pTime);
+extern void DXS_Dial_HookStateSetOnhook(DXS_CHANNEL_t *pChannel);
+#endif /* __DXS_HSM_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_init.c b/marvell/services/dxslic/api_lib/src/dxs_init.c
new file mode 100644
index 0000000..e5ab2eb
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_init.c
@@ -0,0 +1,1241 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_init.c
+   Implementation of initialization functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdlib.h>
+
+#include "dxs_config.h"
+#include "dxs_version.h"
+#include "dxs_init.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_pcm.h"
+#include "dxs_sdd.h"
+#include "dxs_sig.h"
+#include "dxs_gpio.h"
+#include "dxs_access.h"
+#include "dxs_cid.h"
+#include "dxs_pollint.h"
+#include "dxs_outbox.h"
+#include "dxs_event.h"
+#include "dxs_spi.h"
+#include "dxs_dcdc_hw.h"
+#include "dxs_ring.h"
+#ifdef EVENT_LOGGER_DEBUG
+#include <sys/ioctl.h>
+#endif
+
+const char DXS_WHATVERSION[] = DXS_WHAT_STR;
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** Data structure for DXS_FW_SYS_VERS_ECMD firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Device Number */
+   uint32_t DEVNR : 11;
+   /** Calender Week */
+   uint32_t CW : 6;
+   /** Production Year */
+   uint32_t YEAR : 6;
+   /** Channel */
+   uint32_t CH : 1;
+   /** Device ID Representing PEB Number */
+   uint32_t DEV : 8;
+   /** Major */
+   uint32_t MAJ : 8;
+   /** Minor */
+   uint32_t MIN : 8;
+   /** Hotfix */
+   uint32_t HF : 8 ;
+   /** Reserved */
+   uint32_t Res02 : 8;
+   /** Time Stamp */
+   uint32_t TIME;
+#else
+   CMD_HEAD_LE;
+   /** Device ID Representing PEB Number */
+   uint32_t DEV : 8;
+   /** Channel */
+   uint32_t CH : 1;
+   /** Production Year */
+   uint32_t YEAR : 6;
+   /** Calender Week */
+   uint32_t CW : 6;
+   /** Device Number */
+   uint32_t DEVNR : 11;
+   /** Reserved */
+   uint32_t Res02 : 8;
+   /** Hotfix */
+   uint32_t HF : 8 ;
+   /** Minor */
+   uint32_t MIN : 8;
+   /** Major */
+   uint32_t MAJ : 8;
+   /** Time Stamp */
+   uint32_t TIME;
+#endif
+} __attribute__ ((packed)) DXS_FW_SYS_VERS_t;
+#define DXS_FW_SYS_VERS_ECMD    6
+#define DXS_FW_SYS_VERS_LENGTH  12
+
+/** Data structure for system capabilities firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /* Reserved */
+   uint32_t Res02 : 25;
+   /* Howler Support Available */
+   uint32_t HOWLER : 1;
+   /* Caller ID Available */
+   uint32_t CID : 1;
+   /* Universal Tone Detector Available */
+   uint32_t UTD : 1;
+   /* Teletax Support Available */
+   uint32_t TTX : 1;
+   /* Reserved */
+   uint32_t Res03 : 1;
+   /* AC Level Meter Support Available */
+   uint32_t ACLM : 1;
+   /* GR909 available */
+   uint32_t GR909 : 1;
+#else
+   CMD_HEAD_LE;
+   /* GR909 available */
+   uint32_t GR909 : 1;
+   /* AC Level Meter Support Available */
+   uint32_t ACLM : 1;
+   /* Reserved */
+   uint32_t Res03 : 1;
+   /* Teletax Support Available */
+   uint32_t TTX : 1;
+   /* Universal Tone Detector Available */
+   uint32_t UTD : 1;
+   /* Caller ID Available */
+   uint32_t CID : 1;
+   /* Howler Support Available */
+   uint32_t HOWLER : 1;
+   /* Reserved */
+   uint32_t Res02 : 25;
+#endif
+} __attribute__ ((packed)) DXS_FW_SYS_CAPS_t;
+#define DXS_FW_SYS_CAPS_ECMD    7
+#define DXS_FW_SYS_CAPS_LENGTH  4
+
+/** Data structure for DXS_FW_SYS_Control_ECMD firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /* Reserved */
+   uint32_t Res02 : 25;
+   /* Sync-Fail/ Clock-Fail Handling Enable */
+   uint32_t SYCLKE : 1;
+   /* PLL Limiter Enable */
+   uint32_t PLIM : 1;
+   /*  Charge Pump Voltage Level */
+   uint32_t CP_VOLT : 3;
+   /* Charge Pump Enable */
+   uint32_t CP_EN : 1;
+   /* Sleep Enable */
+   uint32_t SE : 1;
+#else
+   CMD_HEAD_LE;
+   /* Sleep Enable */
+   uint32_t SE : 1;
+   /* Charge Pump Enable */
+   uint32_t CP_EN : 1;
+   /*  Charge Pump Voltage Level */
+   uint32_t CP_VOLT : 3;
+   /* PLL Limiter Enable */
+   uint32_t PLIM : 1;
+   /* Sync-Fail/ Clock-Fail Handling Enable */
+   uint32_t SYCLKE : 1;
+   /* Reserved */
+   uint32_t Res02 : 25;
+#endif
+} __attribute__ ((packed)) DXS_FW_SYS_Control_t;
+#define DXS_FW_SYS_Control_ECMD     8
+#define DXS_FW_SYS_Control_LENGTH   4
+#define DXS_FW_SYS_Control_CP_VOLT_5_0V   3
+
+/** Device capabilities */
+typedef struct
+{
+   /* status flag */
+   uint32_t         flag;
+#define DXS_DEV_CAPS_INITIALIZED  1
+#define DXS_DEV_CAPS_UPDATED      2
+#define DXS_DEV_SYS_CTRL_UPDATED  4
+   /* device version */
+   DXS_Dev_t     dev;
+   /* device package */
+   DXS_Package_t pack;
+   /* firmware version */
+   DXS_FW_SYS_VERS_t fw_vers;
+   /* firmware capabilities */
+   DXS_FW_SYS_CAPS_t fw_caps;
+   /* firmware system control */
+   DXS_FW_SYS_Control_t fw_sys_ctrl;
+} DXS_Dev_Caps_t;
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+/* static data */
+static DXS_DEVICE_t dxs_devices[DXS_MAX_DEVICES] = {0};
+static DXS_Dev_Caps_t dxs_caps[DXS_MAX_DEVICES] = {0};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+static int32_t dxs_controller_reset(DXS_DEVICE_t *pDev);
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+#ifdef EVENT_LOGGER_DEBUG
+static void dxs_el_register(DXS_DEVICE_t *pDev)
+{
+   EL_IoctlRegister_t el_reg;
+   int ret;
+
+   pDev->el_fd = open(EL_DEVICE_NAME, 2, 0644);
+   if (pDev->el_fd < 0)
+   {
+      return;
+   }
+   else
+   {
+      snprintf(el_reg.sName, sizeof(el_reg.sName), "dxs_lib");
+
+      el_reg.nType = DXS_LIB_DEV_TYPE;
+      el_reg.nDevNum = pDev->nDevNum;
+
+      ret = ioctl(pDev->el_fd, EL_REGISTER, (int32_t)&el_reg);
+      if (ret == IFX_SUCCESS)
+      {
+         IFX_char_t *pCmd ="echo \"*\"  > /proc/driver/el/logs/all";
+         FILE *el_pipe_fd;
+
+         el_pipe_fd = popen(pCmd, "r");
+         if (!el_pipe_fd)
+         {
+            return;
+         }
+         pclose(el_pipe_fd);
+      }
+   }
+}
+
+static void dxs_el_unregister(DXS_DEVICE_t *pDev)
+{
+   EL_IoctlRegister_t el_reg;
+
+   snprintf(el_reg.sName, sizeof(el_reg.sName), "dxs_lib");
+   el_reg.nType = DXS_LIB_DEV_TYPE;
+   el_reg.nDevNum = pDev->nDevNum;
+
+   if (pDev->el_fd > 0)
+   {
+      ioctl(pDev->el_fd, EL_UNREGISTER, (int32_t)&el_reg);
+   }
+}
+#endif
+
+/**
+   Function dxs_caps_init
+
+   \param   dev     - device number
+
+*/
+static void *dxs_caps_init(uint8_t dev)
+{
+   DXS_Dev_Caps_t *p;
+
+   if (dev >= DXS_MAX_DEVICES)
+      return (void *)NULL;
+
+   p = &dxs_caps[dev];
+
+   p->flag = 0;
+
+   p->fw_vers.CMD = CMD_EOP;
+   p->fw_vers.MOD = MOD_SYS;
+   p->fw_vers.ECMD = DXS_FW_SYS_VERS_ECMD;
+   p->fw_vers.LENGTH = DXS_FW_SYS_VERS_LENGTH;
+
+   p->fw_caps.CMD = CMD_EOP;
+   p->fw_caps.MOD = MOD_SYS;
+   p->fw_caps.ECMD = DXS_FW_SYS_CAPS_ECMD;
+   p->fw_caps.LENGTH =  DXS_FW_SYS_CAPS_LENGTH;
+
+   p->fw_sys_ctrl.CMD = CMD_EOP;
+   p->fw_sys_ctrl.MOD = MOD_SYS;
+   p->fw_sys_ctrl.ECMD = DXS_FW_SYS_Control_ECMD;
+   p->fw_sys_ctrl.LENGTH = DXS_FW_SYS_Control_LENGTH;
+
+   p->flag |= DXS_DEV_CAPS_INITIALIZED;
+
+   return (void *)p;
+}
+
+/**
+   Function dxs_caps_vers_update
+
+   \param   pDev     - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_caps_vers_update(DXS_DEVICE_t *pDev)
+{
+   DXS_Dev_Caps_t *p;
+   int32_t err;
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!(p->flag & DXS_DEV_CAPS_UPDATED))
+   {
+      err = CmdRead(pDev, (uint32_t *)&p->fw_caps, (uint32_t *)&p->fw_caps);
+      if (err)
+      {
+         DXS_RETURN(DXS_statusCapVersUpdateError);
+      }
+      err = CmdRead(pDev, (uint32_t *)&p->fw_vers, (uint32_t *)&p->fw_vers);
+      if (err)
+      {
+         DXS_RETURN(DXS_statusCapVersUpdateError);
+      }
+      /* update device ROM version */
+      pDev->rom_mask_ver = p->fw_vers.MAJ & 0x7F;
+
+      if (p->fw_vers.DEV == 0x9)
+      {
+         /* XS_VQFN-68_ES DXS Engineering Sample (A11 design)
+            in PG-VQFN-68 package */
+         p->pack = DXS_PACKAGE_VQFN68;
+         if (p->fw_vers.CH == 0)
+         {
+            p->dev = DXS_DEV_PEF32002_A11;
+            pDev->nChannels = 2;
+         }
+         else
+         {
+            p->dev = DXS_DEV_PEF32001_A11;
+            pDev->nChannels = 1;
+         }
+      }
+      else if (p->fw_vers.DEV == 0xA)
+      {
+         /* XS_VQFN-68_V11 DXS V1.1 (A12 design)
+            in PG-VQFN-68 package */
+         p->pack = DXS_PACKAGE_VQFN68;
+         if (p->fw_vers.CH == 0)
+         {
+            p->dev = DXS_DEV_PEF32002_A12;
+            pDev->nChannels = 2;
+         }
+         else
+         {
+            p->dev = DXS_DEV_PEF32001_A12;
+            pDev->nChannels = 1;
+         }
+      }
+      else if (p->fw_vers.DEV == 0x2A)
+      {
+         /* XC_VQFN-68_V11 DXC2 V1.1 (A12 design)
+            in PG-VQFN-68 package, only 2 channel version */
+         p->pack = DXS_PACKAGE_VQFN68;
+         p->dev = DXC_DEV_PEF31002_A12;
+         pDev->nChannels = 2;
+      }
+      else if (p->fw_vers.DEV == 0x49)
+      {
+         /* XS_VQFN-48_ES DXS1 Engineering Sample (A11 design)
+            in PG-VQFN-48 package */
+         p->pack = DXS_PACKAGE_VQFN48;
+         p->dev = DXS_DEV_PEF32001_A11;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0x4A)
+      {
+         /* XS_VQFN-48_V11 DXS1 V1.1 (A12 design)
+            in PG-VQFN-48 package */
+         p->pack = DXS_PACKAGE_VQFN48;
+         p->dev = DXS_DEV_PEF32001_A12;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0x6A)
+      {
+         /* XC_VQFN-48_V11 DXC1 V1.1 (A12 design)
+            in PG-VQFN-48 package */
+         p->pack = DXS_PACKAGE_VQFN48;
+         p->dev = DXC_DEV_PEF31001_A12;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0x0B)
+      {
+         /* XS_VQFN-68_V12 DXS2 V1.2 (A13 design)
+            in PG-VQFN-68 package */
+         p->pack = DXS_PACKAGE_VQFN68;
+         p->dev = DXS_DEV_PEF32002_V12_A13;
+         pDev->nChannels = 2;
+      }
+      else if (p->fw_vers.DEV == 0x2B)
+      {
+         /* XC_VQFN-68_V12 DXC2 V1.2 (A13 design)
+            in PG-VQFN-68 package */
+         p->pack = DXS_PACKAGE_VQFN68;
+         p->dev = DXC_DEV_PEF31002_V12_A13;
+         pDev->nChannels = 2;
+      }
+      else if (p->fw_vers.DEV == 0x8C)
+      {
+         /* XS_VQFN-44_V12 DXS1 V1.2
+            (A11 new codec design) in PG-VQFN-44 package */
+         p->pack = DXS_PACKAGE_VQFN44;
+         p->dev = DXS_DEV_PEF32001_V12_A11;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0xAC)
+      {
+         /* XC_VQFN-44_V12 DXC1 V1.2
+            (A11 new codec design) in PG-VQFN-44 package */
+         p->pack = DXS_PACKAGE_VQFN44;
+         p->dev = DXC_DEV_PEF31001_V12_A11;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0x4C)
+      {
+         /* XS_VQFN-48_V12 DXS1 V1.2
+            (A11 new codec design) in PG-VQFN-48 package */
+         p->pack = DXS_PACKAGE_VQFN48;
+         p->dev = DXS_DEV_PEF32001_V12_A11;
+         pDev->nChannels = 1;
+
+      }
+      else if (p->fw_vers.DEV == 0x6C)
+      {
+         /* XC_VQFN-48_V12 DXC1 V1.2
+            (A11 new codec design) in PG-VQFN-48 package */
+         p->pack = DXS_PACKAGE_VQFN48;
+         p->dev = DXC_DEV_PEF31001_V12_A11;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0x0C)
+      {
+         /* XS_VQFN-68_V12 DXS1 V1.2
+            (A11 new codec design) in PG-VQFN-68 package */
+         p->pack = DXS_PACKAGE_VQFN68;
+         p->dev = DXS_DEV_PEF32001_V12_A11;
+         pDev->nChannels = 1;
+      }
+      else if (p->fw_vers.DEV == 0x2C)
+      {
+         /* XC_VQFN-68_V12 DXC1 V1.2
+            (A11 new codec design) in PG-VQFN-68 package */
+         p->pack = DXS_PACKAGE_VQFN68;
+         p->dev = DXC_DEV_PEF31001_V12_A11;
+         pDev->nChannels = 1;
+      }
+      else
+      {
+         p->pack = DXS_PACKAGE_UNKNOWN;
+         p->dev = DXS_DEV_UNKNOWN;
+         /* default for unfused device */
+         pDev->nChannels = 1;
+      }
+
+      p->flag |= DXS_DEV_CAPS_UPDATED;
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_caps_vers_forget
+
+   \param   pDev     - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_caps_vers_forget(DXS_DEVICE_t *pDev)
+{
+   DXS_Dev_Caps_t *p;
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   p->flag &= ~DXS_DEV_CAPS_UPDATED;
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_get_dev
+
+   \param   dxs     - device number
+
+   \return
+   - pointer to DxS device structure
+*/
+DXS_DEVICE_t *dxs_get_dev (uint8_t dxs)
+{
+   if (dxs >= DXS_MAX_DEVICES)
+      return NULL;
+
+   return &dxs_devices[dxs];
+}
+
+
+/**
+   Calculate CRC-8-CCITT. POLYNOMIAL = 0x07
+
+   \param  pData          Pointer to data for CRC calculation
+   \param  nLength        Length of data buffer
+
+   \return
+   Calculated CRC value.
+*/
+uint8_t dxs_CRC_8_CCITT(uint8_t *pData, uint32_t nLength)
+{
+   uint8_t nCRC = 0;
+   int32_t i, j;
+
+   /* Perform modulo-2 division, a byte at a time. */
+   for (i = 0; i < nLength; i++)
+   {
+      /* Bring the next byte into the nCRC. */
+      nCRC ^= pData[i];
+
+      /* Perform modulo-2 division, a bit at a time. */
+      for (j = 8; j > 0; j--)
+      {
+         /* Try to divide the current data bit. */
+         if (nCRC & 0x80)
+            nCRC = (nCRC << 1) ^ 0x07;
+         else
+            nCRC = (nCRC << 1);
+      }
+   }
+   return nCRC;
+}
+
+
+/**
+   Function dxs_exit
+
+   \param   pDev     - pointer to DXS device structure
+
+*/
+int32_t dxs_exit(DXS_DEVICE_t *pDev)
+{
+   uint8_t ch;
+   int32_t ret = DXS_statusOk;
+
+   if (pDev->flags & DXS_DEV_INITIALIZED)
+   {
+      /* DCDC HW specific deinit */
+      DXS_DCDC_HW_Exit(pDev);
+
+      if (pDev->irqNumber == -1)
+      {
+         /* stop polling */
+         dxs_polling_timer_stop();
+      }
+      else
+      {
+         /* uninstall interrupt handler */
+         dxs_interrupt_exit();
+      }
+
+      /* stop obx handling thread */
+      dxs_outbox_handler_exit(pDev);
+      pDev->flags &= ~DXS_DEV_OBX_HND_INITIALIZED;
+
+      /* uninitialize event memory pool */
+      dxs_event_pool_exit(pDev);
+
+      /* uninitialize message queues */
+      fifo_destroy(pDev->event_queue);
+      fifo_destroy(pDev->cmd_obx_queue);
+
+      /* close SPI interface */
+      dxs_spi_linux_exit(pDev->spidev);
+      pDev->flags &= ~DXS_DEV_ACCESS_INITIALIZED;
+
+      /* delete mbx access mutex */
+      ret = pthread_mutex_unlock(&pDev->mtxMbxAcc);
+      if (ret != 0)
+        DXS_ERROR_PUSH(ret);
+      ret = pthread_mutex_destroy(&pDev->mtxMbxAcc);
+      if (ret != 0)
+        DXS_ERROR_PUSH(ret);
+
+      sem_destroy(&pDev->mtxPatchDwld);
+
+#ifdef DXS_FEAT_UTD
+      /* delete UTD mutex */
+      dxs_sig_utd_mtx_destroy();
+#endif /* DXS_FEAT_UTD */
+
+      /* close channel resources */
+      for (ch = 0; ch < pDev->nChannels; ch++)
+      {
+         DXS_CHANNEL_t *pCh = &pDev->pChannel[ch];
+
+#ifdef DXS_FEAT_HSM
+         DXS_Dial_Cleanup(pCh);
+#endif
+         /* cleanup only for SDD resource */
+         ret = DXS_SDD_ChExit(pCh);
+         if (ret != DXS_statusOk)
+            DXS_ERROR_PUSH(ret);
+      }
+
+#ifdef EVENT_LOGGER_DEBUG
+      dxs_el_unregister(pDev);
+#endif /* EVENT_LOGGER_DEBUG */
+
+      pDev->flags &= ~DXS_DEV_INITIALIZED;
+   }
+   DXS_RETURN(ret);
+}
+
+/**
+   Default initialization of DXS registers.
+
+   Enable the required interrupts in the register interface.
+
+   \param pDev pointer to the device structure
+
+   \return
+   - DXS_statusOk
+   - DXS_statusSpiAccError
+*/
+static int32_t dxs_default_reg_init(DXS_DEVICE_t *pDev)
+{
+   int32_t       ret = DXS_statusOk;
+   uint16_t      nRegHostIen1, nRegHostIen2;
+
+   /*
+      Enable the interrupts OBX_RDY and ERR.
+   */
+   nRegHostIen1 = DXS_REG_IEN1_RESET;
+   nRegHostIen1 |= DXS_REG_IEN1_OBX_RDY;
+   nRegHostIen1 |= DXS_REG_IEN1_ERR;
+   ret = DXS_RegWrite(pDev, DXS_REG_IEN1, nRegHostIen1);
+   if (ret != DXS_statusOk)
+      DXS_RETURN(ret);
+
+   /*
+      Enable the interrupts OBX_UFL and IBX_OFL.
+   */
+   nRegHostIen2 = DXS_REG_IEN2_RESET;
+   nRegHostIen2 |= DXS_REG_IEN2_OBX_UFL;
+   nRegHostIen2 |= DXS_REG_IEN2_IBX_OFL;
+   ret = DXS_RegWrite(pDev, DXS_REG_IEN2, nRegHostIen2);
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function dxs_init
+
+   \param   pDev       - pointer to DXS device structure
+   \param   chipSelect - CS number
+   \param   irqNumber  - IRQ line number
+   \param   dcdcType   - DCDC variant handled by DXS_DCDC_Var_t type
+   \param   dev        - device number
+
+   \return
+   - DXS_status_t
+*/
+/*
+ * should return either 0 or -1
+ */
+int32_t dxs_init(DXS_DEVICE_t *pDev, uint8_t chipSelect, int32_t irqNumber,
+                     uint8_t dcdcType, uint8_t access, uint8_t dev)
+{
+   int32_t ret = DXS_statusOk, i;
+#ifdef DXS_FEAT_HSM
+   DXS_status_t status;
+#endif
+   uint8_t ch;
+
+   if (access >= DXS_ACCESS_LAST)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   if (dev >= DXS_MAX_DEVICES)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   for (i=0; i<DXS_MAX_DEVICES; i++)
+   {
+      DXS_DEVICE_t *pdev = dxs_get_dev(i);
+
+      if (pdev->flags & DXS_DEV_INITIALIZED && pdev->dcdcType != dcdcType)
+      {
+         /* provided dcdcType does not match
+            with previously initialized devices */
+         DXS_RETURN(DXS_statusInvalidParam);
+      }
+   }
+
+   ret = dxs_exit(pDev);
+   if (ret != DXS_statusOk)
+   {
+      DXS_RETURN(DXS_statusDevInitFailed);
+   }
+
+   pDev->nDevNum = dev;
+   pDev->chipSelect = chipSelect;
+   pDev->irqNumber = irqNumber;
+   pDev->dcdcType = dcdcType;
+   pDev->access = access;
+
+   pthread_mutex_init(&pDev->mtxMbxAcc, NULL);
+   pDev->nMbxCachedCbiLen = 0;
+
+#ifdef EVENT_LOGGER_DEBUG
+   dxs_el_register(pDev);
+#endif
+
+   /* open SPI interface */
+   pDev->spidev = dxs_spi_linux_init(chipSelect, access);
+   if (pDev->spidev > 0)
+   {
+      pDev->flags |= DXS_DEV_ACCESS_INITIALIZED;
+   }
+   else
+   {
+      DXS_RETURN(DXS_statusSpiOpenError);
+   }
+
+   /* TODO: light chip access test + error code if failed */
+
+   /* Reset the DXS controller to bring the chip into the default state.
+      The data structures of the driver will be initialized to the same
+      known default state.*/
+   dxs_controller_reset(pDev);
+
+   /* initialize message queues */
+   pDev->event_queue = fifo_init (20);
+   if (NULL == pDev->event_queue)
+   {
+      DXS_RETURN(DXS_statusMsgQueueCreatError);
+   }
+   pDev->cmd_obx_queue = fifo_init (64);
+   if (NULL == pDev->cmd_obx_queue)
+   {
+      DXS_RETURN(DXS_statusMsgQueueCreatError);
+   }
+
+   /* initialize event memory pool */
+   if (DXS_statusOk != dxs_event_pool_init(pDev))
+   {
+      DXS_RETURN(DXS_statusMpoolInitError);
+   }
+
+   /* start obx handling thread */
+   ret = dxs_outbox_handler_init(pDev);
+   if (ret != DXS_statusOk)
+   {
+      DXS_RETURN(DXS_statusObxHandlerStartError);
+   }
+   pDev->flags |= DXS_DEV_OBX_HND_INITIALIZED;
+
+   /* initialize device resources */
+   pDev->caps = dxs_caps_init(dev);
+   pDev->pcm = dxs_pcm_dev_init(dev);
+
+   if (pDev->access == DXS_ACCESS_CSI)
+   {
+      /* default configuration of CSI Master */
+      uint16_t nCSIMasterCFG =
+         (DXS_REG_CSI_M_CFG_PAUSE_DEFAULT | DXS_REG_CSI_M_CFG_PDEMUX);
+      ret = DXS_RegWrite(pDev, DXS_REG_CSI_M_CFG, nCSIMasterCFG);
+      if (ret != DXS_statusOk)
+      {
+         DXS_RETURN(ret);
+      }
+   }
+
+#ifdef DXS_FEAT_GPIO
+   pDev->gpio = DXS_GPIO_DevInit(dev);
+#endif
+
+   /* start device polling */
+   if (pDev->irqNumber != 255 &&
+       (pDev->irqNumber == -1 || dxs_interrupt_init(pDev) != DXS_statusOk))
+   {
+      dxs_polling_timer_start();
+   }
+
+   /* In IRQ as well as polling mode set the interrupt masks. */
+   ret = dxs_default_reg_init(pDev);
+   if (ret != DXS_statusOk)
+   {
+      DXS_RETURN(ret);
+   }
+
+   /* read capabilities and version from device -
+      must be after polling start or interrupt enable */
+   dxs_caps_vers_update(pDev);
+
+#ifdef DXS_FEAT_UTD
+   /* initialize UTD mutex */
+   dxs_sig_utd_mtx_init();
+#endif /* DXS_FEAT_UTD */
+
+   /* initialize channel resources -
+      must be after capabilities read */
+   for (ch = 0; ch < pDev->nChannels; ch++)
+   {
+      DXS_CHANNEL_t *pCh = &pDev->pChannel[ch];
+
+      pCh->pParent = pDev;
+      pCh->nCh = ch;
+      pCh->pcm = dxs_pcm_ch_init(pDev->nDevNum, ch);
+      pCh->sdd = DXS_SDD_ChInit(pDev->nDevNum, ch);
+      pCh->sig = dxs_sig_ch_init(pDev->nDevNum, ch);
+#ifdef DXS_FEAT_HSM
+      status = DXS_Dial_Initialise_Unprot(pCh);
+      if (status != DXS_statusOk)
+      {
+         DXS_RETURN(status);
+      }
+#endif
+#ifdef DXS_FEAT_CID
+      /* cleanup static data */
+      DXS_CID_Cleanup(pCh);
+#endif
+      pCh->ring = DXS_Ring_ResInit(pCh);
+      DXS_EventMaskSetDefault(pCh);
+   }
+
+   /* From now on process all events. */
+   dxs_outbox_handler_enable(pDev);
+
+   /* patch download sync sem */
+   sem_init(&pDev->mtxPatchDwld, 0, 0);
+   pDev->bWaitingInPatchDwld = 0;
+
+   /* DCDC HW specific init */
+   DXS_DCDC_HW_Init(pDev);
+
+   pDev->flags |= DXS_DEV_INITIALIZED;
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_controller_reset
+
+   \param   pDev       - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_controller_reset(DXS_DEVICE_t *pDev)
+{
+   int32_t  ret = DXS_statusOk;
+   uint16_t nDxsRegBootCfg = 0,
+            nDxsRegBootInfo = 0,
+            nDxsRegCfg  = 0;
+
+   /* Set the controller startup configuration in the Boot Configuration
+      Register to boot from ROM. */
+   nDxsRegBootCfg = DXS_REG_BCFG_ASC_ROM;
+   ret = DXS_RegWrite(pDev, DXS_REG_BCFG, nDxsRegBootCfg);
+   if (ret != DXS_statusOk)
+   {
+      /* errmsg: Setting of boot configuration register failed. */
+      ret = DXS_statusSetBootCfgErr;
+   }
+
+   /* Reset controller to start the boot. */
+   if (ret == DXS_statusOk)
+   {
+      nDxsRegCfg = DXS_REG_CFG_RST_RSTCORE|DXS_REG_CFG_8BIT_EN;
+      ret = DXS_RegWrite(pDev, DXS_REG_CFG, nDxsRegCfg);
+      if (ret != DXS_statusOk)
+      {
+         /* errmsg: Controller reset failed. */
+         ret =  DXS_statusCtrlResErr;
+      }
+   }
+
+   /* Check success of the reset by reading the boot info register. */
+   if (ret == DXS_statusOk)
+   {
+      uint8_t loop = 10;
+
+      while (loop > 0)
+      {
+         struct timespec ts = {0, 2000000}; /* 2 ms */
+
+         nanosleep(&ts, NULL);
+
+         /* read the boot state indication */
+         ret = DXS_RegRead(pDev, DXS_REG_BINF, &nDxsRegBootInfo);
+
+         if ((ret == DXS_statusOk) &&
+             ((nDxsRegBootInfo & DXS_REG_BINF_BOOTSTATE_MASK) >= 0x10))
+         {
+            break;
+         }
+
+         loop--;
+      }
+
+      if (loop == 0)
+      {
+         /* errmsg: Firmware download timeout. */
+         ret = DXS_statusFwDwldTimeout;
+      }
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function dxs_caps_read
+
+   \param   pDev       - pointer to DXS device structure
+   \param   pCap       - pointer to DXS_Caps_t structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_caps_read(DXS_DEVICE_t *pDev, DXS_Caps_t *pCap)
+{
+   DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   if (DXS_statusOk == dxs_caps_vers_update(pDev))
+   {
+      pCap->nChannels = pDev->nChannels;
+      pCap->nGR909 = p->fw_caps.GR909;
+      pCap->nACLM = p->fw_caps.ACLM;
+      pCap->nTTX = p->fw_caps.TTX;
+      pCap->nUTD = p->fw_caps.UTD;
+      pCap->nCID = p->fw_caps.CID;
+      pCap->nHowler = p->fw_caps.HOWLER;
+   }
+   else
+   {
+      DXS_RETURN(DXS_statusCapVersUpdateError);
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_vers_read
+
+   \param   pDev       - pointer to DXS device structure
+   \param   pVersion - pointer to DXS_Version_t structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_vers_read(DXS_DEVICE_t *pDev, DXS_Version_t *pVersion)
+{
+   DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   if (DXS_statusOk == dxs_caps_vers_update(pDev))
+   {
+      pVersion->device = p->dev;
+      pVersion->package = p->pack;
+
+      pVersion->fw_maj = p->fw_vers.MAJ;
+      pVersion->fw_min = p->fw_vers.MIN;
+      pVersion->fw_hfix = p->fw_vers.HF;
+      pVersion->fw_time = p->fw_vers.TIME;
+
+      pVersion->lib_ver = DXS_LIB_VERSION;
+      pVersion->api_ver = DXS_API_VERSION;
+   }
+   else
+   {
+      DXS_RETURN(DXS_statusCapVersUpdateError);
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_sleep
+
+   \param   pDev       - pointer to DXS device structure
+   \param   enable     - enable
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_sleep(DXS_DEVICE_t *pDev, uint8_t enable)
+{
+   DXS_Dev_Caps_t *p;
+   int32_t ret = DXS_statusOk;
+
+   if (pDev == NULL || enable > 1)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!(p->flag & DXS_DEV_SYS_CTRL_UPDATED))
+   {
+      ret = CmdRead(pDev, (uint32_t *)&p->fw_sys_ctrl, (uint32_t *)&p->fw_sys_ctrl);
+      if (ret != DXS_statusOk)
+      {
+         DXS_RETURN(ret);
+      }
+      p->flag |= DXS_DEV_SYS_CTRL_UPDATED;
+   }
+
+   /* sleep mode is not allowed for shared DCDC */
+   if (pDev->dcdcType == DXS_DCDC_IFB12CH8 && enable)
+   {
+      DXS_RETURN(DXS_statusSleepModeNotAllowed);
+   }
+
+   /* update command */
+   if (enable != p->fw_sys_ctrl.SE)
+   {
+      p->fw_sys_ctrl.SE = enable;
+      ret = CmdWrite(pDev, (uint32_t *)&p->fw_sys_ctrl);
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Check if a particular feature is supported by the device
+
+   \param   pDev  - pointer to DXS device structure
+   \param   cap   - feature enumerator \ref e_DXS_DevCaps
+
+   \return
+   - 1 if a featire is supported, 0 if not
+*/
+int32_t DXS_IsFeatureSupported(DXS_DEVICE_t *pDev, enum e_DXS_DevCaps cap)
+{
+   DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+   DXS_FW_SYS_CAPS_t *pCap = &p->fw_caps;
+   uint32_t sys_read_caps_I1 = *((uint32_t *)pCap + 1);
+
+   if (sys_read_caps_I1 & (1 << cap))
+      return 1;
+
+   return 0;
+}
+
+/**
+   Switch on the Charge Pump
+
+   \param   pDev  - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_ChargePumpSwitchOn(DXS_DEVICE_t *pDev)
+{
+   DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+   DXS_FW_SYS_Control_t *pSysCtrl = &p->fw_sys_ctrl;
+   int32_t ret = DXS_statusOk;
+
+   /* for IFB12CH8 apply the configuration only for the device
+      that owns a master channel */
+   if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      DXS_CHANNEL_t *pCh, *pChMaster;
+      uint8_t i = 0, master_found = 0;
+
+      if ((pChMaster=DXS_DCDC_HW_SharedDcDcMasterChGetInt(pDev)) != NULL)
+      {
+         for (pCh=&pDev->pChannel[0],i=0; i < pDev->nChannels; i++, pCh++)
+         {
+            if (pCh == pChMaster)
+            {
+               master_found = 1;
+               break;
+            }
+         }
+
+         if (!master_found)
+            return DXS_statusOk;
+      }
+   }
+
+   if (pSysCtrl->CP_EN != 1)
+   {
+      pSysCtrl->CP_VOLT = DXS_FW_SYS_Control_CP_VOLT_5_0V;
+      pSysCtrl->CP_EN = 1;
+      ret = CmdWrite(pDev, (uint32_t *)pSysCtrl);
+   }
+
+   DXS_RETURN(ret);
+}
+
+#if 0
+/**
+   Switch off the Charge Pump
+
+   \param   pDev  - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_ChargePumpSwitchOff(DXS_DEVICE_t *pDev)
+{
+   DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+   DXS_FW_SYS_Control_t *pSysCtrl = &p->fw_sys_ctrl;
+   int32_t ret = DXS_statusOk;
+
+   /* for IFB12CH8 apply the configuration only for the device
+      that owns a master channel */
+   if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      DXS_CHANNEL_t *pCh, *pChMaster;
+      uint8_t i = 0, master_found = 0;
+
+      if ((pChMaster=DXS_DCDC_HW_SharedDcDcMasterChGetInt(pDev)) != NULL)
+      {
+         for (pCh=&pDev->pChannel[0],i=0; i < pDev->nChannels; i++, pCh++)
+         {
+            if (pCh == pChMaster)
+            {
+               master_found = 1;
+               break;
+            }
+         }
+
+         if (!master_found)
+            return DXS_statusOk;
+      }
+   }
+
+   if (pSysCtrl->CP_EN != 0)
+   {
+      pSysCtrl->CP_EN = 0;
+      ret = CmdWrite(pDev, (uint32_t *)pSysCtrl);
+   }
+
+   DXS_RETURN(ret);
+}
+#endif /* 0 */
+
+/**
+   Switch on/off Clock Failure handling
+
+   \param   pDev   -  pointer to DXS device structure
+   \param   enable -  0 or 1
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CfEsdSwitch (DXS_DEVICE_t *pDev, uint8_t enable)
+{
+   DXS_Dev_Caps_t *p;
+   int32_t ret = DXS_statusOk;
+   uint8_t plim;
+
+   if (pDev == NULL || enable > 1)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!(p->flag & DXS_DEV_SYS_CTRL_UPDATED))
+   {
+      ret = CmdRead(pDev, (uint32_t *)&p->fw_sys_ctrl, (uint32_t *)&p->fw_sys_ctrl);
+      if (ret != DXS_statusOk)
+      {
+         DXS_RETURN(ret);
+      }
+      p->flag |= DXS_DEV_SYS_CTRL_UPDATED;
+   }
+
+   plim = enable ? 0 : 1;
+
+   if (p->fw_sys_ctrl.PLIM != plim || p->fw_sys_ctrl.SYCLKE != enable)
+   {
+      p->fw_sys_ctrl.PLIM = plim;
+      p->fw_sys_ctrl.SYCLKE = enable;
+      ret = CmdWrite(pDev, (uint32_t *)&p->fw_sys_ctrl);
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Get device info
+
+   \param   pDev      -   pointer to DXS device structure
+   \param   pROM_id   -   ROM mask ID (output)
+   \param   pChannels -   number of channels (output)
+
+   \return
+   - DXS_status_t
+*/
+void DXS_DevInfoGet (DXS_DEVICE_t *pDev, uint8_t *pROM_id,
+                                uint8_t *pChannels)
+{
+   DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+
+   *pROM_id = p->fw_vers.MAJ & 0x7f;
+   *pChannels = p->fw_vers.CH ? 1 : 2;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_init.h b/marvell/services/dxslic/api_lib/src/dxs_init.h
new file mode 100644
index 0000000..c8448f5
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_init.h
@@ -0,0 +1,73 @@
+#ifndef __DXS_INIT_H__
+#define __DXS_INIT_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_init.h
+   Initialization functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs.h"
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+enum e_DXS_DevCaps
+{
+   /** GR909 available */
+   dxs_cap_gr909 = 0,
+   /** AC Level Meter Support Available */
+   dxs_cap_aclm,
+   /** Reserved for future use */
+   dxs_cap_reserved,
+   /** Teletax Support Available */
+   dxs_cap_ttx,
+   /** Universal Tone Detector Available */
+   dxs_cap_utd,
+   /** Caller ID Available */
+   dxs_cap_cid,
+   /** Howler Support Available */
+   dxs_cap_howler,
+};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern DXS_DEVICE_t *dxs_get_dev (uint8_t dxs);
+extern uint8_t dxs_CRC_8_CCITT(uint8_t *pData, uint32_t nLength);
+extern int32_t dxs_init(DXS_DEVICE_t *pDev, uint8_t chipSelect,
+                        int32_t irqNumber, uint8_t dcdcType, uint8_t access,
+                        uint8_t dev);
+extern int32_t dxs_exit(DXS_DEVICE_t *pDev);
+extern int32_t dxs_caps_vers_update(DXS_DEVICE_t *pDev);
+extern int32_t dxs_caps_vers_forget(DXS_DEVICE_t *pDev);
+extern int32_t dxs_caps_read(DXS_DEVICE_t *pDev, DXS_Caps_t *pCap);
+extern int32_t dxs_vers_read(DXS_DEVICE_t *pDev, DXS_Version_t *pVersion);
+extern int32_t DXS_IsFeatureSupported(DXS_DEVICE_t *pDev,
+                                      enum e_DXS_DevCaps cap);
+extern int32_t DXS_ChargePumpSwitchOn(DXS_DEVICE_t *pDev);
+#if 0
+extern int32_t DXS_ChargePumpSwitchOff(DXS_DEVICE_t *pDev);
+#endif
+extern int32_t DXS_CfEsdSwitch (DXS_DEVICE_t *pDev, uint8_t on);
+extern void DXS_DevInfoGet (DXS_DEVICE_t *pDev, uint8_t *pROM_id,
+                                uint8_t *pChannels);
+extern int32_t dxs_sleep(DXS_DEVICE_t *pDev, uint8_t enable);
+#endif /* __DXS_INIT_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_lib.h b/marvell/services/dxslic/api_lib/src/dxs_lib.h
new file mode 100644
index 0000000..51226db
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_lib.h
@@ -0,0 +1,185 @@
+#ifndef __DXS_LIB_H__
+#define __DXS_LIB_H__
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_lib.h
+   This file contains the device and channel structure definitions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_config.h"
+#include <stdint.h>
+#include <semaphore.h>
+#include <string.h>
+#include <pthread.h>
+#include <endian.h>
+#include "dxs_fifo.h"
+#ifdef EVENT_LOGGER_DEBUG
+#include <linux/ioctl.h>
+#include "el_ioctl.h"
+#endif /* EVENT_LOGGER_DEBUG */
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define CH_PER_DEVICE     2
+
+#ifdef EVENT_LOGGER_DEBUG
+#define DXS_LIB_DEV_TYPE 17
+#endif
+
+#define POINTER_ASSERT(pPointer) \
+   do \
+   { \
+      if (pPointer == NULL) \
+      { \
+         DXS_RETURN(DXS_statusInvalidParam); \
+      } \
+   } while (0)
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+typedef struct dxs_device_t DXS_DEVICE_t;
+typedef struct dxs_channel_t DXS_CHANNEL_t;
+
+/* dxs_hsm.h uses DXS_CHANNEL_t, therefore it should be placed after the
+ * typedef of DXS_CHANNEL_t*/
+#include "dxs_hsm.h"
+
+/** Channel structure */
+struct dxs_channel_t
+{
+   /** channel number starting from 0 */
+   uint8_t nCh;
+   /** status flags */
+#define DXS_CH_BBD_DOWNLOADED             0x00000001
+#define DXS_CH_DIAL_DATA_INITIALIZED      0x00000008
+   volatile uint32_t flags;
+   /** pointer to parent device */
+   DXS_DEVICE_t *pParent;
+   /* mask for event reporting, 64 bits */
+   uint32_t event_mask[2];
+   /** PCM resource */
+   void *pcm;
+   /** SDD resource */
+   void *sdd;
+   /** SIG resource */
+   void *sig;
+#ifdef DXS_FEAT_HSM
+   DXS_DIAL_DATA_t               DXS_DialData;
+#endif /* DXS_FEAT_HSM */
+   void *ring;
+};
+
+/** Device structure */
+struct dxs_device_t
+{
+   /** device number */
+   uint8_t nDevNum;
+   /** chip select number */
+   uint8_t chipSelect;
+   /** IRQ line number */
+   int32_t irqNumber;
+   /** DCDC variant */
+   uint8_t dcdcType;
+   /** Access mode */
+   DXS_ACCESS_MODE_t access;
+
+   /** device status flags */
+#define DXS_DEV_INITIALIZED            0x00000001
+#define DXS_DEV_PRAM_PATCH_DOWNLOADED  0x00000002
+#define DXS_DEV_OBX_HND_INITIALIZED    0x00000004
+#define DXS_DEV_ACCESS_INITIALIZED     0x00000008
+   volatile uint32_t flags;
+
+   /** SPI device fd */
+   int spidev;
+
+   /** Device ROM mask version */
+   uint32_t rom_mask_ver;
+   /** Patch download sync sem */
+   sem_t mtxPatchDwld;
+   /** Waiting status flag */
+   volatile uint32_t bWaitingInPatchDwld;
+
+   /** outbox data serving thread */
+   pthread_t obxThread;
+
+   /** outbox data thread semaphore */
+   sem_t obxSemaphore;
+   /** signaling semaphore used by
+      the outbox thread for command
+      read response */
+   sem_t obxCmdDataSem;
+   /** condition to stop the thread */
+   volatile uint8_t obxThreadStop;
+   /** Flag to discard events.
+       Used at startup until the startup finished event is received. */
+   uint8_t obxDiscardEvents;
+
+   /** mailbox access mutex */
+   pthread_mutex_t mtxMbxAcc;
+   /** cached command inbox length */
+   uint8_t nMbxCachedCbiLen;
+
+   /** event queue */
+   FIFO_t *event_queue;
+   /** command outbox data queue */
+   FIFO_t *cmd_obx_queue;
+
+   /** waiting list (the device is a member of) */
+   void *wait_list;
+
+   /* ======= fw capabilities: ====== */
+   /** actual analog channels count */
+   uint8_t nChannels;
+   /** capabilities handler */
+   void *caps;
+   /* === end of fw capabilities: === */
+
+   /* TODO: last error */
+
+   /** device event memory pool */
+   void *event_pool;
+
+   /** pcm resource handler */
+   void *pcm;
+
+   /** GPIO resource */
+   void *gpio;
+
+   /* 2022-3-17, expand array size from 32 to 512.
+    *
+    * DXS_ObxRead does not check array boundary;
+    * This will protect memory afterwards from overwritten.
+    */
+   /** copy of the mailbox */
+   uint16_t dmbx[512];
+
+   /** channel array */
+   DXS_CHANNEL_t pChannel[CH_PER_DEVICE];
+
+#ifdef EVENT_LOGGER_DEBUG
+   int32_t el_fd;
+#endif
+
+};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+#endif /* __DXS_LIB_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_mbx.c b/marvell/services/dxslic/api_lib/src/dxs_mbx.c
new file mode 100644
index 0000000..d423594
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_mbx.c
@@ -0,0 +1,529 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_mbx.c
+   Implementation of mailbox functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <time.h>
+#include <errno.h>
+
+#include "dxs_lib.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_access.h"
+#ifdef EVENT_LOGGER_DEBUG
+#include <sys/ioctl.h>
+#endif
+
+/*#define DXS_CMD_PRINT*/
+#undef DXS_CMD_PRINT
+
+#ifdef DXS_CMD_PRINT
+   #include <stdio.h>
+#endif
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_WAIT_POLLTIME     50000 /* ns */
+#define DXS_FIBXMS_POLL_LOOP  1000
+
+/** Size of the in message box  (Host data message box in)  in bytes */
+#define DXS_MBI_SIZE          32 /* 8 words @ 32-bit */
+/** Size of the out message box (Host data message box out) in bytes */
+#define DXS_MBO_SIZE          32 /* 8 words @ 32-bit */
+
+#define RW_WRITE 0
+#define RW_READ  1
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** Data structure for firmware command header */
+struct dxs_cmd_hdr
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Read/Write */
+   uint32_t RW : 1;
+   /* Reserved */
+   uint32_t Res00 : 2;
+   /* Command */
+   uint32_t CMD : 5;
+   /* Reserved */
+   uint32_t Res01 : 4;
+   /* Channel */
+   uint32_t CHAN : 4;
+   /* Module */
+   uint32_t MOD : 3;
+   /* Command Sub-Mode */
+   uint32_t ECMD : 5;
+   /* Length of Message */
+   uint32_t LENGTH : 8;
+#else
+   /* Length */
+   uint32_t LENGTH : 8;
+   /* Reserved */
+   uint32_t Res : 23;
+   /* Read write Access */
+   uint32_t RW : 1;
+#endif
+} __attribute__((packed));
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+static int32_t dxs_cmdWrite(
+                        DXS_DEVICE_t *pDev,
+                        uint32_t *pCmd,
+                        uint8_t nCount);
+
+static int32_t dxs_Wait4MBIspace(
+                        DXS_DEVICE_t *pDev,
+                        uint8_t nCount);
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+#ifdef EVENT_LOGGER_DEBUG
+static void dxs_el_trace_cmd_wr(DXS_DEVICE_t *pDev, struct dxs_cmd_hdr *pMsgHead)
+{
+   EL_IoctlAddLog_t stLog;
+   stLog.nLogType = EL_LOG_TYPE_CMD_WR;
+   stLog.nOrygLogType = EL_MAX_LOG_TYPE;
+   stLog.nDevType = DXS_LIB_DEV_TYPE;
+   stLog.nDevNum = pDev->nDevNum;
+   stLog.nChNum = pMsgHead->CHAN;
+   stLog.uLogDetails.stCmd_Wr.nStatus = IFX_SUCCESS;
+   stLog.uLogDetails.stCmd_Wr.nCmdLength = 4;
+   stLog.uLogDetails.stCmd_Wr.nCount = pMsgHead->LENGTH + 4;
+   stLog.uLogDetails.stCmd_Wr.nDataLength = pMsgHead->LENGTH;
+   stLog.uLogDetails.stCmd_Wr.pCMD = (IFX_char_t *) pMsgHead;
+   stLog.uLogDetails.stCmd_Wr.pDATA = (IFX_char_t *) ((int16_t *) pMsgHead + 2);
+   ioctl(pDev->el_fd, EL_ADD_LOG, (int32_t)&stLog);
+}
+
+static void dxs_el_trace_cmd_rd(DXS_DEVICE_t *pDev, struct dxs_cmd_hdr *pMsgHead)
+{
+   EL_IoctlAddLog_t stLog;
+   stLog.nLogType = EL_LOG_TYPE_CMD_RD;
+   stLog.nOrygLogType = EL_MAX_LOG_TYPE;
+   stLog.nDevType = DXS_LIB_DEV_TYPE;
+   stLog.nDevNum = pDev->nDevNum;
+   stLog.uLogDetails.stCmd_Rd.nStatus = IFX_SUCCESS;
+   stLog.uLogDetails.stCmd_Rd.nCmdLength = 4;
+   stLog.uLogDetails.stCmd_Rd.nCount = pMsgHead->LENGTH + 4;
+   stLog.uLogDetails.stCmd_Rd.nDataLength = pMsgHead->LENGTH;
+   stLog.uLogDetails.stCmd_Rd.pCMD = (IFX_char_t *) pMsgHead;
+   stLog.uLogDetails.stCmd_Rd.pDATA = (IFX_char_t *) ((int16_t*) pMsgHead + 2);
+   ioctl(pDev->el_fd, EL_ADD_LOG, (int32_t)&stLog);
+}
+#endif
+
+/**
+   Function dxs_cmdWrite
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pCmd    - pointer to command
+   \param   nCount  - command length
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_cmdWrite(DXS_DEVICE_t *pDev, uint32_t *pCmd, uint8_t nCount)
+{
+   int32_t ret;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   uint16_t  pCmd_le[DXS_MBI_SIZE >> 1];
+   int32_t i;
+#else
+   uint16_t*  pCmd_le = (uint16_t *)pCmd;
+#endif
+
+   nCount += sizeof(struct dxs_cmd_hdr);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   if (nCount > DXS_MBI_SIZE || (nCount % 4))
+   {
+      DXS_RETURN(DXS_statusCmdLengthInvalid);
+   }
+   /* swap 2 byte words */
+   for(i = 0; i < nCount>>2; i++)
+   {
+      pCmd_le[i << 1] = *((uint16_t*)pCmd + (i << 1) + 1);
+      pCmd_le[(i << 1) + 1] = *((uint16_t*)pCmd + (i << 1));
+   }
+#endif
+   /* wait for free space in command inbox */
+   ret = dxs_Wait4MBIspace(pDev, nCount);
+
+   if (ret == DXS_statusOk)
+   {
+      ret = DXS_RegWriteMulti(pDev, DXS_REG_DATA, pCmd_le, nCount>>1);
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function dxs_Wait4MBIspace
+
+   \param   pDev    - pointer to DXS device structure
+   \param   nCount  - count
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_Wait4MBIspace(DXS_DEVICE_t *pDev, uint8_t nCount)
+{
+   int32_t  nWaitCnt = 0;
+   uint16_t nReg = 0;
+
+   do
+   {
+      struct timespec ts = {0, DXS_WAIT_POLLTIME};
+
+
+      if (pDev->nMbxCachedCbiLen < nCount)
+      {
+         DXS_RegRead(pDev, DXS_REG_LEN, &nReg);
+         /* shift to get number of bytes from 16bit words */
+         pDev->nMbxCachedCbiLen = (nReg & 0xff) << 1;
+      }
+
+      if (nCount <= pDev->nMbxCachedCbiLen)
+      {
+         /* Sufficient free space in command-inbox to grant the request. */
+         /* Reduce the cache by the amount that was just granted. */
+         pDev->nMbxCachedCbiLen -= nCount;
+         return DXS_statusOk;
+      }
+      /* Not enough free space in the command-inbox, we have to wait until more
+         space becomes available and start the loop again after a short delay.
+         The iterations are limited and the resulting timeout is:
+         (WAIT_POLLTIME * DXT_FIBXMS_POLL_LOOP)us. */
+      nanosleep(&ts, NULL);
+   } while ((++nWaitCnt < DXS_FIBXMS_POLL_LOOP));
+
+#if 0
+   /* exceeded maximum wait time or device error,
+      reset the command-inbox by writing CMDMBX_RES bit */
+   nReg = 1;
+   REG_WRITE_UNPROT(pDev, DXS_REG_CMD, nReg);
+
+   /* poll the HOST_CMD.CMDMBX_RES bit until cleared */
+   do
+   {
+      REG_READ_UNPROT(pDev, DXS_REG_CMD, &nReg);
+   } while (nReg & 1);
+#endif
+
+   DXS_RETURN(DXS_statusCmdIbxNoSpace);
+}
+
+/**
+   Function DXS_CmdWrite
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pCmd    - pointer to command
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CmdWrite(DXS_DEVICE_t *pDev, uint32_t *pCmd)
+{
+   struct dxs_cmd_hdr *pMsgHead = (struct dxs_cmd_hdr *)pCmd;
+   int32_t ret, err;
+
+   if (sizeof(struct dxs_cmd_hdr) + pMsgHead->LENGTH > DXS_MBI_SIZE)
+   {
+      DXS_RETURN(DXS_statusCmdLengthInvalid);
+   }
+
+   pMsgHead->RW = RW_WRITE;
+
+   err = pthread_mutex_lock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   ret = dxs_cmdWrite(pDev, pCmd, pMsgHead->LENGTH);
+
+   err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+#ifdef DXS_CMD_PRINT
+   {
+      int i, words = (pMsgHead->LENGTH + sizeof(*pMsgHead))/sizeof(*pMsgHead);
+
+      fprintf (stderr, "[cw] dev:%d err:0x%04X  ", pDev->nDevNum, err);
+      for (i=0; i<words; i++)
+         fprintf (stderr, "%08X ", pCmd[i]);
+      fprintf (stderr, "\n");
+   }
+#endif
+#ifdef EVENT_LOGGER_DEBUG
+   dxs_el_trace_cmd_wr(pDev, pMsgHead);
+#endif
+
+   if (ret)
+   {
+      DXS_RETURN(DXS_statusCmdMbxWriteError);
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function DXS_CmdRead
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pCmd    - pointer to command
+   \param   pData   - pointer to data
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_CmdRead(DXS_DEVICE_t *pDev, uint32_t *pCmd, uint32_t *pData)
+{
+   struct dxs_cmd_hdr *pMsgHead = (struct dxs_cmd_hdr *)pCmd;
+   int32_t ret = DXS_statusOk, err;
+   uint8_t nReadBytes, nExpectedBytes, nCnt = 0;
+   struct timespec ts = {0};
+#ifdef DXS_CMD_PRINT
+   /* just for logging */
+   uint32_t *pw = pData;
+#endif
+   uint8_t runs;
+
+   if (pMsgHead->LENGTH > DXS_MBO_SIZE)
+   {
+      DXS_RETURN(DXS_statusCmdLengthInvalid);
+   }
+
+   err = pthread_mutex_lock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* Write the read request */
+   pMsgHead->RW = RW_READ;
+   if ((ret = dxs_cmdWrite(pDev, pCmd, 0)) != DXS_statusOk)
+   {
+      err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      DXS_RETURN(DXS_statusCmdMbxWriteError);
+   }
+
+   /* This is the number of bytes we are going to read. */
+   nExpectedBytes = sizeof(struct dxs_cmd_hdr) + pMsgHead->LENGTH;
+
+   /* make 3 read attempts with 1 sec interval */
+   runs = 0;
+   do
+   {
+      /* schedule obxThread for execution */
+      sem_post(&pDev->obxSemaphore);
+      /* wait 1s */
+      clock_gettime (CLOCK_REALTIME, &ts);
+      ts.tv_sec += 1;
+      ret = sem_timedwait(&pDev->obxCmdDataSem, &ts);
+   } while(++runs < 3 && ret);
+
+   if (runs == 3 && ret == -1 && errno == ETIMEDOUT)
+   {
+      err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      DXS_RETURN(DXS_statusCmdObDataRdTmout);
+   }
+   else if (ret != 0)
+   {
+      err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      DXS_RETURN(DXS_statusCmdObRdErr);
+   }
+
+   /* nCnt is a number of elements, 32-bit each */
+   nCnt = fifo_count (pDev->cmd_obx_queue);
+   nReadBytes = (nCnt * sizeof(uint32_t));
+
+   if (nReadBytes > nExpectedBytes)
+   {
+      /* more data than expected */
+#ifdef DXS_CMD_PRINT
+      fprintf (stderr,
+               "[cr] dev:%d ERROR excess data. Read:%d Expected:%d -",
+               pDev->nDevNum, nReadBytes, nExpectedBytes);
+      while (nCnt--)
+      {
+         void *pdummy;
+         uint32_t nData;
+
+         /* Clear the fifo by reading it and print the content. */
+         fifo_get (pDev->cmd_obx_queue, &pdummy, &nData);
+         fprintf (stderr, " %08X", nData);
+      }
+         fprintf (stderr, "\n");
+#else
+      /* Discard all data. The error code will report this event. */
+      fifo_flush (pDev->cmd_obx_queue);
+#endif
+      err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      DXS_RETURN(DXS_statusCmdObDataOvld);
+   }
+
+   while (nCnt--)
+   {
+      void *pdummy;
+
+      /* read the data from the fifo to pData */
+      fifo_get (pDev->cmd_obx_queue, &pdummy, pData++);
+   }
+
+   err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+#ifdef EVENT_LOGGER_DEBUG
+   dxs_el_trace_cmd_rd(pDev, pMsgHead);
+#endif
+
+#ifdef DXS_CMD_PRINT
+   {
+      int i, words = (pMsgHead->LENGTH + sizeof(*pMsgHead))/sizeof(*pMsgHead);
+
+      fprintf (stderr, "[cr] dev:%d return:0x%04X - ", pDev->nDevNum, ret);
+      for (i=0; i<words; i++)
+         fprintf (stderr, " %08X", pw[i]);
+      fprintf (stderr, "\n");
+   }
+#endif
+
+   return DXS_statusOk;
+}
+
+/**
+   Download binary into patch ram.
+
+   The given data is sent in to the mailbox. This code takes care of
+   fragmenting it into chunks of the size of the mailbox.
+   Note that the download does not need to read the mailbox length register
+   and wait for enough space to be available because the DXS reads the patch
+   faster out of the mailbox than it can be filled via the SPI interface.
+
+   \param  pDev         pointer to the device interface
+   \param  pBuffer      Pointer to Buffer for download
+   \param  nSize        size of the buffer in bytes
+   \return
+   Error code.
+*/
+int32_t DXS_DwldPatch ( DXS_DEVICE_t *pDev,
+                        uint8_t *pBuffer,
+                        uint32_t nSize)
+{
+   int32_t        ret = DXS_statusOk, err;
+   uint32_t       pos = 0,
+                  remaining = nSize,
+                  fragment,
+                  fragment_limit;
+   uint16_t       pBuf[DXS_MBI_SIZE>>1];
+
+   if ((pBuffer == NULL) || (nSize == 0))
+   {
+      /* errmsg: At least one parameter is wrong. */
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   /* Find the maximum size a fragment may have to pass through SPI without
+      incurring addtional fragmentation there. */
+   fragment_limit = DXS_spi_blocksize_get(pDev);
+
+   err = pthread_mutex_lock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* write all data */
+   while ((remaining > 0) && (ret == DXS_statusOk))
+   {
+      /* calculate length of fragment: note that count is in bytes */
+      fragment = (remaining > DXS_MBI_SIZE) ? DXS_MBI_SIZE : remaining;
+      fragment = (fragment > fragment_limit) ? fragment_limit : fragment;
+      /* ensure that the fragment has a multiple of 4 bytes */
+      fragment = fragment - (fragment % 4);
+
+      /* copy into the output buffer */
+      DXS_cpb2w(pBuf, &pBuffer[pos], fragment);
+
+      ret = DXS_RegWriteMulti(pDev, DXS_REG_DATA, pBuf, fragment>>1);
+      /* increment position */
+      pos += fragment;
+      /* decrement count */
+      remaining -= fragment;
+   } /* while */
+
+   err = pthread_mutex_unlock (&pDev->mtxMbxAcc);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   DXS_RETURN(ret);
+}
+
+/**
+   DXS_ObxRead - read DATA outbox content
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pData   - buffer where to store data
+   \param   len     - returned data length in 16-bit words
+
+*/
+void DXS_ObxRead(DXS_DEVICE_t *pDev, uint16_t *pData, uint8_t *len)
+{
+   uint16_t nHostLen;
+   uint8_t  words = 0; /* 16-bit words */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   int32_t i;
+   uint16_t tmp;
+#endif
+
+   /* read HOST_LEN */
+   DXS_RegRead(pDev, DXS_REG_LEN, &nHostLen);
+
+   words = nHostLen >> 8;
+
+   if (words > 0)
+   {
+      /* Read from HOST_DATA, the out mailbox. */
+      DXS_RegReadMulti(pDev, DXS_REG_DATA, pData, words);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   /* swap 2 byte words */
+   for (i = 0; i < words >> 1; i++)
+   {
+      tmp = pData[i << 1];
+      pData[i << 1] = pData[(i << 1) + 1];
+      pData[(i << 1) + 1] = tmp;
+   }
+#endif
+   }
+
+   *len = words;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_mbx.h b/marvell/services/dxslic/api_lib/src/dxs_mbx.h
new file mode 100644
index 0000000..9e3eb1d
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_mbx.h
@@ -0,0 +1,55 @@
+#ifndef __DXS_MBX_H__
+#define __DXS_MBX_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_mbx.h
+   Mailbox functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define CmdWrite  DXS_CmdWrite
+#define CmdRead   DXS_CmdRead
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t DXS_CmdWrite(
+                        DXS_DEVICE_t *pDev,
+                        uint32_t *pCmd);
+
+extern int32_t DXS_CmdRead(
+                        DXS_DEVICE_t *pDev,
+                        uint32_t *pCmd,
+                        uint32_t *pData);
+
+extern int32_t DXS_DwldPatch (
+                        DXS_DEVICE_t *pDev,
+                        uint8_t *pBuffer,
+                        uint32_t nSize);
+extern void DXS_ObxRead(
+                        DXS_DEVICE_t *pDev, 
+                        uint16_t *pData, 
+                        uint8_t *len);
+
+#endif /* __DXS_MBX_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_mempool.c b/marvell/services/dxslic/api_lib/src/dxs_mempool.c
new file mode 100644
index 0000000..df53b71
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_mempool.c
@@ -0,0 +1,354 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_mempool.c
+   XXXXXX
+
+   \remarks
+   XXXXXX
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdlib.h>
+#include <pthread.h>
+#include "dxs_mempool.h"
+#include "dxs_error.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_MAX_MEMPOOLS            16
+#define DXS_MAX_MEMPOOL_ELEMENTS    32
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+struct __mempool
+{
+   uint8_t            in_use;
+   pthread_mutex_t    mtx;
+   struct __buffer    *free;
+   struct __buffer    *allocated;
+};
+
+struct __buffer
+{
+   void            *p;
+   struct __buffer *next;
+};
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static struct __mempool mempool[DXS_MAX_MEMPOOLS] = {{0},};
+static struct __buffer  buffers[DXS_MAX_MEMPOOLS * DXS_MAX_MEMPOOL_ELEMENTS];
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Initialize a memory buffer pool.
+
+   \param mem        Address of continuous memory block
+                     on which to organize a pool.
+   \param size       Size of continuous memory block in bytes.
+   \param elem_num   Number of buffers to create.
+   \param elem_size  Size of each individual buffer in bytes.
+   \param *pool_id   pool instance to return.
+
+   \return
+      DXS_MPOOL_OK             success
+      DXS_MPOOL_PARAMS         invalid parameters
+      DXS_MPOOL_NOT_ENOUGH     not enough memory for a pool
+      DXS_MPOOL_NO_FREE_POOLS  cannot allocate a pool
+*/
+int32_t mempool_init(void *mem, uint32_t size, uint16_t elem_num,
+                     uint16_t elem_size, void **pool_id)
+{
+   int i, err;
+   struct __mempool *pool;
+   struct __buffer  *curr;
+
+   if (mem == NULL || size == 0)
+      return DXS_MPOOL_PARAMS;
+
+   if (elem_num > DXS_MAX_MEMPOOL_ELEMENTS)
+      elem_num = DXS_MAX_MEMPOOL_ELEMENTS;
+
+   if ((elem_num * elem_size) > size)
+      return DXS_MPOOL_NOT_ENOUGH;
+
+   /* get next available pool */
+   for (i=0; i<DXS_MAX_MEMPOOLS; i++)
+   {
+      pool = &mempool[i];
+      if (!pool->in_use)
+         break;
+   }
+
+   if (i == DXS_MAX_MEMPOOLS)
+   {
+      /* cannot allocate a free pool */
+      return DXS_MPOOL_NO_FREE_POOLS;
+   }
+
+   pool->in_use = 1;
+   pthread_mutex_init(&pool->mtx, NULL);
+
+   err = pthread_mutex_lock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* create a head node */
+   curr = pool->free = &buffers[i * DXS_MAX_MEMPOOL_ELEMENTS];
+   curr->p = mem;
+   curr->next = NULL;
+
+   /* initialize remaining nodes */
+   for (i=1; i<elem_num; i++)
+   {
+      /* get the new buffer */
+      struct __buffer  *b = pool->free + i;
+
+      b->p = (void *)((uint8_t *)mem + i * elem_size);
+      b->next = NULL;
+
+      /* add the new buffer to the tail */
+      curr->next = b;
+      curr = b;
+   }
+
+   /* allocated list is initially empty */
+   pool->allocated = NULL;
+
+   /* return a pool instance */
+   *pool_id = (void *)pool;
+
+   err = pthread_mutex_unlock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return DXS_MPOOL_OK;
+}
+
+/**
+   Get a buffer from the pool.
+
+   \param pool_id   Memory pool selector.
+
+   \return
+      A memory buffer or NULL in case of an error.
+*/
+void *mempool_get(void *pool_id)
+{
+   int err;
+   struct __mempool *pool = (struct __mempool *)pool_id;
+   struct __buffer *buff;
+
+   /* TODO: trap on wild pool_id ? */
+
+   err = pthread_mutex_lock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+   /* get the buffer from the free list head */
+   buff = pool->free;
+   if (buff == NULL)
+   {
+      /* empty list - no buffers available */
+      err = pthread_mutex_unlock (&pool->mtx);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      return (void *)NULL;
+   }
+
+   /* advance the free list head */
+   pool->free = buff->next;
+
+   /* buff now goes to the tail of the allocated list */
+   buff->next = NULL;
+   if (pool->allocated == NULL)
+   {
+      pool->allocated = buff;
+   }
+   else
+   {
+      struct __buffer *b = pool->allocated;
+
+      while (b->next != NULL)
+         b = b->next;
+
+      b->next = buff;
+   }
+
+   err = pthread_mutex_unlock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return (buff->p);
+}
+
+/**
+   Return a buffer to the pool.
+
+   \param pool_id   Memory pool selector.
+   \param p         Memory buffer to return to the pool.
+
+   \return
+      DXS_MPOOL_OK
+      DXS_MPOOL_BUF_NOT_FOUND
+*/
+int32_t mempool_put(void *pool_id, void *p)
+{
+   struct __mempool *pool = (struct __mempool *)pool_id;
+   struct __buffer *prev = NULL, *buff;
+   uint8_t found = 0;
+   int err;
+
+   /* TODO: trap on wild pool_id ? */
+
+   err = pthread_mutex_lock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   buff = pool->allocated;
+
+   /* search the allocated list for the buffer */
+   while (buff != NULL)
+   {
+      if (buff->p == p)
+      {
+         found = 1;
+         break;
+      }
+      else
+      {
+        prev = buff;
+        buff = buff->next;
+      }
+   }
+
+   if (!found)
+   {
+      /* buffer is not found in the allocated list */
+      err = pthread_mutex_unlock (&pool->mtx);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      return DXS_MPOOL_BUF_NOT_FOUND;
+   }
+
+   /* remove buff from the allocated list */
+   if (prev != NULL)
+      prev->next = buff->next;
+   else
+      pool->allocated = buff->next;
+
+   /* add buff to the tail of the free list */
+   buff->next = NULL;
+   if (pool->free == NULL)
+   {
+      pool->free = buff;
+   }
+   else
+   {
+      struct __buffer *b = pool->free;
+
+      while (b->next != NULL)
+         b = b->next;
+
+      b->next = buff;
+   }
+
+   err = pthread_mutex_unlock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return DXS_MPOOL_OK;
+}
+
+/**
+   Obtain the number of busy and free buffers in a pool.
+
+   \param pool_id  Memory pool selector.
+   \param *busy    Returned parameter reflecting number of busy buffers.
+   \param *free    Returned parameter reflecting number of free buffers.
+
+   \return
+      None.
+*/
+void mempool_status(void *pool_id, uint16_t *busy,  uint16_t *free)
+{
+   struct __mempool *pool = (struct __mempool *)pool_id;
+   struct __buffer *b;
+   int err;
+
+   /* TODO: trap on wild pool_id ? */
+
+   err = pthread_mutex_lock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   *free = 0;
+   b = pool->free;
+   if (b != NULL)
+   {
+      while (b != NULL)
+      {
+         (*free)++;
+         b = b->next;
+      }
+   }
+
+   *busy = 0;
+   b = pool->allocated;
+   if (b != NULL)
+   {
+      while (b != NULL)
+      {
+         (*busy)++;
+         b = b->next;
+      }
+   }
+
+   err = pthread_mutex_unlock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+}
+
+/**
+   Destroy a memory buffer pool.
+
+   \param pool_id   Memory pool selector.
+
+   \return
+      None.
+*/
+void mempool_destroy(void *pool_id)
+{
+   struct __mempool *pool = (struct __mempool *)pool_id;
+   int err;
+
+   /* TODO: trap on wild pool_id ? */
+
+   err = pthread_mutex_lock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+   pool->in_use = 0;
+   err = pthread_mutex_unlock (&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+   err = pthread_mutex_destroy(&pool->mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_mempool.h b/marvell/services/dxslic/api_lib/src/dxs_mempool.h
new file mode 100644
index 0000000..49a0564
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_mempool.h
@@ -0,0 +1,49 @@
+#ifndef __DXS_MEMPOOL_H__
+#define __DXS_MEMPOOL_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_mempool.h
+   XXXXXX
+
+   \remarks
+   XXXXXX
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdint.h>
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* return codes */
+#define DXS_MPOOL_OK             0
+#define DXS_MPOOL_PARAMS         (-1)
+#define DXS_MPOOL_NOT_ENOUGH     (-2)
+#define DXS_MPOOL_NO_FREE_POOLS  (-3)
+#define DXS_MPOOL_BUF_NOT_FOUND  (-4)
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+extern int32_t mempool_init(void *mem, uint32_t size, uint16_t elem_num,
+                            uint16_t elem_size, void **pool_id);
+extern void *mempool_get(void *pool_id);
+extern int32_t mempool_put(void *pool_id, void *p);
+extern void mempool_status(void *pool_id, uint16_t *busy,  uint16_t *free);
+extern void mempool_destroy(void *pool_id);
+
+#endif /* __DXS_MEMPOOL_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_misc.c b/marvell/services/dxslic/api_lib/src/dxs_misc.c
new file mode 100644
index 0000000..8739339
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_misc.c
@@ -0,0 +1,436 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_misc.c
+   This file contains the implementation of the miscellaneous functions.
+*/
+
+/* ========================================================================= */
+/*                                 Includes                                  */
+/* ========================================================================= */
+#include "dxs_misc.h"
+
+/* ========================================================================= */
+/*                             Macro definitions                             */
+/* ========================================================================= */
+#define Q                      15
+#define Q_PRECISION            1
+#define Q_ABS(a)               ((a) < 0 ? -(a) : (a))
+
+/* ========================================================================= */
+/*                         Function implementation                           */
+/* ========================================================================= */
+
+/**
+   Rotate right (circular shift) an arbitrary data block for up to 8 bits
+   FIXME - data block length is a multiple of bytes, change to multiple of bits
+
+   \param   data  - pointer to the beginning of the data block
+   \param   n     - length of the data block in bytes
+   \param   shift - number of bits to shift (min=0, max=8)
+
+   \return
+   - none
+*/
+static void dxs_misc_data_blk_ror8 (unsigned char *data, int n, int shift)
+{
+   int i;
+   unsigned char tmp = data[n-1];
+
+   for (i=n-1; i>0; i--)
+      data[i] = (data[i] >> shift)|((data[i-1] & (0xff >> (8 - shift))) << (8-shift));
+   data[0] = (data[0] >> shift)|((tmp & (0xff >> (8 - shift))) << (8-shift));
+}
+
+/**
+   Rotate right (circular shift) an arbitrary data block
+
+   \param   data  - pointer to the beginning of the data block
+   \param   len   - length of the data block in bytes
+   \param   shift - number of bits to shift
+
+   \return
+   - none
+*/
+void DXS_Misc_DataBlkRor (unsigned char *data, int len, int shift)
+{
+   int i;
+
+   for (i=0; i<(shift >> 3); i++)
+      dxs_misc_data_blk_ror8(data, len, 8);
+   dxs_misc_data_blk_ror8(data, len, (shift % 8));
+}
+
+/**
+   Function DXS_Misc_MulQ15
+
+   \param   a    - Q15 number
+   \param   b    - Q15 number
+
+   \return
+   - uint16_t multiplication result of two Q15 numbers
+*/
+uint16_t DXS_Misc_MulQ15 (int16_t a, int16_t b)
+{
+   signed long int  temp;
+
+   temp = (long int)a * (long int)b;
+   /* Rounding up */
+   temp += (1 << (Q-1));
+
+   /* Correct by dividing by base */
+   return (temp >> Q);
+}
+
+/**
+   Function DXS_Misc_LeveldB_to_Factor
+
+   \param   dB_ten    - integer value in units of 0.1 dB
+   \remark  Parameter dB_ten must be zero or negative.
+
+   \return
+   - uint16_t factor in Q15 format
+*/
+uint16_t DXS_Misc_LeveldB_to_Factor (int16_t dB_ten)
+{
+   int16_t n, r, hundr, tens, units, mul1 = 32767, mul2 = 32767;
+
+   /* switch to 0.01 dB units */
+   dB_ten *= 10;
+
+   /* calculate factors of 0.5 */
+   n = dB_ten / -602;
+
+   /* calculate reminder */
+   r = -dB_ten - n * 602;
+
+   hundr = r / 100;
+   tens = (r % 100) / 10;
+   units = (r % 100) % 10;
+
+   while (n--)
+   {
+      /* multiply 0.5 n times */
+      mul1 = DXS_Misc_MulQ15(mul1, 16384);
+   }
+
+   while (hundr--)
+   {
+      /* multiply 0.891251 (1dB) hundr times */
+      mul2 = DXS_Misc_MulQ15(mul2, 29205);
+   }
+
+   while (tens--)
+   {
+      /* multiply 0.988553 (0.1dB) tens times */
+      mul2 = DXS_Misc_MulQ15(mul2, 32393);
+   }
+
+   while (units--)
+   {
+      /* multiply 0.998849 (0.01dB) units times */
+      mul2 = DXS_Misc_MulQ15(mul2, 32730);
+   }
+
+   return (DXS_Misc_MulQ15(mul1, mul2));
+}
+
+/*
+ * alt_method
+ *
+ *    - parameter dB_t - integer, in 0.1 dB units, must be negative
+ *
+ */
+uint16_t DXS_Misc_PowerdB_to_Factor (int16_t dB_t)
+{
+   int16_t n, r, hundr, tens, units, mul1 = 32767, mul2 = 32767;
+
+   /* switch to 0.01 dB units */
+   dB_t *= 10;
+
+   /* calculate factors of 0.5 */
+   n = dB_t / -301;
+
+   /* calculate reminder */
+   r = -dB_t - n * 301;
+
+   hundr = r / 100;
+   tens = (r % 100) / 10;
+   units = (r % 100) % 10;
+
+   while (n--)
+   {
+      /* multiply 0.5 n times */
+      mul1 = DXS_Misc_MulQ15(mul1, 16384);
+   }
+
+   while (hundr--)
+   {
+      /* multiply 0.794328 (1dB) hundr times */
+      mul2 = DXS_Misc_MulQ15(mul2, 26029);
+   }
+
+   while (tens--)
+   {
+      /* multiply 0.977237 (0.1dB) tens times */
+      mul2 = DXS_Misc_MulQ15(mul2, 32022);
+   }
+
+   while (units--)
+   {
+      /* multiply 0.9977 (0.01dB) units times */
+      mul2 = DXS_Misc_MulQ15(mul2, 32693);
+   }
+
+   return (DXS_Misc_MulQ15 (mul1, mul2));
+}
+
+/**
+   Function DXS_Misc_RoundDiv
+
+   \param   dividend
+   \param   divisor
+
+   \return
+   - uint32_t division result
+*/
+uint32_t DXS_Misc_RoundDiv(uint32_t dividend, uint32_t divisor)
+{
+   return (dividend + (divisor >> 1)) / divisor;
+}
+
+/******************************************************************************/
+/*                Fixed Point Calculations in Q4.27 format                    */
+/******************************************************************************/
+#if 0
+/**
+   Q4.27 Division
+
+   \param  a  - dividend in Q4.27
+   \param  b  - divisor in Q4.27
+   \return    - a/b in Q4.27
+*/
+static int32_t q4_27_div (int32_t a, int32_t b)
+{
+   int64_t temp = ((int64_t)a) << 27;
+
+   /* round up */
+   temp += (b >> 1);
+
+   return (temp / b);
+}
+
+/**
+   Q4.27 Square Root
+
+   \param   a - argument in Q4.27
+   \return
+   - sqrt(a) in Q4.27
+*/
+int32_t DXS_Misc_Q4_27_Sqrt(int32_t a)
+{
+   int32_t x0, x1;
+
+   if (a == 0) return a;
+
+   /* initial guess */
+   x0 = a;
+
+   /* Newton's formula */
+   while (1)
+   {
+      x1 = (x0 + q4_27_div(a, x0)) >> 1;
+
+      if (Q_ABS(x1-x0) <= Q_PRECISION)
+         break;
+
+      x0 = x1;
+   }
+
+   return x1;
+}
+#endif /* 0 */
+
+/**
+   Convert float to Q4.27
+
+   \param   f - floating point number
+   \return
+   - Q4.27 representation of f
+*/
+int32_t DXS_Misc_Float_to_Q4_27 (float f)
+{
+   f *= 134217728.0f;
+   /* round up */
+   f += (f >= 0) ? 0.5 : -0.5;
+
+   return (int32_t)f;
+}
+
+/**
+   Convert Q4.27 to float
+
+   \param   q - Q4.27 number
+   \return
+   - floating point representaion of Q4.27 q
+*/
+float DXS_Misc_Q4_27_to_Float (int32_t q)
+{
+   return ((float)q / 134217728.0f);
+}
+
+/**
+   Q4.27 Multiplication
+
+   \param   a - Q4.27 number
+   \param   b - Q4.27 number
+   \return
+   - (a*b) in Q4.27 format
+*/
+int32_t DXS_Misc_Q4_27_Mul (int32_t a, int32_t b)
+{
+   int64_t tmp = (int64_t)a * (int64_t)b;
+
+   /* round up */
+   tmp += (1 << 26);
+
+   return (int32_t)(tmp >> 27);
+}
+
+/******************************************************************************/
+/*               Fixed Point Calculations in Q15.16 format                    */
+/******************************************************************************/
+#define  Q15_16_LN_10   0x24D76
+
+/**
+   Q15.16 Division
+
+   \param  a  - dividend in Q15.16
+   \param  b  - divisor in Q15.16
+   \return    - a/b in Q15.16
+*/
+static int32_t q15_16_div (int32_t a, int32_t b)
+{
+   int64_t temp = ((int64_t)a) << 16;
+
+   /* round up */
+   temp += (b >> 1);
+
+   return (temp / b);
+}
+
+/**
+   Q15.16 Multiplication
+
+   \param  a  - Q15.16 number
+   \param  b  - Q15.16 number
+   \return    - (a*b) in Q15.16
+*/
+static int32_t q15_16_mul (int32_t a, int32_t b)
+{
+   int64_t tmp = (int64_t)a * (int64_t)b;
+
+   /* round up */
+   tmp += (1 << 15);
+
+   return (int32_t)(tmp >> 16);
+}
+
+/**
+   Q15.16 Power
+
+   \param  a  - Q15.16 number
+   \param  pw - power, conventional integer, not Q
+   \return    - (a^pw) in Q15.16
+*/
+static int32_t q15_16_pow (int32_t a, int32_t pw)
+{
+   int32_t result = Q15_16_ONE;
+   int32_t (*op)(int32_t a, int32_t b);
+
+   if (pw < 0)
+   {
+      op = q15_16_div;
+      pw = -pw;
+   }
+   else
+      op = q15_16_mul;
+
+   while (pw--)
+      result = op(result, a);
+
+   return result;
+}
+
+/**
+   Convert float to Q15.16
+
+   \param  f  - floating point number
+   \return    - Q15.16 representation of f
+*/
+int32_t DXS_Misc_Float_to_Q15_16 (float f)
+{
+   f *= 65536.0f;
+   /* round up */
+   f += (f >= 0) ? 0.5 : -0.5;
+
+   return (int32_t)f;
+}
+
+/**
+   Convert Q15.16 to float
+
+   \param  q  - Q15.16 number
+   \return    - floating point representation of q
+*/
+float DXS_Misc_Q15_16_to_Float (int32_t q)
+{
+   return ((float)q / 65536.0f);
+}
+
+/**
+   Common logarithm calculation
+
+   \param  a  - argument in Q15.16
+   \return    - log10(a) in Q15.16
+*/
+int32_t DXS_Misc_Q15_16_Log10 (int32_t a)
+{
+   int32_t k=Q15_16_ONE, p=1, result=0, tmp=0;
+
+   while (1)
+   {
+      /* Taylor series */
+      result +=
+         (q15_16_mul(q15_16_pow(-Q15_16_ONE, (p+1)),
+                     q15_16_div(q15_16_pow((a-Q15_16_ONE), p), k)));
+
+      if (Q_ABS(result-tmp) <= Q_PRECISION)
+         break;
+
+      tmp = result;
+      k += Q15_16_ONE;
+      p++;
+   }
+
+   return q15_16_div(result, Q15_16_LN_10);
+}
+
+int32_t DXS_Misc_Q15_16_Mul(int32_t a, int32_t b)
+{
+   return q15_16_mul (a, b);
+}
+
+int32_t DXS_Misc_Q15_16_Div(int32_t a, int32_t b)
+{
+   return q15_16_div (a, b);
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_misc.h b/marvell/services/dxslic/api_lib/src/dxs_misc.h
new file mode 100644
index 0000000..23ba071
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_misc.h
@@ -0,0 +1,66 @@
+#ifndef __DXS_MISC_H__
+#define __DXS_MISC_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_misc.h
+   Miscellaneous functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdint.h>
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern uint16_t DXS_Misc_MulQ15 (int16_t a, int16_t b);
+extern uint16_t DXS_Misc_LeveldB_to_Factor (int16_t dB_ten);
+extern uint16_t DXS_Misc_PowerdB_to_Factor (int16_t dB_t);
+extern uint32_t DXS_Misc_RoundDiv(uint32_t dividend, uint32_t divisor);
+/******************************************************************************/
+/*                Fixed Point Calculations in Q4.27 format                    */
+/******************************************************************************/
+#define Q4_27_ONE     (1 << 27)
+#define Q4_27_TEN     (10 * Q4_27_ONE)
+/*extern int32_t DXS_Misc_Q4_27_Sqrt(int32_t a);*/
+extern int32_t DXS_Misc_Float_to_Q4_27 (float f);
+extern float DXS_Misc_Q4_27_to_Float (int32_t q);
+extern int32_t DXS_Misc_Q4_27_Mul (int32_t a, int32_t b);
+/******************************************************************************/
+/*               Fixed Point Calculations in Q15.16 format                    */
+/******************************************************************************/
+#define Q15_16_ONE    (1 << 16)
+#define Q15_16_HALF   (Q15_16_ONE >> 1)
+#define Q15_16_TEN    (10 * Q15_16_ONE)
+#define Q15_16_TWENTY (2 * Q15_16_TEN)
+#define Q15_16__3_14  0x323D7
+extern int32_t DXS_Misc_Float_to_Q15_16 (float f);
+extern float DXS_Misc_Q15_16_to_Float (int32_t q);
+extern int32_t DXS_Misc_Q15_16_Log10 (int32_t a);
+extern int32_t DXS_Misc_Q15_16_Mul(int32_t a, int32_t b);
+extern int32_t DXS_Misc_Q15_16_Div(int32_t a, int32_t b);
+/******************************************************************************/
+/*                        Other functions                                     */
+/******************************************************************************/
+extern void DXS_Misc_DataBlkRor (unsigned char* , int , int );
+
+#endif /* __DXS_MISC_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_outbox.c b/marvell/services/dxslic/api_lib/src/dxs_outbox.c
new file mode 100644
index 0000000..5a347f9
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_outbox.c
@@ -0,0 +1,918 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_outbox.c
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdio.h>
+#include <errno.h>
+
+#include "dxs_config.h"
+#include "dxs.h"
+#include "dxs_lib.h"
+#include "dxs_mbx.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_event.h"
+#include "dxs_sdd.h"
+#include "dxs_sig.h"
+#include "dxs_cid_fsk.h"
+#include "dxs_cid.h"
+#include "dxs_init.h"
+#include "dxs_dcdc_hw.h"
+#ifdef EVENT_LOGGER_DEBUG
+#include <sys/ioctl.h>
+#endif
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/*#define DXS_CMD_PRINT*/
+#undef DXS_CMD_PRINT
+//#define DXS_CMD_PRINT
+
+/* SDD events */
+/** Over temperature detected */
+#define EVT_SDD_OTEMP            0
+/** Line testing finished */
+#define EVT_SDD_LT_FIN           1
+/** Ground fault detected */
+#define EVT_SDD_GF               3
+/** Ground key detected */
+#define EVT_SDD_GK               4
+/** Opmode changed */
+#define EVT_SDD_OPC              5
+/** Error in command SDD_CoeffReadConfig */
+#define EVT_SDD_CORCE            6
+/** Error in command SDD_Coeff */
+#define EVT_SDD_COEFE            7
+/** On-hook */
+#define EVT_SDD_ONH              9
+/** Off-hook */
+#define EVT_SDD_OFFH             10
+/** Ground Fault Finished */
+#define EVT_SDD_GF_FIN           12
+/** Ground Key Finished */
+#define EVT_SDD_GK_FIN           13
+/** Overtemp finished which means that
+   SLIC temperature is back in normal range */
+#define EVT_SDD_OTEMP_FIN        14
+/** Operating Mode Ignored */
+#define EVT_SDD_OMI              17
+/** Operating Mode discarded */
+#define EVT_SDD_OPM_DIS          18
+/** Line testing aborted */
+#define EVT_SDD_LT_ABORT         19
+
+/* SIG events */
+/** DTMF detector */
+#define EVT_SIG_DTMF_DET       1
+/** Caller ID sender request */
+#define EVT_SIG_CIS_REQ        2
+/** Caller ID sender buffer underflow */
+#define EVT_SIG_CIS_BUF        3
+/** Caller ID sender has finished sending data */
+#define EVT_SIG_CIS_FIN        4
+/** Start of tone detected */
+#define EVT_SIG_UTD_START      5
+/** End of tone detected */
+#define EVT_SIG_UTD_END        6
+/** Metering pulse sent */
+#define EVT_SIG_TTX_FIN        9
+/** AC level metering finished */
+#define EVT_SIG_AC_LM_FIN      10
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+struct __fw_evt_header
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t Res00 : 3;
+   /* Command Type */
+   uint32_t CMD : 5;
+   /* Channel */
+   uint32_t CHAN : 8;
+   /* Command Mode */
+   uint32_t MOD : 3;
+   /* Command Sub-Mode */
+   uint32_t ECMD : 5;
+   /* Length of Command Payload */
+   uint32_t LENGTH : 8;
+#else
+   /* Length of Command Payload */
+   uint32_t LENGTH : 8;
+   /* Command Sub-Mode */
+   uint32_t ECMD : 5;
+   /* Command Mode */
+   uint32_t MOD : 3;
+   /* Channel */
+   uint32_t CHAN : 8;
+   /* Command Type */
+   uint32_t CMD : 5;
+   /* Reserved */
+   uint32_t Res00 : 3;
+#endif
+} __attribute__ ((packed));
+
+struct __fw_evt_int_err
+{
+   struct __fw_evt_header hdr;
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t Res01 : 27;
+   /* Event Code */
+   uint32_t ERREVT : 5;
+#else
+   /* Event Code */
+   uint32_t ERREVT : 5;
+   /* Reserved */
+   uint32_t Res01 : 27;
+#endif
+} __attribute__ ((packed));
+
+struct __fw_evt_cmd_err
+{
+   struct __fw_evt_header hdr;
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Reserved */
+   uint32_t Res01 : 18;
+   /* Error Cause */
+   uint32_t CMDERR : 14;
+   /* Command Header of Command */
+   uint32_t CMDHDR;
+#else
+   /* Error Cause */
+   uint32_t CMDERR : 14;
+   /* Reserved */
+   uint32_t Res01 : 18;
+   /* Command Header of Command */
+   uint32_t CMDHDR;
+#endif
+} __attribute__ ((packed));
+
+struct __fw_evt_sdd
+{
+   struct __fw_evt_header hdr;
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Time Stamp */
+   uint32_t TIME_STAMP : 16;
+   /* Analog line operating mode */
+   uint32_t OPMODE : 8;
+   /* Reserved */
+   uint32_t Res01 : 3;
+   /* Event code */
+   uint32_t EVT : 5;
+#else
+   /* Event code */
+   uint32_t EVT : 5;
+   /* Reserved */
+   uint32_t Res01 : 3;
+   /* Analog line operating mode */
+   uint32_t OPMODE : 8;
+   /* Time Stamp */
+   uint32_t TIME_STAMP : 16;
+#endif
+} __attribute__ ((packed));
+
+struct __fw_evt_sig
+{
+   struct __fw_evt_header hdr;
+#if __BYTE_ORDER == __BIG_ENDIAN
+   /* Time Stamp */
+   uint32_t TIME_STAMP : 16;
+   /* Reserved */
+   uint32_t Res01 : 4;
+   /*  DTMF Key */
+   uint32_t DTMF_KEY : 4;
+   /* Reserved */
+   uint32_t Res02 : 3;
+   /* Event code */
+   uint32_t SIGEVT : 5;
+#else
+   /* Event code */
+   uint32_t SIGEVT : 5;
+   /* Reserved */
+   uint32_t Res02 : 3;
+   /*  DTMF Key */
+   uint32_t DTMF_KEY : 4;
+   /* Reserved */
+   uint32_t Res01 : 4;
+   /* Time Stamp */
+   uint32_t TIME_STAMP : 16;
+#endif
+} __attribute__ ((packed));
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+#ifdef EVENT_LOGGER_DEBUG
+static void dxs_el_trace_event_read(DXS_DEVICE_t *pDev,
+                                    struct __fw_evt_header *pHdr)
+{
+   EL_IoctlAddLog_t stLog;
+   stLog.nLogType = EL_LOG_TYPE_EVT_MBX_RD;
+   stLog.nOrygLogType = EL_MAX_LOG_TYPE;
+   stLog.nDevType = DXS_LIB_DEV_TYPE;
+   stLog.nDevNum = pDev->nDevNum;
+   stLog.nChNum = pHdr->CHAN;
+   stLog.uLogDetails.stEvt_Mbx_Rd.nCmdLength = 4;
+   stLog.uLogDetails.stEvt_Mbx_Rd.nCount = pHdr->LENGTH + 4;
+   stLog.uLogDetails.stEvt_Mbx_Rd.nDataLength = pHdr->LENGTH;
+   stLog.uLogDetails.stEvt_Mbx_Rd.pCmd = (char*)pHdr;
+   if(pHdr->LENGTH == 0)
+   {
+      stLog.uLogDetails.stEvt_Mbx_Rd.pDATA = NULL;
+   }
+   else
+   {
+      stLog.uLogDetails.stEvt_Mbx_Rd.pDATA = (IFX_char_t*)((int16_t*) pHdr + 2);
+   }
+   ioctl(pDev->el_fd, EL_ADD_LOG, (int32_t)&stLog);
+}
+#endif
+
+/**
+   Dispatch raw off-hook event
+
+   \param   pCh    - pointer to DXS channel structure
+   \return  none
+*/
+static void dxs_evt_offhook_raw (DXS_CHANNEL_t *pCh)
+{
+   DXS_Event_t evt = {0};
+
+   evt.dev = pCh->pParent->nDevNum;
+   evt.ch = pCh->nCh;
+   evt.id = DXS_EVENT_FXS_RAW_OFFHOOK;
+   DXS_EventDispatch(pCh->pParent, &evt);
+}
+
+/**
+   Dispatch raw on-hook event
+
+   \param   pCh    - pointer to DXS channel structure
+   \return  none
+*/
+static void dxs_evt_onhook_raw (DXS_CHANNEL_t *pCh)
+{
+   DXS_Event_t evt = {0};
+
+   evt.dev = pCh->pParent->nDevNum;
+   evt.ch = pCh->nCh;
+   evt.id = DXS_EVENT_FXS_RAW_ONHOOK;
+   DXS_EventDispatch(pCh->pParent, &evt);
+}
+
+/**
+   Function dxs_cerr_ack
+
+   \param   pDev    - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_cerr_ack(DXS_DEVICE_t *pDev)
+{
+   uint32_t cerr_ack_cmd = 0x0600e000;
+
+   return DXS_CmdWrite(pDev, &cerr_ack_cmd);
+}
+
+/**
+   Function dxs_event_sdd
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pSddEvt - pointer to SDD event structure
+
+*/
+static void dxs_event_sdd(DXS_DEVICE_t *pDev, struct __fw_evt_sdd *pSddEvt)
+{
+   DXS_Event_t dxs_event = {0};
+   int32_t ret;
+   uint8_t nTmp;
+   DXS_CHANNEL_t *pCh = &pDev->pChannel[pSddEvt->hdr.CHAN];
+
+   dxs_event.dev = pDev->nDevNum;
+   dxs_event.ch = pSddEvt->hdr.CHAN;
+
+   switch (pSddEvt->EVT)
+   {
+      case EVT_SDD_OTEMP:
+         dxs_event.id = DXS_EVENT_OVERTEMP;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_OTEMP_FIN:
+         DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+         dxs_event.id = DXS_EVENT_OVERTEMP_END;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_LT_FIN:
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+         obx_DXS_SDD_OLCalibrationFinished(pCh, 0);
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+         dxs_event.id = DXS_EVENT_NLT_END;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_LT_ABORT:
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+         obx_DXS_SDD_OLCalibrationFinished(pCh, 1);
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+         dxs_event.id = DXS_EVENT_NLT_ABORT;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_GF:
+         dxs_event.id = DXS_EVENT_GROUND_FAULT;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_GF_FIN:
+         DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+         dxs_event.id = DXS_EVENT_GROUND_FAULT_END;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_GK:
+         dxs_event.id = DXS_EVENT_GROUND_KEY;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_GK_FIN:
+         dxs_event.id = DXS_EVENT_GROUND_KEY_END;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+
+      case EVT_SDD_OPC:
+      case EVT_SDD_OMI:
+         {
+            uint8_t opmode_changed = (pSddEvt->EVT == EVT_SDD_OPC) ? 1 : 0;
+
+            /*DXS_DCDC_HW_Lock(pCh);*/
+            obx_DXS_SDD_OpmodeUpdate(pCh, pSddEvt->OPMODE, opmode_changed);
+            /*DXS_DCDC_HW_UnLock(pCh);*/
+
+            /* For some OPC events more actions are needed */
+            if (opmode_changed)
+            {
+#ifdef DXS_FEAT_HSM
+               /* Set hook-state to ONHOOK if opmode was changed to disabled */
+               if (pSddEvt->OPMODE == DXS_LINE_FEED_DISABLED)
+               {
+#ifdef DXS_FEAT_CID
+                  if (DXS_CID_EventOpcDisabled(pCh))
+#endif
+                  {
+                     DXS_Dial_HookStateSetOnhook(pCh);
+                  }
+               }
+#endif
+               /* Calibration ends with an opmode change */
+               if (pSddEvt->OPMODE != DXS_LINE_FEED_CALIBRATE)
+               {
+                  ret = DXS_SDD_CalibrationRunningGet(pCh, &nTmp);
+                  /* if calibration was running, signal that it has finished */
+                  if (ret == DXS_statusOk && nTmp == 1)
+                     DXS_SDD_Calibration_Finish(pCh, &dxs_event);
+               }
+            }
+         }
+         break;
+
+      case EVT_SDD_CORCE:
+         break;
+      case EVT_SDD_COEFE:
+         break;
+      case EVT_SDD_ONH:
+         /* Report RAW on-hook */
+         dxs_evt_onhook_raw(pCh);
+#ifdef DXS_FEAT_CID
+         /* Report on-hook */
+         if (DXS_CID_EventOnhook(pCh, pSddEvt->TIME_STAMP))
+#endif
+         {
+#ifdef DXS_FEAT_HSM
+            DXS_Dial_HookEvent(pCh, 0, pSddEvt->TIME_STAMP);
+#else
+            dxs_event.id = DXS_EVENT_FXS_ONHOOK;
+            DXS_EventDispatch(pDev, &dxs_event);
+#endif
+         }
+         break;
+
+      case EVT_SDD_OFFH:
+         /* Report RAW off-hook */
+         dxs_evt_offhook_raw(pCh);
+#ifdef DXS_FEAT_FSK
+         /* Attempt to disable FSK generator */
+         DXS_FSK_Disable(pCh, 0);
+#endif
+#ifdef DXS_FEAT_CID
+         /* Report off-hook */
+         if (DXS_CID_EventOffhook(pCh, pSddEvt->TIME_STAMP))
+#endif
+         {
+#ifdef DXS_FEAT_HSM
+         DXS_Dial_HookEvent(pCh, 1, pSddEvt->TIME_STAMP);
+#else
+         dxs_event.id = DXS_EVENT_FXS_OFFHOOK;
+         DXS_EventDispatch(pDev, &dxs_event);
+#endif
+         }
+         break;
+
+      case EVT_SDD_OPM_DIS:
+         break;
+
+      default:
+         break;
+   }
+}
+
+/**
+   Function dxs_event_sig
+
+   \param   pDev    - pointer to DXS device structure
+   \param   pSigEvt - pointer to SIG event structure
+
+*/
+static void dxs_event_sig(DXS_DEVICE_t *pDev, struct __fw_evt_sig *pSigEvt)
+{
+   DXS_Event_t dxs_event = {0};
+#if defined (DXS_FEAT_CID) || defined (DXS_FEAT_UTD) || defined (DXS_FEAT_METERING) || defined (DXS_FEAT_ACMETER)
+   DXS_CHANNEL_t *pCh = &pDev->pChannel[pSigEvt->hdr.CHAN];
+#endif
+   dxs_event.dev = pDev->nDevNum;
+   dxs_event.ch = pSigEvt->hdr.CHAN;
+
+   switch (pSigEvt->SIGEVT)
+   {
+      case EVT_SIG_DTMF_DET:
+      {
+         dxs_event.id = DXS_EVENT_DTMF_DIGIT;
+         switch (pSigEvt->DTMF_KEY)
+         {
+            case 0x0:
+               dxs_event.data.dtmf.digit = 11;
+               dxs_event.data.dtmf.ascii = '0';
+               break;
+            case 0x1:
+            case 0x2:
+            case 0x3:
+            case 0x4:
+            case 0x5:
+            case 0x6:
+            case 0x7:
+            case 0x8:
+            case 0x9:
+               dxs_event.data.dtmf.digit = pSigEvt->DTMF_KEY;
+               dxs_event.data.dtmf.ascii = '0' + pSigEvt->DTMF_KEY;
+               break;
+            case 0xA:
+               dxs_event.data.dtmf.digit = 10;
+               dxs_event.data.dtmf.ascii = '*';
+               break;
+            case 0xB:
+               dxs_event.data.dtmf.digit = 12;
+               dxs_event.data.dtmf.ascii = '#';
+               break;
+            case 0xC:
+               dxs_event.data.dtmf.digit = 28;
+               dxs_event.data.dtmf.ascii = 'A';
+               break;
+            case 0xD:
+               dxs_event.data.dtmf.digit = 29;
+               dxs_event.data.dtmf.ascii = 'B';
+               break;
+            case 0xE:
+               dxs_event.data.dtmf.digit = 30;
+               dxs_event.data.dtmf.ascii = 'C';
+               break;
+            case 0xF:
+               dxs_event.data.dtmf.digit = 31;
+               dxs_event.data.dtmf.ascii = 'D';
+               break;
+            default:
+               break;
+         }
+#ifdef DXS_FEAT_CID
+         /* Report dtmf tone */
+         if (DXS_CID_EventDtmf(pCh, &dxs_event))
+#endif
+         {
+            DXS_EventDispatch(pDev, &dxs_event);
+            break;
+         }
+      }
+      break;
+
+#if defined(DXS_FEAT_FSK) || defined(DXS_FEAT_CID)
+      case EVT_SIG_CIS_REQ:
+         dxs_event.id = DXS_EVENT_CID_REQ_DATA;
+         DXS_EventDispatch(pDev, &dxs_event);
+#ifdef DXS_FEAT_CID
+         /* inform FSK state machine */
+         DXS_CID_FSK_EventInfo (pCh, DXS_CID_FSK_DATA_REQUEST);
+#endif /* DXS_FEAT_CID */
+         break;
+      case EVT_SIG_CIS_BUF:
+         dxs_event.id = DXS_EVENT_CID_BUF_UNDERFLOW;
+         DXS_EventDispatch(pDev, &dxs_event);
+#ifdef DXS_FEAT_CID
+         /* inform FSK state machine */
+         DXS_CID_FSK_EventInfo (pCh, DXS_CID_FSK_DATA_BUF);
+#endif /* DXS_FEAT_CID */
+         break;
+      case EVT_SIG_CIS_FIN:
+         dxs_event.id = DXS_EVENT_CID_END;
+         DXS_EventDispatch(pDev, &dxs_event);
+#ifdef DXS_FEAT_CID
+         /* inform FSK state machine */
+         DXS_CID_FSK_EventInfo (pCh, DXS_CID_FSK_DATA_FINISH);
+#endif /* DXS_FEAT_CID */
+         break;
+#endif /* DXS_FEAT_FSK || DXS_FEAT_CID */
+
+#ifdef DXS_FEAT_UTD
+      case EVT_SIG_UTD_START:
+         dxs_event.id = DXS_EVENT_TONE_DET_CPT;
+         dxs_event.data.tone_det.index = DXS_UTD_ToneIdxGet(pCh);
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+      case EVT_SIG_UTD_END:
+         dxs_event.id = DXS_EVENT_TONE_DET_CPT_END;
+         dxs_event.data.tone_det.index = DXS_UTD_ToneIdxGet(pCh);
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+#endif /* DXS_FEAT_UTD */
+
+#ifdef DXS_FEAT_METERING
+      case EVT_SIG_TTX_FIN:
+         obx_DXS_SIG_MeterPulseStatusClear(pCh);
+         dxs_event.id = DXS_EVENT_METERING_END;
+         DXS_EventDispatch(pDev, &dxs_event);
+         break;
+#endif /* DXS_FEAT_METERING */
+
+#ifdef DXS_FEAT_ACMETER
+      case EVT_SIG_AC_LM_FIN:
+         obx_DXS_SDD_ACLM_Finish(pCh);
+         break;
+#endif /* DXS_FEAT_ACMETER */
+
+      default:
+         break;
+   }
+}
+
+/**
+   Function dxs_handle_event
+
+   \param   pDev      Pointer to DXS device structure.
+   \param   pHdr      Pointer to __fw_evt_header structure.
+*/
+static void dxs_handle_event(DXS_DEVICE_t *pDev, struct __fw_evt_header *pHdr)
+{
+   /* Discard all events here while event handling is globally disabled. */
+   if (pDev->obxDiscardEvents != 0)
+   {
+#ifdef DXS_CMD_PRINT
+      /* The boot finished event has only one word all other two words. */
+      if (pHdr->MOD == 7 && pHdr->ECMD == 0)
+         fprintf (stderr, "[evt] dev:%d %08X          DISCARDED\n",
+                  pDev->nDevNum, *((uint32_t *)pHdr));
+      else
+         fprintf (stderr, "[evt] dev:%d %08X %08X DISCARDED\n", pDev->nDevNum,
+                  *((uint32_t *)pHdr), *((uint32_t *)pHdr + 1));
+#endif /* DXS_CMD_PRINT */
+      return;
+   }
+
+   if (pHdr->MOD == 7 && pHdr->ECMD == 0)
+   {
+      /* Boot Finished Event */
+
+      uint8_t  i;
+
+#ifdef DXS_CMD_PRINT
+      fprintf (stderr, "[evt] dev:%d %08X\n", pDev->nDevNum,
+               *((uint32_t *)pHdr));
+#endif /* DXS_CMD_PRINT */
+
+      /* clear flags and capabilities */
+      dxs_caps_vers_forget(pDev);
+      pDev->flags &= ~DXS_DEV_PRAM_PATCH_DOWNLOADED;
+      for (i=0; i<CH_PER_DEVICE; i++)
+      {
+         DXS_CHANNEL_t *pCh = &pDev->pChannel[i];
+
+         pCh->flags &= ~DXS_CH_BBD_DOWNLOADED;
+      }
+
+      if (pDev->bWaitingInPatchDwld)
+      {
+         sem_post(&pDev->mtxPatchDwld);
+         pDev->bWaitingInPatchDwld = 0;
+      }
+      else
+      {
+         /* FW crash */
+
+         DXS_Event_t dxs_event = {0};
+
+         dxs_event.dev = pDev->nDevNum;
+         dxs_event.ch = 0;
+         dxs_event.id = DXS_EVENT_FAULT_FW_WATCHDOG;
+         DXS_EventDispatch(pDev, &dxs_event);
+      }
+   }
+
+   if (pHdr->MOD == 7 && pHdr->ECMD == 11)
+   {
+      /* Internal Error Event */
+
+#ifdef DXS_CMD_PRINT
+      fprintf (stderr, "[evt] dev:%d %08X %08X\n", pDev->nDevNum,
+               *((uint32_t *)pHdr), *((uint32_t *)pHdr + 1));
+#endif /* DXS_CMD_PRINT */
+   }
+   else if (pHdr->MOD == 7 && pHdr->ECMD == 2)
+   {
+      /* Command Error Event */
+
+      struct __fw_evt_cmd_err *pCerr = (struct __fw_evt_cmd_err *)pHdr;
+      DXS_Event_t dxs_event = {0};
+
+#ifdef DXS_CMD_PRINT
+      fprintf (stderr, "[evt] dev:%d %08X %08X %08X\n", pDev->nDevNum,
+               *((uint32_t *)pHdr), *((uint32_t *)pHdr + 1),
+               *((uint32_t *)pHdr + 2));
+#endif /* DXS_CMD_PRINT */
+
+      /* acknowledge command error */
+      dxs_cerr_ack(pDev);
+
+      dxs_event.dev = pDev->nDevNum;
+      dxs_event.id = DXS_EVENT_DEBUG_CERR;
+      dxs_event.data.cerr.reason = pCerr->CMDERR;
+      dxs_event.data.cerr.command = pCerr->CMDHDR;
+      DXS_EventDispatch(pDev, &dxs_event);
+   }
+   else if (pHdr->MOD == 1 && pHdr->ECMD == 4)
+   {
+      /* SDD Event */
+
+#ifdef DXS_CMD_PRINT
+      fprintf (stderr, "[evt] dev:%d %08X %08X\n", pDev->nDevNum,
+               *((uint32_t *)pHdr), *((uint32_t *)pHdr + 1));
+#endif /* DXS_CMD_PRINT */
+
+      dxs_event_sdd(pDev, (struct __fw_evt_sdd *)pHdr);
+   }
+   else if (pHdr->MOD == 1 && pHdr->ECMD == 5)
+   {
+      /* Signaling Event */
+
+#ifdef DXS_CMD_PRINT
+      fprintf (stderr, "[evt] dev:%d %08X %08X\n", pDev->nDevNum,
+               *((uint32_t *)pHdr), *((uint32_t *)pHdr + 1));
+#endif /* DXS_CMD_PRINT */
+
+      dxs_event_sig(pDev, (struct __fw_evt_sig *)pHdr);
+   }
+}
+
+/**
+   Function dxs_outbox_handler
+
+   \param   arg    - pointer to device
+
+*/
+static void *dxs_outbox_handler (void *arg)
+{
+   DXS_DEVICE_t *pDev = (DXS_DEVICE_t *)arg;
+
+   while (pDev->obxThreadStop == 0)
+   {
+      uint8_t  words16, words32, msg_len/*in 32-bit words*/, tmp,
+               words32_remaining;
+      /* 16 bit index points to the header of message that has been read out */
+      uint8_t pos1;
+      int32_t ret;
+
+      ret = sem_wait (&pDev->obxSemaphore);
+      if (ret == EINTR)
+         pthread_exit((void *)DXS_statusOk);
+
+      /* TODO:- take additional mutex (trylock ???) - concurrency with CmdRead() */
+      /* TODO: check if SPI works */
+
+      /* read the outbox */
+      DXS_ObxRead(pDev, pDev->dmbx, &words16);
+
+      if (words16 == 0)
+      {
+         continue;
+      }
+      if (words16 & 1)
+      {
+         /* TODO: is this an error ? */
+         fprintf (stderr, "OutMbx: Odd word count: %d\n", words16);
+         continue;
+      }
+
+      words32_remaining = words32 = words16 >> 1;
+      pos1 = 0;
+
+      while ((pos1/2) < words32)
+      {
+         struct __fw_evt_header *pHdr = (struct __fw_evt_header *)(pDev->dmbx+pos1);
+         uint8_t attempts = 0, out_of_sync = 0;
+
+         /* get the length of the message in 32-bit words */
+         msg_len = (pHdr->LENGTH + sizeof(struct __fw_evt_header)) >> 2;
+
+         while (msg_len > words32_remaining)
+         {
+            /* read 2nd segment */
+
+            /* read the outbox again */
+            DXS_ObxRead(pDev, pDev->dmbx + words16, &tmp);
+
+            /* here we don't expect that nothing is read */
+
+            words16 += tmp;
+            words32 = words16 >> 1;
+            words32_remaining += (tmp >> 1);
+
+            if (++attempts == 3)
+            {
+               out_of_sync = 1;
+               break;
+            }
+         }
+
+         if (out_of_sync)
+         {
+            int32_t i;
+            fprintf (stderr, "Mailbox out of sync.\n");
+            /* print the read buffer */
+            fprintf (stderr, "READ BUFFER:\n");
+            for (i=0; i<(sizeof(pDev->dmbx)>>1); i+=2)
+               fprintf (stderr, "%02d: %04X %04X\n", i, pDev->dmbx[i], pDev->dmbx[i+1]);
+            fprintf (stderr, "pos=%02d\n", pos1);
+            break;
+         }
+
+         /* decode message, buffer it, advance to the next */
+         if (pHdr->Res00 == 0 &&
+             pHdr->CMD == 9 &&
+             (pHdr->MOD == 1 || pHdr->MOD == 7) &&
+             (pHdr->LENGTH == 0 || pHdr->LENGTH == 4 || pHdr->LENGTH == 8))
+         {
+#ifdef EVENT_LOGGER_DEBUG
+            dxs_el_trace_event_read(pDev, pHdr);
+#endif
+
+            /* this is an event header */
+            dxs_handle_event(pDev, pHdr);
+         }
+         else
+         {
+            /* this is a command header */
+            int i;
+            uint32_t *pw32;
+
+            for (i=0, pw32 = (uint32_t *)pHdr; i<msg_len; i++, pw32++)
+            {
+               fifo_put(pDev->cmd_obx_queue, NULL, *pw32);
+            }
+            sem_post(&pDev->obxCmdDataSem);
+         }
+
+         pos1 += (msg_len * 2);
+         words32_remaining -= msg_len;
+
+         /* This implementation works in IRQ edge mode. */
+#if 0
+         /* If the IRQ is edge triggered we have to make sure that the
+            mailbox is empty when we exit the loop. There won't be another IRQ
+            generated if there is still data left in outbox. */
+         if (pos1 >= words16)
+         {
+            DXS_ObxRead(pDev, pDev->dmbx, &words16);
+            if (words16 == 0)
+               break;
+            if (words16 & 1)
+            {
+               /* TODO: is this an error ? */
+               fprintf (stderr, "OutMbx: Odd word count: %d\n", words16);
+               break;
+            }
+            words32 = words16 >> 1;
+            pos1 = 0;
+         }
+#endif
+      }
+   }
+   pthread_exit((void *)DXS_statusOk);
+}
+
+/**
+   Function dxs_outbox_handler_init
+
+   \param   pDev    - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_outbox_handler_init(DXS_DEVICE_t *pDev)
+{
+   int32_t ret;
+
+   sem_init(&pDev->obxSemaphore, 0, 0);
+   sem_init(&pDev->obxCmdDataSem, 0, 0);
+
+   pDev->obxThreadStop = 0;
+   pDev->obxDiscardEvents = 1;
+
+   ret = pthread_create(&pDev->obxThread, NULL, dxs_outbox_handler, (void *)pDev);
+   if (ret)
+   {
+      /* error code */
+      DXS_RETURN(DXS_statusThreadCreatError);
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_outbox_handler_exit
+
+   \param   pDev    - pointer to DXS device structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_outbox_handler_exit(DXS_DEVICE_t *pDev)
+{
+   int32_t ret;
+   void *status;
+
+   /* condition to stop */
+   pDev->obxThreadStop = 1;
+
+   /* let the thread run */
+   sem_post (&pDev->obxSemaphore);
+
+   /* wait for the thread to exit */
+   ret = pthread_join(pDev->obxThread, &status);
+   if (ret || status != DXS_statusOk)
+   {
+      /* error code */
+      DXS_RETURN(DXS_statusThreadStopError);
+   }
+
+   sem_destroy(&pDev->obxSemaphore);
+   sem_destroy(&pDev->obxCmdDataSem);
+
+   return ret;
+}
+
+/**
+   Function dxs_outbox_handler_enable
+
+   This enables the event handling. After init the outbox is processed but
+   events are discarded until this function is called.
+
+   \param   pDev    - pointer to DXS device structure
+*/
+void dxs_outbox_handler_enable(DXS_DEVICE_t *pDev)
+{
+   /* From now on process all events. */
+   pDev->obxDiscardEvents = 0;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_outbox.h b/marvell/services/dxslic/api_lib/src/dxs_outbox.h
new file mode 100644
index 0000000..a8f2022
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_outbox.h
@@ -0,0 +1,37 @@
+#ifndef __DXS_OUTBOX_H__
+#define __DXS_OUTBOX_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_outbox.h
+   Miscellaneous functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int32_t dxs_outbox_handler_exit(DXS_DEVICE_t *pDev);
+extern void dxs_outbox_handler_enable(DXS_DEVICE_t *pDev);
+extern int32_t dxs_outbox_handler_init(DXS_DEVICE_t *pDev);
+#endif /* __DXS_OUTBOX_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_pcm.c b/marvell/services/dxslic/api_lib/src/dxs_pcm.c
new file mode 100644
index 0000000..703d5af
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_pcm.c
@@ -0,0 +1,516 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_pcm.c
+   Implementation of PCM functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_FW_PCM_IF_BIT_OFF_MAX   7
+#define DXS_FW_PCM_CH_CODEC_LINEAR  0
+#define DXS_FW_PCM_CH_CODEC_G711A   2
+#define DXS_FW_PCM_CH_CODEC_G711U   3
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** Data structure for PCM interface configuration firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Enable */
+   uint32_t EN : 1;
+   /** Data Streaming Enable */
+   uint32_t DS : 1;
+   /** Reserved */
+   uint32_t Res02 : 3;
+   /** Transmit Bit Offset */
+   uint32_t XOFF : 3;
+   /** Double Bit Clock */
+   uint32_t DBL : 1;
+   /** Transmit Slope */
+   uint32_t XS : 1;
+   /** Receive Slope */
+   uint32_t RS : 1;
+   /** Bit 0 Drive Length */
+   uint32_t DRV0 : 1;
+   /** Shift Control */
+   uint32_t SH : 1;
+   /** Receive Bit Offset */
+   uint32_t ROFF : 3;
+   /** Reserved */
+   uint32_t Res03 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res03 : 16;
+   /** Receive Bit Offset */
+   uint32_t ROFF : 3;
+   /** Shift Control */
+   uint32_t SH : 1;
+   /** Bit 0 Drive Length */
+   uint32_t DRV0 : 1;
+   /** Receive Slope */
+   uint32_t RS : 1;
+   /** Transmit Slope */
+   uint32_t XS : 1;
+   /** Double Bit Clock */
+   uint32_t DBL : 1;
+   /** Transmit Bit Offset */
+   uint32_t XOFF : 3;
+   /** Reserved */
+   uint32_t Res02 : 3;
+   /** Data Streaming Enable */
+   uint32_t DS : 1;
+   /** Enable */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_PCM_IF_t;
+#define DXS_FW_PCM_IF_ECMD    0
+#define DXS_FW_PCM_IF_LENGTH  4
+
+/** Data structure for PCM channel activation firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Enable */
+   uint32_t EN : 1;
+   /** Coder */
+   uint32_t COD : 3;
+   /** Wideband 16 kHz */
+   uint32_t WIDE : 1;
+   /** Wide Band PCM Time Slot Configuration Bit */
+   uint32_t WBTSC : 1;
+   /** Reserved */
+   uint32_t Res02 : 11;
+   /** Transmit Highway Time Slot */
+   uint32_t XTS : 7;
+   /** Reserved */
+   uint32_t Res03 : 1;
+   /** Receive Highway Time Slot */
+   uint32_t RTS : 7;
+#else
+   CMD_HEAD_LE;
+   /** Receive Highway Time Slot */
+   uint32_t RTS : 7;
+   /** Reserved */
+   uint32_t Res03 : 1;
+   /** Transmit Highway Time Slot */
+   uint32_t XTS : 7;
+   /** Reserved */
+   uint32_t Res02 : 11;
+   /** Wide Band PCM Time Slot Configuration Bit */
+   uint32_t WBTSC : 1;
+   /** Wideband 16 kHz */
+   uint32_t WIDE : 1;
+   /** Coder */
+   uint32_t COD : 3;
+   /** Enable */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_PCM_CH_t;
+#define DXS_FW_PCM_CH_ECMD    1
+#define DXS_FW_PCM_CH_LENGTH  4
+
+/** Data structure for PCM channel mute firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Reserved */
+   uint32_t Res02 : 31;
+   /** Mute of RX Direction */
+   uint32_t RX_MUTE : 1;
+#else
+   CMD_HEAD_LE;
+   /** Mute of RX Direction */
+   uint32_t RX_MUTE : 1;
+   /** Reserved */
+   uint32_t Res02 : 31;
+#endif
+} __attribute__ ((packed)) DXS_FW_PCM_CH_MUTE_t;
+#define DXS_FW_PCM_CH_MUTE_ECMD    4
+#define DXS_FW_PCM_CH_MUTE_LENGTH  4
+
+/** Data structure for PCM device resource */
+typedef struct
+{
+   /** status flag */
+   uint32_t         flag;
+#define PCM_DEV_INITIALIZED  1
+   /**  PCM Interface Control firmware message */
+   DXS_FW_PCM_IF_t pcm_if;
+} DXS_PCM_Dev_Resource_t;
+
+/** Data structure for PCM channel resource */
+typedef struct
+{
+   /** status flag */
+   uint32_t         flag;
+#define PCM_CH_INITIALIZED   1
+   /**  PCM Channel Control firmware message */
+   DXS_FW_PCM_CH_t pcm_ch;
+   /**  PCM Channel Mute firmware message */
+   DXS_FW_PCM_CH_MUTE_t pcm_ch_mute;
+} DXS_PCM_Ch_Resource_t;
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static DXS_PCM_Dev_Resource_t pcm_devs[DXS_MAX_DEVICES] = {0};
+static DXS_PCM_Ch_Resource_t  pcm_chan[DXS_MAX_DEVICES * CH_PER_DEVICE] = {0};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+/**
+   Function dxs_pcm_dev_init
+
+   \param   devnum  - device number
+
+*/
+void *dxs_pcm_dev_init(uint8_t devnum)
+{
+   DXS_PCM_Dev_Resource_t *p;
+
+   if (devnum >= DXS_MAX_DEVICES)
+      return (void *)NULL;
+
+   p = &pcm_devs[devnum];
+
+   p->flag = 0;
+
+   p->pcm_if.CMD = CMD_EOP;
+   p->pcm_if.MOD = MOD_SDD_PCM;
+   p->pcm_if.ECMD = DXS_FW_PCM_IF_ECMD;
+   p->pcm_if.LENGTH = DXS_FW_PCM_IF_LENGTH;
+   /* DS bit should always be set to one (= double buffer) */
+   p->pcm_if.DS = 1;
+
+   p->flag |= PCM_DEV_INITIALIZED;
+
+   return (void *)p;
+}
+
+/**
+   Function dxs_pcm_ch_init
+
+   \param   dev - device number
+   \param   ch  - channel number
+
+*/
+void *dxs_pcm_ch_init(uint8_t dev, uint8_t ch)
+{
+   DXS_PCM_Ch_Resource_t  *p;
+
+   if (dev >= DXS_MAX_DEVICES || ch >= CH_PER_DEVICE)
+      return (void *)NULL;
+
+   p = &pcm_chan[dev * CH_PER_DEVICE + ch];
+
+   p->flag = 0;
+
+   p->pcm_ch.CMD = CMD_EOP;
+   p->pcm_ch.MOD = MOD_SDD_PCM;
+   p->pcm_ch.ECMD = DXS_FW_PCM_CH_ECMD;
+   p->pcm_ch.LENGTH = DXS_FW_PCM_CH_LENGTH;
+   p->pcm_ch.CHAN = ch;
+
+   p->pcm_ch_mute.CMD = CMD_EOP;
+   p->pcm_ch_mute.MOD = MOD_SDD_PCM;
+   p->pcm_ch_mute.ECMD = DXS_FW_PCM_CH_MUTE_ECMD;
+   p->pcm_ch_mute.LENGTH = DXS_FW_PCM_CH_MUTE_LENGTH;
+   p->pcm_ch_mute.CHAN = ch;
+
+   p->flag |= PCM_CH_INITIALIZED;
+
+   return (void *)p;
+}
+
+/**
+   Function dxs_pcm_if_config
+
+   \param pDev - pointer to DXS device structure
+   \param xoff - transmit bit offset
+   \param dbl  - double bit clock
+   \param xs   - transmit slope
+   \param rs   - receive slope
+   \param drv0 - bit 0 drive length
+   \param sh   - shift control
+   \param roff - receive bit offset
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_pcm_if_config(DXS_DEVICE_t *pDev, uint8_t xoff, uint8_t dbl,
+                          uint8_t xs, uint8_t rs, uint8_t drv0, uint8_t sh,
+                          uint8_t roff)
+{
+   DXS_PCM_Dev_Resource_t *p;
+   int32_t err;
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_PCM_Dev_Resource_t *)pDev->pcm;
+
+   if (!(p->flag & PCM_DEV_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* parameter sanity check */
+   if (xoff > DXS_FW_PCM_IF_BIT_OFF_MAX || roff > DXS_FW_PCM_IF_BIT_OFF_MAX ||
+       dbl > 1 || xs > 1 || rs > 1 || drv0 > 1 || sh > 1)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   if (p->pcm_if.EN == 1)
+   {
+      uint8_t ch;
+
+      /* check if there are active channels */
+      for (ch = 0; ch < pDev->nChannels; ch++)
+      {
+         DXS_PCM_Ch_Resource_t *pPcmChRes =
+               (DXS_PCM_Ch_Resource_t *)pDev->pChannel[ch].pcm;
+
+         if ((pPcmChRes->flag & PCM_CH_INITIALIZED) && pPcmChRes->pcm_ch.EN == 1)
+         {
+            /* error code - there are active PCM timeslots on this highway */
+            DXS_RETURN(DXS_statusPcmChNotDisabled);
+         }
+      }
+
+      p->pcm_if.EN = 0;
+      err = CmdWrite(pDev, (uint32_t *)&p->pcm_if);
+      if (err)
+      {
+         DXS_RETURN(DXS_statusPcmIfActError);
+      }
+   }
+
+   p->pcm_if.XOFF = xoff;
+   p->pcm_if.DBL = dbl;
+   p->pcm_if.XS = xs;
+   p->pcm_if.RS = rs;
+   p->pcm_if.DRV0 = drv0;
+   p->pcm_if.SH = sh;
+   p->pcm_if.ROFF = roff;
+   p->pcm_if.EN = 1;
+
+   err = CmdWrite(pDev, (uint32_t *)&p->pcm_if);
+   if (err)
+   {
+      DXS_RETURN(DXS_statusPcmIfActError);
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_pcm_ch_act
+
+   \param pCh   - pointer to DXS channel structure
+   \param line  - line number
+   \param wb    - wideband
+   \param wbtsc - wideband PCM time slot configuration
+   \param codec - codec
+   \param xts   - transmit highway time slot
+   \param rts   - receive highway time slot
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_pcm_ch_act(DXS_CHANNEL_t *pCh, uint8_t wb, uint8_t wbtsc,
+                       uint8_t codec, uint8_t xts, uint8_t rts)
+{
+   DXS_PCM_Ch_Resource_t *p;
+   DXS_PCM_Dev_Resource_t *pPcmDevRes;
+   int32_t err;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_PCM_Ch_Resource_t *)pCh->pcm;
+
+   if (!(p->flag & PCM_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   pPcmDevRes = (DXS_PCM_Dev_Resource_t *)pCh->pParent->pcm;
+   if (pPcmDevRes->pcm_if.EN != 1)
+   {
+      /* error code - PCM interface is not enabled */
+      DXS_RETURN(DXS_statusPcmIfNotEnabled);
+   }
+
+   /* parameter sanity check */
+   if (wb > 1 || wbtsc > 1 ||
+       (codec != DXS_FW_PCM_CH_CODEC_LINEAR &&
+        codec != DXS_FW_PCM_CH_CODEC_G711A &&
+        codec != DXS_FW_PCM_CH_CODEC_G711U))
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   if (p->pcm_ch.EN == 1)
+   {
+      if (p->pcm_ch.COD != codec || p->pcm_ch.WIDE != wb ||
+          p->pcm_ch.WBTSC != wbtsc || p->pcm_ch.XTS != xts || p->pcm_ch.RTS != rts)
+      {
+         p->pcm_ch.EN = 0;
+         err = CmdWrite(pCh->pParent, (uint32_t *)&p->pcm_ch);
+         if (err)
+         {
+            DXS_RETURN(DXS_statusPcmChActError);
+         }
+      }
+      else
+      {
+         /* parameters aren't changed */
+         return DXS_statusOk;
+      }
+   }
+
+   p->pcm_ch.COD = codec;
+   p->pcm_ch.WIDE = wb;
+   p->pcm_ch.WBTSC = wbtsc;
+   p->pcm_ch.XTS = xts;
+   p->pcm_ch.RTS = rts;
+   /* always set EN bit */
+   p->pcm_ch.EN = 1;
+
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->pcm_ch);
+   if (err)
+   {
+      DXS_RETURN(DXS_statusPcmChActError);
+   }
+
+   /* unmute Rx direction implicitly */
+   if (p->pcm_ch_mute.RX_MUTE)
+   {
+      p->pcm_ch_mute.RX_MUTE = 0;
+
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->pcm_ch_mute);
+      if (err)
+      {
+         DXS_RETURN(DXS_statusPcmChActError);
+      }
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_pcm_ch_deact
+
+   \param pCh   - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_pcm_ch_deact(DXS_CHANNEL_t *pCh)
+{
+   DXS_PCM_Ch_Resource_t *p;
+   int32_t err;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_PCM_Ch_Resource_t *)pCh->pcm;
+
+   if (!(p->flag & PCM_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (p->pcm_ch.EN == 0)
+   {
+      /* already deactivated */
+      return DXS_statusOk;
+   }
+
+   p->pcm_ch.EN = 0;
+
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->pcm_ch);
+   if (err)
+   {
+      DXS_RETURN(DXS_statusPcmChActError);
+   }
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_pcm_ch_mute
+
+   \param pCh    - pointer to DXS channel structure
+   \param action - action mute/unmute
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_pcm_ch_mute(DXS_CHANNEL_t *pCh, uint8_t action)
+{
+   DXS_PCM_Ch_Resource_t *p;
+   int32_t err;
+
+   if (pCh == NULL || action > 1)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_PCM_Ch_Resource_t *)pCh->pcm;
+
+   if (!(p->flag & PCM_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (p->pcm_ch_mute.RX_MUTE == action)
+   {
+      /* parameters aren't changed */
+      return DXS_statusOk;
+   }
+
+   p->pcm_ch_mute.RX_MUTE = action;
+
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->pcm_ch_mute);
+   if (err)
+   {
+      DXS_RETURN(DXS_statusPcmChMuteError);
+   }
+
+   return DXS_statusOk;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_pcm.h b/marvell/services/dxslic/api_lib/src/dxs_pcm.h
new file mode 100644
index 0000000..b3a0353
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_pcm.h
@@ -0,0 +1,45 @@
+#ifndef __DXS_PCM_H__
+#define __DXS_PCM_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_pcm.h
+   PCM functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern void *dxs_pcm_dev_init(uint8_t devnum);
+extern void *dxs_pcm_ch_init(uint8_t dev, uint8_t ch);
+extern int32_t dxs_pcm_if_config(DXS_DEVICE_t *pDev, uint8_t xoff, uint8_t dbl,
+                                  uint8_t xs, uint8_t rs, uint8_t drv0,
+                                  uint8_t sh, uint8_t roff);
+extern int32_t dxs_pcm_ch_act(DXS_CHANNEL_t *pCh, uint8_t wb, uint8_t wbtsc,
+                              uint8_t codec, uint8_t xts, uint8_t rts);
+extern int32_t dxs_pcm_ch_deact(DXS_CHANNEL_t *pCh);
+extern int32_t dxs_pcm_ch_mute(DXS_CHANNEL_t *pCh, uint8_t action);
+
+#endif /* __DXS_PCM_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_pollint.c b/marvell/services/dxslic/api_lib/src/dxs_pollint.c
new file mode 100644
index 0000000..9697868
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_pollint.c
@@ -0,0 +1,272 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_pollint.c
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdint.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <pthread.h>
+#include <sched.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "dxs_init.h"
+#include "dxs_config.h"
+#include "dxs_error.h"
+#include "dxs_pollint.h"
+#include "irq_handler/dxs_irq.h"
+#include "dxs_access.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_SHARED_INTERRUPT
+/*#undef DXS_SHARED_INTERRUPT*/
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static timer_t gPollTimerId;
+static uint8_t timer_use = 0;
+static pthread_t gInterruptThread;
+static volatile int gInterruptThreadStop = 0;
+static int gInterruptFD = -1;
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Function dxs_poll_devices
+*/
+static void dxs_poll_devices()
+{
+   uint8_t dev;
+   DXS_DEVICE_t *pDev;
+
+   for (dev=0; dev<DXS_MAX_DEVICES; dev++)
+   {
+      pDev = dxs_get_dev (dev);
+      DXS_StatusGet(pDev);
+   }
+}
+
+/**
+   Function dxs_polling_timer_start
+*/
+void dxs_polling_timer_start()
+{
+   if (!timer_use)
+   {
+      struct itimerspec value;
+
+      (void) signal(SIGALRM, dxs_poll_devices);
+
+      value.it_value.tv_sec = 0;
+      value.it_value.tv_nsec = DXS_POLLING_INTERVAL_MS * 1000000;
+      value.it_interval.tv_sec = 0;
+      value.it_interval.tv_nsec = DXS_POLLING_INTERVAL_MS * 1000000;
+      timer_create (CLOCK_REALTIME, NULL, &gPollTimerId);
+      timer_settime (gPollTimerId, 0, &value, NULL);
+   }
+
+   timer_use++;
+}
+
+/**
+   Function dxs_polling_timer_stop
+*/
+void dxs_polling_timer_stop()
+{
+   timer_use--;
+
+   if (!timer_use)
+   {
+      struct itimerspec value;
+
+      value.it_value.tv_sec = 0;
+      value.it_value.tv_nsec = 0;
+      value.it_interval.tv_sec = 0;
+      value.it_interval.tv_nsec = 0;
+      timer_settime (gPollTimerId, 0, &value, NULL);
+      timer_delete (gPollTimerId);
+   }
+}
+
+/* definition of dxs_int_client() */
+/* - open /dev/dxs
+ * - prepare select
+ * - while (1) {
+ * -    sleep on select()
+ * -    when woken up, call dxs_poll_devices()
+ * - }
+ */
+
+
+/**
+   Function dxs_interrupt_handler
+
+   \param   arg    - unused
+
+*/
+static void *dxs_interrupt_handler (void *arg)
+{
+   fd_set readfds;
+   int ret, dev;
+
+   FD_ZERO(&readfds);
+   while (gInterruptThreadStop == 0)
+   {
+      FD_SET(gInterruptFD, &readfds);
+      ret = select (gInterruptFD + 1, &readfds, NULL, NULL, NULL);
+      if (ret > 0)
+      {
+#if defined(DXS_SHARED_INTERRUPT)
+         ret = ioctl(gInterruptFD, DXS_INT_DEV_GET, &dev);
+         if (ret == 0)
+         {
+            dxs_poll_devices();
+
+            /* Outbox handling is finished. Release IRQ line. */
+            ioctl(gInterruptFD, DXS_INT_DEV_REL, &dev);
+         }
+#else
+         do
+         {
+            ret = ioctl(gInterruptFD, DXS_INT_DEV_GET, &dev);
+            if (ret == 0)
+            {
+               DXS_DEVICE_t *pDev = dxs_get_dev(dev);
+               if (pDev && (pDev->flags & DXS_DEV_OBX_HND_INITIALIZED))
+               {
+                  DXS_StatusGet(pDev);
+
+                  /* Outbox handling is finished. Release IRQ line. */
+                  ioctl(gInterruptFD, DXS_INT_DEV_REL, &dev);
+               }
+            }
+         } while (ret == 0 && dev != -1);
+#endif /* DXS_SHARED_INTERRUPT */
+      }
+   }
+   return NULL;
+}
+
+/**
+   Initialize interrupt handling code. Start interrupt handling thread,
+   configure interrupt number.
+
+   \param  pDev         pointer to the device interface
+   \return
+   Error code.
+*/
+int32_t dxs_interrupt_init (DXS_DEVICE_t *pDev)
+{
+   int32_t ret;
+   DXS_INT_CONF_t int_conf;
+   pthread_attr_t irq_thread_attr;
+
+   if (pDev->irqNumber == -1)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   if (gInterruptFD == -1)
+   {
+      gInterruptFD = open("/dev/" DXS_IRQ_NAME, O_RDWR);
+      if (gInterruptFD == -1)
+      {
+         DXS_RETURN(DXS_statusFdOpenError);
+      }
+
+      /* Set highest priority for IRQ thread handling */
+      pthread_attr_init(&irq_thread_attr);
+      pthread_attr_setschedpolicy(&irq_thread_attr, SCHED_RR);
+
+      ret = pthread_create(&gInterruptThread, &irq_thread_attr,
+                           dxs_interrupt_handler, NULL);
+      if (ret != 0)
+      {
+         close(gInterruptFD);
+         pthread_attr_destroy(&irq_thread_attr);
+         gInterruptFD = -1;
+         /* error code */
+         DXS_RETURN(DXS_statusThreadCreatError);
+      }
+      pthread_attr_destroy(&irq_thread_attr);
+#if defined(DXS_SHARED_INTERRUPT)
+      int_conf.dev = pDev->nDevNum;
+      int_conf.irq = pDev->irqNumber;
+      ret = ioctl(gInterruptFD, DXS_INT_CONF, &int_conf);
+      if (ret < 0)
+      {
+         DXS_RETURN(DXS_statusIntConfError);
+      }
+#endif
+   }
+#if !defined(DXS_SHARED_INTERRUPT)
+   int_conf.dev = pDev->nDevNum;
+   int_conf.irq = pDev->irqNumber;
+   ret = ioctl(gInterruptFD, DXS_INT_CONF, &int_conf);
+   if (ret < 0)
+   {
+      DXS_RETURN(DXS_statusIntConfError);
+   }
+#endif
+   return DXS_statusOk;
+}
+
+/**
+   Release interrupt handling code. Stop interrupt handling thread,
+   close interrupt handler driver file descriptor.
+
+   \param  none
+   \return
+   Error code.
+*/
+int32_t dxs_interrupt_exit (void)
+{
+   int32_t ret = DXS_statusOk;
+   void *status;
+
+   if (gInterruptFD != -1)
+   {
+      gInterruptThreadStop = 1;
+      /* wait for the thread to exit */
+      ret = pthread_join(gInterruptThread, &status);
+      if (ret || status != DXS_statusOk)
+      {
+         /* error code */
+         DXS_RETURN(DXS_statusThreadStopError);
+      }
+      close(gInterruptFD);
+      gInterruptFD = -1;
+   }
+   return ret;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_pollint.h b/marvell/services/dxslic/api_lib/src/dxs_pollint.h
new file mode 100644
index 0000000..c5885fa
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_pollint.h
@@ -0,0 +1,38 @@
+#ifndef __DXS_POLLINT_H__
+#define __DXS_POLLINT_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_pollint.h
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+extern int32_t dxs_interrupt_init (DXS_DEVICE_t *pDev);
+extern int32_t dxs_interrupt_exit (void);
+extern void dxs_polling_timer_stop(void);
+extern void dxs_polling_timer_start(void);
+#endif /* __DXS_POLLINT_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_ring.c b/marvell/services/dxslic/api_lib/src/dxs_ring.c
new file mode 100644
index 0000000..8ad1c68
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_ring.c
@@ -0,0 +1,754 @@
+/*******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, 2017, 2018 Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+*******************************************************************************/
+
+/**
+   \file dxs_ring.c
+   Function implementation for cadenced ringing.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <time.h>
+#include <errno.h>
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_sdd.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_misc.h"
+#include "dxs_ring.h"
+#include "dxs_dcdc_hw.h"
+#include "dxs_cid.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* total channel count */
+#define DXS_RING_CHANNELS         (DXS_MAX_DEVICES * CH_PER_DEVICE)
+#define RING_TIMER_INTERVAL_MS    50
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+typedef struct
+{
+#define RING_TIMER_STOPPED   0
+#define RING_TIMER_RUNNING   1
+   int32_t state;
+   sem_t sem;
+   pthread_t thr;
+   int32_t ret_val;
+   int32_t current_bit;
+   int32_t reset_bits;
+} dxs_ring_timer_t;
+
+typedef struct
+{
+#define RING_CADENCE_NOT_INIT  0
+#define RING_CADENCE_INIT      1
+#define RING_CADENCE_CID_ACT   2
+   int32_t flag;
+   DXS_CHANNEL_t *pCh;
+#define RING_POLARITY_NORMAL   0
+#define RING_POLARITY_REVERSE  1
+   int32_t polarity;
+#define RING_CAD_STATE_IDLE    0
+#define RING_CAD_STATE_RINGING 1
+#define RING_CAD_STATE_CID_DURING_RINGING 2
+#define RING_CAD_STATE_CID_PRIOR_TO_RINGING 3
+   volatile int32_t ring_cadence_state;
+#define RINGER_STATE_PAUSE     0
+#define RINGER_STATE_RINGING   1
+   int32_t ringer_state;
+   DXS_RingCadence_t cadence;
+   /* used only for
+      prior to ringing CID standards */
+   int32_t wait_counter;
+   int32_t current_bit;
+} dxs_ring_res_t;
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+static dxs_ring_timer_t reft = {0};
+static dxs_ring_res_t ring_cadence[DXS_RING_CHANNELS] = {0};
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Return the bit position of the ringing pulse number in a cadence
+
+   \param   pRes  - pointer to ringing cadence resource
+   \param   ring  - ringing pulse number starting from 0
+
+   \return
+   - bit position of the ringing pulse
+*/
+static int32_t dxs_ring_next_pos_get (dxs_ring_res_t *pRes, int32_t ring)
+{
+   int32_t bit=0, i=0, rpulse=0, ring_phase=0;
+
+   /* TODO: protection against infinite loop */
+
+   while (1)
+   {
+      if ((pRes->cadence.data[i >> 3] >> (7-(i%8))) & 1)
+      {
+         ring_phase = 1;
+         if (rpulse == ring)
+            break;
+      }
+      else
+      {
+         if (ring_phase)
+         {
+            ring_phase = 0;
+            ++rpulse;
+         }
+      }
+      ++bit;
+      if (++i == pRes->cadence.valid_bits)
+         i = 0;
+   }
+   return bit;
+}
+
+/**
+   Return the ringing cadence initial state; decision point
+   whether the CID sequence shall be used in the ringing cadence.
+
+   \param   pCh  - pointer to \ref DXS_CHANNEL_t
+
+   \return
+   - RING_CAD_STATE_CID_DURING_RINGING
+   - RING_CAD_STATE_CID_PRIOR_TO_RINGING
+   - RING_CAD_STATE_RINGING
+*/
+static int32_t dxs_ring_cad_initial_state (DXS_CHANNEL_t *pCh)
+{
+   int32_t  err, ret = RING_CAD_STATE_RINGING;
+   DXS_CID_Std_t cid_std;
+   DXS_CID_AS_t cid_as;
+
+   err = DXS_CID_StandardGet(pCh, &cid_std);
+   if (err == DXS_statusOk)
+   {
+      err = DXS_CID_AlertSigGet(pCh, &cid_as);
+   }
+
+   if (err == DXS_statusOk)
+   {
+      if (cid_as == DXS_CID_AS_NONE &&
+            (cid_std == DXS_CID_STD_TELCORDIA || cid_std == DXS_CID_STD_ETSI))
+      {
+         ret = RING_CAD_STATE_CID_DURING_RINGING;
+      }
+      else if (cid_as != DXS_CID_AS_NONE && cid_std != DXS_CID_STD_UNDEF)
+      {
+         ret = RING_CAD_STATE_CID_PRIOR_TO_RINGING;
+      }
+   }
+   return ret;
+}
+
+/**
+   Attempt to shift the ringing cadence so that the new cadence
+   fits into the limitation of IFB12CH8 HW - only two ring bursts
+   are possible at a time per DCDC.
+   1) The first available bit position for a cadence is searched -
+   where less than two rings are programmed for parallel channels.
+   2) The new cadence is bit shifted to the found position.
+   3) The  new shifted cadence is checked from shift position to the
+   end if there is no conflict of two parallel rings.
+   If step 1) or 3) fails, than the new cadence does not fit into
+   the ring matrix of a DCDC and an error will be returned.
+
+   \param   pointer to ringing resource context
+   \param   ringing cadence length in bytes
+   \return
+   the code from \ref DXS_status_t list
+*/
+static int32_t dxs_ifb12ch8_shift_cadence (dxs_ring_res_t *pRes, int32_t len)
+{
+   int i, pos=0, conflict=0, dcdc;
+   unsigned int max_bits;
+   uint8_t channels_per_dcdc;
+
+   dcdc = DXS_DCDC_HW_SharedDcDcNumberGet(pRes->pCh);
+   channels_per_dcdc = DXS_DCDC_HW_SharedDcDcChannelNumGet(pRes->pCh);
+
+   /* get maximum cadence length for a DCDC */
+   for (i=0, max_bits=0; i<channels_per_dcdc; i++)
+   {
+      DXS_CHANNEL_t *pCh = DXS_DCDC_HW_SharedDcDcChannelGet(dcdc, i);
+
+      if (pCh != NULL)
+      {
+         dxs_ring_res_t *p = (dxs_ring_res_t *)pCh->ring;
+
+         if (p->cadence.valid_bits > max_bits)
+            max_bits = p->cadence.valid_bits;
+      }
+   }
+
+   /* find the first available bit position for the cadence */
+   for (i=0; i<max_bits; i++)
+   {
+      int c = 0;
+      uint8_t bits=0,
+              my_bit = (pRes->cadence.data[i >> 3] >> (7-(i % 8))) & 1;
+
+      while (c < channels_per_dcdc)
+      {
+         DXS_CHANNEL_t *pCh = DXS_DCDC_HW_SharedDcDcChannelGet(dcdc, c);
+
+         if (pCh != NULL && pCh != pRes->pCh)
+         {
+            dxs_ring_res_t *p = (dxs_ring_res_t *)pCh->ring;
+
+            uint8_t bit = (p->cadence.data[i >> 3] >> (7-(i % 8))) & 1;
+            if (bit) ++bits;
+         }
+         ++c;
+      }
+      if (bits >= 2 && my_bit && !conflict)
+      {
+         conflict = 1;
+      }
+      else if (conflict && bits < 2)
+      {
+         pos = i;
+         conflict = 0;
+         break;
+      }
+   }
+
+   if (conflict)
+   {
+      DXS_RETURN(DXS_statusRingCadConfInvalid);
+   }
+
+   DXS_Misc_DataBlkRor(pRes->cadence.data, len, pos);
+
+   /* position for a cadence start is found, now check the rest
+      of the cadence for possible conflicts */
+   i = pos;
+   do
+   {
+      int c = 0;
+      uint8_t bits=0,
+              my_bit = (pRes->cadence.data[i >> 3] >> (7-(i % 8))) & 1;
+
+      while (c < channels_per_dcdc)
+      {
+         DXS_CHANNEL_t *pCh = DXS_DCDC_HW_SharedDcDcChannelGet(dcdc, c);
+
+         if (pCh != NULL && pCh != pRes->pCh)
+         {
+            dxs_ring_res_t *p = (dxs_ring_res_t *)pCh->ring;
+
+            uint8_t bit = (p->cadence.data[i >> 3] >> (7-(i % 8))) & 1;
+            if (bit) ++bits;
+         }
+         ++c;
+      }
+
+      if (bits >= 2 && my_bit)
+      {
+         DXS_RETURN(DXS_statusRingCadConfInvalid);
+      }
+
+      if (++i == pRes->cadence.valid_bits)
+         i = 0;
+   } while (i != pos);
+   return DXS_statusOk;
+}
+
+/**
+   Start the ringing pulse
+
+   \param   pointer to ringing resource context
+   \return
+   the code from \ref DXS_status_t list
+*/
+static int32_t dxs_ring_pulse_start (dxs_ring_res_t *pRes)
+{
+   int32_t ret = DXS_statusOk;
+
+   if (pRes->ring_cadence_state == RING_CAD_STATE_RINGING ||
+        pRes->ring_cadence_state == RING_CAD_STATE_CID_DURING_RINGING)
+   {
+      DXS_CHANNEL_t *pCh = pRes->pCh;
+
+      ret = DXS_SDD_LineModeSet(pCh, pRes->polarity ?
+                                DXS_LINE_FEED_RINGING_REVPOL :
+                                DXS_LINE_FEED_RING_BURST
+                               );
+      pRes->ringer_state = (DXS_statusOk == ret) ?
+                           RINGER_STATE_RINGING : RINGER_STATE_PAUSE;
+   }
+   return ret;
+}
+
+/**
+   Stop the ringing pulse
+
+   \param   pointer to ringing resource context
+   \return
+   the code from \ref DXS_status_t list
+*/
+static int32_t dxs_ring_pulse_stop (dxs_ring_res_t *pRes)
+{
+   int32_t ret = DXS_statusOk;
+
+   if (pRes->ring_cadence_state == RING_CAD_STATE_RINGING ||
+        pRes->ring_cadence_state == RING_CAD_STATE_CID_DURING_RINGING)
+   {
+      DXS_CHANNEL_t *pCh = pRes->pCh;
+
+      ret = DXS_SDD_LineModeSet(pCh, pRes->polarity ?
+                                DXS_LINE_FEED_ACTIVE_REVPOL :
+                                DXS_LINE_FEED_ACTIVE
+                               );
+      pRes->ringer_state = (DXS_statusOk == ret) ?
+                           RINGER_STATE_PAUSE : RINGER_STATE_RINGING;
+   }
+   return ret;
+}
+
+/**
+   Get current bit position for the ringing cadence
+
+   \param   pointer to ringing cadence resource context
+   \return  bit position
+*/
+static int32_t dxs_ring_cad_bit_position_get (dxs_ring_res_t *pRes)
+{
+   int32_t bit_pos;
+
+   if (pRes->pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      /* cadence bit position is global for all channels
+         in case of IFB12CH8 */
+      bit_pos = reft.current_bit;
+   }
+   else
+   {
+      /* cadence bit position is individual for each
+         channel in case of HW without ringing limitations */
+      bit_pos = pRes->current_bit;
+   }
+   return bit_pos;
+}
+
+/**
+   Ringing timer thread function
+
+   \param   pointer to ringing timer context
+   \return  none
+*/
+static void *ring_timer_thread (void *arg)
+{
+   int err;
+   dxs_ring_timer_t *p = (dxs_ring_timer_t *)arg;
+   struct timespec ts = {0};
+   unsigned long ns;
+
+   while (p->state == RING_TIMER_RUNNING)
+   {
+      int32_t i, bit_position = -1;
+
+      /* run through all channels, get ring cadence bit value for
+         each channel and execute appropriate action */
+      for (i=0; i<DXS_RING_CHANNELS; i++)
+      {
+         dxs_ring_res_t *pRes = &ring_cadence[i];
+         uint8_t *cad, ring;
+
+         if (!(pRes->flag & RING_CADENCE_INIT))
+            continue;
+
+         cad = pRes->cadence.data;
+         bit_position = dxs_ring_cad_bit_position_get(pRes);
+         /* get ring cadence bit value */
+         ring = (cad[bit_position >> 3] >> (7-(bit_position % 8))) & 1;
+
+         /* handle CID prior to ringing */
+         if (pRes->ring_cadence_state == RING_CAD_STATE_CID_PRIOR_TO_RINGING)
+         {
+            if (!pRes->wait_counter && !(pRes->flag & RING_CADENCE_CID_ACT))
+            {
+               pRes->flag |= RING_CADENCE_CID_ACT;
+               err = DXS_CID_TypeI_Play(pRes->pCh, DXS_CID_MSG_TYPE_CS,
+                                   DXS_CID_CALL_FROM_RING_SM);
+               if (err)
+               {
+                  DXS_ERROR_PUSH(err);
+               }
+            }
+            else
+               pRes->wait_counter--;
+         }
+
+         if (!ring && pRes->ringer_state == RINGER_STATE_RINGING)
+         {
+            /* RING OFF */
+            err = dxs_ring_pulse_stop(pRes);
+            if (err)
+            {
+               DXS_ERROR_PUSH(err);
+            }
+
+            /* handle CID during ringing */
+            if (pRes->ring_cadence_state == RING_CAD_STATE_CID_DURING_RINGING)
+            {
+               pRes->flag |= RING_CADENCE_CID_ACT;
+               err = DXS_CID_TypeI_Play(pRes->pCh, DXS_CID_MSG_TYPE_CS,
+                                   DXS_CID_CALL_FROM_RING_SM);
+               if (err)
+               {
+                  DXS_ERROR_PUSH(err);
+               }
+            }
+         }
+      }
+
+      if (bit_position == -1)
+      {
+         DXS_ERROR_PUSH(-1);
+         continue;
+      }
+
+      for (i=0; i<DXS_RING_CHANNELS; i++)
+      {
+         dxs_ring_res_t *pRes = &ring_cadence[i];
+         uint8_t *cad, ring;
+
+         if (!(pRes->flag & RING_CADENCE_INIT))
+            continue;
+
+         cad = pRes->cadence.data;
+         bit_position = dxs_ring_cad_bit_position_get(pRes);
+         /* get ring cadence bit value */
+         ring = (cad[bit_position >> 3] >> (7-(bit_position % 8))) & 1;
+
+         if (ring && pRes->ringer_state == RINGER_STATE_PAUSE)
+         {
+            int32_t reset_bits = (pRes->pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8) ?
+                                     p->reset_bits : pRes->cadence.valid_bits;
+            int32_t pos = ((bit_position + 1) >= reset_bits) ?
+                                  0 : (bit_position + 1);
+            int32_t ring_bits = 0;
+            uint8_t bit_val = ring;
+
+            /* skip execution of "short ring pulses",
+               ensure that ring pulse is at least 500ms long */
+            while (bit_val)
+            {
+               bit_val = (cad[pos >> 3] >> (7-(pos % 8))) & 1;
+               if (bit_val)
+                  ++ring_bits;
+
+               if (++pos == reset_bits)
+                  pos = 0;
+            }
+
+            if (ring_bits >= 10)
+            {
+               /* RING ON */
+               err = dxs_ring_pulse_start(pRes);
+               if (err)
+               {
+                  DXS_ERROR_PUSH(err);
+               }
+            }
+         }
+      }
+
+      /* wait 50ms */
+      clock_gettime (CLOCK_REALTIME, &ts);
+      ns = ts.tv_nsec + RING_TIMER_INTERVAL_MS * 1000 * 1000;
+      ts.tv_nsec = ns % (1000 * 1000 * 1000);
+      ts.tv_sec += ns / (1000 * 1000 * 1000);
+      while ((err = sem_timedwait(&p->sem, &ts)) == -1 && errno == EINTR)
+               continue;
+      if (err == -1 && errno != ETIMEDOUT)
+      {
+         p->ret_val = errno;
+         break;
+      }
+
+      /* update global bit position */
+      if (++p->current_bit == p->reset_bits)
+         p->current_bit = 0;
+
+      /* update individual bit positions per channel */
+      for (i=0; i<DXS_RING_CHANNELS; i++)
+      {
+         dxs_ring_res_t *pRes = &ring_cadence[i];
+
+         if (!(pRes->flag & RING_CADENCE_INIT))
+            continue;
+
+         if (pRes->ring_cadence_state != RING_CAD_STATE_CID_PRIOR_TO_RINGING)
+         {
+            if (++pRes->current_bit == pRes->cadence.valid_bits)
+               pRes->current_bit = 0;
+         }
+      }
+   }
+   pthread_exit((void *)(&p->ret_val));
+}
+
+/**
+   Start the ringing timer
+
+   \param   none
+   \return
+   the code from \ref DXS_status_t list
+*/
+static int32_t ring_timer_start (void)
+{
+   int32_t ret = DXS_statusOk;
+
+   if (reft.state == RING_TIMER_STOPPED)
+   {
+      int32_t i;
+
+      reft.state = RING_TIMER_RUNNING;
+      sem_init(&reft.sem, 0, 0);
+      reft.current_bit = 0;
+      reft.reset_bits = 0;
+
+      for (i=0; i<DXS_RING_CHANNELS; i++)
+      {
+         dxs_ring_res_t *pRes = &ring_cadence[i];
+         /* reset_bits is the maximum cadence length */
+         if ((pRes->flag & RING_CADENCE_INIT) &&
+                reft.reset_bits < pRes->cadence.valid_bits)
+         {
+            reft.reset_bits = pRes->cadence.valid_bits;
+         }
+      }
+
+      if (0 != pthread_create(&reft.thr, NULL, ring_timer_thread, (void *)&reft))
+         ret = DXS_statusThreadCreatError;
+   }
+   return ret;
+}
+
+/**
+   Stop the ringing timer
+
+   \param   none
+   \return  none
+*/
+static void ring_timer_stop (void)
+{
+   int i;
+
+   for (i=0; i<DXS_RING_CHANNELS; i++)
+   {
+      dxs_ring_res_t *pRes = &ring_cadence[i];
+
+      if (pRes->ring_cadence_state != RING_CAD_STATE_IDLE)
+         return;
+   }
+
+   if (reft.state != RING_TIMER_STOPPED)
+   {
+      reft.state = RING_TIMER_STOPPED;
+      sem_post(&reft.sem);
+      pthread_join(reft.thr, NULL);
+      sem_destroy(&reft.sem);
+   }
+}
+
+/**
+   Inform ringing SM about finished CID sequence
+
+   \param   pCh    - pointer to DXS channel structure
+   \return
+   - none
+*/
+void DXS_Ring_CidFinished (DXS_CHANNEL_t *pCh)
+{
+   dxs_ring_res_t *pRes =
+          &ring_cadence[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   if (pRes->ring_cadence_state == RING_CAD_STATE_CID_DURING_RINGING ||
+        pRes->ring_cadence_state == RING_CAD_STATE_CID_PRIOR_TO_RINGING)
+   {
+      pRes->ring_cadence_state = RING_CAD_STATE_RINGING;
+   }
+   pRes->flag &= ~RING_CADENCE_CID_ACT;
+}
+
+/**
+   Initialize ringing resource and link it
+   with the \ref DXS_CHANNEL_t structure
+
+   \param   pCh    - pointer to DXS channel structure
+   \return
+   pointer to ringing resource
+*/
+void *DXS_Ring_ResInit(DXS_CHANNEL_t *pCh)
+{
+   dxs_ring_res_t *pRes =
+          &ring_cadence[pCh->pParent->nDevNum * CH_PER_DEVICE + pCh->nCh];
+
+   pRes->pCh = pCh;
+   pRes->flag = RING_CADENCE_NOT_INIT;
+
+   return (void *)pRes;
+}
+
+/**
+   Initialize ringing cadence
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   pConf  - pointer to \ref DXS_RingCadence_t structure
+   \return
+   the code from \ref DXS_status_t list
+*/
+int32_t DXS_RING_CadenceInit (DXS_CHANNEL_t *pCh, DXS_RingCadence_t *pConf)
+{
+   int32_t ret = DXS_statusOk;
+   dxs_ring_res_t *pRes = (dxs_ring_res_t *)pCh->ring;
+   int32_t bytes, bytes_to_copy, extra_bits;
+
+   POINTER_ASSERT(pConf);
+
+   if (pRes->ring_cadence_state != RING_CAD_STATE_IDLE)
+   {
+      DXS_RETURN(DXS_statusRingCadConfNotPossible);
+   }
+
+   bytes = pConf->valid_bits >> 3;
+   extra_bits = pConf->valid_bits % 8;
+   bytes_to_copy = bytes + (extra_bits ? 1 : 0);
+
+   if (bytes_to_copy > DXS_RING_CADENCE_MAX_LEN_BYTES)
+   {
+      DXS_RETURN(DXS_statusRingCadConfInvalid);
+   }
+
+   pRes->flag &= ~RING_CADENCE_INIT;
+
+   /* copy cadence data and valid bits */
+   pRes->cadence = *pConf;
+   if (extra_bits)
+      pRes->cadence.data[bytes] &= (0xff & (0xff << (8 - extra_bits)));
+
+   /* special arrangements for IFB12CH8 HW */
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      ret = dxs_ifb12ch8_shift_cadence(pRes, bytes_to_copy);
+   }
+
+   if (ret == DXS_statusOk)
+   {
+      pRes->ring_cadence_state = RING_CAD_STATE_IDLE;
+      pRes->ringer_state = RINGER_STATE_PAUSE;
+      pRes->flag |= RING_CADENCE_INIT;
+   }
+   DXS_RETURN(ret);
+}
+
+/**
+   Start ringing cadence
+
+   \param   pCh    - pointer to DXS channel structure
+   \return
+   the code from \ref DXS_status_t list
+*/
+int32_t DXS_RING_CadenceStart (DXS_CHANNEL_t *pCh)
+{
+   dxs_ring_res_t *pRes = (dxs_ring_res_t *)pCh->ring;
+   int32_t ret;
+   int opmode;
+
+   if (!(pRes->flag & RING_CADENCE_INIT))
+   {
+      DXS_RETURN(DXS_statusRingCadStartNotConf);
+   }
+
+   ret = DXS_SDD_LineModeGet(pCh, &opmode);
+   if (ret == DXS_statusOk && opmode == DXS_LINE_FEED_ACTIVE_REVPOL)
+      pRes->polarity = RING_POLARITY_REVERSE;
+
+   if (ret == DXS_statusOk)
+   {
+      pRes->current_bit = 0;
+      pRes->ring_cadence_state = dxs_ring_cad_initial_state(pCh);
+      pRes->ringer_state = RINGER_STATE_PAUSE;
+      pRes->wait_counter = 0;
+      if (pRes->pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8 &&
+             pRes->ring_cadence_state == RING_CAD_STATE_CID_PRIOR_TO_RINGING)
+      {
+         int32_t next_ring_bit_pos, cid_len_bits, ring_pulse=0;
+
+         DXS_CID_LengthBitsGet(pCh, &cid_len_bits);
+         if (cid_len_bits > 0)
+         {
+            /* set the wait_counter */
+            do
+            {
+               next_ring_bit_pos = dxs_ring_next_pos_get(pRes, ring_pulse++);
+               pRes->wait_counter = next_ring_bit_pos - cid_len_bits;
+            } while (pRes->wait_counter < 0);
+         }
+         else
+         {
+            /* zero or negative CID length means no CID */
+            pRes->ring_cadence_state = RING_CAD_STATE_RINGING;
+         }
+      }
+      ret = ring_timer_start();
+   }
+   DXS_RETURN(ret);
+}
+
+/**
+   Stop ringing cadence
+
+   \param   pCh    - pointer to DXS channel structure
+   \return
+   DXS_statusOk
+*/
+int32_t DXS_RING_CadenceStop (DXS_CHANNEL_t *pCh)
+{
+   int32_t ret = DXS_statusOk;
+   dxs_ring_res_t *pRes = (dxs_ring_res_t *)pCh->ring;
+
+   if (pRes->ringer_state == RINGER_STATE_RINGING)
+   {
+      ret = dxs_ring_pulse_stop(pRes);
+   }
+
+   if (pRes->ring_cadence_state == RING_CAD_STATE_CID_DURING_RINGING ||
+         pRes->ring_cadence_state == RING_CAD_STATE_CID_PRIOR_TO_RINGING)
+   {
+      DXS_CID_Stop(pCh);
+   }
+
+   if (ret == DXS_statusOk)
+   {
+      pRes->ring_cadence_state = RING_CAD_STATE_IDLE;
+      ring_timer_stop();
+   }
+   DXS_RETURN(ret);
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_ring.h b/marvell/services/dxslic/api_lib/src/dxs_ring.h
new file mode 100644
index 0000000..5376d76
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_ring.h
@@ -0,0 +1,28 @@
+#ifndef __DXS_RING_H__
+#define __DXS_RING_H__
+/*******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, 2017, 2018 Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+*******************************************************************************/
+
+/**
+   \file dxs_ring.h
+   API functions for cadenced ringing operation.
+*/
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern void *DXS_Ring_ResInit(DXS_CHANNEL_t *);
+extern void DXS_Ring_CidFinished(DXS_CHANNEL_t *);
+extern int32_t DXS_RING_CadenceInit (DXS_CHANNEL_t* , DXS_RingCadence_t* );
+extern int32_t DXS_RING_CadenceStart (DXS_CHANNEL_t* );
+extern int32_t DXS_RING_CadenceStop (DXS_CHANNEL_t* );
+
+#endif /* __DXS_RING_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_sdd.c b/marvell/services/dxslic/api_lib/src/dxs_sdd.c
new file mode 100644
index 0000000..de2beb3
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_sdd.c
@@ -0,0 +1,3692 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_sdd.c
+   This file contains the implementation of the functions for SDD operations.
+*/
+
+/* ========================================================================= */
+/*                                 Includes                                  */
+/* ========================================================================= */
+#include <errno.h>
+#include <time.h>
+
+#include "dxs.h"
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_misc.h"
+#include "dxs_init.h"
+#include "dxs_sdd.h"
+#include "dxs_pcm.h"
+#include "dxs_sig.h"
+#include "dxs_event.h"
+#include "dxs_access.h"
+#include "dxs_dcdc_hw.h"
+
+/* ========================================================================= */
+/*                             Macro definitions                             */
+/* ========================================================================= */
+
+#define SDD_MWL_VOLTAGE_MAX     144  /* V */
+#define SDD_MWL_THRESH_MAX      100  /* mA */
+#define SDD_MWL_SLOPE_MIN       100  /* V/s */
+#define SDD_MWL_SLOPE_MAX       1000 /* V/s */
+#define SDD_MWL_ONOFFTIME_MAX   6375 /* ms */
+
+#define SDD_RING_FREQ_MIN    15   /* Hz */
+#define SDD_RING_FREQ_MAX    50   /* Hz */
+#define SDD_RING_CF_MAX      7
+#define SDD_RING_AMP_MAX     144  /* V */
+
+#define SDD_GR909_DC_LIMIT_MAX      655350 /* mV */
+#define SDD_GR909_AC_LIMIT_MAX      463472 /* mVrms */
+#define SDD_GR909_RFT_RIT_MAX      1048560 /* Ohm */
+#define SDD_GR909_SETTLE_TIME_MAX     3968 /* ms */
+#define SDD_GR909_ROH_LIN_MAX        65535 /* % */
+
+#define SDD_EVT_TIMEOUT_MS   100  /* ms */
+
+/* Add line mode valid transition to table */
+#define SDD_LINEMODE_TRANSITION_ADD(nModeSrc, nModeDst)  \
+   line_mode_table[nModeSrc] |= 0x80000000 >> nModeDst;
+
+#define SDD_TX_GAIN_MIN        (-900)
+#define SDD_TX_GAIN_MAX        40
+#define SDD_RX_GAIN_MIN        (-900)
+#define SDD_RX_GAIN_MAX        0
+#define SDD_TX_GAIN_DEFAULT    (-30)
+#define SDD_RX_GAIN_DEFAULT    (-100)
+
+/* ACLM constants */
+#define DXS_ACLM_FR_MEASUREMENTS          35
+#define DXS_ACLM_TH_MEASUREMENTS          37
+#define DXS_ACLM_GT_MEASUREMENTS          30
+#define DXS_ACLM_SNR_MEASUREMENTS         28
+#define DXS_ACLM_INT_TIME_MS_DEFAULT      50
+#define DXS_ACLM_AC_DELAY_MS_DEFAULT      20
+#define DXS_ACLM_FR_TH_FREQ_MIN_HZ        100
+#define DXS_ACLM_FR_FREQ_CENTER_HZ        1020
+#define DXS_ACLM_FR_TH_FREQ_STEP_HZ       100
+#define DXS_ACLM_GT_LEVEL_MIN_DBM0        (-55)
+#define DXS_ACLM_SNR_LEVEL_MIN_DBM0       (-51)
+#define DXS_ACLM_GT_SNR_LEVEL_STEP_DBM0   2
+#define DXS_ACLM_MAX_RESULTS              DXS_ACLM_TH_MEASUREMENTS
+
+#ifndef DXS_SHARED_DCDC_STANDBY_MODE_WKR
+#define DXS_SHARED_DCDC_STANDBY_MODE_WKR  1
+#endif
+
+/* ========================================================================= */
+/*                             Type definitions                              */
+/* ========================================================================= */
+/** Data structure for SDD basic config firmware command */
+typedef struct
+{
+   struct DXS_FW_Cmd_Header      hdr;
+   struct DXS_basicConfigData        bc_data;
+   /*uint32_t data[sizeof(struct DXS_FW_SDD_BasicConfig)/sizeof(uint32_t)];*/
+} __attribute__ ((packed)) DXS_FW_SDD_BasicConfig_t;
+#define DXS_FW_SDD_BasicConfig_ECMD     4
+#define DXS_FW_SDD_BasicConfig_LENGTH   20
+
+/** Data structure for SDD ring config firmware command */
+typedef struct
+{
+   struct DXS_FW_Cmd_Header      hdr;
+   struct DXS_FW_SDD_RingConfig  content;
+} __attribute__ ((packed)) DXS_FW_SDD_RingConfig_t;
+#define DXS_FW_SDD_RingConfig_ECMD    5
+#define DXS_FW_SDD_RingConfig_LENGTH  20
+
+/** Data structure for SDD DC/DC config firmware command */
+typedef struct
+{
+   struct DXS_FW_Cmd_Header      hdr;
+   struct DXS_DcDcConfigData     dcdc_data;
+} __attribute__ ((packed)) DXS_FW_SDD_DcDcConfig_t;
+#define DXS_FW_SDD_DcDcConfig_ECMD          12
+#define DXS_FW_SDD_DcDcConfig_LENGTH        8
+
+/** Data structure for SDD gain config firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Tx Relative Level Setting */
+   uint32_t TxGain : 16;
+   /** Rx Relative Level setting */
+   uint32_t RxGain : 16;
+#else
+   CMD_HEAD_LE;
+   /** Rx Relative Level setting */
+   uint32_t RxGain : 16;
+   /** Tx Relative Level Setting */
+   uint32_t TxGain : 16;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_TxRxGain_t;
+#define DXS_FW_SDD_TxRxGain_ECMD   14
+#define DXS_FW_SDD_TxRxGain_LENGTH 4
+
+/** Data structure for SDD basic config firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Reserved */
+   uint32_t Res02 : 8;
+   /** Select Operating Mode */
+   uint32_t OpMode : 8;
+   /** Reserved */
+   uint32_t Res03 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res03 : 16;
+   /** Select Operating Mode */
+   uint32_t OpMode : 8;
+   /** Reserved */
+   uint32_t Res02 : 8;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_Opmode_t;
+#define DXS_FW_SDD_Opmode_ECMD    7
+#define DXS_FW_SDD_Opmode_LENGTH  4
+
+/** Data structure for SDD MWL config firmware command */
+typedef struct
+{
+   struct DXS_FW_Cmd_Header      hdr;
+   struct DXS_FW_SDD_MwlConfig   content;
+} __attribute__ ((packed)) DXS_FW_SDD_MwlConfig_t;
+#define DXS_FW_SDD_MwlConfig_ECMD     6
+#define DXS_FW_SDD_MwlConfig_LENGTH   8
+
+/** Data structure for SDD coefficients firmware command */
+typedef struct
+{
+   struct DXS_FW_Cmd_Header hdr;
+   struct DXS_FW_SDD_Coeff  content;
+} __attribute__ ((packed)) DXS_FW_SDD_Coeff_t;
+
+
+
+#define DXS_CALIBRATION_VERSION  1
+
+/** Data structure for calibration data */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+#else
+   CMD_HEAD_LE;
+#endif
+   union
+   {
+      uint32_t data1_32;
+      uint8_t data1_8[sizeof(uint32_t)];
+   };
+   union
+   {
+      uint32_t data2_32;
+      uint8_t data2_8[sizeof(uint32_t)];
+   };
+} __attribute__ ((packed)) DXS_FW_SDD_Calibrate_t;
+#define DXS_FW_SDD_Calibrate_ECMD         3
+#define DXS_FW_SDD_Calibrate_LENGTH       8
+
+
+/** Data structure for capacitance measurement result firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Capacitance Ring to Ground */
+   uint32_t CapR2G : 16;
+   /** Capacitance Tip to Ground */
+   uint32_t CapT2G : 16;
+   /** Capacitance Tip to Ring */
+   uint32_t CapT2R : 16;
+   /** Reserved */
+   uint32_t Res02 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Capacitance Tip to Ground */
+   uint32_t CapT2G : 16;
+   /** Capacitance Ring to Ground */
+   uint32_t CapR2G : 16;
+   /** Reserved */
+   uint32_t Res02 : 16;
+   /** Capacitance Tip to Ring */
+   uint32_t CapT2R : 16;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_CapMeasurRes_t;
+#define DXS_FW_SDD_CapMeasurRes_ECMD     16
+#define DXS_FW_SDD_CapMeasurRes_LENGTH    8
+
+/** Data structure for continuous measurement result firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Line Voltage */
+   int32_t Vline : 16;
+   /** Line Current */
+   int32_t Itrans : 16;
+   /** RING Current */
+   uint32_t Iring : 16;
+   /** RING Voltage */
+   uint32_t Vring : 16;
+   /** Reserved */
+   uint32_t Res02 : 32;
+#else
+   CMD_HEAD_LE;
+   /** Line Current */
+   int32_t Itrans : 16;
+   /** Line Voltage */
+   int32_t Vline : 16;
+   /** RING Voltage */
+   uint32_t Vring : 16;
+   /** RING Current */
+   uint32_t Iring : 16;
+   /** Reserved */
+   uint32_t Res02 : 32;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_ContMeasurRes_t;
+#define DXS_FW_SDD_ContMeasurRes_ECMD      2
+#define DXS_FW_SDD_ContMeasurRes_LENGTH   12
+
+/** Data structure for GR-909 limits configuration firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Reserved */
+   uint32_t Res02 : 11;
+   /** Settle Time */
+   uint32_t SettleTime : 5;
+   /** HPT Wire to GND AC Limit */
+   uint32_t HptW2gAcLim : 16;
+   /** HPT Wire to Wire AC Limit */
+   uint32_t HptW2wAcLim : 16;
+   /** HPT Wire to GND DC Limit */
+   uint32_t HptW2gDcLim : 16;
+   /** HPT Wire to Wire DC Limit */
+   uint32_t HptW2wDcLim : 16;
+   /** FEMF Wire to GND AC Limit */
+   uint32_t FemfW2gAcLim : 16;
+   /** FEMF Wire to Wire AC Limit */
+   uint32_t FemfW2wAcLim : 16;
+   /** FEMF Wire to GND DC Limit */
+   uint32_t FemfW2gDcLim : 16;
+   /** FEMF Wire to Wire DC Limit */
+   uint32_t FemfW2wDcLim : 16;
+   /** RFT Resistance Limit */
+   uint32_t RftResLim : 16;
+   /** ROH Linearity Limit */
+   uint32_t RohLinLim : 16;
+   /** RIT Lower Limit */
+   uint32_t RitLowLim : 16;
+   /** RIT Higher Limit */
+   uint32_t RitHighLim : 16;
+   /** Reserved */
+   uint32_t Res03 : 16;
+#else
+   CMD_HEAD_LE;
+   /** HPT Wire to GND AC Limit */
+   uint32_t HptW2gAcLim : 16;
+   /** Settle Time */
+   uint32_t SettleTime : 5;
+   /** Reserved */
+   uint32_t Res02 : 11;
+   /** HPT Wire to GND DC Limit */
+   uint32_t HptW2gDcLim : 16;
+   /** HPT Wire to Wire AC Limit */
+   uint32_t HptW2wAcLim  : 16;
+   /** FEMF Wire to GND AC Limit */
+   uint32_t FemfW2gAcLim : 16;
+   /** HPT Wire to Wire DC Limit */
+   uint32_t HptW2wDcLim : 16;
+   /** FEMF Wire to GND DC Limit */
+   uint32_t FemfW2gDcLim : 16;
+   /** FEMF Wire to Wire AC Limit */
+   uint32_t FemfW2wAcLim : 16;
+   /** RFT Resistance Limit */
+   uint32_t RftResLim : 16;
+   /** FEMF Wire to Wire DC Limit */
+   uint32_t FemfW2wDcLim : 16;
+   /** RIT Lower Limit */
+   uint32_t RitLowLim : 16;
+   /** ROH Linearity Limit */
+   uint32_t RohLinLim : 16;
+   /** Reserved */
+   uint32_t Res03 : 16;
+   /** RIT Higher Limit */
+   uint32_t RitHighLim : 16;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_GR909Config_t;
+#define DXS_FW_SDD_GR909Config_ECMD      8
+#define DXS_FW_SDD_GR909Config_LENGTH   28
+
+/** Data structure for GR-909 result firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** HPT Test Valid */
+   uint32_t HptValid : 1;
+   /** FEMF Test Valid */
+   uint32_t FemfValid : 1;
+   /** RFT Test Valid */
+   uint32_t RftValid : 1;
+   /** ROH Test Valid */
+   uint32_t RohValid : 1;
+   /** RIT Test Valid */
+   uint32_t RitValid : 1;
+   /** Reserved */
+   uint32_t Res02 : 11;
+   /** HPT Test Passed */
+   uint32_t HptPass : 1;
+   /** FEMF Test Passed */
+   uint32_t FemfPass : 1;
+   /** RFT Test Passed */
+   uint32_t RftPass : 1;
+   /** ROH Test Passed */
+   uint32_t RohPass : 1;
+   /** RIT Test Passed */
+   uint32_t RitPass : 1;
+   /** Reserved */
+   uint32_t Res03 : 11;
+   /** Test Result HPT or FEMF AC Ring to GND */
+   uint32_t HptAcR2g : 16;
+   /** Test Result HPT or FEMF AC Tip to GND */
+   uint32_t HptAcT2g : 16;
+   /** Test Result HPT or FEMF AC Tip to Ring */
+   uint32_t HptAcT2r : 16;
+   /** Test Result HPT or FEMF DC Ring to GND */
+   int32_t HptDcR2g : 16;
+   /** Test Result HPT or FEMF DC Tip to GND */
+   int32_t HptDcT2g : 16;
+   /** Test Result HPT or FEMF DC Tip to Ring */
+   int32_t HptDcT2r : 16;
+   /** Resistive Fault Ring to Ground Result */
+   uint32_t RftR2g : 16;
+   /** Resistive Fault Tip to Ground Result */
+   uint32_t RftT2g : 16;
+   /** Resistive Fault Tip to Ring Result */
+   uint32_t RftT2r : 16;
+   /** Test Result ROH Low */
+   uint32_t RohLow : 16;
+   /** Test Result ROH High */
+   uint32_t RohHigh : 16;
+   /** Test Result RIT */
+   uint32_t RitRes : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res03: 11;
+   /** RIT Test Passed */
+   uint32_t RitPass : 1;
+   /** ROH Test Passed */
+   uint32_t RohPass : 1;
+   /** RFT Test Passed */
+   uint32_t RftPass : 1;
+   /** FEMF Test Passed */
+   uint32_t FemfPass : 1;
+   /** HPT Test Passed */
+   uint32_t HptPass : 1;
+   /** Reserved */
+   uint32_t Res02 : 11;
+   /** RIT Test Valid */
+   uint32_t RitValid : 1;
+   /** ROH Test Valid */
+   uint32_t RohValid : 1;
+   /** RFT Test Valid */
+   uint32_t RftValid : 1;
+   /** FEMF Test Valid */
+   uint32_t FemfValid : 1;
+   /** HPT Test Valid */
+   uint32_t HptValid : 1;
+   /** Test Result HPT or FEMF AC Tip to GND */
+   uint32_t HptAcT2g : 16;
+   /** Test Result HPT or FEMF AC Ring to GND */
+   uint32_t HptAcR2g : 16;
+   /** Test Result HPT or FEMF DC Ring to GND */
+   int32_t HptDcR2g : 16;
+   /** Test Result HPT or FEMF AC Tip to Ring */
+   uint32_t HptAcT2r : 16;
+   /** Test Result HPT or FEMF DC Tip to Ring */
+   int32_t HptDcT2r : 16;
+   /** Test Result HPT or FEMF DC Tip to GND */
+   int32_t HptDcT2g : 16;
+   /** Resistive Fault Tip to Ground Result */
+   uint32_t RftT2g : 16;
+   /** Resistive Fault Ring to Ground Result */
+   uint32_t RftR2g : 16;
+   /** Test Result ROH Low */
+   uint32_t RohLow : 16;
+   /** Resistive Fault Tip to Ring Result */
+   uint32_t RftT2r : 16;
+   /** Test Result RIT */
+   uint32_t RitRes : 16;
+   /** Test Result ROH High */
+   uint32_t RohHigh : 16;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_GR909Result_t;
+#define DXS_FW_SDD_GR909Result_ECMD      9
+#define DXS_FW_SDD_GR909Result_LENGTH   28
+
+/** Data structure for open loop calibration firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Open Loop Conductance Ring To Ground */
+   uint32_t GRG : 8;
+   /** Open Loop Conductance Tip To Ground */
+   uint32_t GTG : 8;
+   /** Open Loop Conductance Tip To Ring */
+   uint32_t GTR : 8;
+   /** Reserved */
+   uint32_t Res02 : 8;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res02 : 8;
+   /** Open Loop Conductance Tip To Ring */
+   uint32_t GTR : 8;
+   /** Open Loop Conductance Tip To Ground */
+   uint32_t GTG : 8;
+   /** Open Loop Conductance Ring To Ground */
+   uint32_t GRG : 8;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_OpenLoopCalibration_t;
+#define DXS_FW_SDD_OpenLoopCalibration_ECMD     11
+#define DXS_FW_SDD_OpenLoopCalibration_LENGTH    4
+
+/** The SDD_AcLevelMeterControl message starts and stops
+    the AC level meter measurement. */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Enable: 0=stop, 1=start */
+   uint32_t EN : 1;
+   /** Reserved */
+   uint32_t Res02 : 31;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res02 : 31;
+   /** Enable: 0-stop, 1-start */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_AcLevelMeterControl_t;
+#define DXS_FW_SDD_AcLevelMeterControl_ECMD    17
+#define DXS_FW_SDD_AcLevelMeterControl_LENGTH  4
+
+/** The SDD_AcLevelMeterConfig message configures the AC level meter. */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Bandwidth Coefficient */
+   uint32_t BW : 16;
+   /** Center Frequency Coefficient */
+   uint32_t CF : 16;
+   /** Reserved */
+   uint32_t Res02 : 14;
+   /** Bandpass enable: 0=disable, 1=enable */
+   uint32_t BP : 1;
+   /** Transhybrid enable: 0=disable, 1=enable */
+   uint32_t TH : 1;
+   /** AC Delay [ms] */
+   uint32_t Del : 7;
+   /** AC Integration Time [ms] */
+   uint32_t Int : 9;
+#else
+   CMD_HEAD_LE;
+   /** Center Frequency Coefficient */
+   uint32_t CF : 16;
+   /** Bandwidth Coefficient */
+   uint32_t BW : 16;
+   /** AC Integration Time [ms] */
+   uint32_t Int : 9;
+   /** AC Delay [ms] */
+   uint32_t Del : 7;
+   /** Transhybrid enable: 0=disable, 1=enable */
+   uint32_t TH : 1;
+   /** Bandpass enable: 0=disable, 1=enable */
+   uint32_t BP : 1;
+   /** Reserved */
+   uint32_t Res02 : 14;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_AcLevelMeterConfig_t;
+#define DXS_FW_SDD_AcLevelMeterConfig_ECMD    18
+#define DXS_FW_SDD_AcLevelMeterConfig_LENGTH  8
+
+/** The SDD_AcLevelMeterResult message carries the AC level meter
+    measurement result. */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** AC Levelmeter Inband Result */
+   uint32_t AcInb : 24;
+   /** AC Levelmeter Inband Result Shift (signed) */
+   int32_t AcInbSh : 8;
+   /** AC Levelmeter Outband Result */
+   uint32_t AcOutb : 24;
+   /** AC Levelmeter Outband Result Shift (signed) */
+   int32_t AcOutbSh : 8;
+#else
+   CMD_HEAD_LE;
+   /** AC Levelmeter Inband Result Shift */
+   int32_t AcInbSh : 8;
+   /** AC Levelmeter Inband Result */
+   uint32_t AcInb : 24;
+   /** AC Levelmeter Outband Result Shift */
+   int32_t AcOutbSh : 8;
+   /** AC Levelmeter Outband Result */
+   uint32_t AcOutb : 24;
+#endif
+} __attribute__ ((packed)) DXS_FW_SDD_AcLevelMeterResult_t;
+#define DXS_FW_SDD_AcLevelMeterResult_ECMD    19
+#define DXS_FW_SDD_AcLevelMeterResult_LENGTH  8
+
+enum ACLM_meas_status
+{
+   /** Initial */
+   dxs_aclm_init,
+   /** Measurement in progress */
+   dxs_aclm_in_progress,
+   /** Measurement finished */
+   dxs_aclm_finished,
+   /** Measurement aborted */
+   dxs_aclm_aborted
+};
+
+typedef struct
+{
+   /** Argument */
+   int32_t   arg;
+   /** Value */
+   int32_t   value;
+} DXS_ACLM_Result_t;
+
+/** Data structure for SDD channel resource */
+typedef struct
+{
+   /** status flag */
+#define SDD_CH_INITIALIZED    0x00000001
+#define SDD_RING_CONFIGURED   0x80000000
+#define SDD_MWL_CONFIGURED    0x40000000
+#define SDD_DCDC_CONFIGURED   0x20000000
+   volatile uint32_t         flag;
+   /** SDD Event mutex */
+   pthread_mutex_t    sdd_event_mtx;
+   /* semaphore to defer until calibration has completed. */
+   sem_t    calibration_wait_sem;
+   /** SDD Opmode Change condition variable */
+   pthread_cond_t     sdd_opc_cv;
+   /** pending opmode change: 0=no, 1=yes */
+   volatile uint8_t   bOpmodeChangePending;
+   /* Indicates that calibration was called by library (internal). */
+   volatile uint8_t   bCalibrationInternal;
+   /* Indicates that calibration is needed after BBD download. */
+   volatile uint8_t   bCalibrationNeeded;
+   /* Indicates that calibration is running */
+   volatile uint8_t   bCalibrationRunning;
+   /** current opmode: written by outbox thread from OPC event,
+      read by DxsLineModeGet() */
+   DXS_LINE_MODE_t    curr_opmode;
+   /** SDD_Coeff command */
+   DXS_FW_SDD_Coeff_t sdd_coeff;
+   /** SDD_BasicConfig command */
+   DXS_FW_SDD_BasicConfig_t basic_config;
+   /** SDD_DcDcConfig command */
+   DXS_FW_SDD_DcDcConfig_t dcdc_config;
+   /** SDD_Opmode command */
+   DXS_FW_SDD_Opmode_t opmode;
+   /** SDD_TxRxGain command */
+   DXS_FW_SDD_TxRxGain_t gain;
+   /**  SDD_RingConfig command */
+   DXS_FW_SDD_RingConfig_t ring_config;
+   /**  SDD_MwlConfig command */
+   DXS_FW_SDD_MwlConfig_t mwl;
+   /**  SDD_Calibrate command */
+   DXS_FW_SDD_Calibrate_t calibrate;
+   /**  SDD_ContMeasurRes command */
+   DXS_FW_SDD_ContMeasurRes_t contmeasur_res;
+#ifdef DXS_FEAT_CAPMEAS
+   /**  SDD_CapMeasurRes command */
+   DXS_FW_SDD_CapMeasurRes_t capmeasur_res;
+#endif /* DXS_FEAT_CAPMEAS */
+#ifdef DXS_FEAT_GR909
+   /**  SDD_GR909Config command */
+   DXS_FW_SDD_GR909Config_t gr909cfg;
+   /** SDD_GR909Result command */
+   DXS_FW_SDD_GR909Result_t gr909res;
+#endif /* DXS_FEAT_GR909 */
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+   /** semaphore to defer untill C-Measurement or GR-909 for
+      OL calibration has completed. */
+   sem_t    ol_calibration_wait_sem;
+   /** Indicates that OL calibration is running */
+   volatile uint8_t   bOLCalibrationRunning;
+   /** Indicates that C-Measurements or GR-909 results for
+      OL calibration received. */
+   volatile uint8_t   bOLCalibrationNltResultRdy;
+   /** OL calibration results for capacitance */
+   DXS_Capacitance_t  ol_cap_meas_res;
+   /**  SDD_OpenLoopCalibration command */
+   DXS_FW_SDD_OpenLoopCalibration_t ol_calibration;
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+#ifdef DXS_FEAT_ACMETER
+   /** AC Level Meter event signaling semaphore */
+   sem_t    aclm_sig_sem;
+   /** SDD_AcLevelMeterConfig command */
+   DXS_FW_SDD_AcLevelMeterConfig_t   aclm_config;
+   /** SDD_AcLevelMeterControl command */
+   DXS_FW_SDD_AcLevelMeterControl_t  aclm_ctrl;
+   /** SDD_AcLevelMeterResult command */
+   DXS_FW_SDD_AcLevelMeterResult_t   aclm_result;
+   /** Current measurement selector */
+   DXS_ACLM_Measurement_t aclm_current_meas;
+   /** Measurement status */
+   enum ACLM_meas_status  aclm_meas_status;
+   /** Flag to restore DISABLED opmode after measurement finish */
+   uint8_t bAclmRestoreDisabled;
+   /** Result index in a table */
+   uint8_t aclm_result_tbl_idx;
+   /** Results table */
+   DXS_ACLM_Result_t aclm_results[DXS_ACLM_MAX_RESULTS];
+#endif /* DXS_FEAT_ACMETER */
+} DXS_SDD_Ch_Resource_t;
+
+
+
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static DXS_SDD_Ch_Resource_t  sdd_chan[DXS_MAX_DEVICES * CH_PER_DEVICE] = {0};
+
+/* Line mode transition table based on DXS_LINE_MODE_t */
+static uint8_t bLineModeTblSet = 0;
+static uint32_t line_mode_table[31] = {0};
+
+static uint16_t dxs_sdd_tx_gain_precalc[] = {
+/* 0.0      0.1      0.2      0.3      0.4       0.5       0.6      0.7    dB */
+   0x4f00,  0x4fea,  0x50d7,  0x51c7,  0x52b9,   0x53ae,   0x54a6,  0x55a1,
+/* 0.8      0.9      1.0      1.1      1.2       1.3       1.4      1.5    dB */
+   0x569f,  0x57a0,  0x58a4,  0x59aa,  0x5ab4,   0x5bc1,   0x5cd1,  0x5de4,
+/* 1.6      1.7      1.8      1.9      2.0       2.1       2.2      2.3    dB */
+   0x5efb,  0x6014,  0x6131,  0x6251,  0x6375,   0x649b,   0x65c6,  0x66f3,
+/* 2.4      2.5      2.6      2.7      2.8       2.9       3.0      3.1    dB */
+   0x6824,  0x6959,  0x6a91,  0x6bcd,  0x6d0d,   0x6e50,   0x6f97,  0x70e2,
+/* 3.2      3.3      3.4      3.5      3.6       3.7       3.8      3.9    dB */
+   0x7231,  0x7383,  0x74d9,  0x7634,  0x7792,   0x78f5,   0x7a5b,  0x7bc6,
+/* 4.0  dB */
+   0x7d35
+};
+
+/* ========================================================================= */
+/*                           Function prototypes                             */
+/* ========================================================================= */
+
+/* ========================================================================= */
+/*                         Function implementation                           */
+/* ========================================================================= */
+
+/**
+   Gain calculator used by DXS_SDD_GainGet function.
+
+   \param      factor  - factor in Q15.16 format
+   \return
+   - int16_t   calculated gain in 0.1[dB] units
+*/
+static int16_t dxs_gain_get_calc (int32_t factor)
+{
+   int32_t qCorrection_dB = 0, qTmp, qGain;
+
+   while ((qTmp = DXS_Misc_Q15_16_Mul(factor, Q15_16_TEN)) < Q15_16_ONE)
+   {
+      qCorrection_dB += Q15_16_ONE;
+      factor = qTmp;
+   }
+   qGain = DXS_Misc_Q15_16_Log10(factor);
+   /* apply gain correction, dB */
+   qGain -= qCorrection_dB;
+   qGain = DXS_Misc_Q15_16_Mul(Q15_16_TWENTY, qGain);
+   /* switch to 0.1 dB units */
+   qGain = DXS_Misc_Q15_16_Mul(qGain, Q15_16_TEN);
+   /* round up */
+   qGain += (qGain >= 0 ? Q15_16_HALF : -(Q15_16_HALF));
+
+   return (int16_t)DXS_Misc_Q15_16_to_Float(qGain);
+}
+
+/**
+   Function dxs_sdd_opmode_get
+
+   \param   pRes    - pointer to DXS SDD channel structure
+
+   \return
+   - int32_t
+*/
+static int32_t dxs_sdd_opmode_get(DXS_SDD_Ch_Resource_t *pRes)
+{
+   int ret = 0, err;
+   unsigned long ns;
+   struct timespec ts = {0};
+
+   err = pthread_mutex_lock(&pRes->sdd_event_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   clock_gettime(CLOCK_REALTIME, &ts);
+   ns = ts.tv_nsec + SDD_EVT_TIMEOUT_MS * 1000 * 1000;
+   ts.tv_nsec = ns % (1000 * 1000 * 1000);
+   ts.tv_sec += ns / (1000 * 1000 * 1000);
+
+   while(pRes->bOpmodeChangePending == 1)
+   {
+      ret = pthread_cond_timedwait(&pRes->sdd_opc_cv,
+                                     &pRes->sdd_event_mtx, &ts);
+      if (ret != 0)
+         break;
+   }
+
+   if (ret == EINVAL || ret == EPERM)
+      ret = DXS_statusSddEvtWaitError;
+   else if (ret == ETIMEDOUT)
+      ret = DXS_statusSddEvtWaitTmout;
+
+   err = pthread_mutex_unlock(&pRes->sdd_event_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return ret;
+}
+
+/**
+   Function to add all possible valid line mode transitions
+
+*/
+static void dxs_sdd_linemode_valid_transitions_set()
+{
+   /* Valid transitions for DISABLED line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_RING_BURST);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_STANDBY);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_GROUND_START);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_CALIBRATE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_GR909);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_RINGING_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_ACTIVE_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_DISABLED, DXS_LINE_FEED_CAP_MEAS);
+   /* Valid transitions for RING_BURST line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RING_BURST, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RING_BURST, DXS_LINE_FEED_RING_BURST);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RING_BURST, DXS_LINE_FEED_STANDBY);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RING_BURST, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RING_BURST, DXS_LINE_FEED_GROUND_START);
+   /* Valid transitions for STANDBY line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_STANDBY, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_STANDBY, DXS_LINE_FEED_RING_BURST);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_STANDBY, DXS_LINE_FEED_STANDBY);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_STANDBY, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_STANDBY, DXS_LINE_FEED_RINGING_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_STANDBY, DXS_LINE_FEED_ACTIVE_REVPOL);
+   /* Valid transitions for ACTIVE line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_RING_BURST);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_STANDBY);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_GROUND_START);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_ACTIVE_MWI);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_ACTIVE_HOWL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE, DXS_LINE_FEED_ACTIVE_REVPOL);
+   /* Valid transitions for GROUND_START line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_RING_BURST);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_GROUND_START);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_RINGING_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_ACTIVE_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START, DXS_LINE_FEED_GROUND_START_T2G);
+   /* Valid transitions for CALIBRATE line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_CALIBRATE, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_CALIBRATE, DXS_LINE_FEED_CALIBRATE);
+   /* Valid transitions for GR909 line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GR909, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GR909, DXS_LINE_FEED_GR909);
+   /* Valid transitions for ACTIVE_MWI line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_MWI, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_MWI, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_MWI, DXS_LINE_FEED_ACTIVE_MWI);
+   /* Valid transitions for ACTIVE_HOWL line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_HOWL, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_HOWL, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_HOWL, DXS_LINE_FEED_ACTIVE_HOWL);
+   /* Valid transitions for RINGING_REVPOL line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RINGING_REVPOL, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RINGING_REVPOL, DXS_LINE_FEED_STANDBY);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RINGING_REVPOL, DXS_LINE_FEED_GROUND_START);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RINGING_REVPOL, DXS_LINE_FEED_RINGING_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_RINGING_REVPOL, DXS_LINE_FEED_ACTIVE_REVPOL);
+   /* Valid transitions for ACTIVE_REVPOL line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_STANDBY);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_GROUND_START);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_RINGING_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_ACTIVE_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_REVPOL, DXS_LINE_FEED_ACTIVE_HOWL_REVPOL);
+   /* Valid transitions for GROUND_START_T2G line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_RING_BURST);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_ACTIVE);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_GROUND_START);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_RINGING_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_ACTIVE_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_GROUND_START_T2G, DXS_LINE_FEED_GROUND_START_T2G);
+   /* Valid transitions for CAP_MEAS line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_CAP_MEAS, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_CAP_MEAS, DXS_LINE_FEED_CAP_MEAS);
+   /* Valid transitions for ACTIVE_HOWL_REVPOL line mode */
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_HOWL_REVPOL, DXS_LINE_FEED_DISABLED);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_HOWL_REVPOL, DXS_LINE_FEED_ACTIVE_REVPOL);
+   SDD_LINEMODE_TRANSITION_ADD(DXS_LINE_FEED_ACTIVE_HOWL_REVPOL, DXS_LINE_FEED_ACTIVE_HOWL_REVPOL);
+   /* Internal fw emergency shutdown state */
+   SDD_LINEMODE_TRANSITION_ADD(11, DXS_LINE_FEED_DISABLED);
+
+   bLineModeTblSet = 1;
+}
+
+/**
+   Function to verify if the line mode state transition is valid
+
+   \param   nLineModeSrc    - current line mode
+   \param   nLineModeDst    - requested line mode
+
+   \return
+   - DXS_statusOk or DXS_statusLineModeInvalidTransition
+*/
+static int32_t dxs_sdd_linemode_transition_check(DXS_LINE_MODE_t nLineModeSrc,
+                                                   DXS_LINE_MODE_t nLineModeDst)
+{
+   int32_t err = DXS_statusLineModeInvalidTransition;
+
+   if ((line_mode_table[nLineModeSrc] << nLineModeDst) & 0x80000000)
+      err = DXS_statusOk;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_ChExit
+
+   \param   pCh  - pointer to DXS channel structure
+
+*/
+int32_t DXS_SDD_ChExit(DXS_CHANNEL_t *pCh)
+{
+   DXS_SDD_Ch_Resource_t  *pRes;
+   int32_t ret = DXS_statusOk;
+
+   if (pCh == NULL)
+      return ret;
+
+   pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   /* delete SDD Opmode Change condition variable */
+   ret = pthread_cond_destroy(&pRes->sdd_opc_cv);
+   if (ret != 0)
+      DXS_ERROR_PUSH(ret);
+   /* delete SDD Event mutex */
+   ret = pthread_mutex_unlock(&pRes->sdd_event_mtx);
+   if (ret != 0)
+      DXS_ERROR_PUSH(ret);
+   ret = pthread_mutex_destroy(&pRes->sdd_event_mtx);
+   if (ret != 0)
+      DXS_ERROR_PUSH(ret);
+
+   /* Delete the sem to wait for calibration to finish. */
+   sem_destroy(&pRes->calibration_wait_sem);
+
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+   /* Delete the sem required by OL Calibration. */
+   sem_destroy(&pRes->ol_calibration_wait_sem);
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+
+#ifdef DXS_FEAT_ACMETER
+   sem_destroy(&pRes->aclm_sig_sem);
+#endif /* DXS_FEAT_ACMETER */
+   DXS_RETURN(ret);
+}
+
+/**
+   Function obx_DXS_SDD_OpmodeUpdate
+
+   \param   pCh  - pointer to DXS channel structure
+   \param   mode - line mode
+   \param   bOPC - bOPC
+
+*/
+void obx_DXS_SDD_OpmodeUpdate(DXS_CHANNEL_t *pCh, DXS_LINE_MODE_t mode, uint8_t bOPC)
+{
+   DXS_SDD_Ch_Resource_t  *pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   int32_t err;
+
+   /* Avoiding race condition with DXS_SDD_ChInit().
+      Consequence - loosing of the first two OPC events, which is not a problem
+      as the device always starts from DISABLED mode after booting up. */
+   if (pRes == NULL || !(pRes->flag & SDD_CH_INITIALIZED))
+      return;
+
+   err = pthread_mutex_lock(&pRes->sdd_event_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   pRes->bOpmodeChangePending = 0;
+
+   if (bOPC == 1)
+   {
+      pRes->curr_opmode = mode;
+   }
+
+   pthread_cond_signal(&pRes->sdd_opc_cv);
+
+   err = pthread_mutex_unlock(&pRes->sdd_event_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+}
+
+/**
+   Function to initialize SDD channel resource
+
+   \param   dev - device number
+   \param   ch  - channel number
+
+*/
+void *DXS_SDD_ChInit(uint8_t dev, uint8_t ch)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int err;
+
+   if (dev >= DXS_MAX_DEVICES || ch >= CH_PER_DEVICE)
+      return (void *)NULL;
+
+   p = &sdd_chan[dev * CH_PER_DEVICE + ch];
+
+   p->flag = 0;
+
+   p->sdd_coeff.hdr.CMD = CMD_SDD;
+   p->sdd_coeff.hdr.MOD = MOD_SDD_PCM;
+   p->sdd_coeff.hdr.ECMD = DXS_FW_SDD_Coeff_ECMD;
+   p->sdd_coeff.hdr.LENGTH = DXS_FW_SDD_Coeff_MAXLENGTH;
+   p->sdd_coeff.hdr.CHAN = ch;
+
+   p->basic_config.hdr.CMD = CMD_SDD;
+   p->basic_config.hdr.MOD = MOD_SDD_PCM;
+   p->basic_config.hdr.ECMD = DXS_FW_SDD_BasicConfig_ECMD;
+   p->basic_config.hdr.LENGTH = DXS_FW_SDD_BasicConfig_LENGTH;
+   p->basic_config.hdr.CHAN = ch;
+
+   p->dcdc_config.hdr.CMD = CMD_SDD;
+   p->dcdc_config.hdr.MOD = MOD_SDD_PCM;
+   p->dcdc_config.hdr.ECMD = DXS_FW_SDD_DcDcConfig_ECMD;
+   p->dcdc_config.hdr.LENGTH = DXS_FW_SDD_DcDcConfig_LENGTH;
+   p->dcdc_config.hdr.CHAN = ch;
+
+   p->opmode.CMD = CMD_SDD;
+   p->opmode.MOD = MOD_SDD_PCM;
+   p->opmode.ECMD = DXS_FW_SDD_Opmode_ECMD;
+   p->opmode.LENGTH = DXS_FW_SDD_Opmode_LENGTH;
+   p->opmode.CHAN = ch;
+
+   p->gain.CMD = CMD_SDD;
+   p->gain.MOD = MOD_SDD_PCM;
+   p->gain.ECMD = DXS_FW_SDD_TxRxGain_ECMD;
+   p->gain.LENGTH = DXS_FW_SDD_TxRxGain_LENGTH;
+   p->gain.CHAN = ch;
+
+   p->ring_config.hdr.CMD = CMD_SDD;
+   p->ring_config.hdr.MOD = MOD_SDD_PCM;
+   p->ring_config.hdr.ECMD = DXS_FW_SDD_RingConfig_ECMD;
+   p->ring_config.hdr.LENGTH = DXS_FW_SDD_RingConfig_LENGTH;
+   p->ring_config.hdr.CHAN = ch;
+
+   p->mwl.hdr.CMD = CMD_SDD;
+   p->mwl.hdr.MOD = MOD_SDD_PCM;
+   p->mwl.hdr.ECMD = DXS_FW_SDD_MwlConfig_ECMD;
+   p->mwl.hdr.LENGTH = DXS_FW_SDD_MwlConfig_LENGTH;
+   p->mwl.hdr.CHAN = ch;
+
+   p->calibrate.CMD = CMD_SDD;
+   p->calibrate.MOD = MOD_SDD_PCM;
+   p->calibrate.ECMD = DXS_FW_SDD_Calibrate_ECMD;
+   p->calibrate.LENGTH = DXS_FW_SDD_Calibrate_LENGTH;
+   p->calibrate.CHAN = ch;
+
+   p->contmeasur_res.CMD = CMD_SDD;
+   p->contmeasur_res.MOD = MOD_SDD_PCM;
+   p->contmeasur_res.ECMD = DXS_FW_SDD_ContMeasurRes_ECMD;
+   p->contmeasur_res.LENGTH = DXS_FW_SDD_ContMeasurRes_LENGTH;
+   p->contmeasur_res.CHAN = ch;
+
+#ifdef DXS_FEAT_CAPMEAS
+   p->capmeasur_res.CMD = CMD_SDD;
+   p->capmeasur_res.MOD = MOD_SDD_PCM;
+   p->capmeasur_res.ECMD = DXS_FW_SDD_CapMeasurRes_ECMD;
+   p->capmeasur_res.LENGTH = DXS_FW_SDD_CapMeasurRes_LENGTH;
+   p->capmeasur_res.CHAN = ch;
+#endif /* DXS_FEAT_CAPMEAS */
+
+#ifdef DXS_FEAT_GR909
+   p->gr909cfg.CMD = CMD_SDD;
+   p->gr909cfg.MOD = MOD_SDD_PCM;
+   p->gr909cfg.ECMD = DXS_FW_SDD_GR909Config_ECMD;
+   p->gr909cfg.LENGTH = DXS_FW_SDD_GR909Config_LENGTH;
+   p->gr909cfg.CHAN = ch;
+
+   p->gr909res.CMD = CMD_SDD;
+   p->gr909res.MOD = MOD_SDD_PCM;
+   p->gr909res.ECMD = DXS_FW_SDD_GR909Result_ECMD;
+   p->gr909res.LENGTH = DXS_FW_SDD_GR909Result_LENGTH;
+   p->gr909res.CHAN = ch;
+#endif /* DXS_FEAT_GR909 */
+
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+   p->ol_calibration.CMD = CMD_SDD;
+   p->ol_calibration.MOD = MOD_SDD_PCM;
+   p->ol_calibration.ECMD = DXS_FW_SDD_OpenLoopCalibration_ECMD;
+   p->ol_calibration.LENGTH = DXS_FW_SDD_OpenLoopCalibration_LENGTH;
+   p->ol_calibration.CHAN = ch;
+
+   /* Open Loop Calibration flags and parameters */
+   sem_init(&p->ol_calibration_wait_sem, 0, 0);
+   p->ol_cap_meas_res.Cap_R2G = 0;
+   p->ol_cap_meas_res.Cap_T2G = 0;
+   p->ol_cap_meas_res.Cap_T2R = 0;
+   p->bOLCalibrationRunning = 0;
+   p->bOLCalibrationNltResultRdy = 0;
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+
+#ifdef DXS_FEAT_ACMETER
+   p->aclm_config.CMD = CMD_SDD;
+   p->aclm_config.MOD = MOD_SDD_PCM;
+   p->aclm_config.ECMD = DXS_FW_SDD_AcLevelMeterConfig_ECMD;
+   p->aclm_config.LENGTH = DXS_FW_SDD_AcLevelMeterConfig_LENGTH;
+   p->aclm_config.CHAN = ch;
+
+   p->aclm_ctrl.CMD = CMD_SDD;
+   p->aclm_ctrl.MOD = MOD_SDD_PCM;
+   p->aclm_ctrl.ECMD = DXS_FW_SDD_AcLevelMeterControl_ECMD;
+   p->aclm_ctrl.LENGTH = DXS_FW_SDD_AcLevelMeterControl_LENGTH;
+   p->aclm_ctrl.CHAN = ch;
+
+   p->aclm_result.CMD = CMD_SDD;
+   p->aclm_result.MOD = MOD_SDD_PCM;
+   p->aclm_result.ECMD = DXS_FW_SDD_AcLevelMeterResult_ECMD;
+   p->aclm_result.LENGTH = DXS_FW_SDD_AcLevelMeterResult_LENGTH;
+   p->aclm_result.CHAN = ch;
+
+   p->aclm_current_meas = 0;
+   p->aclm_meas_status = dxs_aclm_init;
+
+   sem_init(&p->aclm_sig_sem, 0, 0);
+#endif /* DXS_FEAT_ACMETER */
+
+   pthread_mutex_init(&p->sdd_event_mtx, NULL);
+
+   err = pthread_cond_init (&p->sdd_opc_cv, NULL);
+   if (err != 0)
+   {
+      DXS_ERROR_PUSH(err);
+      err = pthread_mutex_destroy(&p->sdd_event_mtx);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      return NULL;
+   }
+
+   /* Initialize the semaphore to wait for calibration to finish. */
+   sem_init(&p->calibration_wait_sem, 0, 0);
+
+   p->bOpmodeChangePending = 0;
+   /* No calibration is needed - flag will be set during BBD download. */
+   p->bCalibrationNeeded = 0;
+   /* currently calibration is not running */
+   p->bCalibrationRunning = 0;
+   p->curr_opmode = DXS_LINE_FEED_DISABLED;
+
+   /* Set up line mode valid transitions table */
+   if (!bLineModeTblSet)
+      dxs_sdd_linemode_valid_transitions_set();
+
+   p->flag |= SDD_CH_INITIALIZED;
+
+   return (void *)p;
+}
+
+/**
+   Function DXS_SDD_CoeffBBD
+
+   \param   pCh        - pointer to DXS channel structure
+   \param   dest       - destination
+   \param   blk_offset - BBD block offset
+   \param   blk_len    - BBD block length
+   \param   pData      - pointer to BBD data
+   \param   padding    - padding (in bytes)
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_CoeffBBD(DXS_CHANNEL_t *pCh,
+                         uint8_t dest,
+                         uint16_t blk_offset,
+                         uint8_t blk_len, /* in words */
+                         uint8_t *pData,
+                         uint16_t padding) /* in bytes */
+{
+   DXS_FW_SDD_Coeff_t *pCoeff;
+   DXS_SDD_Ch_Resource_t *p;
+   int32_t err = DXS_statusOk;
+   uint8_t cmd_LENGTH;
+   uint16_t coeff0;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   pCoeff = &p->sdd_coeff;
+
+   cmd_LENGTH = (blk_len + 1) << 1;
+
+   pCoeff->hdr.LENGTH = cmd_LENGTH;
+   pCoeff->content.BlockOffset = blk_offset;
+   pCoeff->content.BlockLength = blk_len;
+   pCoeff->content.Dest = dest;
+   DXS_cpb2w(&coeff0, pData, sizeof(coeff0));
+   pCoeff->content.Coefficient0 = coeff0;
+
+   DXS_cpb2dw(&pCoeff->content.Coefficients_32[0],
+      pData + sizeof(coeff0),
+      cmd_LENGTH - sizeof(coeff0) - 2);
+
+   if (padding)
+      pCoeff->hdr.LENGTH += padding;
+
+#if 1
+   err = CmdWrite(pCh->pParent, (uint32_t *)pCoeff);
+#else
+   {
+      int i;
+      uint32_t *p = (uint32_t *)pCoeff;
+
+      fprintf (stderr, "BBD CRAM: ");
+      for (i=0; i<((pCoeff->hdr.LENGTH >> 2) + 1); i++, p++)
+      {
+         fprintf (stderr, "%08X ", *p);
+      }
+      fprintf (stderr, "\n");
+   }
+#endif
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_DcDcConfigBBD
+
+   \param   pCh        - pointer to DXS channel structure
+   \param   data       - SDD_DcDcConfig command payload
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_DcDcConfigBBD (DXS_CHANNEL_t *pCh, struct DXS_DcDcConfigData *data)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   int32_t err;
+   DXS_CHANNEL_t *pChMaster;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* Block dcdc reconfiguration */
+   if (p->flag & SDD_DCDC_CONFIGURED)
+      return DXS_statusBbdDcDcReconfig;
+
+   p->dcdc_config.dcdc_data = *data;
+
+   /* Download dcdc_config for both channels in case of combined DC/DC */
+   if (pCh->pParent->dcdcType == DXS_DCDC_CIBB12 ||
+        pCh->pParent->dcdcType == DXS_DCDC_CIFB12 ||
+        pCh->pParent->dcdcType == DXS_DCDC_CBB48)
+   {
+      DXS_CHANNEL_t *pChNeighbour;
+      DXS_SDD_Ch_Resource_t *pN;
+
+      pChNeighbour =
+             pCh->nCh ? &pCh->pParent->pChannel[0] : &pCh->pParent->pChannel[1];
+      pN = (DXS_SDD_Ch_Resource_t*) pChNeighbour->sdd;
+      if (!(pN->flag & SDD_DCDC_CONFIGURED))
+      {
+         pN->dcdc_config.dcdc_data = *data;
+         /* In case of CmdWrite error for neighbour channel do not return an
+            error but clear BBD_DOWNLOAD and do not set DCDC_CONFIGURED flags */
+         if (CmdWrite(pChNeighbour->pParent, (uint32_t *)&pN->dcdc_config) !=
+                                                                   DXS_statusOk)
+            pChNeighbour->flags &= ~DXS_CH_BBD_DOWNLOADED;
+         else
+            pN->flag |= SDD_DCDC_CONFIGURED;
+      }
+   }
+
+   /* if master channel is available, write configuration
+      only for master channel */
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      pChMaster = DXS_DCDC_HW_SharedDcDcMasterChGetInt(pCh->pParent);
+      if (pChMaster == NULL)
+      {
+         DXS_RETURN(DXS_statusBbdDCDCMasterNotSet);
+      }
+
+      if (pCh == pChMaster)
+         err = CmdWrite(pCh->pParent, (uint32_t *)&p->dcdc_config);
+      else
+         err = DXS_statusOk;
+   }
+   else
+   {
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->dcdc_config);
+   }
+
+   if (err == DXS_statusOk)
+      p->flag |= SDD_DCDC_CONFIGURED;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_BasicConfigBBD
+
+   \param   pCh        - pointer to DXS channel structure
+   \param   data       - SDD_BasicConfig command payload
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_BasicConfigBBD (DXS_CHANNEL_t *pCh, struct DXS_basicConfigData *data)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   int32_t err;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+   p->basic_config.bc_data = *data;
+
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->basic_config);
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_RingConfigBBD
+
+   \param   pCh        - pointer to DXS channel structure
+   \param   pRingConf  - pointer to SDD ring configuration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_RingConfigBBD (DXS_CHANNEL_t *pCh,
+                               struct DXS_FW_SDD_RingConfig *pRingConf)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   int32_t err;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   p->ring_config.content = *pRingConf;
+
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->ring_config);
+   if (!err)
+   {
+      p->flag |= SDD_RING_CONFIGURED;
+   }
+
+   DXS_RETURN(err);
+}
+
+
+/**
+   Function DXS_SDD_RingConfigAPI
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   waveForm    - waveform type
+   \param   crestFactor - crest factor
+   \param   frequency   - frequency
+   \param   amplitude   - amplitude
+   \param   dcOffset    - DC offset
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_RingConfigAPI (DXS_CHANNEL_t *pCh, uint8_t waveForm,
+                                uint8_t crestFactor, uint8_t frequency,
+                                uint16_t amplitude, uint16_t dcOffset)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   uint16_t new_freq, new_amp, new_dcoff;
+   int32_t err = DXS_statusOk;
+   uint32_t tmp;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* parameter sanity check */
+   if (waveForm > 1 || crestFactor > SDD_RING_CF_MAX ||
+       frequency < SDD_RING_FREQ_MIN || frequency > SDD_RING_FREQ_MAX ||
+       (amplitude + dcOffset) > SDD_RING_AMP_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   if (!(p->flag & SDD_RING_CONFIGURED))
+   {
+      /* read configuration from the device */
+      err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->ring_config,
+                          (uint32_t *)&p->ring_config);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   /* calculate new parameter values */
+
+   /* Frequency = (32768 * fring[Hz]) / 1000 */
+   tmp = frequency << 15;
+   new_freq = (uint16_t)DXS_Misc_RoundDiv(tmp, 1000);
+
+   /* Amplitude = V[Vp] * 2^15 / 144 */
+   tmp = amplitude << 15;
+   new_amp = (uint16_t)DXS_Misc_RoundDiv(tmp, 144);
+
+   /* DcOffset = Voltage[V] * 32768 / 144 */
+   tmp = dcOffset << 15;
+   new_dcoff = (uint16_t)DXS_Misc_RoundDiv(tmp, 144);
+
+   if (p->ring_config.content.WaveForm != waveForm ||
+       p->ring_config.content.CrestFact != crestFactor ||
+       p->ring_config.content.Frequency != new_freq ||
+       p->ring_config.content.Amplitude != new_amp ||
+       p->ring_config.content.DcOffset != new_dcoff)
+   {
+      p->ring_config.content.WaveForm = waveForm;
+      p->ring_config.content.CrestFact = crestFactor;
+      p->ring_config.content.Frequency = new_freq;
+      /* amplitude dependencies */
+      p->ring_config.content.Amplitude = new_amp;
+      if (amplitude >= 57/*~40Vrms*/)
+      {
+         p->ring_config.content.Vmin = 0x32AB;/*~40Vrms*/
+      }
+      else
+      {
+         p->ring_config.content.Vmin = p->ring_config.content.Amplitude;
+      }
+      /* DC offset dependencies */
+      p->ring_config.content.DcOffset = new_dcoff;
+      if (dcOffset >= 12)
+      {
+         p->ring_config.content.RingTripType = 0;
+         tmp = DXS_Misc_RoundDiv(dcOffset * 1000000,1700);
+      }
+      else
+      {
+         p->ring_config.content.RingTripType = 1;
+         tmp = DXS_Misc_RoundDiv(amplitude * 636620,1000);
+      }
+      p->ring_config.content.Thresh = (uint16_t)DXS_Misc_RoundDiv(tmp << 15, 100000);
+
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->ring_config);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   p->flag |= SDD_RING_CONFIGURED;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_MwlConfigBBD
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   pMwlConf    - pointer to SDD MWL configuration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_MwlConfigBBD (DXS_CHANNEL_t *pCh,
+                              struct DXS_FW_SDD_MwlConfig *pMwlConf)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   int32_t err;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   p->mwl.content = *pMwlConf;
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->mwl);
+   if (!err)
+   {
+      p->flag |= SDD_MWL_CONFIGURED;
+   }
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_MwlConfigAPI
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   voltage - voltage
+   \param   thresh  - threshold
+   \param   slope   - slope
+   \param   onTime  - on-time
+   \param   offTime - off-time
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_MwlConfigAPI(DXS_CHANNEL_t *pCh, uint8_t voltage,
+                             uint8_t thresh, uint16_t slope, uint16_t onTime,
+                             uint16_t offTime)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   uint16_t new_voltage, new_thresh, new_slope;
+   uint8_t  new_onTime, new_offTime;
+   int32_t err = DXS_statusOk;
+   uint32_t tmp;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* parameter range check */
+   if (voltage >= SDD_MWL_VOLTAGE_MAX || thresh >= SDD_MWL_THRESH_MAX ||
+       slope < SDD_MWL_SLOPE_MIN || slope > SDD_MWL_SLOPE_MAX ||
+       onTime > SDD_MWL_ONOFFTIME_MAX || offTime > SDD_MWL_ONOFFTIME_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   /* MWL is not allowed for combined and shared DCDC variants */
+   if (pCh->pParent->dcdcType == DXS_DCDC_CIBB12 ||
+        pCh->pParent->dcdcType == DXS_DCDC_CIFB12 ||
+        pCh->pParent->dcdcType == DXS_DCDC_CBB48 ||
+        pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+   {
+      DXS_RETURN(DXS_statusMwlNotAllowed);
+   }
+
+   if (!(p->flag & SDD_MWL_CONFIGURED))
+   {
+      /* read configuration from the device */
+      err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->mwl, (uint32_t *)&p->mwl);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   /* calculate new parameter values */
+
+   /* Voltage = V[Vp] * 2^15 / 144 */
+   tmp = (uint32_t)voltage << 15;
+   new_voltage = DXS_Misc_RoundDiv(tmp, 144);
+
+   /* Thresh = Current[A] * 32768 / 0.1 */
+   tmp = (uint32_t)thresh << 15;
+   new_thresh = DXS_Misc_RoundDiv(tmp, 100);
+
+   /* Slope = Slope[V/s] * 32768 / 144 / 2000 */
+   tmp = (uint32_t)slope << 15;
+   tmp = DXS_Misc_RoundDiv(tmp, 144);
+   new_slope = DXS_Misc_RoundDiv(tmp, 2000);
+
+   /* OnTime = time[s] / 0.025 */
+   new_onTime = DXS_Misc_RoundDiv(onTime, 25);
+
+   /* OffTime = time[s] / 0.025 */
+   new_offTime = DXS_Misc_RoundDiv(offTime, 25);
+
+   if (p->mwl.content.Voltage != new_voltage ||
+       p->mwl.content.Thresh != new_thresh ||
+       p->mwl.content.Slope != new_slope ||
+       p->mwl.content.OnTime != new_onTime ||
+       p->mwl.content.OffTime != new_offTime)
+   {
+      /* write new values */
+      p->mwl.content.Voltage = new_voltage;
+      p->mwl.content.Thresh = new_thresh;
+      p->mwl.content.Slope = new_slope;
+      p->mwl.content.OnTime = new_onTime;
+      p->mwl.content.OffTime = new_offTime;
+
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->mwl);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   p->flag |= SDD_MWL_CONFIGURED;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_GainSet
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   TxGain  - digital gain in units of 0.1 dB (A->D direction)
+   \param   RxGain  - digital gain in units of 0.1 dB (D->A direction)
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_GainSet(DXS_CHANNEL_t *pCh, int16_t TxGain, int16_t RxGain)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+   uint16_t new_gain_tx, new_gain_rx;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* parameter range check */
+   if (TxGain < SDD_TX_GAIN_MIN || TxGain > SDD_TX_GAIN_MAX ||
+       RxGain < SDD_RX_GAIN_MIN || RxGain > SDD_RX_GAIN_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   /* calculate new parameter values */
+   if (TxGain >= 0)
+   {
+      new_gain_tx = dxs_sdd_tx_gain_precalc[TxGain];
+   }
+   else
+   {
+      new_gain_tx = DXS_Misc_MulQ15(20224, DXS_Misc_LeveldB_to_Factor(TxGain));
+   }
+
+   new_gain_rx = DXS_Misc_MulQ15(30720, DXS_Misc_LeveldB_to_Factor(RxGain));
+
+   if (new_gain_tx != p->gain.TxGain || new_gain_rx != p->gain.RxGain)
+   {
+      /* write new values */
+      p->gain.TxGain = new_gain_tx;
+      p->gain.RxGain = new_gain_rx;
+
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->gain);
+      if (err)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function DXS_SDD_GainGet
+
+   \param   pCh     - pointer to DXS channel structure
+   \param   pTxGain - pointer to a digital gain value in dB, A->D direction
+   \param   pRxGain - pointer to a digital gain value in dB, D->A direction
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_GainGet(DXS_CHANNEL_t *pCh, int16_t *pTxGain, int16_t *pRxGain)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk, qFactor /* in Q15.16 scale */;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* read gains from device */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->gain,
+      (uint32_t *)&p->gain);
+
+   if (err == DXS_statusOk)
+   {
+      /* Tx */
+      qFactor = DXS_Misc_Q15_16_Div(p->gain.TxGain, 20224);
+      *pTxGain = dxs_gain_get_calc(qFactor);
+
+      /* Rx */
+      qFactor = DXS_Misc_Q15_16_Div(p->gain.RxGain, 30720);
+      *pRxGain = dxs_gain_get_calc(qFactor);
+   }
+   else
+   {
+      err = DXS_statusError;
+   }
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to set line mode
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   mode        - line mode
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_LineModeSet(DXS_CHANNEL_t *pCh, int mode)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (!(pCh->flags & DXS_CH_BBD_DOWNLOADED) && (mode != DXS_LINE_FEED_DISABLED))
+   {
+      DXS_RETURN(DXS_statusBbdNotDownloaded);
+   }
+
+   /* The following checks can be skipped for mode=DISABLED */
+   if (mode != DXS_LINE_FEED_DISABLED)
+   {
+      /* Verify line mode id parameter */
+      /*   From every valid line mode it is possible to switch to disabled,
+              therefore to check if the line mode is valid the line modes
+              transition table can be used. */
+      if (((mode < 0) || (mode > 31)) ||
+                (dxs_sdd_linemode_transition_check(mode, DXS_LINE_FEED_DISABLED)
+                                        == DXS_statusLineModeInvalidTransition))
+      {
+         DXS_RETURN(DXS_statusParamsOutRange);
+      }
+
+      /* following opmodes require device capabilities check */
+      if ((mode == DXS_LINE_FEED_ACTIVE_HOWL ||
+           mode == DXS_LINE_FEED_ACTIVE_HOWL_REVPOL) &&
+              !DXS_IsFeatureSupported(pCh->pParent, dxs_cap_howler))
+      {
+         DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+      }
+
+      /* Combined DC/DC have restrictions */
+      if (pCh->pParent->dcdcType == DXS_DCDC_CIBB12 ||
+           pCh->pParent->dcdcType == DXS_DCDC_CIFB12 ||
+           pCh->pParent->dcdcType == DXS_DCDC_CBB48 ||
+           pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8)
+      {
+         if (mode == DXS_LINE_FEED_ACTIVE_MWI)
+         {
+            /* Message Waiting Lamp is not allowed for combined and shared DCDC variants */
+            DXS_RETURN(DXS_statusMwlNotAllowed);
+         }
+      }
+   }
+
+   /* update current opmode,
+      wait while an opmode change is ongoing */
+   err = dxs_sdd_opmode_get(p);
+   if (err == DXS_statusSddEvtWaitError)
+   {
+      DXS_RETURN(err);
+   }
+
+#if (DXS_SHARED_DCDC_STANDBY_MODE_WKR==1)
+   if (pCh->pParent->dcdcType == DXS_DCDC_IFB12CH8 &&
+          mode == DXS_LINE_FEED_STANDBY)
+   {
+      /* temporary workaround: replace STBY with ACT */
+      mode = DXS_LINE_FEED_ACTIVE;
+   }
+#endif /* DXS_SHARED_DCDC_STANDBY_MODE_WKR */
+
+   if (p->curr_opmode == mode)
+   {
+      /* parameters aren't changed */
+      return DXS_statusOk;
+   }
+
+   /* Check if line mode transition is valid */
+   err = dxs_sdd_linemode_transition_check(p->curr_opmode, mode);
+   if (err == DXS_statusLineModeInvalidTransition)
+   {
+      DXS_RETURN(err);
+   }
+
+   /* handle DC/DC HW specific limitations */
+   if (mode == DXS_LINE_FEED_RING_BURST || mode == DXS_LINE_FEED_RINGING_REVPOL)
+   {
+      if ((err = DXS_DCDC_HW_RingingCapsCheck(pCh)) != DXS_statusOk)
+      {
+         DXS_RETURN(err);
+      }
+   }
+
+   p->bOpmodeChangePending = 1;
+
+   p->opmode.OpMode = mode;
+
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->opmode);
+   if (err)
+   {
+      DXS_RETURN(DXS_statusSddOpmodeSetError);
+   }
+   /* Set flag so that we can detect the end of calibration */
+   if (mode == DXS_LINE_FEED_CALIBRATE)
+      p->bCalibrationRunning = 1;
+
+   return DXS_statusOk;
+}
+
+/**
+   Function to get line mode
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   pMode       - pointer to line mode
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_LineModeGet(DXS_CHANNEL_t *pCh, int *pMode)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* update current opmode,
+      wait while an opmode change is ongoing */
+   err = dxs_sdd_opmode_get(p);
+   if (err == DXS_statusSddEvtWaitError)
+   {
+      DXS_RETURN(err);
+   }
+
+   *pMode = p->curr_opmode;
+
+   return DXS_statusOk;
+}
+
+
+/* ========================================================================== */
+/*                         Calibration stuff                                  */
+/* ========================================================================== */
+#if 0
+/**
+   Start calibration process for analog channel.
+
+   Run calibration mechanism and check new calibration offsets
+
+   \param  pCh          Pointer to the DxS channel structure.
+
+   \return
+   - DXS_statusOk                   if successful, error code otherwise
+*/
+static int32_t DXS_SDD_CalibrationStart(DXS_CHANNEL_t *pCh)
+{
+   DXS_SDD_Ch_Resource_t   *p          = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   int32_t                 ret         = DXS_statusOk;
+
+   /* Remember if started from API or driver internal. */
+   p->bCalibrationInternal = 1;
+   /* Start calibration */
+   ret = DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_CALIBRATE);
+   DXS_RETURN(ret);
+}
+#endif
+
+
+/**
+   Finish calibration process on the analog line.
+
+   This function is called after the firmware indicated that calibration has
+   finished. An event is sent to the application
+   to inform about the end of the calibration process, if calibration was
+   started using API (DxsLineModeSet).
+
+   \param  pCh          Pointer to the DxS channel structure.
+
+   \return
+   - DXS_statusOk                   if successful, error code otherwise
+*/
+int32_t DXS_SDD_Calibration_Finish(DXS_CHANNEL_t *pCh,
+   DXS_Event_t *pEvent)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+
+   /* sanity check */
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   p->bCalibrationRunning = 0;
+   p->bCalibrationNeeded = 0;
+   if (p->bCalibrationInternal)
+   {
+      /* Wake the waiting call in DXS_SDD_Calibration below. */
+      sem_post(&p->calibration_wait_sem);
+   }
+   else
+   {
+      pEvent->id = DXS_EVENT_CALIBRATION_END;
+      DXS_EventDispatch(pCh->pParent, pEvent);
+   }
+
+   return DXS_statusOk;
+}
+
+
+/**
+   Used internally to start calibration on the given analog line.
+
+   This function is called after a BBD download was done to calibrate the
+   analog channel where the download has just been done. This function blocks
+   until the finished event has been received.
+
+   \param  pCh          Pointer to the DXT channel structure.
+
+   \return
+   - DXS_statusOk                   if successful
+   - DXS_statusInvalidParam         Invalid parameters
+*/
+int32_t DXS_SDD_Calibration(DXS_CHANNEL_t *pCh)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t ret;
+
+   /* sanity check */
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (p->bCalibrationRunning == 1)
+   {
+      /* Current line mode is CALIBRATE */
+      DXS_RETURN (DXS_statusCalInProgress);
+   }
+   p->bCalibrationInternal = 1;
+   /* Start calibration */
+   ret = DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_CALIBRATE);
+
+   if (ret == DXS_statusOk)
+   {
+      /* Block until the semaphore is given in the calibration finished
+         function */
+      ret = sem_wait(&p->calibration_wait_sem);
+      if (ret)
+         DXS_RETURN(ret);
+   }
+
+   DXS_RETURN(ret);
+}
+
+
+/**
+   Function to read the results of calibration measurements
+
+   \param   pCh          - pointer to DXS channel structure
+   \param   pCalibration - pointer to calibration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_CalibrationGet(DXS_CHANNEL_t *pCh,
+   DXS_Calibration_t *pCalibration)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+
+   if (pCh == NULL || pCalibration == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+   if (pCalibration->version != DXS_CALIBRATION_VERSION)
+   {
+      DXS_RETURN(DXS_statusCalVersInvalid);
+   }
+   if (p->bCalibrationRunning == 1)
+   {
+      /* Current line mode is CALIBRATE */
+      DXS_RETURN (DXS_statusCalInProgress);
+   }
+
+   /* read results from the device */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->calibrate,
+      (uint32_t *)&p->calibrate);
+   if (err)
+   {
+      DXS_RETURN(err);
+   }
+
+   /* Set the parameters */
+   /* Note: DXS_cpb2dw() is needed for dxs_CRC_8_CCITT() */
+   DXS_cpb2dw(pCalibration->data, &p->calibrate.data1_8[0], sizeof(uint32_t));
+   DXS_cpb2dw(pCalibration->data + 1, &p->calibrate.data2_8[0], sizeof(uint32_t));
+   pCalibration->crc8ccitt = dxs_CRC_8_CCITT((uint8_t *)pCalibration->data,
+      sizeof(pCalibration->data));
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   /* Restore the values for output after processing dxs_CRC_8_CCITT() */
+   pCalibration->data[0] = p->calibrate.data1_32;
+   pCalibration->data[1] = p->calibrate.data2_32;
+#endif
+
+   DXS_RETURN(err);
+}
+
+
+/**
+   Function to write calibration hardware configuration values
+
+   \param   pCh          - pointer to DXS channel structure
+   \param   pCalibration - pointer to calibration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_CalibrationSet(DXS_CHANNEL_t *pCh,
+   DXS_Calibration_t *pCalibration)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t ret = DXS_statusOk;
+   uint8_t nCRC;
+   uint32_t pDataOrdered[2];
+
+   if (pCh == NULL || pCalibration == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+   if (pCalibration->version != DXS_CALIBRATION_VERSION)
+   {
+      DXS_RETURN(DXS_statusCalVersInvalid);
+   }
+   if (p->bCalibrationRunning == 1)
+   {
+      /* Current line mode is CALIBRATE */
+      DXS_RETURN (DXS_statusCalInProgress);
+   }
+
+   /* Get the parameters */
+   p->calibrate.data1_32 = pCalibration->data[0];
+   p->calibrate.data2_32 = pCalibration->data[1];
+   /* DXS_cpb2dw() is needed for dxs_CRC_8_CCITT() */
+   DXS_cpb2dw(pDataOrdered, &p->calibrate.data1_8[0], sizeof(uint32_t));
+   DXS_cpb2dw(pDataOrdered + 1, &p->calibrate.data2_8[0], sizeof(uint32_t));
+   nCRC = dxs_CRC_8_CCITT((uint8_t *)pDataOrdered, sizeof(pDataOrdered));
+
+   /* If CRC is correct and at least one of data fields is non-zero, write
+    * calibration data to device */
+   if (nCRC == pCalibration->crc8ccitt && (p->calibrate.data1_32 != 0 ||
+      p->calibrate.data2_32 != 0))
+      ret = DXS_CmdWrite(pCh->pParent, (uint32_t *)&p->calibrate);
+   else
+   {
+      ret = DXS_SDD_Calibration(pCh);
+      if (ret != DXS_statusOk)
+      {
+         /* Automatic calibration failed. */
+         ret = DXS_statusAutomaticCalibrationFailed;
+      }
+   }
+
+   DXS_RETURN(ret);
+}
+
+#ifdef DXS_FEAT_CAPMEAS
+/**
+   Function to get capacitance measurement result
+
+   \param   pCh          - pointer to DXS channel structure
+   \param   bCalibrated  - flag to return calibrated values
+   \param   pCapacitance - pointer to capacitance measurement result structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_CapMeasurementResultGet(DXS_CHANNEL_t *pCh, uint8_t bCalibrated,
+                                                DXS_Capacitance_t *pCapacitance)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+
+   if (pCh == NULL || pCapacitance == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* read results from the device */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->capmeasur_res,
+                                                 (uint32_t *)&p->capmeasur_res);
+   if (err)
+   {
+      DXS_RETURN(err);
+   }
+
+   /* Set the parameters */
+#ifdef DXS_FEAT_GR909
+   if (bCalibrated)
+   {
+      pCapacitance->Cap_R2G =
+                         p->capmeasur_res.CapR2G >= p->ol_cap_meas_res.Cap_R2G ?
+                       p->capmeasur_res.CapR2G - p->ol_cap_meas_res.Cap_R2G : 0;
+      pCapacitance->Cap_T2G =
+                         p->capmeasur_res.CapT2G >= p->ol_cap_meas_res.Cap_T2G ?
+                       p->capmeasur_res.CapT2G - p->ol_cap_meas_res.Cap_T2G : 0;
+      pCapacitance->Cap_T2R = p->ol_cap_meas_res.Cap_T2R + DXS_Misc_RoundDiv(
+                   (uint32_t) pCapacitance->Cap_R2G + pCapacitance->Cap_T2G, 4);
+      pCapacitance->Cap_T2R = p->capmeasur_res.CapT2R >= pCapacitance->Cap_T2R ?
+                            p->capmeasur_res.CapT2R - pCapacitance->Cap_T2R : 0;
+   }
+   else
+#endif /* DXS_FEAT_GR909 */
+   {
+      pCapacitance->Cap_R2G = p->capmeasur_res.CapR2G;
+      pCapacitance->Cap_T2G = p->capmeasur_res.CapT2G;
+      pCapacitance->Cap_T2R = p->capmeasur_res.CapT2R;
+   }
+
+   DXS_RETURN(err);
+}
+#endif /* DXS_FEAT_CAPMEAS */
+
+/**
+   Function to get continuous measurement result
+
+   \param   pCh              - pointer to DXS channel structure
+   \param   pContMeasurement - pointer to continuous measurement result structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_ContMeasurementResultGet(DXS_CHANNEL_t *pCh,
+                                  DXS_ContMeasurementResult_t *pContMeasurement)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pContMeasurement);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* read results from the device */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->contmeasur_res,
+                                                 (uint32_t *)&p->contmeasur_res);
+   if (err)
+      DXS_RETURN(err);
+
+   /* Set the parameters */
+
+   /* Output voltage of DC regulation. (with conversion to milivolts) */
+   /* V [V] = Vline / 2^15 * 144 */
+   pContMeasurement->Vline =
+               (((int64_t) p->contmeasur_res.Vline * 144000) + 0x4000) / 0x8000;
+   /* Value of the actual line current. (with conversion to microampere) */
+   /* I[A] = Itrans / 2^15 * 0.1 */
+   pContMeasurement->Itrans =
+              (((int64_t) p->contmeasur_res.Itrans * 100000) + 0x4000) / 0x8000;
+   /* Value of the last ring burst current. RMS valueof ring current
+      within the last ring period. (with conversion to microampere) */
+   /* I[A RMS ] = Iring / 2^15 * 0.07071 */
+   pContMeasurement->Iring =
+               (((uint64_t) p->contmeasur_res.Iring * 70710) + 0x4000) / 0x8000;
+   /* Value of the last ring burst voltage. RMS value of VDAC sine.
+      (with conversion to milivolts) */
+   /* V[V RMS ] = Vring / 2^15 * 101.82 */
+   pContMeasurement->Vring =
+              (((uint64_t) p->contmeasur_res.Vring * 101820) + 0x4000) / 0x8000;
+
+   DXS_RETURN(err);
+}
+
+#ifdef DXS_FEAT_GR909
+/**
+   Function to set GR-909 limits
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   pGR909Conf    - pointer to SDD GR909 configuration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_GR909LimitsSet(DXS_CHANNEL_t *pCh,
+                                                  DXS_GR909Config_t *pGR909Conf)
+{
+   int32_t err = DXS_statusOk;
+   DXS_SDD_Ch_Resource_t  *p;
+   uint16_t settle_time, HPT_W2G_AC_Lim, HPT_W2W_AC_Lim, HPT_W2G_DC_Lim,
+           HPT_W2W_DC_Lim, FEMF_W2G_AC_Lim, FEMF_W2W_AC_Lim, FEMF_W2G_DC_Lim,
+           FEMF_W2W_DC_Lim, RFT_Res_Lim, ROH_Lin_Lim, RIT_Low_Lim, RIT_High_Lim;
+
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pGR909Conf);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* Parameters' sanity check */
+   if (pGR909Conf->settle_time > SDD_GR909_SETTLE_TIME_MAX ||
+            pGR909Conf->HPT_W2G_AC_Lim > SDD_GR909_AC_LIMIT_MAX ||
+            pGR909Conf->HPT_W2W_AC_Lim > SDD_GR909_AC_LIMIT_MAX ||
+            pGR909Conf->FEMF_W2G_AC_Lim > SDD_GR909_AC_LIMIT_MAX ||
+            pGR909Conf->FEMF_W2W_AC_Lim > SDD_GR909_AC_LIMIT_MAX ||
+            pGR909Conf->HPT_W2G_DC_Lim > SDD_GR909_DC_LIMIT_MAX ||
+            pGR909Conf->HPT_W2W_DC_Lim > SDD_GR909_DC_LIMIT_MAX ||
+            pGR909Conf->FEMF_W2G_DC_Lim > SDD_GR909_DC_LIMIT_MAX ||
+            pGR909Conf->FEMF_W2W_DC_Lim > SDD_GR909_DC_LIMIT_MAX ||
+            pGR909Conf->RFT_Res_Lim > SDD_GR909_RFT_RIT_MAX ||
+            pGR909Conf->ROH_Lin_Lim > SDD_GR909_ROH_LIN_MAX ||
+            pGR909Conf->RIT_Low_Lim > SDD_GR909_RFT_RIT_MAX ||
+            pGR909Conf->RIT_High_Lim > SDD_GR909_RFT_RIT_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   /* Settle Time after Discharge, [ms] */
+   /* SettleTime = Time[ms] / 128 */
+   settle_time = DXS_Misc_RoundDiv(pGR909Conf->settle_time, 128);
+   /* HPT Wire to GND AC Limit, [mVrms] */
+   /* HptW2gAcLim = V lim [V rms ] * 141.4 */
+   HPT_W2G_AC_Lim = DXS_Misc_RoundDiv(pGR909Conf->HPT_W2G_AC_Lim * 1414, 10000);
+   /* HPT Wire to Wire AC Limit, [mVrms] */
+   /* HptW2wAcLim = V lim [V rms ] * 141.4 */
+   HPT_W2W_AC_Lim = DXS_Misc_RoundDiv(pGR909Conf->HPT_W2W_AC_Lim * 1414, 10000);
+   /* HPT Wire to GND DC Limit, [mV] */
+   /* HptW2gDcLim = V lim [V] * 100 */
+   HPT_W2G_DC_Lim = DXS_Misc_RoundDiv(pGR909Conf->HPT_W2G_DC_Lim, 10);
+   /* HPT Wire to Wire DC Limit, [mV] */
+   /* HptW2wDcLim = V lim [V] * 100 */
+   HPT_W2W_DC_Lim = DXS_Misc_RoundDiv(pGR909Conf->HPT_W2W_DC_Lim, 10);
+   /* FEMF Wire to GND AC Limit, [mVrms] */
+   /* FemfW2gAcLim = V lim [V rms ] * 141.4 */
+   FEMF_W2G_AC_Lim = DXS_Misc_RoundDiv(
+                                     pGR909Conf->FEMF_W2G_AC_Lim * 1414, 10000);
+   /* FEMF Wire to Wire AC Limit, [mVrms] */
+   /* FemfW2wAcLim = V lim [V rms ] * 141.4 */
+   FEMF_W2W_AC_Lim = DXS_Misc_RoundDiv(
+                                     pGR909Conf->FEMF_W2W_AC_Lim * 1414, 10000);
+   /* FEMF Wire to GND DC Limit, [mV] */
+   /* FemfW2gDcLim = V lim [V] * 100 */
+   FEMF_W2G_DC_Lim = DXS_Misc_RoundDiv(pGR909Conf->FEMF_W2G_DC_Lim, 10);
+   /* FEMF Wire to Wire DC Limit, [mV] */
+   /* FemfW2wDcLim = V lim [V] * 100 */
+   FEMF_W2W_DC_Lim = DXS_Misc_RoundDiv(pGR909Conf->FEMF_W2W_DC_Lim, 10);
+   /* RFT Resistance Limit, [Ohm] */
+   /* RftResLim = R lim [Ohm] / 16 */
+   RFT_Res_Lim = DXS_Misc_RoundDiv(pGR909Conf->RFT_Res_Lim, 16);
+   /* ROH Linearity Limit, [%] */
+   /* RohLinLim = Limit[%] */
+   ROH_Lin_Lim = pGR909Conf->ROH_Lin_Lim;
+   /* RIT Lower Limit, [Ohm] */
+   /* RitLowLim = Z lim [Ohm] / 16 */
+   RIT_Low_Lim = DXS_Misc_RoundDiv(pGR909Conf->RIT_Low_Lim, 16);
+   /* RIT Higher Limit, [Ohm] */
+   /* RitHighLim = Z lim [Ohm] / 16 */
+   RIT_High_Lim = DXS_Misc_RoundDiv(pGR909Conf->RIT_High_Lim, 16);
+
+   if (settle_time != p->gr909cfg.SettleTime ||
+                        HPT_W2G_AC_Lim != p->gr909cfg.HptW2gAcLim ||
+                        HPT_W2W_AC_Lim != p->gr909cfg.HptW2wAcLim ||
+                        HPT_W2G_DC_Lim != p->gr909cfg.HptW2gDcLim ||
+                        HPT_W2W_DC_Lim != p->gr909cfg.HptW2wDcLim ||
+                        FEMF_W2G_AC_Lim != p->gr909cfg.FemfW2gAcLim ||
+                        FEMF_W2W_AC_Lim != p->gr909cfg.FemfW2wAcLim ||
+                        FEMF_W2G_DC_Lim != p->gr909cfg.FemfW2gDcLim ||
+                        FEMF_W2W_DC_Lim != p->gr909cfg.FemfW2wDcLim ||
+                        RFT_Res_Lim != p->gr909cfg.RftResLim ||
+                        ROH_Lin_Lim != p->gr909cfg.RohLinLim ||
+                        RIT_Low_Lim != p->gr909cfg.RitLowLim ||
+                        RIT_High_Lim != p->gr909cfg.RitHighLim)
+   {
+      /* write new values */
+      p->gr909cfg.SettleTime = settle_time;
+      p->gr909cfg.HptW2gAcLim = HPT_W2G_AC_Lim;
+      p->gr909cfg.HptW2wAcLim = HPT_W2W_AC_Lim;
+      p->gr909cfg.HptW2gDcLim = HPT_W2G_DC_Lim;
+      p->gr909cfg.HptW2wDcLim = HPT_W2W_DC_Lim;
+      p->gr909cfg.FemfW2gAcLim = FEMF_W2G_AC_Lim;
+      p->gr909cfg.FemfW2wAcLim = FEMF_W2W_AC_Lim;
+      p->gr909cfg.FemfW2gDcLim = FEMF_W2G_DC_Lim;
+      p->gr909cfg.FemfW2wDcLim = FEMF_W2W_DC_Lim;
+      p->gr909cfg.RftResLim = RFT_Res_Lim;
+      p->gr909cfg.RohLinLim = ROH_Lin_Lim;
+      p->gr909cfg.RitLowLim = RIT_Low_Lim;
+      p->gr909cfg.RitHighLim = RIT_High_Lim;
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->gr909cfg);
+      if (err)
+         DXS_RETURN(err);
+   }
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to get GR-909 limits
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   pGR909Conf    - pointer to SDD GR909 configuration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_GR909LimitsGet(DXS_CHANNEL_t *pCh,
+                                                  DXS_GR909Config_t *pGR909Conf)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pGR909Conf);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* read configuration from the device */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->gr909cfg,
+                                                      (uint32_t *)&p->gr909cfg);
+   if (err)
+      DXS_RETURN(err);
+
+   /* Calculate the parameters */
+
+   /* Settle Time after Discharge, [ms] */
+   /* SettleTime = Time[ms] / 128 */
+   pGR909Conf->settle_time = p->gr909cfg.SettleTime * 128;
+   /* HPT Wire to GND AC Limit, [mVrms] */
+   /* HptW2gAcLim = V lim [V rms ] * 141.4 */
+   pGR909Conf->HPT_W2G_AC_Lim =
+                         DXS_Misc_RoundDiv(p->gr909cfg.HptW2gAcLim * 10000, 1414);
+   /* HPT Wire to Wire AC Limit, [mVrms] */
+   /* HptW2wAcLim = V lim [V rms ] * 141.4 */
+   pGR909Conf->HPT_W2W_AC_Lim =
+                         DXS_Misc_RoundDiv(p->gr909cfg.HptW2wAcLim * 10000, 1414);
+   /* HPT Wire to GND DC Limit, [mV] */
+   /* HptW2gDcLim = V lim [V] * 100 */
+   pGR909Conf->HPT_W2G_DC_Lim = p->gr909cfg.HptW2gDcLim * 10;
+   /* HPT Wire to Wire DC Limit, [mV] */
+   /* HptW2wDcLim = V lim [V] * 100 */
+   pGR909Conf->HPT_W2W_DC_Lim = p->gr909cfg.HptW2wDcLim * 10;
+   /* FEMF Wire to GND AC Limit, [mVrms] */
+   /* FemfW2gAcLim = V lim [V rms ] * 141.4 */
+   pGR909Conf->FEMF_W2G_AC_Lim =
+                        DXS_Misc_RoundDiv(p->gr909cfg.FemfW2gAcLim * 10000, 1414);
+   /* FEMF Wire to Wire AC Limit, [mVrms] */
+   /* FemfW2wAcLim = V lim [V rms ] * 141.4 */
+   pGR909Conf->FEMF_W2W_AC_Lim =
+                        DXS_Misc_RoundDiv(p->gr909cfg.FemfW2wAcLim * 10000, 1414);
+   /* FEMF Wire to GND DC Limit, [mV] */
+   /* FemfW2gDcLim = V lim [V] * 100 */
+   pGR909Conf->FEMF_W2G_DC_Lim = p->gr909cfg.FemfW2gDcLim * 10;
+   /* FEMF Wire to Wire DC Limit, [mV] */
+   /* FemfW2wDcLim = V lim [V] * 100 */
+   pGR909Conf->FEMF_W2W_DC_Lim = p->gr909cfg.FemfW2wDcLim * 10;
+   /* RFT Resistance Limit, [Ohm] */
+   /* RftResLim = R lim [Ohm] / 16 */
+   pGR909Conf->RFT_Res_Lim = p->gr909cfg.RftResLim * 16;
+   /* ROH Linearity Limit, [%] */
+   /* RohLinLim = Limit[%] */
+   pGR909Conf->ROH_Lin_Lim = p->gr909cfg.RohLinLim;
+   /* RIT Lower Limit, [Ohm] */
+   /* RitLowLim = Z lim [Ohm] / 16 */
+   pGR909Conf->RIT_Low_Lim = p->gr909cfg.RitLowLim * 16;
+   /* RIT Higher Limit, [Ohm] */
+   /* RitHighLim = Z lim [Ohm] / 16 */
+   pGR909Conf->RIT_High_Lim = p->gr909cfg.RitHighLim * 16;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to get GR-909 result
+
+   \param   pCh          - pointer to DXS channel structure
+   \param   pGR909Result - pointer to SDD GR909 result structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_GR909ResultGet(DXS_CHANNEL_t *pCh,
+                                                DXS_GR909Result_t *pGR909Result)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pGR909Result);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* read results from the device */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->gr909res,
+                                                      (uint32_t *)&p->gr909res);
+   if (err)
+      DXS_RETURN(err);
+
+   /* Calculate the parameters */
+   /* The results of the last RIT test are valid.  */
+   pGR909Result->HPT_Valid = p->gr909res.HptValid;
+   pGR909Result->FEMF_Valid = p->gr909res.FemfValid;
+   pGR909Result->RFT_Valid = p->gr909res.RftValid;
+   pGR909Result->ROH_Valid = p->gr909res.RohValid;
+   pGR909Result->RIT_Valid = p->gr909res.RitValid;
+   /* The HPT test passed within the limits. */
+   pGR909Result->HPT_Pass = p->gr909res.HptPass;
+   pGR909Result->FEMF_Pass = p->gr909res.FemfPass;
+   pGR909Result->RFT_Pass = p->gr909res.RftPass;
+   pGR909Result->ROH_Pass = p->gr909res.RohPass;
+   pGR909Result->RIT_Pass = p->gr909res.RitPass;
+
+   if ((pGR909Result->HPT_Valid) || (pGR909Result->FEMF_Valid))
+   {
+      /* Convert to milivolts all the values below */
+      /* Test Result HPT or FEMF AC Ring to GND */
+      /* V [Vrms] = HptAcR2g * 0.00707 */
+      pGR909Result->HPT_AC_R2G =
+                             DXS_Misc_RoundDiv(p->gr909res.HptAcR2g * 707, 100);
+      /* Test Result HPT or FEMF AC Tip to GND */
+      /* V [Vrms] = HptAcT2g * 0.00707 */
+      pGR909Result->HPT_AC_T2G =
+                             DXS_Misc_RoundDiv(p->gr909res.HptAcT2g * 707, 100);
+      /* Test Result HPT or FEMF AC Tip to Ring */
+      /* V [Vrms] = HptAcT2r * 0.00707 */
+      pGR909Result->HPT_AC_T2R =
+                             DXS_Misc_RoundDiv(p->gr909res.HptAcT2r * 707, 100);
+      /* Test Result HPT or FEMF DC Ring to GND */
+      /* V [V] = HptDcR2g * 0.01 */
+      pGR909Result->HPT_DC_R2G = p->gr909res.HptDcR2g * 10;
+      /* Test Result HPT or FEMF DC Tip to GND */
+      /* V [V] = HptDcT2g * 0.01 */
+      pGR909Result->HPT_DC_T2G = p->gr909res.HptDcT2g * 10;
+      /* Test Result HPT or FEMF DC Tip to Ring */
+      /* V [V] = HptDcT2r * 0.01 */
+      pGR909Result->HPT_DC_T2R = p->gr909res.HptDcT2r * 10;
+   }
+   if (pGR909Result->RFT_Valid)
+   {
+      /* Resistive Fault Ring to Ground Result */
+      /* The returned value is represented by a 12-bit mantissa and a 4-
+         bit shift factor (MMMM MMMM MMMM SSSS).
+         R [Ohm] = floor(RftR2g/16)*2^(RftR2g&0xF) */
+      pGR909Result->RFT_R2G = (p->gr909res.RftR2g >> 4) *
+                                              (1 << (0xF & p->gr909res.RftR2g));
+      /* Saturate to 3 MOhm */
+      pGR909Result->RFT_R2G = pGR909Result->RFT_R2G > 3000000 ?
+                                                3000000 : pGR909Result->RFT_R2G;
+      /* Resistive Fault Tip to Ground Result */
+      /* The returned value is represented by a 12-bit mantissa and a 4-
+         bit shift factor (MMMM MMMM MMMM SSSS).
+         R [Ohm] = floor(RftT2g/16)*2^(RftT2g&0xF) */
+      pGR909Result->RFT_T2G = (p->gr909res.RftT2g >> 4) *
+                                              (1 << (0xF & p->gr909res.RftT2g));
+      /* Saturate to 3 MOhm */
+      pGR909Result->RFT_T2G = pGR909Result->RFT_T2G > 3000000 ?
+                                                3000000 : pGR909Result->RFT_T2G;
+      /* Resistive Fault Tip to Ring Result */
+      /* The returned value is represented by a 12-bit mantissa and a 4-
+         bit shift factor (MMMM MMMM MMMM SSSS).
+         R [Ohm] = integer(RftT2r/16)*2^(RftT2r&0xF) */
+      pGR909Result->RFT_T2R = (p->gr909res.RftT2r >> 4) *
+                                              (1 << (0xF & p->gr909res.RftT2r));
+      /* Saturate to 3 MOhm */
+      pGR909Result->RFT_T2R = pGR909Result->RFT_T2R > 3000000 ?
+                                                3000000 : pGR909Result->RFT_T2R;
+   }
+   if (pGR909Result->ROH_Valid)
+   {
+      /* Test Result ROH Low */
+      /* R [Ohm] = RohLow * 16 */
+      pGR909Result->ROH_Low = p->gr909res.RohLow * 16;
+      /* Test Result ROH High */
+      /* R [Ohm] = RohHigh * 16 */
+      pGR909Result->ROH_High = p->gr909res.RohHigh * 16;
+   }
+   if (pGR909Result->RIT_Valid)
+   {
+      /* Test Result RIT */
+      /* Z [Ohm] = RitRes * 16 */
+      pGR909Result->RIT_Res = p->gr909res.RitRes * 16;
+   }
+
+   DXS_RETURN(err);
+}
+#endif /* DXS_FEAT_GR909 */
+
+
+int32_t DXS_SDD_CalibrationNeededSet(DXS_CHANNEL_t *pCh, uint8_t value)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   p->bCalibrationNeeded = value;
+
+   return DXS_statusOk;
+}
+
+int32_t DXS_SDD_CalibrationNeededGet(DXS_CHANNEL_t *pCh, uint8_t* value)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   *value = p->bCalibrationNeeded;
+
+   return DXS_statusOk;
+}
+
+int32_t DXS_SDD_CalibrationInternalSet(DXS_CHANNEL_t *pCh, uint8_t value)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   p->bCalibrationInternal = value;
+
+   return DXS_statusOk;
+}
+
+int32_t DXS_SDD_CalibrationInternalGet(DXS_CHANNEL_t *pCh, uint8_t* value)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   *value = p->bCalibrationInternal;
+
+   return DXS_statusOk;
+}
+
+
+int32_t DXS_SDD_CalibrationRunningSet(DXS_CHANNEL_t *pCh, uint8_t value)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   p->bCalibrationRunning = value;
+
+   return DXS_statusOk;
+}
+
+
+int32_t DXS_SDD_CalibrationRunningGet(DXS_CHANNEL_t *pCh, uint8_t* value)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (p == NULL || !(p->flag & SDD_CH_INITIALIZED))
+      return DXS_statusInvalidParam;
+   *value = p->bCalibrationRunning;
+
+   return DXS_statusOk;
+}
+
+#if defined(DXS_FEAT_CAPMEAS) && defined(DXS_FEAT_GR909)
+/**
+   Function to wait for the opmode to be DISABLED (2 seconds).
+
+   \param   pCh    - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_sdd_olc_wait_opmode_disabled(DXS_CHANNEL_t *pCh)
+{
+   int32_t err;
+   struct timespec ts = {0, 100000000};
+   uint32_t i;
+   DXS_LINE_MODE_t iMode;
+
+   POINTER_ASSERT(pCh);
+
+   for (i = 0; i < 20; i++)
+   {
+      err = DXS_SDD_LineModeGet(pCh, (int*) &iMode);
+      if (!err)
+      {
+         if (iMode == DXS_LINE_FEED_DISABLED)
+         {
+            DXS_RETURN(DXS_statusOk);
+         }
+      }
+      else
+      {
+         DXS_RETURN(err);
+      }
+      nanosleep(&ts, NULL);
+   }
+
+   DXS_RETURN(DXS_statusOLCalibrationWaitError);
+}
+
+/**
+   Function to run open loop calibration
+
+   \param   pCh                  - pointer to DXS channel structure
+   \param   unLoops              - number of loops
+   \param   pOLCalibrationResult - pointer to Open Loop Calibration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_OLCalibration(DXS_CHANNEL_t *pCh, uint8_t unLoops,
+                                      DXS_OLCalibration_t *pOLCalibrationResult)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+   DXS_Capacitance_t xCapMeasurementResult;
+   uint32_t i, uiR2Gtmp, uiT2Gtmp, uiT2Rtmp, uiValTmp, uiValidLoops;
+   struct timespec ts = {0};
+
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pOLCalibrationResult);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* Return if OL calibration is already running */
+   if (p->bOLCalibrationRunning)
+      DXS_RETURN(DXS_statusOLCalibrationInProgress);
+
+   /* Set flag that OL calibration process is started */
+   p->bOLCalibrationRunning = 1;
+
+   /* Set conductance parameters to 0 */
+   p->ol_calibration.GRG = 0;
+   p->ol_calibration.GTG = 0;
+   p->ol_calibration.GTR = 0;
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->ol_calibration);
+   if (err)
+   {
+      p->bOLCalibrationRunning = 0;
+      DXS_RETURN(err);
+   }
+
+   /* Run GR-909 for N times */
+   uiValidLoops = 0;
+   uiR2Gtmp = uiT2Gtmp = uiT2Rtmp = 0;
+   for (i = 0; i < unLoops; i++)
+   {
+      /* Start GR-909 */
+      err = DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_GR909);
+      if (!err)
+      {
+         /* Block untill results are received */
+         clock_gettime (CLOCK_REALTIME, &ts);
+         ts.tv_sec += 5;
+         if (sem_timedwait(&p->ol_calibration_wait_sem, &ts))
+         {
+            /* If timeout occured - stop calibration immediately */
+            p->bOLCalibrationRunning = 0;
+            DXS_RETURN(DXS_statusOLCalibrationNoResults);
+         }
+         /* Verify that new results are received */
+         if (p->bOLCalibrationNltResultRdy)
+         {
+            /* Clear flag in any case */
+            p->bOLCalibrationNltResultRdy = 0;
+            /* Read results */
+            err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->gr909res,
+                                                      (uint32_t *)&p->gr909res);
+            if (!err)
+            {
+               /* Verify that measurements are valid */
+               if (p->gr909res.RftValid)
+               {
+                  /* GTG = 2^16 * 1158 * Gtg[S],
+                     Where Gtg = 1/RftT2g. Default value is 0.
+                     Note: RftT2g is the resistance value measured during open
+                       loop resistance measurement (see SDD_GR909ResultsRead) */
+                  uiValTmp = (p->gr909res.RftR2g >> 4) *
+                                              (1 << (0xF & p->gr909res.RftR2g));
+                  if (uiValTmp)
+                  {
+                     uiValTmp = DXS_Misc_RoundDiv(75890688, uiValTmp);
+                     uiR2Gtmp = uiR2Gtmp + (uiValTmp > 255 ? 255 : uiValTmp);
+                  }
+                  uiValTmp = (p->gr909res.RftT2g >> 4) *
+                                              (1 << (0xF & p->gr909res.RftT2g));
+                  if (uiValTmp)
+                  {
+                     uiValTmp = DXS_Misc_RoundDiv(75890688, uiValTmp);
+                     uiT2Gtmp = uiT2Gtmp + (uiValTmp > 255 ? 255 : uiValTmp);
+                  }
+                  /* GTR = 2^19 * 1158 * Gtr[S] */
+                  uiValTmp = (p->gr909res.RftT2r >> 4) *
+                                              (1 << (0xF & p->gr909res.RftT2r));
+                  if (uiValTmp)
+                  {
+                     uiValTmp = DXS_Misc_RoundDiv(607125504, uiValTmp);
+                     uiT2Rtmp = uiT2Rtmp + (uiValTmp > 255 ? 255 : uiValTmp);
+                  }
+                  uiValidLoops++;
+               }
+               /* Wait for the line feed mode to be restored to DISABLED */
+               err = dxs_sdd_olc_wait_opmode_disabled(pCh);
+            }
+         }
+         else
+            err = DXS_statusOLCalibrationNoResults;
+      }
+      if (err)
+      {
+         p->bOLCalibrationRunning = 0;
+         DXS_RETURN(err);
+      }
+   }
+   /* Calculate average conductances */
+   if (!uiValidLoops)
+   {
+      p->bOLCalibrationRunning = 0;
+      DXS_RETURN(DXS_statusOLCalibrationNoResults);
+   }
+   pOLCalibrationResult->GRG = DXS_Misc_RoundDiv(uiR2Gtmp, uiValidLoops);
+   pOLCalibrationResult->GTG = DXS_Misc_RoundDiv(uiT2Gtmp, uiValidLoops);
+   pOLCalibrationResult->GTR = DXS_Misc_RoundDiv(uiT2Rtmp, uiValidLoops);
+
+   /* Run uncalibrated capacitance measurements for N times */
+   uiR2Gtmp = uiT2Gtmp = uiT2Rtmp = 0;
+   for (i = 0; i < unLoops; i++)
+   {
+      /* Start Capacitance measurements */
+      err = DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_CAP_MEAS);
+      if (!err)
+      {
+         /* Block untill results are received */
+         clock_gettime (CLOCK_REALTIME, &ts);
+         ts.tv_sec += 5;
+         if (sem_timedwait(&p->ol_calibration_wait_sem, &ts))
+         {
+            /* If timeout occured - stop calibration immediately */
+            p->bOLCalibrationRunning = 0;
+            DXS_RETURN(DXS_statusOLCalibrationNoResults);
+         }
+         /* Verify that new results are received */
+         if (p->bOLCalibrationNltResultRdy)
+         {
+            /* Clear flag in any case */
+            p->bOLCalibrationNltResultRdy = 0;
+            /* Read uncalibrated results */
+            err = DXS_SDD_CapMeasurementResultGet(pCh, 0, &xCapMeasurementResult);
+            if (!err)
+            {
+               /* Sum up the values */
+               uiR2Gtmp = uiR2Gtmp + xCapMeasurementResult.Cap_R2G;
+               uiT2Gtmp = uiT2Gtmp + xCapMeasurementResult.Cap_T2G;
+               uiT2Rtmp = uiT2Rtmp + xCapMeasurementResult.Cap_T2R;
+               /* Wait for the line feed mode to be restored to DISABLED */
+               err = dxs_sdd_olc_wait_opmode_disabled(pCh);
+            }
+         }
+         else
+            err = DXS_statusOLCalibrationNoResults;
+      }
+      if (err)
+      {
+         p->bOLCalibrationRunning = 0;
+         DXS_RETURN(err);
+      }
+   }
+   /* Calculate average capacitances */
+   pOLCalibrationResult->CRG = DXS_Misc_RoundDiv(uiR2Gtmp, unLoops);
+   pOLCalibrationResult->CTG = DXS_Misc_RoundDiv(uiT2Gtmp, unLoops);
+   pOLCalibrationResult->CTR = DXS_Misc_RoundDiv(uiT2Rtmp, unLoops);
+
+   /* Write conductance parameters to the firmware */
+   p->ol_calibration.GRG = pOLCalibrationResult->GRG;
+   p->ol_calibration.GTG = pOLCalibrationResult->GTG;
+   p->ol_calibration.GTR = pOLCalibrationResult->GTR;
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->ol_calibration);
+   if (err)
+   {
+      p->bOLCalibrationRunning = 0;
+      DXS_RETURN(err);
+   }
+
+   /* Set capacitance parameters */
+   p->ol_cap_meas_res.Cap_R2G = pOLCalibrationResult->CRG;
+   p->ol_cap_meas_res.Cap_T2G = pOLCalibrationResult->CTG;
+   p->ol_cap_meas_res.Cap_T2R = pOLCalibrationResult->CTR;
+
+   /* Clear OL calibration flag */
+   p->bOLCalibrationRunning = 0;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to set the Open Loop Calibration configuration
+
+   \param   pCh                 - pointer to DXS channel structure
+   \param   pOLCalibration      - pointer to Open Loop Calibration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_OLCalibrationConfigSet(DXS_CHANNEL_t *pCh,
+                                            DXS_OLCalibration_t *pOLCalibration)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pOLCalibration);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* Return if OL calibration is running */
+   if (p->bOLCalibrationRunning)
+      DXS_RETURN(DXS_statusOLCalibrationInProgress);
+
+   /* Write conductance parameters to the firmware */
+   p->ol_calibration.GRG = pOLCalibration->GRG;
+   p->ol_calibration.GTG = pOLCalibration->GTG;
+   p->ol_calibration.GTR = pOLCalibration->GTR;
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->ol_calibration);
+   if (err)
+      DXS_RETURN(err);
+
+   /* Set capacitance parameters */
+   p->ol_cap_meas_res.Cap_R2G = pOLCalibration->CRG;
+   p->ol_cap_meas_res.Cap_T2G = pOLCalibration->CTG;
+   p->ol_cap_meas_res.Cap_T2R = pOLCalibration->CTR;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to get the Open Loop Calibration configuration
+
+   \param   pCh                 - pointer to DXS channel structure
+   \param   pOLCalibration      - pointer to Open Loop Calibration structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_OLCalibrationConfigGet(DXS_CHANNEL_t *pCh,
+                                            DXS_OLCalibration_t *pOLCalibration)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+   int32_t err = DXS_statusOk;
+
+   POINTER_ASSERT(pCh);
+   POINTER_ASSERT(pOLCalibration);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* Read conductance parameters from the firmware */
+   err = DXS_CmdRead(pCh->pParent, (uint32_t *)&p->ol_calibration,
+                                                (uint32_t *)&p->ol_calibration);
+   if (err)
+      DXS_RETURN(err);
+
+   pOLCalibration->GRG = p->ol_calibration.GRG;
+   pOLCalibration->GTG = p->ol_calibration.GTG;
+   pOLCalibration->GTR = p->ol_calibration.GTR;
+   /* Get capacitance parameters */
+   pOLCalibration->CRG = p->ol_cap_meas_res.Cap_R2G;
+   pOLCalibration->CTG = p->ol_cap_meas_res.Cap_T2G;
+   pOLCalibration->CTR = p->ol_cap_meas_res.Cap_T2R;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to signal OLCalibration that Capacitance or GR-909 measurements are
+      finished.
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   bAbort - indicates that measurements were aborted
+
+   \return
+   - DXS_status_t
+*/
+int32_t obx_DXS_SDD_OLCalibrationFinished(DXS_CHANNEL_t *pCh, uint8_t bAbort)
+{
+   DXS_SDD_Ch_Resource_t  *p;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   /* Indicate that results are ready and wake up ol_calibration */
+   if (p->bOLCalibrationRunning)
+   {
+      if (!bAbort)
+         p->bOLCalibrationNltResultRdy = 1;
+      sem_post(&p->ol_calibration_wait_sem);
+   }
+
+   DXS_RETURN(DXS_statusOk);
+}
+#endif /* DXS_FEAT_CAPMEAS && DXS_FEAT_GR909 */
+
+#ifdef DXS_FEAT_ACMETER
+/**
+   ACLM gain calculator.
+
+   \param      qFactor   - factor in Q4.27 format
+   \return
+   - int32_t   calculated gain in 0.1[dB] units
+*/
+static int32_t dxs_aclm_gain_calc (int32_t qFactor)
+{
+   int32_t qCorrection_dB = 0, qTmp, qGain;
+
+   if (qFactor != 0)
+   {
+      /* calculate gain correction, dB */
+      while ((qTmp = DXS_Misc_Q4_27_Mul(qFactor, Q4_27_TEN)) < Q4_27_ONE)
+      {
+         qCorrection_dB += Q15_16_ONE;
+         qFactor = qTmp;
+      }
+      /* shift to Q15.16 scale */
+      qFactor >>= 11;
+      /* calculate log10 */
+      qGain = DXS_Misc_Q15_16_Log10(qFactor);
+      /* apply gain correction, dB */
+      qGain -= qCorrection_dB;
+      /* final gain, dB, in Q15.16 */
+      qGain = DXS_Misc_Q15_16_Mul(Q15_16_TEN, qGain) + Q15_16__3_14;
+      /* switch to 0.1 dB units */
+      qGain = DXS_Misc_Q15_16_Mul(qGain, Q15_16_TEN);
+      /* round up */
+      qGain += (qGain >= 0 ? Q15_16_HALF : -(Q15_16_HALF));
+   }
+   else
+   {
+      /* -87.17 dBm0 */
+      qGain = 0xFC98500C;
+   }
+
+   return (int32_t)DXS_Misc_Q15_16_to_Float(qGain);
+}
+
+/**
+   ACLM core function. Called for all measurement types.
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   inb    - ACLM measurement inband result
+   \param   outb   - ACLM measurement outband result
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_aclm (DXS_CHANNEL_t *pCh, int32_t *inb, int32_t *outb)
+{
+   /* no parameter sanity check - already done in a calling function */
+   DXS_SDD_Ch_Resource_t *p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   DXS_FW_SDD_AcLevelMeterControl_t *pAcLmCtrl = &p->aclm_ctrl;
+   int32_t err;
+   DXS_FW_SDD_AcLevelMeterResult_t *pAclmRes = &p->aclm_result;
+   struct timespec ts = {0};
+
+   /* enable AC measurement */
+   pAcLmCtrl->EN = 1;
+   err = CmdWrite(pCh->pParent, (uint32_t *)pAcLmCtrl);
+   if (err)
+      DXS_RETURN(err);
+
+   clock_gettime (CLOCK_REALTIME, &ts);
+   ts.tv_sec += 3;
+   err = sem_timedwait(&p->aclm_sig_sem, &ts);
+   if (!err)
+   {
+      /* read the measurement result */
+      err = DXS_CmdRead(pCh->pParent,
+                         (uint32_t *)pAclmRes, (uint32_t *)pAclmRes);
+
+      if (!err)
+      {
+         DXS_FW_SDD_AcLevelMeterConfig_t *pAclmConf = &p->aclm_config;
+         int32_t shift, qPeakLevel;
+         float   fInput;
+
+         /* inband calculation */
+         shift = 21 - pAclmRes->AcInbSh;
+         if (shift >= 0)
+         {
+            /* input value */
+            fInput =
+               (float)pAclmRes->AcInb/(1 << shift)/(pAclmConf->Int << 3);
+            /* peak level in Q4.27 */
+            qPeakLevel = DXS_Misc_Float_to_Q4_27(fInput);
+            /* calculate resulting gain from factor */
+            *inb = dxs_aclm_gain_calc(qPeakLevel);
+         }
+         else
+         {
+            DXS_RETURN(DXS_statusAclmInbCalcError);
+         }
+
+         /* outband calculation */
+         shift = 21 - pAclmRes->AcOutbSh;
+         if (shift >= 0)
+         {
+            /* input value */
+            fInput =
+               (float)pAclmRes->AcOutb/(1 << shift)/(pAclmConf->Int << 3);
+            /* peak level in Q4.27 */
+            qPeakLevel = DXS_Misc_Float_to_Q4_27(fInput);
+            /* calculate resulting gain from factor */
+            *outb = dxs_aclm_gain_calc(qPeakLevel);
+         }
+         else
+         {
+            DXS_RETURN(DXS_statusAclmOutbCalcError);
+         }
+      }
+   }
+   DXS_RETURN(err);
+}
+
+/**
+   ACLM function for Frequency Response and Transhybrid measurements.
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   type   - ACLM measurement code
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_aclm_fr_th(DXS_CHANNEL_t *pCh, DXS_ACLM_Measurement_t type)
+{
+   DXS_SDD_Ch_Resource_t *pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   DXS_FW_SDD_AcLevelMeterConfig_t   *pAcLmCfg;
+   int32_t err, inband, outband, ref_level=0;
+   uint16_t freq;
+   int16_t level;
+   uint8_t mpoint=0, measurements;
+
+   if (!(pRes->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   if (pRes->aclm_meas_status == dxs_aclm_in_progress)
+      /* measurement is already running */
+      DXS_RETURN(DXS_statusAclmInProgress);
+
+   /* ACLM start is possible either from DISABLED or ACTIVE opmode */
+   if (pRes->curr_opmode != DXS_LINE_FEED_DISABLED &&
+          pRes->curr_opmode != DXS_LINE_FEED_ACTIVE)
+      DXS_RETURN(DXS_statusAclmStartErrInvOpmode);
+
+   if (pRes->curr_opmode == DXS_LINE_FEED_DISABLED)
+   {
+      DXS_LINE_MODE_t opmode;
+
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE);
+      /* continue only if line mode has really switched to ACTIVE */
+      if (DXS_statusOk == DXS_SDD_LineModeGet(pCh, (int *)&opmode) &&
+                       opmode == DXS_LINE_FEED_ACTIVE)
+      {
+         struct timespec ts = {0, 150000000L};
+
+         /* delay 150 ms */
+         nanosleep(&ts, NULL);
+         pRes->bAclmRestoreDisabled = 1;
+      }
+      else
+      {
+         DXS_RETURN(DXS_statusAclmStartErrActOpmodeTmout);
+      }
+   }
+   else
+   {
+      pRes->bAclmRestoreDisabled = 0;
+   }
+
+   pRes->aclm_current_meas = type;
+   pRes->aclm_meas_status = dxs_aclm_in_progress;
+
+   /* configure the AC measurement */
+   pAcLmCfg = &pRes->aclm_config;
+   pAcLmCfg->Int = DXS_ACLM_INT_TIME_MS_DEFAULT;
+   pAcLmCfg->Del = DXS_ACLM_AC_DELAY_MS_DEFAULT;
+   pAcLmCfg->BP = 0;
+   if (type == DXS_ACLM_FR)
+   {
+      measurements = DXS_ACLM_FR_MEASUREMENTS;
+      freq = DXS_ACLM_FR_FREQ_CENTER_HZ;
+      level = -100; /* -10.0 dBm0 */
+      pAcLmCfg->TH = 0;
+   }
+   else
+   {
+      measurements = DXS_ACLM_TH_MEASUREMENTS;
+      freq = DXS_ACLM_FR_TH_FREQ_MIN_HZ;
+      level = 0; /* 0.0 dBm0 */
+      pAcLmCfg->TH = 1;
+   }
+   err = CmdWrite(pCh->pParent, (uint32_t *)pAcLmCfg);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+
+   /* configure TG */
+   err = dxs_tone_config(pCh, -869, level, 0, freq, 0, 0);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+
+   /* enable the TG */
+   err = dxs_tone_start(pCh);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+
+#if 0
+   /* for Frequency Response measurement -
+      get the reference level from inband */
+   if (type == DXS_ACLM_FR)
+   {
+      err = dxs_aclm (pCh, &ref_level, &outband);
+      if (err)
+      {
+         pRes->aclm_meas_status = dxs_aclm_aborted;
+         dxs_tone_stop(pCh);
+         DXS_RETURN(err);
+      }
+   }
+#endif
+
+   for (freq = DXS_ACLM_FR_TH_FREQ_MIN_HZ; mpoint < measurements;
+             mpoint++, freq += DXS_ACLM_FR_TH_FREQ_STEP_HZ)
+   {
+      /* configure TG */
+      err = dxs_tone_config(pCh, -869, level, 0, freq, 0, 0);
+      if (err)
+         break;
+
+      /* run the measurement */
+      err = dxs_aclm (pCh, &inband, &outband);
+      if (err == DXS_statusOk)
+      {
+#if 0
+         /* for Frequency Response measurement -
+            subtract the reference level */
+         if (type == DXS_ACLM_FR)
+         {
+            inband -= ref_level;
+            outband -= ref_level;
+         }
+#else
+         if (type == DXS_ACLM_FR && freq == 1000)
+         {
+            ref_level = inband;
+         }
+#endif /*0*/
+
+         /* store the result in a resource context */
+         pRes->aclm_result_tbl_idx = mpoint;
+         pRes->aclm_results[mpoint].arg = freq;
+         pRes->aclm_results[mpoint].value = inband;
+      }
+      else
+      {
+         break;
+      }
+   }
+
+   if (type == DXS_ACLM_FR && err == DXS_statusOk)
+   {
+      /* for Frequency Response measurement -
+         subtract the reference level @1000Hz */
+      for (mpoint = 0; mpoint < measurements; mpoint++)
+      {
+            pRes->aclm_results[mpoint].value -= ref_level;
+      }
+   }
+
+   /* stop TG */
+   dxs_tone_stop(pCh);
+
+   if (pRes->bAclmRestoreDisabled)
+   {
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+   }
+
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+   }
+   else
+   {
+      pRes->aclm_meas_status = dxs_aclm_finished;
+   }
+
+   DXS_RETURN(err);
+}
+
+/**
+   ACLM function for Gain Tracking measurement.
+
+   \param   pCh    - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_aclm_gt (DXS_CHANNEL_t *pCh)
+{
+   DXS_SDD_Ch_Resource_t *pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   DXS_FW_SDD_AcLevelMeterConfig_t   *pAcLmCfg;
+   int32_t err, ref_level, inband, outband, level;
+   uint8_t mpoint=0;
+
+   if (!(pRes->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   if (pRes->aclm_meas_status == dxs_aclm_in_progress)
+      /* measurement is already running */
+      DXS_RETURN(DXS_statusAclmInProgress);
+
+   /* ACLM start is possible either from DISABLED or ACTIVE opmode */
+   if (pRes->curr_opmode != DXS_LINE_FEED_DISABLED &&
+          pRes->curr_opmode != DXS_LINE_FEED_ACTIVE)
+      DXS_RETURN(DXS_statusAclmStartErrInvOpmode);
+
+   if (pRes->curr_opmode == DXS_LINE_FEED_DISABLED)
+   {
+      DXS_LINE_MODE_t opmode;
+
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE);
+      /* continue only if line mode has really switched to ACTIVE */
+      if (DXS_statusOk == DXS_SDD_LineModeGet(pCh, (int *)&opmode) &&
+                       opmode == DXS_LINE_FEED_ACTIVE)
+      {
+         struct timespec ts = {0, 150000000L};
+
+         /* delay 150 ms */
+         nanosleep(&ts, NULL);
+         pRes->bAclmRestoreDisabled = 1;
+      }
+      else
+      {
+         DXS_RETURN(DXS_statusAclmStartErrActOpmodeTmout);
+      }
+   }
+   else
+   {
+      pRes->bAclmRestoreDisabled = 0;
+   }
+
+   pRes->aclm_current_meas = DXS_ACLM_GT;
+   pRes->aclm_meas_status = dxs_aclm_in_progress;
+
+   /* configure the AC measurement */
+   pAcLmCfg = &pRes->aclm_config;
+   pAcLmCfg->Int = DXS_ACLM_INT_TIME_MS_DEFAULT;
+   pAcLmCfg->Del = DXS_ACLM_AC_DELAY_MS_DEFAULT;
+   pAcLmCfg->BP = 0;
+   pAcLmCfg->TH = 0;
+   err = CmdWrite(pCh->pParent, (uint32_t *)pAcLmCfg);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+   /* configure TG */
+   err = dxs_tone_config(pCh, -869, -100, 0, DXS_ACLM_FR_FREQ_CENTER_HZ, 0, 0);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+   /* enable the TG */
+   err = dxs_tone_start(pCh);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+   /* measure reference tone from inband */
+   err = dxs_aclm (pCh, &ref_level, &outband);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      dxs_tone_stop(pCh);
+      DXS_RETURN(err);
+   }
+
+   ref_level += 100;
+
+   for (level = DXS_ACLM_GT_LEVEL_MIN_DBM0; mpoint < DXS_ACLM_GT_MEASUREMENTS;
+             mpoint++, level += DXS_ACLM_GT_SNR_LEVEL_STEP_DBM0)
+   {
+      err = dxs_tone_config(pCh, -869, (level*10), 0, DXS_ACLM_FR_FREQ_CENTER_HZ, 0, 0);
+      if (err)
+         break;
+
+      /* run the measurement */
+      err = dxs_aclm (pCh, &inband, &outband);
+      if (err == DXS_statusOk)
+      {
+         /* Should the tone level be read back here to avoid rounding effects?
+            Currently no action is taken. */
+
+         inband = inband - 10*level - ref_level;
+
+         /* store the result in a resource context */
+         pRes->aclm_result_tbl_idx = mpoint;
+         pRes->aclm_results[mpoint].arg = level*10;
+         pRes->aclm_results[mpoint].value = inband;
+      }
+      else
+      {
+         break;
+      }
+   }
+
+   /* stop TG */
+   dxs_tone_stop(pCh);
+
+   if (pRes->bAclmRestoreDisabled)
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+
+   if (err)
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+   else
+      pRes->aclm_meas_status = dxs_aclm_finished;
+
+   DXS_RETURN(err);
+}
+
+/**
+   ACLM function for Signal to Noise Ratio measurement.
+
+   \param   pCh    - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+static int32_t dxs_aclm_snr (DXS_CHANNEL_t *pCh)
+{
+   DXS_SDD_Ch_Resource_t *pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+   DXS_FW_SDD_AcLevelMeterConfig_t   *pAcLmCfg;
+   int32_t err, inband, outband, level;
+   uint8_t mpoint=0;
+   int16_t rxGain, txGain, txGainOriginal;
+
+   if (!(pRes->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   if (pRes->aclm_meas_status == dxs_aclm_in_progress)
+      /* measurement is already running */
+      DXS_RETURN(DXS_statusAclmInProgress);
+
+   /* ACLM start is possible either from DISABLED or ACTIVE opmode */
+   if (pRes->curr_opmode != DXS_LINE_FEED_DISABLED &&
+          pRes->curr_opmode != DXS_LINE_FEED_ACTIVE)
+      DXS_RETURN(DXS_statusAclmStartErrInvOpmode);
+
+   if (pRes->curr_opmode == DXS_LINE_FEED_DISABLED)
+   {
+      DXS_LINE_MODE_t opmode;
+
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_ACTIVE);
+      /* continue only if line mode has really switched to ACTIVE */
+      if (DXS_statusOk == DXS_SDD_LineModeGet(pCh, (int *)&opmode) &&
+                       opmode == DXS_LINE_FEED_ACTIVE)
+      {
+         struct timespec ts = {0, 150000000L};
+
+         /* delay 150 ms */
+         nanosleep(&ts, NULL);
+         pRes->bAclmRestoreDisabled = 1;
+      }
+      else
+      {
+         DXS_RETURN(DXS_statusAclmStartErrActOpmodeTmout);
+      }
+   }
+   else
+   {
+      pRes->bAclmRestoreDisabled = 0;
+   }
+
+   pRes->aclm_current_meas = DXS_ACLM_SNR;
+   pRes->aclm_meas_status = dxs_aclm_in_progress;
+
+   /* configure the AC measurement */
+   pAcLmCfg = &pRes->aclm_config;
+   pAcLmCfg->Int = DXS_ACLM_INT_TIME_MS_DEFAULT;
+   pAcLmCfg->Del = 50;
+   pAcLmCfg->BP = 1;
+   pAcLmCfg->TH = 0;
+   pAcLmCfg->BW = 864;
+   pAcLmCfg->CF = 22804;
+   err = CmdWrite(pCh->pParent, (uint32_t *)pAcLmCfg);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+
+   /* configure TxRx gain to 0 dBr */
+   err = DXS_SDD_GainGet(pCh, &txGain, &rxGain);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+   /* remember original Tx gain */
+   txGainOriginal = txGain;
+   err = DXS_SDD_GainSet(pCh, 0, rxGain);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+
+   /* configure TG */
+   err = dxs_tone_config(pCh, -869, (DXS_ACLM_SNR_LEVEL_MIN_DBM0*10), 0, DXS_ACLM_FR_FREQ_CENTER_HZ, 0, 0);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+   /* enable the TG */
+   err = dxs_tone_start(pCh);
+   if (err)
+   {
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+      DXS_RETURN(err);
+   }
+
+   for (level = DXS_ACLM_SNR_LEVEL_MIN_DBM0; mpoint < DXS_ACLM_SNR_MEASUREMENTS;
+             mpoint++, level += DXS_ACLM_GT_SNR_LEVEL_STEP_DBM0)
+   {
+      err = dxs_tone_config(pCh, -869, (level*10), 0, DXS_ACLM_FR_FREQ_CENTER_HZ, 0, 0);
+      if (err)
+         break;
+
+#if 0
+      if (level > -10)
+      {
+         /* set gain 10 dBr */
+         DXS_SDD_GainSet(pCh, -100, rxGain);
+      }
+#else
+      /* automatically increase the attenuation in TX
+         depending on the actual RX gain */
+      txGain = -(200 + rxGain + (level*10));
+      if (txGain > 0)
+         txGain = 0;
+
+      DXS_SDD_GainSet(pCh, txGain, rxGain);
+#endif
+
+      /* run the measurement */
+      err = dxs_aclm (pCh, &inband, &outband);
+      if (err == DXS_statusOk)
+      {
+         /* Should the tone level be read back here to avoid rounding effects?
+            Currently no action is taken. */
+
+         /* store the result in a resource context */
+         pRes->aclm_result_tbl_idx = mpoint;
+         pRes->aclm_results[mpoint].arg = level*10;
+         pRes->aclm_results[mpoint].value = inband - outband;
+      }
+      else
+      {
+         break;
+      }
+   }
+
+   /* stop TG */
+   dxs_tone_stop(pCh);
+
+   /* restore original Tx gain */
+   DXS_SDD_GainSet(pCh, txGainOriginal, rxGain);
+
+   if (pRes->bAclmRestoreDisabled)
+      DXS_SDD_LineModeSet(pCh, DXS_LINE_FEED_DISABLED);
+
+   if (err)
+      pRes->aclm_meas_status = dxs_aclm_aborted;
+   else
+      pRes->aclm_meas_status = dxs_aclm_finished;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to start the ACLM measurement.
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   type   - ACLM measurement code
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_ACLM_Start(DXS_CHANNEL_t *pCh, DXS_ACLM_Measurement_t type)
+{
+   int32_t ret, ret1;
+   POINTER_ASSERT(pCh);
+
+   /* check if ACLM measurement feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_aclm))
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+
+   /* mute PCM channel */
+   if ((ret = dxs_pcm_ch_mute(pCh, 1)) != DXS_statusOk)
+      DXS_RETURN(ret);
+
+   switch (type)
+   {
+      case DXS_ACLM_FR:
+      case DXS_ACLM_TH:
+         ret = dxs_aclm_fr_th(pCh, type);
+         break;
+      case DXS_ACLM_GT:
+         ret = dxs_aclm_gt(pCh);
+         break;
+      case DXS_ACLM_SNR:
+         ret = dxs_aclm_snr(pCh);
+         break;
+      default:
+         ret = DXS_statusParamsOutRange;
+   }
+
+   /* unmute PCM channel */
+   if ((ret1 = dxs_pcm_ch_mute(pCh, 0)) != DXS_statusOk)
+      DXS_RETURN(ret1);
+
+   /* return code
+      from the measurement */
+   DXS_RETURN(ret);
+}
+
+/**
+   Function to retrieve the ACLM measurement results.
+
+   \param   pCh    - pointer to DXS channel structure
+   \param   type   - ACLM measurement code
+   \param   what   - what to output: result number, argument or value
+   \param   index  - ACLM measurement index (point)
+   \param   output - output placeholder
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SDD_ACLM_ResultGet(DXS_CHANNEL_t *pCh, DXS_ACLM_Measurement_t type,
+                               uint8_t what, int32_t index, int32_t *output)
+{
+   DXS_SDD_Ch_Resource_t *p;
+   int32_t ret = DXS_statusOk;
+
+   POINTER_ASSERT(pCh);
+
+   p = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   if (!(p->flag & SDD_CH_INITIALIZED))
+      DXS_RETURN(DXS_statusNotInitResource);
+
+   if (p->aclm_current_meas == type &&
+          p->aclm_meas_status == dxs_aclm_finished)
+   {
+      switch (what)
+      {
+         case DXS_ACLM_RESULT_NUMBER:
+            *output = p->aclm_result_tbl_idx + 1;
+            break;
+         case DXS_ACLM_RESULT_ARG:
+            *output = p->aclm_results[index].arg;
+            break;
+         case DXS_ACLM_RESULT_VALUE:
+            *output = p->aclm_results[index].value;
+            break;
+         default:
+            ret = DXS_statusParamsOutRange;
+      }
+   }
+   else
+   {
+      *output = 0;
+      ret = DXS_statusAclmResultsNotAvail;
+   }
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function to unlock the waiting semaphore.
+   Called from outbox handler.
+
+   \param   pCh    - pointer to DXS channel structure
+
+   \return
+   - none
+*/
+void obx_DXS_SDD_ACLM_Finish(DXS_CHANNEL_t *pCh)
+{
+   DXS_SDD_Ch_Resource_t *pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   sem_post(&pRes->aclm_sig_sem);
+}
+#endif /* DXS_FEAT_ACMETER */
+
+/**
+   Return the ringer status for a channel
+
+   \param   none
+   \return
+   non-zero value if the channel is currently generating
+   ringing voltage, otherwise zero
+*/
+int32_t DXS_SDD_IsRingingUnprot (DXS_CHANNEL_t *pCh)
+{
+   int32_t err;
+   DXS_SDD_Ch_Resource_t *pRes = (DXS_SDD_Ch_Resource_t *)pCh->sdd;
+
+   /* update current opmode,
+      wait while an opmode change is ongoing */
+   err = dxs_sdd_opmode_get(pRes);
+   if (err != DXS_statusOk)
+   {
+      DXS_ERROR_PUSH(err);
+      return 0;
+   }
+
+   if (pRes->curr_opmode == DXS_LINE_FEED_RING_BURST ||
+            pRes->curr_opmode == DXS_LINE_FEED_RINGING_REVPOL)
+      return 1;
+
+   return 0;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_sdd.h b/marvell/services/dxslic/api_lib/src/dxs_sdd.h
new file mode 100644
index 0000000..d98d765
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_sdd.h
@@ -0,0 +1,108 @@
+#ifndef __DXS_SDD_H__
+#define __DXS_SDD_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_sdd.h
+   This file contains the declaration of the functions for SDD operations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+#include "dxs_fw_cmd.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_ACLM_RESULT_NUMBER      100
+#define DXS_ACLM_RESULT_ARG         101
+#define DXS_ACLM_RESULT_VALUE       102
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern void *DXS_SDD_ChInit (uint8_t dev, uint8_t ch);
+extern int32_t DXS_SDD_ChExit (DXS_CHANNEL_t *pCh);
+extern int32_t DXS_SDD_BasicConfigBBD (DXS_CHANNEL_t *pCh,
+                                     struct DXS_basicConfigData *pData);
+extern int32_t DXS_SDD_RingConfigBBD (DXS_CHANNEL_t *pCh,
+                                     struct DXS_FW_SDD_RingConfig *pRingConf);
+extern int32_t DXS_SDD_DcDcConfigBBD (DXS_CHANNEL_t *pCh,
+                                     struct DXS_DcDcConfigData *pData);
+extern int32_t DXS_SDD_MwlConfigBBD (DXS_CHANNEL_t *pCh,
+                                     struct DXS_FW_SDD_MwlConfig *pMwlConf);
+extern int32_t DXS_SDD_RingConfigAPI (DXS_CHANNEL_t *pCh,
+                                       uint8_t waveForm,
+                                       uint8_t crestFactor,
+                                       uint8_t frequency,
+                                       uint16_t amplitude,
+                                       uint16_t dcOffset);
+extern int32_t DXS_SDD_MwlConfigAPI(DXS_CHANNEL_t *pCh,
+                                       uint8_t voltage,
+                                       uint8_t thresh,
+                                       uint16_t slope,
+                                       uint16_t onTime,
+                                       uint16_t offTime);
+extern int32_t DXS_SDD_CoeffBBD(DXS_CHANNEL_t *pCh,
+                                uint8_t dest,
+                                uint16_t blk_offset,
+                                uint8_t blk_len,
+                                uint8_t *pData,
+                                uint16_t padding);
+extern int32_t DXS_SDD_LineModeSet(DXS_CHANNEL_t *pCh, int mode);
+extern int32_t DXS_SDD_LineModeGet(DXS_CHANNEL_t *pCh, int *pMode);
+extern void obx_DXS_SDD_OpmodeUpdate(DXS_CHANNEL_t *pCh, DXS_LINE_MODE_t mode, uint8_t bOPC);
+
+extern int32_t DXS_SDD_GainSet(DXS_CHANNEL_t *pCh, int16_t usGain, int16_t dsGain);
+extern int32_t DXS_SDD_GainGet(DXS_CHANNEL_t *pCh, int16_t *txGain, int16_t *rxGain);
+extern int32_t DXS_SDD_Calibration(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_SDD_Calibration_Finish(DXS_CHANNEL_t *pCh, DXS_Event_t *pEvent);
+extern int32_t DXS_SDD_CalibrationNeededSet(DXS_CHANNEL_t *pCh, uint8_t value);
+extern int32_t DXS_SDD_CalibrationNeededGet(DXS_CHANNEL_t *pCh, uint8_t* value);
+extern int32_t DXS_SDD_CalibrationInternalSet(DXS_CHANNEL_t *pCh, uint8_t value);
+extern int32_t DXS_SDD_CalibrationInternalGet(DXS_CHANNEL_t *pCh, uint8_t* value);
+extern int32_t DXS_SDD_CalibrationRunningSet(DXS_CHANNEL_t *pCh, uint8_t value);
+extern int32_t DXS_SDD_CalibrationRunningGet(DXS_CHANNEL_t *pCh, uint8_t* value);
+extern int32_t DXS_SDD_CalibrationGet(DXS_CHANNEL_t *pCh, DXS_Calibration_t *pCalibration);
+extern int32_t DXS_SDD_CalibrationSet(DXS_CHANNEL_t *pCh, DXS_Calibration_t *pCalibration);
+extern int32_t DXS_SDD_ContMeasurementResultGet(DXS_CHANNEL_t *pCh,
+                                 DXS_ContMeasurementResult_t *pContMeasurement);
+extern int32_t DXS_SDD_CapMeasurementResultGet(DXS_CHANNEL_t *pCh,
+                          uint8_t bCalibrated, DXS_Capacitance_t *pCapacitance);
+extern int32_t DXS_SDD_GR909LimitsSet(DXS_CHANNEL_t *pCh,
+                                                 DXS_GR909Config_t *pGR909Conf);
+extern int32_t DXS_SDD_GR909LimitsGet(DXS_CHANNEL_t *pCh,
+                                                 DXS_GR909Config_t *pGR909Conf);
+extern int32_t DXS_SDD_GR909ResultGet(DXS_CHANNEL_t *pCh,
+                                               DXS_GR909Result_t *pGR909Result);
+extern int32_t DXS_SDD_OLCalibration(DXS_CHANNEL_t *pCh, uint8_t unLoops,
+                                     DXS_OLCalibration_t *pOLCalibrationResult);
+extern int32_t DXS_SDD_OLCalibrationConfigSet(DXS_CHANNEL_t *pCh,
+                                           DXS_OLCalibration_t *pOLCalibration);
+extern int32_t DXS_SDD_OLCalibrationConfigGet(DXS_CHANNEL_t *pCh,
+                                           DXS_OLCalibration_t *pOLCalibration);
+extern int32_t obx_DXS_SDD_OLCalibrationFinished(DXS_CHANNEL_t *pCh,
+                                                                uint8_t bAbort);
+extern int32_t DXS_SDD_ACLM_Start(DXS_CHANNEL_t *pCh,
+                                     DXS_ACLM_Measurement_t type);
+extern int32_t DXS_SDD_ACLM_ResultGet(DXS_CHANNEL_t *pCh,
+                                     DXS_ACLM_Measurement_t type, uint8_t what,
+                                     int32_t index, int32_t *output);
+extern void obx_DXS_SDD_ACLM_Finish(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_SDD_IsRingingUnprot (DXS_CHANNEL_t *pCh);
+#endif /* __DXS_SDD_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_sig.c b/marvell/services/dxslic/api_lib/src/dxs_sig.c
new file mode 100644
index 0000000..56e827f
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_sig.c
@@ -0,0 +1,1418 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_sig.c
+   Implementation of signalling channel functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs.h"
+#include "dxs_config.h"
+#include "dxs_lib.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_misc.h"
+#include "dxs_init.h"
+#include "dxs_access.h"
+#include "dxs_sdd.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/** Maximum number of CID data bytes sent via one message */
+#define DXS_CID_GEN_DATA_MAX     27
+#define DXS_CID_V23_BEL202        0
+#define DXS_CID_V23_ITU_T         1
+#define DXS_CID_AUTODEACT_OFF     0
+#define DXS_CID_AUTODEACT_ON      1
+#define DXS_CID_HLEV_HIGH         1
+#define DXS_CID_MAX_SEIZURE   32767
+#define DXS_CID_MAX_MARK      32767
+#define DXS_CID_MAX_LEVEL        31
+#define DXS_CID_MIN_LEVEL      -929
+
+/** Maximum number of tones in UTD table */
+#define UTD_COEF_TABLE_MAX  5
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+/** Data structure for DTMF receiver coefficients firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Minimum Signal Level */
+   uint32_t LEVEL : 16;
+   /** Maximal Allowed Signal Twist */
+   uint32_t TWIST : 16;
+#else
+   CMD_HEAD_LE;
+   /** Maximal Allowed Signal Twist */
+   uint32_t TWIST : 16;
+   /** Minimum Signal Level */
+   uint32_t LEVEL : 16;
+#endif
+} __attribute__ ((packed)) DXS_FW_DTMF_RecCoeff_t;
+#define DXS_FW_DTMF_RecCoeff_ECMD    12
+#define DXS_FW_DTMF_RecCoeff_LENGTH  4
+
+/** Data structure for DTMF receiver control firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Enable */
+   uint32_t  EN : 1;
+   /** Reserved */
+   uint32_t  Res02 : 31;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t  Res02 : 31;
+   /** Enable */
+   uint32_t  EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_DTMF_RecCtrl_t;
+#define DXS_FW_DTMF_RecCtrl_ECMD      4
+#define DXS_FW_DTMF_RecCtrl_LENGTH    4
+
+/** Data structure for DTMF generator coefficients firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Level for Frequency 1 (Lower Frequency) */
+   uint32_t LEVEL1 : 16;
+   /** Level for Frequency 2 (Higher Frequency) */
+   uint32_t LEVEL2 : 16;
+   /** Frequency 1 of Tone */
+   uint32_t FREQ1 : 16;
+   /** Frequency 2 of Tone */
+   uint32_t FREQ2 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Level for Frequency 2 (Higher Frequency) */
+   uint32_t LEVEL2 : 16;
+   /** Level for Frequency 1 (Lower Frequency) */
+   uint32_t LEVEL1 : 16;
+   /** Frequency 2 of Tone */
+   uint32_t FREQ2 : 16;
+   /** Frequency 1 of Tone */
+   uint32_t FREQ1 : 16;
+#endif
+} __attribute__ ((packed)) DXS_FW_DTMF_AT_GenCoeff_t;
+#define DXS_FW_DTMF_AT_GenCoeff_ECMD     10
+#define DXS_FW_DTMF_AT_GenCoeff_LENGTH   8
+
+/** Data structure for DTMF generator control firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Status of DTMF/AT Generator */
+   uint32_t EN : 1;
+   /** Reserved */
+   uint32_t Res02 : 14;
+   /** Amplitude Modulation */
+   uint32_t AM : 1;
+   /** Reserved */
+   uint32_t Res03 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res03 : 16;
+   /** Amplitude Modulation */
+   uint32_t AM : 1;
+   /** Reserved */
+   uint32_t Res02 : 14;
+   /** Status of DTMF/AT Generator */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_DTMF_AT_GenCtrl_t;
+#define DXS_FW_DTMF_AT_GenCtrl_ECMD     3
+#define DXS_FW_DTMF_AT_GenCtrl_LENGTH   4
+
+/** Data structure for FSK generator control firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Status of CID sender */
+   uint32_t EN : 1;
+   /** Reserved */
+   uint32_t Res02 : 1;
+   /** Auto Deactivation */
+   uint32_t AD : 1;
+   /** High Level CID Generation Mode */
+   uint32_t HLEV : 1;
+   /** CID Specification */
+   uint32_t V23 : 1;
+   /** Reserved */
+   uint32_t Res03 : 27;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res02 : 27;
+   /** CID Specification */
+   uint32_t V23 : 1;
+   /** High Level CID Generation Mode */
+   uint32_t HLEV : 1;
+   /** Auto Deactivation */
+   uint32_t AD : 1;
+   /** Reserved */
+   uint32_t Res03 : 1;
+   /** Status of CID sender */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_FSK_GenCtrl_t;
+#define DXS_FW_FSK_GenCtrl_ECMD     2
+#define DXS_FW_FSK_GenCtrl_LENGTH   4
+
+/** Data structure for FSK generator coefficients firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** CID Send Level */
+   uint32_t LEVEL : 16;
+   /** Number of Seizure Bits */
+   uint32_t SEIZURE : 16;
+   /** Number of Mark Bits */
+   uint32_t MARK : 16;
+   /** Reserved */
+   uint32_t Res02 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Number of Seizure Bits */
+   uint32_t SEIZURE : 16;
+   /** CID Send Level */
+   uint32_t LEVEL : 16;
+   /** Reserved */
+   uint32_t Res02 : 16;
+   /** Number of Mark Bits */
+   uint32_t MARK : 16;
+
+#endif
+} __attribute__ ((packed)) DXS_FW_FSK_GenCoeff_t;
+#define DXS_FW_FSK_GenCoeff_ECMD     8
+#define DXS_FW_FSK_GenCoeff_LENGTH   8
+
+/** Data structure for FSK generator data firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Number of Data Bytes following */
+   uint32_t NRDATA : 8;
+   /** Data Byte 0 */
+   uint32_t DATA0 : 8;
+   /** Data Byte 1 */
+   uint32_t DATA1 : 8;
+   /** Data Byte 2 */
+   uint32_t DATA2 : 8;
+#else
+   CMD_HEAD_LE;
+   /** Data Byte 2 */
+   uint32_t DATA2 : 8;
+   /** Data Byte 1 */
+   uint32_t DATA1 : 8;
+   /** Data Byte 0 */
+   uint32_t DATA0 : 8;
+   /** Number of Data Bytes following */
+   uint32_t NRDATA : 8;
+#endif
+    /** Data Bytes 3-26 */
+    uint32_t DATA[DXS_CID_GEN_DATA_MAX >> 2];
+} __attribute__ ((packed)) DXS_FW_FSK_GenData_t;
+#define DXS_FW_FSK_GenData_ECMD     9
+#define DXS_FW_FSK_GenData_LENGTH   28
+
+/** Data structure for metering pulse control firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Bit to start or stop the metering pulse */
+   uint32_t EN : 1;
+   /** Reserved */
+   uint32_t Res02 : 31;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res02 : 31;
+   /** Bit to start or stop the metering pulse */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_MeterPulseCtrl_t;
+#define DXS_FW_MeterPulseCtrl_ECMD     4
+#define DXS_FW_MeterPulseCtrl_LENGTH   4
+
+/** Data structure for UTD coefficients firmware command */
+typedef struct
+{
+   struct DXS_FW_Cmd_Header        hdr;
+   struct DXS_FW_SIG_UtdCoeff  content;
+} __attribute__ ((packed)) DXS_FW_SIG_UtdCoeff_t;
+#define DXS_FW_SIG_UtdCoeff_ECMD     18
+#define DXS_FW_SIG_UtdCoeff_LENGTH   16
+
+/** Data structure for UTD control firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+   CMD_HEAD_BE;
+   /** Bit to enable or disable universal tone detector */
+   uint32_t EN : 1;
+   /** Reserved */
+   uint32_t Res02 : 14;
+   /** With this bit the UTD direction can be configured */
+   uint32_t DIR : 1;
+   /** Reserved */
+   uint32_t Res03 : 16;
+#else
+   CMD_HEAD_LE;
+   /** Reserved */
+   uint32_t Res03 : 16;
+   /** With this bit the UTD direction can be configured */
+   uint32_t DIR : 1;
+   /** Reserved */
+   uint32_t Res02 : 14;
+   /** Bit to enable or disable universal tone detector */
+   uint32_t EN : 1;
+#endif
+} __attribute__ ((packed)) DXS_FW_SIG_UtdCtrl_t;
+#define DXS_FW_SIG_UtdCtrl_ECMD    17
+#define DXS_FW_SIG_UtdCtrl_LENGTH   4
+
+/** Data structure for signalling channel resource */
+typedef struct
+{
+   /** status flag */
+   uint32_t         flag;
+#define SIG_CH_INITIALIZED     0x00000001
+
+#ifdef DXS_FEAT_DTMFD
+   /** DTMF Receiver Coefficients */
+   DXS_FW_DTMF_RecCoeff_t dtmf_rec_coef;
+   /** DTMF Receiver Control */
+   DXS_FW_DTMF_RecCtrl_t  dtmf_rec_ctrl;
+#endif /* DXS_FEAT_DTMFD */
+
+#ifdef DXS_FEAT_TG
+   /** DTMF and AT Generator Coefficients */
+   DXS_FW_DTMF_AT_GenCoeff_t dtmf_at_gen_coef;
+   /** DTMF and AT Generator Control */
+   DXS_FW_DTMF_AT_GenCtrl_t  dtmf_at_gen_ctrl;
+#endif /* DXS_FEAT_TG */
+
+#ifdef DXS_FEAT_FSK
+   /** Caller ID Control */
+   DXS_FW_FSK_GenCtrl_t    fsk_ctrl;
+   /** Caller ID Coefficients */
+   DXS_FW_FSK_GenCoeff_t   fsk_coef;
+   /** Caller ID Data */
+   DXS_FW_FSK_GenData_t    fsk_data;
+#endif /* DXS_FEAT_FSK */
+
+#ifdef DXS_FEAT_METERING
+   /** Metering pulse current status */
+   uint8_t bMeterPulse;
+   /** Metering Pulse Control */
+   DXS_FW_MeterPulseCtrl_t  meter_ctrl;
+#endif /* DXS_FEAT_METERING */
+
+#ifdef DXS_FEAT_UTD
+   /** UTD Control */
+   DXS_FW_SIG_UtdCtrl_t  utd_ctrl;
+   /** UTD coefficients */
+   DXS_FW_SIG_UtdCoeff_t utd_coeff;
+   /** Tone index of last active UTD */
+   uint16_t utd_tone_idx;
+#endif /* DXS_FEAT_UTD */
+
+} DXS_SIG_Ch_Resource_t;
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static DXS_SIG_Ch_Resource_t  sig_chan[DXS_MAX_DEVICES * CH_PER_DEVICE] = {0};
+
+static uint16_t dBm0_level_tbl[] = {
+/* 0.0 dBm0 */ 0x592a,
+/* 0.1 dBm0 */ 0x5a32,
+/* 0.2 dBm0 */ 0x5b3e,
+/* 0.3 dBm0 */ 0x5c4c,
+/* 0.4 dBm0 */ 0x5d5e,
+/* 0.5 dBm0 */ 0x5e73,
+/* 0.6 dBm0 */ 0x5f8b,
+/* 0.7 dBm0 */ 0x60a6,
+/* 0.8 dBm0 */ 0x61c4,
+/* 0.9 dBm0 */ 0x62e6,
+/* 1.0 dBm0 */ 0x640b,
+/* 1.1 dBm0 */ 0x6534,
+/* 1.2 dBm0 */ 0x6660,
+/* 1.3 dBm0 */ 0x678f,
+/* 1.4 dBm0 */ 0x68c2,
+/* 1.5 dBm0 */ 0x69f9,
+/* 1.6 dBm0 */ 0x6b33,
+/* 1.7 dBm0 */ 0x6c71,
+/* 1.8 dBm0 */ 0x6db2,
+/* 1.9 dBm0 */ 0x6ef7,
+/* 2.0 dBm0 */ 0x7040,
+/* 2.1 dBm0 */ 0x718d,
+/* 2.2 dBm0 */ 0x72de,
+/* 2.3 dBm0 */ 0x7432,
+/* 2.4 dBm0 */ 0x758b,
+/* 2.5 dBm0 */ 0x76e7,
+/* 2.6 dBm0 */ 0x7847,
+/* 2.7 dBm0 */ 0x79ac,
+/* 2.8 dBm0 */ 0x7b15,
+/* 2.9 dBm0 */ 0x7c82,
+/* 3.0 dBm0 */ 0x7df3,
+/* 3.1 dBm0 */ 0x7f68
+};
+
+#ifdef DXS_FEAT_UTD
+static uint32_t uiUtdMtxInit = 0;
+static pthread_mutex_t utd_tone_mtx;
+static uint8_t UtdTonesNum = 0;
+static struct DXS_SIG_UtdCoefEntry
+{
+   uint16_t unToneIdx;
+   struct DXS_FW_SIG_UtdCoeff coef_data;
+} utd_coef_tbl[UTD_COEF_TABLE_MAX] = {0};
+#endif /* DXS_FEAT_UTD */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/**
+   Function dxs_sig_ch_init
+
+   \param   dev    - device number
+   \param   ch     - channel number
+   \param   nBytes  - size of the buffer
+
+*/
+void *dxs_sig_ch_init(uint8_t dev, uint8_t ch)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (dev >= DXS_MAX_DEVICES || ch >= CH_PER_DEVICE)
+      return (void *)NULL;
+
+   p = &sig_chan[dev * CH_PER_DEVICE + ch];
+
+   p->flag = 0;
+
+#ifdef DXS_FEAT_DTMFD
+   p->dtmf_rec_coef.CMD = CMD_EOP;
+   p->dtmf_rec_coef.MOD = MOD_SIG_DET;
+   p->dtmf_rec_coef.ECMD = DXS_FW_DTMF_RecCoeff_ECMD;
+   p->dtmf_rec_coef.LENGTH = DXS_FW_DTMF_RecCoeff_LENGTH;
+   p->dtmf_rec_coef.CHAN = ch;
+
+   p->dtmf_rec_ctrl.CMD = CMD_EOP;
+   p->dtmf_rec_ctrl.MOD = MOD_SIG_DET;
+   p->dtmf_rec_ctrl.ECMD = DXS_FW_DTMF_RecCtrl_ECMD;
+   p->dtmf_rec_ctrl.LENGTH = DXS_FW_DTMF_RecCtrl_LENGTH;
+   p->dtmf_rec_ctrl.CHAN = ch;
+#endif /* DXS_FEAT_DTMFD */
+
+#ifdef DXS_FEAT_TG
+   p->dtmf_at_gen_coef.CMD = CMD_EOP;
+   p->dtmf_at_gen_coef.MOD = MOD_SIG_GEN;
+   p->dtmf_at_gen_coef.ECMD = DXS_FW_DTMF_AT_GenCoeff_ECMD;
+   p->dtmf_at_gen_coef.LENGTH = DXS_FW_DTMF_AT_GenCoeff_LENGTH;
+   p->dtmf_at_gen_coef.CHAN = ch;
+
+   p->dtmf_at_gen_ctrl.CMD = CMD_EOP;
+   p->dtmf_at_gen_ctrl.MOD = MOD_SIG_GEN;
+   p->dtmf_at_gen_ctrl.ECMD = DXS_FW_DTMF_AT_GenCtrl_ECMD;
+   p->dtmf_at_gen_ctrl.LENGTH = DXS_FW_DTMF_AT_GenCtrl_LENGTH;
+   p->dtmf_at_gen_ctrl.CHAN = ch;
+#endif /* DXS_FEAT_TG */
+
+#ifdef DXS_FEAT_FSK
+   p->fsk_ctrl.CMD = CMD_EOP;
+   p->fsk_ctrl.MOD = MOD_SIG_GEN;
+   p->fsk_ctrl.ECMD = DXS_FW_FSK_GenCtrl_ECMD;
+   p->fsk_ctrl.LENGTH = DXS_FW_FSK_GenCtrl_LENGTH;
+   p->fsk_ctrl.CHAN = ch;
+   /* Only high level is supported. */
+   p->fsk_ctrl.HLEV = DXS_CID_HLEV_HIGH;
+
+   p->fsk_coef.CMD = CMD_EOP;
+   p->fsk_coef.MOD = MOD_SIG_GEN;
+   p->fsk_coef.ECMD = DXS_FW_FSK_GenCoeff_ECMD;
+   p->fsk_coef.LENGTH = DXS_FW_FSK_GenCoeff_LENGTH;
+   p->fsk_coef.CHAN = ch;
+
+   p->fsk_data.CMD = CMD_EOP;
+   p->fsk_data.MOD = MOD_SIG_GEN;
+   p->fsk_data.ECMD = DXS_FW_FSK_GenData_ECMD;
+   p->fsk_data.LENGTH = DXS_FW_FSK_GenData_LENGTH;
+   p->fsk_data.CHAN = ch;
+#endif /* DXS_FEAT_FSK */
+
+#ifdef DXS_FEAT_METERING
+   p->bMeterPulse = 0;
+   p->meter_ctrl.CMD = CMD_EOP;
+   p->meter_ctrl.MOD = MOD_SIG_GEN;
+   p->meter_ctrl.ECMD = DXS_FW_MeterPulseCtrl_ECMD;
+   p->meter_ctrl.LENGTH = DXS_FW_MeterPulseCtrl_LENGTH;
+   p->meter_ctrl.CHAN = ch;
+#endif /* DXS_FEAT_METERING */
+
+#ifdef DXS_FEAT_UTD
+   p->utd_tone_idx = 0;
+
+   p->utd_coeff.hdr.CMD = CMD_EOP;
+   p->utd_coeff.hdr.MOD = MOD_SIG_DET;
+   p->utd_coeff.hdr.ECMD = DXS_FW_SIG_UtdCoeff_ECMD;
+   p->utd_coeff.hdr.LENGTH = DXS_FW_SIG_UtdCoeff_LENGTH;
+   p->utd_coeff.hdr.CHAN = ch;
+
+   p->utd_ctrl.CMD = CMD_EOP;
+   p->utd_ctrl.MOD = MOD_SIG_DET;
+   p->utd_ctrl.ECMD = DXS_FW_SIG_UtdCtrl_ECMD;
+   p->utd_ctrl.LENGTH = DXS_FW_SIG_UtdCtrl_LENGTH;
+   p->utd_ctrl.CHAN = ch;
+#endif /* DXS_FEAT_UTD */
+
+   p->flag |= SIG_CH_INITIALIZED;
+
+   return (void *)p;
+}
+
+#ifdef DXS_FEAT_UTD
+/**
+   Function to initialize UTD mutex
+
+*/
+void dxs_sig_utd_mtx_init()
+{
+   if (!uiUtdMtxInit)
+      pthread_mutex_init(&utd_tone_mtx, NULL);
+
+   uiUtdMtxInit++;
+}
+
+/**
+   Function to destroy UTD mutex and reset UTD tone table
+
+*/
+void dxs_sig_utd_mtx_destroy()
+{
+   int err;
+   if (uiUtdMtxInit)
+      uiUtdMtxInit--;
+
+   if (!uiUtdMtxInit)
+   {
+      err = pthread_mutex_unlock(&utd_tone_mtx);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      err = pthread_mutex_destroy(&utd_tone_mtx);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      UtdTonesNum = 0;
+   }
+}
+#endif /* DXS_FEAT_UTD */
+
+#ifdef DXS_FEAT_DTMFD
+
+/* ============================ DTMF Detection ============================== */
+
+#define DXS_SIG_DTMF_LEVEL_MIN    (-369)  /* in units of 0.1 dBm0 */
+#define DXS_SIG_DTMF_LEVEL_MAX    (-29)   /* in units of 0.1 dBm0 */
+
+#define DXS_SIG_DTMF_TWIST_MIN    10    /* in units of 0.1 dB */
+#define DXS_SIG_DTMF_TWIST_MAX    120   /* in units of 0.1 dB */
+
+/**
+   Function dxs_dtmf_config
+
+   \param   pCh        - pointer to DXS channel structure
+   \param   level      - minimum signal level
+   \param   twist      - maximum allowed twist
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_dtmf_config(DXS_CHANNEL_t *pCh, int16_t level, int16_t twist)
+{
+   DXS_SIG_Ch_Resource_t *p;
+   uint16_t new_LEVEL, new_TWIST;
+   int32_t ret = DXS_statusOk;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (level < DXS_SIG_DTMF_LEVEL_MIN || level > DXS_SIG_DTMF_LEVEL_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   if (twist < DXS_SIG_DTMF_TWIST_MIN || twist > DXS_SIG_DTMF_TWIST_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   /* calculate new values */
+   new_LEVEL = DXS_Misc_MulQ15(DXS_Misc_PowerdB_to_Factor(level), 14173);
+   new_TWIST = DXS_Misc_MulQ15(DXS_Misc_PowerdB_to_Factor(-twist), 29205);
+
+   if (new_LEVEL != p->dtmf_rec_coef.LEVEL ||
+          new_TWIST != p->dtmf_rec_coef.TWIST)
+   {
+      /* write new values */
+      p->dtmf_rec_coef.LEVEL = new_LEVEL;
+      p->dtmf_rec_coef.TWIST = new_TWIST;
+      ret = CmdWrite(pCh->pParent, (uint32_t *)&p->dtmf_rec_coef);
+   }
+
+   return ret;
+}
+
+/**
+   Function dxs_dtmf_enable
+
+   \param   pCh        - pointer to DXS channel structure
+   \param   action     - action enable/disable
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_dtmf_enable(DXS_CHANNEL_t *pCh, uint8_t action)
+{
+   DXS_SIG_Ch_Resource_t *p;
+   int32_t ret = DXS_statusOk;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (p->dtmf_rec_ctrl.EN != action)
+   {
+      p->dtmf_rec_ctrl.EN = action;
+      ret = CmdWrite(pCh->pParent, (uint32_t *)&p->dtmf_rec_ctrl);
+   }
+
+   return ret;
+}
+
+#endif /* DXS_FEAT_DTMFD */
+
+#ifdef DXS_FEAT_TG
+
+#define TG_LEVEL_MIN     (-869)  /* in units of 0.1 dBm0 */
+#define TG_LEVEL_MIN_API (-169)  /* in units of 0.1 dBm0 */
+#define TG_LEVEL_MAX     31      /* in units of 0.1 dBm0 */
+
+#define TG_FREQ_MAX  4000    /* Hz */
+
+/**
+   Function dxs_tone_config
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   level1      - level for frequency 1
+   \param   level2      - level for frequency 2
+   \param   freq1       - tone frequency 1
+   \param   freq2       - tone frequency 2
+   \param   am          - amplitude modulation flag
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_tone_config(DXS_CHANNEL_t *pCh,
+                        int16_t level1, int16_t level2, uint16_t freq1,
+                        uint16_t freq2, uint8_t am, uint8_t called_from_api)
+{
+   DXS_SIG_Ch_Resource_t *p;
+   uint16_t new_level1, new_level2, new_freq1, new_freq2;
+   unsigned long temp;
+   int32_t ret = DXS_statusOk;
+   int16_t tg_level_min = (called_from_api == 0) ? TG_LEVEL_MIN : TG_LEVEL_MIN_API;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (level1 < tg_level_min || level1 > TG_LEVEL_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+   if (level2 < tg_level_min || level2 > TG_LEVEL_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+   if (freq1 >= TG_FREQ_MAX || freq2 >= TG_FREQ_MAX)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+   if (am > 1)
+   {
+      DXS_RETURN(DXS_statusParamsOutRange);
+   }
+
+   /* calculate new values */
+   if (level1 >= 0)
+   {
+      new_level1 = dBm0_level_tbl[level1];
+   }
+   else
+   {
+      new_level1 = DXS_Misc_MulQ15(22826, DXS_Misc_LeveldB_to_Factor(level1));
+   }
+
+   if (level2 >= 0)
+   {
+      new_level2 = dBm0_level_tbl[level2];
+   }
+   else
+   {
+      new_level2 = DXS_Misc_MulQ15(22826, DXS_Misc_LeveldB_to_Factor(level2));
+   }
+
+   temp = 8192 * (unsigned long)freq1 / 1000;
+   new_freq1 = (uint16_t)temp;
+   temp = 8192 * (unsigned long)freq2 / 1000;
+   new_freq2 = (uint16_t)temp;
+
+   if (new_level1 != p->dtmf_at_gen_coef.LEVEL1 ||
+       new_level2 != p->dtmf_at_gen_coef.LEVEL2 ||
+       new_freq1 != p->dtmf_at_gen_coef.FREQ1 ||
+       new_freq2 != p->dtmf_at_gen_coef.FREQ2)
+   {
+      /* write new values */
+      p->dtmf_at_gen_coef.LEVEL1 = new_level1;
+      p->dtmf_at_gen_coef.LEVEL2 = new_level2;
+      p->dtmf_at_gen_coef.FREQ1 = new_freq1;
+      p->dtmf_at_gen_coef.FREQ2 = new_freq2;
+      ret = CmdWrite(pCh->pParent, (uint32_t *)&p->dtmf_at_gen_coef);
+   }
+
+   if (ret == DXS_statusOk)
+   {
+      p->dtmf_at_gen_ctrl.AM = am;
+   }
+
+   return ret;
+}
+
+/**
+   Function dxs_tone_start
+
+   \param   pCh         - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_tone_start(DXS_CHANNEL_t *pCh)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (p->dtmf_at_gen_ctrl.EN == 1)
+   {
+      /* parameters aren't changed */
+      return DXS_statusOk;
+   }
+
+   /* AM field is already set by dxs_tone_config() */
+
+   p->dtmf_at_gen_ctrl.EN = 1;
+
+   return CmdWrite(pCh->pParent, (uint32_t *)&p->dtmf_at_gen_ctrl);
+}
+
+/**
+   Function dxs_tone_stop
+
+   \param   pCh         - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_tone_stop(DXS_CHANNEL_t *pCh)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   if (p->dtmf_at_gen_ctrl.EN == 0)
+   {
+      /* parameters aren't changed */
+      return DXS_statusOk;
+   }
+
+   p->dtmf_at_gen_ctrl.EN = 0;
+
+   return CmdWrite(pCh->pParent, (uint32_t *)&p->dtmf_at_gen_ctrl);
+}
+#endif /* DXS_FEAT_TG */
+
+
+#ifdef DXS_FEAT_UTD
+
+/**
+   Get current tone index
+
+   \param   pCh         - pointer to DXS channel structure
+
+   \return
+   - tone index, uint8_t
+*/
+uint8_t DXS_UTD_ToneIdxGet(DXS_CHANNEL_t *pCh)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      return 0;
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   return (uint8_t) p->utd_tone_idx;
+}
+
+#endif /* DXS_FEAT_UTD */
+
+#ifdef DXS_FEAT_METERING
+/**
+   Function to enable metering pulse
+
+   \param   pCh         - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SIG_MeterPulseEnable(DXS_CHANNEL_t *pCh)
+{
+   int32_t err = DXS_statusOk;
+   DXS_SIG_Ch_Resource_t *p;
+   int line_mode;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if TTX feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_ttx))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   /* Verify that line mode is set to Active (normal or reversed) */
+   line_mode = 0;
+   err = DXS_SDD_LineModeGet(pCh, &line_mode);
+   if (err != DXS_statusOk)
+   {
+      DXS_RETURN(err);
+   }
+   if ((line_mode != DXS_LINE_FEED_ACTIVE_REVPOL) &&
+                                            (line_mode != DXS_LINE_FEED_ACTIVE))
+   {
+      DXS_RETURN(DXS_statusMeteringLineModeNotActive);
+   }
+
+   /* Check if metering pulse is already enabled */
+   if (p->bMeterPulse)
+   {
+      DXS_RETURN(DXS_statusMeteringPreviousPulseNotFinished);
+   }
+
+   /* Enable metering pulse */
+   p->meter_ctrl.EN = 1;
+   err = CmdWrite(pCh->pParent, (uint32_t *)&p->meter_ctrl);
+   if (err == DXS_statusOk)
+      p->bMeterPulse = 1;
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to disable metering pulse
+
+   \param   pCh         - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SIG_MeterPulseDisable(DXS_CHANNEL_t *pCh)
+{
+   int32_t err = DXS_statusOk;
+   DXS_SIG_Ch_Resource_t *p;
+   int line_mode;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if TTX feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_ttx))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   /* Verify that line mode is set to Active (normal or reversed) */
+   line_mode = 0;
+   err = DXS_SDD_LineModeGet(pCh, &line_mode);
+   if (err != DXS_statusOk)
+   {
+      DXS_RETURN(err);
+   }
+   if ((line_mode != DXS_LINE_FEED_ACTIVE_REVPOL) &&
+                                            (line_mode != DXS_LINE_FEED_ACTIVE))
+   {
+      /* If line mode is not active then meterig pulse should be disabled already,
+         therefore success can be returned without cmd_read and cmd_write */
+      DXS_RETURN(err);
+   }
+
+   /* Disable metering pulse if it is enabled */
+   if (p->bMeterPulse)
+   {
+      p->meter_ctrl.EN = 0;
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->meter_ctrl);
+      if (err == DXS_statusOk)
+         p->bMeterPulse = 0;
+   }
+
+   DXS_RETURN(err);
+}
+
+/**
+   Function to clear metering pulse status
+
+   \param   pCh         - pointer to DXS channel structure
+
+   \return
+   - DXS_statusOk or DXS_statusInvalidParam
+*/
+int32_t obx_DXS_SIG_MeterPulseStatusClear(DXS_CHANNEL_t *pCh)
+{
+   int32_t err = DXS_statusOk;
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   p->bMeterPulse = 0;
+
+   DXS_RETURN(err);
+}
+#endif /* DXS_FEAT_METERING */
+
+#ifdef DXS_FEAT_FSK
+/**
+   CID Generator Coefficients update
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   level       - FSK send level
+   \param   seizure     - number of seizure bytes
+   \param   mark        - number of mark bits
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_FSK_Configure(DXS_CHANNEL_t *pCh, int16_t level, uint16_t seizure,
+                          uint16_t mark)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if CID/FSK feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_cid))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   if (seizure > DXS_CID_MAX_SEIZURE)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   if (mark > DXS_CID_MAX_MARK)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   if ((level < DXS_CID_MIN_LEVEL) || (level > DXS_CID_MAX_LEVEL))
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   /* calculate new values */
+   if (level >= 0)
+   {
+      p->fsk_coef.LEVEL = dBm0_level_tbl[level];
+   }
+   else
+   {
+      p->fsk_coef.LEVEL = DXS_Misc_MulQ15(22826, DXS_Misc_LeveldB_to_Factor(level));
+   }
+
+   p->fsk_coef.SEIZURE = seizure;
+   p->fsk_coef.MARK = mark;
+
+   return CmdWrite(pCh->pParent, (uint32_t *)&p->fsk_coef);
+}
+
+/**
+   CID Generator Enable
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   standard    - CID standard
+   \param   autodeact   - auto deactivation
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_FSK_Enable(DXS_CHANNEL_t *pCh, uint8_t standard, uint8_t autodeact)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if CID/FSK feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_cid))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   if ((standard != DXS_CID_V23_BEL202) && (standard != DXS_CID_V23_ITU_T))
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   if ((autodeact != DXS_CID_AUTODEACT_ON) &&
+                                           (autodeact != DXS_CID_AUTODEACT_OFF))
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   /* The DTMF and the CID generator should not be enabled at the same time. */
+   if (p->dtmf_at_gen_ctrl.EN == 1)
+   {
+      DXS_RETURN(DXS_statusFskEnableNotAllowed);
+   }
+
+   /* CID Specification can only be changed if the EN bit is set to 0. */
+   if ((p->fsk_ctrl.V23 != standard) && (p->fsk_ctrl.EN == 1))
+   {
+      DXS_RETURN(DXS_statusFskStandardChangeNotAllowed);
+   }
+
+   p->fsk_ctrl.EN = 1;
+   p->fsk_ctrl.AD = autodeact;
+   p->fsk_ctrl.V23 = standard;
+
+   return CmdWrite(pCh->pParent, (uint32_t *)&p->fsk_ctrl);
+}
+
+/**
+   CID Generator Disable
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   autodeact   - auto deactivation
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_FSK_Disable(DXS_CHANNEL_t *pCh, uint8_t autodeact)
+{
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if CID/FSK feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_cid))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   if (p->fsk_ctrl.EN == 0)
+   {
+      /* parameters aren't changed */
+      return DXS_statusOk;
+   }
+
+   p->fsk_ctrl.EN = 0;
+   p->fsk_ctrl.AD = autodeact;
+
+   return CmdWrite(pCh->pParent, (uint32_t *)&p->fsk_ctrl);
+}
+
+/**
+   Send new data to the CID sender
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   nByte       - data buffer size
+   \param   pByte       - pointer to data buffer
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_FSK_Data(DXS_CHANNEL_t *pCh, uint8_t nByte, uint8_t *pByte)
+{
+   DXS_SIG_Ch_Resource_t *p = NULL;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if CID/FSK feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_cid))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   if (nByte > DXS_CID_GEN_DATA_MAX)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   if (pByte == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   /* Fill first 3 bytes of data */
+   if (nByte > 0)
+   {
+      p->fsk_data.DATA0 = pByte[0];
+   }
+
+   if (nByte > 1)
+   {
+      p->fsk_data.DATA1 = pByte[1];
+   }
+
+   if (nByte > 2)
+   {
+      p->fsk_data.DATA2 = pByte[2];
+   }
+
+   if (nByte > 3)
+   {
+      /* Copy the data with endianess respecting. */
+      DXS_cpb2dw(p->fsk_data.DATA, pByte + 3, nByte - 3);
+   }
+
+   /* Set the number of CID bytes to be transmitted. */
+   p->fsk_data.NRDATA = nByte;
+
+   return CmdWrite(pCh->pParent, (uint32_t *)&p->fsk_data);
+}
+#endif /* DXS_FEAT_FSK */
+
+#ifdef DXS_FEAT_UTD
+/**
+   Update tone coefficients in the tone table
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   unToneIdx   - tone index
+   \param   pUtdCoeff   - pointer to UTD coefficients
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SIG_UtdCoeffUpdate(DXS_CHANNEL_t *pCh, uint16_t unToneIdx,
+                                          struct DXS_FW_SIG_UtdCoeff *pUtdCoeff)
+{
+   int32_t ret = DXS_statusOk, err;
+   uint32_t i;
+
+   if (pUtdCoeff == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   err = pthread_mutex_lock(&utd_tone_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   for (i = 0; i < UtdTonesNum; i++)
+   {
+      if (utd_coef_tbl[i].unToneIdx == unToneIdx)
+         break;
+   }
+
+   if (i < UTD_COEF_TABLE_MAX)
+   {
+      /* Tone index or empty record found */
+      if (i >= UtdTonesNum)
+      {
+         utd_coef_tbl[i].unToneIdx = unToneIdx;
+         UtdTonesNum++;
+      }
+      utd_coef_tbl[i].coef_data.BW = pUtdCoeff->BW;
+      utd_coef_tbl[i].coef_data.CF = pUtdCoeff->CF;
+      utd_coef_tbl[i].coef_data.NLEV = pUtdCoeff->NLEV;
+      utd_coef_tbl[i].coef_data.SLEV = pUtdCoeff->SLEV;
+      utd_coef_tbl[i].coef_data.DLEV = pUtdCoeff->DLEV;
+      utd_coef_tbl[i].coef_data.LPCOEFF = pUtdCoeff->LPCOEFF;
+      utd_coef_tbl[i].coef_data.DUP = pUtdCoeff->DUP;
+   }
+   else
+   {
+      /* Tone table is full */
+      ret = DXS_statusError;
+   }
+   err = pthread_mutex_unlock(&utd_tone_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function to enable UTD
+
+   \param   pCh         - pointer to DXS channel structure
+   \param   unToneIdx   - tone index
+   \param   unDirection - direction
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SIG_UtdEnable(DXS_CHANNEL_t *pCh, uint16_t unToneIdx,
+                                                            uint8_t unDirection)
+{
+   int32_t ret = DXS_statusOk, err;
+   DXS_SIG_Ch_Resource_t *p;
+   uint32_t i;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if UTD feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_utd))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   /* Disable UTD if it is enabled */
+   if (p->utd_ctrl.EN)
+   {
+      p->utd_ctrl.EN = 0;
+      ret = CmdWrite(pCh->pParent, (uint32_t *)&p->utd_ctrl);
+      if (ret != DXS_statusOk)
+      {
+         p->utd_ctrl.EN = 1;
+         DXS_RETURN(ret);
+      }
+   }
+
+   err = pthread_mutex_lock(&utd_tone_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* Get UTD coefficients */
+   for (i = 0; i < UtdTonesNum; i++)
+   {
+      if (unToneIdx == utd_coef_tbl[i].unToneIdx)
+         break;
+   }
+   if (i >= UtdTonesNum)
+   {
+      /* Tone with the specified index was not loaded into the tone table */
+      ret = DXS_statusUtdToneIdxMissing;
+   }
+   else
+   {
+      /* Write UTD coefficients to the firmware */
+      p->utd_coeff.content = utd_coef_tbl[i].coef_data;
+      ret = CmdWrite(pCh->pParent, (uint32_t *)&p->utd_coeff);
+   }
+
+   err = pthread_mutex_unlock(&utd_tone_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   if (ret != DXS_statusOk)
+   {
+      DXS_RETURN(ret);
+   }
+
+   /* Enable UTD */
+   p->utd_ctrl.EN = 1;
+   p->utd_ctrl.DIR = unDirection ? 0 : 1;
+   ret = CmdWrite(pCh->pParent, (uint32_t *)&p->utd_ctrl);
+   if (ret != DXS_statusOk)
+   {
+      p->utd_ctrl.EN = 0;
+      DXS_RETURN(ret);
+   }
+
+   /* Update tone index */
+   p->utd_tone_idx = unToneIdx;
+
+   DXS_RETURN(ret);
+}
+
+/**
+   Function to disable UTD
+
+   \param   pCh               - pointer to DXS channel structure
+
+   \return
+   - DXS_status_t
+*/
+int32_t DXS_SIG_UtdDisable(DXS_CHANNEL_t *pCh)
+{
+   int32_t err = DXS_statusOk;
+   DXS_SIG_Ch_Resource_t *p;
+
+   if (pCh == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+   p = (DXS_SIG_Ch_Resource_t *)pCh->sig;
+
+   if (!(p->flag & SIG_CH_INITIALIZED))
+   {
+      DXS_RETURN(DXS_statusNotInitResource);
+   }
+
+   /* check if UTD feature is supported */
+   if (!DXS_IsFeatureSupported(pCh->pParent, dxs_cap_utd))
+   {
+      DXS_RETURN(DXS_statusFeatNotSupportedCaps);
+   }
+
+   /* Disable UTD if it is enabled */
+   if (p->utd_ctrl.EN)
+   {
+      p->utd_ctrl.EN = 0;
+      err = CmdWrite(pCh->pParent, (uint32_t *)&p->utd_ctrl);
+      if (err != DXS_statusOk)
+         p->utd_ctrl.EN = 1;
+   }
+
+   DXS_RETURN(err);
+}
+#endif /* DXS_FEAT_UTD */
+
diff --git a/marvell/services/dxslic/api_lib/src/dxs_sig.h b/marvell/services/dxslic/api_lib/src/dxs_sig.h
new file mode 100644
index 0000000..d9397cc
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_sig.h
@@ -0,0 +1,62 @@
+#ifndef __DXS_SIG_H__
+#define __DXS_SIG_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_sig.h
+   Signalling channel functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs_lib.h"
+#include "dxs_fw_cmd.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern void *dxs_sig_ch_init(uint8_t dev, uint8_t ch);
+extern void dxs_sig_utd_mtx_init();
+extern void dxs_sig_utd_mtx_destroy();
+
+extern int32_t dxs_dtmf_config(DXS_CHANNEL_t *pCh, int16_t level,
+                               int16_t twist);
+extern int32_t dxs_dtmf_enable(DXS_CHANNEL_t *pCh, uint8_t action);
+extern int32_t DXS_SIG_MeterPulseEnable(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_SIG_MeterPulseDisable(DXS_CHANNEL_t *pCh);
+extern int32_t obx_DXS_SIG_MeterPulseStatusClear(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_FSK_Configure(DXS_CHANNEL_t *pCh, int16_t level,
+                                 uint16_t seizure, uint16_t mark);
+extern int32_t DXS_FSK_Enable(DXS_CHANNEL_t *pCh, uint8_t standard, uint8_t autodeact);
+extern int32_t DXS_FSK_Disable(DXS_CHANNEL_t *pCh, uint8_t autodeact);
+extern int32_t DXS_FSK_Data(DXS_CHANNEL_t *pCh, uint8_t nByte, uint8_t *pByte);
+extern uint8_t DXS_UTD_ToneIdxGet(DXS_CHANNEL_t *pCh);
+extern int32_t DXS_SIG_UtdCoeffUpdate(DXS_CHANNEL_t *pCh, uint16_t unToneIdx,
+                                         struct DXS_FW_SIG_UtdCoeff *pUtdCoeff);
+extern int32_t DXS_SIG_UtdEnable(DXS_CHANNEL_t *pCh, uint16_t unToneIdx,
+                                                           uint8_t unDirection);
+extern int32_t DXS_SIG_UtdDisable(DXS_CHANNEL_t *pCh);
+extern int32_t dxs_tone_start(DXS_CHANNEL_t *pCh);
+extern int32_t dxs_tone_stop(DXS_CHANNEL_t *pCh);
+extern int32_t dxs_tone_config(DXS_CHANNEL_t *pCh,
+                        int16_t level1, int16_t level2, uint16_t freq1,
+                        uint16_t freq2, uint8_t am, uint8_t called_from_api);
+#endif /* __DXS_SIG_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_spi.h b/marvell/services/dxslic/api_lib/src/dxs_spi.h
new file mode 100644
index 0000000..f77d725
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_spi.h
@@ -0,0 +1,42 @@
+#ifndef __DXS_SPI_H__
+#define __DXS_SPI_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_spi.h
+   SPI functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern int dxs_spi_linux_init(uint8_t cs, uint8_t access);
+extern void dxs_spi_linux_exit(int fd);
+extern int32_t dxs_spi_linux_read_write(
+                        int fd,
+                        uint8_t *tx_buf,
+                        uint8_t *rx_buf,
+                        uint32_t length);
+
+#endif /* __DXS_SPI_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_spi_linux.c b/marvell/services/dxslic/api_lib/src/dxs_spi_linux.c
new file mode 100644
index 0000000..0ad6596
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_spi_linux.c
@@ -0,0 +1,128 @@
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_spi_linux.c
+   Implementation of SPI functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+#include <linux/types.h>
+#include <linux/spi/spidev.h>
+
+#include "dxs_access.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+
+#include "dxslic_spi.h"
+#include "spidev.h"
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/* TODO: pull to the API ? */
+#ifndef SPI_BUS_NUMBER
+#define SPI_BUS_NUMBER    32766
+#endif
+#define SPI_BITS_PER_WORD 8
+#define SPI_SPEED_HZ      8192000
+#define SPI_SPEED_CSI_HZ  2048000
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+/**
+   Function dxs_spi_linux_init
+
+   \param   cs    - cs
+
+   \return
+   - int
+*/
+int dxs_spi_linux_init(uint8_t cs, uint8_t access)
+{
+   return dxslic_spiObj.spi_fd;
+}
+
+/**
+   Function dxs_spi_linux_exit
+
+   \param   fd    - fd
+
+*/
+void dxs_spi_linux_exit(int fd)
+{
+   close (fd);
+}
+
+/**
+   Function dxs_spi_linux_read_write
+
+   \param   fd      - fd
+   \param   tx_buf  - pointer to tx buffer
+   \param   rx_buf  - pointer to rx buffer
+   \param   length  - size of the buffer
+
+   \remark Both buffers need to be of the same size which is given in the length
+           parameter.
+
+   \return
+   - DXS_statusOk or DXS_statusSpiTxLenError
+*/
+int32_t dxs_spi_linux_read_write(
+                        int fd,
+                        uint8_t *tx_buf,
+                        uint8_t *rx_buf,
+                        uint32_t length)
+{
+   int32_t   ret = 0;
+
+   struct spi_ioc_transfer tr = {0};
+
+   /* Access SPI for full duplex reading and writing. */
+   tr.tx_buf = (unsigned long)tx_buf;
+   tr.rx_buf = (unsigned long)rx_buf;
+   tr.len = length;
+      
+   ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+   if (ret < 0)
+   {
+      fprintf (stderr, "%s:%d SPI_IOC_MESSAGE ret=%d\n",
+               __FILE__, __LINE__, ret);
+      DXS_RETURN(DXS_statusSpiAccError);
+   }
+   
+   return ret == length ? DXS_statusOk : DXS_statusSpiTxLenError;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_timer.c b/marvell/services/dxslic/api_lib/src/dxs_timer.c
new file mode 100644
index 0000000..fb3c1e7
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_timer.c
@@ -0,0 +1,881 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_timer.c
+   This file contains the implementation of timers used in DXS driver.
+*/
+
+/* ========================================================================= */
+/*                                 Includes                                  */
+/* ========================================================================= */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <errno.h>
+
+#include "dxs_timer.h"
+
+/* ========================================================================= */
+/*                             Macro definitions                             */
+/* ========================================================================= */
+
+/** default timeout thread poll time (in milliseconds),
+    this is the polling time used to check if new entiries/events were added */
+#ifndef TIMEOUT_THREAD_POLL_TIME
+   #define TIMEOUT_THREAD_POLL_TIME   50
+#endif
+
+/** get pointer to payload of given entry */
+#define list_entry_data(ENTRY) ((void *)((char *)ENTRY + sizeof(struct list_entry)))
+
+/** check if list is empty */
+#define is_list_empty(LIST) \
+   (((LIST)->first_element.next == &(LIST)->first_element) ? DXS_TM_TRUE : DXS_TM_FALSE)
+#define foreach_list_entry_safe_ll(PLIST, ENTRY, NEXT_ENTRY) \
+   for ((ENTRY) = (PLIST)->next, (NEXT_ENTRY) = (ENTRY)->next; \
+        (ENTRY)->next != (PLIST)->next; \
+        (ENTRY) = (NEXT_ENTRY), (NEXT_ENTRY) = (ENTRY)->next)
+#define foreach_list_entry(PLIST, ENTRY) \
+   for ((ENTRY) = (PLIST)->first_element.next; \
+        (ENTRY)->next != (PLIST)->first_element.next; \
+        (ENTRY) = (ENTRY)->next)
+
+/* ========================================================================= */
+/*                             Type definitions                              */
+/* ========================================================================= */
+
+/** List entry */
+struct list_entry {
+   /** Previous list entry */
+   struct list_entry *next;
+   /** Next list entry */
+   struct list_entry *prev;
+};
+
+/** List structure */
+struct list {
+   /** Used list entries, this first element is empty
+       and can be used only to pint to other elements */
+   struct list_entry first_element;
+   /** Size of list entry data */
+   size_t payload_size;
+   /** List lock */
+   sem_t lock;
+};
+
+/** timeout descriptor structure */
+struct timeout {
+   /** set DXS_TM_TRUE if handler should be called periodically,
+       otherwise set DXS_TM_FALSE */
+   DXS_TM_BOOL_t bPeriodical;
+   /** timeout argument */
+   unsigned long arg1;
+   /** timeout handler */
+   TIMER_ENTRY handler;
+};
+
+/** timeout list entry */
+struct timeout_list_entry {
+   /** Time when the timeout becomes active (in milliseconds) */
+   time_t timeout_time;
+   /** Time to wait from setting the timeout, used for periodic events */
+   time_t time_in;
+   /** timeout descriptor */
+   struct timeout timeout;
+};
+
+/** timeout control structure */
+struct DXS_TM_Context {
+   /* DXS_TM_TRUE if timers were initialized */
+   DXS_TM_BOOL_t bTimersInialized;
+   /** timeout list */
+   struct list timeout_list;
+   /** Timeout thread control structure */
+   pthread_t timeout_thread_ctrl;
+};
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+
+/** \todo deleting/clean up of timers is missing for user space, it should
+    be called upon closing the tapi thread or even maybe for dev stop */
+/** control structure for timers in user's space */
+struct DXS_TM_Context G_timers /* = {.bTimersInialized = DXS_TM_FALSE} */;
+static volatile sig_atomic_t timer_thr_exit = 0;
+
+/* ========================================================================== */
+/*                                Local functions                             */
+/* ========================================================================== */
+
+static int32_t DXS_TM_list_init(struct list *list, size_t payload_size);
+static void DXS_TM_list_entry_free(struct list *list,
+             struct list_entry *entry);
+static int32_t DXS_TM_lockless_event_remove(struct DXS_TM_Context *context,
+                    struct list_entry *entry_to_remove);
+static int32_t DXS_TM_timeout_event_remove(struct DXS_TM_Context *context,
+                 struct list_entry *timer_entry);
+static void DXS_TM_timeout_event_stop(struct DXS_TM_Context *context,
+                 struct list_entry *timer_entry);
+static struct list_entry *DXS_TM_next_active_event_get(struct DXS_TM_Context *context,
+                    struct timeout *timeout,
+                    time_t * time_to_next_entry);
+static void DXS_TM_list_entry_remove(struct list *list,
+             struct list_entry *entry);
+static void DXS_TM_lockless_event_stop(struct DXS_TM_Context *context,
+                    struct list_entry *entry_to_stop);
+static void *DXS_TM_timeout_thread_main(void *arg);
+static void DXS_TM_list_delete(struct list *list);
+static int32_t DXS_TM_timeout_init(struct DXS_TM_Context *context);
+static struct list_entry *DXS_TM_event_entry_create(struct DXS_TM_Context *context,
+                   const struct timeout *timeout);
+static struct list_entry *DXS_TM_timeout_event_create(struct DXS_TM_Context *context,
+              TIMER_ENTRY handler,
+              unsigned long arg1);
+static int32_t DXS_TM_timeout_event_start(struct DXS_TM_Context *context,
+              struct list_entry *timer_entry,
+              time_t timeout_time, DXS_TM_BOOL_t bPeriodical);
+static int32_t DXS_TM_event_entry_start(struct DXS_TM_Context *context,
+                   struct list_entry *timer_entry,
+                   time_t timeout_time,
+                   DXS_TM_BOOL_t bPeriodical);
+static int32_t DXS_TM_lockless_event_entry_start(struct DXS_TM_Context *context,
+                   struct list_entry *timer_entry,
+                   time_t timeout_time);
+static void DXS_TM_list_entry_add_before(struct list *list,
+            struct list_entry *entry,
+            struct list_entry *new_entry);
+static void DXS_TM_list_entry_add_tail(struct list *list,
+                   struct list_entry *new_entry);
+static void DXS_TM_list_entry_add_after(struct list *list,
+           struct list_entry *entry,
+           struct list_entry *new_entry);
+
+/**
+   Sleep for defined time period.
+
+   \param  pTVal    pointer to timespec structure
+
+   \return
+     - none
+*/
+static void dxs_nanosleep(struct timespec *pTVal)
+{
+   while (1)
+   {
+      int rval = nanosleep(pTVal, pTVal);
+      if (rval == 0)
+      {
+         return;
+      }
+      else
+      {
+         if (errno == EINTR)
+            continue;
+         else
+            return;
+      }
+   }
+}
+
+/**
+   Sleep for an interval in ms.
+
+   \param  sleepTime_ms   sleep time in ms
+
+   \return
+     - none
+*/
+static void dxs_MSecSleep(time_t sleepTime_ms)
+{
+   struct timespec tv;
+   tv.tv_sec = sleepTime_ms/1000;
+   tv.tv_nsec = (long) ((sleepTime_ms - (tv.tv_sec * 1000)) * 1000 * 1000);
+
+   dxs_nanosleep(&tv);
+
+   return;
+}
+
+/**
+   Elapsed time in ms after given timestamp.
+
+   \param  refTime_ms    reference time in ms
+
+   \return
+     - elapsed time in ms as time_t value
+*/
+static time_t dxs_ElapsedTimeMSecGet(
+               time_t refTime_ms)
+{
+   struct timeval tv = {0};
+   time_t   nTime_ms = 0;
+
+   gettimeofday(&tv, NULL);
+   nTime_ms = (time_t)(tv.tv_sec*1000 + (tv.tv_usec) / 1000);
+
+   if ( (refTime_ms == 0) || (refTime_ms > nTime_ms) )
+   {
+      return nTime_ms;
+   }
+
+   return (nTime_ms - refTime_ms);
+}
+
+/**
+   Create new list_entry element and assign a callback function to it.
+
+   \param  context      pointer to tapi timer context structure
+   \param  handler      pointer to callback function
+   \param  arg1         private data for the callback, can be pointer or int
+
+   \return
+     - pointer to newly allocated list_entry
+     - NULL in case of error, return value of DXS_TM_event_entry_create()
+*/
+static struct list_entry *DXS_TM_timeout_event_create(struct DXS_TM_Context *context,
+              TIMER_ENTRY handler,
+              unsigned long arg1)
+{
+   struct timeout timeout;
+
+   timeout.handler = handler;
+   timeout.arg1 = arg1;
+   timeout.bPeriodical = DXS_TM_FALSE;
+
+   return DXS_TM_event_entry_create(context, &timeout);
+}
+
+/**
+   Create new list_entry element, allocate memory and copy timeout data.
+
+   \param  context      pointer to tapi timer context structure
+   \param  timeout      pointer to timeout stucture
+
+   \return
+     - pointer to newly allocated list_entry
+     - NULL in case of error
+*/
+static struct list_entry *DXS_TM_event_entry_create(struct DXS_TM_Context *context,
+                   const struct timeout *timeout)
+{
+   struct list_entry *new_entry;
+   struct timeout_list_entry *new_timeout_entry;
+
+   if (sem_wait(&context->timeout_list.lock))
+      return NULL;
+   /* allocate memory for list entry with payload */
+   new_entry = malloc(sizeof(struct list_entry) + context->timeout_list.payload_size);
+   if (!new_entry) {
+      sem_post(&context->timeout_list.lock);
+      return NULL;
+   }
+
+   new_timeout_entry = list_entry_data(new_entry);
+
+   new_timeout_entry->timeout = *timeout;
+
+   sem_post(&context->timeout_list.lock);
+
+   return new_entry;
+}
+
+/**
+   Initialize DXS_TM_Context structure and its list and start timeout control
+   thread.
+
+   \param  context      pointer to tapi timer context structure
+
+   \return
+     - DXS_TM_SUCCESS or DXS_TM_ERROR in case of errors
+*/
+static int32_t DXS_TM_timeout_init(struct DXS_TM_Context *context)
+{
+   int32_t error;
+
+   error = DXS_TM_list_init(&context->timeout_list, sizeof(struct timeout_list_entry));
+
+   if (error)
+   {
+      fprintf( stderr,
+           ("DXS_API: DXS_TM_list_init() failed for timer Initialization\n"));
+      return error;
+   }
+   error = (DXS_TM_SUCCESS == pthread_create(&context->timeout_thread_ctrl,
+                 NULL,
+                 DXS_TM_timeout_thread_main,
+                 (void *)context)) ? DXS_TM_SUCCESS : DXS_TM_ERROR;
+
+   if (error)
+   {
+      fprintf( stderr,
+           ("DXS_API: Thread init failed for timer Initialization\n"));
+      DXS_TM_list_delete(&context->timeout_list);
+      return error;
+   }
+   return DXS_TM_SUCCESS;
+}
+
+/**
+   Release memory and other resources used.
+
+   \param  list         pointer to list
+
+*/
+static void DXS_TM_list_delete(struct list *list)
+{
+   struct list_entry *entry, *tmp_entry;
+
+   foreach_list_entry_safe_ll(&list->first_element, entry, tmp_entry)
+   {
+      free(entry);
+   }
+   /* if list is empty fileds next and prev should point first_element */
+   list->first_element.next = &list->first_element;
+   list->first_element.prev = &list->first_element;
+   (void)sem_destroy(&list->lock);
+}
+
+/*
+ * exit from timer thread
+ */
+void terminate_timer_thread(int sig)
+{
+   timer_thr_exit = 1;
+}
+
+/** timeout events handling thread
+
+   \param[in] arg Thread arguments
+
+   \return 0
+*/
+static void *DXS_TM_timeout_thread_main(void *arg)
+{
+   struct DXS_TM_Context *context = (struct DXS_TM_Context *)arg;
+   struct timeout timer = {0};
+   struct list_entry *timer_to_execute_entry = NULL;
+   time_t wait_time;
+   struct sigaction act = {0};
+   int32_t ret;
+
+   act.sa_handler = terminate_timer_thread;
+   sigaction(SIGTERM, &act, NULL);
+
+   /* while thread is running */
+   while (!timer_thr_exit)
+   {
+      /* wait for message in FIFO */
+      while (!timer_thr_exit)
+      {
+         wait_time = 0;
+         ret = sem_wait(&context->timeout_list.lock);
+         if (ret)
+            break;
+         timer_to_execute_entry = DXS_TM_next_active_event_get(context, &timer,
+                                     &wait_time);
+         sem_post(&context->timeout_list.lock);
+         if (timer_to_execute_entry == NULL)
+         {
+            /* if time to the next timeout is longer than the poll time,
+               then wait only TIMEOUT_THREAD_POLL_TIME ms */
+            if ((wait_time == 0) || (wait_time > TIMEOUT_THREAD_POLL_TIME))
+            {
+               wait_time = TIMEOUT_THREAD_POLL_TIME;
+            }
+            /** \todo replace sleep with select, for this some sync mechanism
+                with add/start entry is needed, for example select could wait
+                for a pipe fd being readable, each function for add/start entry
+                would write to this pipe, this could replace the polling,
+                if above is implemented then wait_time could be set to exact
+                time to next timeout or wait forever untill and event/entry
+                is added */
+            dxs_MSecSleep((time_t) wait_time);
+         }
+         else
+         {
+            break;
+         }
+      }
+
+#if 0
+      /* check if we are shutting down */
+      if (thr_params->bShutDown == DXS_TM_TRUE
+          || thr_params->bRunning == DXS_TM_FALSE)
+      {
+         break;
+      }
+#endif
+
+      ret = sem_wait(&context->timeout_list.lock);
+      if (ret)
+      {
+         break;
+      }
+      else
+      {
+         struct timeout_list_entry *periodical_timeout_entry;
+         time_t time_in;
+
+         periodical_timeout_entry = list_entry_data(timer_to_execute_entry);
+         DXS_TM_lockless_event_stop(context, timer_to_execute_entry);
+         if (periodical_timeout_entry && timer.bPeriodical)
+         {
+            /* for periodical events get time to next timeout and add new timeout */
+            time_in = periodical_timeout_entry->time_in;
+            (void) DXS_TM_lockless_event_entry_start(context, timer_to_execute_entry,
+                                                      time_in);
+         }
+      }
+      sem_post(&context->timeout_list.lock);
+      if (timer.handler != NULL)
+      {
+         (void) timer.handler((Timer_ID) timer_to_execute_entry, (void *) timer.arg1);
+      }
+      else
+      {
+         fprintf( stderr,
+               ("DXS_TM_timeout_thread_main - ERROR: found event without timer handler"));
+      }
+   }
+   return 0;
+}
+
+/**
+   Lockless version of DXS_TM_timeout_event_remove.
+
+   \param  context         pointer to tapi timer context structure
+   \param  entry_to_stop   pointer to tapi entry structure
+
+   \return
+     - DXS_TM_SUCCESS
+*/
+static void DXS_TM_lockless_event_stop(struct DXS_TM_Context *context,
+                    struct list_entry *entry_to_stop)
+{
+   struct list_entry *current_entry;
+
+   if (is_list_empty(&context->timeout_list))
+   {
+      return;
+   }
+   foreach_list_entry(&context->timeout_list, current_entry)
+   {
+      if (current_entry == entry_to_stop)
+      {
+         DXS_TM_list_entry_remove(&context->timeout_list, current_entry);
+         return;
+      }
+   }
+   return;
+}
+
+/**
+   Remove entry from the list.
+
+   \param  list      pointer to list structure
+   \param  entry     pointer to entry structure that will be removed
+*/
+static void DXS_TM_list_entry_remove(struct list *list,
+             struct list_entry *entry)
+{
+   entry->next->prev = entry->prev;
+   entry->prev->next = entry->next;
+   entry->prev = NULL;
+   entry->next = NULL;
+   if (list->first_element.next == entry)
+   {
+      list->first_element.next = &list->first_element;
+   }
+}
+
+/** Get next timeouted event
+
+   \param[in]  context              timer context pointer
+   \param[out] timeout              Returns timeout descriptor
+   \param[out] time_to_next_entry   time till the next timeout expires,
+                                    set only if no entry was found
+
+   \return first entry on the list for which timeout expired or NULL
+*/
+static struct list_entry *DXS_TM_next_active_event_get(struct DXS_TM_Context *context,
+                    struct timeout *timeout,
+                    time_t * time_to_next_entry)
+{
+   struct timeout_list_entry *first_entry;
+   time_t currentTime;
+
+   if (is_list_empty(&context->timeout_list)) {
+      return NULL;
+   }
+
+   /* get the first entry from the list,
+      should be the one for which timeout expires first */
+   first_entry = list_entry_data(context->timeout_list.first_element.next);
+   if (!first_entry)
+   {
+      return NULL;
+   }
+   currentTime = (time_t)dxs_ElapsedTimeMSecGet(0);
+   if (first_entry->timeout_time <= currentTime)
+   {
+      /* timeout occured for this entry */
+      *timeout = first_entry->timeout;
+      return context->timeout_list.first_element.next;
+   }
+   else
+   {
+      /* get time to next timeout */
+      *time_to_next_entry = first_entry->timeout_time - currentTime;
+   }
+   return NULL;
+}
+
+/** Stop handling of given entry
+
+   \param[in]  context        timer context pointer
+   \param[in]  timer_entry    timer entry to stop
+
+   \return always DXS_TM_SUCCESS as DXS_TM_lockless_event_stop does
+*/
+static void DXS_TM_timeout_event_stop(struct DXS_TM_Context *context,
+                 struct list_entry *timer_entry)
+{
+   struct timeout_list_entry *timeout_entry_to_start;
+
+   sem_wait(&context->timeout_list.lock);
+   timeout_entry_to_start = list_entry_data(timer_entry);
+   timeout_entry_to_start->timeout.bPeriodical = DXS_TM_FALSE;
+   DXS_TM_lockless_event_stop(context, timer_entry);
+   sem_post(&context->timeout_list.lock);
+
+   return;
+}
+
+/** Remove given entry from the list
+
+   \param[in]  context        timer context pointer
+   \param[in]  timer_entry    timer entry to remove
+
+   \return always DXS_TM_SUCCESS as DXS_TM_lockless_event_remove does
+*/
+static int32_t DXS_TM_timeout_event_remove(struct DXS_TM_Context *context,
+                 struct list_entry *timer_entry)
+{
+   int32_t error;
+
+   sem_wait(&context->timeout_list.lock);
+   error = DXS_TM_lockless_event_remove(context, timer_entry);
+   sem_post(&context->timeout_list.lock);
+
+   return error;
+}
+
+/** Lockless version of DXS_TM_timeout_event_remove
+
+   \param[in]  context           timer context pointer
+   \param[in]  entry_to_remove   entry to remove
+
+   \return always DXS_TM_SUCCESS
+ */
+static int32_t DXS_TM_lockless_event_remove(struct DXS_TM_Context *context,
+                    struct list_entry *entry_to_remove)
+{
+   struct list_entry *current_entry;
+
+   if (is_list_empty(&context->timeout_list))
+   {
+      return DXS_TM_SUCCESS;
+   }
+   foreach_list_entry(&context->timeout_list, current_entry)
+   {
+      if (current_entry == entry_to_remove)
+      {
+         DXS_TM_list_entry_free(&context->timeout_list, current_entry);
+         return DXS_TM_SUCCESS;
+      }
+   }
+   return DXS_TM_SUCCESS;
+}
+
+/** Release memory allocated for given entry
+
+   \param[in]  list     pointeer to the list - unused
+   \param[in]  entry    entry to remove and free memory
+ */
+static void DXS_TM_list_entry_free(struct list *list,
+             struct list_entry *entry)
+{
+   if ((NULL != entry->next) && (NULL != entry->prev))
+   {
+      entry->next->prev = entry->prev;
+      entry->prev->next = entry->next;
+   }
+   free(entry);
+}
+
+/** Release memory allocated for given entry
+
+   \param[in]  list           pointeer to the list
+   \param[in]  payload_size   size of memory in bytes needed to hold the entry data
+
+   \return value sem_init() call
+ */
+static int32_t DXS_TM_list_init(struct list *list, size_t payload_size)
+{
+   /* for first element next and prev point to first element if list is empty */
+   list->first_element.next = &list->first_element;
+   list->first_element.prev = &list->first_element;
+   list->payload_size = payload_size;
+   /* get the lock */
+   return sem_init(&list->lock, 0, 1);
+}
+
+/** Start handling of given timeout entry
+
+   \param[in]  context        timer context pointer
+   \param[in]  timer_entry    timer entry to start
+   \param[in]  timeout_time   timoeout time for new timer entry
+   \param[in]  bPeriodical    if DXS_TM_TRUE, then timeout for event will be
+                              checked periodicaly to execute the handler
+
+   \return always DXS_TM_SUCCESS as DXS_TM_event_entry_start does
+*/
+static int32_t DXS_TM_timeout_event_start(struct DXS_TM_Context *context,
+              struct list_entry *timer_entry,
+              time_t timeout_time, DXS_TM_BOOL_t bPeriodical)
+{
+   /** \todo add a check if timers are initialized */
+   return DXS_TM_event_entry_start(context, timer_entry, timeout_time, bPeriodical);
+}
+
+/** Start handling of given timeout entry
+
+   \param[in]  context        timer context pointer
+   \param[in]  timer_entry    timer entry to start
+   \param[in]  timeout_time   timoeout time for new timer entry
+   \param[in]  bPeriodical    if DXS_TM_TRUE, then timeout for event will be
+                              checked periodicaly to execute the handler
+
+   \return always DXS_TM_SUCCESS
+*/
+static int32_t DXS_TM_event_entry_start(struct DXS_TM_Context *context,
+                   struct list_entry *timer_entry,
+                   time_t timeout_time,
+                   DXS_TM_BOOL_t bPeriodical)
+{
+   struct timeout_list_entry *timeout_entry_to_start;
+   int32_t ret;
+
+   sem_wait(&context->timeout_list.lock);
+   timeout_entry_to_start = list_entry_data(timer_entry);
+   timeout_entry_to_start->timeout.bPeriodical = bPeriodical;
+   ret = DXS_TM_lockless_event_entry_start(context, timer_entry, timeout_time);
+   sem_post(&context->timeout_list.lock);
+
+   return ret;
+}
+
+/** Add timeout event
+
+   \param[in]  context        timer context pointer
+   \param[in]  timer_entry    timer entry to start
+   \param[in]  timeout_time   timoeout time for new timer entry (in ms)
+
+   \return always DXS_TM_SUCCESS
+*/
+static int32_t DXS_TM_lockless_event_entry_start(struct DXS_TM_Context *context,
+                   struct list_entry *timer_entry,
+                   time_t timeout_time)
+{
+   struct list_entry *current_entry;
+   struct timeout_list_entry *timeout_entry, *timeout_entry_to_start;
+   DXS_TM_BOOL_t added = DXS_TM_FALSE;
+
+   if (timer_entry == NULL)
+      return DXS_TM_ERROR;
+   timeout_entry_to_start = list_entry_data(timer_entry);
+   if (timeout_entry_to_start == NULL)
+      return DXS_TM_ERROR;
+   /* get timeout time to compare with current time read
+      with dxs_ElapsedTimeMSecGet(0) */
+   timeout_entry_to_start->timeout_time = dxs_ElapsedTimeMSecGet(0) + timeout_time;
+   timeout_entry_to_start->time_in = timeout_time;
+   foreach_list_entry(&context->timeout_list, current_entry)
+   {
+      timeout_entry = list_entry_data(current_entry);
+      if (timeout_entry->timeout_time >
+          timeout_entry_to_start->timeout_time)
+      {
+         DXS_TM_list_entry_add_before(&context->timeout_list, current_entry,
+                     timer_entry);
+         added = DXS_TM_TRUE;
+         break;
+      }
+   }
+   if (!added)
+   {
+      DXS_TM_list_entry_add_tail(&context->timeout_list, timer_entry);
+   }
+   return DXS_TM_SUCCESS;
+}
+
+/** Add add new entry before entry that is already on the list
+
+   \param[in]  list           the list - unused
+   \param[in]  entry          entry from the list
+   \param[in]  new_entry      entry to add
+*/
+static void DXS_TM_list_entry_add_before(struct list *list,
+            struct list_entry *entry,
+            struct list_entry *new_entry)
+{
+   entry->prev->next = new_entry;
+   new_entry->prev = entry->prev;
+   new_entry->next = entry;
+   entry->prev = new_entry;
+}
+
+/** Add add new entry at the end of the list
+
+   \param[in]  list           the list
+   \param[in]  entry          entry to add
+*/
+static void DXS_TM_list_entry_add_tail(struct list *list,
+                   struct list_entry *new_entry)
+{
+   DXS_TM_list_entry_add_after(list, list->first_element.prev, new_entry);
+}
+
+/** Add add new entry after entry that is already on the list
+
+   \param[in]  list           the list - unused
+   \param[in]  entry          entry from the list
+   \param[in]  new_entry      entry to add
+*/
+static void DXS_TM_list_entry_add_after(struct list *list,
+           struct list_entry *entry,
+           struct list_entry *new_entry)
+{
+   entry->next->prev = new_entry;
+   new_entry->next = entry->next;
+   entry->next = new_entry;
+   new_entry->prev = entry;
+}
+
+/* ========================================================================== */
+/*                                Public functions                            */
+/* ========================================================================== */
+
+/**
+   Create a timer.
+
+   \param  pTimerEntry  Function pointer to the call back function.
+   \param  nArgument    Pointer to DXS channel structure.
+
+   \return
+   Timer_ID  Pointer to internal timer structure.
+
+   \remarks
+   Initialize a task queue which will be scheduled once a timer interrupt occurs
+   to execute the appropriate operation in a process context, process in which
+   semaphores ... are allowed.
+   Please notice that this task has to run under the keventd process, in which
+   it can be executed thousands of times within a single timer tick.
+*/
+Timer_ID DXS_TimerCreate(TIMER_ENTRY pTimerEntry, void *nArgument)
+{
+   if (DXS_TM_TRUE != G_timers.bTimersInialized)
+   {
+      /* timeout thread needs to be started only once */
+      G_timers.bTimersInialized = DXS_TM_TRUE;
+      DXS_TM_timeout_init(&G_timers);
+   }
+   return (Timer_ID) DXS_TM_timeout_event_create(&G_timers, pTimerEntry,
+                                                     (unsigned long)nArgument);
+}
+
+/**
+   Sets a timer to the specified time and starts it. It can be choose if the
+   timer starts periodically.
+
+   \param  Timer_ID     Pointer to internal timer structure.
+   \param  nTime        Time in ms.
+   \param  bPeriodically Starts the timer periodically or not.
+   \param  bRestart     Restart the timer or normal start.
+
+   \return
+   Returns an error code: DXS_TM_TRUE / DXS_TM_FALSE
+*/
+DXS_TM_BOOL_t DXS_TimerSet(Timer_ID Timer, uint32_t nTime, DXS_TM_BOOL_t bPeriodically,
+                                 DXS_TM_BOOL_t bRestart)
+{
+   /** \todo add a check if timers are initialized */
+   if (bRestart == DXS_TM_TRUE)
+   {
+      DXS_TM_timeout_event_stop(&G_timers, (struct list_entry *) Timer);
+   }
+
+   if (DXS_TM_timeout_event_start(&G_timers,
+              (struct list_entry *) Timer,
+              (time_t) nTime,
+              bPeriodically) != 0)
+   {
+      fprintf ( stderr, ("DXS_TimerSet: failed to start timer\n"));
+      return DXS_TM_FALSE;
+   }
+
+   return DXS_TM_TRUE;
+}
+
+/**
+   Stop a timer.
+
+   \param  Timer_ID     Pointer to internal timer structure.
+
+   \return
+   Returns an error code: DXS_TM_TRUE / DXS_TM_FALSE
+*/
+DXS_TM_BOOL_t DXS_TimerStop(Timer_ID Timer)
+{
+   if(Timer)
+      DXS_TM_timeout_event_stop(&G_timers, (struct list_entry *) Timer);
+
+   return DXS_TM_TRUE;
+}
+
+/**
+   Delete a timer.
+
+   \param  Timer_ID     Pointer to internal timer structure.
+
+   \return
+   Returns an error code: DXS_TM_TRUE / DXS_TM_FALSE
+*/
+DXS_TM_BOOL_t DXS_TimerDestroy(Timer_ID Timer)
+{
+   if (Timer == NULL)
+      return DXS_TM_FALSE;
+
+   DXS_TimerStop(Timer);
+
+   /* free memory */
+   (void) DXS_TM_timeout_event_remove(&G_timers, (struct list_entry *)Timer);
+
+   return DXS_TM_TRUE;
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_timer.h b/marvell/services/dxslic/api_lib/src/dxs_timer.h
new file mode 100644
index 0000000..843b5cf
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_timer.h
@@ -0,0 +1,54 @@
+#ifndef __DXS_TIMER_H__
+#define __DXS_TIMER_H__
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_timer.h
+   This file contains the declaration of the functions for timers.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include <stdint.h>
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+#define DXS_TM_SUCCESS 0
+#define DXS_TM_ERROR   (-1)
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+typedef enum
+{
+   DXS_TM_FALSE = 0,
+   DXS_TM_TRUE
+} DXS_TM_BOOL_t;
+
+typedef void* Timer_ID;
+typedef void (*TIMER_ENTRY)(Timer_ID timer_id, void *arg);
+
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+extern Timer_ID DXS_TimerCreate(TIMER_ENTRY pTimerEntry, void *nArgument);
+extern DXS_TM_BOOL_t DXS_TimerSet(Timer_ID Timer,
+                                  uint32_t nTime,
+                                  DXS_TM_BOOL_t bPeriodically,
+                                  DXS_TM_BOOL_t bRestart);
+extern DXS_TM_BOOL_t DXS_TimerStop(Timer_ID Timer);
+extern DXS_TM_BOOL_t DXS_TimerDestroy(Timer_ID Timer);
+
+#endif /* __DXS_TIMER_H__ */
diff --git a/marvell/services/dxslic/api_lib/src/dxs_wait.c b/marvell/services/dxslic/api_lib/src/dxs_wait.c
new file mode 100644
index 0000000..f42a215
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_wait.c
@@ -0,0 +1,391 @@
+/******************************************************************************
+
+  Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2016, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_wait.c
+   Implementation of WaitList functions.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+#include "dxs.h"
+#include "dxs_lib.h"
+#include "dxs_fifo.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+/* max number of waiting lists */
+#define DXS_MAX_WAITLISTS            16
+/* max elements in a single waiting list */
+#define DXS_MAX_WAITLIST_OBJ         32
+/* max total waiting list elements */
+#define DXS_MAX_WAITLIST_ELEMENTS    (DXS_MAX_WAITLISTS*DXS_MAX_WAITLIST_OBJ)
+
+#define DXS_WAITLIST_MAGIC          0x574C7853
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+struct __waitlist
+{
+   uint32_t             magic;
+   uint8_t              in_use;
+   pthread_mutex_t      op_mtx;
+   sem_t                wait_sem;
+   struct __waiting_obj *head;
+};
+
+struct __waiting_obj
+{
+   DXS_DEVICE_t *pDev;
+   struct __waiting_obj *next;
+};
+
+/* ========================================================================== */
+/*                             Global variables                               */
+/* ========================================================================== */
+static struct __waitlist waitlists[DXS_MAX_WAITLISTS] = {{0},};
+static struct __waiting_obj wobjects[DXS_MAX_WAITLIST_ELEMENTS] = {{NULL},};
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                         Function implementation                            */
+/* ========================================================================== */
+
+/*
+ *
+ * FIXME: current limitation:
+ *    a device can be a member of the one waiting list
+ *
+ */
+
+ /**
+   Function dxs_wl_init
+
+   \return
+   - waiting list instance or NULL
+*/
+DXS_WaitList_t dxs_wl_init()
+{
+   int i, err;
+   struct __waitlist    *wl;
+
+   /* find the next free list */
+   for (i=0; i<DXS_MAX_WAITLISTS; i++)
+   {
+      wl = &waitlists[i];
+      if (!wl->in_use)
+         break;
+   }
+   if (i == DXS_MAX_WAITLISTS)
+   {
+      /* list not found */
+      return (DXS_WaitList_t)NULL;
+   }
+
+   pthread_mutex_init(&wl->op_mtx, NULL);
+
+   err = pthread_mutex_lock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   wl->magic = DXS_WAITLIST_MAGIC;
+   wl->in_use = 1;
+   wl->head = NULL;
+
+   /* initialize wait sem */
+   sem_init(&wl->wait_sem, 0, 0);
+
+   err = pthread_mutex_unlock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return (DXS_WaitList_t)wl;
+}
+
+/**
+   Function dxs_wl_destroy
+
+   \param   wlist  - WaitList
+
+*/
+void dxs_wl_destroy(DXS_WaitList_t wlist)
+{
+   struct __waitlist *wl = (struct __waitlist *)wlist;
+   int err;
+   if (wl == NULL || wl->magic != DXS_WAITLIST_MAGIC)
+      return;
+
+   err = pthread_mutex_lock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   wl->in_use = 0;
+   wl->magic = 0;
+
+   sem_destroy(&wl->wait_sem);
+
+   err = pthread_mutex_unlock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   err = pthread_mutex_destroy(&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+}
+
+/**
+   Function dxs_wl_dev_add
+
+   \param   pDev    - pointer to DXS device structure
+   \param   wlist   - WaitList
+
+   \return
+   - DXS_status_t
+*/
+int32_t dxs_wl_dev_add(DXS_DEVICE_t *pDev, DXS_WaitList_t wlist)
+{
+   struct __waitlist *wl = (struct __waitlist *)wlist;
+   struct __waiting_obj *wo;
+   int i, err;
+
+   if (wl == NULL || wl->magic != DXS_WAITLIST_MAGIC)
+   {
+      DXS_RETURN(DXS_statusWaitListObjInv);
+   }
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   err = pthread_mutex_lock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   /* check if pDev was already added to the list */
+   if (wl->head != NULL)
+   {
+      uint8_t found = 0;
+      struct __waiting_obj *w = wl->head;
+
+      while (w != NULL)
+      {
+         if (w->pDev == pDev)
+         {
+            found = 1;
+            break;
+         }
+         w = w->next;
+      }
+
+      if (found)
+      {
+         /* device was already added - not an error */
+         err = pthread_mutex_unlock (&wl->op_mtx);
+         if (err != 0)
+           DXS_ERROR_PUSH(err);
+         return DXS_statusOk;
+      }
+   }
+
+   /* get the next free element */
+   for (i=0; i<DXS_MAX_WAITLIST_ELEMENTS; i++)
+   {
+      wo = &wobjects[i];
+      if (wo->pDev == NULL)
+         break;
+   }
+   if (i == DXS_MAX_WAITLIST_ELEMENTS)
+   {
+      /* cannot add a device into the list */
+      err = pthread_mutex_unlock (&wl->op_mtx);
+      if (err != 0)
+        DXS_ERROR_PUSH(err);
+      DXS_RETURN(DXS_statusWaitListDevAddErr);
+   }
+
+   wo->pDev = pDev;
+   wo->next = NULL;
+
+   /* add to the tail of the list */
+   if (wl->head == NULL)
+   {
+      wl->head = wo;
+   }
+   else
+   {
+      struct __waiting_obj *w = wl->head;
+
+      while (w->next != NULL)
+         w = w->next;
+
+      w->next = wo;
+   }
+
+   /* link pDev with wl
+      TODO: introduce a list of wl as a device
+      might be a member of more than one wl */
+   pDev->wait_list = wlist;
+
+   err = pthread_mutex_unlock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   return DXS_statusOk;
+}
+
+/**
+   Function dxs_wl_dev_remove
+
+   \param   pDev    - pointer to DXS device structure
+   \param   wlist   - WaitList
+
+   \return
+   - int32_t 0 or -1
+*/
+int32_t dxs_wl_dev_remove(DXS_DEVICE_t *pDev, DXS_WaitList_t wlist)
+{
+   struct __waitlist *wl = (struct __waitlist *)wlist;
+   struct __waiting_obj *wo, *prev;
+   int err;
+
+   if (wl == NULL || wl->magic != DXS_WAITLIST_MAGIC)
+   {
+      DXS_RETURN(DXS_statusWaitListObjInv);
+   }
+
+   if (pDev == NULL)
+   {
+      DXS_RETURN(DXS_statusInvalidParam);
+   }
+
+   err = pthread_mutex_lock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   wo = wl->head;
+   prev = NULL;
+
+   while (wo != NULL)
+   {
+      if (wo->pDev == pDev)
+      {
+         if (prev == NULL)
+         {
+            wl->head = wo->next;
+         }
+         else
+         {
+            prev->next = wo->next;
+         }
+         wo->pDev = NULL;
+         wo->next = NULL;
+         break;
+      }
+
+      prev = wo;
+      wo = wo->next;
+   }
+
+   err = pthread_mutex_unlock (&wl->op_mtx);
+   if (err != 0)
+     DXS_ERROR_PUSH(err);
+
+   DXS_RETURN(DXS_statusOk);
+}
+
+/**
+   Function dxs_wait
+
+   \param   wlist   - WaitList
+
+   \return
+   - device number
+*/
+int32_t dxs_wait(DXS_WaitList_t wlist)
+{
+   struct __waitlist *wl = (struct __waitlist *)wlist;
+   struct __waiting_obj *wo;
+   int32_t ret;
+
+   if (wl == NULL || wl->magic != DXS_WAITLIST_MAGIC)
+   {
+      return -1;
+   }
+
+   if (wl->head == NULL)
+   {
+      return -2;
+   }
+
+   wo = wl->head;
+
+   while (wo != NULL)
+   {
+      FIFO_t *evq = wo->pDev->event_queue;
+
+      if (0 < fifo_count (evq))
+      {
+         return wo->pDev->nDevNum;
+      }
+
+      wo = wo->next;
+   }
+
+   ret = sem_wait (&wl->wait_sem);
+   if (ret)
+   {
+      return ret;
+   }
+
+   wo = wl->head;
+
+   while (wo != NULL)
+   {
+      FIFO_t *evq = wo->pDev->event_queue;
+
+      if (0 < fifo_count (evq))
+      {
+         return wo->pDev->nDevNum;
+      }
+
+      wo = wo->next;
+   }
+
+   /* unreachable */
+   return 0;
+}
+
+/**
+   Function dxs_wakeup
+
+   \param   pDev    - pointer to DXS device structure
+
+*/
+void dxs_wakeup(DXS_DEVICE_t *pDev)
+{
+   struct __waitlist *wl;
+
+   if (pDev != NULL && pDev->wait_list != NULL)
+   {
+      wl = (struct __waitlist *)pDev->wait_list;
+
+      sem_post (&wl->wait_sem);
+   }
+}
diff --git a/marvell/services/dxslic/api_lib/src/dxs_wait.h b/marvell/services/dxslic/api_lib/src/dxs_wait.h
new file mode 100644
index 0000000..033cfd6
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_wait.h
@@ -0,0 +1,42 @@
+#ifndef __DXS_WAIT_H__
+#define __DXS_WAIT_H__
+/******************************************************************************
+
+  Copyright (c) 2006-2015 Lantiq Deutschland GmbH
+  Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG
+  Copyright 2018, Intel Corporation.
+
+  For licensing information, see the file 'LICENSE' in the root folder of
+  this software module.
+
+******************************************************************************/
+
+/**
+   \file dxs_wait.h
+   WaitList functions declarations.
+*/
+
+/* ========================================================================== */
+/*                                 Includes                                   */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Macro definitions                              */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                             Type definitions                               */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/*                           Function prototypes                              */
+/* ========================================================================== */
+
+extern DXS_WaitList_t dxs_wl_init();
+extern void dxs_wl_destroy(DXS_WaitList_t wlist);
+extern int32_t dxs_wl_dev_add(DXS_DEVICE_t *pDev, DXS_WaitList_t wlist);
+extern int32_t dxs_wl_dev_remove(DXS_DEVICE_t *pDev, DXS_WaitList_t wlist);
+extern int32_t dxs_wait(DXS_WaitList_t wlist);
+extern void dxs_wakeup(DXS_DEVICE_t *pDev);
+
+#endif /* __DXS_WAIT_H__ */