diff options
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.c | 911 |
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; +} |