diff options
Diffstat (limited to 'Acceleration/library/icp_telephony/tdm_io_access')
31 files changed, 18617 insertions, 0 deletions
diff --git a/Acceleration/library/icp_telephony/tdm_io_access/Makefile b/Acceleration/library/icp_telephony/tdm_io_access/Makefile new file mode 100644 index 0000000..04fc632 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/Makefile @@ -0,0 +1,136 @@ +############################################################################ +# Targets supported +# all - builds everything and installs +# install - identical to all +# depend - build dependencies +# clean - clears derived objects except the .depend files +# distclean- clears all derived objects and the .depend file +# +# @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. +# Copyright(c) 2010,2011,2012 Avencall +# +# 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. +# +# BSD LICENSE +# +# Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. +# All rights reserved. +# Copyright(c) 2010,2011,2012 Avencall +# +# 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. +# +# +# +############################################################################ + + +# Ensure The ENV_DIR environmental var is defined. +ifndef ICP_ENV_DIR +$(error ICP_ENV_DIR is undefined. Please set the path to your environment makefile \ + "-> setenv ENV_DIR <path>") +endif + +#Add your project environment Makefile, extra comment +include $(ICP_ENV_DIR)/environment.mk + + +#include the makefile with all the default and common Make variable definitions +include $(ICP_BUILDSYSTEM_PATH)/build_files/common.mk + + +#Add the name for the executable, Library or Module output definitions +OUTPUT_NAME=$(ICP_TDM_IO_NAME) + +# List of Source Files to be compiled (to be in a single line or on different lines separated by a "\" and tab. +SOURCES= icp_hssacc_common.c \ + icp_hssacc_channel_list.c \ + icp_hssacc_channel_config.c \ + icp_hssacc_voice_bypass.c \ + icp_hssacc_service.c \ + icp_hssacc_queues_config.c \ + icp_hssacc_rx_datapath.c \ + icp_hssacc_tx_datapath.c \ + icp_hssacc_port_config.c \ + icp_hssacc_port_hdma_reg_mgr.c \ + icp_hssacc_common_timeslot_allocation.c \ + $(ICP_DEVICE)$(ICP_SLASH)icp_hssacc_timeslot_allocation.c \ + $(ICP_DEVICE)$(ICP_SLASH)icp_hssacc_address_translate.c \ + $(ICP_DEVICE)$(ICP_SLASH)icp_hssacc_param_check.c + + +# Setup include directory +INCLUDES += -I $(src)/include \ + -I $(PWD)/include \ + -I $(ICP_API_DIR) \ + -I $(ICP_API_DIR)/hss \ + -I $(ICP_API_DIR)/accel_infra \ + -I $(ICP_OSAL_DIR)/common/include + +ifeq ($(ICP_INTEL_DEV),YES) +INCLUDES += -I $(ICP_OSAL_DIR)/common/include/modules \ + -I $(ICP_OSAL_DIR)/common/include/modules/ddk \ + -I $(ICP_OSAL_DIR)/common/include/modules/bufferMgt \ + -I $(ICP_OSAL_DIR)/common/include/modules/ioMem +endif + +EXTRA_CFLAGS += -DENABLE_IOMEM -DENABLE_BUFFERMGT + + +#include your $(ICP_OS)_$(ICP_OS_LEVEL).mk file +include $(ICP_TDM_IO_DIR)/$(ICP_OS)_$(ICP_OS_LEVEL).mk + + +# Install the module to the output dir +install: module + + +###################Include rules and dependency makefiles######################## +include $(ICP_BUILDSYSTEM_PATH)/build_files/rules.mk +###################End of Rules and dependency inclusion######################### + + + + diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_address_translate.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_address_translate.c new file mode 100644 index 0000000..73a1269 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_address_translate.c @@ -0,0 +1,178 @@ +/****************************************************************************** + * @file icp_hssacc_address_translate.c + * + * @description Content of this file provides the definition of + * address translation functions from the virtual + * address space to the physical and vice-versa + * + * @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 "IxOsal.h" + +#include "icp.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_address_translate.h" +#include "icp_hssacc_trace.h" + +uint32_t +HssAccVirtToPhysAddressTranslateAndSwap(void* pVirtAddr) +{ + uint32_t physAddr = 0; + /* Convert the table base address to a physical address */ + physAddr = HssAccVirtToPhysAddressTranslate (pVirtAddr); +#ifdef SW_SWAPPING + /* Now convert the physical address to network order */ + physAddr = IX_OSAL_SWAP_BE_SHARED_LONG(physAddr); +#endif + return physAddr; +} + +void * +HssAccPhysToVirtAddressSwapAndTranslate(uint32_t physAddr) +{ + void * pVirtAddr = NULL; +#ifdef SW_SWAPPING + /* Now convert the physical address back to little endian mode */ + physAddr = IX_OSAL_SWAP_BE_SHARED_LONG(physAddr); +#endif + /* Convert the physical address to a virtual address*/ + pVirtAddr = HssAccPhysToVirtAddressTranslate (physAddr); + + return pVirtAddr; +} + + + +uint32_t +HssAccVirtToPhysAddressTranslate(void * const pVirtAddr) +{ + uint32_t physAddr = 0; + /* Convert the table base address to a physical address */ + physAddr = (uint32_t)IX_OSAL_MMU_VIRT_TO_PHYS (pVirtAddr); + + return physAddr; +} + + +void * +HssAccPhysToVirtAddressTranslate(const uint32_t physAddr) +{ + void * pVirtAddr = NULL; + + /* Convert the physical address to a table base address*/ + pVirtAddr = (void*)IX_OSAL_MMU_PHYS_TO_VIRT (physAddr); + + return pVirtAddr; +} + + + +void * +HssAccDmaMemAllocate(uint32_t sizeBytes, + uint32_t * physOffset) +{ + void * pVirtAddr = NULL; + *physOffset = 0; + pVirtAddr = (void *)IX_OSAL_CACHE_DMA_MALLOC(sizeBytes); + if (NULL != pVirtAddr) + { + *physOffset = HssAccVirtToPhysAddressTranslate(pVirtAddr); + } + return pVirtAddr; + +} + +/* This function perform an endianness swap on each word of the provided buffer + it assumed that the buffer size is a multiple of word size */ +void +HssAccDataEndiannessSwap(IX_OSAL_MBUF * const buffer) +{ +#ifdef SW_SWAPPING + uint32_t index = 0; + uint32_t * dataPtr = (uint32_t*)IX_OSAL_MBUF_MDATA(buffer); +#endif + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccDataEndiannessSwap" + " for Buffer 0x%08X\n", + (uint32_t)buffer); +#ifdef SW_SWAPPING + if ( 0 != (IX_OSAL_MBUF_PKT_LEN(buffer) % ICP_HSSACC_WORD_SIZE)) + { + ICP_HSSACC_REPORT_ERROR("HssAccDataEndiannessSwap - Buffer Provided" + " has a size that is not a multiple of a " + "word size\n"); + } + for (; + index < (IX_OSAL_MBUF_PKT_LEN(buffer) / ICP_HSSACC_WORD_SIZE); + index ++) + { + dataPtr[index] = IX_OSAL_SWAP_BE_SHARED_LONG(dataPtr[index]); + } +#endif + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccDataEndiannessSwap\n"); +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_config.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_config.c new file mode 100644 index 0000000..4f4da9b --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_channel_config.c @@ -0,0 +1,2174 @@ +/****************************************************************************** + * + * @file icp_hssacc_channel_config.c + * + * @description Contents of this file is the channel configuration module which + * include the implementation of the channel configuration API. + * + * @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 "IxOsal.h" + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_queues_config.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_channel_config.h" +#include "icp_hssacc_channel_list.h" +#include "icp_hssacc_timeslot_allocation.h" +#include "icp_hssacc_address_translate.h" +#include "icp_hssacc_tx_datapath.h" +#include "icp_hssacc_rx_datapath.h" + + +/* Stats */ +typedef struct icp_hssacc_channel_config_stats_s +{ + icp_hssacc_msg_with_resp_stats_t chanCfg; + icp_hssacc_msg_with_resp_stats_t chanEnable; + icp_hssacc_msg_with_resp_stats_t chanDisable; + icp_hssacc_msg_with_resp_stats_t hdlcChanCfg; + icp_hssacc_msg_with_resp_stats_t voiceChanCfg; + icp_hssacc_msg_with_resp_stats_t offsetTableLoad; + icp_hssacc_msg_with_resp_stats_t hdlcMaxRxCfg; +} icp_hssacc_channel_config_stats_t; + +typedef enum + { + ICP_HSSACC_VOICE_NB_CHAN_SIZE = 1, + ICP_HSSACC_VOICE_NBL_CHAN_SIZE = 2, + ICP_HSSACC_VOICE_WB_CHAN_SIZE = 4, + ICP_HSSACC_VOICE_UWB_CHAN_SIZE = 8 + } icp_hssacc_voice_supported_sizes_t; + + +/* definition in Bytes of the maximum sample size for each type of voice + channel.for example, G711 30msec sample is the factor for determining max + size for a narrowband channel */ + +#define ICP_HSSACC_VOICE_NB_MAX_SAMPLE_SIZE (240) +#define ICP_HSSACC_VOICE_NBL_MAX_SAMPLE_SIZE (480) +#define ICP_HSSACC_VOICE_WB_MAX_SAMPLE_SIZE (960) +#define ICP_HSSACC_VOICE_UWB_MAX_SAMPLE_SIZE (1920) + + +#define ICP_HSSACC_FCS_4_BYTE_WIDTH (4) +#define ICP_HSSACC_FCS_2_BYTE_WIDTH (2) + +/* + * Sets the enable bit in the timeslot word of HSS port provision table. + */ +#define ICP_HSSACC_HDMA_TIMESLOT_ENABLE (BIT_SET(23)) + +/* + * The channel ID must be shifted by this offset in the HSS port + * provision table + */ +#define ICP_HSSACC_HDMA_CHANNEL_OFFSET (16) + + + + +/* + * ---------------------------------------------------------------------------- + * Struct types + * ---------------------------------------------------------------------------- + */ +/* + * ---------------------------------------------------------------------------- + * Global variables + * ---------------------------------------------------------------------------- + */ + +/* Tracks the current channel state and configuration */ +TDM_PRIVATE icp_hssacc_channel_config_t +hssAccChannelConfig[ICP_HSSACC_MAX_NUM_CHANNELS]; + + +/* This variable holds the number of channels currently allocated. */ +TDM_PRIVATE unsigned hssAccNumChansAllocated = 0; + +TDM_PRIVATE icp_hssacc_channel_config_stats_t hssAccChanCfgStats; + +TDM_PRIVATE icp_boolean_t channelConfigModuleInitialised = ICP_FALSE; + + +/* + * ---------------------------------------------------------------------------- + * Static function declarations + * ---------------------------------------------------------------------------- + */ + +TDM_PRIVATE icp_status_t +HssAccChannelConfigHdlcServiceMsgSend (unsigned channelId); + +TDM_PRIVATE icp_status_t +HssAccChannelConfigVoiceServiceMsgSend (unsigned channelId); + + +TDM_PRIVATE icp_status_t +HssAccChannelConfigHdlcMaxFrameSizeSend (unsigned channelId); + +TDM_PRIVATE icp_status_t +HssAccChannelConfigMsgSend (unsigned channelId); + +TDM_PRIVATE void +HssAccChannelConfigStateReset (unsigned channelId); + + +/***************************************************************************** + * Abstract: + * The timeslot map for a given channel cannot span multiple TDM trunks, + * i.e. all timeslots pertaining to a channel must reside solely on + * line0_timeslot_bit_map, line1_timeslot_bit_map, line2_timeslot_bit_map + * or line3_timeslot_bit_map. + * This function enforces this policy as well as checking that at least 1 + * TS as been assigned. + *****************************************************************************/ +inline icp_status_t HssAccTimeslotErrorCheck (icp_hssacc_timeslot_map_t tsMap) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTimeslotErrorCheck\n"); + if (tsMap.line0_timeslot_bit_map != 0) + { + if ( (tsMap.line1_timeslot_bit_map | tsMap.line2_timeslot_bit_map | + tsMap.line3_timeslot_bit_map) != 0 ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTimeslotErrorCheck - The channel " + "timeslot mapping cannot span " + "TDM lines!\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + else if (tsMap.line1_timeslot_bit_map != 0) + { + if ( (tsMap.line2_timeslot_bit_map | + tsMap.line3_timeslot_bit_map) != 0 ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTimeslotErrorCheck - The channel " + "timeslot mapping cannot span " + "TDM lines!\n"); + status = ICP_STATUS_INVALID_PARAM; } + } + else if (tsMap.line2_timeslot_bit_map != 0) + { + if ( (tsMap.line3_timeslot_bit_map) != 0 ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTimeslotErrorCheck - The channel " + "timeslot mapping cannot span " + "TDM lines!\n"); + status = ICP_STATUS_INVALID_PARAM; } + } + else if (tsMap.line3_timeslot_bit_map == 0) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTimeslotErrorCheck - Invalid timeslot" + " configuration, no slots were chosen!\n"); + status = ICP_STATUS_INVALID_PARAM; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTimeslotErrorCheck\n"); + + return status; +} + + +/****************************************************************************** + * Abstract: + * counts the number of timeslots requested by the channel, + * determines the HSS line that the timeslots reside on and copies the + * appropriate line's TDM map to the variable chanTsMap. at least one TS + * must be assigned for this function to function correctly. + * + ****************************************************************************/ +void HssAccTimeslotConfigGet(icp_hssacc_timeslot_map_t tsMap, + unsigned * numTs, + icp_hssacc_line_t * lineId, + uint32_t * chanTsMap, + unsigned * firstTsPosition, + unsigned * lastTsPosition) +{ + unsigned tempNumTs = 0; + uint32_t bitMap = 0; + icp_boolean_t firstFound = ICP_FALSE; + + (*lastTsPosition) = 0; + (*firstTsPosition) = 0; + if (tsMap.line0_timeslot_bit_map != 0) + { + *lineId = ICP_HSSACC_LINE_0; + *chanTsMap = tsMap.line0_timeslot_bit_map; + } + else if (tsMap.line1_timeslot_bit_map != 0) + { + *lineId = ICP_HSSACC_LINE_1; + *chanTsMap = tsMap.line1_timeslot_bit_map; + } + else if (tsMap.line2_timeslot_bit_map != 0) + { + *lineId = ICP_HSSACC_LINE_2; + *chanTsMap = tsMap.line2_timeslot_bit_map; + } + else if (tsMap.line3_timeslot_bit_map != 0) + { + *lineId = ICP_HSSACC_LINE_3; + *chanTsMap = tsMap.line3_timeslot_bit_map; + } + bitMap = *chanTsMap; + tempNumTs += (bitMap & 1); + if (bitMap & 1) + { + firstFound = ICP_TRUE; + } + bitMap >>= 1; + while (bitMap) + { + tempNumTs += (bitMap & 1); + (*lastTsPosition) ++; + if ((ICP_FALSE == firstFound) && + (bitMap & 1)) + { + firstFound = ICP_TRUE; + (*firstTsPosition) = (*lastTsPosition); + } + bitMap >>= 1; + } + *numTs = tempNumTs; +} + +/****************************************************************************** + * Abstract: + * Initialises all global variables used during channel configuration. + * Allocates memory for the channel offset tables. + * Initialises the channel configuration mutex. + * + *****************************************************************************/ +icp_status_t +HssAccChannelConfigInit(void) +{ + unsigned channelId = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigInit\n"); + + if (ICP_TRUE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("HssAccChannelConfigInit - " + "Module is already Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Initialise the channel configuration struct */ + for (channelId = 0; + channelId < ICP_HSSACC_MAX_NUM_CHANNELS; + channelId ++) + { + HssAccChannelConfigStateReset(channelId); + } + + /* All channels are available */ + hssAccNumChansAllocated = 0; + } + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccTsAllocInit(); + } + if (ICP_STATUS_SUCCESS == status) + { + /* Reset the Messaging Stats */ + HssAccChannelConfigStatsReset(); + + /* Reset the Timeslot Allocation submodule Stats */ + HssAccTsAllocStatsReset(); + + HssAccChannelListsReset(); + + channelConfigModuleInitialised = ICP_TRUE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigInit\n"); + return status; +} + + +/****************************************************************************** + * Abstract: + * shuts down the channel Configuration sub-component of HSS Acc. + * it will reset all internal variables. + * + *****************************************************************************/ +icp_status_t +HssAccChannelConfigShutdown(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigShutdown\n"); + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("HssAccChannelConfigShutdown - " + "Service is not initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + HssAccTsAllocShutdown(); + /* just in case, set the number of used channels to the max so that + no one can allocate new channels */ + hssAccNumChansAllocated = ICP_HSSACC_MAX_NUM_CHANNELS; + channelConfigModuleInitialised = ICP_FALSE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigShutdown\n"); + return status; +} + +/****************************************************************************** + * Abstract: + * Allocate a channel on the specified port using the specified + * timeslots. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelAllocate (unsigned *pChannelId, + unsigned portId, + icp_hssacc_timeslot_map_t tsMap, + icp_hssacc_channel_type_t channelType) +{ + unsigned channelSize = 0; + unsigned channelId = ICP_HSSACC_MAX_NUM_CHANNELS; + icp_hssacc_line_t lineId = ICP_HSSACC_LINE_DELIMITER; + uint32_t channelTsMap = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t suitableChanIdFound = ICP_FALSE; + icp_boolean_t mutexLocked = ICP_FALSE; + unsigned lastTsPos = 0; + unsigned firstTsPos = ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + + ICP_HSSACC_TRACE_3 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelAllocate - " + "\n\tchannelPtr 0x%08X on port %u of type %u\n", + (unsigned)pChannelId, portId, channelType); + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocate - " + "service not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Sanity check the parameters */ + if ( (NULL == pChannelId) || + (portId >= ICP_HSSACC_MAX_NUM_PORTS) || + ICP_HSSACC_ENUM_INVALID (channelType, + ICP_HSSACC_CHAN_TYPE_DELIMITER) ) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocate - invalid " + "parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + if (ICP_STATUS_SUCCESS == status) + { + if (HssAccPortStateGet(portId) != ICP_HSSACC_PORT_ENABLED) + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccChannelAllocate - specified " + "port %u should be Enabled\n", + portId); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Verify that client requested a valid timeslot configuration */ + status = HssAccTimeslotErrorCheck (tsMap); + } + if (ICP_STATUS_SUCCESS == status) + { + /* + Extract all information from the timeslot mapping for this channel; + this includes the number of timeslots that the channel wants to use, + and the line on which the timeslots reside. + */ + HssAccTimeslotConfigGet (tsMap, &channelSize, + &lineId, &channelTsMap, + &firstTsPos, &lastTsPos); + + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "icp_HssAccChannelAllocate -" + " Timeslot Config with Size=%u and lastTsPos=%u\n", + channelSize, + lastTsPos); + + /* Check that the line used and timeslots used are compatible + with the port speed */ + status = HssAccPortLineValidCheck(portId, lineId, + firstTsPos, lastTsPos); + } + + if (ICP_STATUS_SUCCESS == status) + { + /* If this is a voice channel then it can only use + 1, 2 or 4 timeslots */ + if ( (ICP_HSSACC_CHAN_TYPE_VOICE == channelType) && + (channelSize != ICP_HSSACC_VOICE_NB_CHAN_SIZE && + channelSize != ICP_HSSACC_VOICE_NBL_CHAN_SIZE && + channelSize != ICP_HSSACC_VOICE_WB_CHAN_SIZE)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocate - " + "invalid number of timeslots. " + "A voice channel can only use" + " 1, 2 or 4 timeslots.\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocated - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* + * All channels may be used, so check before looping + * through each channel ID + */ + if (ICP_HSSACC_MAX_NUM_CHANNELS == hssAccNumChansAllocated) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocate - " + "All channels have" + " been allocated!\n"); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Verify that the timeslots requested aren't owned by another channel */ + if (ICP_FALSE == HssAccTsAvailableVerify (portId, lineId, channelTsMap)) + { + /* The timeslots are in use by another channel */ + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocate - The requested " + "timeslots have been reserved by " + "another channel\n"); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* + * If the code makes it to here there must be + * at least one channel not in use; find it. + * channelId going out of bounds checked for + * paranoias sake. + */ + channelId = 0; + while ((ICP_HSSACC_MAX_NUM_CHANNELS > channelId) && + (ICP_FALSE == suitableChanIdFound)) + { + if (ICP_HSSACC_CHANNEL_UNINITIALISED == + hssAccChannelConfig[channelId].state) + { + hssAccNumChansAllocated ++; + suitableChanIdFound = ICP_TRUE; + } + else + { + channelId ++; + } + } + + /* Save the channel ID to return to the client */ + *pChannelId = channelId; + + + /* Save these timeslots as in use by this channel */ + HssAccTsRegister (channelId, portId, + lineId, channelTsMap); + + hssAccChannelConfig[channelId].size = channelSize; + hssAccChannelConfig[channelId].lineId = lineId; + hssAccChannelConfig[channelId].timeslotMap = channelTsMap; + + } + + if (ICP_STATUS_SUCCESS == status) + { + + /* Update the channel configuration */ + hssAccChannelConfig[channelId].state = ICP_HSSACC_CHANNEL_ALLOCATED; + hssAccChannelConfig[channelId].type = channelType; + hssAccChannelConfig[channelId].portId = portId; + + HssAccTxDatapathChanTypeUpdate(channelId, + channelType); + + /* Update the channel offset tables with these timeslots */ + status = HssAccTsAllocUpdate (portId, + hssAccChannelConfig); + + if (ICP_STATUS_SUCCESS == status) + { + /* Update the Queue Manager Info */ + status = HssAccQueueConfigQSizeUpdate(channelId, channelType); + } + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccChannelListAdd(portId, channelId, channelSize); + } + if (ICP_STATUS_SUCCESS != status) + { + /* Revert Back */ + HssAccTsUnregister (portId, + hssAccChannelConfig[channelId].lineId, + hssAccChannelConfig[channelId].timeslotMap); + + /* Clear the timeslot allocation but keep the port, we + need it for generating the new tables */ + hssAccChannelConfig[channelId].lineId = ICP_HSSACC_LINE_DELIMITER; + hssAccChannelConfig[channelId].timeslotMap = 0; + hssAccChannelConfig[channelId].size = 0; + + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_UNINITIALISED; + hssAccNumChansAllocated --; + + ICP_HSSACC_REPORT_ERROR("icp_HssAccChannelAllocate - Failure " + "in updating the TDM I/O Unit with " + "the new channel\n"); + } + } + + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelAllocate - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + if (ICP_STATUS_SUCCESS == status) + { + /* In case this channel was previously allocated and has + leftover stats */ + status = icp_HssAccChannelStatsReset(channelId); + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelAllocate\n"); + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Configure the specified channel with the service agnostic parameters. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelConfigure (unsigned channelId, + icp_hssacc_data_polarity_t channelDataPolarity, + icp_hssacc_bit_endian_t channelBitEndianness, + icp_boolean_t channelByteSwapping, + icp_hssacc_bit_robbing_t rBitEnable, + icp_hssacc_robbed_bit_value_t rBitValue, + icp_hssacc_robbed_bit_location_t rBitLocation) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelConfigure for channel %u\n", + channelId); + + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if ((ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) || + ICP_HSSACC_ENUM_INVALID (channelBitEndianness, + ICP_HSSACC_BIT_ENDIAN_DELIMITER) || + ICP_HSSACC_ENUM_INVALID (rBitEnable, + ICP_HSSACC_BIT_ROBBING_DELIMITER) || + ICP_HSSACC_ENUM_INVALID (channelDataPolarity, + ICP_HSSACC_DATA_POLARITY_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - invalid " + "parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_BIT_ROBBING_ONE_BIT == rBitEnable) + { + if (ICP_HSSACC_CHAN_TYPE_VOICE == + hssAccChannelConfig[channelId].type) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - robbed " + "Bit cannot be used for a " + "voice channel\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if (ICP_HSSACC_ENUM_INVALID (rBitValue, + ICP_HSSACC_ROBBED_BIT_DELIMITER) || + ICP_HSSACC_ENUM_INVALID (rBitLocation, + ICP_HSSACC_ROBBED_BIT_POS_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - invalid " + "robbed Bit parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_CHANNEL_ALLOCATED != hssAccChannelConfig[channelId].state) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - Channel " + "is not in the correct state " + "for configuration\n"); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + hssAccChannelConfig[channelId].dataPolarity = channelDataPolarity; + hssAccChannelConfig[channelId].bitEndian = channelBitEndianness; + hssAccChannelConfig[channelId].byteSwap = channelByteSwapping; + hssAccChannelConfig[channelId].bitRobbing = rBitEnable; + hssAccChannelConfig[channelId].rBitValue = rBitValue; + hssAccChannelConfig[channelId].rBitLocation = rBitLocation; + hssAccChannelConfig[channelId].state = ICP_HSSACC_CHANNEL_CONFIGURED; + status = HssAccChannelConfigMsgSend(channelId); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccChannelConfigure - " + "failed to set channel configuration " + "in TDM I/O Unit\n"); + hssAccChannelConfig[channelId].state = ICP_HSSACC_CHANNEL_ALLOCATED; + } + } + + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelConfigure - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelConfigure\n"); + return status; +} + + + + + +/****************************************************************************** + * Abstract: + * Configure the HDLC service specific parameters for the + * specified channel. + *****************************************************************************/ +icp_status_t +icp_HssAccChannelHdlcServiceConfigure ( + unsigned channelId, + icp_hssacc_hdlc_crc_bit_width_t hdlcCrcBitWidth, + icp_hssacc_hdlc_sof_flag_type_t hdlcSofFlagType, + icp_hssacc_hdlc_idle_pattern_t hdlcRxIdlePattern, + icp_hssacc_hdlc_idle_pattern_t hdlcTxIdlePattern, + unsigned hdlcMaximumFrameSize) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + uint32_t maxHdlcServFrameSize = 0; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelHdlcServiceConfigure " + "for channel %u\n", + channelId); + + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if ((ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) || + ICP_HSSACC_ENUM_INVALID (hdlcCrcBitWidth, + ICP_HSSACC_HDLC_CRC_BIT_WIDTH_DELIMITER) || + ICP_HSSACC_ENUM_INVALID (hdlcSofFlagType, + ICP_HSSACC_HDLC_SOF_FLAG_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID (hdlcRxIdlePattern, + ICP_HSSACC_HDLC_IDLE_PATTERN_DELIMITER) || + ICP_HSSACC_ENUM_INVALID (hdlcTxIdlePattern, + ICP_HSSACC_HDLC_IDLE_PATTERN_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "invalid parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + + + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if (0 == hdlcMaximumFrameSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "Maximum HDLC Frame Size cannot be zero\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + maxHdlcServFrameSize = + HssAccRxDatapathMaxServiceFrameSizeGet(ICP_HSSACC_CHAN_TYPE_HDLC); + if (0 == maxHdlcServFrameSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "Maximum HDLC Frame Size for the HDLC " + "Service is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if (hdlcMaximumFrameSize > maxHdlcServFrameSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "Maximum HDLC Frame Size for this channel" + " is greater than that for the Service\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + + } + + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_CHANNEL_CONFIGURED != + hssAccChannelConfig[channelId].state) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "Channel is not in the appropriate " + "State\n"); + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "icp_HssAccChannelHdlcServiceConfigure - " + "Channel is in State (%u)\n", + hssAccChannelConfig[channelId].state); + status = ICP_STATUS_RESOURCE; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_CHAN_TYPE_VOICE == hssAccChannelConfig[channelId].type) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "attempting to configure HDLC Service " + "for an allocated Voice Channel\n"); + status = ICP_STATUS_RESOURCE; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + + hssAccChannelConfig[channelId].sofFlagType = hdlcSofFlagType; + hssAccChannelConfig[channelId].hdlcTxIdlePattern = hdlcTxIdlePattern; + hssAccChannelConfig[channelId].hdlcRxIdlePattern = hdlcRxIdlePattern; + hssAccChannelConfig[channelId].hdlcMaxFrSize = hdlcMaximumFrameSize; + hssAccChannelConfig[channelId].hdlcCrcBitWidth = hdlcCrcBitWidth; + + + status = HssAccChannelConfigHdlcServiceMsgSend(channelId); + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccChannelConfigHdlcMaxFrameSizeSend (channelId); + } + + if (ICP_STATUS_SUCCESS == status) + { + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED; + } + } + + /* Free the channel configuration mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelHdlcServiceConfigure - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelHdlcServiceConfigure\n"); + return status; +} + + + +/***************************************************************************** + * Abstract: + * Configure the Voice service specific parameters for the + * specified channel. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelVoiceServiceConfigure ( + unsigned channelId, + icp_hssacc_channel_voice_tx_idle_action_t txIdleAction, + uint8_t voiceIdlePattern, + unsigned voicePacketSize) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned maxAllowedPacketSize = 0; + icp_boolean_t mutexLocked = ICP_FALSE; + uint32_t maxVoiceServSampleSize = 0; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelVoiceServiceConfigure " + "for channel %u\n", + channelId); + + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if ((ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) || + ICP_HSSACC_ENUM_INVALID (txIdleAction, + ICP_HSSACC_VOICE_TX_IDLE_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "invalid parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_CHANNEL_CONFIGURED != + hssAccChannelConfig[channelId].state) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure -" + " Channel not in the appropriate state\n"); + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "icp_HssAccChannelVoiceServiceConfigure - " + "Channel is in State (%u)\n", + hssAccChannelConfig[channelId].state); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_CHAN_TYPE_HDLC == hssAccChannelConfig[channelId].type) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "attempting to configure Voice Service " + "for an allocated HDLC Channel\n"); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + switch (hssAccChannelConfig[channelId].size) + { + case ICP_HSSACC_VOICE_NB_CHAN_SIZE: + maxAllowedPacketSize = ICP_HSSACC_VOICE_NB_MAX_SAMPLE_SIZE; + break; + case ICP_HSSACC_VOICE_NBL_CHAN_SIZE: + maxAllowedPacketSize = ICP_HSSACC_VOICE_NBL_MAX_SAMPLE_SIZE; + break; + case ICP_HSSACC_VOICE_WB_CHAN_SIZE: + maxAllowedPacketSize = ICP_HSSACC_VOICE_WB_MAX_SAMPLE_SIZE; + break; + case ICP_HSSACC_VOICE_UWB_CHAN_SIZE: + maxAllowedPacketSize = ICP_HSSACC_VOICE_UWB_MAX_SAMPLE_SIZE; + break; + default: + /* unreachable due to verification in Allocation function */ + break; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if (maxAllowedPacketSize < voicePacketSize) + { + ICP_HSSACC_REPORT_ERROR_2 ("icp_HssAccChannelVoiceServiceConfigure -" + " Voice Sample Size (%u) too large for " + "channel (max Allowed is %u)\n", + voicePacketSize, + maxAllowedPacketSize); + status = ICP_STATUS_INVALID_PARAM; + } + if (0 == voicePacketSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure -" + " Voice Sample Size cannot be zero\n"); + status = ICP_STATUS_INVALID_PARAM; + } + maxVoiceServSampleSize = + HssAccRxDatapathMaxServiceFrameSizeGet(ICP_HSSACC_CHAN_TYPE_VOICE); + if (0 == maxVoiceServSampleSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "Maximum Voice Sample Size for the Voice " + "Service is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if (voicePacketSize > maxVoiceServSampleSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "Maximum Voice Sample Size for this channel" + " is greater than that for the Service\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + } + + + if (ICP_STATUS_SUCCESS == status) + { + + hssAccChannelConfig[channelId].voiceSampleSize = voicePacketSize; + hssAccChannelConfig[channelId].voiceIdlePattern = voiceIdlePattern; + hssAccChannelConfig[channelId].txIdleAction = txIdleAction; + hssAccChannelConfig[channelId].numBypasses = 0; + + status = HssAccChannelConfigVoiceServiceMsgSend (channelId); + + if (ICP_STATUS_SUCCESS == status) + { + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED; + } + } + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelVoiceServiceConfigure - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelVoiceServiceConfigure\n"); + return status; +} + + + + + + +/***************************************************************************** + * Abstract: + * Bring the specified channel UP, this will enable traffic flow on the + * channel. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelUp (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + icp_boolean_t mutexLocked = ICP_FALSE; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelUp for channel %u\n", + channelId); + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelUp - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelUp - invalid " + "channel Number\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + if (ICP_STATUS_SUCCESS == status) + { + if ((ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED != + hssAccChannelConfig[channelId].state) && + (ICP_HSSACC_CHANNEL_DOWN != + hssAccChannelConfig[channelId].state)) + + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccChannelUp - channel %u " + "is not in an appropriate state " + "for enabling\n", + channelId); + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "icp_HssAccChannelUp - channel %u " + "is state (%u) for enabling\n", + channelId, + hssAccChannelConfig[channelId].state); + status = ICP_STATUS_RESOURCE; + } + } + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelUp - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + mutexLocked = ICP_TRUE; + + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd8byteMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_ENABLE, + channelId, + ICP_HSSACC_TDM_IO_UNIT_FLOW_DIR_BOTH, + 0, 0, 0, 0, 0, + &message); + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_ENABLE_RESPONSE, + &(hssAccChanCfgStats.chanEnable), + NULL); + + + if (ICP_STATUS_SUCCESS == status) + { + hssAccChannelConfig[channelId].state = ICP_HSSACC_CHANNEL_ENABLED; + } + } + + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelUp - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelUp\n"); + return status; +} + + + +/***************************************************************************** + * Abstract: + * Bring down the specified channel. this will stop all traffic on + * that channel. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelDown (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + icp_boolean_t mutexLocked = ICP_FALSE; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelDown for channel %u\n", + channelId); + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDown - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDown - invalid " + "channel\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + if (ICP_STATUS_SUCCESS == status) + { + + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDown - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_CHANNEL_ENABLED != hssAccChannelConfig[channelId].state) + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccChannelDown - " + "channel %u is not enabled\n", + channelId); + status = ICP_STATUS_RESOURCE; + } + } + if (ICP_STATUS_SUCCESS == status) + { + if (0 != hssAccChannelConfig[channelId].numBypasses) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDown - channel is " + "used as part of a bypass, " + "disable bypass first\n"); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* change the channel state so that the datapath puts + rx buffers onto the rx free queue and not into the + channel ring */ + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_DOWN_TRANSITION; + + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd8byteMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_DISABLE, + channelId, + ICP_HSSACC_TDM_IO_UNIT_FLOW_DIR_BOTH, + 0, 0, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_DISABLE_RESPONSE, + &(hssAccChanCfgStats.chanDisable), + NULL); + + if (ICP_STATUS_SUCCESS == status) + { + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_DOWN; + } + else + { + /* restore state to enabled as the channel down failed */ + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_ENABLED; + } + } + + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDown - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelDown\n"); + return status; +} + + + + + + + +/***************************************************************************** + * Abstract: + * Delete the specified Channel. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelDelete (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelDelete for channel %u\n", + channelId); + + if (ICP_FALSE == channelConfigModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDelete - " + "Service is not Initialised\n"); + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelDelete\n"); + return ICP_STATUS_FAIL; + } + + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDelete - invalid " + "channel\n"); + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelDelete\n"); + return ICP_STATUS_INVALID_PARAM; + } + + + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDelete - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + + if (ICP_STATUS_SUCCESS == status) + { + if (!((ICP_HSSACC_CHANNEL_CONFIGURED == + hssAccChannelConfig[channelId].state) || + (ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED == + hssAccChannelConfig[channelId].state) || + (ICP_HSSACC_CHANNEL_ALLOCATED == + hssAccChannelConfig[channelId].state))) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDelete - channel " + "not available for deletion\n"); + status = ICP_STATUS_RESOURCE; + } + } + if (ICP_STATUS_SUCCESS == status) + { + + status = HssAccChannelListRemove(hssAccChannelConfig[channelId].portId, + channelId, + hssAccChannelConfig[channelId].size); + } + if (ICP_STATUS_SUCCESS == status) + { + /* Reset config, may have to actually send message to the + TDM I/O Unit to completely remove conf */ + HssAccTsUnregister (hssAccChannelConfig[channelId].portId, + hssAccChannelConfig[channelId].lineId, + hssAccChannelConfig[channelId].timeslotMap); + + /* Clear the timeslot allocation but keep the port, we + need it for generating the new tables */ + hssAccChannelConfig[channelId].lineId = ICP_HSSACC_LINE_DELIMITER; + hssAccChannelConfig[channelId].timeslotMap = 0; + hssAccChannelConfig[channelId].size = 0; + + /* Clear Timeslot Allocation for this channel */ + status = HssAccTsAllocDelete(channelId, + hssAccChannelConfig); + + /* Deregister rx callback */ + HssAccChannelRxCallbackDeregister(channelId); + + /* Deregister tx callback */ + HssAccTxDatapathChanTxDoneCallbackDeregister(channelId); + + } + if (ICP_STATUS_SUCCESS == status) + { + hssAccNumChansAllocated --; + + /* Clear the internal state */ + HssAccChannelConfigStateReset(channelId); + } + + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelDelete - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelDelete\n"); + return status; +} + +/***************************************************************************** + * Abstract: + * Sends the channel Common Configuration message to the TDM I/O Unit. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccChannelConfigMsgSend (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint16_t sdcCtrl = 0; + uint8_t sdcCtrlMsB = 0; + uint8_t sdcCtrlLsB = 0; + uint32_t inversion = ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_INVERT_OFF; + uint8_t channelType = 0; + uint8_t bitReverse = ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_NO_REVERSE; + uint8_t byteSwap = ICP_HSSACC_TDM_IO_UNIT_SDC_BYTE_NO_SWAP; + uint8_t bitRobbing = ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_OFF; + uint8_t rBitValue = ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_VALUE_ZERO; + uint8_t rBitLocation = ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_LOC_SEVEN; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigMsgSend for channel %u\n", + channelId); + /* Build SDC Ctrl Register for the TDM I/O Unit */ + if (ICP_HSSACC_DATA_POLARITY_INVERT == + hssAccChannelConfig[channelId].dataPolarity) + { + inversion = ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_INVERT_ON; + } + + if (ICP_HSSACC_CHAN_TYPE_VOICE == hssAccChannelConfig[channelId].type) + { + channelType = ICP_HSSACC_TDM_IO_UNIT_SDC_CHAN_TYPE_VOICE; + } + else + { + channelType = ICP_HSSACC_TDM_IO_UNIT_SDC_CHAN_TYPE_HDLC; + } + + /* if channel endianness is LSB then bit reversion required */ + if (ICP_HSSACC_BIT_ENDIAN_LSB == hssAccChannelConfig[channelId].bitEndian) + { + bitReverse = ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_REVERSE; + } + + if (ICP_TRUE == hssAccChannelConfig[channelId].byteSwap) + { + byteSwap = ICP_HSSACC_TDM_IO_UNIT_SDC_BYTE_SWAP; + } + + if (ICP_HSSACC_BIT_ROBBING_ONE_BIT == + hssAccChannelConfig[channelId].bitRobbing) + { + bitRobbing = ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_ONE_BIT_ON; + } + + if (ICP_HSSACC_ROBBED_BIT_ONE == hssAccChannelConfig[channelId].rBitValue) + { + rBitValue = ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_VALUE_ONE; + } + + if (ICP_HSSACC_ROBBED_BIT_POS_0 == + hssAccChannelConfig[channelId].rBitLocation) + { + rBitLocation = ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_LOC_ZERO; + } + + sdcCtrl = (bitRobbing << + ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_ROBBING_OFFSET) | + (rBitLocation << + ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_LOC_OFFSET) | + (rBitValue << + ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_VAL_OFFSET) | + (inversion << ICP_HSSACC_TDM_IO_UNIT_SDC_INVERT_OFFSET) | + (channelType << ICP_HSSACC_TDM_IO_UNIT_SDC_CHAN_TYPE_OFFSET) | + (bitReverse << ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_REVERSE_OFFSET) | + (byteSwap << ICP_HSSACC_TDM_IO_UNIT_SDC_BYTE_SWAP_OFFSET); + ICP_HSSACC_TRACE_1(ICP_HSSACC_DEBUG, + "Created SDC Ctrl Register 0x%04X\n", + sdcCtrl); + + sdcCtrlMsB = (sdcCtrl & ICP_HSSACC_TDM_IO_UNIT_SDC_CTRL_MSB_MASK) >> + ICP_HSSACC_TDM_IO_UNIT_SDC_CTRL_MSB_OFFSET; + + sdcCtrlLsB = sdcCtrl & ICP_HSSACC_TDM_IO_UNIT_SDC_CTRL_LSB_MASK; + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd8byteMsgCreate (ICP_HSSACC_TDM_IO_UNIT_HSS_CHAN_CFG, + channelId, + hssAccChannelConfig[channelId].type, + hssAccChannelConfig[channelId].size, + sdcCtrlMsB, + sdcCtrlLsB, + 0, + 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_CHAN_CFG_RESPONSE, + &(hssAccChanCfgStats.chanCfg), + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigMsgSend\n"); + return status; +} + + + + +/***************************************************************************** + * Abstract: + * Create the Transmit HDLC configuration register to be passed to the + * TDM I/O Unit. + * + *****************************************************************************/ +TDM_PRIVATE uint8_t +HssAccChannelHdlcTxCfgRegCreate (unsigned channelId) +{ + uint8_t cfgReg = 0; + /* will always post tx-hdlc block bit flip in SDC co-proc */ + uint8_t bitFlip = ICP_HSSACC_TDM_IO_UNIT_HDLC_CFG_BIT_FLIP; + uint8_t sofFlagType = ICP_HSSACC_TDM_IO_UNIT_HDLC_SOF_SHARED; + uint8_t hdlcCrcBitWidth = ICP_HSSACC_TDM_IO_UNIT_HDLC_16_BIT_CRC; + uint8_t hdlcTxIdlePattern = ICP_HSSACC_TDM_IO_UNIT_HDLC_IDLE_FLAG; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelHdlcTxCfgRegCreate\n"); + + if (ICP_HSSACC_HDLC_IDLE_PATTERN_ONES == + hssAccChannelConfig[channelId].hdlcTxIdlePattern) + { + hdlcTxIdlePattern = ICP_HSSACC_TDM_IO_UNIT_HDLC_IDLE_ONES; + } + + if (ICP_HSSACC_HDLC_CRC_BIT_WIDTH_32 == + hssAccChannelConfig[channelId].hdlcCrcBitWidth) + { + hdlcCrcBitWidth = ICP_HSSACC_TDM_IO_UNIT_HDLC_32_BIT_CRC; + } + if (ICP_HSSACC_HDLC_SOF_ONE_FLAG == + hssAccChannelConfig[channelId].sofFlagType) + { + sofFlagType = ICP_HSSACC_TDM_IO_UNIT_HDLC_SOF_ONE; + } + else if (ICP_HSSACC_HDLC_SOF_TWO_FLAGS == + hssAccChannelConfig[channelId].sofFlagType) + { + sofFlagType = ICP_HSSACC_TDM_IO_UNIT_HDLC_SOF_TWO; + } + + cfgReg = + (sofFlagType << + ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_SF_OFFSET) | + (hdlcCrcBitWidth << + ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_FCS_OFFSET) | + (hdlcTxIdlePattern << + ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_IM_OFFSET) | + (bitFlip << + ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_POSTBF_OFFSET); + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccChannelHdlcTxCfgRegCreate 0x%02X\n", + cfgReg); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelHdlcTxCfgRegCreate\n"); + return cfgReg; +} + +/***************************************************************************** + * Abstract: + * Create the Receive HDLC configuration register to be passed to the + * TDM I/O Unit. + * + *****************************************************************************/ +TDM_PRIVATE uint8_t +HssAccChannelHdlcRxCfgRegCreate (unsigned channelId) +{ + uint8_t cfgReg = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelHdlcRxCfgRegCreate\n"); + + + cfgReg = + (hssAccChannelConfig[channelId].hdlcCrcBitWidth << + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_CFG_FCS_OFFSET) | + (hssAccChannelConfig[channelId].hdlcRxIdlePattern << + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_CFG_IM_OFFSET); + + /* always pre rx-hdlc block bit flip in SDC co-proc */ + cfgReg |= (ICP_HSSACC_TDM_IO_UNIT_HDLC_CFG_BIT_FLIP << + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_CFG_PREBF_OFFSET); + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccChannelHdlcRxCfgRegCreate 0x%02X\n", cfgReg); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelHdlcRxCfgRegCreate\n"); + return cfgReg; +} + + + +/***************************************************************************** + * Abstract: + * Sends the channel HDLC Service Configuration message to + * the TDM I/O Unit + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccChannelConfigHdlcServiceMsgSend (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint32_t fcsSizeB = ICP_HSSACC_FCS_4_BYTE_WIDTH; + uint8_t txCfg = 0, rxCfg = 0; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigHdlcServiceMsgSend " + "for channel %u\n", + channelId); + + if (ICP_HSSACC_HDLC_CRC_BIT_WIDTH_16 == + hssAccChannelConfig[channelId].hdlcCrcBitWidth) + { + fcsSizeB = ICP_HSSACC_FCS_2_BYTE_WIDTH; + } + + + /* Construct the TxCfg and RxCfg registers for the TDM I/O Unit */ + txCfg = HssAccChannelHdlcTxCfgRegCreate(channelId); + + rxCfg = HssAccChannelHdlcRxCfgRegCreate(channelId); + + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd8byteMsgCreate (ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_CFG, + channelId, + 0, + 0, + 0, + rxCfg, + txCfg, + fcsSizeB, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_CFG_RESPONSE, + &(hssAccChanCfgStats.hdlcChanCfg), + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigHdlcServiceMsgSend\n"); + return status; +} + + + + + +/***************************************************************************** + * Abstract: + * Sends the channel HDLC Maximum Receive Frame Size configuration message + * to the TDM I/O Unit. + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccChannelConfigHdlcMaxFrameSizeSend (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint32_t hdlcMaximumFrameSize = 0; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigHdlcMaxFrameSizeSend " + "for channel %u\n", + channelId); + + hdlcMaximumFrameSize = + hssAccChannelConfig[channelId].hdlcMaxFrSize << + ICP_HSSACC_TDM_IO_UNIT_SHORT0_OFFSET; + + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_RX_MAX_SIZE_WR, + channelId, + 0, + 0, + hdlcMaximumFrameSize, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_RX_MAX_SIZE_WR_RESPONSE, + &(hssAccChanCfgStats.hdlcMaxRxCfg), + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigHdlcMaxFrameSizeSend\n"); + return status; +} + + +/***************************************************************************** + * Abstract: + * Sends the channel Voice Service Configuration message to + * the TDM I/O Unit + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccChannelConfigVoiceServiceMsgSend (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint32_t msgWord = 0; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigVoiceServiceMsgSend " + "for channel %u\n", + channelId); + msgWord = + (hssAccChannelConfig[channelId].voiceIdlePattern << + ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET) | + (hssAccChannelConfig[channelId].txIdleAction << + ICP_HSSACC_TDM_IO_UNIT_BYTE1_OFFSET) | + hssAccChannelConfig[channelId].voiceSampleSize; + + /* Construct the message for Channel Voice parameters setting + in the TDM I/O Unit */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_VOICE_CHAN_CFG, + channelId, + 0, + 0, + msgWord, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_VOICE_CHAN_CFG_RESPONSE, + &(hssAccChanCfgStats.voiceChanCfg), + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigVoiceServiceMsgSend\n"); + return status; +} + + + + + + +/***************************************************************************** + * Abstract: + * determines if it is valid to configure a bypass using the + * specified channel. + * + *****************************************************************************/ +icp_boolean_t +HssAccChannelConfigValidBypass(const unsigned channelId, + const unsigned portId) +{ + icp_boolean_t validChannel = ICP_FALSE; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelConfigValidBypass\n"); + + + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccChannelConfigValidBypass - " + "Channel %u of size %u and state %u " + "selected for Bypass\n", + channelId, + hssAccChannelConfig[channelId].size, + hssAccChannelConfig[channelId].state); + + if ((ICP_HSSACC_CHAN_TYPE_VOICE == hssAccChannelConfig[channelId].type) && + (ICP_HSSACC_VOICE_NB_CHAN_SIZE == hssAccChannelConfig[channelId].size) && + (ICP_HSSACC_CHANNEL_ENABLED == hssAccChannelConfig[channelId].state) && + (portId == hssAccChannelConfig[channelId].portId)) + { + validChannel = ICP_TRUE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelConfigValidBypass\n"); + return validChannel; +} + + + +/***************************************************************************** + * Abstract: + * reset the Channel configuration stats + * + *****************************************************************************/ +void +HssAccChannelConfigStatsReset (void) +{ + memset (&hssAccChanCfgStats, 0, sizeof(icp_hssacc_channel_config_stats_t)); + HssAccChannelListsStatsReset (); + +} + +/***************************************************************************** + * Abstract: + * Display stats for channel configuration + * + *****************************************************************************/ +void +HssAccChannelConfigStatsShow (void) +{ + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Configuration Statistics:\nChannel Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.chanCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nHDLC Channel Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.hdlcChanCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nVoice Channel Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.voiceChanCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\noffset Table Load\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.offsetTableLoad); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nHDLC Max Receive Frame Size Cfg messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.hdlcMaxRxCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Enable messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.chanEnable); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Disable messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccChanCfgStats.chanDisable); + + /* Also print out the Timeslot Allocation submodule stats */ + HssAccTsAllocStatsShow (); + +} + + +/***************************************************************************** + * Abstract: + * display the state of the specified channel + * + *****************************************************************************/ +void +HssAccChannelConfigStateShow (unsigned channelId) +{ + if (ICP_HSSACC_CHANNEL_UNINITIALISED == + hssAccChannelConfig[channelId].state) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel %u is Uninitialised.\n", + channelId, 0, 0, 0, 0, 0); + } + else + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel %u is Allocated on port %u Line %u with " + "%u Timeslots\nTimeslot Map is 0x%08X\n", + channelId, + hssAccChannelConfig[channelId].portId, + hssAccChannelConfig[channelId].lineId, + hssAccChannelConfig[channelId].size, + hssAccChannelConfig[channelId].timeslotMap, 0); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel has been Configured with:\n" + "\tData Inversion %u\n" + "\tBit Endianness %u\n" + "\tByte Endianness %u\n", + hssAccChannelConfig[channelId].dataPolarity, + hssAccChannelConfig[channelId].bitEndian, + hssAccChannelConfig[channelId].byteSwap, 0, 0, 0); + if (ICP_HSSACC_BIT_ROBBING_ONE_BIT == + hssAccChannelConfig[channelId].bitRobbing) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Bit Robbing is Enabled with a value of %u and " + "a position of %d\n", + hssAccChannelConfig[channelId].rBitValue, + hssAccChannelConfig[channelId].rBitLocation == + ICP_HSSACC_ROBBED_BIT_POS_7 ? 7 + : (hssAccChannelConfig[channelId].rBitLocation == + ICP_HSSACC_ROBBED_BIT_POS_0 ? 0 : -1), + 0, 0, 0, 0); + } + + if (ICP_HSSACC_CHAN_TYPE_VOICE == hssAccChannelConfig[channelId].type) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel is Allocated for Voice\n", 0, 0, 0, 0, 0, 0); + } + else + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel is Allocated for HDLC\n", 0, 0, 0, 0, 0, 0); + } + switch (hssAccChannelConfig[channelId].state) + { + case ICP_HSSACC_CHANNEL_ALLOCATED: + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel has only been allocated\n", 0, 0, 0, 0, 0, 0); + break; + + } + case ICP_HSSACC_CHANNEL_CONFIGURED: + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel has been allocated and configured with " + "general settings\n", + 0, 0, 0, 0, 0, 0); + break; + + } + case ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED: + case ICP_HSSACC_CHANNEL_DOWN: + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel has been allocated and service " + "specific parameters have been set\n", 0, 0, 0, 0, 0, 0); + break; + + } + case ICP_HSSACC_CHANNEL_ENABLED: + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channel is Enabled\n", 0, 0, 0, 0, 0, 0); + break; + + } + case ICP_HSSACC_CHANNEL_UNINITIALISED: + default: + { + /* This statement is unreachable due to previous error checking */ + ICP_HSSACC_REPORT_ERROR("HssAccChannelConfigStateShow - " + "Invalid Channel State to be printed\n"); + break; + } + } + } +} + +/***************************************************************************** + * Abstract: + * reset all the internal data regarding the specified channel + * + *****************************************************************************/ +TDM_PRIVATE void +HssAccChannelConfigStateReset (unsigned channelId) +{ + hssAccChannelConfig[channelId].state = ICP_HSSACC_CHANNEL_UNINITIALISED; + hssAccChannelConfig[channelId].type = ICP_HSSACC_CHAN_TYPE_DELIMITER; + hssAccChannelConfig[channelId].size = 0; + hssAccChannelConfig[channelId].portId = ICP_HSSACC_MAX_NUM_PORTS; + hssAccChannelConfig[channelId].lineId = ICP_HSSACC_LINE_DELIMITER; + hssAccChannelConfig[channelId].timeslotMap = 0; + hssAccChannelConfig[channelId].sdcCtrlReg = 0; + hssAccChannelConfig[channelId].rxCfg = 0; + hssAccChannelConfig[channelId].txCfg = 0; + hssAccChannelConfig[channelId].dataPolarity = ICP_HSSACC_DATA_POLARITY_SAME; + hssAccChannelConfig[channelId].bitEndian = ICP_HSSACC_BIT_ENDIAN_DELIMITER; + hssAccChannelConfig[channelId].byteSwap = ICP_FALSE; + hssAccChannelConfig[channelId].bitRobbing = ICP_HSSACC_BIT_ROBBING_DELIMITER; + hssAccChannelConfig[channelId].rBitValue = ICP_HSSACC_ROBBED_BIT_DELIMITER; + hssAccChannelConfig[channelId].rBitLocation = + ICP_HSSACC_ROBBED_BIT_POS_DELIMITER; + hssAccChannelConfig[channelId].hdlcMaxFrSize = 0; + hssAccChannelConfig[channelId].numBypasses = 0; + hssAccChannelConfig[channelId].sofFlagType = + ICP_HSSACC_HDLC_SOF_FLAG_TYPE_DELIMITER; + hssAccChannelConfig[channelId].hdlcTxIdlePattern = + ICP_HSSACC_HDLC_IDLE_PATTERN_DELIMITER; + hssAccChannelConfig[channelId].hdlcRxIdlePattern = + ICP_HSSACC_HDLC_IDLE_PATTERN_DELIMITER; + hssAccChannelConfig[channelId].voiceSampleSize = 0; + hssAccChannelConfig[channelId].voiceIdlePattern = 0; + hssAccChannelConfig[channelId].txIdleAction = + ICP_HSSACC_VOICE_TX_IDLE_DELIMITER; + hssAccChannelConfig[channelId].hdlcCrcBitWidth = + ICP_HSSACC_HDLC_CRC_BIT_WIDTH_DELIMITER; +} + +/***************************************************************************** + * Abstract: + * returns the configured channel type for the specified channel + * + *****************************************************************************/ +icp_hssacc_channel_type_t +HssAccChannelConfigTypeQuery (unsigned channelId) +{ + return hssAccChannelConfig[channelId].type; +} + + +/***************************************************************************** + * Abstract: + * set the specified channels as part of a bypass. + * + *****************************************************************************/ +void +HssAccChannelBypassPairSet(unsigned srcChannelId, + unsigned destChannelId) +{ + hssAccChannelConfig[srcChannelId].numBypasses ++; + hssAccChannelConfig[destChannelId].numBypasses ++; +} + + +/***************************************************************************** + * Abstract: + * clear the bypassed state for the specified channels + * + *****************************************************************************/ +void +HssAccChannelBypassPairClear(unsigned srcChannelId, + unsigned destChannelId) +{ + hssAccChannelConfig[srcChannelId].numBypasses --; + hssAccChannelConfig[destChannelId].numBypasses --; +} + + +/***************************************************************************** + * Abstract: + * returns the state of the specified channel + * + *****************************************************************************/ +icp_hssacc_channel_state_t +HssAccChannelConfigStateQuery (unsigned channelId) +{ + return hssAccChannelConfig[channelId].state; +} + + +/***************************************************************************** + * Abstract: + * used by the datapath modules to notify for a change of channel state + * following the retrieval of all buffers in the channel queues. + * + *****************************************************************************/ +void +HssAccChannelConfigBuffersClearedNotify (unsigned channelId) +{ + if (ICP_HSSACC_CHANNEL_DOWN == hssAccChannelConfig[channelId].state) + { + hssAccChannelConfig[channelId].state = + ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED; + } +} + + + + +/***************************************************************************** + * Abstract: + * return ICP_TRUE if there are any allocated channels on + * the specified port. + * + *****************************************************************************/ +icp_boolean_t +HssAccChannelConfigUsedChansOnPortFind (const unsigned portId) +{ + icp_boolean_t chanFound = ICP_FALSE; + unsigned index = 0; + + for (index = 0; index < ICP_HSSACC_MAX_NUM_CHANNELS; index ++) + { + if ((ICP_HSSACC_CHANNEL_UNINITIALISED != + hssAccChannelConfig[index].state) && + (portId == hssAccChannelConfig[index].portId)) + { + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "HssAccChannelConfigUsedChansOnPortFind - " + "Channel %u allocated on port %u\n", + index, + portId); + chanFound = ICP_TRUE; + break; + } + } + + return chanFound; +} + + 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; +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_common.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_common.c new file mode 100644 index 0000000..25dc112 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_common.c @@ -0,0 +1,464 @@ +/****************************************************************************** + * @file icp_hssacc_common.c + * + * @description Content of this file provides the implementation of + * common functionality used by all modules of the HSS Access component + * + * @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 "IxOsal.h" + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_trace.h" + +/* + * The command ID offset for TDM I/O Unit messages + */ +#define HSSACC_TDM_IO_UNIT_CMD_ID_OFFSET (ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET) + +/* + * The mask for the command ID in TDM I/O Unit messages + */ +#define HSSACC_TDM_IO_UNIT_CMD_ID_MASK \ + (0xFF << HSSACC_TDM_IO_UNIT_CMD_ID_OFFSET) + +/* + * The length of time to sleep while waiting for the TDM I/O Unit to + * respond (in milliseconds) + */ +#define HSSACC_TDM_IO_UNIT_WAIT_SLEEP_TIMEOUT (10) + +/* + * The number of times the HssAcc component will sleep while waiting for a + * response message from the TDM I/O Unit before triggering a time-out. + */ +#define HSSACC_TDM_IO_UNIT_MAX_NUM_SLEEPS (100) + + +/***************************************************************************** + * Abstract: + * This struct is used to notify a function that the TDM I/O unit has + * replied to the message previously submitted to it. + * Typically, the function that submitted the message will poll + * respReceived. When this flag is set (in the context of this callback), + * the polling client knows that a response has been generated for the + * message it submitted. + * + * Fields: + * respMsg - A 2 element array which is used to save the message response. + * respReceived - A boolean flag used to notify the polling client of the + * TDM I/O Unit's response. + * + *****************************************************************************/ +typedef struct icp_hss_acc_tdm_io_unit_resp_msg_s +{ + IxPiuMhMessage respMsg; + volatile icp_boolean_t respReceived; +} icp_hss_acc_tdm_io_unit_resp_msg_t; + + +/***************************************************************************** + * Abstract: + * Static variable used to store the most recent message response from the + * the TDM I/O Unit. + * + *****************************************************************************/ +TDM_PRIVATE icp_hss_acc_tdm_io_unit_resp_msg_t tdmIOUnitResponseMessage; + + +/* + * Function prototypes + */ +TDM_PRIVATE +void HssAccTdmIOUnitCmdRespCallback( + IxPiuMhPiuId piuId, + IxPiuMhMessage msg); + +TDM_PRIVATE +icp_status_t +HssAccComTdmIOUnitCmdMsgWait (volatile icp_boolean_t *const flagToWaitFor); + +TDM_PRIVATE +icp_status_t +HssAccComTdmIOUnitCmdMsgSend( + IxPiuMhMessage message, + icp_boolean_t reqResp, + volatile icp_boolean_t *const flagToWaitFor, + IxPiuMhCallback respCallback, + uint8_t solicitedPiuMsgId); + + +/***************************************************************************** + * Abstract: + * Constructs a 4-byte, 1-word TDM I/O Unit message. + * + * + *****************************************************************************/ +void +HssAccComTdmIOUnitCmd4byte1wordMsgCreate (uint32_t byte0, + uint32_t byte1, + uint32_t byte2, + uint32_t byte3, + uint32_t word, + IxPiuMhMessage *pMessage) +{ + /* create the message */ + pMessage->data[0] = + (byte3 << ICP_HSSACC_TDM_IO_UNIT_BYTE3_OFFSET) | + (byte2 << ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET) | + (byte1 << ICP_HSSACC_TDM_IO_UNIT_BYTE1_OFFSET) | + (byte0 << ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET); + pMessage->data[1] = word; + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmd4byte1wordMsgCreate " + "0x%08X 0x%08X\n", + pMessage->data[0], pMessage->data[1]); +} + + +/***************************************************************************** + * Abstract: + * Constructs an 8-byte TDM I/O Unit message. + * + * + *****************************************************************************/ +void +HssAccComTdmIOUnitCmd8byteMsgCreate (uint32_t byte0, + uint32_t byte1, + uint32_t byte2, + uint32_t byte3, + uint32_t byte4, + uint32_t byte5, + uint32_t byte6, + uint32_t byte7, + IxPiuMhMessage *pMessage) +{ + + + /* Create the TDM I/O Unit message format */ + pMessage->data[0] = + (byte3 << ICP_HSSACC_TDM_IO_UNIT_BYTE3_OFFSET) | + (byte2 << ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET) | + (byte1 << ICP_HSSACC_TDM_IO_UNIT_BYTE1_OFFSET) | + (byte0 << ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET); + + pMessage->data[1] = + (byte7 << ICP_HSSACC_TDM_IO_UNIT_BYTE3_OFFSET) | + (byte6 << ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET) | + (byte5 << ICP_HSSACC_TDM_IO_UNIT_BYTE1_OFFSET) | + (byte4 << ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET); + + ICP_HSSACC_TRACE_2(ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmd8byteMsgCreate 0x%08X 0x%08X\n", + pMessage->data[0], pMessage->data[1]); +} + + + + + +/***************************************************************************** + * Abstract: + * Submits a message to the TDM I/O Unit, waits for a response and verifies + * that the correct response was received, response word is + * passed back to client + * + * + *****************************************************************************/ +icp_status_t +HssAccComTdmIOUnitMsgSendAndRecv(IxPiuMhMessage message, + uint8_t response, + icp_hssacc_msg_with_resp_stats_t * stats, + uint32_t * responseWord) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint8_t cmdType = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOUnitMsgSendAndRecv\n"); + status = + HssAccComTdmIOUnitCmdMsgSend (message, + TRUE, + &(tdmIOUnitResponseMessage.respReceived), + HssAccTdmIOUnitCmdRespCallback, + response); + if (ICP_STATUS_SUCCESS == status) + { + stats->numTdmIOUnitMessagesSent ++; + stats->numTdmIOUnitRespReceived ++; + /* Extract the command ID from the message */ + cmdType = ( (tdmIOUnitResponseMessage.respMsg.data[0] & + HSSACC_TDM_IO_UNIT_CMD_ID_MASK) >> + HSSACC_TDM_IO_UNIT_CMD_ID_OFFSET ); + + if (cmdType != response) + { + stats->numTdmIOUnitInvalidResp ++; + ICP_HSSACC_REPORT_ERROR_2("HssAccComTdmIOUnitmsgSendAndRecv - " + "TDM I/O Unit provided invalid response\n" + "Expected %u Cmd and got %u\n", + cmdType, response); + status = ICP_STATUS_FATAL; + } + } + else if (ICP_STATUS_FATAL == status) + { + stats->numTdmIOUnitMessagesSent ++; + stats->numTdmIOUnitTimeoutErrs ++; + } + + if (ICP_STATUS_SUCCESS == status) + { + if (NULL != responseWord) + { + *responseWord = + tdmIOUnitResponseMessage.respMsg.data[1]; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOUnitMsgSendAndRecv\n"); + return status; +} + + +/***************************************************************************** + * Abstract: + * This callback is triggered by the TDM I/O unit in response to a message. + * + * + *****************************************************************************/ +TDM_PRIVATE +void HssAccTdmIOUnitCmdRespCallback(IxPiuMhPiuId piuId, + IxPiuMhMessage msg) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOUnitCmdRespCallback\n"); + + tdmIOUnitResponseMessage.respMsg = msg; + + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccTdmIOUnitCmdRespCallback 0x%08X 0x%08X " + "from TDM I/O Unit %u\n", + msg.data[0], msg.data[1], + piuId); + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOUnitCmdRespCallback\n"); + + /* This must be the last step in the callback */ + tdmIOUnitResponseMessage.respReceived = TRUE; +} + + +/***************************************************************************** + * Abstract: + * Sleeps until the specified flag is set (this occurs in + * HssAccTdmIOUnitCmdRespCallback), or times out and returns an error. + * + * + *****************************************************************************/ +TDM_PRIVATE +icp_status_t +HssAccComTdmIOUnitCmdMsgWait (volatile icp_boolean_t *const flagToWaitFor) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t numSleepsWithNoResp = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccComTdmIOUnitCmdMsgWait\n"); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmdMsgWait - " + "Waiting on the TDM I/O Unit to respond...\n"); + + /* wait until a response is received */ + while (numSleepsWithNoResp < HSSACC_TDM_IO_UNIT_MAX_NUM_SLEEPS) + { + if (TRUE == *flagToWaitFor) + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmdMsgWait - " + "TDM I/O Unit responded\n"); + break; + } + numSleepsWithNoResp ++; + ixOsalSleep (HSSACC_TDM_IO_UNIT_WAIT_SLEEP_TIMEOUT); + } + + /* check for timeout */ + if (HSSACC_TDM_IO_UNIT_MAX_NUM_SLEEPS == numSleepsWithNoResp) + { + ICP_HSSACC_REPORT_ERROR("HssAccComTdmIOUnitCmdMsgWait - " + "TDM I/O Unit failed to respond in time\n"); + status = ICP_STATUS_FATAL; + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccComTdmIOUnitCmdMsgWait\n"); + + return status; +} + + +/***************************************************************************** + * Abstract: + * Submits a message to the TDM I/O Unit and waits for the specified + * response from the TDM I/O Unit (if specified). + * + * + *****************************************************************************/ +TDM_PRIVATE +icp_status_t +HssAccComTdmIOUnitCmdMsgSend( + IxPiuMhMessage message, + icp_boolean_t reqResp, + volatile icp_boolean_t *const flagToWaitFor, + IxPiuMhCallback respCallback, + uint8_t solicitedPiuMsgId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IX_STATUS mhStatus = IX_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccComTdmIOUnitCmdMsgSend\n"); + + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmdMsgSend\n", + message.data[0], message.data[1]); + + /* check if a response is required */ + if (TRUE == reqResp) + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmdMsgSend - " + "Calling ixPiuMhMessageWithResponseSend\n"); + + /* Send the message to the Programmable I/O Unit + (TDM I/O Unit in this case) */ + *flagToWaitFor = FALSE; + mhStatus = ixPiuMhMessageWithResponseSend(IX_PIUMH_PIUID_PIU0, + message, + solicitedPiuMsgId, + respCallback, + IX_PIUMH_SEND_RETRIES_DEFAULT); + } + else + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccComTdmIOUnitCmdMsgSend - " + "Calling ixPiuMhMessageSend\n"); + + /* Send the message to the PiuMh */ + mhStatus = ixPiuMhMessageSend (IX_PIUMH_PIUID_PIU0, + message, + IX_PIUMH_SEND_RETRIES_DEFAULT); + } + + /* check the return from the Message Handler and block for response if + requested */ + if (IX_SUCCESS != mhStatus) + { + /* report the error */ + ICP_HSSACC_REPORT_ERROR ("HssAccComTdmIOUnitCmdMsgSend - " + "Message Handler failed to send\n"); + /* set return status */ + status = ICP_STATUS_FAIL; + } + else + { + /* wait for a response from the TDM I/O Unit if one is expected */ + if (TRUE == reqResp) + { + status = HssAccComTdmIOUnitCmdMsgWait (flagToWaitFor); + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccComTdmIOUnitCmdMsgSend\n"); + + return status; +} + + + + +/***************************************************************************** + * Abstract: + * Single message stat struct show + * + * + *****************************************************************************/ +void HssAccSingleMessageStatsShow (icp_hssacc_msg_with_resp_stats_t stat) +{ + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, + IX_OSAL_LOG_DEV_STDOUT, + "\n\t%u messages Sent\n\t%u messages received\n\t" + "%u invalid responses\t\n%u timeouts\n", + stat.numTdmIOUnitMessagesSent, stat.numTdmIOUnitRespReceived, + stat.numTdmIOUnitInvalidResp, stat.numTdmIOUnitTimeoutErrs, 0, 0); +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_common_timeslot_allocation.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_common_timeslot_allocation.c new file mode 100644 index 0000000..074d372 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_common_timeslot_allocation.c @@ -0,0 +1,441 @@ +/****************************************************************************** + * + * @file icp_hssacc_common_timeslot_allocation.c + * + * @description Content of this file is the implementation of the Timeslot + * allocation and de-allocation functionality used for channel Allocation + * and deletion common accross all platforms. + * + * @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 "IxOsal.h" + +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_timeslot_allocation.h" +#include "icp_hssacc_port_config.h" +#include "icp_hssacc_channel_config.h" + + + + +/* Base address of the TDM I/O Unit channel offset table */ +TDM_PRIVATE void * hssAccHdmaProvTableVirtAddr = NULL; + +TDM_PRIVATE void * hssAccTdmIoUnitOffsetTableVirtAddr = NULL; + +/* Tracks which channel is using which timeslot(s). */ +TDM_PRIVATE unsigned +hssAccChanTimeslotUsage[ICP_HSSACC_MAX_NUM_PORTS] +[ICP_HSSACC_MAX_TIMESLOTS_PER_PORT]; + + +void * HssAccTsAllocHdmaProvTableVirtAddrGet (void) +{ + return hssAccHdmaProvTableVirtAddr; +} + + + +void * HssAccTsAllocTdmIoUnitOffsetTableVirtAddrGet (void) +{ + return hssAccTdmIoUnitOffsetTableVirtAddr; +} + + + +/** + * Function Definition + */ +icp_status_t HssAccTsAllocInit (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned portId = ICP_HSSACC_MAX_NUM_PORTS; + unsigned tsIndex = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocInit\n"); + + /* Mark all timeslots as unreserved */ + for (portId = 0; portId < ICP_HSSACC_MAX_NUM_PORTS; portId ++) + { + for (tsIndex = 0; + tsIndex < ICP_HSSACC_MAX_TIMESLOTS_PER_PORT; + tsIndex ++) + { + hssAccChanTimeslotUsage[portId][tsIndex] = + ICP_HSSACC_INVALID_CHAN; + } + } + + hssAccHdmaProvTableVirtAddr = + (void*)IX_OSAL_CACHE_DMA_MALLOC (ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + if (NULL == hssAccHdmaProvTableVirtAddr) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTsAllocInit - TDM I/O Unit Timeslot " + "Provision table allocation failed\n"); + status = ICP_STATUS_FAIL; + } + + + + hssAccTdmIoUnitOffsetTableVirtAddr = + (void*)IX_OSAL_CACHE_DMA_MALLOC (ICP_HSSACC_TDM_IO_UNIT_OFFSET_TABLE_SZ); + + if (NULL == hssAccTdmIoUnitOffsetTableVirtAddr) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTsAllocInit - TDM I/O Unit Channel " + "Offset table allocation failed\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccTsAllocPlatformInit (); + } + else + { + /* Best Effort shutdown */ + HssAccTsAllocShutdown(); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocInit\n"); + return status; +} + + +/** + * Function Definition + */ +void HssAccTsAllocShutdown (void) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocShutdown\n"); + + if (NULL != hssAccHdmaProvTableVirtAddr) + { + IX_OSAL_CACHE_DMA_FREE(hssAccHdmaProvTableVirtAddr); + hssAccHdmaProvTableVirtAddr = NULL; + } + if (NULL != hssAccTdmIoUnitOffsetTableVirtAddr) + { + IX_OSAL_CACHE_DMA_FREE(hssAccTdmIoUnitOffsetTableVirtAddr); + hssAccTdmIoUnitOffsetTableVirtAddr = NULL; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocShutdown\n"); +} + + + + + +/** + * Function definition: HssAccTsAllocTableSwap + */ +icp_status_t HssAccTsAllocTableSwap (unsigned hssPortId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocTableSwap\n"); + + /* Create Message for TDM I/O Unit */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_SWAP, + 0, + hssPortId, + 0, + 0, + &message); + /* Send the message */ + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_SWAP_DONE, + HssAccTsAllocSwapStatsGet(), + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocTableSwap\n"); + + return status; +} + + + + + +/** + * Function definition: HssAccTsAllocDelete + */ +icp_status_t +HssAccTsAllocDelete (unsigned channelId, + icp_hssacc_channel_config_t * hssChannelData) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocDelete\n"); + + + /* Update the timeslot Allocation tables */ + status = HssAccTsAllocUpdate(hssChannelData[channelId].portId, + hssChannelData); + if (status != ICP_STATUS_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTsAllocDelete -" + " Error updating HDMA Timeslot Tables\n"); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocDelete\n"); + return status; +} + + +/** + * Function definition: HssAccOffsetTableWordRead + */ +icp_status_t +HssAccTsAllocOffsetTableWordRead (icp_boolean_t readShadowTable, + uint16_t tableOffset, + uint32_t *tableWord) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint8_t tableSwitch = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocOffsetTableWordRead\n"); + + if (ICP_TRUE == readShadowTable) + { + tableSwitch = 1; + } + + /* Create Message for TDM I/O Unit */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_READ, + tableSwitch, + 0, + 0, + tableOffset, + &message); + /* Send the message */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_READ_RESPONSE, + HssAccTsAllocOffsetTableReadStatsGet(), + tableWord); + + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccTsAllocOffsetTableWordRead - " + "Failed to retrieve Table data from " + "TDM I/O Unit\n"); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocOffsetTableWordRead\n"); + + return status; +} + + + + +/***************************************************************************** + * Abstract: + * Marks the specified timeslots as registered by the specified channel. + * + *****************************************************************************/ +void +HssAccTsRegister(unsigned channelId, + unsigned portId, + icp_hssacc_line_t lineId, + uint32_t tsMap) +{ + unsigned tsIndex = 0; + unsigned offset = 0; + + ICP_HSSACC_TRACE_3 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsRegister " + "on port %u line %u tsMap 0x%08X\n", + portId, lineId, tsMap); + + offset = lineId * ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + + /* Reserve the timeslot(s) */ + for (tsIndex = 0; + tsIndex < ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + tsIndex ++) + { + if (tsMap & BIT_SET(tsIndex)) + { + ICP_HSSACC_TRACE_2(ICP_HSSACC_DEBUG, + "HssAccTsRegister - " + "Registering timeslot %u on port %u\n", + offset + tsIndex, portId); + hssAccChanTimeslotUsage[portId][offset + tsIndex] = channelId; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsRegister\n"); +} + +/***************************************************************************** + * Abstract: + * Frees the specified timeslots. + * + *****************************************************************************/ +void +HssAccTsUnregister(unsigned portId, + icp_hssacc_line_t lineId, + uint32_t tsMap) +{ + unsigned tsIndex = 0; + unsigned offset = lineId * + ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + + ICP_HSSACC_TRACE_3 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsUnregister " + "on port %u line %u timeslots 0x%08X\n", + portId, + lineId, + tsMap); + + for (tsIndex = 0; + tsIndex < ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + tsIndex ++) + { + if (tsMap & BIT_SET(tsIndex)) + { + hssAccChanTimeslotUsage[portId] + [offset + tsIndex] = ICP_HSSACC_INVALID_CHAN; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsUnregister\n"); +} + +/***************************************************************************** + * Abstract: + * Checks if the requested timeslots are available for use by a channel. + * + *****************************************************************************/ +icp_boolean_t +HssAccTsAvailableVerify(unsigned portId, + icp_hssacc_line_t lineId, + uint32_t tsMap) +{ + unsigned tsIndex = 0; + unsigned offset = 0; + icp_boolean_t timeslotsAvailable = ICP_TRUE; + + ICP_HSSACC_TRACE_3 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAvailableVerify" + " on port %u line %u and tsMap 0x%08X\n", + portId, + lineId, + tsMap); + + /* + * There are 4 lines per HSS port and each line has 32 timeslots. Since + * timeslot usage is recorded per port, need to offset by N*32, where + * N is the HSS line number. + */ + offset = lineId * ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + + while ((ICP_TRUE == timeslotsAvailable) && + (tsIndex < ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE)) + { + if ( (tsMap & BIT_SET(tsIndex)) && + (ICP_HSSACC_INVALID_CHAN != + hssAccChanTimeslotUsage[portId][offset + tsIndex]) + ) + { + ICP_HSSACC_TRACE_2(ICP_HSSACC_DEBUG, + "Found a Timeslot already used on port %u, " + "TS %u\n", + portId, + offset + tsIndex); + timeslotsAvailable = ICP_FALSE; + } + tsIndex ++; + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAvailableVerify\n"); + + return timeslotsAvailable; +} + diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_param_check.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_param_check.c new file mode 100644 index 0000000..d8cba6d --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_param_check.c @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * @file icp_hssacc_param_check.c + * + * @description Content of this file is the implementation of parameter checking + * as valid for this specific platform. Other platforms may not support the same + * set of clock modes. + * + * @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_port_config.h" +#include "icp_hssacc_common.h" + + +icp_boolean_t +HssAccPortConfigTxClkModeInvalid(icp_hssacc_clk_mode_t clkMode) +{ + return ICP_HSSACC_ENUM_INVALID(clkMode,ICP_HSSACC_CLK_MODE_DELIMITER); +} + +icp_boolean_t +HssAccPortConfigRxClkModeInvalid(icp_hssacc_clk_mode_t clkMode) +{ + /* For Tolapai Rx, all listed modes are supported */ + return ICP_HSSACC_ENUM_INVALID(clkMode,ICP_HSSACC_CLK_MODE_DELIMITER); +} + + + diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_port_config.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_port_config.c new file mode 100644 index 0000000..652c9b1 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_port_config.c @@ -0,0 +1,1175 @@ +/****************************************************************************** + * @file icp_hssacc_port_config.c + * + * @description Contents of this file provide the implementation of the + * Port Configuration functionality for the HSS Access component + * + * @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. + * + * + * + * + *****************************************************************************/ + +/* ---------------------------------------------------------------------------- + * Includes + * ---------------------------------------------------------------------------- + */ +#include "IxOsal.h" + +#include "icp_hssacc.h" +#include "icp_hssacc_port_config.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_port_hdma_reg_mgr.h" +#include "icp_hssacc_timeslot_allocation.h" +#include "icp_hssacc_address_translate.h" + +/* + * ---------------------------------------------------------------------------- + * Macros + * ---------------------------------------------------------------------------- + */ +#define ICP_HSSACC_PORT_API_CONFIG_RESET(cfg) do { \ + cfg.frmSyncType = ICP_HSSACC_FRM_PULSE_SYNC_TYPE_DELIMITER; \ + cfg.frmSyncIO = ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_DELIMITER;\ + cfg.frmSyncClkEdge = ICP_HSSACC_CLK_EDGE_TYPE_DELIMITER;\ + cfg.dataClkEdge = ICP_HSSACC_CLK_EDGE_TYPE_DELIMITER;\ + cfg.clkMode = ICP_HSSACC_CLK_MODE_DELIMITER;\ + cfg.frmPulseUsage = ICP_HSSACC_FRM_PULSE_USAGE_TYPE_DELIMITER;\ + cfg.dataPolarity = ICP_HSSACC_DATA_POLARITY_DELIMITER;\ + cfg.drainMode = ICP_HSSACC_TX_PINS_DRAIN_MODE_TYPE_DELIMITER;\ + cfg.refFrame = ICP_HSSACC_REF_FRAME_DELIMITER;\ + cfg.dataPinsEnable = ICP_HSSACC_DATA_PINS_TYPE_DELIMITER;\ + cfg.loopback = ICP_FALSE;\ + cfg.frm_offset = 0;\ + cfg.fBitType = ICP_HSSACC_TX_FBIT_TYPE_DELIMITER; \ + cfg.fBitEnable = ICP_FALSE;\ + cfg.unassignedType = ICP_HSSACC_UNASSIGNED_DATA_DRIVE_DELIMITER; \ + cfg.interleaving = ICP_HSSACC_INTERLEAVING_TYPE_DELIMITER; \ +} while (0); + +#define ICP_HSSACC_PORT_ADD_CONFIG_RESET(addCfg) do { \ + addCfg.dataRate = ICP_HSSACC_DATA_RATE_EQUALS_CLK_RATE; \ + addCfg.frmPulseWidth = ICP_HSSACC_RX_DFLT_FRM_PULSE_WIDTH; \ +} while (0); + + + +/* + * ---------------------------------------------------------------------------- + * Struct types + * ---------------------------------------------------------------------------- + */ + + +/* Stats */ +typedef struct icp_hssacc_port_config_stats_s +{ + icp_hssacc_msg_with_resp_stats_t configTableLoad; + icp_hssacc_msg_with_resp_stats_t portEnable; + icp_hssacc_msg_with_resp_stats_t portDisable; +} icp_hssacc_port_config_stats_t; + +/* + * ---------------------------------------------------------------------------- + * Global variables + * ---------------------------------------------------------------------------- + */ + +/* Flag used to test whether the Port Config sub-component is initialised */ +TDM_PRIVATE icp_boolean_t portConfigInitialised = ICP_FALSE; + +/* Tracks the current port state and configuration */ +TDM_PRIVATE icp_hssacc_port_internal_config_t +hssAccPortConfig[ICP_HSSACC_MAX_NUM_PORTS]; + +/* Base address of the Port Config tables */ +TDM_PRIVATE void * hssAccPortConfigTablesBaseVirtAddr = NULL; + +TDM_PRIVATE icp_hssacc_port_config_stats_t hssAccPortConfigStats; + + + +/* + * ---------------------------------------------------------------------------- + * Static function declarations + * ---------------------------------------------------------------------------- + */ +TDM_PRIVATE icp_status_t +HssAccPortConfigTableUpdate(unsigned portId); + + +TDM_PRIVATE icp_status_t +HssAccPortConfigTableLoad(unsigned portId, + void * tableVirtAddr, + uint8_t msgId, + uint8_t msgRespId); + + +TDM_PRIVATE icp_status_t +HssAccPortStateSet(unsigned portId, + uint8_t msgId, + uint8_t msgRespId, + icp_hssacc_msg_with_resp_stats_t * stats); + + +/* + * ---------------------------------------------------------------------------- + * Function definitions + * ---------------------------------------------------------------------------- + */ +/****************************************************************************** + * Abstract: + * Initialises all global variables used for port configuration. + * Allocates memory for the HDMA port configuration tables. + * Initialises the port configuration mutex. + *****************************************************************************/ +icp_status_t +HssAccPortConfigInit(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned portId = 0; + icp_hssacc_hdma_port_config_t * pHdmaConfigTables = NULL; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortConfigInit\n"); + + if (ICP_TRUE == portConfigInitialised) + { + ICP_HSSACC_REPORT_ERROR ("HssAccPortConfigInit - " + "component has already been initialised\n"); + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigInit\n"); + return ICP_STATUS_FAIL; + } + + /* Allocate memory for the port config tables */ + hssAccPortConfigTablesBaseVirtAddr = + (void*)IX_OSAL_CACHE_DMA_MALLOC (ICP_HSSACC_MAX_NUM_PORTS* + sizeof(icp_hssacc_hdma_port_config_t)); + + if (NULL == hssAccPortConfigTablesBaseVirtAddr) + { + ICP_HSSACC_REPORT_ERROR ("HssAccPortConfigInit - " + "malloc for port config tables failed\n"); + status = ICP_STATUS_FAIL; + } + else + { + pHdmaConfigTables = + (icp_hssacc_hdma_port_config_t *)hssAccPortConfigTablesBaseVirtAddr; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Initialise the port configuration struct */ + for (portId = 0; portId < ICP_HSSACC_MAX_NUM_PORTS; portId ++) + { + hssAccPortConfig[portId].state = ICP_HSSACC_PORT_UNCONFIGURED; + hssAccPortConfig[portId].hdmaPortCfgTableVirtAddr = + &pHdmaConfigTables[portId]; + hssAccPortConfig[portId].clkSpeed = ICP_HSSACC_CLK_SPEED_DELIMITER; + + /* Rx dir config */ + ICP_HSSACC_PORT_API_CONFIG_RESET(hssAccPortConfig[portId].rx.cfg); + ICP_HSSACC_PORT_ADD_CONFIG_RESET(hssAccPortConfig[portId].rx.addCfg); + + + /* Tx dir config */ + ICP_HSSACC_PORT_API_CONFIG_RESET(hssAccPortConfig[portId].tx.cfg); + ICP_HSSACC_PORT_ADD_CONFIG_RESET(hssAccPortConfig[portId].tx.addCfg); + + } + /* Initialise the internal Stats */ + HssAccPortConfigStatsReset(); + portConfigInitialised = ICP_TRUE; + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigInit\n"); + return status; +} + + +/****************************************************************************** + * Abstract: + * Shutdown this sub-module: free any memory ... + * + *****************************************************************************/ +icp_status_t +HssAccPortConfigShutdown(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned portId = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortConfigShutdown\n"); + + if (ICP_FALSE == portConfigInitialised) + { + ICP_HSSACC_REPORT_ERROR ("HssAccPortConfigShutdown - " + "component has not been initialised\n"); + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigShutdown\n"); + return ICP_STATUS_FAIL; + } + for (portId = 0; portId < ICP_HSSACC_MAX_NUM_PORTS; portId ++) + { + if (hssAccPortConfig[portId].state == ICP_HSSACC_PORT_ENABLED) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccPortConfigShutdown - " + "port %d is still enabled, " + "shut it down first\n", + portId); + status = ICP_STATUS_FAIL; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Free memory allocated for the port config tables */ + IX_OSAL_CACHE_DMA_FREE(hssAccPortConfigTablesBaseVirtAddr); + hssAccPortConfigTablesBaseVirtAddr = NULL; + + for (portId = 0; portId < ICP_HSSACC_MAX_NUM_PORTS; portId ++) + { + hssAccPortConfig[portId].state = ICP_HSSACC_PORT_UNCONFIGURED; + hssAccPortConfig[portId].hdmaPortCfgTableVirtAddr = NULL; + } + + portConfigInitialised = ICP_FALSE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigShutdown\n"); + return status; +} + + +/****************************************************************************** + * Abstract: + * returns the number of supported HSS ports + * + *****************************************************************************/ +unsigned +icp_HssAccNumSupportedPortsGet ( void ) +{ + return ICP_HSSACC_MAX_NUM_PORTS; +} + + + +/****************************************************************************** + * Abstract: + * saves the specified configuration for the specified port + * + *****************************************************************************/ +icp_status_t +icp_HssAccPortConfig (unsigned portId, + icp_hssacc_port_config_params_t *configParams) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + icp_hssacc_port_config_t * pTxPortConfig = &(configParams->txPortConfig); + icp_hssacc_port_config_t * pRxPortConfig = &(configParams->rxPortConfig); + + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccPortConfig - port %d\n", + portId); + + /* Check if port config component has been initialised */ + if (ICP_FALSE == portConfigInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - port config component " + "has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Check Port Number */ + if (portId >= ICP_HSSACC_MAX_NUM_PORTS) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - " + "port number is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + + if (NULL == configParams) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - invalid " + "port settings pointer\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + + if (ICP_HSSACC_ENUM_INVALID(configParams->clkSpeed, + ICP_HSSACC_CLK_SPEED_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - " + "port clock speed is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + /* TX Check */ + if (ICP_HSSACC_ENUM_INVALID(pTxPortConfig->frmSyncType, + ICP_HSSACC_FRM_PULSE_SYNC_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->frmSyncIO, + ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_DELIMITER)|| + (pTxPortConfig->frmSyncIO == + ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_INVALID_VALUE) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->frmSyncClkEdge, + ICP_HSSACC_CLK_EDGE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->dataClkEdge, + ICP_HSSACC_CLK_EDGE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->frmPulseUsage, + ICP_HSSACC_FRM_PULSE_USAGE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->dataPolarity, + ICP_HSSACC_DATA_POLARITY_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->drainMode, + ICP_HSSACC_TX_PINS_DRAIN_MODE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->refFrame, + ICP_HSSACC_REF_FRAME_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->dataPinsEnable, + ICP_HSSACC_DATA_PINS_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->fBitType, + ICP_HSSACC_TX_FBIT_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->unassignedType, + ICP_HSSACC_UNASSIGNED_DATA_DRIVE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pTxPortConfig->interleaving, + ICP_HSSACC_INTERLEAVING_TYPE_DELIMITER) || +#ifdef IXP23xx + (ICP_TRUE == pTxPortConfig->loopback) || +#endif + HssAccPortConfigTxClkModeInvalid(pTxPortConfig->clkMode) ) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - one or more Tx port " + "config parameters is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + + + /* RX Check */ + if (ICP_HSSACC_ENUM_INVALID(pRxPortConfig->frmSyncType, + ICP_HSSACC_FRM_PULSE_SYNC_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pRxPortConfig->frmSyncIO, + ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_DELIMITER)|| + (pRxPortConfig->frmSyncIO == + ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_INVALID_VALUE) || + ICP_HSSACC_ENUM_INVALID(pRxPortConfig->frmSyncClkEdge, + ICP_HSSACC_CLK_EDGE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pRxPortConfig->dataClkEdge, + ICP_HSSACC_CLK_EDGE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pRxPortConfig->frmPulseUsage, + ICP_HSSACC_FRM_PULSE_USAGE_TYPE_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pRxPortConfig->dataPolarity, + ICP_HSSACC_DATA_POLARITY_DELIMITER) || + ICP_HSSACC_ENUM_INVALID(pRxPortConfig->interleaving, + ICP_HSSACC_INTERLEAVING_TYPE_DELIMITER) || + HssAccPortConfigRxClkModeInvalid(pRxPortConfig->clkMode) ) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - one or more Rx port " + "config parameters is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if ((pRxPortConfig->refFrame != + ICP_HSSACC_REF_FRAME_NOT_SELECTED) && + (pRxPortConfig->frmSyncIO == + ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_INPUT)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - Rx Reference Frame " + "selection is invalid for the Frame " + "pulse source setting\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if ((pTxPortConfig->refFrame != + ICP_HSSACC_REF_FRAME_NOT_SELECTED) && + (pTxPortConfig->frmSyncIO == + ICP_HSSACC_FRM_PULSE_SYNC_IO_TYPE_INPUT)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - Tx Reference Frame " + "selection is invalid for the Frame " + "pulse source setting\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + + if ((ICP_HSSACC_CLK_SPEED_1544KHZ != configParams->clkSpeed) && + (pRxPortConfig->fBitEnable || + pTxPortConfig->fBitEnable)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - " + "FBit is only supported for T1 speed\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if ((pRxPortConfig->fBitEnable && + (ICP_HSSACC_FRM_PULSE_USAGE_DISABLED == + pRxPortConfig->frmPulseUsage)) || + (pTxPortConfig->fBitEnable && + (ICP_HSSACC_FRM_PULSE_USAGE_DISABLED == + pTxPortConfig->frmPulseUsage))) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccPortConfig - " + "fBit and Frameless operation " + "not permitted\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + + if ((ICP_TRUE == pRxPortConfig->loopback) && + (ICP_TRUE == pTxPortConfig->loopback)) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccPortConfig -" + " The port cannot be configured for " + "both Remote and Internal loopback\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Lock the HssAcc mutex and update port configuration */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccPortConfig - " + "Mutex Lock Error\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + } + + if (ICP_STATUS_SUCCESS == status) + { + if ((0 == memcmp(&(hssAccPortConfig[portId].rx.cfg), + pRxPortConfig, + sizeof(icp_hssacc_port_config_t))) && + (0 == memcmp (&(hssAccPortConfig[portId].tx.cfg), + pTxPortConfig, + sizeof(icp_hssacc_port_config_t)))) + { + /* Supplied config is identical to what is already configured */ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "icp_HssAccPortConfig - port already " + "configured with identical settings\n"); + } + else + { + + /* Check if port is in a valid state for configuration */ + if (ICP_HSSACC_PORT_UNCONFIGURED != hssAccPortConfig[portId].state) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortConfig - " + "port has already been " + "configured at some stage\n"); + status = ICP_STATUS_FAIL; + } + else + { + /* Store Port Config Parameters in static memory */ + hssAccPortConfig[portId].clkSpeed = configParams->clkSpeed; + /* Rx dir config */ + memcpy (&(hssAccPortConfig[portId].rx.cfg), + pRxPortConfig, + sizeof(icp_hssacc_port_config_t)); + + /* Tx dir config */ + memcpy (&(hssAccPortConfig[portId].tx.cfg), + pTxPortConfig, + sizeof(icp_hssacc_port_config_t)); + + hssAccPortConfig[portId].state = ICP_HSSACC_PORT_CONFIGURED; + + } + } + } + + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccPortConfig - " + "Mutex Unlock Error\n"); + status = ICP_STATUS_MUTEX; + } + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortConfig\n"); + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Enable traffic on the specified TDM port + * + *****************************************************************************/ +icp_status_t +icp_HssAccPortUp (unsigned portId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccPortUp - port %d\n", + portId); + + /* Check if port config component has been initialised */ + if (ICP_FALSE == portConfigInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortUp - port config component " + "has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Check Port Number */ + if (portId >= ICP_HSSACC_MAX_NUM_PORTS) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortUp - " + "port number is invalid\n"); + + status = ICP_STATUS_INVALID_PARAM; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* Lock the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortUp - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* Check if port is already enabled */ + if (ICP_HSSACC_PORT_ENABLED == hssAccPortConfig[portId].state) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortUp - " + "failed to unlock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + + /* this port is already enabled so we dont need to do anything */ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortUp\n"); + return status; + } + + if (ICP_HSSACC_PORT_UNCONFIGURED == hssAccPortConfig[portId].state) + { + ICP_HSSACC_REPORT_ERROR_2 ("icp_HssAccPortUp - " + "port is not in an appropriate State - " + "port %d, state %d\n", + portId, + hssAccPortConfig[portId].state); + status = ICP_STATUS_FAIL; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccPortConfigTableUpdate(portId); + + } + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccTsAllocInitialAllocationUpdate(portId); + } + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccPortStateSet(portId, + ICP_HSSACC_TDM_IO_UNIT_PORT_ENABLE, + ICP_HSSACC_TDM_IO_UNIT_PORT_ENABLE_RESPONSE, + &(hssAccPortConfigStats.portEnable)); + } + if (ICP_STATUS_SUCCESS == status) + { + hssAccPortConfig[portId].state = ICP_HSSACC_PORT_ENABLED; + } + + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortUp - " + "failed to unlock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortUp\n"); + return status; + +} + + +/****************************************************************************** + * Abstract: + * Disables traffic on the specified TDM port. + * + *****************************************************************************/ +icp_status_t +icp_HssAccPortDown (unsigned portId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccPortDown - port %d\n", + portId); + + /* Check if port config component has been initialised */ + if (ICP_FALSE == portConfigInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortDown - port config component " + "has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Check Port Number */ + if (portId >= ICP_HSSACC_MAX_NUM_PORTS) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortDown - " + "port number is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + /* Check if port is enabled */ + if (ICP_STATUS_SUCCESS == status) + { + + /* Lock the HssAcc mutex and update port loopback configuration */ + if (ICP_STATUS_SUCCESS == ICP_HSSACC_MUTEX_LOCK()) + { + if ((ICP_HSSACC_PORT_ENABLED == hssAccPortConfig[portId].state) && + (!HssAccChannelConfigUsedChansOnPortFind(portId))) + { + status = + HssAccPortStateSet(portId, + ICP_HSSACC_TDM_IO_UNIT_PORT_DISABLE, + ICP_HSSACC_TDM_IO_UNIT_PORT_DISABLE_RESPONSE, + &(hssAccPortConfigStats.portDisable)); + + if (ICP_STATUS_SUCCESS == status) + { + + hssAccPortConfig[portId].state = ICP_HSSACC_PORT_CONFIGURED; + } + else + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccPortDown - " + "unable to bring down port %d\n", + portId); + } + } + else if (ICP_HSSACC_PORT_CONFIGURED != + hssAccPortConfig[portId].state) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortDown - " + "there are still allocated channels on" + " this port\n"); + status = ICP_STATUS_RESOURCE; + } + + /* Unlock the HssAcc configuration mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortDown - " + "failed to unlock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + + } + else + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortDown - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortDown\n"); + return status; + +} + + +/****************************************************************************** + * Abstract: + * Update the port configuration table in the TDM I/O Unit for this port. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccPortConfigTableUpdate(unsigned portId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_hdma_port_config_t * pPortCfgTable = NULL; + + ICP_HSSACC_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortConfigTableUpdate for " + "port %d at speed %d\n", + portId, + hssAccPortConfig[portId].clkSpeed); + /* Get the base address of the port config tables */ + pPortCfgTable = hssAccPortConfig[portId].hdmaPortCfgTableVirtAddr; + + /* Clear the contents of the HDMA port config table */ + memset (pPortCfgTable, 0, + sizeof(icp_hssacc_hdma_port_config_t)); + +#ifdef IXP23XX + /* Need to Create the LUT for IXP23XX as it is part of the + Port Config Table,creating tables with all TimeSlots assigned */ + status = HssAccHdmaMgrLUTCreate(hssAccPortConfig[portId].clkSpeed, + pPortCfgTable->tx_LUT); + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccHdmaMgrLUTCreate(hssAccPortConfig[portId].clkSpeed, + pPortCfgTable->rx_LUT); + } + HssAccHdmaMgrVCRCreate(&(pPortCfgTable->tx_vcr)); + HssAccHdmaMgrVCRCreate(&(pPortCfgTable->rx_vcr)); +#endif + + if (ICP_STATUS_SUCCESS == status) + { + HssAccHdmaMgrPCRCreate (ICP_HSSACC_HDMA_TX_REG_TYPE, + &(hssAccPortConfig[portId].tx), + &(pPortCfgTable->tx_pcr)); + HssAccHdmaMgrICRCreate (ICP_HSSACC_HDMA_TX_REG_TYPE, + portId, + &(pPortCfgTable->tx_icr)); + HssAccHdmaMgrClkCRCreate (hssAccPortConfig[portId].clkSpeed, + &(pPortCfgTable->clkcr)); + + status = HssAccHdmaMgrFCRCreate (ICP_HSSACC_HDMA_TX_REG_TYPE, + hssAccPortConfig[portId].clkSpeed, + &(hssAccPortConfig[portId].tx), + &(pPortCfgTable->tx_fcr)); + } + if (ICP_STATUS_SUCCESS == status) + { + HssAccHdmaMgrPCRCreate (ICP_HSSACC_HDMA_RX_REG_TYPE, + &(hssAccPortConfig[portId].rx), + &(pPortCfgTable->rx_pcr)); + + HssAccHdmaMgrICRCreate (ICP_HSSACC_HDMA_RX_REG_TYPE, + portId, + &(pPortCfgTable->rx_icr)); + + if ((hssAccPortConfig[portId].tx.cfg.frmPulseUsage != + ICP_HSSACC_FRM_PULSE_USAGE_ENABLED) || + (hssAccPortConfig[portId].rx.cfg.frmPulseUsage != + ICP_HSSACC_FRM_PULSE_USAGE_ENABLED)) + { + HssAccHdmaMgrCWRCreate (hssAccPortConfig[portId].clkSpeed, + &(pPortCfgTable->cwr)); + } + + status = HssAccHdmaMgrFCRCreate (ICP_HSSACC_HDMA_RX_REG_TYPE, + hssAccPortConfig[portId].clkSpeed, + &(hssAccPortConfig[portId].rx), + &(pPortCfgTable->rx_fcr)); + + } + + if (ICP_STATUS_SUCCESS == status) + { + + /* Flush the new table to memory */ + IX_OSAL_CACHE_FLUSH (pPortCfgTable, + sizeof(icp_hssacc_hdma_port_config_t)); + + /* Load the new HDMA port config table for this port */ + status = + HssAccPortConfigTableLoad ( + portId, + pPortCfgTable, + ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_LOAD, + ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_LOAD_RESPONSE); + } + + if (ICP_STATUS_FATAL == status) + { + ICP_HSSACC_REPORT_ERROR ("HssAccPortConfigTableUpdate - HDMA port " + "config table update - Fatal Error " + "communicating with the TDM I/O unit\n"); + } + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigTableUpdate\n"); + return status; +} + +/****************************************************************************** + * Abstract: + * Send Port Configuration message to the TDM I/O Unit + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccPortConfigTableLoad(unsigned portId, + void * tableVirtAddr, + uint8_t msgId, + uint8_t msgRespId) +{ + uint32_t physAddr = 0; + IxPiuMhMessage message; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortConfigTableLoad\n"); + + + + /* Convert the table base address to a physical address */ + physAddr = + HssAccVirtToPhysAddressTranslate(tableVirtAddr); + + if (0 == physAddr) + { + ICP_HSSACC_REPORT_ERROR("HssAccPortConfigTableLoad - Translation of " + "Virtual Address resulted in NULL value\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + msgId, + 0, + portId, + (sizeof(icp_hssacc_hdma_port_config_t) / ICP_HSSACC_WORD_SIZE), + physAddr, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + msgRespId, + &(hssAccPortConfigStats.configTableLoad), + NULL); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigTableLoad\n"); + + return status; +} + + +/****************************************************************************** + * Abstract: + * Set the state of the TDM port within the TDM I/O Unit. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccPortStateSet(unsigned portId, + uint8_t msgId, + uint8_t msgRespId, + icp_hssacc_msg_with_resp_stats_t * stats) +{ + IxPiuMhMessage message; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortStateSet\n"); + + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate (msgId, + 0, + portId, + 0, + 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv(message, + msgRespId, + stats, + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortStateSet\n"); + + return status; +} + + + +/****************************************************************************** + * Abstract: + * check the validity of the line and last timeslot to be used using + * the known internal port configuration. + * + *****************************************************************************/ +icp_status_t +HssAccPortLineValidCheck (unsigned portId, + icp_hssacc_line_t lineId, + unsigned firstTsPos, + unsigned lastTsPos) +{ + icp_status_t status = ICP_STATUS_RESOURCE; + ICP_HSSACC_TRACE_3 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortLineValidCheck for " + "Port %d, line %d and TS %d\n", + portId, + lineId, + lastTsPos); + + if (ICP_HSSACC_LINE_0 != lineId) + { + if (((ICP_HSSACC_LINE_1 == lineId) || + (ICP_HSSACC_LINE_3 == lineId) || + (ICP_HSSACC_LINE_2 == lineId)) && + (ICP_HSSACC_CLK_SPEED_8192KHZ == hssAccPortConfig[portId].clkSpeed)) + { + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccPortLineValidCheck - " + "Line %d config Valid\n", + lineId); + status = ICP_STATUS_SUCCESS; + } + else + { + ICP_HSSACC_REPORT_ERROR ("HssAccPortLineValidCheck - Line specified " + "is not valid for current Clock speed\n"); + } + } + else + { + if ((ICP_HSSACC_CLK_SPEED_1544KHZ == + hssAccPortConfig[portId].clkSpeed) && + ((lastTsPos > ICP_HSSACC_TIMESLOTS_PER_T1_LINE) || + (firstTsPos == 0))) + { + ICP_HSSACC_REPORT_ERROR ("HssAccPortLineValidCheck - " + "Attempting to allocate Invalid " + "Timeslots for a T1 line\n"); + } + else + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccPortLineValidCheck - " + "Line 0 config Valid\n"); + status = ICP_STATUS_SUCCESS; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortLineValidCheck\n"); + return status; +} + +/****************************************************************************** + * Abstract: + * return the current state of the specified port + * + *****************************************************************************/ +icp_hssacc_port_state_t +HssAccPortStateGet ( unsigned portId) +{ + return hssAccPortConfig[portId].state; +} + + +/****************************************************************************** + * Abstract: + * Reset the internal stats for this sub-module + * + *****************************************************************************/ +void +HssAccPortConfigStatsReset (void) +{ + memset (&hssAccPortConfigStats, 0, sizeof(icp_hssacc_port_config_stats_t)); +} + + + +/****************************************************************************** + * Abstract: + * display all the internal stats for this sub-module + * + *****************************************************************************/ +void +HssAccPortConfigStatsShow (void) +{ + unsigned portId = 0; + icp_hssacc_hdma_port_config_t * portConfig = NULL; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccPortConfigStatsShow\n"); + if (ICP_TRUE == portConfigInitialised) + { + for (portId = 0; portId < ICP_HSSACC_MAX_NUM_PORTS; portId ++) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nPort %d:\n", + portId, + 0, 0, 0, 0, 0); + + if (ICP_HSSACC_PORT_UNCONFIGURED == hssAccPortConfig[portId].state) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\tnot configured\n", + 0, 0, 0, 0, 0, 0); + } + else + { + portConfig = (hssAccPortConfig[portId].hdmaPortCfgTableVirtAddr); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nPort %d in State %d, Configuration:" + "\n\ttx_pcr 0x%08X" + "\n\trx_pcr 0x%08X" + "\n\ttx_fcr 0x%08X" + "\n\trx_fcr 0x%08X", + portId, hssAccPortConfig[portId].state, + portConfig->tx_pcr, + portConfig->rx_pcr, + portConfig->tx_fcr, + portConfig->rx_fcr); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\n\ttx_icr 0x%08X\n\trx_icr 0x%08X" + "\n\tclkcr 0x%08X\n\tcwr 0x%08X\n", + portConfig->tx_icr, + portConfig->rx_icr, + portConfig->clkcr, + portConfig->cwr, 0, 0); + + switch (hssAccPortConfig[portId].clkSpeed) + { + case ICP_HSSACC_CLK_SPEED_1544KHZ: + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\tPort Speed Configured For 1.544MHZ\n", + 0, 0, 0, 0, 0, 0); + break; + case ICP_HSSACC_CLK_SPEED_2048KHZ: + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\tPort Speed Configured For 2.048MHZ\n", + 0, 0, 0, 0, 0, 0); + break; + case ICP_HSSACC_CLK_SPEED_8192KHZ: + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\tPort Speed Configured For 8.192MHZ\n", + 0, 0, 0, 0, 0, 0); + break; + default: + break; + } + } + } + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nPort Configuration Statistics:\n" + "Config Table Load Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccPortConfigStats.configTableLoad); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nPort Up Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccPortConfigStats.portEnable); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nPort Down Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccPortConfigStats.portDisable); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccPortConfigStatsShow\n"); + +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_port_hdma_reg_mgr.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_port_hdma_reg_mgr.c new file mode 100644 index 0000000..66ea618 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_port_hdma_reg_mgr.c @@ -0,0 +1,546 @@ +/****************************************************************************** + * @file icp_hssacc_port_hdma_reg_mgr.c + * + * @description Contents of this file is the implementation of the HSS + * Port registers Creation from API parameters and internal settings. + * + * @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 "IxOsal.h" + +#include "icp_hssacc.h" +#include "icp_hssacc_port_config.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_port_hdma_reg_mgr.h" + + +/** + * Typedefs whose scope is limited to this file. + */ + +/* Structure holding HDMA Co-p system clock divider definitions */ +typedef struct icp_hssacc_hdma_sys_clk_s +{ + uint16_t main; + uint16_t num; + uint16_t denom; +} icp_hssacc_hdma_sys_clk_t; + + + +/* HSS Co-p clock divider from the TDM I/O Unit system clk */ +TDM_PRIVATE icp_hssacc_hdma_sys_clk_t +hssAccHdmaSysClk[ICP_HSSACC_CLK_SPEED_DELIMITER] = + { + ICP_HSSACC_HDMA_SYSCLK_1544KHZ, + ICP_HSSACC_HDMA_SYSCLK_2048KHZ, + ICP_HSSACC_HDMA_SYSCLK_8192KHZ + }; + +TDM_PRIVATE uint32_t +tdmPbaAddresses[ICP_HSSACC_HDMA_REG_TYPE_DELIMITER] + [ICP_HSSACC_MAX_NUM_PORTS] = + { + { + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_0, + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_1, + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_2 +#ifdef IXP23XX +, + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_3 +#endif + }, + { + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_0, + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_1, + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_2 +#ifdef IXP23XX +, + ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_3 +#endif + } + } ; + + + +/** + * Function definition: HssAccHdmaMgrPCRCreate + */ +void +HssAccHdmaMgrPCRCreate (icp_hssacc_hdma_reg_trans_t type, + const icp_hssacc_port_full_config_t *portConfig, + uint32_t *pcr) +{ + + + uint32_t offsetInReg = ICP_HSSACC_TDM_IO_UNIT_HDMA_RX_PCR_LB_OFFSET; + uint32_t clkDirection = ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CLKDIR_OUTPUT; +#ifdef EP805XX + uint32_t clkSelect = ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CS_INT; +#endif + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccHdmaMgrPCRCreate\n"); + + *pcr = 0; + + if (ICP_HSSACC_CLK_MODE_INPUT_EXTERNAL == portConfig->cfg.clkMode) + { + clkDirection = ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CLKDIR_INPUT; + } +#ifdef EP805XX + /* A single API parameter maps to 2 fields of this register + map 1 to 2 here starting with default values above */ + if (ICP_HSSACC_CLK_MODE_OUTPUT_REF == portConfig->cfg.clkMode) + { + clkSelect = ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CS_EXT_REF; + } +#endif + + + + /* create the common parts of the HSS co-p pcr register */ + /* note: portDataBitEndianness is now ICP_HSSACC_BIT_ENDIAN_MSB + at all times */ + *pcr = + (portConfig->cfg.frmSyncType << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FT_OFFSET) | + (portConfig->cfg.frmSyncIO << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FS_OFFSET) | + (portConfig->cfg.frmSyncClkEdge << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FE_OFFSET) | + (portConfig->cfg.dataClkEdge << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_DE_OFFSET) | + (clkDirection << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CLKDIR_OFFSET)| + (portConfig->cfg.frmPulseUsage << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FR_OFFSET) | + (portConfig->addCfg.dataRate << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_RATE_OFFSET) | + (portConfig->cfg.dataPolarity << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_DP_OFFSET) | + (ICP_HSSACC_BIT_ENDIAN_MSB << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_BITEND_OFFSET)| +#ifdef EP805XX + (portConfig->cfg.refFrame << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_REFF_OFFSET) | + (clkSelect << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CS_OFFSET) | +#endif + (portConfig->addCfg.frmPulseWidth - 1); + /* width varies from 1 to 8 but input value to co-proc is 0 to 7*/ + + + /* check the tx specific parameters */ + if (ICP_HSSACC_HDMA_TX_REG_TYPE == type) + { + offsetInReg = ICP_HSSACC_TDM_IO_UNIT_HDMA_TX_PCR_LB_OFFSET; + /* create the tx specific parts of the HSS co-p pcr register */ + *pcr |= + (portConfig->cfg.drainMode << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_OD_OFFSET) | + (portConfig->cfg.dataPinsEnable << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_EN_OFFSET) | + (portConfig->cfg.fBitType << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FB_OFFSET) | + (0 << ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_56KTYPE_OFFSET) | + (portConfig->cfg.unassignedType << + ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_UTYPE_OFFSET) | + (0 << ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_56KEND_OFFSET ) | + (0 << ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_56KSEL_OFFSET ); + } + if (ICP_TRUE == portConfig->cfg.loopback) + { + *pcr |= (ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_LB_ON + << offsetInReg); + } + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccHdmaMgrPCRCreate - " + "PCR = 0x%08X\n", *pcr); + +#ifdef SW_SWAPPING + *pcr = IX_OSAL_SWAP_BE_SHARED_LONG(*pcr); +#endif + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccHdmaMgrPCRCreate\n"); +} + +/** + * Function definition: HssAccHdmaMgrFCRCreate + */ +icp_status_t +HssAccHdmaMgrFCRCreate (icp_hssacc_hdma_reg_trans_t type, + icp_hssacc_clk_speed_t clkSpeed, + const icp_hssacc_port_full_config_t *portConfig, + uint32_t *fcr) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint8_t size = 0; + uint16_t offsetMaxVal = 0; + uint32_t offset = 0; + uint32_t fBitEnable = 0; + /* Used to indicate if this Hss Port is using MVIP or not */ + icp_hssacc_hdma_mvip_switch_t mvipSwitch = + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_DELIMITER; + /* Used to indicate if this Hss Port is using quad MVIP or not */ + icp_hssacc_hdma_mvip_setting_t mvipSetting = + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_DELIMITER; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccHdmaMgrFCRCreate\n"); + + switch (clkSpeed) + { + case ICP_HSSACC_CLK_SPEED_1544KHZ: + size = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_T1_IN_TS; + mvipSwitch = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_OFF; + offsetMaxVal = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_T1_IN_BITS; + if (portConfig->cfg.frm_offset >= offsetMaxVal) + { + ICP_HSSACC_REPORT_ERROR ("HssAccHdmaMgrFCRCreate - frmOffset >=" + " T1 frame size\n"); + status = ICP_STATUS_INVALID_PARAM; + } + break; + + case ICP_HSSACC_CLK_SPEED_2048KHZ: + size = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_TS; + mvipSwitch = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_OFF; + offsetMaxVal = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_BITS; + if (portConfig->cfg.frm_offset >= offsetMaxVal) + { + ICP_HSSACC_REPORT_ERROR ("HssAccHdmaMgrFCRCreate - frmOffset >=" + " E1 frame size\n"); + status = ICP_STATUS_INVALID_PARAM; + } + break; + + + case ICP_HSSACC_CLK_SPEED_8192KHZ: + size = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_TS; + mvipSwitch = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_ON; + mvipSetting = ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_QUAD; + offsetMaxVal = + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_QUAD_MVIP_IN_BITS; + /* No need to check if (offset > offsetMaxVal), the service I/F has + done this already. */ + break; + + default: + /* clkSpeed is already error checked so this default is unreachable */ + ICP_HSSACC_REPORT_ERROR_1 ("HssAccHdmaMgrFCRCreate - Invalid clock " + "speed (%d) in clkSpeed struct\n", + clkSpeed); + status = ICP_STATUS_INVALID_PARAM; + } + + if ( ICP_STATUS_SUCCESS == status ) + { + offset = portConfig->cfg.frm_offset; + if (ICP_HSSACC_HDMA_TX_REG_TYPE == type) + { + if (ICP_HSSACC_DATA_RATE_EQUALS_CLK_RATE == + portConfig->addCfg.dataRate) + { + offset += + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_TX_ADD_CLK_RATE; + } + else if (ICP_HSSACC_DATA_RATE_HALF_CLK_RATE == + portConfig->addCfg.dataRate) + { + offset += + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_TX_ADD_HALF_CLK_RATE; + } + /* + It is the modulus of the frame size that the frame pulse + delineates, which is expected to fit into the offset bits + of the FCR + */ + offset %= offsetMaxVal; + + /* With FBit Enabled, offset values of 0-7 are illegal */ + if (ICP_TRUE == portConfig->cfg.fBitEnable) + { + offset += ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_FBIT_ADDITION; + } + } + + } + + + if (ICP_STATUS_SUCCESS == status) + { + + if (ICP_TRUE == portConfig->cfg.fBitEnable) + { + fBitEnable = 1; + } + + *fcr = 0; + /* create the HSS co-proc 32bit register format */ + *fcr = + (fBitEnable << ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FBIT_OFFSET) | + (size << ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_OFFSET) | + (mvipSwitch << ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_OFFSET) | + (portConfig->cfg.interleaving << + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_INT_OFFSET) | + (offset << ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_OFFSET); + + if (ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_ON == mvipSwitch) + { + *fcr |= mvipSetting << + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_OFFSET; + } + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccHdmaMgrFCRCreate - " + "FCR = 0x%08X\n", *fcr); + +#ifdef SW_SWAPPING + *fcr = IX_OSAL_SWAP_BE_SHARED_LONG(*fcr); +#endif + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccHdmaMgrFCRCreate\n"); + return status; +} + + + +/** + * Function definition: HssAccHdmaMgrICRCreate + */ +void +HssAccHdmaMgrICRCreate (icp_hssacc_hdma_reg_trans_t type, + unsigned hssPortId, + uint32_t *icr) +{ + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccHdmaMgrICRCreate\n"); + + *icr = + (ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_PID_SHIFT << + ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PID_OFFSET) | + (tdmPbaAddresses[type][hssPortId] << + ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PBA_OFFSET); + +#ifdef IXP23XX + *icr |= + (ICP_HSSACC_TDM_IO_UNIT_HSS_PING_PONG_ENABLED << + ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PINGPONG_OFFSET) | + (ICP_HSSACC_TDM_IO_UNIT_HSS_VCH_ENABLED << + ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_VOICE_CHANNELISATION_OFFSET); +#endif + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccHdmaMgrICRCreate - ICR = 0x%08X\n", + *icr); + +#ifdef SW_SWAPPING + *icr = IX_OSAL_SWAP_BE_SHARED_LONG(*icr); +#endif + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccHdmaMgrICRCreate\n"); +} + + +/** + * Function definition: HssAccHdmaMgrClkCRCreate + */ +void +HssAccHdmaMgrClkCRCreate (icp_hssacc_clk_speed_t clkSpeed, + uint32_t *clkCR) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccHdmaMgrClkCRCreate\n"); + *clkCR = + (hssAccHdmaSysClk[clkSpeed].main << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CLKCR_MAIN_OFFSET) | + (hssAccHdmaSysClk[clkSpeed].num << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CLKCR_NUM_OFFSET) | + (hssAccHdmaSysClk[clkSpeed].denom << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CLKCR_DENOM_OFFSET); + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccHdmaMgrClkCRCreate - CLKCR = 0x%08X\n", + *clkCR); + +#ifdef SW_SWAPPING + *clkCR = IX_OSAL_SWAP_BE_SHARED_LONG(*clkCR); +#endif + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccHdmaMgrClkCRCreate\n"); +} + + +#ifdef IXP23XX +/** + * Function definition: HssAccHdmaMgrVCRCreate + */ +void +HssAccHdmaMgrVCRCreate (uint32_t *vcr) +{ + uint8_t voiceOffset = 0; + uint8_t lineIndex = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccHdmaMgrVCRCreate\n"); + + for(lineIndex = 0; + lineIndex < ICP_HSSACC_MAX_TDM_LINES_PER_PORT; + lineIndex ++) + { + if(lineIndex != 0 ) + { + (*vcr) |= + (voiceOffset << + ((lineIndex - 1) * + ICP_HSSACC_TDM_IO_UNIT_HDMA_VCR_FRAME_BASE_OFFSET)); + } + voiceOffset += ICP_HSSACC_TDM_IO_UNIT_HSS_SUB_FRAME_DELTA_OFFSET; + + } + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccHdmaMgrVCRCreate VCR = 0x%08X\n", + *vcr); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccHdmaMgrVCRCreate\n"); +} +#endif + + +/** + * Function definition: HssAccHdmaMgrCWRCreate + */ +void +HssAccHdmaMgrCWRCreate (icp_hssacc_clk_speed_t clkSpeed, + uint32_t *cwr) +{ + uint8_t timeslotsOnLastLine = 0; + uint8_t numOfActiveLines = 0; + uint32_t cwLocation = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccHdmaMgrCWRCreate\n"); + switch (clkSpeed) + { + case ICP_HSSACC_CLK_SPEED_1544KHZ: + timeslotsOnLastLine = ICP_HSSACC_TIMESLOTS_PER_T1_LINE; + numOfActiveLines = 1; + break; + case ICP_HSSACC_CLK_SPEED_2048KHZ: + timeslotsOnLastLine = ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + numOfActiveLines = 1; + break; + case ICP_HSSACC_CLK_SPEED_8192KHZ: + timeslotsOnLastLine = ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + numOfActiveLines = ICP_HSSACC_MAX_TDM_LINES_PER_PORT; + break; + default: + /* Code is not reachable under normal operation */ + ICP_HSSACC_REPORT_ERROR ("HssAccHdmaMgrCWRCreate - invalid" + " clock speed\n"); + return; + } + + + *cwr = /* first, shift in the enabling of the CW conditions */ + (ICP_HSSACC_TDM_IO_UNIT_HSS_TX_CW1_ENABLED << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW1_ENABLE_OFFSET) | + (ICP_HSSACC_TDM_IO_UNIT_HSS_TX_CW2_DISABLED << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW2_ENABLE_OFFSET) | + (ICP_HSSACC_TDM_IO_UNIT_HSS_RX_CW1_ENABLED << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW1_ENABLE_OFFSET) | + (ICP_HSSACC_TDM_IO_UNIT_HSS_RX_CW2_DISABLED << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW2_ENABLE_OFFSET) ; + + /* Calculate the location where the TDM I/O Unit is to be woken up, + it is at the last timeslot used on the last active line (timeslot + location start from 0) */ + cwLocation = (timeslotsOnLastLine - 1) + + ((numOfActiveLines - 1) * ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE); + /* Now shift in the addresses of the CW offsets */ + *cwr |= + (cwLocation << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW1_ADDRESS_OFFSET) | + (cwLocation << + ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW1_ADDRESS_OFFSET); + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccHdmaMgrCWRCreate CWR = 0x%08X\n", + *cwr); + +#ifdef SW_SWAPPING + *cwr = IX_OSAL_SWAP_BE_SHARED_LONG(*cwr); +#endif + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccHdmaMgrCWRCreate\n"); +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_queues_config.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_queues_config.c new file mode 100644 index 0000000..93766d5 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_queues_config.c @@ -0,0 +1,1501 @@ +/****************************************************************************** + * @file icp_hssacc_queues_config.c + * + * @description Contents of this file provide the implementation of the + * Tx and Rx Queues Configuration 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 "IxOsal.h" + +#include "IxQMgr.h" +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_rx_datapath.h" +#include "icp_hssacc_queues_config.h" +#include "icp_hssacc_address_translate.h" + +/* + * ---------------------------------------------------------------------------- + * Macros + * ---------------------------------------------------------------------------- + */ + +/* + * Macros that are used to distinguish between the voice and HDLC callback + * routines. The same macros are used for both the Rx queues and the Rx free + * queues. + */ +#define ICP_HSSACC_VOICE_RX_QMGR_CB_ID (0) +#define ICP_HSSACC_HDLC_RX_QMGR_CB_ID (1) + + + +#define ICP_HSSACC_CACHE_MASK (IX_OSAL_CACHE_LINE_SIZE-1) + +#define ICP_HSSACC_Q_NAME_SIZE 16 +#define ICP_HSSACC_Q_TYPE_NAME_SIZE 12 + + + +/* Defines Virtual and Physical values for the same memory block */ +typedef struct icp_hssacc_mem_base_addr_s +{ + void * virt; + uint32_t physOffset; +} icp_hssacc_mem_base_addr_t; + +/* + * ---------------------------------------------------------------------------- + * Static variable declarations + * ---------------------------------------------------------------------------- + */ +/* Flag used to test whether the queues have been initialised or not. */ +TDM_PRIVATE icp_boolean_t queuesConfigured = FALSE; + + +/* + * Holds the address of the memory allocated for the queue counters. + */ +TDM_PRIVATE icp_hssacc_mem_base_addr_t readCountersBaseAddress = + { + NULL, 0 + }; + +TDM_PRIVATE icp_hssacc_mem_base_addr_t writeCountersBaseAddress = + { + NULL, 0 + }; + +/* + * the virtual Addresses of each block that will have its physical + * address sent to the TDM I/O Unit + */ +/* Block containing the Tx Queues for ALL channels */ +TDM_PRIVATE icp_hssacc_mem_base_addr_t +txQsAddrArray[ICP_HSSACC_MAX_NUM_CHANNELS]; + +/* Block with Rx and RxFree for HDLC */ +TDM_PRIVATE icp_hssacc_mem_base_addr_t rxHdlcQsBlockAddr = + { + NULL, 0 + }; +/* Block with Rx and RxFree for VOICE */ +TDM_PRIVATE icp_hssacc_mem_base_addr_t rxVoiceQsBlockAddr = + { + NULL, 0 + }; + +/* Stores the list of Queue IDs as provided by the QMgr + this will be used to access the queues later. + we have 1 queue for each channel on Tx and 2 queues on Rx per + service supported */ +TDM_PRIVATE IxQMgrQId +hssAccQueueIds[ICP_HSSACC_MAX_NUM_CHANNELS + ICP_HSSACC_NUM_RECEIVE_QS]; + + +TDM_PRIVATE icp_hssacc_queues_config_stats_t hssAccQueuesCfgStats; + +/* + * ---------------------------------------------------------------------------- + * Static function declarations + * ---------------------------------------------------------------------------- + */ +TDM_PRIVATE void +HssAccQueueMemoryAlloc(icp_hssacc_mem_base_addr_t * txQsMemBaseArray, + icp_hssacc_mem_base_addr_t * pRxHdlcQsMemBase, + icp_hssacc_mem_base_addr_t * pRxVoiceQsMemBase, + icp_hssacc_mem_base_addr_t * pReadCounterMemBase, + icp_hssacc_mem_base_addr_t * pWriteCounterMemBase); + +TDM_PRIVATE icp_status_t +HssAccQueuesConfig(void); + +TDM_PRIVATE icp_status_t +HssAccQueueConfigMsgSubmit(uint32_t qBasePhysOffset, + uint32_t qDepth, + uint8_t msgId, + uint8_t msgRespId, + icp_hssacc_msg_with_resp_stats_t * stat); + +TDM_PRIVATE icp_status_t +HssAccTxQueuesConfigMsgsSubmit(icp_hssacc_mem_base_addr_t * qTxQBaseAddresses, + icp_hssacc_msg_with_resp_stats_t * stat); + +TDM_PRIVATE icp_status_t +HssAccQueueCounterConfigMsgSubmit(uint32_t qCounterPhysOffset, + uint8_t msgId, + uint8_t msgRespId, + icp_hssacc_msg_with_resp_stats_t * stat); + +TDM_PRIVATE icp_status_t +HssAccTdmIOUnitQueuesConfig(void); + +TDM_PRIVATE icp_status_t +HssAccTdmIOUnitQueueCountersConfig(void); + + +/* + * ---------------------------------------------------------------------------- + * Public function definitions + * ---------------------------------------------------------------------------- + */ +/****************************************************************************** + * Abstract: + * Allocates memory for all of the queues shared between the access layer + * and the TDM I/O unit. Also allocates memory for the head and tail + * counters for each queue. + * Verifies that the memory allocated is aligned on a cache line boundary. + * Registers each queue with QMgr and configures the queue watermark, etc. + * Submits the queue details to the TDM I/O unit. + * + * + *****************************************************************************/ +icp_status_t +HssAccQueuesInit(void) +{ + unsigned channel = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccQueuesInit\n"); + + if (TRUE == queuesConfigured) + { + ICP_HSSACC_REPORT_ERROR ("HssAccQueuesInit - Queues already " + "configured\n"); + return ICP_STATUS_SUCCESS; + } + + /* Allocate a block of memory for the queues and the head & tail counters */ + HssAccQueueMemoryAlloc (txQsAddrArray, + &rxHdlcQsBlockAddr, + &rxVoiceQsBlockAddr, + &readCountersBaseAddress, + &writeCountersBaseAddress); + + /* Check if the memory was correctly allocated */ + for (channel = 0; channel < ICP_HSSACC_MAX_NUM_CHANNELS; channel++) + { + if (NULL == txQsAddrArray[channel].virt) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesInit - " + "Failed to allocate Tx queue memory" + " for channel %d\n", + channel); + status = ICP_STATUS_FAIL; + break; + } + } + + if ((NULL == rxHdlcQsBlockAddr.virt) || + (NULL == rxVoiceQsBlockAddr.virt)) + { + ICP_HSSACC_REPORT_ERROR ("HssAccQueuesInit - " + "Failed to allocate Rx queues memory\n"); + + status = ICP_STATUS_FAIL; + } + + if ((NULL == readCountersBaseAddress.virt) || + (NULL == writeCountersBaseAddress.virt)) + { + ICP_HSSACC_REPORT_ERROR ("HssAccQueuesInit - " + "Failed to allocate queue counter memory\n"); + + status = ICP_STATUS_FAIL; + } + + if (status == ICP_STATUS_SUCCESS) + { + /* Allocated memory must start on a cache boundary */ + for (channel = 0; + channel < ICP_HSSACC_MAX_NUM_CHANNELS; + channel ++) + { + if ((((uint32_t)txQsAddrArray[channel].virt & + ICP_HSSACC_CACHE_MASK) != 0)) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesInit - " + "Allocated Tx queue memory" + " for channel %d is NOT on" + " a cache line boundary\n", + channel); + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "\tTx queue " + "base memory 0x%08X\n\t", + (uint32_t)txQsAddrArray[channel].virt); + + status = ICP_STATUS_RESOURCE; + break; + } + } + + if ((((uint32_t)rxHdlcQsBlockAddr.virt & ICP_HSSACC_CACHE_MASK) != 0) || + (((uint32_t)rxVoiceQsBlockAddr.virt & ICP_HSSACC_CACHE_MASK) != 0) || + (((uint32_t)readCountersBaseAddress.virt & + ICP_HSSACC_CACHE_MASK) != 0) || + (((uint32_t)writeCountersBaseAddress.virt & + ICP_HSSACC_CACHE_MASK) != 0) ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccQueuesInit - Allocated Memory " + "must start on a cache line boundary\n"); + + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "\tqueue " + "read counter memory 0x%x\n\t" + "write counter memory 0x%x\n\t", + (uint32_t)readCountersBaseAddress.virt, + (uint32_t)writeCountersBaseAddress.virt); + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "\tRx Hdlc queue memory 0x%x and Rx " + "Voice queue memory 0x%x\n\t ", + (uint32_t)rxHdlcQsBlockAddr.virt, + (uint32_t)rxVoiceQsBlockAddr.virt); + + status = ICP_STATUS_RESOURCE; + } + } + + if (status == ICP_STATUS_SUCCESS) + { + /* + * Carve up the memory between the queues and submit the queue + * configuration (for each queue) to the QMgr. + */ + status = HssAccQueuesConfig (); + + } + if (ICP_STATUS_SUCCESS == status) + { + /* + * Now that the Qmgr queues have been initialised, inform the + * TDM I/O Unit of the base address and size of each of the queues. + */ + status = HssAccTdmIOUnitQueuesConfig (); + } + if (ICP_STATUS_SUCCESS == status) + { + /* + * Now that the Qmgr queues have been initialised, and the queue base + * addresses submitted to the TDM I/O unit, submit the base address + * of each of the counters to TDM I/O unit. + */ + status = HssAccTdmIOUnitQueueCountersConfig (); + } + + /* This statement verifies that all queue initialisation steps succeeded */ + if (ICP_STATUS_SUCCESS == status) + { + /* all queues initialised and configured */ + queuesConfigured = TRUE; + } + else + { + ICP_HSSACC_REPORT_ERROR( "HssAccQueuesInit - Cleanup\n"); + HssAccQueuesShutdown(); + } + + /* Reset the Stats */ + HssAccQueuesConfigStatsReset(); + + ICP_HSSACC_TRACE_0( ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccQueuesInit\n" ); + + return status; +} + + +/***************************************************************************** + * Abstract: + * Frees the memory allocated for the queues and the queue counters, and + * resets the queue configuration flag. + * + * + *****************************************************************************/ +icp_status_t +HssAccQueuesShutdown(void) +{ + unsigned channel = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0(ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccQueuesShutdown\n" ); + + + /* Best Effort cleanup, we dont care about success or failure + at this stage. we still try to cleanup everything. */ + status = ixQMgrUnconfigGroup(IX_QMGR_DISPATCH_TX_HSS); + + status |= ixQMgrUnconfigGroup(IX_QMGR_DISPATCH_VOICE_RX_HSS); + + status |= ixQMgrUnconfigGroup(IX_QMGR_DISPATCH_HDLC_RX_HSS); + + /* Only Free the memory that was allocated */ + for (channel = 0; channel < ICP_HSSACC_MAX_NUM_CHANNELS; channel++) + { + if (NULL != txQsAddrArray[channel].virt) + { + /* Free the memory allocated for the queues */ + IX_OSAL_CACHE_DMA_FREE(txQsAddrArray[channel].virt); + txQsAddrArray[channel].virt = NULL; + + ICP_HSSACC_TRACE_1(ICP_HSSACC_DEBUG, + "HssAccQueuesShutdown - Free memory" + " for Tx Channel %d\n", + channel); + + } + } + + if (NULL != rxHdlcQsBlockAddr.virt) + { + IX_OSAL_CACHE_DMA_FREE (rxHdlcQsBlockAddr.virt); + rxHdlcQsBlockAddr.virt = NULL; + ICP_HSSACC_TRACE_0(ICP_HSSACC_DEBUG, + "HssAccQueuesShutdown - Free Rx Hdlc memory\n"); + + } + + if (NULL != rxVoiceQsBlockAddr.virt) + { + IX_OSAL_CACHE_DMA_FREE (rxVoiceQsBlockAddr.virt); + rxVoiceQsBlockAddr.virt = NULL; + ICP_HSSACC_TRACE_0(ICP_HSSACC_DEBUG, + "HssAccQueuesShutdown - Free Rx Voice memory\n"); + + } + + if (NULL != readCountersBaseAddress.virt) + { + /* Free the memory allocated for the queue counters */ + IX_OSAL_CACHE_DMA_FREE (readCountersBaseAddress.virt); + readCountersBaseAddress.virt = NULL; + ICP_HSSACC_TRACE_0(ICP_HSSACC_DEBUG, + "HssAccQueuesShutdown - Free Read Counter memory\n"); + + } + + + if (NULL != writeCountersBaseAddress.virt) + { + /* Free the memory allocated for the queue counters */ + IX_OSAL_CACHE_DMA_FREE (writeCountersBaseAddress.virt); + writeCountersBaseAddress.virt = NULL; + ICP_HSSACC_TRACE_0( ICP_HSSACC_DEBUG, + "HssAccQueuesShutdown - Free Write Counter memory\n"); + + } + + /* Reset the queue configuration flag */ + queuesConfigured = FALSE; + + + ICP_HSSACC_TRACE_0( ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccQueuesShutdown\n" ); + return status; +} + +/***************************************************************************** + * Abstract: + * Allocates memory for all of the queues shared between the access layer + * and the TDM I/O unit. Also allocates memory for the head and tail + * counters for each queue. + * The memory is allocated on a cache line boundary, and each queue is an + * integer multiple of the cache line size. This guarantees that each queue + * is cache-aligned. + * The counter memory is also allocated on a cache boundary, and each set + * of counters is cache-aligned. + * + *****************************************************************************/ +TDM_PRIVATE void +HssAccQueueMemoryAlloc(icp_hssacc_mem_base_addr_t * txQsMemBaseArray, + icp_hssacc_mem_base_addr_t * pRxHdlcQsMemBase, + icp_hssacc_mem_base_addr_t * pRxVoiceQsMemBase, + icp_hssacc_mem_base_addr_t * pReadCounterMemBase, + icp_hssacc_mem_base_addr_t * pWriteCounterMemBase) +{ + /* + * Malloc enough memory for the following queues: + * Voice RX free Q + * Voice RX Q + * HDLC RX free Q + * HDLC RX Q + * Max Num Chan TX Qs (1 per channel) + * And the Following Counters: + * Max Num Chan Tx Tail 8 bit ctrs (1 per chan) + * Max Num Chan Tx Head 8 bit ctrs (1 per chan) + * Voice Rx Free Head and Tail (32 bits each) + * HDLC Rx Free Head and Tail (32 bits each) + * Voice Rx Head and Tail (32 bits each) + * HDLC Rx Head and Tail (32 bits each) + */ + + + /* + * Note 1: the rx free Q and the rx Q must be contiguous in memory. + * Note 2: the rx free Q and the rx Q must have the same depth. + * Note 3: a TX queue for an HDLC channel may be deeper than a TX queue for + * a Voice channel. Thus, the default TX queue depth will be that of an + * HDLC channel. The watermark will be moved accordingly to accomodate + * both depths. + * Each queue should be aligned on a cache line boundary, and should be a + * multiple of the cache line size. + */ + + uint32_t bytesToAlloc = 0; + unsigned channel = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccQueueMemoryAlloc\n"); + + + /* Calculate the total amount of memory needed for each Tx queue */ + bytesToAlloc = ICP_HSSACC_TX_QUEUE_SIZE_IN_BYTES; + + for (channel = 0; channel < ICP_HSSACC_MAX_NUM_CHANNELS; channel++) + { + /* All queues must use memory that is aligned on a cache line boundary */ + txQsMemBaseArray[channel].virt = + HssAccDmaMemAllocate(bytesToAlloc, + &(txQsMemBaseArray[channel].physOffset)); + ICP_HSSACC_TRACE_4 (ICP_HSSACC_DEBUG, + "HssAccQueueMemoryAlloc - Allocated Tx Queue Mem from " + "0x%08X (phys 0x%08X) with Size %d bytes" + " for chan %d\n", + (uint32_t)(txQsMemBaseArray[channel].virt), + txQsMemBaseArray[channel].physOffset, + bytesToAlloc, + channel); + } + + /* Calculate the total amount of memory needed for Rx Hdlc queues */ + bytesToAlloc = ICP_HSSACC_HDLC_RX_QUEUE_SIZE_IN_BYTES + + ICP_HSSACC_HDLC_RX_FREE_QUEUE_SIZE_IN_BYTES; + + /* All queues must use memory that is aligned on a cache line boundary */ + pRxHdlcQsMemBase->virt = + HssAccDmaMemAllocate(bytesToAlloc, + &(pRxHdlcQsMemBase->physOffset)); + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccQueueMemoryAlloc - Allocated Rx Hdlc Queue Mem " + "from 0x%08X (phys 0x%08X) with Size %d bytes\n", + (uint32_t)pRxHdlcQsMemBase->virt, + pRxHdlcQsMemBase->physOffset, + bytesToAlloc); + + + /* Calculate the total amount of memory needed for the Rx Voice queues */ + bytesToAlloc = ICP_HSSACC_VOICE_RX_QUEUE_SIZE_IN_BYTES + + ICP_HSSACC_VOICE_RX_FREE_QUEUE_SIZE_IN_BYTES; + + /* All queues must use memory that is aligned on a cache line boundary */ + pRxVoiceQsMemBase->virt = + HssAccDmaMemAllocate(bytesToAlloc, + &(pRxVoiceQsMemBase->physOffset)); + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccQueueMemoryAlloc - Allocated Rx Voice Queue Mem " + "from 0x%08X (phys 0x%08X) with Size %d bytes\n", + (uint32_t)pRxVoiceQsMemBase->virt, + pRxVoiceQsMemBase->physOffset, + bytesToAlloc); + + /* + * Allocate memory in DRAM for the queue head & tail counters. + * The read (from the access layer perspective) counters need to be arranged + * as follows: + * "max num chans" bytes (packed) for the Tx tail counters. These + * "max num chans" bytes must be contiguous in memory. + * 4-byte Voice Rx free tail and 4-byte Rx head counters, which must be + * contiguous in memory and aligned on a cache line boundary. + * 4-byte HDLC Rx free tail and 4-byte Rx head counters, which must + * be contiguous in memory and aligned on a cache line boundary. + * + * The write counters need to be arranged as follows: + * "max num chans" bytes (packed) for the Tx head counters. + * 4-byte Voice Rx free head and 4-byte Rx tail counters, which must be + * contiguous in memory and aligned on a cache line boundary. + * 4-byte HDLC Rx free head and 4-byte Rx tail counters, which must + * be contiguous in memory and aligned on a cache line boundary. + * + */ + bytesToAlloc = sizeof(icp_hssacc_queue_reader_counters_t); + + pReadCounterMemBase->virt = + HssAccDmaMemAllocate(bytesToAlloc, + &(pReadCounterMemBase->physOffset)); + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccQueueMemoryAlloc - Allocated Read Counter Memory " + "from 0x%08X (phys 0x%08X) with Size %d bytes\n", + (uint32_t)pReadCounterMemBase->virt, + pReadCounterMemBase->physOffset, + bytesToAlloc); + + bytesToAlloc = sizeof(icp_hssacc_queue_write_counters_t); + + pWriteCounterMemBase->virt = + HssAccDmaMemAllocate(bytesToAlloc, + &(pWriteCounterMemBase->physOffset)); + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccQueueMemoryAlloc - Allocated Write Counter Memory " + "from 0x%08X (phys 0x%08X) with Size %d bytes\n", + (uint32_t)pWriteCounterMemBase->virt, + pWriteCounterMemBase->physOffset, + bytesToAlloc); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccQueueMemoryAlloc\n"); + return; +} + + +/***************************************************************************** + * Abstract: + * Divides the queue memory between each of the queues and does likewise + * with the queue counter memory. + * Registers each queue with the QMgr and configures each queue. + * Configures the address of the counters to flush and invalidate for each + * iteration of the dispatcher loop. The counters read by the access layer + * will be invalidated and the counters written by the access layer will be + * flushed. + * + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccQueuesConfig(void) +{ + uint32_t channel, qBaseOffset = 0; + IxQMgrQId qId = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_queue_write_counters_t *pWriteCounters = NULL; + icp_hssacc_queue_reader_counters_t *pReadCounters = NULL; + uint8_t *pTxQueueHead = NULL; + uint8_t *pTxQueueTail = NULL; + uint32_t *pRxQueueHead = NULL; + uint32_t *pRxQueueTail = NULL; + uint32_t invalidateAddress = 0; + uint32_t flushAddress = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccQueuesConfig\n "); + + /* Cast the counter structure to the memory allocated for the counters */ + pWriteCounters = + (icp_hssacc_queue_write_counters_t *)writeCountersBaseAddress.virt; + pReadCounters = + (icp_hssacc_queue_reader_counters_t *)readCountersBaseAddress.virt; + + invalidateAddress = (uint32_t)(pReadCounters->txTail); + flushAddress = (uint32_t)(pWriteCounters->txHead); + + /* + * This function sets the address of the counters to be + * flushed/invalidated each time the QMgrDispatcher runs. + * The QMgr dispatcher will only check the queues that have been + * registered with it. In this case only the Rx queues will be serviced + * by the dispatcher. + */ + + /* configure the address and size to be flushed/invalidated */ + if (ixQMgrGroupMemoryConfig (IX_QMGR_DISPATCH_TX_HSS, + (void *)flushAddress, + (void *)invalidateAddress, + sizeof(pReadCounters->txTail)) + != ICP_STATUS_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR("HssAccQueuesConfig - Failed Tx Queue group " + "configuration\n"); + return ICP_STATUS_FAIL; + } + + invalidateAddress = (uint32_t)&(pReadCounters->voiceRxCounters); + flushAddress = (uint32_t)&(pWriteCounters->voiceRxCounters); + + /* configure the address and size to be flushed/invalidated for + voice receive q's */ + if (ixQMgrGroupMemoryConfig (IX_QMGR_DISPATCH_VOICE_RX_HSS, + (void *)flushAddress, + (void *)invalidateAddress, + sizeof(pReadCounters->voiceRxCounters)) + != ICP_STATUS_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR("HssAccQueuesConfig - Failed Voice Rx " + "Queue group configuration\n"); + return ICP_STATUS_FAIL; + } + + /* + * Increment addresses by size of receive queue counter block + */ + invalidateAddress = (uint32_t)&(pReadCounters->hdlcRxCounters); + flushAddress = (uint32_t)&(pWriteCounters->hdlcRxCounters); + + /* configure the address and size to be flushed/invalidated for HDLC + receive q's */ + if (ixQMgrGroupMemoryConfig (IX_QMGR_DISPATCH_HDLC_RX_HSS, + (void *)flushAddress, + (void *)invalidateAddress, + sizeof(pReadCounters->hdlcRxCounters)) + != ICP_STATUS_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR("HssAccQueuesConfig - Failed HDLC Rx Queue group " + "configuration\n"); + return ICP_STATUS_FAIL; + } + + + /* + * The queues are allocated in memory in the following blocks: + * 1: "max num chans" Tx queues + * 2:Voice Rx Free queue + * Voice Rx queue + * 3:HDLC Rx Free queue + * HDLC Rx queue + * 4:Read Counters + * 5: Write Counters + */ + + /* + * Configure the Tx queues + */ + for (channel = 0; + channel < ICP_HSSACC_MAX_NUM_CHANNELS; + channel ++) + { + + char qName[ICP_HSSACC_Q_NAME_SIZE] = "HssAcc Tx Q "; + + /* Append the queue number to its string identifier */ + snprintf (&qName[ICP_HSSACC_Q_TYPE_NAME_SIZE], + ICP_HSSACC_Q_NAME_SIZE - ICP_HSSACC_Q_TYPE_NAME_SIZE, + "%u", channel); + + /* Set the address of the head and tail counters for this queue */ + pTxQueueHead = &(pWriteCounters->txHead[channel]); + pTxQueueTail = &(pReadCounters->txTail[channel]); + + status = + ixQMgrQConfig (qName, + &qId, + ICP_HSSACC_TX_QUEUE_DEPTH, + ICP_HSSACC_QUEUE_DESC_SIZE_IN_WORDS, + IX_QMGR_Q_COUNT_ENTRIES, + IX_QMGR_Q_ALIGN_BYTE, + IX_QMGR_DISPATCH_TX_HSS, + IX_QMGR_Q_SHADOW_TAIL_ONLY, + txQsAddrArray[channel].virt, + pTxQueueHead, + pTxQueueTail); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_2 ("HssAccQueuesConfig - Failed to configure " + "Tx Q %u. ixQMgrQConfig() returned %u\n", + channel, status); + return ICP_STATUS_FAIL; + } + + hssAccQueueIds[channel] = qId; + status = ixQMgrWatermarkSet (qId, ICP_HSSACC_TX_WATERMARK); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_2 ("HssAccQueuesConfig - Failed to set " + "watermark for Tx Q " + "%u. ixQMgrWatermarkSet() returned %u\n", + channel, status); + + return ICP_STATUS_FAIL; + } + } + /* + * The TDM I/O Unit expects the voice Rx & Rx free queues to be contiguous + * in memory, with the Rx free queue preceeding the Rx queue. However, the + * voice Rx queue should be serviced before the voice Rx free queue. + * The order in which a queue is registered with the dispatcher determines + * the order in which it will be serviced by the QMgr dispatcher. + * hence all Receive Queues are first allocated then registered. registration + * is done at a later stage. + */ + + /* + * Voice Rx free queue + */ + + pRxQueueHead = &(pWriteCounters->voiceRxCounters.rxFreeHead); + pRxQueueTail = &(pReadCounters->voiceRxCounters.rxFreeTail); + + status = ixQMgrQConfig ("Voice Rx Free Q", + &qId, + ICP_HSSACC_VOICE_RX_FREE_QUEUE_DEPTH, + ICP_HSSACC_QUEUE_DESC_SIZE_IN_WORDS, + IX_QMGR_Q_COUNT_ENTRIES, + IX_QMGR_Q_ALIGN_WORD, + IX_QMGR_DISPATCH_VOICE_RX_HSS, + IX_QMGR_Q_NO_SHADOWING, + (void*)rxVoiceQsBlockAddr.virt, + pRxQueueHead, + pRxQueueTail); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to configure " + "voice Rx free queue." + " ixQMgrQConfig() returned %u\n", status); + return ICP_STATUS_FAIL; + } + hssAccQueueIds[ICP_HSSACC_VOICE_RX_FREE_Q] = qId; + + /* + * Voice Rx queue + */ + qBaseOffset = ICP_HSSACC_VOICE_RX_FREE_QUEUE_SIZE_IN_BYTES; + + pRxQueueHead = &(pReadCounters->voiceRxCounters.rxHead); + pRxQueueTail = &(pWriteCounters->voiceRxCounters.rxTail); + + status = + ixQMgrQConfig ("Voice Rx Q", + &qId, + ICP_HSSACC_VOICE_RX_QUEUE_DEPTH, + ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_WORDS, + IX_QMGR_Q_COUNT_ENTRIES, + IX_QMGR_Q_ALIGN_WORD, + IX_QMGR_DISPATCH_VOICE_RX_HSS, + IX_QMGR_Q_NO_SHADOWING, + (void*)(qBaseOffset + (uint32_t)rxVoiceQsBlockAddr.virt), + pRxQueueHead, + pRxQueueTail); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to configure " + "voice Rx queue." + " ixQMgrQConfig() returned %u\n", + status); + return ICP_STATUS_FAIL; + } + + hssAccQueueIds[ICP_HSSACC_VOICE_RX_Q] = qId; + status = ixQMgrWatermarkSet (qId, ICP_HSSACC_VOICE_RX_WATERMARK); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to set watermark " + "for voice Rx queue." + " ixQMgrWatermarkSet() returned %u\n", + status); + return ICP_STATUS_FAIL; + } + + /* Register the callback for this Q */ + status = ixQMgrNotificationCallbackSet (qId, + HssAccRxQServiceCallback, + ICP_HSSACC_VOICE_RX_QMGR_CB_ID); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to set " + "Notification callback function for voice " + "Rx Q. ixQMgrWatermarkSet() returned %u\n", + status); + return ICP_STATUS_FAIL; + } + + /* + * HDLC Rx free queue + */ + + pRxQueueHead = &(pWriteCounters->hdlcRxCounters.rxFreeHead); + pRxQueueTail = &(pReadCounters->hdlcRxCounters.rxFreeTail); + + status = ixQMgrQConfig ("HDLC Rx Free Q", + &qId, + ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH, + ICP_HSSACC_QUEUE_DESC_SIZE_IN_WORDS, + IX_QMGR_Q_COUNT_ENTRIES, + IX_QMGR_Q_ALIGN_WORD, + IX_QMGR_DISPATCH_HDLC_RX_HSS, + IX_QMGR_Q_NO_SHADOWING, + (void*)rxHdlcQsBlockAddr.virt, + pRxQueueHead, + pRxQueueTail); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to configure " + "HDLC Rx free queue." + " ixQMgrQConfig() returned %u\n", status); + return ICP_STATUS_FAIL; + } + + hssAccQueueIds[ICP_HSSACC_HDLC_RX_FREE_Q] = qId; + + + /* + * HDLC Rx queue + */ + qBaseOffset = ICP_HSSACC_HDLC_RX_FREE_QUEUE_SIZE_IN_BYTES; + + pRxQueueHead = &(pReadCounters->hdlcRxCounters.rxHead); + pRxQueueTail = &(pWriteCounters->hdlcRxCounters.rxTail); + + status = + ixQMgrQConfig ("HDLC Rx Q", + &qId, + ICP_HSSACC_HDLC_RX_QUEUE_DEPTH, + ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_WORDS, + IX_QMGR_Q_COUNT_ENTRIES, + IX_QMGR_Q_ALIGN_WORD, + IX_QMGR_DISPATCH_HDLC_RX_HSS, + IX_QMGR_Q_NO_SHADOWING, + (void*)(qBaseOffset + (uint32_t)rxHdlcQsBlockAddr.virt), + pRxQueueHead, + pRxQueueTail); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to configure " + "HDLC Rx queue." + " ixQMgrQConfig() returned %u\n", + status); + return ICP_STATUS_FAIL; + } + + hssAccQueueIds[ICP_HSSACC_HDLC_RX_Q] = qId; + status = ixQMgrWatermarkSet (qId, ICP_HSSACC_HDLC_RX_WATERMARK); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to set watermark " + "for HDLC Rx queue." + " ixQMgrWatermarkSet() returned %u\n", + status); + return ICP_STATUS_FAIL; + } + + + /* Register the callback for this Q */ + status = ixQMgrNotificationCallbackSet (qId, + HssAccRxQServiceCallback, + ICP_HSSACC_HDLC_RX_QMGR_CB_ID); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccQueuesConfig - Failed to set " + "Notification callback function for HDLC " + "Rx Q. ixQMgrWatermarkSet() returned %u\n", + status); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccQueuesConfig\n"); + + return status; +} + + + +/****************************************************************************** + * Abstract: + * Enables Notification on the Receive Queues. order of is critical here + * as it will determine the order of servicing in the Queue Manager Dispatcher. + * + *****************************************************************************/ +icp_status_t +HssAccRxQueuesNotificationEnable(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxQueuesNotificationEnable\n"); + + status = ixQMgrNotificationEnable (hssAccQueueIds[ICP_HSSACC_VOICE_RX_Q], + IX_QMGR_Q_SOURCE_ID_NOT_E); + if (ICP_STATUS_SUCCESS == status) + { + status = ixQMgrNotificationEnable (hssAccQueueIds[ICP_HSSACC_HDLC_RX_Q], + IX_QMGR_Q_SOURCE_ID_NOT_E); + } + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxQueuesNotificationEnable - " + "Failed to enable notifications\n"); + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxQueuesNotificationEnable\n"); + return status; +} + + + +/****************************************************************************** + * Abstract: + * Configures all the receive queues used by the TDM I/O unit, + * i.e. it converts the virtual base address of the queue into a + * physical address and passes this address down to the TDM I/O unit. + * It also configures the depth of the queue. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccQueueConfigMsgSubmit(uint32_t qBasePhysOffset, + uint32_t qDepth, + uint8_t msgId, + uint8_t msgRespId, + icp_hssacc_msg_with_resp_stats_t * stat) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint8_t qSizeByte1, qSizeByte0 = 0; + + ICP_HSSACC_TRACE_4 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccQueueConfigMsgSubmit - Offset=0x%08X " + "qDepth=0x%04X msg=0x%02X msgResp=0x%02X\n", + (uint32_t)qBasePhysOffset, qDepth, msgId, msgRespId); + + qSizeByte1 = (qDepth&ICP_HSSACC_TDM_IO_UNIT_BYTE2_MASK) >> + ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET; + + qSizeByte0 = qDepth&ICP_HSSACC_TDM_IO_UNIT_BYTE3_MASK; + + /* Construct the message to configure the queue */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate (msgId, + 0, + qSizeByte1, + qSizeByte0, + qBasePhysOffset, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv(message, + msgRespId, + stat, + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccQueueConfigMsgSubmit\n"); + + return status; +} + + +/****************************************************************************** + * Abstract: + * Configures all the base addresses for the Tx Queues. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccTxQueuesConfigMsgsSubmit(icp_hssacc_mem_base_addr_t * pTxQBaseAddresses, + icp_hssacc_msg_with_resp_stats_t * stat) +{ + + unsigned channel = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxQueuesConfigMsgsSubmit\n"); + + for (channel = 0; channel < ICP_HSSACC_MAX_NUM_CHANNELS; channel++) + { + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "HssAccTxQueuesConfigMsgsSubmit - configuring " + "channel %d with Offset=0x%08X\n", + channel, + pTxQBaseAddresses[channel].physOffset); + + /* Construct the message to configure the queue */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_TX_CHAN_Q_ADDR_CFG, + channel, + 0, + 0, + pTxQBaseAddresses[channel].physOffset, + &message); + + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_TX_CHAN_Q_ADDR_CFG_RESPONSE, + stat, + NULL); + + if (ICP_STATUS_SUCCESS != status) + { + /* Error will reported in calling function */ + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccTxQueuesConfigMsgsSubmit - Failed " + "configuring channel %d\n", + channel); + break; + } + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxQueuesConfigMsgsSubmit\n"); + + return status; + +} + + +/****************************************************************************** + * Abstract: + * Converts the virtual address of the queue counter into a physical + * address and submits this address to the TDM I/O unit. + * + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccQueueCounterConfigMsgSubmit(uint32_t qCounterPhysOffset, + uint8_t msgId, + uint8_t msgRespId, + icp_hssacc_msg_with_resp_stats_t * stat) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + + ICP_HSSACC_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccQueueCounterConfigMsgSubmit - " + "msg 0x%02X offset 0x%08X\n", + msgId, qCounterPhysOffset); + + + /* Construct the message to configure the queue */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate (msgId, + 0, + 0, + 0, + qCounterPhysOffset, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv(message, + msgRespId, + stat, + NULL); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccQueueCounterConfigMsgSubmit\n"); + + return status; +} + +/***************************************************************************** + * Abstract: + * Configures all of the queues used by the TDM I/O unit, i.e. it + * passes the phys address down to the TDM I/O unit. It also configures the + * depth of each queue. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccTdmIOUnitQueuesConfig (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t qDepth = 0; + + ICP_HSSACC_TRACE_0(ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOUnitQueuesConfig\n"); + + /* + * Configure the address and depth of all of the queues shared between + * the HssAcc I/O library and the TDM I/O unit. + */ + + /* configure Tx queues */ + qDepth = ((ICP_HSSACC_HDLC_TX_QUEUE_DEPTH_POW_2) << + ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET) + | (ICP_HSSACC_VOICE_TX_QUEUE_DEPTH_POW_2); + + status = + HssAccQueueConfigMsgSubmit (0, + qDepth, + ICP_HSSACC_TDM_IO_UNIT_TX_Q_CFG, + ICP_HSSACC_TDM_IO_UNIT_TX_Q_CFG_RESPONSE, + &(hssAccQueuesCfgStats.txQCfg)); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit Tx queue Depths " + "status = %u\n", + status); + } + + if (ICP_STATUS_SUCCESS == status) + { + status = + HssAccTxQueuesConfigMsgsSubmit(txQsAddrArray, + &(hssAccQueuesCfgStats.txChanQAddrCfg)); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit Tx queue Base " + "Addresses status = %u\n", + status); + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* Configure the base address of the Voice Rx free & Rx queues */ + status = + HssAccQueueConfigMsgSubmit( + rxVoiceQsBlockAddr.physOffset, + ICP_HSSACC_VOICE_RX_QUEUE_DEPTH, + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_CFG, + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_CFG_RESPONSE, + &(hssAccQueuesCfgStats.voiceRxQCfg)); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit voice Rx queue base " + "address. status = %u\n", status); + } + } + + /* Configure the base address of the HDLC Rx free & Rx queues */ + if (ICP_STATUS_SUCCESS == status) + { + status = + HssAccQueueConfigMsgSubmit( + rxHdlcQsBlockAddr.physOffset, + ICP_HSSACC_HDLC_RX_QUEUE_DEPTH, + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_CFG, + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_CFG_RESPONSE, + &(hssAccQueuesCfgStats.hdlcRxQCfg)); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit HDLC Rx queue base " + "address. status = %u\n", status); + } + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOUnitQueuesConfig\n"); + return status; +} + + +/***************************************************************************** + * Abstract: + * Submits the base address of each of the queue counters to the TDM I/O + * unit. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccTdmIOUnitQueueCountersConfig (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_queue_write_counters_t *pWriteCounters = NULL; + icp_hssacc_queue_reader_counters_t *pReadCounters = NULL; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOUnitQueueCountersConfig\n"); + + /* + * Map the counter struct to the address of the memory allocated for the + * counters. + */ + pWriteCounters = + (icp_hssacc_queue_write_counters_t *)writeCountersBaseAddress.physOffset; + pReadCounters = + (icp_hssacc_queue_reader_counters_t *)readCountersBaseAddress.physOffset; + + /* Configure the address of the TX head counters */ + status = + HssAccQueueCounterConfigMsgSubmit ( + (uint32_t)&(pReadCounters->txTail), + ICP_HSSACC_TDM_IO_UNIT_TX_Q_TAIL_CTR_CFG, + ICP_HSSACC_TDM_IO_UNIT_TX_Q_TAIL_CTR_CFG_RESPONSE, + &(hssAccQueuesCfgStats.txQTailCfg)); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit Tx Tail counter base " + "address. status = %u\n", status); + } + else + { + + /* Configure the address of the TX tail counters */ + status = + HssAccQueueCounterConfigMsgSubmit ( + (uint32_t)&(pWriteCounters->txHead), + ICP_HSSACC_TDM_IO_UNIT_TX_Q_HEAD_CTR_CFG, + ICP_HSSACC_TDM_IO_UNIT_TX_Q_HEAD_CTR_CFG_RESPONSE, + &(hssAccQueuesCfgStats.txQHeadCfg)); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit Tx Head counter base " + "address. status = %u\n", status); + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* + * Configure the address of the Voice Rx Free head counter and the voice + * Rx tail counter. + */ + status = + HssAccQueueCounterConfigMsgSubmit ( + (uint32_t)&(pWriteCounters->voiceRxCounters), + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_READER_CFG, + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_READER_CFG_RESPONSE, + &(hssAccQueuesCfgStats.voiceRxQReaderCfg)); + + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit HssAcc Voice Rx Write " + "counters base address. status = %u\n", + status); + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* + * Configure the address of the Voice Rx Free tail counter and the voice + * Rx head counter. + */ + status = + HssAccQueueCounterConfigMsgSubmit ( + (uint32_t)&(pReadCounters->voiceRxCounters), + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_WRITER_CFG, + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_WRITER_CFG_RESPONSE, + &(hssAccQueuesCfgStats.voiceRxQWriterCfg)); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit HssAcc Voice Rx read " + "counters base address. status = %u\n", + status); + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* + * Configure the address of the HDLC Rx Free head counter and the HDLC + * Rx tail counter. + */ + status = + HssAccQueueCounterConfigMsgSubmit ( + (uint32_t)&(pWriteCounters->hdlcRxCounters), + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_READER_CFG, + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_READER_CFG_RESPONSE, + &(hssAccQueuesCfgStats.hdlcRxQReaderCfg)); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit HssAcc HDLC Rx write " + "counters base address. status = %u\n", + status); + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* + * Configure the address of the HDLC Rx Free tail counter and the HDLC + * Rx head counter. + */ + status = + HssAccQueueCounterConfigMsgSubmit ( + (uint32_t)&(pReadCounters->hdlcRxCounters), + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_WRITER_CFG, + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_WRITER_CFG_RESPONSE, + &(hssAccQueuesCfgStats.hdlcRxQWriterCfg)); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("Failed to submit HssAcc HDLC Rx read " + "counters base address. status = %u\n", + status); + } + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOUnitQueueCountersConfig\n"); + + return status; +} + +/***************************************************************************** + * Abstract: + * Updates the TDM I/O Unit with a new Q depth for a specific Q. + * + *****************************************************************************/ +icp_status_t +HssAccQueueConfigQSizeUpdate(uint32_t channelId, + icp_hssacc_channel_type_t type) +{ + IxQMgrQSize depth = 0; + + if (ICP_HSSACC_CHAN_TYPE_VOICE == type) + { + depth = ICP_HSSACC_VOICE_TX_QUEUE_DEPTH; + } + else + { + depth = ICP_HSSACC_HDLC_TX_QUEUE_DEPTH; + } + return ixQMgrQSizeReconfig (channelId, depth); +} + + +/***************************************************************************** + * Abstract: + * Retrieves the QMgr Q Id for a specific HSS Acc Queue. + * + *****************************************************************************/ +IxQMgrQId +HssAccQueueIdGet (uint32_t qIndexId) +{ + return hssAccQueueIds[qIndexId]; +} + + +/***************************************************************************** + * Abstract: + * Reset the Stats for this module. + * + *****************************************************************************/ +void +HssAccQueuesConfigStatsReset (void) +{ + memset (&hssAccQueuesCfgStats, 0, sizeof(icp_hssacc_queues_config_stats_t)); +} + + + +/***************************************************************************** + * Abstract: + * Displays stats for this module. + * + *****************************************************************************/ +void +HssAccQueuesConfigStatsShow (void) +{ + unsigned channel = 0; + if (TRUE == queuesConfigured) + { + for (channel = 0; channel < ICP_HSSACC_MAX_NUM_CHANNELS; channel++) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Tx Queue %d Base Address Location: 0x%08X\n", + channel, + (uint32_t)txQsAddrArray[channel].virt, + 0, 0, + 0, 0); + } + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Rx Hdlc Queues Base Address Location: 0x%08X\n" + "Rx Voice Queues Base Address Location: 0x%08X\n" + "Queue Read Counter Address Location: 0x%08X\n" + "Queue Write Counter Address Location: 0x%08X\n", + (uint32_t)rxHdlcQsBlockAddr.virt, + (uint32_t)rxVoiceQsBlockAddr.virt, + (uint32_t)readCountersBaseAddress.virt, + (uint32_t)writeCountersBaseAddress.virt, + 0, 0); + + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nQueue Configuration Statistics:\n" + "TX Queue Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.txQCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nHDLC RX Queue Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.hdlcRxQCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nVoice RX Queue Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.voiceRxQCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTX Q Head Counters Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.txQHeadCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTX Q Tail Counters Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.txQTailCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nVoice Rx Q Reader Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.voiceRxQReaderCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nVoice Rx Q Writer Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.voiceRxQWriterCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nHDLC Rx Q Reader Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.hdlcRxQReaderCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nHDLC Rx Q Writer Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccQueuesCfgStats.hdlcRxQWriterCfg); + } + +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_rx_datapath.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_rx_datapath.c new file mode 100644 index 0000000..94bba23 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_rx_datapath.c @@ -0,0 +1,2014 @@ +/****************************************************************************** + * @file icp_hssacc_rx_datapath.c + * + * @description Contents of this file provide the Receive Datapath + * functionality for the HSS Access component + * + * @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 "IxOsal.h" + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_queues_config.h" +#include "icp_hssacc_channel_config.h" +#include "icp_hssacc_rings.h" +#include "icp_hssacc_tdm_io_queue_entry.h" +#include "icp_hssacc_address_translate.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_rx_datapath.h" + +#include "IxQMgr.h" + + +/* Mutex which controls access to receive datapath service functions */ +TDM_PRIVATE IxOsalMutex hssAccRxServiceMutex[ICP_HSSACC_CHAN_TYPE_DELIMITER]; +TDM_PRIVATE +IxOsalMutex hssAccRxFreeQServiceMutex[ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +/* Data for the descriptor to mbuf mapping queue */ +TDM_PRIVATE uint32_t +HssAccRxDpDescPtrRingData[ICP_HSSACC_MAX_NUM_CHANNELS] +[ICP_HSSACC_RX_DP_CHAN_DESC_PTR_RING_SZ]; + +TDM_PRIVATE icp_hssacc_dataplane_ring_t +HssAccRxDpDescRing[ICP_HSSACC_MAX_NUM_CHANNELS]; + +/* Data for the descriptor to mbuf mapping queue */ +TDM_PRIVATE uint32_t +HssAccRxDpFreeQRingData[ICP_HSSACC_CHAN_TYPE_DELIMITER] +[ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH]; + +TDM_PRIVATE icp_hssacc_dataplane_ring_t +HssAccRxDpFreeQRing[ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +TDM_PRIVATE icp_hssacc_rx_callback_t +HssAccRxChannelCallbacks[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_user_context_t +HssAccRxChannelCallbackUserContexts[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE uint32_t +maxRxDatapathFrameSize[ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +TDM_PRIVATE icp_boolean_t +hssAccRxServiceInitialised = ICP_FALSE; + +TDM_PRIVATE uint32_t +hssAccRxDatapathNumPendPkts[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_boolean_t +hssAccRxDatapathLastReceiveSuccess[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_boolean_t +hssAccRxDatapathWatermarkLevelReached[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE int32_t +hssAccRxDatapathNumUserBuffersInRxSystem[ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +/* Stats */ +#ifndef NDEBUG +TDM_PRIVATE uint32_t hssAccRxNumPktsAged[ICP_HSSACC_MAX_NUM_CHANNELS]; +TDM_PRIVATE uint32_t hssAccRxNumPktsReceived[ICP_HSSACC_MAX_NUM_CHANNELS]; +TDM_PRIVATE uint32_t +hssAccRxNumPktsReplenished[ICP_HSSACC_CHAN_TYPE_DELIMITER]; +TDM_PRIVATE uint32_t hssAccRxNumReceiveFailures[ICP_HSSACC_MAX_NUM_CHANNELS]; +TDM_PRIVATE uint32_t +hssAccRxNumReplenishFailures[ICP_HSSACC_CHAN_TYPE_DELIMITER]; +#endif + + + +/* + * Initialises the service mutex. + */ +#define ICP_HSSACC_RX_DP_SERVICE_MUTEX_INIT(service) \ + (ixOsalMutexInit(&(hssAccRxServiceMutex[service]))) + +/* + * Locks the service mutex. + */ +#define ICP_HSSACC_RX_DP_SERVICE_MUTEX_LOCK(service) \ + (ixOsalMutexLock(&(hssAccRxServiceMutex[service]),ICP_HSSACC_MUTEX_TIMEOUT)) + +/* + * Unlocks the service mutex. + */ +#define ICP_HSSACC_RX_DP_SERVICE_MUTEX_UNLOCK(service) \ + (ixOsalMutexUnlock(&(hssAccRxServiceMutex[service]))) + +/* + * Destroys the service mutex. + */ +#define ICP_HSSACC_RX_DP_SERVICE_MUTEX_DESTROY(service) \ + (ixOsalMutexDestroy(&(hssAccRxServiceMutex[service]))) + +/* + * Initialises the rx free q service mutex. + */ +#define ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_INIT(service) \ + (ixOsalMutexInit(&(hssAccRxFreeQServiceMutex[service]))) + +/* + * Locks the rx free q service mutex. + */ +#define ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_LOCK(service) \ + (ixOsalMutexLock(&(hssAccRxFreeQServiceMutex[service]), \ + ICP_HSSACC_MUTEX_TIMEOUT)) + +/* + * Unlocks the rx free q service mutex. + */ +#define ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_UNLOCK(service) \ + (ixOsalMutexUnlock(&(hssAccRxFreeQServiceMutex[service]))) + +/* + * Destroys the rx free q service mutex. + */ +#define ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_DESTROY(service) \ + (ixOsalMutexDestroy(&(hssAccRxFreeQServiceMutex[service]))) + + + + +/****************************************************************************** + * Abstract: + * Return type of channel (voice or HDLC) + * + ******************************************************************************/ +TDM_PRIVATE icp_hssacc_channel_type_t +HssAccChanTypeGet (IxQMgrQId qId) +{ + icp_hssacc_channel_type_t chanType = ICP_HSSACC_CHAN_TYPE_DELIMITER; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChanTypeGet\n"); + + if (qId == HssAccQueueIdGet(ICP_HSSACC_HDLC_RX_Q)) + { + chanType = ICP_HSSACC_CHAN_TYPE_HDLC; + } + else if (qId == HssAccQueueIdGet(ICP_HSSACC_VOICE_RX_Q)) + { + chanType = ICP_HSSACC_CHAN_TYPE_VOICE; + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChanTypeGet\n"); + return chanType; +} + +/****************************************************************************** + * Abstract: + * Add hssAcc-supplied buffer to Rx Free Q for use by TDM I/O Unit + * + ******************************************************************************/ +icp_status_t +icp_HssAccRxFreeChecklessReplenish( + icp_hssacc_channel_type_t channelType, + icp_hssacc_osal_mbuf_tdm_io_section_t *pMBufTdmIo + ) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_tdm_io_queue_entry_t qEntry; + icp_hssacc_tdm_io_queue_entry_t *pEntry = &qEntry; + IxQMgrQEntryType entry = 0; + IxQMgrQId qId = 0; + IX_OSAL_MBUF *pBuffer = NULL; + uint32_t buffer_len = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccRxFreeChecklessReplenish\n"); + pBuffer = + (IX_OSAL_MBUF*) ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo); + + buffer_len = IX_OSAL_MBUF_MLEN(pBuffer); + + /* Set qId based on whether buffer is Voice or HDLC */ + if (channelType == ICP_HSSACC_CHAN_TYPE_HDLC) + { + qId = HssAccQueueIdGet(ICP_HSSACC_HDLC_RX_FREE_Q); + } + else if (channelType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + qId = HssAccQueueIdGet(ICP_HSSACC_VOICE_RX_FREE_Q); + } + else + { + status = ICP_STATUS_INVALID_PARAM; + return status; + } + + /* Fill out Rx Free Q Entry */ + ICP_TDM_IO_Q_ENTRY_CHANNEL_ID(pEntry) = 0; + ICP_TDM_IO_Q_ENTRY_STATUS(pEntry) = 0; + + ICP_TDM_IO_Q_ENTRY_CURR_BUF_LEN_MSB(pEntry) = + ICP_OSAL_MBUF_PKT_LEN_MSB((uint16_t) buffer_len); + + ICP_TDM_IO_Q_ENTRY_CURR_BUF_LEN_LSB(pEntry) = + ICP_OSAL_MBUF_PKT_LEN_LSB((uint16_t) buffer_len); + + ICP_TDM_IO_Q_ENTRY_DATA(pEntry) = + (void *) HssAccVirtToPhysAddressTranslateAndSwap( + (void *) ICP_OSAL_MBUF_TDM_SECT_DATA(pMBufTdmIo)); + + ICP_TDM_IO_Q_ENTRY_PKT_LEN(pEntry) = 0; + + ICP_TDM_IO_Q_ENTRY_OSAL_MBUF(pEntry) = + (IX_OSAL_MBUF *) HssAccVirtToPhysAddressTranslateAndSwap( + (void *) pMBufTdmIo); + + /* Acquire service mutex */ + if (ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_LOCK(channelType) == IX_SUCCESS) + { + /* Add entry to Rx Free Q */ + status = ixQMgrQWrite(qId, (IxQMgrQEntryType *) pEntry); + /* Check for overflow (only possible error returned by a Q write) */ + if (status == ICP_STATUS_OVERFLOW) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeChecklessReplenish - " + "Q overflow writing to Rx Free Q\n", + 0); + } + else + { + if ICP_HSSACC_DATAPLANE_RING_FULL( + HssAccRxDpFreeQRing[channelType]) + { + /* If the internal ring is full, remove the oldest + entry before adding another one */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + HssAccRxDpFreeQRing[channelType], entry); + } + + entry = (IxQMgrQEntryType) + ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo); + + /* Add buffer to internal ring also */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_ADD( + HssAccRxDpFreeQRing[channelType], entry); + } + + if (ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_UNLOCK(channelType) != + IX_SUCCESS) + { + if (channelType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeChecklessReplenish - " + "Mutex Unlock Error for " + "voice service\n", 0); + } + else + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeChecklessReplenish - " + "Mutex Unlock Error for " + "HDLC service\n", 0); + } + status = ICP_STATUS_MUTEX; + } + } + else + { + if (channelType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeChecklessReplenish - " + "Mutex Lock Error for " + "voice service\n", 0); + } + else + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeChecklessReplenish - " + "Mutex Lock Error for " + "HDLC service\n", 0); + } + + status = ICP_STATUS_MUTEX; + } + +#ifndef NDEBUG + /* Log packet */ + if (status != ICP_STATUS_SUCCESS) + { + hssAccRxNumReplenishFailures[channelType] ++; + } + else + { + hssAccRxNumPktsReplenished[channelType] ++; + } +#endif + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccRxFreeChecklessReplenish\n"); + + return status; +} + + +/****************************************************************************** + * Abstract: + * Register rx callback and user context + * + ******************************************************************************/ +void +HssAccChannelRxCallbackRegister(uint32_t channelId, + icp_hssacc_rx_callback_t rxCallback, + icp_user_context_t userContext) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelRxCallbackRegister\n"); + + HssAccRxChannelCallbacks[channelId] = rxCallback; + HssAccRxChannelCallbackUserContexts[channelId] = userContext; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelRxCallbackRegister\n"); +} + +/****************************************************************************** + * Abstract: + * Register rx callback and user context + * + ******************************************************************************/ +void +HssAccChannelRxCallbackDeregister(uint32_t channelId) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelRxCallbackDeregister\n"); + + HssAccRxChannelCallbacks[channelId] = NULL; + HssAccRxChannelCallbackUserContexts[channelId] = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelRxCallbackDeregister\n"); +} + +/****************************************************************************** + * Abstract: + * Service Rx Q and call a callback for every entry received + * Process receive Q, calling callbacks for each received buffer. + * Called from the queue processing function. The Q manager callbacks are + * triggered by HssAccRxDatapathService + * + ******************************************************************************/ +void +HssAccRxQServiceCallback (IxQMgrQId qId, + IxQMgrCallbackId cbId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t numEntries = 0; + uint32_t k = 0; + uint32_t chId = 0; + IxQMgrQEntryType qEntry = 0; + IxQMgrQEntryType physQEntry = 0; + unsigned callbacksToDo = 0; + icp_hssacc_osal_mbuf_tdm_io_section_t *pMBufTdmIo = NULL; + icp_hssacc_channel_type_t chanType = ICP_HSSACC_CHAN_TYPE_DELIMITER; + unsigned chanCallbackNeeded[ICP_HSSACC_MAX_NUM_CHANNELS]; + + + ICP_HSSACC_DP_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxQServiceCallback for " + "Q %d and CB Id %d\n", + qId, cbId); + + /* Retrieve channel type */ + chanType = HssAccChanTypeGet(qId); + + memset(chanCallbackNeeded,0,ICP_HSSACC_MAX_NUM_CHANNELS*sizeof(unsigned)); + + /* Acquire service mutex */ + if (IX_SUCCESS != ICP_HSSACC_RX_DP_SERVICE_MUTEX_LOCK(chanType)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxQService - " + "Mutex Lock Error for service %d\n", + chanType); + return; + } + + /* Get number of entries in q */ + status = ixQMgrQNumEntriesGetWithChecks ( qId, &numEntries); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxQService - " + "Error Reading Num Entries " + "from the Queue\n"); + + if (ICP_HSSACC_RX_DP_SERVICE_MUTEX_UNLOCK(chanType) != IX_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxQService - " + "Mutex Unlock Error for service %d\n", + chanType); + } + + return; + } + + for (k = 0; k < numEntries; k ++) + { + status = ixQMgrQReadWithChecks (qId, &physQEntry); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxQServiceCallback - Error" + " Reading from the Queue\n"); + continue; + } + + /* Convert physical address (that TDM I/O Unit uses) to + virtual address (that Access layer uses) */ + qEntry = (IxQMgrQEntryType) + HssAccPhysToVirtAddressSwapAndTranslate(physQEntry); + + ICP_HSSACC_DP_TRACE_2(ICP_HSSACC_DEBUG, + "HssAccRxQServiceCallback - " + "got Phys Entry 0x%08X to Virt 0x%08X\n", + physQEntry, + qEntry); + + /* Convert q Entry to a pointer to TDM I/O-specific + portion of OSAL MBUF */ + pMBufTdmIo = + (icp_hssacc_osal_mbuf_tdm_io_section_t *) qEntry; + /* Retrieve channel Id */ + chId = ICP_OSAL_MBUF_TDM_SECT_CHANNEL_ID(pMBufTdmIo); + + if (ICP_HSSACC_CHANNEL_ENABLED != + HssAccChannelConfigStateQuery(chId)) + { + /* if channel is not enabled put the buffer on the + rx free q and not on the channel ring */ + if (ICP_STATUS_SUCCESS != + icp_HssAccRxFreeChecklessReplenish(chanType, + pMBufTdmIo)) + { + ICP_HSSACC_REPORT_ERROR_1( + "HssAccRxQServiceCallback - " + " Rx Free Replenish failed for channel type %d\n", + chanType); + } + } + else + { + if (!ICP_HSSACC_DATAPLANE_RING_FULL( + HssAccRxDpDescRing[chId])) + { + /* VOICE PACKET AGING: check the channel type and + queue Level. Reject if above level and + previous buffer was accepted onto ring */ + if (ICP_HSSACC_CHAN_TYPE_VOICE == + HssAccChannelConfigTypeQuery(chId)) + { + if(ICP_HSSACC_RX_Q_WATERMARK_LEVEL <= + hssAccRxDatapathNumPendPkts[chId]) + { + hssAccRxDatapathWatermarkLevelReached[chId] + = ICP_TRUE; + } + else if ((ICP_TRUE == + hssAccRxDatapathWatermarkLevelReached[chId]) && + (0 == hssAccRxDatapathNumPendPkts[chId])) + { + hssAccRxDatapathWatermarkLevelReached[chId] + = ICP_FALSE; + } + } + + if ((ICP_TRUE == + hssAccRxDatapathWatermarkLevelReached[chId]) && + (ICP_TRUE == + hssAccRxDatapathLastReceiveSuccess[chId])) + { + /* can only be true for voice */ + ICP_HSSACC_DP_TRACE_1(ICP_HSSACC_DEBUG, + "HssAccRxQServiceCallback - " + "Regulating Rx Flow for channel %d\n", + chId); + /* put the buffer on the rx free q and not on the + channel ring */ + if (ICP_STATUS_SUCCESS != + icp_HssAccRxFreeChecklessReplenish( + chanType, + pMBufTdmIo)) + { + ICP_HSSACC_REPORT_ERROR_1( + "HssAccRxQServiceCallback - Rx Free" + " Replenish failed for channel type %d\n", + chanType); + } + +#ifndef NDEBUG + hssAccRxNumPktsAged[chId]++; +#endif + hssAccRxDatapathLastReceiveSuccess[chId] + = ICP_FALSE; + } + else + { + /* Put q entry in ring associated with + correct channel */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_ADD( + HssAccRxDpDescRing[chId], + qEntry); + hssAccRxDatapathNumPendPkts[chId] ++; + hssAccRxDatapathLastReceiveSuccess[chId] + = ICP_TRUE; + + /* Log which channel requires a callback and + increment the total num of callbacks to do */ + if (NULL != HssAccRxChannelCallbacks[chId]) + { + chanCallbackNeeded[chId] ++; + callbacksToDo ++; + } + } + } + else + { + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccRxQServiceCallback - Internal Ring" + " overflow on channel %d\n", + chId); + + /* put the buffer on the rx free q and not on the + channel ring */ + if (ICP_STATUS_SUCCESS != + icp_HssAccRxFreeChecklessReplenish( + chanType, + pMBufTdmIo)) + { + ICP_HSSACC_REPORT_ERROR_1( + "HssAccRxQServiceCallback - Rx Free" + " Replenish failed for channel type %d\n", + chanType); + } + + hssAccRxDatapathLastReceiveSuccess[chId] = ICP_FALSE; + continue; + } + } + } + + if (ICP_HSSACC_RX_DP_SERVICE_MUTEX_UNLOCK(chanType) != IX_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxQServiceCallback - " + "Mutex Unlock Error for service %d\n", + chanType); + } + else + { + k = 0; + while (callbacksToDo) + { + while (chanCallbackNeeded[k]) + { + ICP_HSSACC_DP_TRACE_2(ICP_HSSACC_DEBUG, + "HssAccRxQServiceCallback - channel %d, " + " %d callbacks left\n", + k, callbacksToDo-1); + + HssAccRxChannelCallbacks[k]( + HssAccRxChannelCallbackUserContexts[k]); + chanCallbackNeeded[k] --; + callbacksToDo --; + } + k ++; + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxQServiceCallback\n"); + +} + + +/****************************************************************************** + * Abstract: + * Process receive Q *without* any calling of callbacks. Called + * from icp_HssAccReceive. If nothing in rx Q, returns ICP_FALSE in + * bufferReceived arg + * + *****************************************************************************/ +icp_status_t +HssAccRxQService (IxQMgrQId qId, + unsigned channelId, + icp_boolean_t *bufferReceived) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t numEntries = 0; + uint32_t k = 0; + uint32_t chId = 0; + IxQMgrQEntryType qEntry = 0; + IxQMgrQEntryType physQEntry = 0; + icp_hssacc_osal_mbuf_tdm_io_section_t *pMBufTdmIo = NULL; + icp_hssacc_channel_type_t chanType = ICP_HSSACC_CHAN_TYPE_DELIMITER; + + ICP_HSSACC_DP_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxQService for " + "Q %d and channelId %d\n", + qId, channelId); + + *bufferReceived = ICP_FALSE; + + /* Retrieve channel type */ + chanType = HssAccChanTypeGet(qId); + + if (IX_SUCCESS != ICP_HSSACC_RX_DP_SERVICE_MUTEX_LOCK(chanType)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxQService - " + "Mutex Lock Error for service %d\n", + chanType); + status = ICP_STATUS_MUTEX; + return status; + } + + /* Get number of entries in q */ + status = ixQMgrQNumEntriesGetWithChecks ( qId, &numEntries); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxQService - " + "Error Reading Num Entries " + "from the Queue\n"); + + if (ICP_HSSACC_RX_DP_SERVICE_MUTEX_UNLOCK(chanType) != IX_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxQService - " + "Mutex Unlock Error for service %d\n", + chanType); + } + + return status; + } + + for (k = 0; k < numEntries; k ++) + { + status = ixQMgrQReadWithChecks (qId, &physQEntry); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxQService - Error" + " Reading from the Queue\n"); + continue; + } + + /* Convert physical address (that TDM I/O Unit uses) to + virtual address (that Access layer uses) */ + qEntry = (IxQMgrQEntryType) + HssAccPhysToVirtAddressSwapAndTranslate(physQEntry); + + ICP_HSSACC_DP_TRACE_2(ICP_HSSACC_DEBUG, + "HssAccRxQService - " + "got Phys Entry 0x%08X to Virt 0x%08X\n", + physQEntry, + qEntry); + + /* Convert q Entry to a pointer to TDM I/O-specific + portion of OSAL MBUF */ + pMBufTdmIo = + (icp_hssacc_osal_mbuf_tdm_io_section_t *) qEntry; + /* Retrieve channel Id */ + chId = ICP_OSAL_MBUF_TDM_SECT_CHANNEL_ID(pMBufTdmIo); + + if (ICP_HSSACC_CHANNEL_ENABLED != + HssAccChannelConfigStateQuery(chId)) + { + /* if channel is not enabled put the buffer on the + rx free q and not on the channel ring */ + if (ICP_STATUS_SUCCESS != + icp_HssAccRxFreeChecklessReplenish(chanType, + pMBufTdmIo)) + { + ICP_HSSACC_REPORT_ERROR_1( + "HssAccRxQService - " + " Rx Free Replenish failed for channel type %d\n", + chanType); + } + } + else + { + if (!ICP_HSSACC_DATAPLANE_RING_FULL( + HssAccRxDpDescRing[chId])) + { + /* VOICE PACKET AGING: check the channel type and + queue Level. Reject if above level and + previous buffer was accepted onto ring */ + if (ICP_HSSACC_CHAN_TYPE_VOICE == + HssAccChannelConfigTypeQuery(chId)) + { + if(ICP_HSSACC_RX_Q_WATERMARK_LEVEL <= + hssAccRxDatapathNumPendPkts[chId]) + { + hssAccRxDatapathWatermarkLevelReached[chId] + = ICP_TRUE; + } + else if ((ICP_TRUE == + hssAccRxDatapathWatermarkLevelReached[chId]) && + (0 == hssAccRxDatapathNumPendPkts[chId])) + { + hssAccRxDatapathWatermarkLevelReached[chId] + = ICP_FALSE; + } + } + + if ((ICP_TRUE == + hssAccRxDatapathWatermarkLevelReached[chId]) && + (ICP_TRUE == + hssAccRxDatapathLastReceiveSuccess[chId])) + { + /* can only be true for voice */ + ICP_HSSACC_DP_TRACE_1(ICP_HSSACC_DEBUG, + "HssAccRxQService - " + "Regulating Rx Flow for channel %d\n", + chId); + /* put the buffer on the rx free q and not on the + channel ring */ + if (ICP_STATUS_SUCCESS != + icp_HssAccRxFreeChecklessReplenish( + chanType, + pMBufTdmIo)) + { + ICP_HSSACC_REPORT_ERROR_1( + "HssAccRxQService - Rx Free" + " Replenish failed for channel type %d\n", + chanType); + } +#ifndef NDEBUG + hssAccRxNumPktsAged[chId]++; +#endif + hssAccRxDatapathLastReceiveSuccess[chId] + = ICP_FALSE; + } + else + { + /* Put q entry in ring associated with + correct channel */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_ADD( + HssAccRxDpDescRing[chId], + qEntry); + hssAccRxDatapathNumPendPkts[chId] ++; + hssAccRxDatapathLastReceiveSuccess[chId] + = ICP_TRUE; + if (channelId == chId) + { + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccRxQService - A new " + "buffer was pushed into the " + "internal ring on channel %d\n", + chId); + /* flag a buffer has been received */ + *bufferReceived = ICP_TRUE; + } + } + } + else + { + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccRxQService - Internal Ring" + " overflow on channel %d\n", + chId); + + /* put the buffer on the rx free q and not on the + channel ring */ + if (ICP_STATUS_SUCCESS != + icp_HssAccRxFreeChecklessReplenish( + chanType, + pMBufTdmIo)) + { + ICP_HSSACC_REPORT_ERROR_1( + "HssAccRxQService - Rx Free" + " Replenish failed for channel type %d\n", + chanType); + } + + hssAccRxDatapathLastReceiveSuccess[chId] = ICP_FALSE; + continue; + } + } + } + + if (ICP_HSSACC_RX_DP_SERVICE_MUTEX_UNLOCK(chanType) != IX_SUCCESS) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxQService - " + "Mutex Unlock Error for service %d\n", + chanType); + status = ICP_STATUS_MUTEX; + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxQService\n"); + + return status; + +} + + + +/****************************************************************************** + * Abstract: + * Function called from icp_HssAccReceive which + * checks to see if there's anything in channel's internal ring. + * If there is, this is returned immediately, otherwise calls + * HssAccRxQService + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccRxReceive (IxQMgrQId qId, + uint32_t channelId, + IX_OSAL_MBUF ** buffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxQMgrQEntryType qEntry; + icp_hssacc_osal_mbuf_tdm_io_section_t *pMBufTdmIo; + icp_boolean_t bufferReceived = ICP_TRUE; + icp_hssacc_channel_type_t chanType = HssAccChannelConfigTypeQuery(channelId); + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxReceive\n"); + + /* Return NULL buffer by default */ + *buffer = NULL; + + /* If there's anything available for channel, return it, */ + if (ICP_HSSACC_DATAPLANE_RING_EMPTY(HssAccRxDpDescRing[channelId])) + { + /* otherwise, process queue and repeat check */ + status = HssAccRxQService(qId, channelId, &bufferReceived); + } + else + { + bufferReceived = ICP_TRUE; + } + + if ( (status == ICP_STATUS_SUCCESS) && (bufferReceived == ICP_TRUE) ) + { + + /* There is definitely something in channel's ring now */ + + /* Get an entry */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM(HssAccRxDpDescRing[channelId], + qEntry); + hssAccRxDatapathNumUserBuffersInRxSystem[chanType] --; + hssAccRxDatapathNumPendPkts[channelId] --; + + /* Entry is a pointer to TDM I/O Unit-specific portion of + an OSAL buffer, */ + pMBufTdmIo = (icp_hssacc_osal_mbuf_tdm_io_section_t *) qEntry; + + /* look up where start of buffer is */ + *buffer = ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo); + /* Set the length of received buffer in OSAL buffer fields */ + + IX_OSAL_MBUF_MLEN(*buffer) = + ( (ICP_OSAL_MBUF_TDM_SECT_CURR_BUF_LEN_MSB(pMBufTdmIo) << + ICP_OSAL_MBUF_TDM_SECT_LEN_MSB_OFFSET) | + ICP_OSAL_MBUF_TDM_SECT_CURR_BUF_LEN_LSB(pMBufTdmIo) ); + IX_OSAL_MBUF_PKT_LEN(*buffer) = IX_OSAL_MBUF_MLEN(*buffer); + + HssAccDataEndiannessSwap(*buffer); + + }/*if ( (status == ICP_STATUS_SUCCESS) && (bufferReceived == ICP_TRUE) )*/ + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxReceive\n"); + + return status; +} + + + +/****************************************************************************** + * Abstract: + * This function receives a buffer. Simply checks channel type + * and calls HssAccRxReceive. Also logs packets. + * + *****************************************************************************/ +icp_status_t +icp_HssAccReceive (uint32_t channelId, IX_OSAL_MBUF ** buffer) +{ + icp_hssacc_channel_type_t chanType = ICP_HSSACC_CHAN_TYPE_DELIMITER; + icp_status_t status = ICP_STATUS_SUCCESS; + IxQMgrQId qId = IX_QMGR_MAX_NUM_QUEUES; + + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccReceive for channel %d\n", + channelId); + +#ifndef NDEBUG + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccReceive - channelId " + "out of range\n"); + status = ICP_STATUS_INVALID_PARAM; + } +#endif + if (ICP_STATUS_SUCCESS == status) + { + /* Retrieve qId for channel */ + chanType = HssAccChannelConfigTypeQuery(channelId); + if (chanType == ICP_HSSACC_CHAN_TYPE_HDLC) + { + qId = HssAccQueueIdGet(ICP_HSSACC_HDLC_RX_Q); + } + else if (chanType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + qId = HssAccQueueIdGet(ICP_HSSACC_VOICE_RX_Q); + } + else + { + status = ICP_STATUS_INVALID_PARAM; + } + } + if (status == ICP_STATUS_SUCCESS) + { + status = HssAccRxReceive(qId, channelId, buffer); + } + +#ifndef NDEBUG + /* Log packet */ + if ( (status != ICP_STATUS_SUCCESS) || (*buffer == NULL) ) + { + hssAccRxNumReceiveFailures[channelId] ++; + } + else + { + hssAccRxNumPktsReceived[channelId] ++; + } +#endif + + ICP_HSSACC_DP_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccReceive for channel %d " + "with buffer 0x%08X\n", + channelId, + (uint32_t)*buffer); + return status; +} + + +/****************************************************************************** + * Abstract: + * Function to run the Q Mgr processing function and call + * associated callbacks + * + ******************************************************************************/ +icp_status_t +HssAccRxDatapathService(icp_hssacc_channel_type_t channelType) +{ + IxQMgrDispatchGroup group; + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathService\n"); + + /* Just call dispatcher loop for Rx Qs */ + if (channelType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + group = IX_QMGR_DISPATCH_VOICE_RX_HSS; + ixQMgrDispatcherLoopRun(group); + } + else if (channelType == ICP_HSSACC_CHAN_TYPE_HDLC) + { + group = IX_QMGR_DISPATCH_HDLC_RX_HSS; + ixQMgrDispatcherLoopRun(group); + } + else + { + status = ICP_STATUS_INVALID_PARAM; + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathService\n"); + return status; +} + + + +/****************************************************************************** + * Abstract: +* Reset the per-channel statistics +* +******************************************************************************/ +void +HssAccRxDatapathChanStatsReset(uint32_t channelId) +{ +#ifndef NDEBUG + hssAccRxNumPktsReceived[channelId] = 0; + hssAccRxNumReceiveFailures[channelId] = 0; + hssAccRxNumPktsAged[channelId] = 0; +#endif +} + + + + +/****************************************************************************** + * Abstract: + * Print out the per-channel statistics + * + ******************************************************************************/ +void +HssAccRxDatapathChanStatsShow(uint32_t channelId) +{ +#ifndef NDEBUG + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nRx Datapath Statistics for Channel %d\n", + channelId, 0, 0, 0, 0, 0); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\t\t%d Packets Received\n" + "\t\t%d Packet Receive Failures\n" + "\t\t%d Packets Aged\n", + hssAccRxNumPktsReceived[channelId], + hssAccRxNumReceiveFailures[channelId], + hssAccRxNumPktsAged[channelId], 0, 0, 0); + +#else + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Rx Datapath Statistics Not Supported in this Build\n", + 0, 0, 0, 0, 0, 0); +#endif +} + + + +/****************************************************************************** + * Abstract: + * Function to print out stats on replenishing + * + ******************************************************************************/ +void +HssAccRxDatapathReplenishStatsShow(icp_hssacc_channel_type_t serviceType) +{ +#ifndef NDEBUG + if (serviceType == ICP_HSSACC_CHAN_TYPE_HDLC) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nRx Datapath Replenish Statistics for HDLC service\n", + 0, 0, 0, 0, 0, 0); + } + else + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nRx Datapath Replenish Statistics for voice service\n", + 0, 0, 0, 0, 0, 0); + } + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\t\t%d Packets Replenished\n" + "\t\t%d Packet Replenish Failures\n", + hssAccRxNumPktsReplenished[serviceType], + hssAccRxNumReplenishFailures[serviceType], 0, 0, 0, 0); +#else + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nRx Datapath Service Statistics Not Supported in this Build\n", + 0, 0, 0, 0, 0, 0); +#endif +} + + + + +/****************************************************************************** + * Abstract: + * Function to reset stats on replenishing + * + *****************************************************************************/ +void +HssAccRxDatapathReplenishStatsReset(icp_hssacc_channel_type_t serviceType) +{ +#ifndef NDEBUG + hssAccRxNumPktsReplenished[serviceType] = 0; + hssAccRxNumReplenishFailures[serviceType] = 0; +#endif +} + + + +/****************************************************************************** + * Abstract: + * Reset all globals + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccRxDatapathReset(void) +{ + int k = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathReset\n"); + + for (k = 0; k < ICP_HSSACC_MAX_NUM_CHANNELS; k ++) + { + + HssAccRxDpDescRing[k].content = &HssAccRxDpDescPtrRingData[k][0]; + HssAccRxDpDescRing[k].size = + ICP_HSSACC_RX_DP_CHAN_DESC_PTR_RING_SZ; + HssAccRxDpDescRing[k].mask = + ICP_HSSACC_RX_DP_CHAN_DESC_PTR_RING_SZ - 1; + HssAccRxDpDescRing[k].tail = 0; + HssAccRxDpDescRing[k].head = 0; + HssAccRxChannelCallbacks[k] = NULL; + HssAccRxChannelCallbackUserContexts[k] = 0; + HssAccRxDatapathChanStatsReset(k); + hssAccRxDatapathNumPendPkts[k] = 0; + hssAccRxDatapathLastReceiveSuccess[k] = ICP_FALSE; + hssAccRxDatapathWatermarkLevelReached[k] = ICP_FALSE; + } + + for (k = 0; k < ICP_HSSACC_CHAN_TYPE_DELIMITER; k ++) + { + HssAccRxDpFreeQRing[k].content = &HssAccRxDpFreeQRingData[k][0]; + HssAccRxDpFreeQRing[k].size = ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH; + HssAccRxDpFreeQRing[k].mask = ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH-1; + HssAccRxDpFreeQRing[k].tail = 0; + HssAccRxDpFreeQRing[k].head = 0; + maxRxDatapathFrameSize[k] = 0; +#ifndef NDEBUG + hssAccRxNumPktsReplenished[k] = 0; + hssAccRxNumReplenishFailures[k] = 0; +#endif + hssAccRxDatapathNumUserBuffersInRxSystem[k] = 0; + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathReset\n"); + + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Initialise Rx datapath global variables + * + ******************************************************************************/ +icp_status_t +HssAccRxDatapathInit(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t k = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathInit\n"); + /* Check if component has already been initialised */ + if (ICP_TRUE == hssAccRxServiceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("HssAccRxDatapathInit - " + "component has already been initialised\n"); + + status = ICP_STATUS_FAIL; + } + else /* component has never been initialised */ + { + + /* Initialise service mutexes */ + for (k = 0; k < ICP_HSSACC_CHAN_TYPE_DELIMITER; k ++) + { + if (IX_SUCCESS != ICP_HSSACC_RX_DP_SERVICE_MUTEX_INIT(k)) + { + if (k == ICP_HSSACC_CHAN_TYPE_VOICE) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathInit - " + "Mutex Initialisation Error " + "for voice service\n", 0); + } + else + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathInit - " + "Mutex Initialisation " + "Error for HDLC service\n", 0); + } + status = ICP_STATUS_MUTEX; + } + + if (IX_SUCCESS != ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_INIT(k)) + { + if (k == ICP_HSSACC_CHAN_TYPE_VOICE) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathInit - Rx Free " + "Q Mutex Initialisation Error " + "for voice service\n", 0); + } + else + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathInit - Rx Free " + "Q Mutex Initialisation " + "Error for HDLC service\n", 0); + } + status = ICP_STATUS_MUTEX; + } + } + + if (status == ICP_STATUS_SUCCESS) + { + status = HssAccRxDatapathReset(); + if (status == ICP_STATUS_SUCCESS) + { + hssAccRxServiceInitialised = ICP_TRUE; + } + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathInit\n"); + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Shut down Rx datapath Module. + * + *****************************************************************************/ +icp_status_t +HssAccRxDatapathShutdown(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t k = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathShutdown\n"); + + /* Check if component has not been initialised */ + if (ICP_FALSE == hssAccRxServiceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("HssAccRxDatapathShutdown - " + "component has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + else /* component has been initialised */ + { + status = HssAccRxDatapathReset(); + + if (status == ICP_STATUS_SUCCESS) + { + + /* Destroy service mutexes */ + for (k = 0; k < ICP_HSSACC_CHAN_TYPE_DELIMITER; k ++) + { + if (IX_SUCCESS != ICP_HSSACC_RX_DP_SERVICE_MUTEX_DESTROY(k)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathShutdown - " + "Mutex Destroy Error for " + "service %d\n", + k); + status = ICP_STATUS_MUTEX; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathShutdown\n"); + return status; + } + + if (IX_SUCCESS != ICP_HSSACC_RX_FREEQ_DP_SERVICE_MUTEX_DESTROY(k)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathShutdown - Rx " + "Free Q Mutex Destroy Error for " + "service %d\n", + k); + status = ICP_STATUS_MUTEX; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathShutdown\n"); + return status; + } + } + } + if (ICP_STATUS_SUCCESS == status) + { + hssAccRxServiceInitialised = ICP_FALSE; + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathShutdown\n"); + return status; +} + + +/****************************************************************************** + * Abstract: + * Add user-supplied buffer to Rx Free Q for use by TDM I/O Unit + * + ******************************************************************************/ +icp_status_t +icp_HssAccRxFreeReplenish ( + icp_hssacc_channel_type_t channelType, + IX_OSAL_MBUF *buffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_osal_mbuf_tdm_io_section_t *pMBufTdmIo; + uint32_t buffer_len = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccRxFreeReplenish\n"); + + if (channelType != ICP_HSSACC_CHAN_TYPE_HDLC + && channelType != ICP_HSSACC_CHAN_TYPE_VOICE) + { + status = ICP_STATUS_INVALID_PARAM; + return status; + } + + /* Check that buffer is not NULL */ + if (buffer == NULL) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccRxFreeReplenish - " + "Buffer pointer is NULL\n"); + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccRxFreeReplenish\n"); + status = ICP_STATUS_INVALID_PARAM; + return status; + } + + /* Check that buffer is not chained. We do not support chaining. */ + if ((IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(buffer) != NULL) || + (IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(buffer) != NULL)) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccRxFreeReplenish - " + "Buffer or Packet Chaining not supported " + "for reception\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if (IX_OSAL_MBUF_MDATA(buffer) == NULL) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccRxFreeReplenish - " + "Buffer's data pointer cannot be NULL\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + /* Check if buffer length supplied is ok. + All buffers supplied need to accomodate the max frame size possible */ + buffer_len = IX_OSAL_MBUF_MLEN(buffer); + if ( buffer_len < maxRxDatapathFrameSize[channelType]) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccRxFreeReplenish - " + "Buffer is too small. Buffers supplied " + "must all accomodate max frame size\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + if (status == ICP_STATUS_SUCCESS) + { + + /* check chan type and compare num bufs in rx path to size of rx free q */ + if (channelType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + if(ICP_HSSACC_VOICE_RX_QUEUE_DEPTH + <= hssAccRxDatapathNumUserBuffersInRxSystem + [ICP_HSSACC_CHAN_TYPE_VOICE]) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeReplenish - " + "Voice Rx Datapath Max Buffer Limit Reached\n", + 0); + status = ICP_STATUS_OVERFLOW; + } + } + else + { + if(ICP_HSSACC_HDLC_RX_QUEUE_DEPTH + <= hssAccRxDatapathNumUserBuffersInRxSystem + [ICP_HSSACC_CHAN_TYPE_HDLC]) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccRxFreeReplenish - " + "HDLC Rx Datapath Max Buffer Limit Reached\n", + 0); + status = ICP_STATUS_OVERFLOW; + } + } + + if (status == ICP_STATUS_SUCCESS) + { + /* Add buffer to relevant Rx free Q */ + + /* First, copy info from OSAL buffer to TDM I/O + Unit-specific portion */ + /* Get address of TDM I/O Unit-specific portion of OSAL buffer */ + pMBufTdmIo = + (icp_hssacc_osal_mbuf_tdm_io_section_t *) &(buffer->ix_ne); + + /* Copy current buffer data location */ + ICP_OSAL_MBUF_TDM_SECT_DATA(pMBufTdmIo) = + (void *) IX_OSAL_MBUF_MDATA(buffer); + + /* Copy current buffer location */ + ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo) = buffer; + + status = icp_HssAccRxFreeChecklessReplenish (channelType, + pMBufTdmIo); + + if ( ICP_STATUS_SUCCESS == status ) + { + hssAccRxDatapathNumUserBuffersInRxSystem[channelType] ++; + } + + } + + } + + return status; +} + + + +/****************************************************************************** + * Abstract: + * Set max frame size for HDLC, must be done at init + * + *****************************************************************************/ +void +HssAccRxDatapathHdlcInit(uint32_t maxRxFrameSize) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathHdlcInit\n"); + maxRxDatapathFrameSize[ICP_HSSACC_CHAN_TYPE_HDLC] = maxRxFrameSize; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathHdlcInit\n"); +} + + + + +/****************************************************************************** + * Abstract: + * Set max frame size for voice, must be done at init + * + *****************************************************************************/ +void +HssAccRxDatapathVoiceInit(uint32_t maxRxFrameSize) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathVoiceInit\n"); + maxRxDatapathFrameSize[ICP_HSSACC_CHAN_TYPE_VOICE] = maxRxFrameSize; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathVoiceInit\n"); +} + + +/****************************************************************************** + * Abstract: + * Return the Max Rx Sample/Frame size configured for the specified Service + * + *****************************************************************************/ +uint32_t +HssAccRxDatapathMaxServiceFrameSizeGet(icp_hssacc_channel_type_t servType) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Called HssAccRxDatapathMaxServiceFrameSizeGet\n"); + return maxRxDatapathFrameSize[servType]; +} + + + + +/****************************************************************************** + * Abstract: + * Checks to see if any channels exist for a specified service other than + * the one being worked on. + * + *****************************************************************************/ +icp_boolean_t +HssAccRxDatapathServAllChansDisabledQuery(icp_hssacc_channel_type_t chanType, + const unsigned channelId) +{ + uint32_t chanId = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering " + "HssAccRxDatapathServAllChansDisabledQuery\n"); + + for (chanId=0; chanId < ICP_HSSACC_MAX_NUM_CHANNELS; chanId ++) + { + if (chanType == HssAccChannelConfigTypeQuery(chanId) ) + { + if ((HssAccChannelConfigStateQuery(chanId) != + ICP_HSSACC_CHANNEL_UNINITIALISED) && + (chanId != channelId)) + { + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccRxDatapathServAllChansDisabledQuery -" + " Found channel %u\n", + chanId); + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting " + "HssAccRxDatapathServAllChans" + "DisabledQuery\n"); + return ICP_FALSE; + } + } + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting " + "HssAccRxDatapathServAllChansDisabledQuery\n"); + return ICP_TRUE; +} + + +/****************************************************************************** + * Abstract: + * Retrieve all buffers left in a specific service RxFree queue + * + *****************************************************************************/ +icp_status_t +HssAccRxDatapathServiceSpecificRxFreeEmpty(icp_hssacc_channel_type_t chanType, + IX_OSAL_MBUF * * ppStartChainBuffer, + IX_OSAL_MBUF * * ppEndChainBuffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IX_OSAL_MBUF * pCurrentBuffer = NULL; + IxQMgrQId rxfreeqId = IX_QMGR_MAX_NUM_QUEUES; + IxQMgrQId rxqId = IX_QMGR_MAX_NUM_QUEUES; + unsigned numEntries = 0; + IxQMgrQEntryType freeQEntry; + icp_boolean_t bufferReceived = ICP_FALSE; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathServiceSpecificRxFreeEmpty\n"); + + if (chanType == ICP_HSSACC_CHAN_TYPE_HDLC) + { + rxfreeqId = HssAccQueueIdGet(ICP_HSSACC_HDLC_RX_FREE_Q); + rxqId = HssAccQueueIdGet(ICP_HSSACC_HDLC_RX_Q); + } + else if (chanType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + rxfreeqId = HssAccQueueIdGet(ICP_HSSACC_VOICE_RX_FREE_Q); + rxqId = HssAccQueueIdGet(ICP_HSSACC_VOICE_RX_Q); + } + else + { + status = ICP_STATUS_INVALID_PARAM; + return status; + } + + /* the important part here is to drain the rx queue + into the rx free queue */ + if (ICP_STATUS_SUCCESS != + (status = HssAccRxQService(rxqId, + ICP_HSSACC_MAX_NUM_CHANNELS, + &bufferReceived) )) + { + return status; + } + + /* Acquire service mutex */ + if (IX_SUCCESS != ICP_HSSACC_RX_DP_SERVICE_MUTEX_LOCK(chanType)) + { + if (chanType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + ICP_HSSACC_REPORT_ERROR( + "HssAccRxDatapathServiceSpecificRxFreeEmpty - " + "Mutex Lock Error for " + "voice service\n"); + } + else + { + ICP_HSSACC_REPORT_ERROR( + "HssAccRxDatapathServiceSpecificRxFreeEmpty - " + "Mutex Lock Error for " + "HDLC service\n"); + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathServiceSpecificRxFreeEmpty\n"); + return ICP_STATUS_MUTEX; + } + + status = ixQMgrQNumEntriesGet (rxfreeqId, + &numEntries); + + /* Chain all Rx free Q Buffers */ + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccRxDatapathServiceSpecificRxFreeEmpty - " + "Create Chain with Rx Free Buffers\n"); + /* First of all read out useless entries in the ring + that mirrors the Rx Free Q */ + while (ICP_HSSACC_DATAPLANE_RING_NUM_ENTRIES_GET( + HssAccRxDpFreeQRing[chanType]) > + numEntries) + { + ICP_HSSACC_DATAPLANE_RING_TAIL_INCR(HssAccRxDpFreeQRing[chanType]); + } + + /* Wind back write pointer to Rx Free Q by number of + entries in Q */ + status = ixQMgrQWriteRollback(rxfreeqId, numEntries); + } + + if (status == ICP_STATUS_SUCCESS) + { + /* add an entry from free Q to start */ + if ((0 != numEntries) && + (!ICP_HSSACC_DATAPLANE_RING_EMPTY(HssAccRxDpFreeQRing[chanType]))) + { + + /* Remove entry from internal ring mirroring + entries in Rx Free Q */ + /* Difference between ring and Q is that ring holds + pointers to buffers, not Rx Free Q entries */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + HssAccRxDpFreeQRing[chanType], freeQEntry); + + hssAccRxDatapathNumUserBuffersInRxSystem[chanType] --; + numEntries --; + *ppStartChainBuffer = (IX_OSAL_MBUF *) freeQEntry; + pCurrentBuffer = *ppStartChainBuffer; + } + while (!ICP_HSSACC_DATAPLANE_RING_EMPTY(HssAccRxDpFreeQRing[chanType])) + { + /* Remove entry from internal ring mirroring + entries in Rx Free Q */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + HssAccRxDpFreeQRing[chanType], + freeQEntry); + if (NULL == pCurrentBuffer) + { + ICP_HSSACC_REPORT_ERROR( + "HssAccRxDatapathServiceSpecificRxFreeEmpty - " + "Corrupted Internal Receive Free ring\n"); + status = ICP_STATUS_FATAL; + break; + } + + hssAccRxDatapathNumUserBuffersInRxSystem[chanType] --; + + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(pCurrentBuffer) = + (IX_OSAL_MBUF *) freeQEntry; + pCurrentBuffer = (IX_OSAL_MBUF *) freeQEntry; + } + } + + + *ppEndChainBuffer = pCurrentBuffer; + + + +if (ICP_HSSACC_RX_DP_SERVICE_MUTEX_UNLOCK(chanType) != + IX_SUCCESS) + { + if (chanType == ICP_HSSACC_CHAN_TYPE_VOICE) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxDatapathServiceSpecificRxFreeEmpty -" + " Mutex Unlock Error for " + "voice service\n"); + } + else + { + ICP_HSSACC_REPORT_ERROR("HssAccRxDatapathServiceSpecificRxFreeEmpty -" + " Mutex Unlock Error for " + "HDLC service\n"); + } + status = ICP_STATUS_MUTEX; + } + + +ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathServiceSpecificRxFreeEmpty\n"); +return status; +} + + + +/****************************************************************************** + * Abstract: + * Retrieve all buffers left in a specific service RxFree queue + * if this is the last channel + * + *****************************************************************************/ +icp_status_t +HssAccRxDatapathRxFreeEmpty(unsigned channelId, + icp_hssacc_channel_type_t chanType, + IX_OSAL_MBUF * * ppStartChainBuffer, + IX_OSAL_MBUF * * ppEndChainBuffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathRxFreeEmpty\n"); + + /* Are all channels disabled for this service? + (except for channelId) */ + if (HssAccRxDatapathServAllChansDisabledQuery(chanType, + channelId) == ICP_TRUE) + { + /* Retrieve rxfree and rx qIds for channel */ + if (chanType != ICP_HSSACC_CHAN_TYPE_HDLC && + chanType != ICP_HSSACC_CHAN_TYPE_VOICE) + { + status = ICP_STATUS_INVALID_PARAM; + } + else + { + status = HssAccRxDatapathServiceSpecificRxFreeEmpty( + chanType, + ppStartChainBuffer, + ppEndChainBuffer); + +/*unit test code uses ixQMgrWrite() directly - bypassing the + internal hssAcc counter*/ + if (ICP_STATUS_SUCCESS == status) + { + if (0 != hssAccRxDatapathNumUserBuffersInRxSystem[chanType]) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccRxDatapathRxFreeEmpty - " + "Tracked number of user buffers in rx system " + "(%d) != 0\n", + hssAccRxDatapathNumUserBuffersInRxSystem[chanType]); + } + } + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathRxFreeEmpty\n"); + + return status; +} + + +/****************************************************************************** + * Abstract: + * Retrieve all buffers in a chain from both Voice and HDLC Rx Free Qs where + * there are no channels enabled for the particular service + * + *****************************************************************************/ +icp_status_t +HssAccRxFreeQsBufsRetrieve(IX_OSAL_MBUF * * ppStartChainBuffer, + IX_OSAL_MBUF * * ppEndChainBuffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t chainStarted = ICP_FALSE; + IX_OSAL_MBUF * pStartChainRxFreeBuffer = NULL; + IX_OSAL_MBUF * pEndChainRxFreeBuffer = NULL; + int k = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxFreeQsBufsRetrieve "); + + for (k = 0; k < ICP_HSSACC_CHAN_TYPE_DELIMITER; k ++) + { + /* ICP_HSSACC_MAX_NUM_CHANNELS is used so the + internal check is on all channels of type k */ + if (HssAccRxDatapathServAllChansDisabledQuery( + k, + ICP_HSSACC_MAX_NUM_CHANNELS) + == ICP_TRUE) + { + pStartChainRxFreeBuffer = NULL; + pEndChainRxFreeBuffer = NULL; + + status = HssAccRxDatapathServiceSpecificRxFreeEmpty( + k, + &pStartChainRxFreeBuffer, + &pEndChainRxFreeBuffer); + + if (ICP_STATUS_SUCCESS == status) + { + if (NULL != pStartChainRxFreeBuffer) + { + if (ICP_TRUE == chainStarted) + { + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(*ppEndChainBuffer) + = pStartChainRxFreeBuffer; + } + else + { + *ppStartChainBuffer = pStartChainRxFreeBuffer; + } + *ppEndChainBuffer = pEndChainRxFreeBuffer; + + chainStarted = ICP_TRUE; + } + } + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxFreeQsBufsRetrieve\n"); + return status; +} + + +/****************************************************************************** + * Abstract: + * Retrieve all buffers in a chain from Rx Ring for a specified channel + * + *****************************************************************************/ +icp_status_t +HssAccRxDatapathChanBufsRetrieve(uint32_t channelId, + IX_OSAL_MBUF * * ppStartChainBuffer, + IX_OSAL_MBUF * * ppEndChainBuffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t numEntries = 0; + uint32_t entry = 0; + icp_hssacc_osal_mbuf_tdm_io_section_t *pMBufTdmIo = NULL; + IX_OSAL_MBUF * pCurrentBuffer = NULL; + icp_boolean_t chainStarted = ICP_FALSE; + icp_hssacc_channel_type_t chanType = ICP_HSSACC_CHAN_TYPE_DELIMITER; + IX_OSAL_MBUF * pStartChainRxFreeBuffer = NULL; + IX_OSAL_MBUF * pEndChainRxFreeBuffer = NULL; + + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccRxDatapathChanBufsRetrieve " + "for channel %d\n", + channelId); + + /* Process receive Q */ + chanType = HssAccChannelConfigTypeQuery(channelId); + + if (chanType != ICP_HSSACC_CHAN_TYPE_HDLC && + chanType != ICP_HSSACC_CHAN_TYPE_VOICE) + { + status = ICP_STATUS_INVALID_PARAM; + } + + if (status == ICP_STATUS_SUCCESS) + { + numEntries = + ICP_HSSACC_DATAPLANE_RING_NUM_ENTRIES_GET( + HssAccRxDpDescRing[channelId]); + + /* Special case for starting the Chain */ + if (numEntries != 0) + { + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccRxDatapathChanBufsRetrieve - " + "Start retrieving buffers\n"); + numEntries --; + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM(HssAccRxDpDescRing[channelId], + entry); + hssAccRxDatapathNumPendPkts[channelId] --; + hssAccRxDatapathNumUserBuffersInRxSystem[chanType] --; + + /* Entry is a pointer to TDM I/O Unit-specific + portion of an OSAL buffer, */ + pMBufTdmIo = + (icp_hssacc_osal_mbuf_tdm_io_section_t *) entry; + /* look up where start of buffer is */ + if (NULL == pMBufTdmIo) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxDatapathChanBufsRetrieve - " + "Corrupted Internal Receive ring\n"); + return ICP_STATUS_FATAL; + } + *ppStartChainBuffer = + ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo); + if (NULL == *ppStartChainBuffer) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxDatapathChanBufsRetrieve - " + "Corrupted Receive Entry\n"); + return ICP_STATUS_FATAL; + } + + pCurrentBuffer = *ppStartChainBuffer; + *ppEndChainBuffer = pCurrentBuffer; + chainStarted = ICP_TRUE; +#ifndef NDEBUG + hssAccRxNumPktsReceived[channelId] ++; +#endif + } + + } + + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccRxDatapathChanBufsRetrieve - " + "Create Chain with Rx'ed Buffers\n"); + + while (!ICP_HSSACC_DATAPLANE_RING_EMPTY(HssAccRxDpDescRing[channelId])) + { + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM(HssAccRxDpDescRing[channelId], + entry); + numEntries --; + hssAccRxDatapathNumPendPkts[channelId] --; + hssAccRxDatapathNumUserBuffersInRxSystem[chanType] --; + + /* Entry is a pointer to TDM I/O-specific portion + of an OSAL buffer, */ + pMBufTdmIo = + (icp_hssacc_osal_mbuf_tdm_io_section_t *) entry; + if (NULL == pMBufTdmIo) + { + ICP_HSSACC_REPORT_ERROR("HssAccRxDatapathChanBufsRetrieve" + " - Corrupted Internal Receive " + "ring\n"); + status = ICP_STATUS_FATAL; + break; + } + /* look up where start of buffer is */ + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(pCurrentBuffer) = + ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo); + + pCurrentBuffer = + ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pMBufTdmIo); +#ifndef NDEBUG + hssAccRxNumPktsReceived[channelId] ++; +#endif + } + *ppEndChainBuffer = pCurrentBuffer; + + } + + + if (ICP_STATUS_SUCCESS == status) + { + + /* Second Stage: If no channel left enabled for this service, + return all buffers in rx Free Q */ + /* Check if we started a chain previously or not */ + status = HssAccRxDatapathRxFreeEmpty(channelId, + chanType, + &pStartChainRxFreeBuffer, + &pEndChainRxFreeBuffer); + if (NULL != pStartChainRxFreeBuffer) + { + if (ICP_TRUE == chainStarted) + { + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(*ppEndChainBuffer) = + pStartChainRxFreeBuffer; + } + else + { + *ppStartChainBuffer = pStartChainRxFreeBuffer; + } + *ppEndChainBuffer = pEndChainRxFreeBuffer; + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccRxDatapathChanBufsRetrieve\n"); + + return status; +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_service.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_service.c new file mode 100644 index 0000000..71e0fbd --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_service.c @@ -0,0 +1,2579 @@ +/****************************************************************************** + * @file icp_hssacc_service.c + * + * @description Contents of this file provides the implementation of the + * HSS Service functions + * + * @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. + * Copyright(c) 2010,2011,2012 Avencall + * + * 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. + * + * BSD LICENSE + * + * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + * All rights reserved. + * Copyright(c) 2010,2011,2012 Avencall + * + * 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. + * + * + * + * + *****************************************************************************/ + +/* ---------------------------------------------------------------------------- + * Includes + * ---------------------------------------------------------------------------- + */ +#include "IxOsal.h" + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_port_config.h" +#include "icp_hssacc_channel_config.h" +#include "icp_hssacc_queues_config.h" +#include "icp_hssacc_channel_list.h" +#include "icp_hssacc_voice_bypass.h" +#include "icp_hssacc_timeslot_allocation.h" +#include "icp_hssacc_tx_datapath.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_rx_datapath.h" + + + +/* + * ---------------------------------------------------------------------------- + * Global variables + * ---------------------------------------------------------------------------- + */ +/* Mutex which controls access to control path functions */ +IxOsalMutex hssAccControlPathMutex; + +/* Flag to test whether the HssAcc component has been initialised or not. */ +TDM_PRIVATE icp_boolean_t serviceInitialised = ICP_FALSE; + +/* Stats */ +typedef struct icp_hssacc_service_stats_s +{ +/* Internal stats for Timer configuraton messaging */ + icp_hssacc_msg_with_resp_stats_t timerStat; + icp_hssacc_msg_with_resp_stats_t intStat; + icp_hssacc_msg_with_resp_stats_t abtAlnRead; + icp_hssacc_msg_with_resp_stats_t fcsMaxRead; + icp_hssacc_msg_with_resp_stats_t chanStatRead; + icp_hssacc_msg_with_resp_stats_t swErrRead; + icp_hssacc_msg_with_resp_stats_t swErrReset; +} icp_hssacc_service_stats_t; + +TDM_PRIVATE icp_hssacc_service_stats_t hssAccServStats; + +/* Data structure containing all registered callbacks + for all channels and ports */ +TDM_PRIVATE icp_hssacc_port_error_callback_t +hssAccPortErrorCb[ICP_HSSACC_MAX_NUM_PORTS][ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +TDM_PRIVATE icp_hssacc_error_callback_t +hssAccErrorCb[ICP_HSSACC_CHAN_TYPE_DELIMITER]; + + +TDM_PRIVATE icp_user_context_t +hssAccPortErrorCtxt[ICP_HSSACC_MAX_NUM_PORTS][ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +TDM_PRIVATE icp_user_context_t +hssAccErrorCtxt[ICP_HSSACC_CHAN_TYPE_DELIMITER]; + +TDM_PRIVATE uint32_t +hssAccStaticErrorBitmask = 0; + +TDM_PRIVATE icp_boolean_t voiceIntEnabled = ICP_FALSE; +TDM_PRIVATE icp_boolean_t hdlcIntEnabled = ICP_FALSE; + +/* + * ---------------------------------------------------------------------------- + * Function definitions + * ---------------------------------------------------------------------------- + */ +TDM_PRIVATE icp_status_t +HssAccTdmIOUnitErrorMhCbRegister (IxPiuMhCallback callback); + +void +HssAccTdmIOUnitErrorCallback(IxPiuMhPiuId piuId, IxPiuMhMessage message); + +void +HssAccPortErrorDummyClientCb (icp_user_context_t userContext, + icp_hssacc_port_error_t errorType); + +void +HssAccErrorDummyClientCb (icp_user_context_t userContext, + icp_hssacc_error_t errorType); + +TDM_PRIVATE icp_status_t +HssAccTdmIOErrorStatsShow (void); + +TDM_PRIVATE icp_status_t +HssAccSwErrorStatsShow (void); + +TDM_PRIVATE icp_status_t +HssAccSwErrorStatsReset (void); + +TDM_PRIVATE icp_status_t +HssAccChannelTdmIOErrorStatsShow(unsigned channelId); + +TDM_PRIVATE icp_status_t +HssAccChannelTdmIOErrorStatsReset(unsigned channelId); + +TDM_PRIVATE void +HssAccServiceStatsReset (void); + +TDM_PRIVATE void +HssAccServiceStatsShow (void); + +TDM_PRIVATE icp_status_t +HssAccServiceIntGenUpdate (void); + +/***************************************************************************** + * Abstract: + * Sets up the Dual coprocessor instructions in the TDM I/O Unit + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccTdmUnitDualInstSet (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t appDualId = 0; + IxPiuDlAppDualInstruction appDualInstruction; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmUnitDualInstSet\n"); + +#if defined(__ep805xx) + appDualInstruction.copr0 = ICP_HSSACC_TDM_IO_UNIT_CPP_COPROC; + appDualInstruction.inst0 = ICP_HSSACC_TDM_IO_UNIT_CPP_RD_WORD_INST; + appDualInstruction.copr1 = ICP_HSSACC_TDM_IO_UNIT_SDC_COPROC; + appDualInstruction.inst1 = ICP_HSSACC_TDM_IO_UNIT_SDC_WR_HDLC_INST; + status = ixPiuDlAppDualSet ( + IX_PIUDL_PIUID_PIU0, + appDualId, + &appDualInstruction); + if ( ICP_STATUS_SUCCESS != status ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmUnitDualInstSet - " + "Failed to set Application " + "specific dual in TDM I/O Unit\n"); + + return ICP_STATUS_FATAL; + } + + appDualId++; + appDualInstruction.copr0 = ICP_HSSACC_TDM_IO_UNIT_SDC_COPROC; + appDualInstruction.inst0 = ICP_HSSACC_TDM_IO_UNIT_SDC_RD_HDLC_INST; + appDualInstruction.copr1 = ICP_HSSACC_TDM_IO_UNIT_CPP_COPROC; + appDualInstruction.inst1 = ICP_HSSACC_TDM_IO_UNIT_CPP_WR_WORD_INST; + + status = ixPiuDlAppDualSet ( + IX_PIUDL_PIUID_PIU0, + appDualId, + &appDualInstruction); + if ( ICP_STATUS_SUCCESS != status ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmUnitDualInstSet - " + "Failed to set Application " + "specific dual in TDM I/O Unit\n"); + + return ICP_STATUS_FATAL; + } + + + appDualId++; + appDualInstruction.copr0 = ICP_HSSACC_TDM_IO_UNIT_CPP_COPROC; + appDualInstruction.inst0 = ICP_HSSACC_TDM_IO_UNIT_CPP_RD_WORD_INST; + appDualInstruction.copr1 = ICP_HSSACC_TDM_IO_UNIT_SDC_COPROC; + appDualInstruction.inst1 = ICP_HSSACC_TDM_IO_UNIT_SDC_WR_VOICE_INST; + status = ixPiuDlAppDualSet ( + IX_PIUDL_PIUID_PIU0, + appDualId, + &appDualInstruction); + if ( ICP_STATUS_SUCCESS != status ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmUnitDualInstSet - " + "Failed to set Application " + "specific dual in TDM I/O Unit\n"); + + return ICP_STATUS_FATAL; + } + + appDualId++; + appDualInstruction.copr0 = ICP_HSSACC_TDM_IO_UNIT_SDC_COPROC; + appDualInstruction.inst0 = ICP_HSSACC_TDM_IO_UNIT_SDC_RD_VOICE_INST; + appDualInstruction.copr1 = ICP_HSSACC_TDM_IO_UNIT_CPP_COPROC; + appDualInstruction.inst1 = ICP_HSSACC_TDM_IO_UNIT_CPP_WR_WORD_INST; + + status = ixPiuDlAppDualSet ( + IX_PIUDL_PIUID_PIU0, + appDualId, + &appDualInstruction); + if ( ICP_STATUS_SUCCESS != status ) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmUnitDualInstSet - " + "Failed to set Application " + "specific dual in TDM I/O Unit\n"); + + return ICP_STATUS_FATAL; + } + + +#endif + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmUnitDualInstSet\n"); + return status; +} + + + +/****************************************************************************** + * Abstract: + * Initializes the HSS I/O Access library for the HSS TDM I/O Unit. + * This function is responsible for initialising resources for use by + * this component. It should be called before any other HSS Access + * function is called. Default values for configuration items affecting + * all ports will not be set-up; it is up to the client to call the + * relevant port configuration functions before enabling the port. + * + * + *****************************************************************************/ +icp_status_t +icp_HssAccInit(void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned index = 0; + IxPiuMhMessage message; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccInit\n"); + + /* Check if component is already initialised */ + if (ICP_TRUE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "component has already been initialised\n"); + + status = ICP_STATUS_FAIL; + } + else /* component has never been initialised */ + { + /* Initialise the Service Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_INIT()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "failed to initialise HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + if (status == ICP_STATUS_SUCCESS) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + HssAccServiceStatsReset(); + + if(ICP_STATUS_SUCCESS == status) + { + if( (ICP_STATUS_SUCCESS == HssAccTdmUnitDualInstSet() ) && + (ICP_STATUS_SUCCESS == HssAccPortConfigInit()) && + (ICP_STATUS_SUCCESS == HssAccChannelConfigInit()) && + (ICP_STATUS_SUCCESS == HssAccQueuesInit() ) && + (ICP_STATUS_SUCCESS == HssAccTxDatapathInit()) && + (ICP_STATUS_SUCCESS == HssAccRxDatapathInit()) && + (ICP_STATUS_SUCCESS == HssAccTdmIOUnitErrorMhCbRegister + (HssAccTdmIOUnitErrorCallback) )) + { + HssAccVoiceBypassInit(); + + /* Reset all Error Callbacks for the component, + port Error Callbacks and service Errors callbacks */ + for (index =0; index < ICP_HSSACC_MAX_NUM_PORTS; index ++) + { + hssAccPortErrorCb[index][ICP_HSSACC_CHAN_TYPE_VOICE] = + HssAccPortErrorDummyClientCb; + hssAccPortErrorCtxt[index][ICP_HSSACC_CHAN_TYPE_VOICE] = + (icp_user_context_t)index; + hssAccPortErrorCb[index][ICP_HSSACC_CHAN_TYPE_HDLC] = + HssAccPortErrorDummyClientCb; + hssAccPortErrorCtxt[index][ICP_HSSACC_CHAN_TYPE_HDLC] = + (icp_user_context_t)index; + } + hssAccErrorCb[ICP_HSSACC_CHAN_TYPE_VOICE] = + HssAccErrorDummyClientCb; + hssAccErrorCb[ICP_HSSACC_CHAN_TYPE_HDLC] = + HssAccErrorDummyClientCb; + hssAccErrorCtxt[ICP_HSSACC_CHAN_TYPE_VOICE] = + (icp_user_context_t)ICP_HSSACC_CHAN_TYPE_VOICE; + hssAccErrorCtxt[ICP_HSSACC_CHAN_TYPE_HDLC] = + (icp_user_context_t)ICP_HSSACC_CHAN_TYPE_HDLC; + } + else + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - one or more " + "modules failed to initialise\n"); + + status = HssAccPortConfigShutdown(); + status = HssAccChannelConfigShutdown(); + status = HssAccQueuesShutdown(); + status = HssAccTxDatapathShutdown(); + status = HssAccRxDatapathShutdown(); + /* This will deregister the Callback */ + status = HssAccTdmIOUnitErrorMhCbRegister(NULL); + status = ICP_STATUS_FAIL; + } + } + /* Last Step enable notifications with the QMgr + for the Receive Side */ + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_STATUS_SUCCESS == HssAccRxQueuesNotificationEnable()) + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccInit - Service has " + "successfully initialised\n"); + hssAccStaticErrorBitmask = 0; + serviceInitialised = ICP_TRUE; + } + else + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "failed notification enable\n"); + status = HssAccVoiceBypassShutdown(); + status = HssAccPortConfigShutdown(); + status = HssAccChannelConfigShutdown(); + status = HssAccQueuesShutdown(); + status = HssAccTxDatapathShutdown(); + status = HssAccRxDatapathShutdown(); + /* This will deregister the Callback */ + status = HssAccTdmIOUnitErrorMhCbRegister(NULL); + status = ICP_STATUS_FAIL; + } + } + /* Set the Timer interval for the TDM I/O Unit to enable the Unit */ + if (ICP_STATUS_SUCCESS == status) + { + /* Construct the message to configure the queue */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_CFG, + 0, + 0, + 0, + ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_INTERVAL, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + if (ICP_STATUS_SUCCESS == + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_CFG_RESPONSE, + &(hssAccServStats.timerStat), + NULL) ) + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccInit - Timer Interval " + "Set\n"); + } + else + { + + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "failed Timer Interval Set\n"); + status = HssAccVoiceBypassShutdown(); + status = HssAccPortConfigShutdown(); + status = HssAccChannelConfigShutdown(); + status = HssAccQueuesShutdown(); + status = HssAccTxDatapathShutdown(); + status = HssAccRxDatapathShutdown(); + /* This will deregister the Callback */ + status = HssAccTdmIOUnitErrorMhCbRegister(NULL); + status = ICP_STATUS_FAIL; + } + } + + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + } + + + if (status != ICP_STATUS_SUCCESS) + { + /* report the error */ + ICP_HSSACC_REPORT_ERROR ("icp_HssAccInit - " + "failed to initialise HssAcc\n"); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccInit\n"); + + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Initialises the HDLC service specific part of the TDM I/O Unit: + * max frame size and whether to generate interrupts for HDLC data or not + * + *****************************************************************************/ +icp_status_t +icp_HssAccHdlcInit(unsigned maxRxFrameSize, + icp_boolean_t intGenerationEnable) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccHdlcInit\n"); + + /* Check if component is initialised */ + if (ICP_TRUE != serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccHdlcInit - " + "component has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + else + { + if (0 == maxRxFrameSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccHdlcInit - " + "Max Rx Frame Size cannot be 0\n"); + status = ICP_STATUS_INVALID_PARAM; + } + else + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccHdlcInit - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + + else + { + if (ICP_TRUE == intGenerationEnable) + { + hdlcIntEnabled = ICP_TRUE; + status = HssAccServiceIntGenUpdate(); + } + HssAccRxDatapathHdlcInit(maxRxFrameSize); + + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccHdlcInit - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + } + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccHdlcInit\n"); + + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Setup the Voice service on the TDM I/O unit. provides is with the + * max receive frame size and whether to generate interrupts for Voice + * traffic or not. + * + *****************************************************************************/ +icp_status_t +icp_HssAccVoiceInit(unsigned maxRxFrameSize, + icp_boolean_t intGenerationEnable) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccVoiceInit\n"); + + /* Check if component is already been initialised */ + if (ICP_TRUE != serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceInit - " + "component has not been initialised\n"); + + status = ICP_STATUS_FAIL; + } + else + { + if (0 == maxRxFrameSize) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceInit - " + "Max Rx Frame Size cannot be 0\n"); + status = ICP_STATUS_INVALID_PARAM; + } + else + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceInit - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + if (ICP_TRUE == intGenerationEnable) + { + voiceIntEnabled = ICP_TRUE; + status = HssAccServiceIntGenUpdate(); + } + HssAccRxDatapathVoiceInit(maxRxFrameSize); + + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceInit - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + } + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccVoiceInit\n"); + + return status; +} + + + + +/****************************************************************************** + * Abstract: Shutdown the HSS I/O Access Library including all its sub-modules + * + *****************************************************************************/ +icp_status_t +icp_HssAccShutdown (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccShutdown\n"); + + /* If the service hasnt already been initialised then + we dont need to do anything */ + if (ICP_FALSE == serviceInitialised ) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccShutdown - " + "the service is not initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccShutdown - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + voiceIntEnabled = ICP_FALSE; + hdlcIntEnabled = ICP_FALSE; + status = HssAccServiceIntGenUpdate(); + /* Shutdown Tx and Rx datapath sub-components + Tx: buffers in the tx queues will be sent before being freed + Rx: buffers in the rx queue will be freed and not sent to the client + */ + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccPortConfigShutdown(); + } + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccChannelConfigShutdown(); + } + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccQueuesShutdown(); + } + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccVoiceBypassShutdown(); + } + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccTxDatapathShutdown (); + } + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccRxDatapathShutdown (); + } + if (ICP_STATUS_SUCCESS == status) + { + /* This will deregister the Callback */ + status = HssAccTdmIOUnitErrorMhCbRegister(NULL); + } + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccShutdown - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + /* Destroy HssAcc Mutex */ + if (ICP_STATUS_SUCCESS == status) + { + status = ICP_HSSACC_MUTEX_DESTROY(); + } + serviceInitialised = ICP_FALSE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccShutdown\n"); + return status; +} + + + +/****************************************************************************** + * Abstract: register data callbacks for a channel + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelCallbacksRegister ( + unsigned channelId, + icp_user_context_t userContext, + icp_hssacc_rx_callback_t rxCallback, + icp_hssacc_tx_done_callback_t txDoneCallback) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelCallbacksRegister\n"); + + /* If the service hasnt been initialised, report an error */ + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelCallbacksRegister - " + "Service has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelCallbacksRegister - " + "Channel Id is not valid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + if (ICP_STATUS_SUCCESS == status) + { + if ((NULL == rxCallback) || + (NULL == txDoneCallback)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelCallbacksRegister - " + "Callback function pointers invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + /* save the callbacks to an internal structure so that + the datapath can use them */ + if (ICP_STATUS_SUCCESS == status) + { + HssAccChannelRxCallbackRegister(channelId, rxCallback, userContext); + HssAccTxDatapathChanTxDoneCallbackRegister(channelId, + txDoneCallback, + userContext); + } + return status; + +} + + + + +/****************************************************************************** + * Abstract: register Error callbacks for a channel + *****************************************************************************/ +icp_status_t +icp_HssAccErrorCallbackRegister (icp_hssacc_channel_type_t channelType, + icp_user_context_t userContext, + icp_hssacc_error_callback_t errorCallback) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccErrorCallbackRegister\n"); + + /* If the service hasnt already been initialised then + we dont need to do anything */ + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccErrorCallbackRegister - " + "Service has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if ((NULL == errorCallback) || + (ICP_HSSACC_ENUM_INVALID (channelType, + ICP_HSSACC_CHAN_TYPE_DELIMITER))) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccErrorCallbackRegister - " + "one or more parameters invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + if (ICP_STATUS_SUCCESS == status) + { + hssAccErrorCb[channelType] = errorCallback; + hssAccErrorCtxt[channelType] = userContext; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccErrorCallbackRegister\n"); + return status; +} + + + + + +/****************************************************************************** + * Abstract: + * Service the datapath, Rx and Tx + * + *****************************************************************************/ +icp_status_t +icp_HssAccDataPathService (icp_hssacc_channel_type_t channelType) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccDataPathService\n"); +#ifndef NDEBUG + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccDataPathService - " + "service is not initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_ENUM_INVALID(channelType, ICP_HSSACC_CHAN_TYPE_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccDataPathService - " + "invalid Type to service\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } +#endif + if (ICP_STATUS_SUCCESS == status) + { + /* Service Tx Direction */ + status = HssAccTxDatapathService(channelType); + } + if (ICP_STATUS_SUCCESS == status) + { + /* Service Rx Direction */ + status = HssAccRxDatapathService(channelType); + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccDataPathService\n"); + return status; +} + + + + +/****************************************************************************** + * Abstract: + * Retrive all the buffers in the TDM I/O unit associated with the + * specified channel. will call Rx and Tx sub-modules. If channelId is + * equal to ICP_HSSACC_MAX_NUM_CHANNELS then retrieve buffers from the + * rx free queues for any service which has all unitialized channels. + * + *****************************************************************************/ +icp_status_t +icp_HssAccAllBuffersRetrieve (unsigned channelId, + IX_OSAL_MBUF * * buffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + IX_OSAL_MBUF * pEndChainBuffer = NULL; + IX_OSAL_MBUF * pTmpBuffer = NULL; + IX_OSAL_MBUF * pTmpEndChainBuffer = NULL; + icp_hssacc_channel_state_t channelState = ICP_HSSACC_CHANNEL_UNINITIALISED; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccAllBuffersRetrieve\n"); + + if (ICP_TRUE != serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccAllBuffersRetrieve - " + "service is not initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + /* channelId == ICP_HSSACC_MAX_NUM_CHANNELS is allowed */ + if (ICP_HSSACC_MAX_NUM_CHANNELS < channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccAllBuffersRetrieve - " + "Channel Id Invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if (NULL == buffer) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccAllBuffersRetrieve - " + "Buffer Pointer Invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccAllBuffersRetrieve - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + + if (ICP_HSSACC_MAX_NUM_CHANNELS != channelId) + { + /* Check that the channel is not enabled first */ + channelState = HssAccChannelConfigStateQuery(channelId); + + if (ICP_HSSACC_CHANNEL_ENABLED == channelState + || ICP_HSSACC_CHANNEL_DOWN_TRANSITION == channelState) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccAllBuffersRetrieve - " + "Channel is enabled\n"); + status = ICP_STATUS_RESOURCE; + } + } + } + } + + + if (status == ICP_STATUS_SUCCESS) + { + + *buffer = NULL; + + if (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + if (ICP_STATUS_SUCCESS == status) + { + /* Retrieve Tx Datapath Buffers Chain containing all leftover + TxDones and submitted Tx buffers that werent transmitted */ + status = HssAccTxDatapathChannelBuffersRetrieve( + channelId, + buffer, + &pTmpEndChainBuffer); + } + + if (status == ICP_STATUS_SUCCESS) + { + /* Retrieve Rx Datapath Buffer Chain */ + status = HssAccRxDatapathChanBufsRetrieve(channelId, + &pTmpBuffer, + &pEndChainBuffer); + } + } + else + { + /* Retrieve Rx Free Q Buffer Chain(s) */ + status = HssAccRxFreeQsBufsRetrieve(&pTmpBuffer, + &pEndChainBuffer); + } + } + + + if (status == ICP_STATUS_SUCCESS) + { + if (*buffer != NULL) + { + if (pTmpBuffer != NULL) + { + /* Link two chains together */ + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(pTmpEndChainBuffer) = + pTmpBuffer; + } + } + else if (pTmpBuffer != NULL) + { + /* Rx datapath or free queue buffers were retrieved so + operation succeeded */ + *buffer = pTmpBuffer; + } + + /* Notify Channel Config of success */ + if (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + HssAccChannelConfigBuffersClearedNotify(channelId); + } + } + + + if (ICP_TRUE == mutexLocked) + { + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccAllBuffersRetrieve - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccAllBuffersRetrieve\n"); + return status; +} + + + + +/****************************************************************************** + * Abstract: + * saves the provided callback for the specified port and service. + * + *****************************************************************************/ +icp_status_t +icp_HssAccPortErrorCallbackRegister ( + unsigned portId, + icp_hssacc_channel_type_t channelType, + icp_user_context_t userContext, + icp_hssacc_port_error_callback_t portErrorCallback) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccPortErrorCallbackRegister\n"); + + if (ICP_TRUE != serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortErrorCallbackRegister - " + "service is not initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if ((ICP_HSSACC_MAX_NUM_PORTS <= portId) || + ICP_HSSACC_ENUM_INVALID (channelType, + ICP_HSSACC_CHAN_TYPE_DELIMITER)) + { + ICP_HSSACC_REPORT_ERROR_2 ("icp_HssAccPortErrorCallbackRegister - " + "Invalid parameter portId %u for " + "service %u\n", + portId, + channelType); + status = ICP_STATUS_INVALID_PARAM; + } + + if (NULL == portErrorCallback) + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccPortErrorCallbackRegister - " + "Invalid callback provided 0x%08X\n", + (uint32_t)portErrorCallback); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + hssAccPortErrorCb[portId][channelType] = portErrorCallback; + hssAccPortErrorCtxt[portId][channelType] = userContext; + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortErrorCallbackRegister\n"); + return status; +} + + + +/***************************************************************************** + * Abstract: + * display all stats within this Access module and the TDM I/O unit. + * + *****************************************************************************/ +void +icp_HssAccStatsShow (void) +{ + unsigned channelId = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_channel_type_t channelType = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccStatsShow\n"); + + /* If the service hasnt already been initialised then we dont + need to do anything */ + if (ICP_TRUE == serviceInitialised) + { + HssAccPortConfigStatsShow(); + HssAccQueuesConfigStatsShow(); + HssAccChannelConfigStatsShow(); + HssAccTsAllocStatsShow(); + HssAccBypassStatsShow(); + + while ((ICP_STATUS_SUCCESS == status ) && + (channelId < ICP_HSSACC_MAX_NUM_CHANNELS)) + { + status = icp_HssAccChannelStatsShow(channelId); + channelId ++; + } + while ((ICP_STATUS_SUCCESS == status ) && + (channelType < ICP_HSSACC_CHAN_TYPE_DELIMITER)) + { + HssAccRxDatapathReplenishStatsShow(channelType); + channelType ++; + } + HssAccServiceStatsShow(); + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccStatsShow\n"); + +} + + + +/***************************************************************************** + * Abstract: + * Reset all internal stats. + * + *****************************************************************************/ +void +icp_HssAccStatsReset (void) +{ + unsigned channelId = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_channel_type_t channelType = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccStatsReset\n"); + + /* If the service hasnt already been initialised then we dont + need to do anything */ + if (ICP_TRUE == serviceInitialised) + { + HssAccPortConfigStatsReset(); + HssAccQueuesConfigStatsReset(); + HssAccChannelConfigStatsReset(); + HssAccTsAllocStatsReset(); + HssAccBypassStatsReset(); + + while ((ICP_STATUS_SUCCESS == status ) && + (channelId < ICP_HSSACC_MAX_NUM_CHANNELS)) + { + status = icp_HssAccChannelStatsReset(channelId); + channelId ++; + } + while ((ICP_STATUS_SUCCESS == status ) && + (channelType < ICP_HSSACC_CHAN_TYPE_DELIMITER)) + { + HssAccRxDatapathReplenishStatsReset(channelType); + channelType ++; + } + if (ICP_STATUS_SUCCESS == status) + { + /* Also reset here the Sw Error Stats from the TDM IO Unit */ + status = HssAccSwErrorStatsReset (); + } + HssAccServiceStatsReset(); + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccStatsReset\n"); + +} + + + +/***************************************************************************** + * Abstract: + * display all stats relating to the specified channel + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelStatsShow (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelStatsShow\n"); + + /* If the service hasnt already been initialised then we dont + need to do anything */ + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelStatsShow - " + "Service has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelStatsShow - " + "channel number is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + HssAccChannelConfigStateShow (channelId); + HssAccTxDatapathChanStatsShow(channelId); + HssAccRxDatapathChanStatsShow(channelId); + + + if (ICP_STATUS_SUCCESS != HssAccChannelTdmIOErrorStatsShow(channelId)) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccChannelStatsShow - Error " + "retrieving Stats from TDM I/O Unit\n"); + status = ICP_STATUS_RESOURCE; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelStatsShow\n"); + return status; +} + + + +/***************************************************************************** + * Abstract: + * reset all the stats relating to the specified channel. + * + *****************************************************************************/ +icp_status_t +icp_HssAccChannelStatsReset (unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_boolean_t mutexLocked = ICP_FALSE; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccChannelStatsReset\n"); + + /* If the service hasnt already been initialised then we + dont need to do anything */ + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelStatsReset - " + "Service has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelStatsReset - " + "channel number is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelStatsReset - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + } + if (ICP_STATUS_SUCCESS == status) + { + /* Reset the Datapath Stats for this channel */ + HssAccTxDatapathChanStatsReset(channelId); + HssAccRxDatapathChanStatsReset(channelId); + + if (ICP_STATUS_SUCCESS != HssAccChannelTdmIOErrorStatsReset(channelId)) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccChannelStatsShow - Error " + "retrieving Stats from TDM I/O Unit\n"); + status = ICP_STATUS_RESOURCE; + } + + } + if (mutexLocked == ICP_TRUE) + { + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccChannelStatsReset - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccChannelStatsReset\n"); + return status; +} + + + +/***************************************************************************** + * Abstract: + * show all the stats relating to the specified port, this includes + * all the channels associated to timeslots on this port. + * + *****************************************************************************/ +icp_status_t +icp_HssAccPortStatsShow (unsigned portId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned channelId = ICP_HSSACC_MAX_NUM_CHANNELS; + icp_hssacc_tdm_io_unit_channel_list_t listId = + ICP_HSSACC_TDM_IO_UNIT_LIST_TX_PRIMARY; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccPortStatsShow\n"); + + /* If the service hasnt already been initialised then we dont + need to do anything */ + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortStatsShow - " + "Service has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + /* Check Port Number */ + if (portId >= ICP_HSSACC_MAX_NUM_PORTS) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortStatsShow - " + "port number is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if (ICP_STATUS_SUCCESS == status) + { + /* For each port, the channels to be processed are split + into 3 lists for the TDM I/O Unit. + Show the channels in each list */ + channelId = HssAccChannelListLastPortChannelGet (portId, + listId); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channels on the Primary List for port %u:\n", + portId, + 0, 0, 0, 0, 0); + while (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + icp_HssAccChannelStatsShow(channelId); + channelId = HssAccChannelListPrevChannelOnListGet(channelId); + } + + } + /* Repeat for the Secondary 0 list */ + if (ICP_STATUS_SUCCESS == status) + { + listId = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_0; + channelId = HssAccChannelListLastPortChannelGet (portId, + listId); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channels on the Secondary 0 List for port %u:\n", + portId, + 0, 0, 0, 0, 0); + while (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + icp_HssAccChannelStatsShow(channelId); + channelId = HssAccChannelListPrevChannelOnListGet(channelId); + } + + } + + /* Repeat for the Secondary 1 list */ + if (ICP_STATUS_SUCCESS == status) + { + listId = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_1; + channelId = HssAccChannelListLastPortChannelGet (portId, + listId); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channels on the Secondary 1 List for port %u:\n", + portId, + 0, 0, 0, 0, 0); + while (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + icp_HssAccChannelStatsShow(channelId); + channelId = HssAccChannelListPrevChannelOnListGet(channelId); + } + + + /* Also print out here the Sw Error Stats from the TDM IO Unit */ + status = HssAccSwErrorStatsShow (); + } + + if (ICP_STATUS_SUCCESS == status) + { + + /* And overall stats for Abt, Aln, FCS and Max pkt size errors */ + status = HssAccTdmIOErrorStatsShow (); + } + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortStatsShow\n"); + return status; + +} + + + + +/***************************************************************************** + * Abstract: + * reset all the stats relating to the specified port, this includes + * resting all the stats for channels on this port. + * + *****************************************************************************/ +icp_status_t +icp_HssAccPortStatsReset (unsigned portId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned channelId = ICP_HSSACC_MAX_NUM_CHANNELS; + icp_hssacc_tdm_io_unit_channel_list_t listId = + ICP_HSSACC_TDM_IO_UNIT_LIST_TX_PRIMARY; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccPortStatsReset\n"); + + + /* If the service hasnt already been initialised then we dont + need to do anything */ + if (ICP_FALSE == serviceInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortStatsReset - " + "Service has not been initialised\n"); + status = ICP_STATUS_FAIL; + } + + /* Check Port Number */ + if (portId >= ICP_HSSACC_MAX_NUM_PORTS) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccPortStatsReset - " + "port number is invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* For each port, the channels to be processed are split + into 3 lists for the TDM I/O Unit. + Show the channels in each list */ + channelId = HssAccChannelListLastPortChannelGet (portId, + listId); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channels on the Primary List for port %u:\n", + portId, + 0, 0, 0, 0, 0); + while (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + icp_HssAccChannelStatsReset(channelId); + channelId = HssAccChannelListPrevChannelOnListGet(channelId); + } + + } + /* Repeat for the Secondary 0 list */ + if (ICP_STATUS_SUCCESS == status) + { + listId = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_0; + channelId = HssAccChannelListLastPortChannelGet (portId, + listId); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channels on the Secondary 0 List for port %u:\n", + portId, + 0, 0, 0, 0, 0); + while (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + icp_HssAccChannelStatsReset(channelId); + channelId = HssAccChannelListPrevChannelOnListGet(channelId); + } + + } + + /* Repeat for the Secondary 1 list */ + if (ICP_STATUS_SUCCESS == status) + { + listId = ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_1; + channelId = HssAccChannelListLastPortChannelGet (portId, + listId); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Channels on the Secondary 1 List for port %u:\n", + portId, + 0, 0, 0, 0, 0); + while (ICP_HSSACC_MAX_NUM_CHANNELS > channelId) + { + icp_HssAccChannelStatsReset(channelId); + channelId = HssAccChannelListPrevChannelOnListGet(channelId); + } + } + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccPortStatsReset\n"); + return status; + +} + + + +/***************************************************************************** + * Abstract: + * return the number of channels supported by the TDM I/O unit. + * + *****************************************************************************/ +unsigned +icp_HssAccNumSupportedChannelsGet ( void ) +{ + return ICP_HSSACC_MAX_NUM_CHANNELS; +} + + + + +/***************************************************************************** + * Abstract: + * register the HSS I/O Access callback with the Message Handler. + * + *****************************************************************************/ +icp_status_t +HssAccTdmIOUnitErrorMhCbRegister (IxPiuMhCallback callback) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOUnitErrorMhCbRegister\n"); + if (ICP_STATUS_SUCCESS != + ixPiuMhUnsolicitedCallbackRegister ( + IX_PIUMH_PIUID_PIU0, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_STATUS, + callback)) + { + + ICP_HSSACC_REPORT_ERROR ("HssAccTdmIOUnitErrorMhCbRegister - " + "Could not register callback\n"); + status = ICP_STATUS_FAIL; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOUnitErrorMhCbRegister\n"); + + return status; +} + + +/***************************************************************************** + * Abstract: + * this is the callback that the Message Handler will call when it + * receives an error message from the TDM I/O unit. + * + *****************************************************************************/ +void +HssAccTdmIOUnitErrorCallback(IxPiuMhPiuId piuId, IxPiuMhMessage message) +{ + uint32_t localBitmask = 0; + uint32_t portBitmask = 0; + unsigned portId = ICP_HSSACC_MAX_NUM_PORTS; + icp_hssacc_port_error_t portError = ICP_HSSACC_PORT_ERROR_TX_LOS; + uint32_t errorOffset = 0; + icp_hssacc_error_t errorType = ICP_HSSACC_ERROR_DELIMITER; + icp_boolean_t bothServices = ICP_FALSE; + icp_hssacc_channel_type_t service = ICP_HSSACC_CHAN_TYPE_DELIMITER; + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOUnitErrorCallback 0x%08X 0x%08X\n", + message.data[0], + message.data[1]); + + + if ((IX_PIUMH_PIUID_PIU0 != piuId) || + ((message.data[0] >> ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET) != + (ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_STATUS))) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmIOUnitErrorCallback - " + "Invalid parameters\n"); + } + else + { + /* First check if we have any port errors */ + localBitmask = + message.data[0] & ICP_HSSACC_TDM_IO_UNIT_ERR_ALL_PORT_MASK; + if (0 != localBitmask) + { + /* determine which port error triggered this message */ + portId = 0; + while (0 != localBitmask) + { + portBitmask = localBitmask & + ICP_HSSACC_TDM_IO_UNIT_ERR_SGLE_PORT_MASK; + if (0 != portBitmask) + { + while ((portBitmask & 1) != 1) + { + portBitmask >>= 1; + portError ++; + } + ICP_HSSACC_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccTdmIOUnitErrorCallback - " + "Error Reported on port %u\n", + portId); + /* use the client callbacks */ + hssAccPortErrorCb[portId][ICP_HSSACC_CHAN_TYPE_HDLC]( + hssAccPortErrorCtxt[portId][ICP_HSSACC_CHAN_TYPE_HDLC], + portError); + + hssAccPortErrorCb[portId][ICP_HSSACC_CHAN_TYPE_VOICE]( + hssAccPortErrorCtxt[portId][ICP_HSSACC_CHAN_TYPE_VOICE], + portError); + } + localBitmask >>= ICP_HSSACC_TDM_IO_UNIT_NEXT_PORT_SHIFT; + portId ++; + } + } + + + /* now check for a software error triggering this message; + compare the bitmask sent with our static one */ + localBitmask = message.data[1]; + if ((0 != localBitmask) && + (hssAccStaticErrorBitmask != localBitmask)) + { + while ((localBitmask & 1) == (hssAccStaticErrorBitmask & 1)) + { + localBitmask >>= 1; + hssAccStaticErrorBitmask >>= 1; + errorOffset ++; + } + switch (errorOffset) + { + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_MSG_OUT_FIFO_H: + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_MSG_OUT_FIFO_L: + errorType = ICP_HSSACC_ERROR_MESSAGE_FIFO_OVERFLOW; + bothServices = ICP_TRUE; + break; + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_V_FREE_UNDERF: + errorType = ICP_HSSACC_ERROR_RX_FREE_UNDERFLOW; + service = ICP_HSSACC_CHAN_TYPE_VOICE; + break; + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_H_FREE_UNDERF: + errorType = ICP_HSSACC_ERROR_RX_FREE_UNDERFLOW; + service = ICP_HSSACC_CHAN_TYPE_HDLC; + break; + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_V_INT_FIFO_OVERF: + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_V_Q_OVERF: + errorType = ICP_HSSACC_ERROR_RX_OVERFLOW; + service = ICP_HSSACC_CHAN_TYPE_VOICE; + break; + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_H_INT_FIFO_OVERF: + case ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_H_Q_OVERF: + errorType = ICP_HSSACC_ERROR_RX_OVERFLOW; + service = ICP_HSSACC_CHAN_TYPE_HDLC; + break; + default: + ICP_HSSACC_REPORT_ERROR ("HssAccTdmIOUnitErrorCallback - " + "Unknown Software Error " + "from TDM I/O Unit\n"); + status = ICP_STATUS_FAIL; + break; + + } + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTdmIOUnitErrorCallback - " + "Firmware Error Reported\n"); + if (ICP_TRUE == bothServices) + { + hssAccErrorCb[ICP_HSSACC_CHAN_TYPE_HDLC]( + hssAccErrorCtxt[ICP_HSSACC_CHAN_TYPE_HDLC], + errorType); + hssAccErrorCb[ICP_HSSACC_CHAN_TYPE_VOICE]( + hssAccErrorCtxt[ICP_HSSACC_CHAN_TYPE_VOICE], + errorType); + } + else + { + hssAccErrorCb[service](hssAccErrorCtxt[service], + errorType); + } + hssAccStaticErrorBitmask = message.data[1]; + } + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOUnitErrorCallback\n"); +} + + + +/***************************************************************************** + * Abstract: + * this is a dummy callback used in the event of the client never + * registering its own for a port error + * + *****************************************************************************/ +void HssAccPortErrorDummyClientCb (icp_user_context_t userContext, + icp_hssacc_port_error_t errorType) +{ + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "HssAccPortErrorDummyClientCb - received " + "notification of Port error %u for service %u\n", + errorType, + (unsigned)userContext); +} + + + +/***************************************************************************** + * Abstract: + * this is a dummy callback used in the event of the client never + * registering its own for a TDM I/O Unit firmware error. + * + *****************************************************************************/ +void HssAccErrorDummyClientCb (icp_user_context_t userContext, + icp_hssacc_error_t errorType) +{ + ICP_HSSACC_TRACE_2 (ICP_HSSACC_DEBUG, + "HssAccErrorDummyClientCb - " + "received notification of error %u for service %u\n", + errorType, + (unsigned)userContext); +} + + + + + + + +/***************************************************************************** + * Abstract: + * display all stats provided by the TDM I/O unit relating to detected + * firmware errors. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccSwErrorStatsShow (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + unsigned statValue = 0; + icp_boolean_t mutexLocked = ICP_FALSE; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccSwErrorStatsShow\n"); + + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("HssAccSwErrorStatsShow - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + if (ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "TDM IO Unit Firmware Error Stats:\n", + 0, 0, 0, 0, 0, 0); + + /* Retrieve each Sw Error Count and print it */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_Q_OVERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Receive Voice Q Overflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_Q_OVERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Receive HDLC Q Overflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_FIFO_OVERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Receive Voice FIFO Overflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_FIFO_OVERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Receive HDLC FIFO Overflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_FREE_Q_UNDERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Receive Voice Free Q Underflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_FREE_Q_UNDERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Receive Voice HDLC Free Underflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_MSG_OUT_FIFO_LP_OVERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Msg Out FIFO Low Priority Overflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_MSG_OUT_FIFO_HP_OVERFLOW, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Msg Out FIFO High Priority Overflows: %u\n", + statValue, + 0, 0, 0, 0, 0); + + } + + if (ICP_TRUE == mutexLocked) + { + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("HssAccSwErrorStatsShow - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccSwErrorStatsShow\n"); + return status; +} + + +/***************************************************************************** + * Abstract: + * reset the firmware error stats in the TDM I/O Unit. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccSwErrorStatsReset (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint8_t resetFlag = 1; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccSwErrorStatsReset\n"); + + /* Retrieve each Sw Error Count and print it */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_Q_OVERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + + if ( ICP_STATUS_SUCCESS == status) + { + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_Q_OVERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_FIFO_OVERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_FIFO_OVERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_FREE_Q_UNDERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_FREE_Q_UNDERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_MSG_OUT_FIFO_LP_OVERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ, + ICP_HSSACC_TDM_IO_UNIT_MSG_OUT_FIFO_HP_OVERFLOW, + resetFlag, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE, + &(hssAccServStats.swErrReset), + NULL); + } + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccSwErrorStatsReset\n"); + return status; +} + +/***************************************************************************** + * Abstract: + * display all error stats collected by the TDM I/O unit. + * + *****************************************************************************/ +icp_status_t +HssAccTdmIOErrorStatsShow (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + unsigned statValue = 0; + icp_boolean_t mutexLocked = ICP_FALSE; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTdmIOErrorStatsShow\n"); + + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmIOErrorStatsShow - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "TDM IO Unit Global Error Stats:\n", + 0, 0, 0, 0, 0, 0); + + /* Retrieve each hardware error Count and print it */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_ABT_ALN_ERR_READ, + 0, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_ABT_ALN_ERR_READ_RESPONSE, + &(hssAccServStats.abtAlnRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Alignment Errors %u, Abort Errors %u\n", + statValue & ICP_HSSACC_TDM_IO_UNIT_SHORT1_MASK, + (statValue & ICP_HSSACC_TDM_IO_UNIT_SHORT0_MASK) >> + ICP_HSSACC_TDM_IO_UNIT_SHORT0_OFFSET, + 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_FCS_MAX_ERR_READ, + 0, 0, 0, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_FCS_MAX_ERR_READ_RESPONSE, + &(hssAccServStats.fcsMaxRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "FCS Errors %u, Max Frame Size Errors %u\n", + statValue & ICP_HSSACC_TDM_IO_UNIT_SHORT1_MASK, + (statValue & ICP_HSSACC_TDM_IO_UNIT_SHORT0_MASK) >> + ICP_HSSACC_TDM_IO_UNIT_SHORT0_OFFSET, + 0, 0, 0, 0); + } + + if (ICP_TRUE == mutexLocked) + { + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("HssAccTdmIOErrorStatsShow - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTdmIOErrorStatsShow\n"); + return status; +} + + + + + +/***************************************************************************** + * Abstract: + * display all error stats collected by the TDM I/O Unit for the specified + * channel. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccChannelTdmIOErrorStatsShow(unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + unsigned statValue = 0; + icp_boolean_t mutexLocked = ICP_FALSE; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelTdmIOErrorStatsShow\n"); + + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("HssAccChannelTdmIOErrorStatsShow - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "TDM IO Unit channel Error Stats for channel %u:\n", + channelId, 0, 0, 0, 0, 0); + + + /* Retrieve Stats from the TDM I/O Unit */ + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, 0, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_ABT_ALN, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Abort or Alignment: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, 0, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_FCS, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "FCS: %u\n", + statValue, + 0, 0, 0, 0, 0); + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, 0, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_MAX_SIZE, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + &statValue); + + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Max Size: %u\n", + statValue, + 0, 0, 0, 0, 0); + + +#ifndef NDEBUG + /* Retrieve Packet Rx and Tx stats */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, 0, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_TX_PKTS, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + &statValue); + } + + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Transmitted Packets: %u\n", + statValue, + 0, 0, 0, 0, 0); + + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, 0, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_RX_PKTS, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + &statValue); + } + if ( ICP_STATUS_SUCCESS == status) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Received Packets: %u\n", + statValue, + 0, 0, 0, 0, 0); + + +#endif + } + + if (ICP_TRUE == mutexLocked) + { + /* release the HssAcc Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("HssAccChannelTdmIOErrorStatsShow - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelTdmIOErrorStatsShow\n"); + return status; +} + +/***************************************************************************** + * Abstract: + * get the TDM I/O unit to reset all error stats for the specified channel. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccChannelTdmIOErrorStatsReset(unsigned channelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint8_t resetFlag = 1; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelTdmIOErrorStatsReset\n"); + + + + /* Retrieve Stats from the TDM I/O Unit */ + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, resetFlag, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_ABT_ALN, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + NULL); + + if ( ICP_STATUS_SUCCESS == status) + { + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, resetFlag, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_FCS, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, resetFlag, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_MAX_SIZE, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + NULL); + + } + + if ( ICP_STATUS_SUCCESS == status) + { + +#ifndef NDEBUG + /* Retrieve Packet Rx and Tx stats */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, resetFlag, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_TX_PKTS, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + NULL); + } + + if ( ICP_STATUS_SUCCESS == status) + { + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_STATS_READ, + channelId, resetFlag, + ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_RX_PKTS, 0, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE, + &(hssAccServStats.chanStatRead), + NULL); + +#endif + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelTdmIOErrorStatsReset\n"); + return status; +} + + + +/***************************************************************************** + * Abstract: + * reset all internal stats for this sub-module only. + * + *****************************************************************************/ +TDM_PRIVATE void +HssAccServiceStatsReset (void) +{ + memset (&hssAccServStats, 0, sizeof(icp_hssacc_service_stats_t)); +} + + + + +/***************************************************************************** + * Abstract: + * display all internal stats for this sub-module. + * + *****************************************************************************/ +TDM_PRIVATE void +HssAccServiceStatsShow (void) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccServiceStatsShow\n"); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTDM Service Statistics:\n" + "Service Timer Config Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.timerStat); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nInterrupt Generation Configuration Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.intStat); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nAbort and Alignment Error Stats Read Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.abtAlnRead); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nFCS and Max Size Error Stats Read Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.fcsMaxRead); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Stats Read Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.chanStatRead); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTDM IO Unit Firmware Error Stats Read Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.swErrRead); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTDM IO Unit Firmware Error Stats Reset Messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccServStats.swErrReset); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccServiceStatsShow\n"); + +} + + + +/***************************************************************************** + * Abstract: + * Updates the configuration of the int generation on the TDM I/O Unit + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccServiceIntGenUpdate (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint8_t voiceTxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_DISABLED; + uint8_t voiceRxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_DISABLED; + uint8_t hdlcTxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_DISABLED; + uint8_t hdlcRxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_DISABLED; + IxPiuMhMessage message; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccServiceIntGenUpdate\n"); + + if (ICP_TRUE == voiceIntEnabled) + { + voiceTxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_ENABLED; + voiceRxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_ENABLED; + } + + if (ICP_TRUE == hdlcIntEnabled) + { + hdlcTxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_ENABLED; + hdlcRxEnabled = ICP_HSSACC_TDM_IO_UNIT_HSS_INT_ENABLED; + } + + /* Construct the message to configure the interrupt generation */ + HssAccComTdmIOUnitCmd8byteMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_HSS_INT_CFG, + 0, 0, 0, + hdlcTxEnabled, hdlcRxEnabled, + voiceTxEnabled, voiceRxEnabled, + &message); + + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_HSS_INT_CFG_RESPONSE, + &(hssAccServStats.intStat), + NULL); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR ("HssAccServiceIntGenUpdate - " + "Failed to update Interrupt Gen " + "Config in TDM I/O Unit\n"); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccServiceIntGenUpdate\n"); + return status; +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_symbols.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_symbols.c new file mode 100644 index 0000000..53e7855 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_symbols.c @@ -0,0 +1,121 @@ +/****************************************************************************** + * @file icp_hssacc_symbols.c + * + * @description Contents of this file provide the list of symbols to be + * exported by this module + * + * @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. + * Copyright(c) 2010,2011,2012 Avencall + * + * 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. + * + * BSD LICENSE + * + * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + * All rights reserved. + * Copyright(c) 2010,2011,2012 Avencall + * + * 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. + * + * + * + * + *****************************************************************************/ + + +#ifdef __linux + + +#include <linux/module.h> +#include "icp_hssacc.h" + +EXPORT_SYMBOL(icp_HssAccInit); +EXPORT_SYMBOL(icp_HssAccHdlcInit); +EXPORT_SYMBOL(icp_HssAccVoiceInit); +EXPORT_SYMBOL(icp_HssAccShutdown); +EXPORT_SYMBOL(icp_HssAccNumSupportedPortsGet); +EXPORT_SYMBOL(icp_HssAccPortConfig); +EXPORT_SYMBOL(icp_HssAccPortUp); +EXPORT_SYMBOL(icp_HssAccPortDown); +EXPORT_SYMBOL(icp_HssAccNumSupportedChannelsGet); +EXPORT_SYMBOL(icp_HssAccChannelAllocate); +EXPORT_SYMBOL(icp_HssAccChannelConfigure); +EXPORT_SYMBOL(icp_HssAccChannelHdlcServiceConfigure); +EXPORT_SYMBOL(icp_HssAccChannelVoiceServiceConfigure); +EXPORT_SYMBOL(icp_HssAccChannelCallbacksRegister); +EXPORT_SYMBOL(icp_HssAccErrorCallbackRegister); +EXPORT_SYMBOL(icp_HssAccPortErrorCallbackRegister); +EXPORT_SYMBOL(icp_HssAccNumSupportedGCTsGet); +EXPORT_SYMBOL(icp_HssAccNumSupportedVoiceBypassesGet); +EXPORT_SYMBOL(icp_HssAccVoiceBypassGctDownload); +EXPORT_SYMBOL(icp_HssAccVoiceBypassEnable); +EXPORT_SYMBOL(icp_HssAccVoiceBypassDisable); +EXPORT_SYMBOL(icp_HssAccChannelUp); +EXPORT_SYMBOL(icp_HssAccChannelDown); +EXPORT_SYMBOL(icp_HssAccChannelDelete); +EXPORT_SYMBOL(icp_HssAccTransmit); +EXPORT_SYMBOL(icp_HssAccReceive); +EXPORT_SYMBOL(icp_HssAccRxFreeReplenish); +EXPORT_SYMBOL(icp_HssAccTxDoneRetrieve); +EXPORT_SYMBOL(icp_HssAccAllBuffersRetrieve); +EXPORT_SYMBOL(icp_HssAccDataPathService); +EXPORT_SYMBOL(icp_HssAccChannelStatsShow); +EXPORT_SYMBOL(icp_HssAccChannelStatsReset); +EXPORT_SYMBOL(icp_HssAccPortStatsShow); +EXPORT_SYMBOL(icp_HssAccPortStatsReset); +EXPORT_SYMBOL(icp_HssAccStatsShow); +EXPORT_SYMBOL(icp_HssAccStatsReset); + +#include "icp_hssacc_queues_config.h" + +// hacky +EXPORT_SYMBOL(HssAccQueueIdGet); + +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_timeslot_allocation.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_timeslot_allocation.c new file mode 100644 index 0000000..80a9d72 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_timeslot_allocation.c @@ -0,0 +1,665 @@ +/****************************************************************************** + * + * @file icp_hssacc_timeslot_allocation.c + * + * @description Content of this file is the implementation of the Timeslot + * allocation and de-allocation functionality used for channel Allocation + * and deletion. This platform specific implementation compliments the + * file icp_hssacc_common_timeslot_allocation.c containing the common + * sections of this module. + * + * @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 "IxOsal.h" + +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_timeslot_allocation.h" +#include "icp_hssacc_port_config.h" +#include "icp_hssacc_channel_config.h" +#include "icp_hssacc_address_translate.h" + + + +#define ICP_HSSACC_OFFSET_HALF_WD_PER_LINE (16) +#define ICP_HSSACC_CHAN_OFFS_PER_WD (2) + +/* This Macro operates an endianness swap on half-words for + addressing purposes within the TDM I/O Unit channel offset + table */ +#define ICP_HSSACC_CHAN_OFFS_LOC_IN_TBL(chan) ((chan)^1) + +/* Stats */ +typedef struct icp_hssacc_ts_alloc_stats_s +{ + icp_hssacc_msg_with_resp_stats_t hssPortProvTableLoad; + icp_hssacc_msg_with_resp_stats_t chanOffsetTableLoad; + icp_hssacc_msg_with_resp_stats_t chanOffsetTableRead; + icp_hssacc_msg_with_resp_stats_t hssPortProvTableSwap; +} icp_hssacc_ts_alloc_stats_t; + + +TDM_PRIVATE icp_hssacc_ts_alloc_stats_t hssAccTsAllocStats; + +TDM_PRIVATE icp_boolean_t hssAccTsAllocated [ICP_HSSACC_MAX_NUM_PORTS]; + + +/** + * Function Definition: HssAccTsAllocSwapStatsGet + */ +icp_hssacc_msg_with_resp_stats_t * HssAccTsAllocSwapStatsGet(void) +{ + return &(hssAccTsAllocStats.hssPortProvTableSwap); +} + +/** + * Function Definition: HssAccTsAllocOffsetTableReadStatsGet + */ +icp_hssacc_msg_with_resp_stats_t * HssAccTsAllocOffsetTableReadStatsGet(void) +{ + return &(hssAccTsAllocStats.chanOffsetTableRead); +} + +/** + * Function Definition: HssAccTsAllocPlatformInit + */ +icp_status_t HssAccTsAllocPlatformInit (void) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned portIndex = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocPlatformInit\n"); + + for (portIndex = 0; portIndex < ICP_HSSACC_MAX_NUM_PORTS; portIndex ++) + { + hssAccTsAllocated[portIndex] = ICP_FALSE; + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocPlatformInit\n"); + return status; +} + + + +/** + * Function definition: HssAccTsAllocStatsReset + */ +void HssAccTsAllocStatsReset (void) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocStatsReset\n"); + memset (&hssAccTsAllocStats, + 0, + sizeof(icp_hssacc_ts_alloc_stats_t)); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocStatsReset\n"); +} + + + +#ifdef SW_SWAPPING +/** + * Function definition: HssAccTsAllocTableWordsSwap + * This function assumes that the size provided is a multiple + * of a word size. + */ +TDM_PRIVATE +void HssAccTsAllocTableWordsSwap (uint32_t * tableAddr, + uint32_t sizeInBytes) +{ + unsigned index = 0; + for (;index < (sizeInBytes/ICP_HSSACC_WORD_SIZE); index ++) + { + tableAddr[index] = IX_OSAL_SWAP_BE_SHARED_LONG(tableAddr[index]); + } +} +#endif + + + +/** + * Function definition: HssAccTsAllocOffsetTableLoad + */ + +TDM_PRIVATE icp_status_t +HssAccTsAllocOffsetTableLoad (unsigned portId, + uint32_t offsetTablePhysAddr, + uint8_t messageId, + uint8_t messageRespId, + icp_hssacc_msg_with_resp_stats_t * stats, + icp_boolean_t activeTableLoad) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + uint8_t activeShadow = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocOffsetTableLoad\n"); + + /* Translate Active/Shadow, only used for certain types of message + of no impact on others */ + if ( ICP_TRUE == activeTableLoad ) + { + activeShadow = 1; + } + + /* Create Message for TDM I/O Unit */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate (messageId, + 0, + portId, + activeShadow, + offsetTablePhysAddr, + &message); + /* Send the message */ + status = HssAccComTdmIOUnitMsgSendAndRecv(message, + messageRespId, + stats, + NULL); + + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR("HssAccTsAllocOffsetTableLoad - " + "Failed communication with TDM I/O Unit " + "for Timeslot Allocation\n"); + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocOffsetTableLoad\n"); + + return status; +} + + + + +/** + * Function definition: HssAccTsAllocDummyProvTableCreate + * This will create a table with a single channel enabled + * with all timeslots assigned + */ +void +HssAccTsAllocDummyProvTableCreate (uint32_t * provTable) +{ + unsigned index = 0; + for (index = 0; index < ICP_HSSACC_MAX_TIMESLOTS_PER_PORT; index++) + { + provTable[index] = + (ICP_HSSACC_TDM_IO_UNIT_TS_ENABLE << + ICP_HSSACC_TDM_IO_UNIT_TS_EN_BIT_OFFSET); + } +} + + +/***************************************************************************** + * Abstract: + * Builds a new channel offset table for the TDM I/O unit. Only the offsets + * of channels on the specified HSS port will be affected. + * Also constructs a new Timeslot provisioning table for the specified port. + * When both tables have been built, they are loaded into the TDM I/O unit. + * + *****************************************************************************/ +icp_status_t +HssAccTsAllocUpdate(unsigned portId, + const icp_hssacc_channel_config_t * hssChannelData) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + unsigned chanId = 0, hdmaChannelId = 0; + unsigned tableProvOffset[ICP_HSSACC_MAX_NUM_PORTS]; + uint32_t tableOffset = 0; + uint16_t *pTdmIoUnitOffsetTable = NULL; + uint32_t *pHdmaProvTable = NULL; + uint8_t tsIndex, indexOffset = 0; + icp_boolean_t noTsUsed = ICP_TRUE; + uint32_t hdmaProvTablePhysOffset = 0; + uint32_t tdmIoUnitOffsetTablePhysOffset = 0; + + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocUpdate - " + "Configuring timeslots on port %u\n", + portId); + + /* Get the base address of the channel offset tables */ + pTdmIoUnitOffsetTable = + (uint16_t *)HssAccTsAllocTdmIoUnitOffsetTableVirtAddrGet(); + + pHdmaProvTable = + (uint32_t *)HssAccTsAllocHdmaProvTableVirtAddrGet(); + + /* Clear the contents of the TDM I/O Unit channe offset table + and timeslot provisioning table */ + memset (pHdmaProvTable, 0, ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + memset (pTdmIoUnitOffsetTable, 0, ICP_HSSACC_TDM_IO_UNIT_OFFSET_TABLE_SZ); + memset (tableProvOffset, 0, ICP_HSSACC_MAX_NUM_PORTS*sizeof(unsigned)); + /* + * The objective here is to pack the internal TDM I/O Unit memory channel + * usage such that the TDM I/O unit's internal memory doesn't become + * fragmented from adding/removing channels. This allows us to make maximum + * use of the total available memory. + * + * Two tables need to be updated: + * 1) the TDM I/O unit's offset table, which has a 1-to-1 mapping between + * MAX_NUM channels and their location in internal memory. Only + * channels on the specified port will be updated. The offset of each + * channel is relative to the port base address. + * 2) the TDM I/O Unit's timeslot proviosining table, which tracks the + * offsets of all channels active on that port. The channel ID(s) on a + * port differ from that of the TDM I/O unit (since we can't + * have MAX_NUM channels per port). For example, + * channel 5 (from the perspective of the access layer/TDM I/O unit) + * could have a channel ID of 0 on the port where it is active. + * + * Timeslot aggregation is also performed for all channels on the port. + */ + + /* The TDM I/O unit offset table has an entry for MAX_NUM channels */ + for (chanId = 0; chanId < ICP_HSSACC_MAX_NUM_CHANNELS; chanId++) + { + /* + * Only need to update the channels on the specified port, so skip any + * that are active on other ports, or inactive. + * This preserves the offsets for channels on other HSS ports. + */ + if (hssChannelData[chanId].size > 0) + { + /* Update the TDM I/O unit offset table for the active + channel (byte offset required)*/ + pTdmIoUnitOffsetTable[ICP_HSSACC_CHAN_OFFS_LOC_IN_TBL(chanId)] = + tableProvOffset[hssChannelData[chanId].portId]; + + if (hssChannelData[chanId].portId == portId) + { + noTsUsed = ICP_FALSE; + hssAccTsAllocated[portId] = ICP_TRUE; + + /* Calculate the HDMA timeslot index offset */ + indexOffset = hssChannelData[chanId].lineId * + ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + + + /* Enable the timeslots used by this channel */ + for (tsIndex = 0; + tsIndex < ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE; + tsIndex ++) + { + if (hssChannelData[chanId].timeslotMap & BIT_SET(tsIndex)) + { + ICP_HSSACC_TRACE_3 (ICP_HSSACC_DEBUG, + "HssAccTsAllocUpdate - Timeslot" + " %u is used by chan %u " + "on port %u\n", + tsIndex, + chanId, + hssChannelData[chanId].portId); + pHdmaProvTable[indexOffset + tsIndex] = + (ICP_HSSACC_TDM_IO_UNIT_TS_ENABLE << + ICP_HSSACC_TDM_IO_UNIT_TS_EN_BIT_OFFSET) | + (hdmaChannelId << ICP_HSSACC_TDM_IO_UNIT_CHAN_OFFSET); + } + } + + /* + * Must offset by 128 words in order to get to the first channel + * configuration word. + */ + indexOffset = ICP_HSSACC_MAX_TIMESLOTS_PER_PORT; + + /* Update the HDMA offset table */ + pHdmaProvTable[indexOffset + hdmaChannelId] = + tableOffset << ICP_HSSACC_TDM_IO_UNIT_CHAN_OFFSET; + + hdmaChannelId ++; + + /* Update the word offset by the size of the channel */ + tableOffset += hssChannelData[chanId].size; + } + tableProvOffset[hssChannelData[chanId].portId] += + hssChannelData[chanId].size*ICP_HSSACC_WORD_SIZE; + + } + } + + /* if no TS are used for this port, we need to allocate a dummy single + channel with all timeslots assigned to keep the TDM I/O Unit from + generating errors */ + if (noTsUsed) + { + HssAccTsAllocDummyProvTableCreate(pHdmaProvTable); + } +#ifdef SW_SWAPPING + HssAccTsAllocTableWordsSwap(pHdmaProvTable, + ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + + HssAccTsAllocTableWordsSwap((uint32_t*)pTdmIoUnitOffsetTable, + ICP_HSSACC_TDM_IO_UNIT_OFFSET_TABLE_SZ); +#endif + + /* Flush the new tables to memory */ + IX_OSAL_CACHE_FLUSH (pHdmaProvTable, ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + IX_OSAL_CACHE_FLUSH (pTdmIoUnitOffsetTable, + ICP_HSSACC_TDM_IO_UNIT_OFFSET_TABLE_SZ); + + /* Convert virtual addresses to Physical Offsets */ + hdmaProvTablePhysOffset = + HssAccVirtToPhysAddressTranslate(pHdmaProvTable); + tdmIoUnitOffsetTablePhysOffset = + HssAccVirtToPhysAddressTranslate((uint32_t*)pTdmIoUnitOffsetTable); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTsAllocUpdate - Update HDMA" + " provision table\n"); + + + /* Load the new HDMA offset table for this port */ + status = HssAccTsAllocOffsetTableLoad ( + portId, + hdmaProvTablePhysOffset, + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD, + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD_RESPONSE, + &(hssAccTsAllocStats.hssPortProvTableLoad), + ICP_FALSE); + + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTsAllocUpdate - Update offset" + " table\n"); + + /* Load the new TDM I/O unit offset table */ + status = HssAccTsAllocOffsetTableLoad( + 0, + tdmIoUnitOffsetTablePhysOffset, + ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_LOAD, + ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_LOAD_RESPONSE, + &(hssAccTsAllocStats.chanOffsetTableLoad), + ICP_FALSE); + } + + + + if (ICP_STATUS_SUCCESS == status) + { + status = HssAccTsAllocTableSwap (portId); + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocUpdate\n"); + + return status; +} + + + +/** + * Function definition: HssAccTsAllocInitialAllocationUpdate + */ +icp_status_t +HssAccTsAllocInitialAllocationUpdate(unsigned portId) + +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t *pHdmaProvTable = NULL; + uint32_t hdmaProvTablePhysOffset = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocInitialAllocationUpdate\n"); + if (ICP_TRUE != hssAccTsAllocated[portId]) + { + + /* Get the base address of the channel offset tables */ + pHdmaProvTable = + (uint32_t *)HssAccTsAllocHdmaProvTableVirtAddrGet(); + + /* Clear the contents of the HDMA offset table */ + memset (pHdmaProvTable, 0, ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + + + HssAccTsAllocDummyProvTableCreate(pHdmaProvTable); + +#ifdef SW_SWAPPING + HssAccTsAllocTableWordsSwap(pHdmaProvTable, + ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + +#endif + /* Flush the new tables to memory */ + IX_OSAL_CACHE_FLUSH (pHdmaProvTable, + ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ); + + + /* Convert virtual addresses to Physical Offsets */ + hdmaProvTablePhysOffset = + HssAccVirtToPhysAddressTranslate(pHdmaProvTable); + + ICP_HSSACC_TRACE_0(ICP_HSSACC_DEBUG, + "HssAccTsAllocInitialAllocationUpdate - " + "Update Timeslot provisioning table\n"); + + + /* Load the new timeslot Provisioning table for this port */ + status = + HssAccTsAllocOffsetTableLoad ( + portId, + hdmaProvTablePhysOffset, + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD, + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD_RESPONSE, + &(hssAccTsAllocStats.hssPortProvTableLoad), + ICP_TRUE); + + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocInitialAllocationUpdate\n"); + return status; +} + + + + + + + +/** + * Function definition: HssAccTsAllocOffsetTableShow + */ +TDM_PRIVATE void +HssAccTsAllocOffsetTableShow (icp_boolean_t readShadowTable) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t offsetTableWord = 0; + uint16_t offsetTableOffset = 0; + unsigned channelCount = 0; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocOffsetTableShow\n"); + + for (offsetTableOffset = 0; + offsetTableOffset < ICP_HSSACC_TDM_IO_UNIT_OFFSET_TABLE_SZ; + offsetTableOffset += ICP_HSSACC_WORD_SIZE) + { + status = HssAccTsAllocOffsetTableWordRead (readShadowTable, + offsetTableOffset, + &offsetTableWord); + if (ICP_STATUS_SUCCESS == status) + { + if (0 == (offsetTableOffset % ICP_HSSACC_OFFSET_HALF_WD_PER_LINE)) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "%u: ", + channelCount, + 0, 0, 0, 0, 0); + } + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "0x%04X 0x%04X ", + (uint16_t)((offsetTableWord & + ICP_HSSACC_TDM_IO_UNIT_SHORT0_MASK) >> + ICP_HSSACC_TDM_IO_UNIT_SHORT0_OFFSET), + (uint16_t)(offsetTableWord & + ICP_HSSACC_TDM_IO_UNIT_SHORT1_MASK), + 0, 0, 0, 0); + if ((ICP_HSSACC_OFFSET_HALF_WD_PER_LINE - ICP_HSSACC_WORD_SIZE) == + (offsetTableOffset % ICP_HSSACC_OFFSET_HALF_WD_PER_LINE)) + { + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\n", 0, 0, 0, 0, 0, 0); + } + } + else + { + ICP_HSSACC_REPORT_ERROR ("HssAccTsAllocOffsetTableShow - " + "Failed to read " + "Channel Offset Table from TDM I/O Unit\n"); + break; + } + channelCount += ICP_HSSACC_CHAN_OFFS_PER_WD; + } + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\n", 0, 0, 0, 0, 0, 0); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocOffsetTableShow\n"); +} + + +/** + * Function definition: HssAccTsAllocChanOffsetActiveTableShow + */ +void HssAccTsAllocChanOffsetActiveTableShow (void) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocChanOffsetActiveTableShow\n"); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTDM I/O Unit Channel Offset ACTIVE Table:\n", + 0, 0, 0, 0, 0, 0); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\n----------------------------------------------\n", + 0, 0, 0, 0, 0, 0); + HssAccTsAllocOffsetTableShow (ICP_FALSE); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocChanOffsetActiveTableShow\n"); +} + + +/** + * Function definition: HssAccTsAllocChanOffsetShadowTableShow + */ +void HssAccTsAllocChanOffsetShadowTableShow (void) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocChanOffsetShadowTableShow\n"); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTDM I/O Unit Channel Offset SHADOW Table:\n", + 0, 0, 0, 0, 0, 0); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\n----------------------------------------\n", + 0, 0, 0, 0, 0, 0); + HssAccTsAllocOffsetTableShow (ICP_TRUE); + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocChanOffsetShadowTableShow\n"); +} + + + +/** + * Function definition: HssAccTsAllocStatsShow + */ +void HssAccTsAllocStatsShow (void) +{ + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTsAllocStatsShow\n"); + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nTimeslot Allocation Stats:\n", + 0, 0, 0, 0, 0, 0); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Stats for TDM I/O Unit channel Offset Table Load messages:\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow(hssAccTsAllocStats.chanOffsetTableLoad); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Stats for Timeslot Provisioning Table Load messages:\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow(hssAccTsAllocStats.hssPortProvTableLoad); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Stats for Timeslot Provisioning Table Swap messages:\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow(hssAccTsAllocStats.hssPortProvTableSwap); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "Stats for TDM I/O Unit channel Offset Table Read messages:\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow(hssAccTsAllocStats.chanOffsetTableRead); + + HssAccTsAllocChanOffsetActiveTableShow(); + HssAccTsAllocChanOffsetShadowTableShow(); + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTsAllocStatsShow\n"); +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_tx_datapath.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_tx_datapath.c new file mode 100644 index 0000000..3f02636 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_tx_datapath.c @@ -0,0 +1,1023 @@ +/***************************************************************************** + * @file icp_hssacc_tx_datapath.c + * + * @description Contents of this file provide the implementation of the + * transmit functionality for the HSS I/O Access component + * + * @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 "IxOsal.h" + + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_channel_config.h" +#include "icp_hssacc_address_translate.h" + +#include "icp_hssacc_rings.h" +#include "icp_hssacc_queues_config.h" +#include "icp_hssacc_tx_datapath.h" +#include "icp_hssacc_tdm_io_queue_entry.h" +#include "IxQMgr.h" + + +/* Mutex which controls access to transmit datapath path functions */ +TDM_PRIVATE IxOsalMutex hssAccTxMutex[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_hssacc_tx_done_callback_t +hssAccTxDoneChannelCallbacks[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_user_context_t +hssAccTxDoneUserContext[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE uint32_t +hssAccTxDatapathNumPendPkts[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_boolean_t +hssAccTxDatapathLastSubmitSuccess[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_boolean_t hssAccTxServiceInitialised = ICP_FALSE; + + +/* Stats */ +#ifndef NDEBUG +TDM_PRIVATE uint32_t hssAccTxNumPktsSubmissions[ICP_HSSACC_MAX_NUM_CHANNELS]; +TDM_PRIVATE uint32_t +hssAccTxNumPktsSuccessSubmissions[ICP_HSSACC_MAX_NUM_CHANNELS]; +TDM_PRIVATE uint32_t hssAccTxNumPktsDone[ICP_HSSACC_MAX_NUM_CHANNELS]; +#endif + + +/* + * Initialises the service mutex. + */ +#define ICP_HSSACC_TX_DP_MUTEX_INIT(channelId) \ + (ixOsalMutexInit(&hssAccTxMutex[channelId])) + +/* + * Locks the service mutex. + */ +#define ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId) \ + (ixOsalMutexLock(&hssAccTxMutex[channelId],ICP_HSSACC_MUTEX_TIMEOUT)) + +/* + * Unlocks the service mutex. + */ +#define ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId) \ + (ixOsalMutexUnlock(&hssAccTxMutex[channelId])) + +/* + * Destroys the service mutex. + */ +#define ICP_HSSACC_TX_DP_MUTEX_DESTROY(channelId) \ + (ixOsalMutexDestroy(&hssAccTxMutex[channelId])) + +/* + * Reset the stats for a channel + */ +#ifndef NDEBUG +#define ICP_HSSACC_TX_DP_CHAN_STATS_RESET(channelId) do { \ + hssAccTxNumPktsSuccessSubmissions[channelId] = 0; \ + hssAccTxNumPktsSubmissions[channelId] = 0; \ + hssAccTxNumPktsDone[channelId] =0; \ + } while(0); +#else +#define ICP_HSSACC_TX_DP_CHAN_STATS_RESET(channelId) do { \ + } while (0); +#endif + + +/* Data for the descriptor to mbuf mapping queue */ +TDM_PRIVATE uint32_t +hssAccDataPlaneTxDescRingData +[ICP_HSSACC_MAX_NUM_CHANNELS][ICP_HSSACC_TX_QUEUE_DEPTH]; + + +TDM_PRIVATE icp_hssacc_dataplane_ring_t +hssAccDataPlaneTxDescRing[ICP_HSSACC_MAX_NUM_CHANNELS]; + +TDM_PRIVATE icp_boolean_t hssAccDataPlaneTxBypass[ICP_HSSACC_MAX_NUM_CHANNELS]; + + +/***************************************************************************** + * Abstract: + * Resets the Tx Datapath internal data. + * + *****************************************************************************/ +TDM_PRIVATE icp_status_t +HssAccTxDatapathReset(void); + + + + +icp_status_t +HssAccTxDatapathInit(void) +{ + uint32_t index = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathInit\n"); + if (ICP_TRUE == hssAccTxServiceInitialised) + { + ICP_HSSACC_REPORT_ERROR("HssAccTxDatapathInit - Tx Datapath sub-component" + " already initialised\n"); + status = ICP_STATUS_RESOURCE; + } + + if (ICP_STATUS_SUCCESS == status) + { + /* We support 1 client only per channel, to protect against corruption + we need 1 mutex per channel */ + for (index = 0; + index < ICP_HSSACC_MAX_NUM_CHANNELS; + index ++) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_INIT(index)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathInit - Mutex " + "Init Error for channel %d\n", + index); + status = ICP_STATUS_MUTEX; + break; + } + } + status = HssAccTxDatapathReset(); + } + if (ICP_STATUS_SUCCESS == status) + { + hssAccTxServiceInitialised = ICP_TRUE; + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathInit\n"); + return status; +} + + +void +HssAccTxDatapathChanStatsReset(uint32_t channelId) +{ + if (ICP_STATUS_SUCCESS == ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId)) + { + ICP_HSSACC_TX_DP_CHAN_STATS_RESET(channelId); + + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChanStatsReset - " + "Mutex Unlock Error for channel %d\n", + channelId); + } + } + else + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChanStatsReset - " + "Mutex Lock Error for channel %d\n", + channelId); + } +} + + +void +HssAccTxDatapathChanStatsShow(uint32_t channelId) +{ +#ifndef NDEBUG + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Tx Datapath Statistics\n", + 0, 0, 0, 0, 0, 0); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\t\t%d Packets Submitted\n" + "\t\t%d Packets Successfully Submitted\n" + "\t\t%d Packets Done and Recycled to Client\n", + hssAccTxNumPktsSubmissions[channelId], + hssAccTxNumPktsSuccessSubmissions[channelId], + hssAccTxNumPktsDone[channelId], 0, 0, 0); +#else + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nChannel Tx Datapath Statistics Not Supported in this Build\n", + 0, 0, 0, 0, 0, 0); +#endif +} + + +icp_status_t +HssAccTxDatapathShutdown(void) +{ + uint32_t index = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathShutdown\n"); + if (ICP_TRUE == hssAccTxServiceInitialised) + { + status = HssAccTxDatapathReset(); + if (ICP_STATUS_SUCCESS == status) + { + for (index = 0; index < ICP_HSSACC_MAX_NUM_CHANNELS; index ++) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_DESTROY(index)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathShutdown - Mutex " + "Destroy Error for channel %d\n", + index); + status = ICP_STATUS_MUTEX; + break; + } + } + } + if (ICP_STATUS_SUCCESS == status) + { + hssAccTxServiceInitialised = ICP_FALSE; + } + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathShutdown\n"); + return status; +} + + +TDM_PRIVATE icp_status_t +HssAccTxDatapathReset(void) +{ + uint32_t index = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathReset\n"); + for (index = 0; index < ICP_HSSACC_MAX_NUM_CHANNELS; index ++) + { + if (ICP_STATUS_SUCCESS == ICP_HSSACC_TX_DP_MUTEX_LOCK(index)) + { + hssAccDataPlaneTxDescRing[index].content = + hssAccDataPlaneTxDescRingData[index]; + hssAccDataPlaneTxDescRing[index].size = ICP_HSSACC_TX_QUEUE_DEPTH; + hssAccDataPlaneTxDescRing[index].mask = + ICP_HSSACC_TX_QUEUE_DEPTH - 1; + + hssAccDataPlaneTxDescRing[index].tail = 0; + hssAccDataPlaneTxDescRing[index].head = 0; + hssAccDataPlaneTxBypass[index] = ICP_FALSE; + hssAccTxDatapathNumPendPkts[index] = 0; + hssAccTxDatapathLastSubmitSuccess[index] = ICP_FALSE; + ICP_HSSACC_TX_DP_CHAN_STATS_RESET(index); + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(index)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathReset - " + "Mutex Unlock Error for channel %d\n", + index); + status = ICP_STATUS_MUTEX; + break; + } + } + else + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathReset - " + "Mutex Lock Error for channel %d\n", + index); + status = ICP_STATUS_MUTEX; + break; + } + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathReset\n"); + return status; +} + + +icp_status_t +HssAccTxDatapathChanTypeUpdate (uint32_t channelId, + icp_hssacc_channel_type_t chanType) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathChanTypeUpdate\n"); + if (ICP_STATUS_SUCCESS == ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId)) + { + if (ICP_HSSACC_CHAN_TYPE_HDLC == chanType) + { + hssAccDataPlaneTxDescRing[channelId].size = + ICP_HSSACC_HDLC_TX_QUEUE_DEPTH; + hssAccDataPlaneTxDescRing[channelId].mask = + ICP_HSSACC_HDLC_TX_QUEUE_DEPTH - 1; + } + else + { + hssAccDataPlaneTxDescRing[channelId].size = + ICP_HSSACC_VOICE_TX_QUEUE_DEPTH; + hssAccDataPlaneTxDescRing[channelId].mask = + ICP_HSSACC_VOICE_TX_QUEUE_DEPTH - 1; + } + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChanTypeUpdate - " + "Mutex Unlock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + else + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChanTypeUpdate - " + "Mutex Lock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathChanTypeUpdate\n"); + return status; +} + +TDM_PRIVATE icp_status_t +HssAccTxDatapathBufferValidityCheck(const IX_OSAL_MBUF * buffer, + icp_hssacc_channel_type_t channelType) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathBufferValidityCheck\n"); + + if ((NULL != IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(buffer)) || + (NULL != IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(buffer))) + { + ICP_HSSACC_REPORT_ERROR("HssAccTxDatapathBufferValidityCheck - " + "Buffer and Packet Chaining not supported " + "for Transmission\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if ( IX_OSAL_MBUF_PKT_LEN(buffer) != IX_OSAL_MBUF_MLEN(buffer)) + { + ICP_HSSACC_REPORT_ERROR("HssAccTxDatapathBufferValidityCheck - " + "Buffer length and Packet Length in OS " + "Abstraction Layer Buffer must be equal\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if (0 == IX_OSAL_MBUF_PKT_LEN(buffer)) + { + ICP_HSSACC_REPORT_ERROR("HssAccTxDatapathBufferValidityCheck - " + "Buffer length cannot be 0\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if (NULL == IX_OSAL_MBUF_MDATA(buffer)) + { + ICP_HSSACC_REPORT_ERROR("HssAccTxDatapathBufferValidityCheck - " + "Pointer to data cannot be NULL\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if (ICP_HSSACC_CHAN_TYPE_VOICE == channelType) + { + /* voice buffers - check if length is not + modulo 4 (using bit comparison) */ + if (0 != (IX_OSAL_MBUF_PKT_LEN(buffer) & + (uint32_t) ICP_HSSACC_TX_VOICE_PACKET_LENGTH_CHECK_MASK)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathBufferValidityCheck - " + "Voice buffer length must be divisible " + "by 4 - buffer provided has " + "length %d\n", + IX_OSAL_MBUF_PKT_LEN(buffer)); + status = ICP_STATUS_INVALID_PARAM; + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathBufferValidityCheck\n"); + return status; +} + + +TDM_PRIVATE void +HssAccTxDatapathBufferTdmSectionUpdate(uint32_t channelId, + IX_OSAL_MBUF * buffer) +{ + icp_hssacc_osal_mbuf_tdm_io_section_t * pBufferTdmSection = + (icp_hssacc_osal_mbuf_tdm_io_section_t*)&(buffer->ix_ne); + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathBufferTdmSectionUpdate\n"); + + /* Using the data in the normal section of the OSAL Buffer, + we fill the TDM I/O private section of the buffer */ + ICP_OSAL_MBUF_TDM_SECT_CHANNEL_ID(pBufferTdmSection) = channelId; + ICP_OSAL_MBUF_TDM_SECT_STATUS(pBufferTdmSection) = 0; + + ICP_OSAL_MBUF_TDM_SECT_CURR_BUF_LEN_MSB(pBufferTdmSection) = + ICP_OSAL_MBUF_PKT_LEN_MSB(IX_OSAL_MBUF_PKT_LEN(buffer)); + + ICP_OSAL_MBUF_TDM_SECT_CURR_BUF_LEN_LSB(pBufferTdmSection) = + ICP_OSAL_MBUF_PKT_LEN_LSB(IX_OSAL_MBUF_PKT_LEN(buffer)); + + ICP_OSAL_MBUF_TDM_SECT_DATA(pBufferTdmSection) = IX_OSAL_MBUF_MDATA(buffer); + ICP_OSAL_MBUF_TDM_SECT_PKT_LEN(pBufferTdmSection) = 0; + + ICP_OSAL_MBUF_TDM_SECT_NEXT_BUF(pBufferTdmSection) = NULL; + ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(pBufferTdmSection) = buffer; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathBufferTdmSectionUpdate\n"); +} + + + +/* This function requires the OSAL buffer to have been filled + with the correct data in the TDM I/O specific section */ +TDM_PRIVATE void +HssAccTxDatapathQueueEntryCreate(IX_OSAL_MBUF * buffer, + icp_hssacc_tdm_io_queue_entry_t * qEntry) +{ + /* initialise this pointer to the start of the TDM I/O Private section + of the OSAL buffer passed as a parameter */ + icp_hssacc_osal_mbuf_tdm_io_section_t * pBufferTdmSection = + (icp_hssacc_osal_mbuf_tdm_io_section_t*)&(buffer->ix_ne); + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathQueueEntryCreate\n"); + /* Create the first word of the Q Entry using the first word of the TDM I/O + Section of the buffer passed */ + qEntry->descriptor.word = + pBufferTdmSection->tdm_io_entry.descriptor.word; + + /* Endianness Swap done by translation function */ + ICP_TDM_IO_Q_ENTRY_DATA(qEntry) = + (void*)HssAccVirtToPhysAddressTranslateAndSwap( + ICP_OSAL_MBUF_TDM_SECT_DATA(pBufferTdmSection)); + + /* This field is not used for Tx */ + ICP_TDM_IO_Q_ENTRY_PKT_LEN(qEntry) = 0; + + ICP_TDM_IO_Q_ENTRY_OSAL_MBUF(qEntry) = + (IX_OSAL_MBUF*)HssAccVirtToPhysAddressTranslateAndSwap(buffer); + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathQueueEntryCreate\n"); +} + +icp_status_t +icp_HssAccTransmit (uint32_t channelId, + IX_OSAL_MBUF *buffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + icp_hssacc_tdm_io_queue_entry_t qEntry; + icp_boolean_t mutexLocked = ICP_FALSE; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccTransmit\n"); + +#ifndef NDEBUG + if (ICP_TRUE != hssAccTxServiceInitialised) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccTransmit - Service not initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccTransmit - invalid ChannelId\n"); + status = ICP_STATUS_INVALID_PARAM; + } + else + { + hssAccTxNumPktsSubmissions[channelId] ++; + } + if (NULL == buffer) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccTransmit - Invalid Buffer\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + +#endif + + + if (ICP_STATUS_SUCCESS == status) + { + /* Check the Buffer validity */ + status = + HssAccTxDatapathBufferValidityCheck(buffer, + HssAccChannelConfigTypeQuery( + channelId)); + } + if (ICP_STATUS_SUCCESS == status) + { + /* Lock the Datapath on Transmit */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccTransmit - " + "Mutex Lock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + mutexLocked = ICP_TRUE; + if (ICP_TRUE == hssAccDataPlaneTxBypass[channelId]) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccTransmit - " + "Tx not allowed, Channel %d is bypassed\n", + channelId); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Check the Channel Type and Queue Level. reject if above level and + previous submission was accepted */ + if ((ICP_HSSACC_CHAN_TYPE_VOICE == + HssAccChannelConfigTypeQuery(channelId)) && + (ICP_HSSACC_TX_Q_WATERMARK_LEVEL <= + hssAccTxDatapathNumPendPkts[channelId]) && + (ICP_TRUE == hssAccTxDatapathLastSubmitSuccess[channelId])) + { + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "icp_HssAccTransmit - " + "Regulating Tx Flow for channel %d\n", + channelId); + status = ICP_STATUS_OVERFLOW; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + HssAccDataEndiannessSwap(buffer); + HssAccTxDatapathBufferTdmSectionUpdate(channelId, + buffer); + /* Create the Queue Entry for the Q */ + HssAccTxDatapathQueueEntryCreate(buffer, + &qEntry); + /* Submit the Entry to the Queue */ + status = ixQMgrQWrite (HssAccQueueIdGet(channelId), + (IxQMgrQEntryType *)&qEntry); + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Push the Buffer Ptr onto the Ring */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_ADD(hssAccDataPlaneTxDescRing[channelId], + buffer); + hssAccTxDatapathNumPendPkts[channelId] ++; + hssAccTxDatapathLastSubmitSuccess[channelId] = ICP_TRUE; +#ifndef NDEBUG + hssAccTxNumPktsSuccessSubmissions[channelId] ++; +#endif + } + else + { + hssAccTxDatapathLastSubmitSuccess[channelId] = ICP_FALSE; + } + + /* Unlock the datapath */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccTransmit - " + "Mutex Unlock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccTransmit\n"); + return status; +} + + + +icp_status_t +icp_HssAccTxDoneRetrieve (uint32_t channelId, + IX_OSAL_MBUF **buffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t entry = 0; + icp_boolean_t mutexLocked = ICP_FALSE; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccTxDoneRetrieve\n"); +#ifndef NDEBUG + if (ICP_TRUE != hssAccTxServiceInitialised) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccTxDoneRetrieve - " + "Service not initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_HSSACC_MAX_NUM_CHANNELS <= channelId) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccTxDoneRetrieve - " + "invalid ChannelId\n"); + status = ICP_STATUS_INVALID_PARAM; + } + if (NULL == buffer) + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccTxDoneRetrieve - " + "Invalid Buffer\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } +#endif + + if (ICP_STATUS_SUCCESS == status) + { + /* Lock the datapath for this Q */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccTxDoneRetrieve - " + "Mutex Lock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + if (ICP_STATUS_SUCCESS == status) + { + mutexLocked = ICP_TRUE; + /* The Shadow counter allows us to keep track of the number of + transmissions completed by the TDM I/O Unit: real Tail - shadow Tail = + number of transmits completed by unit since last servicing. here we are + retrieving the oldest completed transmission so increment the shadow + counter by 1 */ + status = ixQMgrShadowAdvance(HssAccQueueIdGet(channelId), + IX_QMGR_Q_SHADOW_TAIL_ONLY, + 1); + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Get the Buffer Ptr from the Ring */ + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM(hssAccDataPlaneTxDescRing[channelId], + entry); + *buffer = (IX_OSAL_MBUF*)entry; + hssAccTxDatapathNumPendPkts[channelId] --; +#ifndef NDEBUG + hssAccTxNumPktsDone[channelId] ++; +#endif + } + + /* Unlock datapath */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccTxDoneRetrieve - " + "Mutex Unlock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccTxDoneRetrieve\n"); + return status; +} + + + +icp_status_t +HssAccTxDatapathChanBypassStateSet(uint32_t channelId, + icp_boolean_t bypassed) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathChanBypassedSet\n"); + /* Lock the Tx Datapath Mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChanBypassSet - " + "Mutex Lock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + else + { + hssAccDataPlaneTxBypass[channelId] = bypassed; + + /* Unlock the mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDapapathChanBypassedSet - " + "Mutex Unlock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathChanBypassedSet\n"); + return status; +} + + +void +HssAccTxDatapathChanTxDoneCallbackRegister( + uint32_t channelId, + icp_hssacc_tx_done_callback_t txDoneCallback, + icp_user_context_t userContext) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathChanTxDoneCallbackRegister\n"); + hssAccTxDoneChannelCallbacks[channelId] = txDoneCallback; + hssAccTxDoneUserContext[channelId] = userContext; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathChanTxDoneCallbackRegister\n"); +} + +/****************************************************************************** + * Abstract: + * Register rx callback and user context + * + ******************************************************************************/ +void +HssAccTxDatapathChanTxDoneCallbackDeregister(uint32_t channelId) +{ + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccChannelRxCallbackDeregister\n"); + + hssAccTxDoneChannelCallbacks[channelId] = NULL; + hssAccTxDoneUserContext[channelId] = 0; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccChannelRxCallbackDeregister\n"); +} + + + +/* Service all channels of the specified channel Type: find any completed + transmissions by the TDM I/O Unit and report them to the client */ +icp_status_t +HssAccTxDatapathService(icp_hssacc_channel_type_t channelType) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t index = 0; + uint32_t numEntries = 0; + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathService\n"); + + /* cycle through the channels for this service */ + for (; index < ICP_HSSACC_MAX_NUM_CHANNELS; index ++) + { + numEntries = 0; + /* check if servicing is required on TxDone and use the callback + if this is the case */ + if (channelType == HssAccChannelConfigTypeQuery(index)) + { + if (ICP_HSSACC_CHANNEL_ENABLED != + HssAccChannelConfigStateQuery(index)) + { + /* This channel has been configured for this service but it is + not enabled, Datapath functionality is not enabled yet */ + continue; + } + status = ixQMgrShadowDeltaGet(HssAccQueueIdGet(index), + IX_QMGR_Q_SHADOW_TAIL_ONLY, + &numEntries); + } + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccTxDatapathService - " + "Couldnt determine Queue level for " + "channel %d\n", + index); + break; + } + if (0 < numEntries) + { + if (NULL != hssAccTxDoneChannelCallbacks[index]) + { + hssAccTxDoneChannelCallbacks[index]( + hssAccTxDoneUserContext[index]); + } + else + { + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathService - " + "Channel %d has no TxDone callback\n", + index); + } + ICP_HSSACC_DP_TRACE_1 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathService - Channel %d Serviced\n", + index); + } + } + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathService\n"); + + return status; +} + + + +/* Retrieve all buffers left over on the specified channel, + channel must be disabled */ +icp_status_t +HssAccTxDatapathChannelBuffersRetrieve(uint32_t channelId, + IX_OSAL_MBUF * * startChainBuffer, + IX_OSAL_MBUF * * endChainBuffer) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t numEntries = 0; + uint32_t entry = 0; + IX_OSAL_MBUF * pCurrentBuffer = NULL; + icp_boolean_t mutexLocked = ICP_FALSE; + icp_boolean_t chainStarted = ICP_FALSE; + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccTxDatapathChannelBuffersRetrieve\n"); + + /* Lock the datapath for this Q */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_LOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChannelBuffersRetrieve - " + "Mutex Lock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathChannelBuffersRetrieve - " + "Recycle Tx Done Buffers\n"); + + mutexLocked = ICP_TRUE; + status = ixQMgrShadowDeltaGet(HssAccQueueIdGet(channelId), + IX_QMGR_Q_SHADOW_TAIL_ONLY, + &numEntries); + + if ((ICP_STATUS_SUCCESS == status) && + (0 != numEntries)) + { + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathChannelBuffersRetrieve - " + "Update the QMgr for TxDone\n"); + status = ixQMgrShadowAdvance(HssAccQueueIdGet(channelId), + IX_QMGR_Q_SHADOW_TAIL_ONLY, + numEntries); + + if (ICP_STATUS_SUCCESS == status) + { + numEntries --; + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + hssAccDataPlaneTxDescRing[channelId], + entry); + + *startChainBuffer = (IX_OSAL_MBUF*)entry; + pCurrentBuffer = (IX_OSAL_MBUF*)entry; + chainStarted = ICP_TRUE; +#ifndef NDEBUG + hssAccTxNumPktsDone[channelId] ++; +#endif + } + } + } + + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathChannelBuffersRetrieve - " + "Create Chain with Tx Done Buffers\n"); + + for (; numEntries > 0; numEntries --) + { + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + hssAccDataPlaneTxDescRing[channelId], + entry); + + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(pCurrentBuffer) = + (IX_OSAL_MBUF*)entry; + pCurrentBuffer = (IX_OSAL_MBUF*)entry; +#ifndef NDEBUG + hssAccTxNumPktsDone[channelId] ++; +#endif + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathChannelBuffersRetrieve - " + "Recycle Tx Pending Buffers\n"); + + status = ixQMgrQNumEntriesGet(HssAccQueueIdGet(channelId), + &numEntries); + } + if ((ICP_STATUS_SUCCESS == status) && + (0 != numEntries)) + { + /* Update Queue Head counter */ + status = ixQMgrQWriteRollback(HssAccQueueIdGet(channelId), + numEntries); + + } + if (ICP_STATUS_SUCCESS == status) + { + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_DEBUG, + "HssAccTxDatapathChannelBuffersRetrieve - " + "Append Chain with Tx Buffers\n"); + if ((ICP_FALSE == chainStarted) && + (0 != numEntries)) + { + numEntries --; + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + hssAccDataPlaneTxDescRing[channelId], + entry); + + *startChainBuffer = (IX_OSAL_MBUF*)entry; + pCurrentBuffer = (IX_OSAL_MBUF*)entry; +#ifndef NDEBUG + hssAccTxNumPktsDone[channelId] ++; +#endif + } + for (; numEntries > 0; numEntries --) + { + ICP_HSSACC_DATAPLANE_RING_ENTRY_REM( + hssAccDataPlaneTxDescRing[channelId], + entry); + + IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(pCurrentBuffer) = + (IX_OSAL_MBUF*)entry; + pCurrentBuffer = (IX_OSAL_MBUF*)entry; +#ifndef NDEBUG + hssAccTxNumPktsDone[channelId] ++; +#endif + } + + *endChainBuffer = pCurrentBuffer; + hssAccTxDatapathNumPendPkts[channelId] = 0; + } + + /* Unlock datapath */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_TX_DP_MUTEX_UNLOCK(channelId)) + { + ICP_HSSACC_REPORT_ERROR_1("HssAccTxDatapathChannelBuffersRetrieve - " + "Mutex Unlock Error for channel %d\n", + channelId); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_DP_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccTxDatapathChannelBuffersRetrieve\n"); + return status; +} + + diff --git a/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_voice_bypass.c b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_voice_bypass.c new file mode 100644 index 0000000..591b00b --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/icp_hssacc_voice_bypass.c @@ -0,0 +1,776 @@ +/****************************************************************************** + * @file icp_hssacc_timeslot_switching.c + * + * @description Contents of this file provide the implementation of all + * Timeslot switching functionality as described the icp_hssacc.h header file + * + * @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 "IxOsal.h" + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_trace.h" +#include "icp_hssacc_common.h" +#include "icp_hssacc_channel_config.h" +#include "icp_hssacc_voice_bypass.h" +#include "icp_hssacc_address_translate.h" +#include "icp_hssacc_tx_datapath.h" + + + +/* Stats */ +typedef struct icp_hssacc_bypass_stats_s +{ + icp_hssacc_msg_with_resp_stats_t gctLoad; + icp_hssacc_msg_with_resp_stats_t gainCfg; + icp_hssacc_msg_with_resp_stats_t bypassEnable; + icp_hssacc_msg_with_resp_stats_t bypassDisable; +} icp_hssacc_bypass_stats_t; + + + +/* Internal GCT info */ +typedef struct icp_hssacc_gct_internal_data_s +{ + icp_boolean_t configured; + unsigned numBypassUsing; +} icp_hssacc_gct_internal_data_t; + + + +/* Internal Timeslot switch info */ +typedef struct icp_hssacc_bypass_internal_data_s +{ + icp_boolean_t enabled; + unsigned srcChannelId; + unsigned destChannelId; + unsigned portId; + unsigned gctId; +} icp_hssacc_bypass_internal_data_t; + +TDM_PRIVATE icp_hssacc_gct_internal_data_t +hssAccGctData[ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS]; + +TDM_PRIVATE icp_hssacc_bypass_internal_data_t +hssAccBypassData[ICP_HSSACC_MAX_NUM_VOICE_BYPASSES]; + +TDM_PRIVATE icp_boolean_t channelSwitchModuleInitialised = ICP_FALSE; + +TDM_PRIVATE icp_hssacc_bypass_stats_t hssAccBypassStats; + + + +/****************************************************************************** + * Abstract: + * Initialise the Voice bypass module + * + *****************************************************************************/ +void +HssAccVoiceBypassInit(void) +{ + unsigned index = 0; + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccVoiceBypassInit\n"); + if (ICP_TRUE == channelSwitchModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR("HssAccVoiceBypassInit - module already " + "initialised\n"); + } + else + { + + for (;index < ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS; index ++) + { + hssAccGctData[index].configured = ICP_FALSE; + hssAccGctData[index].numBypassUsing = 0; + } + + for (index = 0; index < ICP_HSSACC_MAX_NUM_VOICE_BYPASSES; index ++) + { + hssAccBypassData[index].enabled = ICP_FALSE; + hssAccBypassData[index].srcChannelId = ICP_HSSACC_MAX_NUM_CHANNELS; + hssAccBypassData[index].destChannelId = ICP_HSSACC_MAX_NUM_CHANNELS; + hssAccBypassData[index].portId = ICP_HSSACC_MAX_NUM_PORTS; + hssAccBypassData[index].gctId = ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS; + } + + HssAccBypassStatsReset(); + + channelSwitchModuleInitialised = ICP_TRUE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccVoiceBypassInit\n"); + +} + + +/****************************************************************************** + * Abstract: + * Shutdown the Voice Bypass module. + * + *****************************************************************************/ +icp_status_t +HssAccVoiceBypassShutdown(void) +{ + unsigned index = 0; + icp_status_t status = ICP_STATUS_SUCCESS; + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering HssAccVoiceBypassShutdown\n"); + if (ICP_TRUE != channelSwitchModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR("HssAccVoiceBypassShutdown - module has not " + "already been initialised\n"); + status = ICP_STATUS_FAIL; + } + + for (index = 0; index < ICP_HSSACC_MAX_NUM_VOICE_BYPASSES; index ++) + { + if (ICP_TRUE == hssAccBypassData[index].enabled) + { + ICP_HSSACC_REPORT_ERROR_1 ("HssAccVoiceBypassShutdown - " + "Bypass %u is still enabled, can't" + " shutdown\n", + index); + status = ICP_STATUS_RESOURCE; + } + } + if (ICP_STATUS_SUCCESS == status) + { + for (index = 0;index < ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS; index ++) + { + hssAccGctData[index].configured = ICP_FALSE; + hssAccGctData[index].numBypassUsing = 0; + } + channelSwitchModuleInitialised = ICP_FALSE; + } + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting HssAccVoiceBypassShutdown\n"); + return status; +} + + + +/****************************************************************************** + * Abstract: + * Returns the number of supported Gain Control Tables. + * + *****************************************************************************/ +unsigned +icp_HssAccNumSupportedGCTsGet ( void ) +{ + return ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS; +} + + +/****************************************************************************** + * Abstract: + * returns the number of Voice bypasses supported + * + *****************************************************************************/ +unsigned +icp_HssAccNumSupportedVoiceBypassesGet ( void ) +{ + return ICP_HSSACC_MAX_NUM_VOICE_BYPASSES; +} + +/****************************************************************************** + * Abstract: + * Download the provided Gain Control Table to the TDM I/O Unit. + * + *****************************************************************************/ +icp_status_t +icp_HssAccVoiceBypassGctDownload (unsigned voiceBypassGct, + uint8_t *gainCtrlTable) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + uint32_t physAddr = 0; + IxPiuMhMessage message; + icp_boolean_t mutexLocked = ICP_FALSE; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccVoiceBypassGctDownload " + "for Table %u\n", + voiceBypassGct); + + if (ICP_FALSE == channelSwitchModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassGctDownload - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if ((voiceBypassGct >= ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS)|| + (NULL == gainCtrlTable)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassGctDownload - " + "invalid parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + else if (0 != + ((uint32_t)gainCtrlTable & ICP_HSSACC_DBLE_WD_ALIGN_MASK)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassGctDownload - " + "invalid alignment for GCT memory " + "location\n"); + status = ICP_STATUS_INVALID_PARAM; + } + + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassGctDownload - " + "failed to lock HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + else + { + mutexLocked = ICP_TRUE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Check if this Gain Control table has already been configured + and if it is already in use for a bypass, we only allow configuration + of the GCT if it is not in use by any bypass */ + if (0 != hssAccGctData[voiceBypassGct].numBypassUsing) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassGctDownload - " + "GCT is currently in use by 1 " + "or more bypasses\n"); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Send Configuration to TDM I/O Unit and save it in + Access for Stats purposes */ + + + /* Convert the table base address to a physical address */ + physAddr = + HssAccVirtToPhysAddressTranslate(gainCtrlTable); + + /* Construct the message to load the table */ + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_GCT_LOAD, + 0, + 0, + voiceBypassGct, + physAddr, + &message); + /* Send the message to the TDM I/O Unit and wait for its reply */ + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_GCT_LOAD_RESPONSE, + &(hssAccBypassStats.gctLoad), + NULL); + + if (ICP_STATUS_SUCCESS == status) + { + hssAccGctData[voiceBypassGct].configured = ICP_TRUE; + } + else + { + ICP_HSSACC_REPORT_ERROR("icp_HssAccVoiceBypassGctDownload - " + "failed to set Table in TDM I/O Unit\n"); + } + + } + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassGctDownload - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccVoiceBypassGctDownload\n"); + return status; +} + + + + + +/****************************************************************************** + * Abstract: + * Enable the specified Voice bypass between the specified source and + * destination channels. + * + *****************************************************************************/ +icp_status_t +icp_HssAccVoiceBypassEnable (unsigned portId, + unsigned voiceBypassId, + unsigned voiceBypassGct, + unsigned srcChannelId, + unsigned destChannelId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + icp_boolean_t mutexLocked = ICP_FALSE; + unsigned index = 0; + ICP_HSSACC_TRACE_2 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccVoiceBypassEnable for Table %u " + "on bypass %u\n", + voiceBypassGct, + voiceBypassId); + + if (ICP_FALSE == channelSwitchModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassEnable - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if ((portId >= ICP_HSSACC_MAX_NUM_PORTS) || + (voiceBypassId >= ICP_HSSACC_MAX_NUM_VOICE_BYPASSES) || + (voiceBypassGct >= ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassEnable - invalid " + "Bypass configuration parameter\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + if ((ICP_HSSACC_MAX_NUM_CHANNELS <= srcChannelId) || + (ICP_HSSACC_MAX_NUM_CHANNELS <= destChannelId)) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassEnable - Channels " + "selected for bypass are invalid\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassEnable - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + mutexLocked = ICP_TRUE; + + if (ICP_TRUE == hssAccBypassData[voiceBypassId].enabled) + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccVoiceBypassEnable - Selected " + "bypass (%u) is already enabled; it must " + "be disabled first before " + "reconfiguring\n", + voiceBypassId); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if (ICP_TRUE != hssAccGctData[voiceBypassGct].configured) + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccVoiceBypassEnable - Selected " + "Gain Control Table (%u) is not " + "configured, need to configure it first\n", + voiceBypassGct); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + for (index = 0; index < ICP_HSSACC_MAX_NUM_VOICE_BYPASSES; index ++) + { + if ((hssAccBypassData[index].srcChannelId == srcChannelId) || + (hssAccBypassData[index].destChannelId == destChannelId)) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccVoiceBypassEnable - " + "One of the channels selected is " + "already used in a identical role " + "for bypass %u\n", + index); + status = ICP_STATUS_RESOURCE; + break; + } + } + } + + if (ICP_STATUS_SUCCESS == status) + { + if ( (ICP_FALSE == HssAccChannelConfigValidBypass(srcChannelId,portId)) || + (ICP_FALSE == HssAccChannelConfigValidBypass(destChannelId,portId))) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassEnable - Channel(s) " + "selected for bypass is(are) not " + "appropriate (Narrowband Enabled Channels " + "only on same port)\n"); + status = ICP_STATUS_RESOURCE; + } + } + + + if (ICP_STATUS_SUCCESS == status) + { + /* Link the Bypass to the Gain Control Table */ + + HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_BYPASS_GAIN_CFG, + portId, + voiceBypassId, + voiceBypassGct, + 0, + &message); + + + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_BYPASS_GAIN_CFG_RESPONSE, + &(hssAccBypassStats.gainCfg), + NULL); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_2("icp_HssAccVoiceBypassEnable - " + "Failed to link GCT %u with Voice " + "Bypass %u on the TDM I/O Unit\n", + voiceBypassGct, + voiceBypassId); + } + + + + if (ICP_STATUS_SUCCESS == status) + { + /* Configure the Bypass*/ + + HssAccComTdmIOUnitCmd8byteMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_BYPASS_ENABLE, + portId, + voiceBypassId, + srcChannelId, + destChannelId, + 0, 0, 0, + &message); + + + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_BYPASS_ENABLE_RESPONSE, + &(hssAccBypassStats.bypassEnable), + NULL); + + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccVoiceBypassEnable - " + "Failed to enable Voice " + "Bypass %u on the TDM I/O Unit\n", + voiceBypassId); + } + + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Save bypass config and send new channel state to tx */ + hssAccBypassData[voiceBypassId].enabled = ICP_TRUE; + hssAccBypassData[voiceBypassId].portId = portId; + hssAccBypassData[voiceBypassId].srcChannelId = srcChannelId; + hssAccBypassData[voiceBypassId].destChannelId = destChannelId; + hssAccBypassData[voiceBypassId].gctId = voiceBypassGct; + hssAccGctData[voiceBypassGct].numBypassUsing ++; + + /* Notify the Tx Datapath and config modules that this channel is + bypassed */ + HssAccTxDatapathChanBypassStateSet(destChannelId, + ICP_TRUE); + HssAccChannelBypassPairSet(srcChannelId, destChannelId); + } + } + + + + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassEnable - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccVoiceBypassEnable\n"); + return status; +} + + + + +/****************************************************************************** + * Abstract: + * disable the specified Voice bypass. + * + *****************************************************************************/ +icp_status_t +icp_HssAccVoiceBypassDisable (unsigned voiceBypassId) +{ + icp_status_t status = ICP_STATUS_SUCCESS; + IxPiuMhMessage message; + icp_boolean_t mutexLocked = ICP_FALSE; + unsigned gctId = ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS; + ICP_HSSACC_TRACE_1 (ICP_HSSACC_FN_ENTRY_EXIT, + "Entering icp_HssAccVoiceBypassDisable for Bypass %u\n", + voiceBypassId); + + if (ICP_FALSE == channelSwitchModuleInitialised) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassDisable - " + "Service is not Initialised\n"); + status = ICP_STATUS_FAIL; + } + + if (ICP_STATUS_SUCCESS == status) + { + if (voiceBypassId >= ICP_HSSACC_MAX_NUM_VOICE_BYPASSES) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassDisable - invalid " + "Bypass ID\n"); + status = ICP_STATUS_INVALID_PARAM; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Grab the HssAcc mutex */ + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_LOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassDisable - " + "failed to lock HssAcc Mutex\n"); + + status = ICP_STATUS_MUTEX; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + mutexLocked = ICP_TRUE; + + if (ICP_TRUE != hssAccBypassData[voiceBypassId].enabled) + { + ICP_HSSACC_REPORT_ERROR_1 ("icp_HssAccVoiceBypassDisable - Selected " + "bypass (%u) is not enabled\n", + voiceBypassId); + status = ICP_STATUS_RESOURCE; + } + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Configure the Bypass*/ + + HssAccComTdmIOUnitCmd8byteMsgCreate ( + ICP_HSSACC_TDM_IO_UNIT_BYPASS_DISABLE, + hssAccBypassData[voiceBypassId].portId, + voiceBypassId, + 0, + 0, 0, 0, 0, + &message); + + + status = + HssAccComTdmIOUnitMsgSendAndRecv( + message, + ICP_HSSACC_TDM_IO_UNIT_BYPASS_DISABLE_RESPONSE, + &(hssAccBypassStats.bypassDisable), + NULL); + if (ICP_STATUS_SUCCESS != status) + { + ICP_HSSACC_REPORT_ERROR_1("icp_HssAccVoiceBypassDisable - " + "Failed to disable Voice " + "Bypass %u on the TDM I/O Unit\n", + voiceBypassId); + } + + + } + + if (ICP_STATUS_SUCCESS == status) + { + /* Save bypass config and send new channel state to tx */ + hssAccBypassData[voiceBypassId].enabled = ICP_FALSE; + gctId = hssAccBypassData[voiceBypassId].gctId; + hssAccBypassData[voiceBypassId].portId = ICP_HSSACC_MAX_NUM_PORTS; + hssAccBypassData[voiceBypassId].gctId = + ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS; + hssAccGctData[gctId].numBypassUsing --; + + /* Notify the Tx Datapath module that this channel is + no longer bypassed */ + HssAccTxDatapathChanBypassStateSet( + hssAccBypassData[voiceBypassId].destChannelId, + ICP_FALSE); + + HssAccChannelBypassPairClear( + hssAccBypassData[voiceBypassId].srcChannelId, + hssAccBypassData[voiceBypassId].destChannelId); + + hssAccBypassData[voiceBypassId].srcChannelId = + ICP_HSSACC_MAX_NUM_CHANNELS; + hssAccBypassData[voiceBypassId].destChannelId = + ICP_HSSACC_MAX_NUM_CHANNELS; + } + + /* Free the HssAcc mutex */ + if (ICP_TRUE == mutexLocked) + { + if (ICP_STATUS_SUCCESS != ICP_HSSACC_MUTEX_UNLOCK()) + { + ICP_HSSACC_REPORT_ERROR ("icp_HssAccVoiceBypassDisable - " + "failed to release HssAcc Mutex\n"); + status = ICP_STATUS_MUTEX; + } + } + + + + ICP_HSSACC_TRACE_0 (ICP_HSSACC_FN_ENTRY_EXIT, + "Exiting icp_HssAccVoiceBypassDisable\n"); + return status; +} + + + +/****************************************************************************** + * Abstract: + * Display the stats collected by this sub-module. + * + * + *****************************************************************************/ +void +HssAccBypassStatsShow (void) +{ + + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nVoice Channel Bypass Configuration:\n" + "Gain Control Table Loading\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccBypassStats.gctLoad); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nBypass Gain Control Config messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccBypassStats.gainCfg); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nBypass Enable messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccBypassStats.bypassEnable); + ixOsalLog(IX_OSAL_LOG_LVL_MESSAGE, IX_OSAL_LOG_DEV_STDOUT, + "\nBypass Disable messaging\n", + 0, 0, 0, 0, 0, 0); + HssAccSingleMessageStatsShow (hssAccBypassStats.bypassDisable); + +} + +/****************************************************************************** + * Abstract: + * Reset the stats collected by this sub-module. + * + *****************************************************************************/ +void +HssAccBypassStatsReset (void) +{ + memset (&hssAccBypassStats, + 0, + sizeof(icp_hssacc_bypass_stats_t)); +} diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_address_translate.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_address_translate.h new file mode 100644 index 0000000..df0475d --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_address_translate.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * @file icp_hssacc_address_translate.h + * + * @description Content of this file provides the prototypes for address + * translation 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. + * + * + * + * + *****************************************************************************/ +#ifndef ICP_HSSACC_ADDRESS_TRANSLATE_H +#define ICP_HSSACC_ADDRESS_TRANSLATE_H + +#include "icp.h" + + +/***************************************************************************** + * Abstract: + * Translate a Virtual address to a physical offset, includes Endianness + * Swapping if necessary. + * + *****************************************************************************/ +uint32_t +HssAccVirtToPhysAddressTranslateAndSwap(void* virtAddr); + + + +/***************************************************************************** + * Abstract: + * Translate a physical offset to a virtual address includes endianness + * swapping and platform specific bit manipulation where required. + * + *****************************************************************************/ +void * +HssAccPhysToVirtAddressSwapAndTranslate(uint32_t physAddr); + + +/***************************************************************************** + * Abstract: + * Translate a Virtual address to a physical offset. + * + *****************************************************************************/ +uint32_t +HssAccVirtToPhysAddressTranslate(void * const virtAddr); + + + +/***************************************************************************** + * Abstract: + * Translate a physical offset to a virtual address. + * + *****************************************************************************/ +void * +HssAccPhysToVirtAddressTranslate(const uint32_t physAddr); + + + +/***************************************************************************** + * Abstract: + * Allocate a chunk of memory for DMA communication with the TDM I/O Unit. + * returns the virtual address and the physical offset as an out parameter. + * virtual Address will be NULL if allocation failed and physAddr will be + * left un-touched. + * + *****************************************************************************/ +void * +HssAccDmaMemAllocate(uint32_t sizeBytes, + uint32_t * physAddr); + + + + +/***************************************************************************** + * Abstract: + * Swap Endianness on the data of an OSAL Buffer + * + *****************************************************************************/ +void +HssAccDataEndiannessSwap(IX_OSAL_MBUF * const buffer); + +#endif /* ICP_HSSACC_ADDRESS_TRANSLATE_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_channel_config.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_channel_config.h new file mode 100644 index 0000000..c355b94 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_channel_config.h @@ -0,0 +1,269 @@ +/******************************************************************************* + * + * @file icp_hssacc_channel_config.h + * + * @description Content of this file is the Prototype definition of the API for + * the Channel Configuration module and all related Data structures shared + * by this module. + * + * @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. + * + * + * + * + ******************************************************************************/ + + +#ifndef ICP_HSSACCCHANNELCONFIG_H +#define ICP_HSSACCCHANNELCONFIG_H + +#include "icp.h" +#include "icp_hssacc.h" +#include "icp_hssacc_port_config.h" + + +#define BIT_SET(index) (1 << index) + + +/* + * ---------------------------------------------------------------------------- + * Enumerated types + * ---------------------------------------------------------------------------- + */ + +/* Enum for the various states a channel can be in */ +typedef enum +{ + ICP_HSSACC_CHANNEL_UNINITIALISED = 0, + ICP_HSSACC_CHANNEL_ALLOCATED, + ICP_HSSACC_CHANNEL_CONFIGURED, + ICP_HSSACC_CHANNEL_SERVICE_CONFIGURED, + ICP_HSSACC_CHANNEL_DOWN, + ICP_HSSACC_CHANNEL_ENABLED, + ICP_HSSACC_CHANNEL_DOWN_TRANSITION +} icp_hssacc_channel_state_t; + + + +/* + Definition of the structure containing all Channel + configuration Data +*/ +typedef struct icp_hssacc_channel_config_s +{ + icp_hssacc_channel_state_t state; /* Current state of the channel */ + icp_hssacc_channel_type_t type; /* Voice or data */ + unsigned size; /* Size of the channel in timeslots */ + unsigned portId; /* HSS port number for the channel */ + icp_hssacc_line_t lineId; /* TDM line number for the channel */ + uint32_t timeslotMap; /* Timeslots reserved for the channel */ + uint32_t sdcCtrlReg; /* Common channel settings */ + uint32_t rxCfg; /* HDLC Rx settings */ + uint32_t txCfg; /* HDLC Tx settings */ + icp_boolean_t dataPolarity; /* polarity of the data */ + icp_hssacc_bit_endian_t bitEndian; /* specifies endianness of the chan */ + icp_boolean_t byteSwap; /* byteSwapping on/off */ + icp_hssacc_robbed_bit_value_t rBitValue; /* value 0/1 of robbed bit */ + icp_hssacc_robbed_bit_location_t rBitLocation; + /* location of the robbed bit in the byte */ + icp_hssacc_bit_robbing_t bitRobbing; /* bit robbing used or not */ + + /* HDLC specific */ + icp_hssacc_hdlc_sof_flag_type_t sofFlagType; /* start of frame */ + icp_hssacc_hdlc_idle_pattern_t hdlcTxIdlePattern; /* idle pattern to Tx */ + icp_hssacc_hdlc_idle_pattern_t hdlcRxIdlePattern; /* expected idle on rx */ + icp_hssacc_hdlc_crc_bit_width_t hdlcCrcBitWidth; /* CRC size */ + uint32_t hdlcMaxFrSize; /* maximum frame size on rx */ + + /* VOICE specific */ + uint32_t voiceSampleSize; /* size of voice samples */ + uint8_t voiceIdlePattern; /* voice silence pattern */ + icp_hssacc_channel_voice_tx_idle_action_t txIdleAction; + /* tx silence or repeat last frame */ + + unsigned numBypasses; /* channel can be involved in up to 2 bypasses, + one as source, one as destination */ +} icp_hssacc_channel_config_t; + +/* ---------------------------------------------------------------------------- + * Function declarations + * ---------------------------------------------------------------------------- + */ +/***************************************************************************** + * Abstract: + * Initialise the Channel Configuration module + * + *****************************************************************************/ +icp_status_t +HssAccChannelConfigInit(void); + + +/***************************************************************************** + * Abstract: + * shutdown the Channel Configuration module + * + *****************************************************************************/ +icp_status_t +HssAccChannelConfigShutdown(void); + + + +/***************************************************************************** + * Abstract: + * Reset the internal stats gathered by this module + * + *****************************************************************************/ +void +HssAccChannelConfigStatsReset (void); + + + +/***************************************************************************** + * Abstract: + * display all stats gathered by this module. + * + *****************************************************************************/ +void +HssAccChannelConfigStatsShow (void); + + + +/***************************************************************************** + * Abstract: + * display the state of the specified channel + * + *****************************************************************************/ +void +HssAccChannelConfigStateShow (unsigned channelId); + + +/***************************************************************************** + * Abstract: + * check whether it is valid to configure a bypass on the specified + * channel. + * + *****************************************************************************/ +icp_boolean_t +HssAccChannelConfigValidBypass(const unsigned channelId, + const unsigned portId); + + +/***************************************************************************** + * Abstract: + * set the 2 specified channels as part of a bypass + * + *****************************************************************************/ +void +HssAccChannelBypassPairSet(unsigned srcChannelId, + unsigned destChannelId); + + +/***************************************************************************** + * Abstract: + * clear the 2 specified channels from any bypass connection + * + *****************************************************************************/ +void +HssAccChannelBypassPairClear(unsigned srcChannelId, + unsigned destChannelId); + + +/***************************************************************************** + * Abstract: + * query the service to which the specified channel is associated, Voice + * or HDLC. + * + *****************************************************************************/ +icp_hssacc_channel_type_t +HssAccChannelConfigTypeQuery (unsigned channelId); + + + +/***************************************************************************** + * Abstract: + * query the current state of the specified channel. + * + *****************************************************************************/ +icp_hssacc_channel_state_t +HssAccChannelConfigStateQuery (unsigned channelId); + + + +/***************************************************************************** + * Abstract: + * notify the Channel Configuration module that all buffers associated + * with this channel have been retrieved. + * + *****************************************************************************/ +void +HssAccChannelConfigBuffersClearedNotify (unsigned channelId); + + + +/***************************************************************************** + * Abstract: + * query whether there are any channels allocated on the specified port. + * + *****************************************************************************/ +icp_boolean_t +HssAccChannelConfigUsedChansOnPortFind (const unsigned portId); +#endif /* ICP_HSSACCCHANNELCONFIG_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_channel_list.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_channel_list.h new file mode 100644 index 0000000..df939fc --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_channel_list.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * @file icp_hssacc_channel_list.h + * + * @description Content of this file includes the prototypes for channel + * list manipulations + * + * @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. + * + * + * + * + *****************************************************************************/ +#ifndef ICP_HSSACC_CHANNEL_LIST_H +#define ICP_HSSACC_CHANNEL_LIST_H + + +#include "icp.h" + +/***************************************************************************** + * Abstract + * Reset All the channels lists + * + *****************************************************************************/ +void HssAccChannelListsReset (void); + + +/***************************************************************************** + * Abstract + * Add a channel to one of the lists for processing. + * + *****************************************************************************/ +icp_status_t HssAccChannelListAdd (unsigned hssPortId, + unsigned chanId, + unsigned chanSize); + + + + +/***************************************************************************** + * Abstract + * Remove the specified channel from processing lists. + * + *****************************************************************************/ +icp_status_t HssAccChannelListRemove (unsigned hssPortId, + unsigned chanId, + unsigned chanSize); + + +/***************************************************************************** + * Abstract + * Retrieve the ID of the last channel being processed on a specific port + * and a specific list + * + *****************************************************************************/ +unsigned +HssAccChannelListLastPortChannelGet (unsigned portId, + icp_hssacc_channel_list_t listId); + +/***************************************************************************** + * Abstract + * Retrieve the prev channel to processed in the list this channel + * belongs to. + * + *****************************************************************************/ +unsigned +HssAccChannelListPrevChannelOnListGet(unsigned channelId); + + +/***************************************************************************** + * Abstract + * Reset the messaging stats for Channel List management. + * + *****************************************************************************/ +void +HssAccChannelListsStatsReset (void); + + +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_common.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_common.h new file mode 100644 index 0000000..c839e53 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_common.h @@ -0,0 +1,978 @@ +/****************************************************************************** + * @file icp_hssacc_common.h + * + * @description this file contains value definitions and function prototypes + * that are common accross all the HSS Access component + * + * @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. + * Copyright(c) 2010,2011,2012 Avencall + * + * 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. + * + * BSD LICENSE + * + * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + * All rights reserved. + * Copyright(c) 2010,2011,2012 Avencall + * + * 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. + * + * + * + *****************************************************************************/ + + +#ifndef ICP_HSSACCCOMMON_H +#define ICP_HSSACCCOMMON_H + +#include "IxOsal.h" +#include "icp.h" +#include "IxPiuMh.h" +#include "IxPiuDl.h" +#include "icp_hssacc.h" + + +#if !defined(TDM_PRIVATE) +#define TDM_PRIVATE static +#else +#define TDM_PRIVATE +#endif +#ifdef IXP23XX +#define ICP_HSSACC_MAX_NUM_CHANNELS (128) +#endif +#ifdef TOLAPAI +#define ICP_HSSACC_MAX_NUM_CHANNELS (128) +#endif + + +/* + * This macro represents an invalid Channel + */ +#define ICP_HSSACC_INVALID_CHAN ICP_HSSACC_MAX_NUM_CHANNELS + + + +#ifdef TOLAPAI +#define ICP_HSSACC_MAX_NUM_PORTS 3 +#else +#ifdef IXP23XX +#define ICP_HSSACC_MAX_NUM_PORTS 4 +#endif +#endif + +#define ICP_HSSACC_MAX_NUM_VOICE_BYPASS_GCTS 4 + +#define ICP_HSSACC_MAX_NUM_VOICE_BYPASSES 4 + +/* ---------------------------------------------------------------------------- + * Externs + * ---------------------------------------------------------------------------- + */ +/* Mutex which controls access to control path functions */ +extern IxOsalMutex hssAccControlPathMutex; + + +/* ---------------------------------------------------------------------------- + * Defines and Macros. + * ---------------------------------------------------------------------------- + */ +/* + * Timeout value in ms + */ +#define ICP_HSSACC_MUTEX_TIMEOUT 10 + +/* + * Initialises the service mutex. + */ +#define ICP_HSSACC_MUTEX_INIT() (ixOsalMutexInit(&hssAccControlPathMutex)) + +/* + * Locks the service mutex. + */ +#define ICP_HSSACC_MUTEX_LOCK() (ixOsalMutexLock( \ + &hssAccControlPathMutex,\ + ICP_HSSACC_MUTEX_TIMEOUT)) + +/* + * Unlocks the service mutex. + */ +#define ICP_HSSACC_MUTEX_UNLOCK() (ixOsalMutexUnlock(&hssAccControlPathMutex)) + +/* + * Destroys the service mutex. + */ +#define ICP_HSSACC_MUTEX_DESTROY() (\ + ixOsalMutexDestroy(&hssAccControlPathMutex)) + +/* + * The bit offset for byte 0 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET (24) + +/* + * The byte mask for byte 0 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE0_MASK (0xFF << \ + ICP_HSSACC_TDM_IO_UNIT_BYTE0_OFFSET) + +/* + * The bit offset for byte 1 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE1_OFFSET (16) + +/* + * The byte mask for byte 1 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE1_MASK (0xFF << \ + ICP_HSSACC_TDM_IO_UNIT_BYTE1_OFFSET) + +/* + * The bit offset for byte 2 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET (8) + +/* + * The byte mask for byte 2 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE2_MASK (0xFF << \ + ICP_HSSACC_TDM_IO_UNIT_BYTE2_OFFSET) + +/* + * The bit offset for byte 3 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE3_OFFSET (0) + +/* + * The byte mask for byte 3 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_BYTE3_MASK (0xFF << \ + ICP_HSSACC_TDM_IO_UNIT_BYTE3_OFFSET) + + + +/* + * The byte offset for Short 0 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_SHORT0_OFFSET (16) + +/* + * The byte mask for short 0 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_SHORT0_MASK (0xFFFF << \ + ICP_HSSACC_TDM_IO_UNIT_SHORT0_OFFSET) + +/* + * The byte offset for Short 1 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_SHORT1_OFFSET 0 + +/* + * The byte mask for Short 1 in a TDM I/O Unit message + */ +#define ICP_HSSACC_TDM_IO_UNIT_SHORT1_MASK (0xFFFF << \ + ICP_HSSACC_TDM_IO_UNIT_SHORT1_OFFSET) + + +/* + * The size of a word in bytes + */ +#define ICP_HSSACC_WORD_SIZE 4 + + +/* Mask to determine whether an address is aligned on a double + word boundary or not */ +#define ICP_HSSACC_DBLE_WD_ALIGN_MASK 0x7 + + +/* + * Mechanism to validate the upper (MAX) and lower (0) bounds + * of a positive enumeration + * + * param int [in] VALUE - the integer value to test + * param int [in] MAX - the maximum value to test against + * + * This macro returns TRUE if the bounds are invalid and FALSE if + * they are okay. NOTE: MAX will be an invalid value, so check >= + * + */ +#define ICP_HSSACC_ENUM_INVALID(VALUE, MAX) ((((VALUE) < 0) || \ + ((VALUE) >= (MAX))) ? \ + TRUE : FALSE) + + +/* + * TDM I/O Unit message commands + */ +/* + * HDMA configuration commands + */ + +/* + * Port configuration commands + */ +#define ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_LOAD (0x20) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_LOAD_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_LOAD +#define ICP_HSSACC_TDM_IO_UNIT_PORT_ENABLE (0x21) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_ENABLE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_ENABLE +#define ICP_HSSACC_TDM_IO_UNIT_PORT_DISABLE (0x22) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_DISABLE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_DISABLE +#define ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD (0x23) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_LOAD +#define ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_SWAP (0x24) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_SWAP_DONE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_PROV_TABLE_SWAP +#define ICP_HSSACC_TDM_IO_UNIT_PORT_ERROR_READ (0x25) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_ERROR_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_ERROR_READ +#define ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_READ (0x26) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_CFG_TABLE_READ +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_PORT_TS_REMAP_TABLE_LOAD (0x27) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_TS_REMAP_TABLE_LOAD_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_TS_REMAP_TABLE_LOAD +#define ICP_HSSACC_TDM_IO_UNIT_PORT_TS_REMAP_TABLE_READ (0x28) +#define ICP_HSSACC_TDM_IO_UNIT_PORT_TS_REMAP_TABLE_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_PORT_TS_REMAP_TABLE_READ +#endif + +/* + * Queue configuration commands + */ +#define ICP_HSSACC_TDM_IO_UNIT_HSS_PORT_CFG (0x40) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_PORT_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HSS_PORT_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HSS_CHAN_CFG (0x41) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_CHAN_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HSS_CHAN_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_CFG (0x42) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_CFG +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_CHAN_CFG (0x43) +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_CHAN_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_VOICE_CHAN_CFG +#define ICP_HSSACC_TDM_IO_UNIT_NEXT_CHAN_WRITE (0x44) +#define ICP_HSSACC_TDM_IO_UNIT_NEXT_CHAN_WRITE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_NEXT_CHAN_WRITE +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_RX_MAX_SIZE_WR (0x45) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_RX_MAX_SIZE_WR_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HDLC_CHAN_RX_MAX_SIZE_WR +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_ENABLE (0x46) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_ENABLE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_ENABLE +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_DISABLE (0x47) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_DISABLE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_CHAN_FLOW_DISABLE +#define ICP_HSSACC_TDM_IO_UNIT_ABT_ALN_ERR_READ (0x48) +#define ICP_HSSACC_TDM_IO_UNIT_ABT_ALN_ERR_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_ABT_ALN_ERR_READ +#define ICP_HSSACC_TDM_IO_UNIT_FCS_MAX_ERR_READ (0x49) +#define ICP_HSSACC_TDM_IO_UNIT_FCS_MAX_ERR_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_FCS_MAX_ERR_READ +#define ICP_HSSACC_TDM_IO_UNIT_STATS_READ (0x4A) +#define ICP_HSSACC_TDM_IO_UNIT_STATS_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_STATS_READ +#define ICP_HSSACC_TDM_IO_UNIT_BYPASS_ENABLE (0x4B) +#define ICP_HSSACC_TDM_IO_UNIT_BYPASS_ENABLE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_BYPASS_ENABLE +#define ICP_HSSACC_TDM_IO_UNIT_BYPASS_DISABLE (0x4C) +#define ICP_HSSACC_TDM_IO_UNIT_BYPASS_DISABLE_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_BYPASS_DISABLE +#define ICP_HSSACC_TDM_IO_UNIT_GCT_LOAD (0x4D) +#define ICP_HSSACC_TDM_IO_UNIT_GCT_LOAD_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_GCT_LOAD +#define ICP_HSSACC_TDM_IO_UNIT_BYPASS_GAIN_CFG (0x4E) +#define ICP_HSSACC_TDM_IO_UNIT_BYPASS_GAIN_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_BYPASS_GAIN_CFG +#define ICP_HSSACC_TDM_IO_UNIT_TX_CHAN_Q_ADDR_CFG (0x4F) +#define ICP_HSSACC_TDM_IO_UNIT_TX_CHAN_Q_ADDR_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_TX_CHAN_Q_ADDR_CFG + + +#define ICP_HSSACC_TDM_IO_UNIT_TX_Q_CFG (0xA0) +#define ICP_HSSACC_TDM_IO_UNIT_TX_Q_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_TX_Q_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_CFG (0xA1) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_CFG +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_CFG (0xA2) +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_CFG +#define ICP_HSSACC_TDM_IO_UNIT_TX_Q_HEAD_CTR_CFG (0xA3) +#define ICP_HSSACC_TDM_IO_UNIT_TX_Q_HEAD_CTR_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_TX_Q_HEAD_CTR_CFG +#define ICP_HSSACC_TDM_IO_UNIT_TX_Q_TAIL_CTR_CFG (0xA4) +#define ICP_HSSACC_TDM_IO_UNIT_TX_Q_TAIL_CTR_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_TX_Q_TAIL_CTR_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_READER_CFG (0xA5) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_READER_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_READER_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_WRITER_CFG (0xA6) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_WRITER_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_Q_WRITER_CFG +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_READER_CFG (0xA7) +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_READER_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_READER_CFG +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_WRITER_CFG (0xA8) +#define ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_WRITER_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_VOICE_RX_Q_WRITER_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HSS_INT_CFG (0xA9) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_INT_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HSS_INT_CFG +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_CFG (0xAA) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_CFG_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_CFG +#define ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_LOAD (0xAB) +#define ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_LOAD_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_LOAD +#define ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_READ (0xAC) +#define ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_OFFS_TABLE_READ + + +#define ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_STATUS (0x80) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ (0x81) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ_RESPONSE \ + ICP_HSSACC_TDM_IO_UNIT_HSS_SW_ERROR_READ + + +/* interval in TDM I/O Unit cycles at which the TDM I/O Unit is to + service the Software Queues */ +#ifdef TOLAPAI +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_INTERVAL (133000) +#else +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TIMER_INTERVAL (100000) +#endif +#endif + +#ifdef TOLAPAI +#define ICP_HSSACC_TDM_IO_UNIT_MAX_TRANSACTION_SIZE_WRDS (14) +#else +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_MAX_TRANSACTION_SIZE_WRDS (9) +#endif +#endif + +#define ICP_HSSACC_TDM_IO_UNIT_HSS_INT_DISABLED (0) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_INT_ENABLED (1) + +/* Channel Stats codes for Stat Read TDM I/O Unit message */ + +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_ABT_ALN (0) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_MAX_SIZE (1) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_FCS (2) +#ifndef NDEBUG +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_RX_PKTS (3) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_STAT_TX_PKTS (4) +#endif + +#ifdef IXP23XX +/* LUT defines used in the creation of the timeslot allocation + tables to be sent to the TDM I/O Unit */ +#define ICP_HSSACC_TDM_IO_UNIT_WORDS_PER_LUT (8) +#define ICP_HSSACC_TDM_IO_UNIT_LUT_WORD_FULL_ASSIGNMENT (0x55555555) +#define ICP_HSSACC_TDM_IO_UNIT_LUT_WORD_T1_ASSIGNMENT (0x5555) +#define ICP_HSSACC_TDM_IO_UNIT_LUT_E1_SIZE_WRDS (2) +#define ICP_HSSACC_TDM_IO_UNIT_LUT_DMVIP_SIZE_WRDS (4) +#define ICP_HSSACC_TDM_IO_UNIT_LUT_QMVIP_SIZE_WRDS (8) +#endif + + +/* Provision Table defines */ +#define ICP_HSSACC_TDM_IO_UNIT_PROV_TABLE_SZ (0x400) +#define ICP_HSSACC_TDM_IO_UNIT_TS_ENABLE (1) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_OFFSET (16) +#define ICP_HSSACC_TDM_IO_UNIT_TS_EN_BIT_OFFSET (23) +#define ICP_HSSACC_TDM_IO_UNIT_OFFSET_TABLE_SZ (0x200) + +/* Queue List configuration */ +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_ADD_FLAG (0) +#define ICP_HSSACC_TDM_IO_UNIT_CHAN_DEL_FLAG (1) + +/* When adding/removing channels on a linked list for + * a port, these values are used to indicate whether the list is + * a Tx list or an Rx list + */ +#define IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_TX (0) +#define IX_HSSACC_TDM_IO_UNIT_LIST_INDICATOR_RX (1) + +/* Defines for specifying the data flow direction which we are + enabling/disabling for this channel */ +#define ICP_HSSACC_TDM_IO_UNIT_FLOW_DIR_NEITHER (0) +#define ICP_HSSACC_TDM_IO_UNIT_FLOW_DIR_TX_ONLY (1) +#define ICP_HSSACC_TDM_IO_UNIT_FLOW_DIR_RX_ONLY (2) +#define ICP_HSSACC_TDM_IO_UNIT_FLOW_DIR_BOTH (3) + + +/* Queue Configuration parameters for QMgr component */ +#define ICP_HSSACC_VOICE_RX_WATERMARK (1) +#define ICP_HSSACC_HDLC_RX_WATERMARK (1) +#define ICP_HSSACC_TX_WATERMARK (1) + + +/* SDC Control Register Offset and Masks */ +#define ICP_HSSACC_TDM_IO_UNIT_SDC_CHAN_TYPE_VOICE (2) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_CHAN_TYPE_HDLC (0) + +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_ROBBING_OFFSET (14) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_LOC_OFFSET (12) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_VAL_OFFSET (9) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_INVERT_OFFSET (8) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_CHAN_TYPE_OFFSET (6) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_REVERSE_OFFSET (5) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BYTE_SWAP_OFFSET (4) + +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_NO_REVERSE (0) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_REVERSE (1) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BYTE_NO_SWAP (0) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BYTE_SWAP (1) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_INVERT_ON (1) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_BIT_INVERT_OFF (0) + +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_ONE_BIT_ON (1) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_OFF (0) + +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_VALUE_ZERO (0) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_VALUE_ONE (1) + +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_LOC_ZERO (1) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RBIT_LOC_SEVEN (0) + +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_IDLE_FLAG (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_IDLE_ONES (1) + +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_32_BIT_CRC (1) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_16_BIT_CRC (0) + +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_SOF_SHARED (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_SOF_ONE (1) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_SOF_TWO (2) + + + + +#define ICP_HSSACC_TDM_IO_UNIT_SDC_CTRL_MSB_MASK (0xFF00) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_CTRL_MSB_OFFSET (8) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_CTRL_LSB_MASK (0xFF) + + +/* HDLC TX & RX CFG Registers Offsets */ +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_IM_OFFSET (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_FCS_OFFSET (1) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_SF_OFFSET (3) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_TX_CFG_POSTBF_OFFSET (5) + +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_CFG_IM_OFFSET (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_CFG_FCS_OFFSET (1) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_RX_CFG_PREBF_OFFSET (3) + +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_CFG_BIT_FLIP (1) +#define ICP_HSSACC_TDM_IO_UNIT_HDLC_CFG_NO_BIT_FLIP (0) + + + + +/* HDMA Register Offset Definitions */ +/* Port Configuration Register Common Section */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FT_OFFSET (30) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FS_OFFSET (28) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FE_OFFSET (27) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_DE_OFFSET (26) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CLKDIR_OFFSET (25) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FR_OFFSET (24) +#ifdef TOLAPAI +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CS_OFFSET (23) +#endif +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_RATE_OFFSET (21) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_DP_OFFSET (20) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_BITEND_OFFSET (19) +#ifdef TOLAPAI +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_REFF_OFFSET (17) +#endif + +/* Port Configuration Register Tx Section */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_OD_OFFSET (18) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_EN_OFFSET (16) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_TX_PCR_LB_OFFSET (15) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_56KTYPE_OFFSET (13) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_UTYPE_OFFSET (11) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_FB_OFFSET (10) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_56KEND_OFFSET (9) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_56KSEL_OFFSET (8) + + +/* Port Configuration Register Rx Section */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_RX_PCR_LB_OFFSET (16) + + +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_LB_ON (1) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_LB_OFF (0) + +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CLKDIR_INPUT (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CLKDIR_OUTPUT (1) +#ifdef TOLAPAI +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CS_INT (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_PCR_CS_EXT_REF (1) +#endif + + +/* Frame Configuration Register */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FBIT_OFFSET (31) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_OFFSET (16) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_OFFSET (7) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_OFFSET (6) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_INT_OFFSET (5) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_OFFSET (0) + +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_T1_IN_TS (23) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_TS (31) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_T1_IN_BITS (193) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_BITS (256) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_DUAL_MVIP_IN_BITS \ + (ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_BITS * 2) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_QUAD_MVIP_IN_BITS \ + (ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_FRAME_SIZE_E1_IN_BITS * 4) + +/* The HSS co-processor register values to be added to OFFSET in the + * case of TX and data in the HSSFCR */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_TX_ADD_CLK_RATE (0x13) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_TX_ADD_HALF_CLK_RATE (0x11) + +/* value to be added to OFFSET in the case of FBIT being set in the FCR */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_OFFSET_FBIT_ADDITION (7) + + +/* Image Configuration Register */ +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_VOICE_CHANNELISATION_OFFSET (20) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PINGPONG_OFFSET (19) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PHO_OFFSET (8) +/* Ping Pong */ +#define ICP_HSSACC_TDM_IO_UNIT_HSS_PING_PONG_ENABLED (1) +/* Voice channelisation. */ +#define ICP_HSSACC_TDM_IO_UNIT_HSS_VCH_ENABLED (0) +#endif +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PID_OFFSET (16) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_ICR_PBA_OFFSET (0) + +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_0 (1) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_1 (3) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_2 (5) +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_RX_PBA_3 (7) +#endif +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_0 (0) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_1 (2) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_2 (4) +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_TX_PBA_3 (6) +#endif + +/*The port image depth as a power of 2. + The port image depth is always 32*4 = 128 no matter + how many timeslots are assigned*/ +#define ICP_HSSACC_TDM_IO_UNIT_HSS_HDMA_PID_SHIFT (7) + +/* CLK CR */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CLKCR_MAIN_OFFSET (22) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CLKCR_DENOM_OFFSET (0) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CLKCR_NUM_OFFSET (12) + +#ifdef IXP23XX +/* HCR */ +#define ICP_HSSACC_TDM_IO_UNIT_HSS_SUB_FRAME_DELTA_OFFSET (32) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_HCR_FRAME_BASE_OFFSET (8) + +/* VCR */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_VCR_FRAME_BASE_OFFSET (8) +#endif + +/* CWR */ +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW2_ENABLE_OFFSET (31) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW2_ADDRESS_OFFSET (24) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW1_ENABLE_OFFSET (23) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_TX_CW1_ADDRESS_OFFSET (16) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW2_ENABLE_OFFSET (15) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW2_ADDRESS_OFFSET (8) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW1_ENABLE_OFFSET (7) +#define ICP_HSSACC_TDM_IO_UNIT_HDMA_CWR_RX_CW1_ADDRESS_OFFSET (0) + +/* + Context wakeup Enabling. +*/ +/* 1 means on. 0 means off */ +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TX_CW1_ENABLED (1) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_RX_CW1_ENABLED (1) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TX_CW1_DISABLED (0) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_RX_CW1_DISABLED (0) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TX_CW2_ENABLED (1) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_RX_CW2_ENABLED (1) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_TX_CW2_DISABLED (0) +#define ICP_HSSACC_TDM_IO_UNIT_HSS_RX_CW2_DISABLED (0) + + + +/* TDM IO UNIT Software Error codes and Bitmask offsets */ +#define ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_Q_OVERFLOW (0x2) +#define ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_Q_OVERFLOW (0x3) +#define ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_FIFO_OVERFLOW (0x4) +#define ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_FIFO_OVERFLOW (0x5) +#define ICP_HSSACC_TDM_IO_UNIT_RX_VOICE_FREE_Q_UNDERFLOW (0x6) +#define ICP_HSSACC_TDM_IO_UNIT_RX_HDLC_FREE_Q_UNDERFLOW (0x7) +#define ICP_HSSACC_TDM_IO_UNIT_MSG_OUT_FIFO_LP_OVERFLOW (0xa) +#define ICP_HSSACC_TDM_IO_UNIT_MSG_OUT_FIFO_HP_OVERFLOW (0xb) + +/* + * Error Bitmask offset definitions + */ +#ifdef TOLAPAI +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_PORT_RX_PARITY (5) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_PORT_TX_PARITY (4) +#endif +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_PORT_RX_FLOW (3) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_PORT_TX_FLOW (2) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_PORT_RX_LOSS (1) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_PORT_TX_LOSS (0) + + +#ifdef IXP23XX +#define ICP_HSSACC_TDM_IO_UNIT_ERR_ALL_PORT_MASK (0xFFFFFF) +#else +#define ICP_HSSACC_TDM_IO_UNIT_ERR_ALL_PORT_MASK (0x3FFFF) +#endif +#define ICP_HSSACC_TDM_IO_UNIT_ERR_SGLE_PORT_MASK (0x3F) +#define ICP_HSSACC_TDM_IO_UNIT_NEXT_PORT_SHIFT (6) + +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_MSG_OUT_FIFO_H (23) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_V_FREE_UNDERF (19) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_H_FREE_UNDERF (18) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_V_INT_FIFO_OVERF (17) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_H_INT_FIFO_OVERF (16) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_MSG_OUT_FIFO_L (3) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_H_Q_OVERF (2) +#define ICP_HSSACC_TDM_IO_UNIT_ERR_BITMSK_RX_V_Q_OVERF (1) + + +/* + * The maximum number of timeslots available on a TDM trunk. + */ +#define ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE (32) +#define ICP_HSSACC_TIMESLOTS_PER_T1_LINE (24) + + +/* + * The number of TDM trunks per HSS port. + */ +#define ICP_HSSACC_MAX_TDM_LINES_PER_PORT (4) + +/* + * The maximum number of timeslots available on a HSS port. + */ +#define ICP_HSSACC_MAX_TIMESLOTS_PER_PORT (\ + ICP_HSSACC_MAX_TIMESLOTS_PER_TDM_LINE * \ + ICP_HSSACC_MAX_TDM_LINES_PER_PORT) + + + +/* System Clock divider definitions for the TDM I/O Unit HDMA coprocessor */ +#ifdef IXP23XX +#define ICP_HSSACC_HDMA_SYSCLK_1544KHZ { 64,147,197 } +#define ICP_HSSACC_HDMA_SYSCLK_2048KHZ { 48, 52, 63 } +#define ICP_HSSACC_HDMA_SYSCLK_8192KHZ { 12, 52,255 } +#else +#ifdef TOLAPAI +#define ICP_HSSACC_HDMA_SYSCLK_1544KHZ { 43,28,192 } +#define ICP_HSSACC_HDMA_SYSCLK_2048KHZ { 32, 135, 255 } +#define ICP_HSSACC_HDMA_SYSCLK_8192KHZ { 8, 135,1023 } +#endif +#endif + + + +/* ---------------------------------------------------------------------------- + * Application Specific Duals + * ---------------------------------------------------------------------------- + */ +#define ICP_HSSACC_TDM_IO_UNIT_CPP_COPROC (0x09) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_COPROC (0x02) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RD_HDLC_INST (0x09) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_WR_HDLC_INST (0x0C) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_RD_VOICE_INST (0x12) +#define ICP_HSSACC_TDM_IO_UNIT_SDC_WR_VOICE_INST (0x02) +#define ICP_HSSACC_TDM_IO_UNIT_CPP_RD_WORD_INST (0x0C) +#define ICP_HSSACC_TDM_IO_UNIT_CPP_WR_WORD_INST (0x08) + +/* ---------------------------------------------------------------------------- + * Structure definitions + * ---------------------------------------------------------------------------- + */ +/* + * structure of stats for TDM I/O Unit messages with responses + */ +typedef struct icp_hssacc_msg_with_resp_stats_s +{ + uint32_t numTdmIOUnitMessagesSent; + uint32_t numTdmIOUnitRespReceived; + uint32_t numTdmIOUnitTimeoutErrs; + uint32_t numTdmIOUnitInvalidResp; +} icp_hssacc_msg_with_resp_stats_t; + + +/* This is a set of identifiers for the + * channel linked lists + */ +typedef enum icp_hssacc_channel_list_s +{ + ICP_HSSACC_CHANNEL_LIST_PRIMARY = 0, + ICP_HSSACC_CHANNEL_LIST_SECONDARY_0, + ICP_HSSACC_CHANNEL_LIST_SECONDARY_1, + ICP_HSSACC_CHANNEL_LIST_DELIMITER +} icp_hssacc_channel_list_t; + + +/* + This is the list of all the channel lists used by the + HSS I/O Access library +*/ +typedef enum icp_hssacc_tdm_io_unit_channel_list_s +{ + ICP_HSSACC_TDM_IO_UNIT_LIST_TX_PRIMARY = 0, + ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_0, + ICP_HSSACC_TDM_IO_UNIT_LIST_TX_SECONDARY_1, + ICP_HSSACC_TDM_IO_UNIT_LIST_RX_PRIMARY, + ICP_HSSACC_TDM_IO_UNIT_LIST_RX_SECONDARY_0, + ICP_HSSACC_TDM_IO_UNIT_LIST_RX_SECONDARY_1, + ICP_HSSACC_TDM_IO_UNIT_LIST_DELIMITER +} icp_hssacc_tdm_io_unit_channel_list_t; + + +/***************************************************************************** + * Abstract + * HssAcc Receive queue reader counters. + * Used by the HssAcc component to access + * counters written solely by the TDM I/O unit. + * + * + *****************************************************************************/ +typedef struct icp_hssacc_rx_q_read_counters_s +{ + uint32_t rxFreeTail; + uint32_t rxHead; +} __attribute__((packed)) icp_hssacc_rx_q_read_counters_t; + + +/***************************************************************************** + * Abstract + * HssAcc queue reader counters. Used by the HssAcc component to access + * counters written solely by the TDM I/O unit. + * + * Purpose + * Should be used by the access layer to read the counters written by the + * TDM I/O unit. + * + * Fields + * txTail - an array of 1-byte counters for each Tx queue. + * voiceRxCounters.rxFreeTail - a 4-byte counter for the voice Rx free + * tail counter. Only the lower 2 bytes + * are used. + * voiceRxCounters.rxHead - a 4-byte counter for the voice Rx head + * counter. Only the lower 2 bytes are used. + * hdlcRxCounters.rxFreeTail - a 4-byte counter for the HDLC Rx free + * tail counter. Only the lower 2 bytes + * are used. + * hdlcRxCounters.rxHead - a 4-byte counter for the HDLC Rx head + * counter. Only the lower 2 bytes are used. + * + *****************************************************************************/ +typedef struct icp_hssacc_queue_reader_counters_s +{ + /* The tail counters for each of the Tx queues */ + uint8_t txTail[ICP_HSSACC_MAX_NUM_CHANNELS]; + + /* The voice Rx free tail and rx head counters */ + icp_hssacc_rx_q_read_counters_t voiceRxCounters; + + /* The HDLC Rx free tail and rx head counters */ + icp_hssacc_rx_q_read_counters_t hdlcRxCounters; +} __attribute__((packed,aligned(4))) icp_hssacc_queue_reader_counters_t; + + + +/***************************************************************************** + * Abstract + * HssAcc Receive queue writer counters. + * These counters are read by the TDM I/O unit + * and written by HssAcc. + * + *****************************************************************************/ +typedef struct icp_hssacc_rx_q_write_counters_s +{ + uint32_t rxFreeHead; + uint32_t rxTail; +} __attribute__((packed)) icp_hssacc_rx_q_write_counters_t; + + + +/***************************************************************************** + * Abstract + * HssAcc queue writer counters. These counters are read by the TDM I/O unit + * and written by HssAcc. + * + * Purpose + * Should be used by the access layer to update the counters read by the + * TDM I/O unit. + * + * Fields + * txHeadCounters - an array of 1-byte counters for each Tx queue. + * voiceRxCounters.rxFreeHead - a 4-byte counter for the voice Rx free + * head counter. Only the lower 2 bytes + * are used. + * voiceRxCounters.rxTail - a 4-byte counter for the voice Rx tail + * counter. Only the lower 2 bytes are used. + * hdlcRxCounters.rxFreeHead - a 4-byte counter for the HDLC Rx free + * head counter. Only the lower 2 bytes + * are used. + * hdlcRxCounters.rxTail - a 4-byte counter for the HDLC Rx tail + * counter. Only the lower 2 bytes are used. + * + *****************************************************************************/ +typedef struct icp_hssacc_queue_write_counters_s +{ + /* The head counters for all the Tx queues */ + uint8_t txHead[ICP_HSSACC_MAX_NUM_CHANNELS]; + + /* The voice Rx free head and rx tail counters */ + icp_hssacc_rx_q_write_counters_t voiceRxCounters; + + /* The HDLC Rx free head and rx tail counters */ + icp_hssacc_rx_q_write_counters_t hdlcRxCounters; +} __attribute__((packed,aligned(4))) icp_hssacc_queue_write_counters_t; + + + +/* ---------------------------------------------------------------------------- + * Function declarations + * ---------------------------------------------------------------------------- + */ + +/***************************************************************************** + * Abstract: + * Constructs a 2 word TDM I/O Unit message out of 4 individual bytes + * values and a full word value. + * + * + * Side Effects: + * The message will be written into pMessage->data[0] & pMessage->data[1]. + * + * Assumptions: + * None. + * + *****************************************************************************/ +void +HssAccComTdmIOUnitCmd4byte1wordMsgCreate ( + uint32_t byte0, + uint32_t byte1, + uint32_t byte2, + uint32_t byte3, + uint32_t word, + IxPiuMhMessage *pMessage); + + +/***************************************************************************** + * Abstract: + * Constructs a 2 word TDM I/O Unit message out of 8 individual byte values. + * + * Side Effects: + * The message will be written into pMessage->data[0] & pMessage->data[1]. + * + * Assumptions: + * None. + * + *****************************************************************************/ +void +HssAccComTdmIOUnitCmd8byteMsgCreate ( + uint32_t byte0, + uint32_t byte1, + uint32_t byte2, + uint32_t byte3, + uint32_t byte4, + uint32_t byte5, + uint32_t byte6, + uint32_t byte7, + IxPiuMhMessage *pMessage); + + +/***************************************************************************** + * Abstract: + * Submits a message to the TDM I/O Unit, waits for a response and verifies + * that the correct response was received. if responseWord is NULL then + * we are not expecting anything more than an ACK. + * + * + *****************************************************************************/ +icp_status_t +HssAccComTdmIOUnitMsgSendAndRecv( + IxPiuMhMessage message, + uint8_t response, + icp_hssacc_msg_with_resp_stats_t * stats, + uint32_t * responseWord); + +/***************************************************************************** + * Abstract: + * Displays Communication Stats relating to a single TDM I/O message + * + * + *****************************************************************************/ +void HssAccSingleMessageStatsShow (icp_hssacc_msg_with_resp_stats_t stat); + +#endif /* ICP_HSSACCCOMMON_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_port_config.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_port_config.h new file mode 100644 index 0000000..407ccae --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_port_config.h @@ -0,0 +1,297 @@ +/****************************************************************************** + * @file icp_hssacc_port_config.h + * + * @description this contains the data structure definitions and function + * prototypes necessary for port configuration + * + * @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. + * + * + * + * + *****************************************************************************/ + +#ifndef ICP_HSSACCPORTCONFIG_H +#define ICP_HSSACCPORTCONFIG_H + +#include "icp_hssacc.h" +#include "icp_hssacc_common.h" + + +/* Default Frame Pulse Widths for the TDM ports + Valid Range for Frame Pulse Width is 1 to 8 */ +#define ICP_HSSACC_RX_DFLT_FRM_PULSE_WIDTH 1 +#define ICP_HSSACC_TX_DFLT_FRM_PULSE_WIDTH 1 + +/* Enum for the enabled state of a port */ +typedef enum +{ + ICP_HSSACC_PORT_UNCONFIGURED = 0 , + ICP_HSSACC_PORT_CONFIGURED, + /* config written to memory but not to TDM I/O Unit */ + ICP_HSSACC_PORT_ENABLED + /* config written to TDM I/O Unit, port enabled */ +} icp_hssacc_port_state_t; + +/* + * Enum for each of the TDM lines on a HSS port + */ +typedef enum +{ + ICP_HSSACC_LINE_0 = 0, + ICP_HSSACC_LINE_1, + ICP_HSSACC_LINE_2, + ICP_HSSACC_LINE_3, + ICP_HSSACC_LINE_DELIMITER +} icp_hssacc_line_t; + + +/* + icp_hssacc_data_rate_t is used to specify the GCI setting of either + full line rate or half line rate +*/ +typedef enum + { + ICP_HSSACC_DATA_RATE_EQUALS_CLK_RATE = 0, + ICP_HSSACC_DATA_RATE_HALF_CLK_RATE, + ICP_HSSACC_DATA_RATE_TYPE_DELIMITER + } icp_hssacc_data_rate_t; + + +/* list of settings for the Frame Config Register MVIP ON/OFF bit */ +typedef enum +{ + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_OFF = 0, + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_ON, + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SWITCH_DELIMITER +} icp_hssacc_hdma_mvip_switch_t; + + +/* list of settings for the Frame Config Register MVIP mode bit */ +typedef enum +{ + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_DUAL = 0, + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_QUAD, + ICP_HSSACC_TDM_IO_UNIT_HDMA_FCR_MVIP_SETTING_DELIMITER +} icp_hssacc_hdma_mvip_setting_t; + +/* + icp_hssacc_port_additional_internal_config_t is used to specify the + additional port configuration information that is not provided through + the HSS I/O Access API + */ +typedef struct icp_hssacc_port_additional_internal_config_s +{ + icp_hssacc_data_rate_t dataRate; + uint32_t frmPulseWidth; +} icp_hssacc_port_additional_internal_config_t; + +/* + combines the API provided port configuration data and the + internal only configuration +*/ +typedef struct icp_hssacc_port_full_config_s +{ + icp_hssacc_port_config_t cfg; /* Port config from API */ + icp_hssacc_port_additional_internal_config_t addCfg; + /* addtional config params needed internally */ +} icp_hssacc_port_full_config_t; + + + +/* + data structure containing all port registers + in the format required by the TDM I/O Unit +*/ +typedef struct icp_hssacc_hdma_port_config_s +{ +#ifdef IXP23XX + uint32_t tx_LUT[ICP_HSSACC_TDM_IO_UNIT_WORDS_PER_LUT]; + /* tx LUT for TDM slot assignments */ + uint32_t rx_LUT[ICP_HSSACC_TDM_IO_UNIT_WORDS_PER_LUT]; + /* rx LUT for TDM slot assignments */ +#endif + uint32_t tx_pcr; + uint32_t rx_pcr; + uint32_t tx_fcr; + uint32_t rx_fcr; + uint32_t tx_icr; +#ifdef IXP23XX + uint32_t tx_vcr; + uint32_t tx_hcr; +#endif + uint32_t rx_icr; +#ifdef IXP23XX + uint32_t rx_vcr; + uint32_t rx_hcr; +#endif + uint32_t clkcr; + uint32_t cwr; +} icp_hssacc_hdma_port_config_t; + + + +/* + internal data structure containing all information + related to port configuration +*/ +typedef struct icp_hssacc_port_internal_config_s +{ + icp_hssacc_port_state_t state; + icp_hssacc_port_full_config_t rx; + icp_hssacc_port_full_config_t tx; + icp_hssacc_hdma_port_config_t * hdmaPortCfgTableVirtAddr; + /* Virtual address of HDMA port cfg table*/ + icp_hssacc_clk_speed_t clkSpeed; +} icp_hssacc_port_internal_config_t; + + + +/* ---------------------------------------------------------------------------- + * Function declarations + * ---------------------------------------------------------------------------- + */ + +/***************************************************************************** + * Abstract: + * sub-module initialisation function + * + *****************************************************************************/ +icp_status_t +HssAccPortConfigInit(void); + + +/***************************************************************************** + * Abstract: + * sub-module shutdown function. + * + *****************************************************************************/ +icp_status_t +HssAccPortConfigShutdown(void); + + +/***************************************************************************** + * Abstract: + * Check the line, first and last TS position are compatible with the + * current port config. + * + *****************************************************************************/ +icp_status_t +HssAccPortLineValidCheck (unsigned portId, + icp_hssacc_line_t lineId, + unsigned firstTsPos, + unsigned lastTsPos); + + + +/***************************************************************************** + * Abstract: + * Retrieve the current state of the port (configgured/disabled/enabled). + * + *****************************************************************************/ +icp_hssacc_port_state_t +HssAccPortStateGet (unsigned portId); + + + + +/***************************************************************************** + * Abstract: + * reset the internal stats of this sub-module + * + *****************************************************************************/ +void +HssAccPortConfigStatsReset (void); + + + +/***************************************************************************** + * Abstract: + * print out the stats of this sub-module + * + *****************************************************************************/ +void +HssAccPortConfigStatsShow (void); + + + +/***************************************************************************** + * Abstract: + * check the validity of the specified Tx clk mode depending on + * the platform + * + *****************************************************************************/ +icp_boolean_t +HssAccPortConfigTxClkModeInvalid(icp_hssacc_clk_mode_t clkMode); + + + +/***************************************************************************** + * Abstract: + * check the validity of the specified Rx clk mode depending on + * the platform + * + *****************************************************************************/ +icp_boolean_t +HssAccPortConfigRxClkModeInvalid(icp_hssacc_clk_mode_t clkMode); + +#endif /* ICP_HSSACCPORTCONFIG_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_port_hdma_reg_mgr.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_port_hdma_reg_mgr.h new file mode 100644 index 0000000..0d77dbe --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_port_hdma_reg_mgr.h @@ -0,0 +1,160 @@ +/******************************************************************************* + * + * @file icp_hssacc_port_hdma_reg_mgr.h + * + * @description Content of this file is the prototype definitions for the Port + * HDMA Register creation module + * + * @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. + * + * + * + * + ******************************************************************************/ + +#ifndef ICP_HSSACC_PORT_HDMA_REG_MGR_H +#define ICP_HSSACC_PORT_HDMA_REG_MGR_H + + +#include "icp_hssacc.h" + + +/* icp_hssacc_hdma_reg_trans_t is used to specify register types of Tx or Rx */ +typedef enum +{ + ICP_HSSACC_HDMA_RX_REG_TYPE = 0, + /* Rx type register for the HSS Port Config registers */ + ICP_HSSACC_HDMA_TX_REG_TYPE, + /* Tx type register for the HSS Port Config registers */ + ICP_HSSACC_HDMA_REG_TYPE_DELIMITER + /* Delimiter for array sizes */ +} icp_hssacc_hdma_reg_trans_t; + + + +/***************************************************************************** + * Abstract: + * Create the Port Config Register Value for the TDM I/O Unit. + * + *****************************************************************************/ +void +HssAccHdmaMgrPCRCreate (icp_hssacc_hdma_reg_trans_t type, + const icp_hssacc_port_full_config_t *portConfig, + uint32_t *pcr); + + + +/***************************************************************************** + * Abstract: + * Create the Frame Config Register value for the TDM I/O Unit + * + *****************************************************************************/ +icp_status_t +HssAccHdmaMgrFCRCreate (icp_hssacc_hdma_reg_trans_t type, + icp_hssacc_clk_speed_t clkSpeed, + const icp_hssacc_port_full_config_t *portConfig, + uint32_t *fcr); + +/***************************************************************************** + * Abstract: + * Create the Image Config Register Value for the TDM I/O Unit. + * + *****************************************************************************/ +void +HssAccHdmaMgrICRCreate (icp_hssacc_hdma_reg_trans_t type, + unsigned hssPortId, + uint32_t *icr); + + + +/***************************************************************************** + * Abstract: + * Create the Clock Config Register Value for the TDM I/O Unit. + * + *****************************************************************************/ +void +HssAccHdmaMgrClkCRCreate (icp_hssacc_clk_speed_t clkSpeed, + uint32_t *clkCR); + + +/***************************************************************************** + * Abstract: + * Create the Context Wakeup Register for the TDM I/O Unit. + * + *****************************************************************************/ +void +HssAccHdmaMgrCWRCreate (icp_hssacc_clk_speed_t clkSpeed, + uint32_t *cwr); + + +#ifdef IXP23XX +/***************************************************************************** + * Abstract: + * create the Voice Config Regsiter Values for the TDM I/O Unit. + * + *****************************************************************************/ +void +HssAccHdmaMgrVCRCreate (uint32_t *vcr); +#endif + + +#endif /* ICP_HSSACC_PORT_HDMA_REG_MGR_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_queues_config.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_queues_config.h new file mode 100644 index 0000000..936b091 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_queues_config.h @@ -0,0 +1,275 @@ +/******************************************************************************* + * + * @file icp_hssacc_queues_config.h + * + * @description Content of this file is the prototype defintions and data + * structure definitions for the Queue configuration module + * + * @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. + * + * + * + * + ******************************************************************************/ +#ifndef ICP_HSSACCQUEUESCONFIG_H +#define ICP_HSSACCQUEUESCONFIG_H + +#include "IxQMgr.h" +#include "icp_hssacc_common.h" +#define ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_WORDS (1) +#define ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_BYTES \ + (ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_WORDS * \ + ICP_HSSACC_WORD_SIZE) + +/* The size of the queue descriptor. This is common to all queues */ +#define ICP_HSSACC_QUEUE_DESC_SIZE_IN_WORDS (4) +#define ICP_HSSACC_QUEUE_DESC_SIZE_IN_BYTES \ + (ICP_HSSACC_QUEUE_DESC_SIZE_IN_WORDS * \ + ICP_HSSACC_WORD_SIZE) + +/* + * HssAcc transmit queue settings + */ + +#define ICP_HSSACC_TX_QUEUE_DEPTH_POW_2 (7) +#define ICP_HSSACC_TX_QUEUE_DEPTH (1 << ICP_HSSACC_TX_QUEUE_DEPTH_POW_2) + +#define ICP_HSSACC_HDLC_TX_QUEUE_DEPTH_POW_2 (ICP_HSSACC_TX_QUEUE_DEPTH_POW_2) +#define ICP_HSSACC_HDLC_TX_QUEUE_DEPTH (ICP_HSSACC_TX_QUEUE_DEPTH) + +#define ICP_HSSACC_VOICE_TX_QUEUE_DEPTH_POW_2 (4) +#define ICP_HSSACC_VOICE_TX_QUEUE_DEPTH \ + (1 << ICP_HSSACC_VOICE_TX_QUEUE_DEPTH_POW_2) + +/* The maximum number of bytes required to accomodate one TX queue */ +#define ICP_HSSACC_TX_QUEUE_SIZE_IN_BYTES \ + ((ICP_HSSACC_TX_QUEUE_DEPTH) * \ + ICP_HSSACC_QUEUE_DESC_SIZE_IN_BYTES ) + + +/* + * HssAcc HDLC receive queue settings + */ +/* The depth of the HDLC RX queue */ +#define ICP_HSSACC_HDLC_RX_QUEUE_DEPTH_POW_2 (11) +#define ICP_HSSACC_HDLC_RX_QUEUE_DEPTH \ + (1 << ICP_HSSACC_HDLC_RX_QUEUE_DEPTH_POW_2) + +/* The total number of bytes required to accomodate the HDLC RX queue */ +#define ICP_HSSACC_HDLC_RX_QUEUE_SIZE_IN_BYTES \ + ((ICP_HSSACC_HDLC_RX_QUEUE_DEPTH) * \ + ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_BYTES ) + + +/* + * HssAcc HDLC receive free queue settings + */ +/* The depth of the HDLC RX free queue 2048*/ +#define ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH_POW_2 \ + (ICP_HSSACC_HDLC_RX_QUEUE_DEPTH_POW_2) + +#define ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH \ + (1 << ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH_POW_2) + +/* The total number of bytes required to accomodate the HDLC RX free queue */ +#define ICP_HSSACC_HDLC_RX_FREE_QUEUE_SIZE_IN_BYTES \ + ((ICP_HSSACC_HDLC_RX_FREE_QUEUE_DEPTH) * \ + ICP_HSSACC_QUEUE_DESC_SIZE_IN_BYTES ) + + +/* + * HssAcc Voice receive queue settings + */ +/* The depth of the voice RX queue */ +#define ICP_HSSACC_VOICE_RX_QUEUE_DEPTH_POW_2 (11) +#define ICP_HSSACC_VOICE_RX_QUEUE_DEPTH \ + (1 << ICP_HSSACC_VOICE_RX_QUEUE_DEPTH_POW_2) + +/* The total number of bytes required to accomodate the voice RX queue */ +#define ICP_HSSACC_VOICE_RX_QUEUE_SIZE_IN_BYTES \ + ((ICP_HSSACC_VOICE_RX_QUEUE_DEPTH) * \ + ICP_HSSACC_RX_QUEUE_ENTRY_SIZE_IN_BYTES ) + + +/* + * HssAcc Voice receive free queue settings + */ +/* The depth of the voice RX free queue, as a power of 2 */ +#define ICP_HSSACC_VOICE_RX_FREE_QUEUE_DEPTH_POW_2 \ + (ICP_HSSACC_VOICE_RX_QUEUE_DEPTH_POW_2) + +#define ICP_HSSACC_VOICE_RX_FREE_QUEUE_DEPTH \ + (1 << ICP_HSSACC_VOICE_RX_FREE_QUEUE_DEPTH_POW_2) + +/* The total number of bytes required to accomodate the voice RX free queue */ +#define ICP_HSSACC_VOICE_RX_FREE_QUEUE_SIZE_IN_BYTES \ + ((ICP_HSSACC_VOICE_RX_FREE_QUEUE_DEPTH) * \ + ICP_HSSACC_QUEUE_DESC_SIZE_IN_BYTES ) + + +/* + List of IDs for Receive Queues used with the TDM I/O Unit +*/ + +typedef enum icp_hssacc_receive_queues_e + { + ICP_HSSACC_VOICE_RX_Q = ICP_HSSACC_MAX_NUM_CHANNELS, + ICP_HSSACC_VOICE_RX_FREE_Q, + ICP_HSSACC_HDLC_RX_Q, + ICP_HSSACC_HDLC_RX_FREE_Q + } icp_hssacc_receive_queues_t; + + +#define ICP_HSSACC_NUM_RECEIVE_QS (4) + + + +/* Stats */ +typedef struct icp_hssacc_queues_config_stats_s +{ + icp_hssacc_msg_with_resp_stats_t txQCfg; + icp_hssacc_msg_with_resp_stats_t txChanQAddrCfg; + icp_hssacc_msg_with_resp_stats_t hdlcRxQCfg; + icp_hssacc_msg_with_resp_stats_t voiceRxQCfg; + icp_hssacc_msg_with_resp_stats_t txQHeadCfg; + icp_hssacc_msg_with_resp_stats_t txQTailCfg; + icp_hssacc_msg_with_resp_stats_t voiceRxQReaderCfg; + icp_hssacc_msg_with_resp_stats_t voiceRxQWriterCfg; + icp_hssacc_msg_with_resp_stats_t hdlcRxQReaderCfg; + icp_hssacc_msg_with_resp_stats_t hdlcRxQWriterCfg; +} icp_hssacc_queues_config_stats_t; + + + +/* ---------------------------------------------------------------------------- + * Function declarations + * ---------------------------------------------------------------------------- + */ +/***************************************************************************** + * Abstract: + * Initialise all the queues used between the access layer and the + * TDM I/O Unit + * + *****************************************************************************/ +icp_status_t +HssAccQueuesInit(void); + + +/***************************************************************************** + * Abstract: + * shutdown all the queues used between the access layer and the + * TDM I/O Unit + * + *****************************************************************************/ +icp_status_t +HssAccQueuesShutdown(void); + + +/***************************************************************************** + * Abstract: + * Voice and HDLC channels use queues of different sizes so when a + * channel gets allocated for a specific service we need to make sure + * the size is correct and up to date. + * + *****************************************************************************/ +icp_status_t +HssAccQueueConfigQSizeUpdate(uint32_t channelId, + icp_hssacc_channel_type_t type); + + +/***************************************************************************** + * Abstract: + * Reset this modules stats. + * + *****************************************************************************/ +void +HssAccQueuesConfigStatsReset (void); + + +/***************************************************************************** + * Abstract: + * Display all the stats inherent to this module. + * + *****************************************************************************/ +void +HssAccQueuesConfigStatsShow (void); + + +/***************************************************************************** + * Abstract: + * Retrieve the QMgr queue Id using the internal ID (channel number for + * Tx or rx queue ID) + * + *****************************************************************************/ +IxQMgrQId +HssAccQueueIdGet (uint32_t qIndexId); + +/***************************************************************************** + * Abstract: + * enables the callbacks within the QMgr component. + * + *****************************************************************************/ +icp_status_t +HssAccRxQueuesNotificationEnable(void); + + +#endif /* ICP_HSSACCQUEUESCONFIG_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_rings.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_rings.h new file mode 100644 index 0000000..c272757 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_rings.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * @file icp_hssacc_rings.h + * + * @description Content of the file provides Ring creation and 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. + * + * + * + *****************************************************************************/ + +#ifndef ICP_HSSACC_RINGS_H +#define ICP_HSSACC_RINGS_H + +/* Tx & Rx s/w ring routines */ +typedef struct icp_hssacc_dataplane_ring_s +{ + volatile uint32_t *content; + uint32_t size; + uint32_t mask; + volatile uint32_t tail; + volatile uint32_t head; +} icp_hssacc_dataplane_ring_t; + +/** + * @def IX_HSSACC_DATAPLANE_RING_ENTRY_ADD + * @brief puts an entry at the head of the sw ring and increments head + * counter + */ +#define ICP_HSSACC_DATAPLANE_RING_ENTRY_ADD(ring,entry) do { \ + icp_hssacc_dataplane_ring_t *pRing = &(ring); \ + pRing->content[pRing->head & pRing->mask] = ((uint32_t)(entry)); \ + pRing->head++; \ + } while (0) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_ENTRY_REM + * @brief gets an entry from the tail of the sw ring and decrements tail + * counter + */ +#define ICP_HSSACC_DATAPLANE_RING_ENTRY_REM(ring,entry) do { \ + icp_hssacc_dataplane_ring_t *pRing = &(ring); \ + entry = pRing->content[pRing->tail & pRing->mask]; \ + pRing->tail++; \ + } while (0) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_TAIL_ENTRY_GET + * @brief Get the entry at the tail of a sw Ring + */ +#define ICP_HSSACC_DATAPLANE_RING_TAIL_ENTRY_GET(ring) \ + (ring).content[ICP_HSSACC_DATAPLANE_RING_TAIL(ring)] + +/** + * @def ICP_HSSACC_DATAPLANE_RING_TAIL + * @brief Get the Tail pointer of a ring + */ +#define ICP_HSSACC_DATAPLANE_RING_TAIL(ring) \ + ((ring).tail & (ring).mask) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_TAIL_INCR + * @brief Increment the Tail pointer of a ring + */ +#define ICP_HSSACC_DATAPLANE_RING_TAIL_INCR(ring) (ring).tail++ + +/** + * @def ICP_HSSACC_DATAPLANE_RING_HEAD_ENTRY_GET + * @brief Get the entry at the head of a sw ring + */ +#define ICP_HSSACC_DATAPLANE_RING_HEAD_ENTRY_GET(ring) \ + (ring).content[ICP_HSSACC_DATAPLANE_RING_HEAD(ring)] + +/** + * @def ICP_HSSACC_DATAPLANE_RING_HEAD + * @brief Get the Head pointer of a sw ring + */ +#define ICP_HSSACC_DATAPLANE_RING_HEAD(ring) \ + ((ring).head & (ring).mask) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_HEAD_INCR + * @brief Increment the Head pointer of a sw ring + */ +#define ICP_HSSACC_DATAPLANE_RING_HEAD_INCR(ring) do { \ + (ring).head++; } while(0) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_NUM_ENTRIES_GET + * @brief gets the number of entries currently in the sw ring + */ +#define ICP_HSSACC_DATAPLANE_RING_NUM_ENTRIES_GET(ring) \ + ((ring).head - (ring).tail) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_FULL + * @brief tests whether the sw ring is full + */ +#define ICP_HSSACC_DATAPLANE_RING_FULL(ring) \ + (((ring).head - (ring).tail) == (ring).size) + +/** + * @def ICP_HSSACC_DATAPLANE_RING_EMPTY + * @brief tests whether the sw ring is empty + */ +#define ICP_HSSACC_DATAPLANE_RING_EMPTY(ring) \ + ((ring).head == (ring).tail) + + +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_rx_datapath.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_rx_datapath.h new file mode 100644 index 0000000..62d18d3 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_rx_datapath.h @@ -0,0 +1,216 @@ +/****************************************************************************** + * @file icp_hssacc_rx_datapath.h + * + * @description Content of this file provides the function prototypes for the + * HSS I/O Access receive 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. + * + * + * + *****************************************************************************/ + +#ifndef ICP_HSSACC_RX_DP_H +#define ICP_HSSACC_RX_DP_H + +#include "IxOsal.h" +#include "icp.h" +#include "icp_hssacc.h" +#include "IxQMgr.h" + +#define ICP_HSSACC_RX_DP_CHAN_DESC_PTR_RING_SZ (256) + +/* Definition of watermark level for pre-emptive Voice traffic flow regulation, + this watermark is tuned following performance testing, at this point +it is assumed that flow regulation should begin early to prevent Speech latency +build-up. */ +#define ICP_HSSACC_RX_Q_WATERMARK_LEVEL (2) + + +void +HssAccRxQServiceCallback(IxQMgrQId qId, + IxQMgrCallbackId cbId); + +/****************************************************************************** + * Abstract: + * Initialise Rx datapath global variables + * + ******************************************************************************/ +icp_status_t +HssAccRxDatapathInit(void); + +/****************************************************************************** + * Abstract: + * Shut down Rx datapath Module. + * + *****************************************************************************/ +icp_status_t +HssAccRxDatapathShutdown(void); + + +/****************************************************************************** + * Abstract: + * Register rx callback and user context + * + ******************************************************************************/ +void +HssAccChannelRxCallbackRegister(uint32_t channelId, + icp_hssacc_rx_callback_t rxCallback, + icp_user_context_t userContext); + +/****************************************************************************** + * Abstract: + * Deregister rx callback and user context + * + ******************************************************************************/ +void +HssAccChannelRxCallbackDeregister(uint32_t channelId); + +/****************************************************************************** + * Abstract: + * Set max frame size for HDLC, must be done at init + * + *****************************************************************************/ +void +HssAccRxDatapathHdlcInit(uint32_t maxRxFrameSize); + +/****************************************************************************** + * Abstract: + * Set max frame size for voice, must be done at init + * + *****************************************************************************/ +void +HssAccRxDatapathVoiceInit(uint32_t maxRxFrameSize); + +/****************************************************************************** + * Abstract: + * Function to run the Q Mgr processing function and call + * associated callbacks + * + ******************************************************************************/ +icp_status_t +HssAccRxDatapathService(icp_hssacc_channel_type_t channelType); + + + +/****************************************************************************** + * Abstract: + * Retrieve all buffers in an Rx Free Queue if there are no initialized + * channels for the corresponding service + * + *****************************************************************************/ +icp_status_t +HssAccRxFreeQsBufsRetrieve(IX_OSAL_MBUF * * ppStartChainBuffer, + IX_OSAL_MBUF * * ppEndChainBuffer); + +/****************************************************************************** + * Abstract: + * Retrieve all buffers in a chain from Rx Ring for a specified channel + * + *****************************************************************************/ +icp_status_t +HssAccRxDatapathChanBufsRetrieve(uint32_t channelId, + IX_OSAL_MBUF * * startChainBuffer, + IX_OSAL_MBUF * * endChainBuffer); + +/****************************************************************************** + * Abstract: + * Print out the per-channel statistics + * + ******************************************************************************/ +void +HssAccRxDatapathChanStatsShow(uint32_t channelId); + + +/****************************************************************************** + * Abstract: + * Function to print out stats on replenishing + * + ******************************************************************************/ +void +HssAccRxDatapathReplenishStatsShow(icp_hssacc_channel_type_t serviceType); + +/****************************************************************************** + * Abstract: + * Reset the per-channel statistics + ******************************************************************************/ +void +HssAccRxDatapathChanStatsReset(uint32_t channelId); + + +/****************************************************************************** + * Abstract: + * Function to reset stats on replenishing + * + *****************************************************************************/ +void +HssAccRxDatapathReplenishStatsReset(icp_hssacc_channel_type_t serviceType); + + +/****************************************************************************** + * Abstract: + * Return the Max Rx Sample/Frame size configured for the specified Service + * + *****************************************************************************/ +uint32_t +HssAccRxDatapathMaxServiceFrameSizeGet(icp_hssacc_channel_type_t servType); +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_tdm_io_queue_entry.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_tdm_io_queue_entry.h new file mode 100644 index 0000000..a6a286a --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_tdm_io_queue_entry.h @@ -0,0 +1,193 @@ +/****************************************************************************** + * @file icp_hssacc_tdm_io_queue_entry.h + * + * @description Content of this file contains the definition and access + * macros for the TDM I/O Queue Entry format + * + * @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. + * + * + * + * + *****************************************************************************/ + +#ifndef ICP_HSSACC_TDM_IO_QUEUE_ENTRY_H +#define ICP_HSSACC_TDM_IO_QUEUE_ENTRY_H + + +/***************************************************************************** + * Definition of the Channel descriptor format + * + *****************************************************************************/ +typedef struct icp_hssacc_chan_desc_s +{ + /* In order to handle both Little and Big Endianness correctly, + this data struct contains the Length split into MSB and LSB fields. */ + uint8_t currBufLength_LSB; + uint8_t currBufLength_MSB; + uint8_t status; + uint8_t channelId; +} icp_hssacc_chan_desc_t; + +/***************************************************************************** + * Definition of the Queue Entry format for Tx and RxFree Queues + * + *****************************************************************************/ +typedef struct icp_hssacc_tdm_io_queue_entry_s +{ + /* this union allows us to manipulate and move around the entire data + struct as a single word,thus saving instructions for copies */ + union { + icp_hssacc_chan_desc_t strct; + uint32_t word; + } descriptor; + void * currBufData; + uint32_t packetLengthBytes; + IX_OSAL_MBUF * currBuf; +} icp_hssacc_tdm_io_queue_entry_t; + + + + +/***************************************************************************** + * Definition of the TDM I/O private section of the OSAL Buffer + * + *****************************************************************************/ +typedef struct icp_hssacc_osal_mbuf_tdm_io_section_s +{ + icp_hssacc_tdm_io_queue_entry_t tdm_io_entry; + IX_OSAL_MBUF * pNextBuf; + uint32_t reserved[3]; +} icp_hssacc_osal_mbuf_tdm_io_section_t; + + + +/***************************************************************************** + * Macros for accessing the different fields of a Queue Entry + * + *****************************************************************************/ + +#define ICP_TDM_IO_Q_ENTRY_CHANNEL_ID(entryPtr) \ + ((entryPtr)->descriptor.strct.channelId) + +#define ICP_TDM_IO_Q_ENTRY_STATUS(entryPtr) (entryPtr->descriptor.strct.status) + +#define ICP_TDM_IO_Q_ENTRY_CURR_BUF_LEN_MSB(entryPtr) \ + ((entryPtr)->descriptor.strct.currBufLength_MSB) + +#define ICP_TDM_IO_Q_ENTRY_CURR_BUF_LEN_LSB(entryPtr) \ + ((entryPtr)->descriptor.strct.currBufLength_LSB) + +#define ICP_TDM_IO_Q_ENTRY_DATA(entryPtr) ((entryPtr)->currBufData) + +#define ICP_TDM_IO_Q_ENTRY_PKT_LEN(entryPtr) ((entryPtr)->packetLengthBytes) + +#define ICP_TDM_IO_Q_ENTRY_OSAL_MBUF(entryPtr) ((entryPtr)->currBuf) + + + +/***************************************************************************** + * Macros for accessing the different fields of the TDM I/O Unit private section + * of the OSAL Buffer + * + *****************************************************************************/ + +#define ICP_OSAL_MBUF_TDM_SECT_CHANNEL_ID(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_CHANNEL_ID((&((mbufPtr)->tdm_io_entry)))) + +#define ICP_OSAL_MBUF_TDM_SECT_STATUS(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_STATUS((&((mbufPtr)->tdm_io_entry)))) + +#define ICP_OSAL_MBUF_TDM_SECT_CURR_BUF_LEN_MSB(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_CURR_BUF_LEN_MSB((&((mbufPtr)->tdm_io_entry)))) + +#define ICP_OSAL_MBUF_TDM_SECT_CURR_BUF_LEN_LSB(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_CURR_BUF_LEN_LSB((&((mbufPtr)->tdm_io_entry)))) + +#define ICP_OSAL_MBUF_TDM_SECT_DATA(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_DATA((&((mbufPtr)->tdm_io_entry)))) + +#define ICP_OSAL_MBUF_TDM_SECT_PKT_LEN(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_PKT_LEN((&((mbufPtr)->tdm_io_entry)))) + +#define ICP_OSAL_MBUF_TDM_SECT_NEXT_BUF(mbufPtr) \ + ((mbufPtr)->pNextBuf) + +#define ICP_OSAL_MBUF_TDM_SECT_OSAL_MBUF_START(mbufPtr) \ + (ICP_TDM_IO_Q_ENTRY_OSAL_MBUF((&((mbufPtr)->tdm_io_entry)))) + + +/***************************************************************************** + * Macros for handling the Packet Length field. these are used to manipulate + * the endianness of the field. + * + *****************************************************************************/ +#define ICP_OSAL_MBUF_TDM_SECT_LEN_MASK 0xFF +#define ICP_OSAL_MBUF_TDM_SECT_LEN_MSB_OFFSET 8 + +/* These macros will return as a byte number the MSB and LSB + respectively of a 2 byte packet length field */ +#define ICP_OSAL_MBUF_PKT_LEN_MSB(len) ((len >> ICP_OSAL_MBUF_TDM_SECT_LEN_MSB_OFFSET) & ICP_OSAL_MBUF_TDM_SECT_LEN_MASK) + +#define ICP_OSAL_MBUF_PKT_LEN_LSB(len) (len & ICP_OSAL_MBUF_TDM_SECT_LEN_MASK) + +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_timeslot_allocation.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_timeslot_allocation.h new file mode 100644 index 0000000..815e289 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_timeslot_allocation.h @@ -0,0 +1,260 @@ +/******************************************************************************* + * + * @file icp_hssacc_timeslot_allocation.h + * + * @description Content of this file provides the main internal API for the + * timeslot allocation module used as part of channel Allocation and Deletion + * + * @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. + * + * + * + * + ******************************************************************************/ + +#ifndef ICP_HSSACC_TIMESLOT_ALLOCATION_H +#define ICP_HSSACC_TIMESLOT_ALLOCATION_H + + + +#include "icp_hssacc_channel_config.h" + + +/***************************************************************************** + * Abstract + * Platform specific initialisation for this sub-module. + * + *****************************************************************************/ +icp_status_t HssAccTsAllocPlatformInit (void); + + + +/***************************************************************************** + * Abstract + * Initialisation of the sub-module. + * + *****************************************************************************/ +icp_status_t HssAccTsAllocInit (void); + + +/***************************************************************************** + * Abstract + * Shutdown this sub-module. + * + *****************************************************************************/ +void HssAccTsAllocShutdown (void); + +/***************************************************************************** + * Abstract + * Remove the allocation of timeslots associated with the specified + * channel. + * + *****************************************************************************/ +icp_status_t +HssAccTsAllocDelete (unsigned channelId, + icp_hssacc_channel_config_t * hssChannelData); + + +/***************************************************************************** + * Abstract + * Update the Timeslot provisioning table for the specified port. will + * also update the offset table for all ports. + * + *****************************************************************************/ +icp_status_t +HssAccTsAllocUpdate(unsigned portId, + const icp_hssacc_channel_config_t * hssChannelData); + + +/***************************************************************************** + * Abstract + * Setup an initial Timeslot allocation for correct behaviour of the + * specified port with no channels configured on it. + * + *****************************************************************************/ +icp_status_t +HssAccTsAllocInitialAllocationUpdate(unsigned portId); + + + + +#ifdef IXP23XX +/***************************************************************************** + * Abstract + * Create the Timeslot Look-up Table for the TDM I/O unit. + * + *****************************************************************************/ +icp_status_t +HssAccTxAllocLUTCreate (icp_hssacc_clk_speed_t clkSpeed, + uint32_t *pHssLUT); +#endif + +/***************************************************************************** + * Abstract + * Swap the Timeslot provisioning tables within the TDM I/O Unit. + * + *****************************************************************************/ +icp_status_t HssAccTsAllocTableSwap (unsigned hssPortId); + + + + +/***************************************************************************** + * Abstract + * returns the address of the Memory block allocated for the + * Timeslot provisioning Table. + * + *****************************************************************************/ +void * HssAccTsAllocHdmaProvTableVirtAddrGet (void); + + +/***************************************************************************** + * Abstract + * Returns the address of the memory block allocated for the timeslot + * offset table. + * + *****************************************************************************/ +void * HssAccTsAllocTdmIoUnitOffsetTableVirtAddrGet (void); + + +/***************************************************************************** + * Abstract + * Return a pointer to the stats for Swap message. + * + *****************************************************************************/ +icp_hssacc_msg_with_resp_stats_t * HssAccTsAllocSwapStatsGet(void); + + +/***************************************************************************** + * Abstract + * return a pointer to the stats for the Offset Table read message. + * + *****************************************************************************/ +icp_hssacc_msg_with_resp_stats_t * HssAccTsAllocOffsetTableReadStatsGet(void); + + + +/***************************************************************************** + * Abstract + * Read one word of the specified table. + * + *****************************************************************************/ +icp_status_t +HssAccTsAllocOffsetTableWordRead (icp_boolean_t readShadowTable, + uint16_t tableOffset, + uint32_t *tableWord); + + + + +/***************************************************************************** + * Abstract: + * Verify that all of the timeslots requested are not already in use. + * + *****************************************************************************/ +icp_boolean_t +HssAccTsAvailableVerify(unsigned portId, icp_hssacc_line_t lineId, + uint32_t tsMap); + + + +/***************************************************************************** + * Abstract: + * Register the timeslots specified for the specified channel. + * + *****************************************************************************/ +void +HssAccTsRegister(unsigned channelId, + unsigned portId, + icp_hssacc_line_t lineId, + uint32_t tsMap); + + +/***************************************************************************** + * Abstract: + * Unregister any timeslots associated with the specified channel. + * + *****************************************************************************/ +void +HssAccTsUnregister(unsigned portId, + icp_hssacc_line_t lineId, + uint32_t tsMap); + +/***************************************************************************** + * Abstract + * Display all the stats collecting within this module. + * + *****************************************************************************/ +void HssAccTsAllocStatsShow (void); + + +/***************************************************************************** + * Abstract + * Reset The stats for the Timeslot allocation module. + * + *****************************************************************************/ +void HssAccTsAllocStatsReset (void); + + + + +#endif /* #ifndef ICP_HSSACC_TIMESLOT_ALLOCATION_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_trace.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_trace.h new file mode 100644 index 0000000..703f6e2 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_trace.h @@ -0,0 +1,339 @@ +/******************************************************************************* + * + * @file icp_hssacc_trace.h + * + * @description Content of this file provides Trace functionality for the + * component + * + * @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. + * + * + * + * + ******************************************************************************/ + + +#ifndef ICP_HSSACC_TRACE_H +#define ICP_HSSACC_TRACE_H + + +/* ---------------------------------------------------------------------------- + * Includes + * ---------------------------------------------------------------------------- + */ +#include "IxOsal.h" + + +/* + * ---------------------------------------------------------------------------- + * Enumerated types + * ---------------------------------------------------------------------------- + */ + +/***************************************************************************** + * Enumeration defining HssAcc trace levels. + *****************************************************************************/ +typedef enum icp_hssacc_trace_level_e +{ + ICP_HSSACC_TRACE_OFF = 0, /**< NO TRACE */ + ICP_HSSACC_DEBUG = 1, /**< Select traces of interest */ + ICP_HSSACC_FN_ENTRY_EXIT = 2 /**< ALL function entry/exit traces + and all traces of interest */ +} icp_hssacc_trace_level_t; + + +/* ---------------------------------------------------------------------------- + * Defines and Macros. + * ---------------------------------------------------------------------------- + */ + +/***************************************************************************** + * The trace level for the HSS Acc Control path and Datapath blocks + * + * Description: + * This macro turns the debug trace on or off, depending on whether the + * code is compiled for debug or release. + * There are 3 levels allowed in the current compilation setup: + * if NDEBUG is not defined and DEBUG is not defined, then selected tracing + * will be done for the control path and the datapath tracing will be off. + * if NDEBUG is not defined and DEBUG is defined then all function + * entry/exits are on as well selected tracing for control and data paths. + * if NDEBUG is defined ALL tracing is off. + * + *****************************************************************************/ + +#ifdef DEBUG +#define ICP_HSSACC_TRACE_LEVEL ICP_HSSACC_FN_ENTRY_EXIT +#define ICP_HSSACC_DP_TRACE_LEVEL ICP_HSSACC_FN_ENTRY_EXIT +#else +#define ICP_HSSACC_TRACE_LEVEL ICP_HSSACC_TRACE_OFF +#define ICP_HSSACC_DP_TRACE_LEVEL ICP_HSSACC_TRACE_OFF +#endif + + + + + +/***************************************************************************** + * Mechanism for reporting HssAcc software errors + * + *****************************************************************************/ +#define ICP_HSSACC_REPORT_ERROR(STR) \ + ixOsalLog (IX_OSAL_LOG_LVL_ERROR, \ + IX_OSAL_LOG_DEV_STDERR, \ + STR, 0, 0, 0, 0, 0, 0); + +/***************************************************************************** + * Mechanism for reporting HssAcc software errors with 1 argument + * + *****************************************************************************/ +#define ICP_HSSACC_REPORT_ERROR_1(STR,ARG1) \ + ixOsalLog (IX_OSAL_LOG_LVL_ERROR, \ + IX_OSAL_LOG_DEV_STDERR, \ + STR, ARG1, 0, 0, 0, 0, 0); + +/***************************************************************************** + * Mechanism for reporting HssAcc software errors with 2 arguments + * + *****************************************************************************/ +#define ICP_HSSACC_REPORT_ERROR_2(STR,ARG1,ARG2) \ + ixOsalLog (IX_OSAL_LOG_LVL_ERROR, \ + IX_OSAL_LOG_DEV_STDERR, \ + STR, ARG1, ARG2, 0, 0, 0, 0); + + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc component, with no arguments + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_TRACE_0(LEVEL, STR) \ + { \ + if (LEVEL <= ICP_HSSACC_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, 0, 0, 0, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_TRACE_0(LEVEL, STR) do { /* nothing */ } while(0) +#endif + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc component, with one argument + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_TRACE_1(LEVEL, STR, ARG1) \ + { \ + if (LEVEL <= ICP_HSSACC_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, ARG1, 0, 0, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_TRACE_1(LEVEL, STR, ARG1) do { /* nothing */ } while(0) +#endif + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc component, with two arguments + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_TRACE_2(LEVEL, STR, ARG1, ARG2) \ + { \ + if (LEVEL <= ICP_HSSACC_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, ARG1, ARG2, 0, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_TRACE_2(LEVEL, STR, ARG1, ARG2) do { } while(0) +#endif + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc component, with three arguments + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + * + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_TRACE_3(LEVEL, STR, ARG1, ARG2, ARG3) \ + { \ + if (LEVEL <= ICP_HSSACC_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, ARG1, ARG2, ARG3, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_TRACE_3(LEVEL, STR, ARG1, ARG2, ARG3) do { } while(0) +#endif + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc component, with four arguments + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + * + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_TRACE_4(LEVEL, STR, ARG1, ARG2, ARG3, ARG4) \ + { \ + if (LEVEL <= ICP_HSSACC_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, ARG1, ARG2, ARG3, ARG4, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_TRACE_4(LEVEL, STR, ARG1, ARG2, ARG3, ARG4) do { } while(0) +#endif + + +/***************************************************************************** + * Mechanism for tracing debug for the HSS Acc Datapath block component, + * with no arguments + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_DP_TRACE_0(LEVEL, STR) \ + { \ + if (LEVEL <= ICP_HSSACC_DP_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, 0, 0, 0, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_DP_TRACE_0(LEVEL, STR) do { /* nothing */ } while(0) +#endif + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc Datapath component, + * with one argument + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_DP_TRACE_1(LEVEL, STR, ARG1) \ + { \ + if (LEVEL <= ICP_HSSACC_DP_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, ARG1, 0, 0, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_DP_TRACE_1(LEVEL, STR, ARG1) do { /* nothing */ } while(0) +#endif + +/***************************************************************************** + * Mechanism for tracing debug for the HssAcc Datapath component, + * with two arguments + * + * Note: + * This macro executes only in debug versions of the code. It does nothing + * in release code. + *****************************************************************************/ +#ifndef NDEBUG + #define ICP_HSSACC_DP_TRACE_2(LEVEL, STR, ARG1, ARG2) \ + { \ + if (LEVEL <= ICP_HSSACC_DP_TRACE_LEVEL) \ + { \ + ixOsalLog (IX_OSAL_LOG_LVL_MESSAGE, \ + IX_OSAL_LOG_DEV_STDOUT, \ + STR, ARG1, ARG2, 0, 0, 0, 0); \ + } \ + } +#else + #define ICP_HSSACC_DP_TRACE_2(LEVEL, STR, ARG1, ARG2) do { } while(0) +#endif + + +#endif /* ICP_HSSACC_TRACE_H */ diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_tx_datapath.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_tx_datapath.h new file mode 100644 index 0000000..4c6c722 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_tx_datapath.h @@ -0,0 +1,191 @@ +/******************************************************************************* + * + * @file icp_hssacc_tx_datapath.h + * + * @description Content of this file provides the internal API for the Transmit + * datapath module. + * + * @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. + * + * + * + * + ******************************************************************************/ + +#ifndef ICP_HSSACC_TX_DATAPATH_H +#define ICP_HSSACC_TX_DATAPATH_H + +#include "icp_hssacc.h" + +/* Definition of watermark level for pre-emptive Voice traffic flow regulation, + this watermark is tuned following performance testing, at this point +it is assumed that flow regulation should begin early to prevent Speech latency +build-up. */ +#define ICP_HSSACC_TX_Q_WATERMARK_LEVEL (4) + +/* Voice packet length should be modulo 4. A pre-transmit voice buffer check +will bitwise AND the voice packet length with this value. */ +#define ICP_HSSACC_TX_VOICE_PACKET_LENGTH_CHECK_MASK (0x00000003) + + +/***************************************************************************** + * Abstract: + * Initialises this subcomponent (mutex...) and Resets the Tx Datapath + * internal data. + * + *****************************************************************************/ +icp_status_t +HssAccTxDatapathInit(void); + + +/***************************************************************************** + * Abstract: + * Destroys all allocated memory and mutexes for this component. + * + *****************************************************************************/ +icp_status_t +HssAccTxDatapathShutdown(void); + +/***************************************************************************** + * Abstract: + * updates the Type for specified channel, + * will potentially trigger a resizing of the Queue associated with this + * channel. + * + *****************************************************************************/ +icp_status_t +HssAccTxDatapathChanTypeUpdate (uint32_t channelId, + icp_hssacc_channel_type_t chanType); + + +/***************************************************************************** + * Abstract: + * Set or unset the channel as bypassed, will allow the component to prevent + * or allow Tx. + * + *****************************************************************************/ +icp_status_t +HssAccTxDatapathChanBypassStateSet(uint32_t channelId, + icp_boolean_t bypassed); + + +/***************************************************************************** + * Abstract: + * Register the Tx Done callback + * + *****************************************************************************/ +void +HssAccTxDatapathChanTxDoneCallbackRegister( + uint32_t channelId, + icp_hssacc_tx_done_callback_t txDoneCallback, + icp_user_context_t userContext); + +/***************************************************************************** + * Abstract: + * Deregister the Tx Done callback + * + *****************************************************************************/ +void +HssAccTxDatapathChanTxDoneCallbackDeregister(uint32_t channelId); + + +/***************************************************************************** + * Abstract: + * Triggers the servicing of all the Tx Queues, this will trigger TxDone + * callbacks when appropriate for each queue of type channelType. + * + *****************************************************************************/ +icp_status_t +HssAccTxDatapathService(icp_hssacc_channel_type_t channelType); + + + +/***************************************************************************** + * Abstract: + * Retrieve all buffers in the transmit path for specified channel + * + *****************************************************************************/ +icp_status_t +HssAccTxDatapathChannelBuffersRetrieve(uint32_t channelId, + IX_OSAL_MBUF * * startChainBuffer, + IX_OSAL_MBUF * * endChainBuffer); + + +/***************************************************************************** + * Abstract: + * Reset the stats for specified channel + * + *****************************************************************************/ +void +HssAccTxDatapathChanStatsReset(uint32_t channelId); + + + +/***************************************************************************** + * Abstract: + * Print out the stats for the specified channel + * + *****************************************************************************/ +void +HssAccTxDatapathChanStatsShow(uint32_t channelId); + +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_voice_bypass.h b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_voice_bypass.h new file mode 100644 index 0000000..e59fec7 --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/include/icp_hssacc_voice_bypass.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * + * @file icp_hssacc_voice_bypass.h + * + * @description Content of this file provides the internal API for the Voice + * bypass module + * + * @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. + * + * + * + * + ******************************************************************************/ + +#ifndef ICP_HSSACC_VOICE_BYPASS_H +#define ICP_HSSACC_VOICE_BYPASS_H + +#include "icp.h" + +/***************************************************************************** + * Abstract + * This function initialises the internals of the Voice Bypass + * sub-module. it can only be called once. + * + *****************************************************************************/ +void +HssAccVoiceBypassInit(void); + + +/***************************************************************************** + * Abstract + * This function shuts down the Voice Bypass submodule. the module + * must have been initialised beforehand. + * + *****************************************************************************/ +icp_status_t +HssAccVoiceBypassShutdown(void); + +/***************************************************************************** + * Abstract + * This function displays the internal gathered by this sub-module. + * + *****************************************************************************/ +void +HssAccBypassStatsShow (void); + + +/***************************************************************************** + * Abstract + * This function resets all the internal stats relating to this sub-module. + * + *****************************************************************************/ +void +HssAccBypassStatsReset (void); + +#endif diff --git a/Acceleration/library/icp_telephony/tdm_io_access/linux_2.6_kernel_space.mk b/Acceleration/library/icp_telephony/tdm_io_access/linux_2.6_kernel_space.mk new file mode 100644 index 0000000..325733d --- /dev/null +++ b/Acceleration/library/icp_telephony/tdm_io_access/linux_2.6_kernel_space.mk @@ -0,0 +1,76 @@ +################### +# @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. +# +# +# +################### + +#specific include directories in kernel space +INCLUDES+= -I $(ICP_OSAL_DIR)/platforms/EP805XX/include \ + -I $(ICP_OSAL_DIR)/platforms/EP805XX/os/linux/include \ + -I $(ICP_OSAL_DIR)/common/os/linux/include/core \ + -I $(ICP_OSAL_DIR)/common/os/linux/include/modules \ + -I $(ICP_OSAL_DIR)/common/os/linux/include/modules/ddk \ + -I $(ICP_OSAL_DIR)/common/os/linux/include/modules/ioMem \ + -I $(ICP_OSAL_DIR)/common/os/linux/include/modules/bufferMgt + + +#Extra Flags Specific in kernel space e.g. include path or debug flags etc. e.g to add an include path EXTRA_CFLAGS += -I$(src)/../include +EXTRA_CFLAGS += $(INCLUDES) -DTOLAPAI -D__tolapai -DEP805XX -D__ep805xx -DIX_HW_COHERENT_MEMORY=1 +EXTRA_LDFLAGS+=-whole-archive + |