summaryrefslogtreecommitdiff
path: root/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_list.c')
-rw-r--r--Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_list.c911
1 files changed, 911 insertions, 0 deletions
diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_list.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_list.c
new file mode 100644
index 0000000..5843de9
--- /dev/null
+++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_list.c
@@ -0,0 +1,911 @@
+/*****************************************************************************
+ *
+ * @file icp_hssacc_channel_list.c
+ *
+ * @description Contents of this file is the implementation of the channel
+ * list manipulation functionality.
+ *
+ * @ingroup icp_HssAcc
+ *
+ * @Revision 1.0
+ *
+ * @par
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ *
+ *
+ *****************************************************************************/
+
+
+#include "icp.h"
+#include "icp_hssacc.h"
+#include "icp_hssacc_trace.h"
+#include "icp_hssacc_common.h"
+
+
+
+
+
+/**
+ * Typedefs whose scope is limited to this file.
+ */
+
+
+/* Structure holding list configuration data for one channel */
+typedef struct icp_hssacc_channel_list_data_s
+{
+ uint16_t prevChannelId;
+ uint16_t nextChannelId;
+ icp_hssacc_channel_list_t listId;
+} icp_hssacc_channel_list_data_t;
+
+
+
+/* Stats for List Management*/
+typedef struct icp_hssacc_channel_list_stats_s
+{
+ icp_hssacc_msg_with_resp_stats_t nextChannelWrite;
+ icp_hssacc_msg_with_resp_stats_t portCfgChannel;
+} icp_hssacc_channel_list_stats_t;
+
+
+/* channel List Data for each channel */
+TDM_PRIVATE icp_hssacc_channel_list_data_t
+hssAccChannelData[ICP_HSSACC_MAX_NUM_CHANNELS];
+
+/* Track which channel is the last of the list for each list
+ on each port */
+TDM_PRIVATE uint32_t
+hssAccLastChannelOnList[ICP_HSSACC_MAX_NUM_PORTS]
+[ICP_HSSACC_CHANNEL_LIST_DELIMITER];
+
+/* Internal Messaging Stats for this sub-module */
+TDM_PRIVATE icp_hssacc_channel_list_stats_t hssAccChannelListStats;
+
+/* Track the amount of IO transactions represented by each
+ list on each port */
+TDM_PRIVATE uint32_t
+hssAccPortChannelListUsage[ICP_HSSACC_MAX_NUM_PORTS]
+[ICP_HSSACC_CHANNEL_LIST_DELIMITER];
+
+/* Construct and send the NextChanWrite message to the TDM IO Unit */
+TDM_PRIVATE icp_status_t
+HssAccChannelNextChanWriteMsgSend (unsigned prevChannelId,
+ unsigned nextChannelId,
+ uint8_t txRxIndicator,
+ uint8_t nullFlag);
+
+
+/*
+ * Function Prototype: HssAccChanIOUsageCalc
+ * Description: this function calculates the number
+ * of IO transactions that a specific channelSize implies
+ */
+inline unsigned HssAccChanIOUsageCalc(unsigned chanSize)
+{
+ unsigned channelUsageIO =
+ chanSize / ICP_HSSACC_TDM_IO_UNIT_MAX_TRANSACTION_SIZE_WRDS;
+ channelUsageIO ++;
+ if ( (chanSize % ICP_HSSACC_TDM_IO_UNIT_MAX_TRANSACTION_SIZE_WRDS) > 1 )
+ {
+ channelUsageIO ++;
+ }
+ return channelUsageIO;
+}
+
+
+
+
+/*
+ * Function Prototype: HssAccChannelListMap
+ * Description: this function maps internal sub-module
+ * list IDs to TDM I/O Unit list IDs
+ */
+inline icp_status_t
+HssAccChannelListMap (icp_hssacc_channel_list_t listId,
+ icp_hssacc_tdm_io_unit_channel_list_t *txList,
+ icp_hssacc_tdm_io_unit_channel_list_t *rxList)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ switch (listId)
+ {
+ case ICP_HSSACC_CHANNEL_LIST_PRIMARY:
+ *txList = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_PRIMARY;
+ *rxList = ICP_HSSACC_TDM_IO_UNIT_LIST_RX_PRIMARY;
+ break;
+ case ICP_HSSACC_CHANNEL_LIST_SECONDARY_0:
+ *txList = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_0;
+ *rxList = ICP_HSSACC_TDM_IO_UNIT_LIST_RX_SECONDARY_0;
+ break;
+ case ICP_HSSACC_CHANNEL_LIST_SECONDARY_1:
+ *txList = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_1;
+ *rxList = ICP_HSSACC_TDM_IO_UNIT_LIST_RX_SECONDARY_1;
+ break;
+ case ICP_HSSACC_CHANNEL_LIST_DELIMITER:
+ default:
+ ICP_HSSACC_REPORT_ERROR("HssAccChannelListMap - "
+ "Invalid List ID provided\n");
+ status = ICP_STATUS_FAIL;
+ break;
+ }
+ return status;
+}
+
+/*
+ * Function Prototype: HssAccChannelFirstChanAdd
+ * Description: this function will add a channel to an empty list of
+ * channels processed on the port.
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelFirstChanAdd (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData);
+
+/*
+ * Function Prototype: HssAccChannelLastChanAdd
+ * Description: this function will add a channel to the end of a list of
+ * channels processed on the port.
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelLastChanAdd (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData);
+
+/*
+ * Function Prototype: HssAccChannelFirstChanDel
+ * Description: this function will remove a channel that is at
+ * the start of a list of channels processed on the port.
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelFirstChanDel (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData);
+
+/*
+ * Function Prototype: HssAccChannelLastChanDel
+ * Description: this function will remove a channel that is at the
+ * end of a list of channels processed on the port.
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelLastChanDel (unsigned hssPortId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData);
+
+/*
+ * Function Prototype: HssAccChannelMiddleChanDel
+ * Description: this function will remove a channel that is in
+ * the middle of a list of channels processed on the port.
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelMiddleChanDel (icp_hssacc_channel_list_data_t *pListData);
+
+
+/*
+ * Function Prototype: HssAccChannelListsStatsReset
+ * Reset the Stats for this sub-module
+ */
+void
+HssAccChannelListsStatsReset (void)
+{
+ memset (&hssAccChannelListStats,0,sizeof(icp_hssacc_channel_list_stats_t));
+}
+
+
+
+/*
+ * Function Definition: HssAccChannelListsReset
+ */
+void HssAccChannelListsReset (void)
+{
+ unsigned index = 0;
+ icp_hssacc_channel_list_t listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelListsReset\n");
+ /* Initialise internal data,
+ set last channel IDs for each HSS Port to INVALID_CHAN */
+ for (index = 0; index < ICP_HSSACC_MAX_NUM_PORTS; index ++)
+ {
+ for (listId = 0; listId < ICP_HSSACC_CHANNEL_LIST_DELIMITER; listId ++)
+ {
+ hssAccLastChannelOnList[index][listId] = ICP_HSSACC_INVALID_CHAN;
+ hssAccPortChannelListUsage[index][listId] = 0;
+ }
+ }
+ for (index = 0; index < ICP_HSSACC_MAX_NUM_CHANNELS; index ++)
+ {
+ hssAccChannelData[index].prevChannelId = ICP_HSSACC_INVALID_CHAN;
+ hssAccChannelData[index].nextChannelId = ICP_HSSACC_INVALID_CHAN;
+ hssAccChannelData[index].listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelListsReset\n");
+}
+
+
+
+/* Function definition: HssAccNextChannelListGet
+ Description: Figures out the next linked list to use when
+ commissioning a new channel
+ ASSUMPTION: The channel data for the specified channel must be valid */
+TDM_PRIVATE icp_hssacc_channel_list_t
+HssAccNextChannelListGet (uint32_t hssPortId)
+{
+ /* Get the List Id (symmetrical for Tx and Rx) */
+
+ icp_hssacc_channel_list_t smallestList = ICP_HSSACC_CHANNEL_LIST_PRIMARY;
+ uint16_t smallestSize =
+ hssAccPortChannelListUsage[hssPortId][ICP_HSSACC_CHANNEL_LIST_PRIMARY];
+
+ if (smallestSize >
+ hssAccPortChannelListUsage[hssPortId]
+ [ICP_HSSACC_CHANNEL_LIST_SECONDARY_0])
+ {
+ smallestList = ICP_HSSACC_CHANNEL_LIST_SECONDARY_0;
+ smallestSize =
+ hssAccPortChannelListUsage[hssPortId]
+ [ICP_HSSACC_CHANNEL_LIST_SECONDARY_0];
+ }
+
+#if !defined(IXP23XX) || defined(UNIT_TEST)
+ if (smallestSize >
+ hssAccPortChannelListUsage[hssPortId]
+ [ICP_HSSACC_CHANNEL_LIST_SECONDARY_1])
+ {
+ smallestList = ICP_HSSACC_CHANNEL_LIST_SECONDARY_1;
+ }
+#endif
+ return smallestList;
+
+}
+
+
+icp_status_t
+HssAccChannelListAdd (unsigned hssPortId,
+ unsigned chanId,
+ unsigned chanSize)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ icp_hssacc_channel_list_t listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ icp_hssacc_channel_list_data_t *pListData = NULL;
+ unsigned channelUsageIO = 0;
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelListAdd\n");
+
+ /* check the channel isnt already in a list */
+ pListData = &(hssAccChannelData[chanId]);
+
+ if (pListData->listId != ICP_HSSACC_CHANNEL_LIST_DELIMITER)
+ {
+ ICP_HSSACC_REPORT_ERROR_2 ("HssAccChannelListAdd - "
+ "Channel %d already part of list %d\n",
+ chanId,
+ pListData->listId);
+ status = ICP_STATUS_FAIL;
+ }
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ /* find a list to add to */
+ listId = HssAccNextChannelListGet(hssPortId);
+
+ ICP_HSSACC_TRACE_4 (ICP_HSSACC_DEBUG,
+ "HssAccChannelListAdd - Adding Channel %d"
+ " to List %d on Port %d, current last chan is %d\n",
+ chanId,
+ listId,
+ hssPortId,
+ hssAccLastChannelOnList[hssPortId][listId]);
+
+ if (hssAccLastChannelOnList[hssPortId][listId] ==
+ ICP_HSSACC_INVALID_CHAN)
+ {
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG,
+ "HssAccChannelListAdd - List is empty\n");
+
+ status = HssAccChannelFirstChanAdd (hssPortId,
+ chanId,
+ listId,
+ pListData);
+ }
+ else
+ {
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG,
+ "HssAccChannelListAdd - Add to end of list\n");
+
+ status = HssAccChannelLastChanAdd (hssPortId,
+ chanId,
+ listId,
+ pListData);
+ }
+ }
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ /* list is selected depending on usage. usage is determined depending on
+ the amount estimated amount of IO transactions generated for that
+ list. for each channel, IO transactions is defined as
+ channelSizeInWords/transactionSize + 1 or 2
+ (if modulus greater than 1). */
+ channelUsageIO = HssAccChanIOUsageCalc(chanSize);
+
+ hssAccPortChannelListUsage[hssPortId][listId] += channelUsageIO;
+
+ }
+
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelListAdd\n");
+ return status;
+}
+
+
+
+
+icp_status_t
+HssAccChannelListRemove (unsigned hssPortId,
+ unsigned chanId,
+ unsigned chanSize)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ icp_hssacc_channel_list_t listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ icp_hssacc_channel_list_data_t *pListData = NULL;
+ unsigned channelUsageIO = 0;
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelListRemove\n");
+ /* Get Channel Data and check that it is in a list */
+ pListData = &(hssAccChannelData[chanId]);
+
+ listId = pListData->listId;
+ if (listId == ICP_HSSACC_CHANNEL_LIST_DELIMITER)
+ {
+ ICP_HSSACC_REPORT_ERROR_1 ("HssAccChannelListRemove - "
+ "Channel %d not part of any list\n",
+ chanId);
+
+ status = ICP_STATUS_FAIL;
+ }
+
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+
+ /* The channel to be deleted is the first channel on this list */
+ if (pListData->prevChannelId == ICP_HSSACC_INVALID_CHAN)
+ {
+ status = HssAccChannelFirstChanDel (hssPortId,
+ chanId,
+ listId,
+ pListData);
+ }
+ /* The channel to be deleted is not the first channel on this list */
+ else
+ {
+ if (hssAccLastChannelOnList[hssPortId][listId] == chanId)
+ {
+ /* we are deleting the last channel of the list */
+ status = HssAccChannelLastChanDel (hssPortId,
+ listId,
+ pListData);
+ }
+ else
+ {
+ /* we are deleting a channel from the middle of the list */
+ status = HssAccChannelMiddleChanDel (pListData);
+ }
+ }
+ }
+
+ /* for the channel we are deleting, set its next pointer to point to NULL to
+ * avoid the possibility of an infinite loop when it is added later */
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ /* first set the tx 'next' pointer to NULL */
+ status =
+ HssAccChannelNextChanWriteMsgSend (
+ chanId,
+ 0,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_TX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG);
+ }
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ /* now set the rx 'next' pointer to NULL */
+ status =
+ HssAccChannelNextChanWriteMsgSend (
+ chanId,
+ 0,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_RX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG);
+ }
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ /* list is selected depending on usage. usage is determined depending on
+ the estimated amount of IO transactions generated for that
+ list. for each channel, IO transactions is defined as
+ channelSizeInWords/transactionSize+1 or 2 (if module greater
+ than 1).*/
+ channelUsageIO = HssAccChanIOUsageCalc(chanSize);
+
+ hssAccPortChannelListUsage[hssPortId][listId] -= channelUsageIO;
+
+ }
+
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelListRemove\n");
+ return status;
+}
+
+
+
+
+
+
+
+/*
+ * Function definition: HssAccChannelNextChanWriteMsgSend
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelNextChanWriteMsgSend (unsigned prevChannelId,
+ unsigned nextChannelId,
+ uint8_t txRxIndicator,
+ uint8_t nullFlag)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ IxPiuMhMessage message;
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelNextChanWriteMsgSend\n");
+
+ /* Create the message for the TDM I/O Unit */
+ HssAccComTdmIOUnitCmd8byteMsgCreate (ICP_HSSACC_TDM_IO_UNIT_NEXT_CHAN_WRITE,
+ prevChannelId,
+ 0, 0,
+ nextChannelId,
+ nullFlag,
+ txRxIndicator,
+ 0,
+ &message);
+
+
+ /* Send the message to the TDM I/O Unit */
+ status =
+ HssAccComTdmIOUnitMsgSendAndRecv(
+ message,
+ ICP_HSSACC_TDM_IO_UNIT_NEXT_CHAN_WRITE_RESPONSE,
+ &(hssAccChannelListStats.nextChannelWrite),
+ NULL);
+
+
+ if (ICP_STATUS_SUCCESS != status)
+ {
+ ICP_HSSACC_REPORT_ERROR_1 ("HssAccChannelNextChanWriteMsgSend - "
+ "Messaging failure for channel %d\n",
+ prevChannelId);
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelNextChanWriteMsgSend\n");
+ return status;
+}
+
+
+
+
+
+/*
+ * Function definition: HssAccChannelPortCfgMsgSend
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelPortCfgMsgSend (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ uint8_t nullFlag)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ IxPiuMhMessage message;
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelPortCfgMsgSend\n");
+
+ /* Create the message for the TDM I/O Unit*/
+ HssAccComTdmIOUnitCmd8byteMsgCreate (ICP_HSSACC_TDM_IO_UNIT_HSS_PORT_CFG,
+ hssPortId,
+ 0, 0,
+ channelId,
+ nullFlag,
+ listId,
+ 0,
+ &message);
+ /* Send the message to the TDM I/O Unit */
+ status = HssAccComTdmIOUnitMsgSendAndRecv(
+ message,
+ ICP_HSSACC_TDM_IO_UNIT_HSS_PORT_CFG_RESPONSE,
+ &(hssAccChannelListStats.portCfgChannel),
+ NULL);
+
+ if (ICP_STATUS_SUCCESS != status)
+ {
+ ICP_HSSACC_REPORT_ERROR_2 ("HssAccChannelPortCfgMsgSend - Messaging "
+ "failure for port %d, channel %d\n",
+ hssPortId,
+ channelId);
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelPortCfgMsgSend\n");
+ return status;
+}
+
+
+/*
+ * Function definition: HssAccChannelFirstChanAdd
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelFirstChanAdd (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ icp_hssacc_tdm_io_unit_channel_list_t rxList, txList =
+ ICP_HSSACC_TDM_IO_UNIT_LIST_DELIMITER;
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelFirstChanAdd\n");
+
+ status = HssAccChannelListMap (listId, &txList, &rxList);
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+
+ status =
+ HssAccChannelPortCfgMsgSend (hssPortId,
+ channelId,
+ txList,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ }
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ status =
+ HssAccChannelPortCfgMsgSend (hssPortId,
+ channelId,
+ rxList,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ }
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ pListData->listId = listId;
+ pListData->prevChannelId = ICP_HSSACC_INVALID_CHAN;
+ pListData->nextChannelId = ICP_HSSACC_INVALID_CHAN;
+
+ hssAccLastChannelOnList[hssPortId][listId] = channelId;
+
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelFirstChanAdd\n");
+ return status;
+}
+
+/*
+ * Function definition: HssAccChannelLastChanAdd
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelLastChanAdd (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ unsigned prevChannelId = 0;
+ icp_hssacc_channel_list_data_t *pPrevChanList = NULL;
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelLastChanAdd\n");
+
+ prevChannelId = hssAccLastChannelOnList[hssPortId][listId];
+
+ status =
+ HssAccChannelNextChanWriteMsgSend (prevChannelId,
+ channelId,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_TX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+
+ status =
+ HssAccChannelNextChanWriteMsgSend(
+ prevChannelId,
+ channelId,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_RX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ }
+
+ if (status == ICP_STATUS_SUCCESS)
+ {
+ pListData->listId = listId;
+ pListData->prevChannelId = prevChannelId;
+ pListData->nextChannelId = ICP_HSSACC_INVALID_CHAN;
+ pPrevChanList = &(hssAccChannelData[prevChannelId]);
+ pPrevChanList->nextChannelId = channelId;
+
+ hssAccLastChannelOnList[hssPortId][listId] = channelId;
+
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelLastChanAdd\n");
+ return status;
+}
+
+
+
+/*
+ * Function definition: HssAccChannelFirstChanDel
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelFirstChanDel (unsigned hssPortId,
+ unsigned channelId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ icp_hssacc_tdm_io_unit_channel_list_t rxList, txList =
+ ICP_HSSACC_TDM_IO_UNIT_LIST_DELIMITER;
+ unsigned nextChannelId = 0;
+ icp_hssacc_channel_list_data_t *pNextChanListData = NULL;
+
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelFirstChanDel\n");
+
+ status = HssAccChannelListMap(listId, &txList, &rxList);
+
+ if (ICP_STATUS_SUCCESS != status)
+ {
+ return status;
+ }
+
+ /* Check if it is also the only channel processed on this list */
+ if (hssAccLastChannelOnList[hssPortId][listId] == channelId)
+ {
+ /* ChannelId parameter will be ignored by the TDM I/O Unit in
+ this case */
+ status =
+ HssAccChannelPortCfgMsgSend (hssPortId,
+ 0,
+ txList,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG);
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ status =
+ HssAccChannelPortCfgMsgSend (hssPortId,
+ 0,
+ rxList,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG);
+
+ }
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ pListData->listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ hssAccLastChannelOnList[hssPortId][listId] = ICP_HSSACC_INVALID_CHAN;
+
+ }
+ }
+ else
+ {
+
+ /* Get information for the next channel on the list */
+ nextChannelId = pListData->nextChannelId;
+
+ status =
+ HssAccChannelPortCfgMsgSend (hssPortId,
+ nextChannelId,
+ txList,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ status =
+ HssAccChannelPortCfgMsgSend (hssPortId,
+ nextChannelId,
+ rxList,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ }
+
+ if (status == ICP_STATUS_SUCCESS)
+ {
+ /* current channel is decoupled from the list */
+ pListData->listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ pListData->nextChannelId = ICP_HSSACC_INVALID_CHAN;
+ /* next channel now becomes the first channel on the list */
+ pNextChanListData = &(hssAccChannelData[nextChannelId]);
+ pNextChanListData->prevChannelId = ICP_HSSACC_INVALID_CHAN;
+ }
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelFirstChanDel\n");
+
+ return status;
+}
+
+/*
+ * Function definition: HssAccChannelLastChanDel
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelLastChanDel (unsigned hssPortId,
+ icp_hssacc_channel_list_t listId,
+ icp_hssacc_channel_list_data_t *pListData)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ unsigned prevChannelId = 0;
+ icp_hssacc_channel_list_data_t *pPrevChanListData = NULL;
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelLastChanDel\n");
+
+ prevChannelId = pListData->prevChannelId;
+ pPrevChanListData = &(hssAccChannelData[prevChannelId]);
+
+
+ status =
+ HssAccChannelNextChanWriteMsgSend (prevChannelId,
+ 0,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_TX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG);
+
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ status =
+ HssAccChannelNextChanWriteMsgSend (
+ prevChannelId,
+ 0,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_RX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG);
+ }
+ if (status == ICP_STATUS_SUCCESS)
+ {
+ pListData->listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ pListData->prevChannelId = ICP_HSSACC_INVALID_CHAN;
+
+ /* The Previous channel in the list now becomes the last */
+ pPrevChanListData->nextChannelId = ICP_HSSACC_INVALID_CHAN;
+ hssAccLastChannelOnList[hssPortId][listId] = prevChannelId;
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelLastChanDel\n");
+ return status;
+}
+
+/*
+ * Function definition: HssAccChannelMiddleChanDel
+ */
+TDM_PRIVATE icp_status_t
+HssAccChannelMiddleChanDel (icp_hssacc_channel_list_data_t *pListData)
+{
+ icp_status_t status = ICP_STATUS_SUCCESS;
+ unsigned prevChannelId, nextChannelId = ICP_HSSACC_INVALID_CHAN;
+ icp_hssacc_channel_list_data_t *pPrevChanListData, *pNextChanListData = NULL;
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Entering HssAccChannelMiddleChanDel\n");
+
+ prevChannelId = pListData->prevChannelId;
+ nextChannelId = pListData->nextChannelId;
+ pPrevChanListData = &(hssAccChannelData[prevChannelId]);
+ pNextChanListData = &(hssAccChannelData[nextChannelId]);
+
+
+
+ status =
+ HssAccChannelNextChanWriteMsgSend (prevChannelId,
+ nextChannelId,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_TX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ if (ICP_STATUS_SUCCESS == status)
+ {
+ status =
+ HssAccChannelNextChanWriteMsgSend (
+ prevChannelId,
+ nextChannelId,
+ IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_RX,
+ ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG);
+ }
+
+ if (status == ICP_STATUS_SUCCESS)
+ {
+ pListData->listId = ICP_HSSACC_CHANNEL_LIST_DELIMITER;
+ pListData->nextChannelId = ICP_HSSACC_INVALID_CHAN;
+ pListData->prevChannelId = ICP_HSSACC_INVALID_CHAN;
+
+ pPrevChanListData->nextChannelId = nextChannelId;
+ pNextChanListData->prevChannelId = prevChannelId;
+ }
+
+ ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT,
+ "Exiting HssAccChannelMiddleChanDel\n");
+
+ return status;
+}
+
+
+unsigned
+HssAccChannelListLastPortChannelGet (uint32_t portId,
+ icp_hssacc_channel_list_t listId)
+{
+ return hssAccLastChannelOnList[portId][listId];
+}
+
+
+unsigned
+HssAccChannelListPrevChannelOnListGet(uint32_t channelId)
+{
+ return hssAccChannelData[channelId].prevChannelId;
+}