diff options
33 files changed, 2153 insertions, 5710 deletions
@@ -1,7 +1,7 @@ # # Makefile for DAHDI Linux kernel modules # -# Copyright (C) 2001-2008 Digium, Inc. +# Copyright (C) 2001-2009 Digium, Inc. # # @@ -98,7 +98,7 @@ include/dahdi/version.h: FORCE fi @rm -f $@.tmp -prereq: include/dahdi/version.h +prereq: include/dahdi/version.h firmware-loaders stackcheck: checkstack modules ./checkstack kernel/*.ko kernel/*/*.ko @@ -131,6 +131,9 @@ endif uninstall-firmware: $(MAKE) -C drivers/dahdi/firmware hotplug-uninstall DESTDIR=$(DESTDIR) +firmware-loaders: + $(MAKE) -C drivers/dahdi/firmware firmware-loaders + install-include: for hdr in $(INST_HEADERS); do \ install -D -m 644 include/dahdi/$$hdr $(DESTDIR)/usr/include/dahdi/$$hdr; \ @@ -233,6 +236,7 @@ distclean: dist-clean dist-clean: clean @rm -f include/dahdi/version.h @$(MAKE) -C drivers/dahdi/firmware dist-clean + @rm -f drivers/dahdi/vpmadt032_loader/*.o_shipped firmware-download: @$(MAKE) -C drivers/dahdi/firmware all @@ -245,6 +249,6 @@ docs: $(GENERATED_DOCS) README.html: README $(ASCIIDOC_CMD) -o $@ $< -.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm +.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders FORCE: diff --git a/drivers/dahdi/Kbuild b/drivers/dahdi/Kbuild index c62de64..d897fa8 100644 --- a/drivers/dahdi/Kbuild +++ b/drivers/dahdi/Kbuild @@ -10,6 +10,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o @@ -64,6 +65,32 @@ endif dahdi-objs := dahdi-base.o +############################################################################### +# VPMADT032 Loader +############################################################################### + +dahdi_vpmadt032_loader-objs := vpmadt032_loader/dahdi_vpmadt032_loader.o + +ifeq ($(ARCH),i386) + ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_x86_32.o_shipped),) + VPMADT032_LOADER_PRESENT=yes + dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_x86_32.o + obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o + endif +else + ifeq ($(ARCH),x86_64) + ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_x86_64.o_shipped),) + VPMADT032_LOADER_PRESENT=yes + dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_x86_64.o + obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o + endif + endif +endif + +############################################################################### +# HPEC Support +############################################################################### + dahdi_echocan_hpec-objs := hpec/dahdi_echocan_hpec.o CFLAGS_dahdi_echocan_hpec.o := -I$(src)/hpec diff --git a/drivers/dahdi/Kconfig b/drivers/dahdi/Kconfig index 22a448a..4986ccc 100644 --- a/drivers/dahdi/Kconfig +++ b/drivers/dahdi/Kconfig @@ -123,9 +123,24 @@ config DAHDI_WCTC4XXP If unsure, say Y. +config DAHDI_VOICEBUS + tristate "VoiceBus(tm) Interface Library" + depends on PCI + default DAHDI + ---help--- + This driver provides the common interface for telephony cards that + use the VoiceBus(tm) interface. It also contains common supporting + libraries for the VPMADT032 hardware echo cancelation module that + is available for the VoiceBus cards. + + To compile this driver as a module, choose M here: the module will + be called voicebus. + + If unsure, say Y. + config DAHDI_WCTDM24XXP tristate "Digium Wildcard VoiceBus analog card Support" - depends on DAHDI && PCI + depends on DAHDI && DAHDI_VOICEBUS default DAHDI ---help--- This driver provides support for the following Digium @@ -145,7 +160,7 @@ config DAHDI_WCTDM24XXP config DAHDI_WCTE12XP tristate "Digium Wildcard VoiceBus digital card Support" - depends on DAHDI && PCI + depends on DAHDI && DAHDI_VOICEBUS default DAHDI ---help--- This driver provides support for the following Digium diff --git a/drivers/dahdi/adt_lec.c b/drivers/dahdi/adt_lec.c index 344669d..a566d5d 100644 --- a/drivers/dahdi/adt_lec.c +++ b/drivers/dahdi/adt_lec.c @@ -1,7 +1,7 @@ /* * ADT Line Echo Canceller Parameter Parsing * - * Copyright (C) 2008 Digium, Inc. + * Copyright (C) 2008-2009 Digium, Inc. * * Kevin P. Fleming <kpfleming@digium.com> * @@ -33,7 +33,8 @@ static inline void adt_lec_init_defaults(struct adt_lec_params *params, __u32 ta params->tap_length = tap_length; } -static int adt_lec_parse_params(struct adt_lec_params *params, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) +static int adt_lec_parse_params(struct adt_lec_params *params, + struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) { unsigned int x; char *c; diff --git a/drivers/dahdi/firmware/Makefile b/drivers/dahdi/firmware/Makefile index ae4f945..023279a 100644 --- a/drivers/dahdi/firmware/Makefile +++ b/drivers/dahdi/firmware/Makefile @@ -3,7 +3,7 @@ # # Makefile for firmware downloading/installation # -# Copyright (C) 2007-2008, Digium, Inc. +# Copyright (C) 2007-2009, Digium, Inc. # # Joshua Colp <jcolp@digium.com> # @@ -11,16 +11,16 @@ # the GNU General Public License # -.PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object +.PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object firmware-loaders OCT6114_064_VERSION:=1.05.01 OCT6114_128_VERSION:=1.05.01 TC400M_VERSION:=MR6.12 -VPMADT032_VERSION:=1.07 +VPMADT032_VERSION:=1.17.0 FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases -ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M FIRMWARE-VPMADT032 +ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M # Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version> # First example: dahdi-fw-oct6114-064-1.05.01 @@ -32,13 +32,13 @@ ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M FIRMWARE- FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz) FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz) FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz) -FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMADT032=dahdi-fw-vpmadt032-$(VPMADT032_VERSION).tar.gz) + +FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz # Build a list of object files if hotplug will not be used OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o) OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o) OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o) -OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMADT032=dahdi-fw-vpmadt032.o) # Force usage of wget, for now DOWNLOAD=wget @@ -55,6 +55,7 @@ all: $(FIRMWARE) dist-clean: clean rm -f dahdi-fw-*.bin rm -f dahdi-fw-*.tar.gz + rm -f dahdi-fwload-*.tar.gz rm -f make_firmware_object # Clean up anything we built @@ -70,6 +71,14 @@ dahdi-fw-%.tar.gz: (cat $@ | gzip -d | tar -xof -) \ fi +firmware-loaders: $(FWLOADERS) + +.PHONY: dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz +dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz: + @if test ! -f $@; then echo "Attempting to download $@"; $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \ + if test ! -f $@; then exit 1; fi; \ + (cd ../../..; cat drivers/dahdi/firmware/$@ | gzip -d | tar -xof -) + # Create object files suitable for linking against object-build: $(FIRMWARE) $(OBJECT_FILES) @@ -111,17 +120,6 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(T else @echo "Firmware dahdi-fw-tc400m.bin is already installed with required version $(TC400M_VERSION)" endif -ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmadt032-$(VPMADT032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-vpmadt032-$(VPMADT032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes) - @echo "Installing dahdi-fw-vpmadt032.bin to hotplug firmware directories" - @install -m 644 dahdi-fw-vpmadt032.bin $(DESTDIR)/usr/lib/hotplug/firmware - @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmadt032-* - @touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmadt032-$(VPMADT032_VERSION) - @install -m 644 dahdi-fw-vpmadt032.bin $(DESTDIR)/lib/firmware - @rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-vpmadt032-* - @touch $(DESTDIR)/lib/firmware/.dahdi-fw-vpmadt032-$(VPMADT032_VERSION) -else - @echo "Firmware dahdi-fw-vpmadt032.bin is already installed with required version $(VPMADT032_VERSION)" -endif # Uninstall any installed dahdi firmware images from hotplug firmware directories hotplug-uninstall: @@ -154,8 +152,3 @@ dahdi-fw-oct6114-128.o: dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz dahdi dahdi-fw-tc400m.o: dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz dahdi-fw-tc400m.bin make_firmware_object @echo Making firmware object file for dahdi-fw-tc400m.bin ./make_firmware_object dahdi-fw-tc400m.bin $@ - -# Build object file of a VPMADT032 firmware image for linking -dahdi-fw-vpmadt032.o: dahdi-fw-vpmadt032-$(VPMADT032_VERSION).tar.gz dahdi-fw-vpmadt032.bin make_firmware_object - @echo Making firmware object file for dahdi-fw-vpmadt032.bin - ./make_firmware_object dahdi-fw-vpmadt032.bin $@ diff --git a/drivers/dahdi/wcte12xp/GpakApi.c b/drivers/dahdi/voicebus/GpakApi.c index 748cc94..4b480ab 100644 --- a/drivers/dahdi/wcte12xp/GpakApi.c +++ b/drivers/dahdi/voicebus/GpakApi.c @@ -16,6 +16,7 @@ * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. + * */ /* @@ -31,15 +32,11 @@ * this program for more details. */ -#include <dahdi/kernel.h> - #include "GpakHpi.h" -#include "vpmadt032.h" +#include "GpakCust.h" #include "GpakApi.h" #include "gpakenum.h" -#ifdef VPM_SUPPORT - /* DSP to Host interface block offsets. */ #define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ #define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ @@ -127,11 +124,6 @@ static int CheckDspReset( DSP_WORD DspStatus; /* DSP Status */ DSP_WORD DspChannels; /* number of DSP channels */ DSP_WORD Temp[2]; -#if 0 - DSP_WORD DspConfs; /* number of DSP conferences */ - DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ - unsigned short int i; /* loop index / counter */ -#endif /* Read the pointer to the Interface Block. */ gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); @@ -164,38 +156,6 @@ static int CheckDspReset( MaxChannels[DspId] = MAX_CHANNELS; else MaxChannels[DspId] = (unsigned short int) DspChannels; -#if 0 - /* read the number of configured DSP conferences */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, - &DspConfs); - if (DspConfs > MAX_CONFS) - MaxConfs[DspId] = MAX_CONFS; - else - MaxConfs[DspId] = (unsigned short int) DspConfs; - - - /* read the number of configured DSP packet channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_PKT_CHANNELS) - MaxPktChannels[DspId] = MAX_PKT_CHANNELS; - else - MaxPktChannels[DspId] = (unsigned short int) DspChannels; - - - /* read the pointer to the circular buffer infor struct table */ - gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(PktBufrMem, Temp); - - - /* Determine the addresses of each channel's Packet buffers. */ - for (i = 0; i < MaxPktChannels[DspId]; i++) - { - pPktInBufr[DspId][i] = PktBufrMem; - pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; - PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); - } -#endif /* read the pointer to the event fifo info struct */ gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); @@ -509,7 +469,7 @@ static unsigned int TransactCmd( */ gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ + const GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ ) { @@ -560,7 +520,7 @@ gpakConfigPortStatus_t gpakConfigurePorts( ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | ((pPortConfig->CompandingMode2 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); + (pPortConfig->SerialWordSize2 & 0x0001)); MsgBuffer[12] = (DSP_WORD) (((pPortConfig->DxDelay3 << 11) & 0x0800) | @@ -608,6 +568,7 @@ gpakConfigPortStatus_t gpakConfigurePorts( else return (CpsParmError); } +EXPORT_SYMBOL(gpakConfigurePorts); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -672,7 +633,7 @@ gpakConfigChanStatus_t gpakConfigureChannel( ((pChanConfig->SoftwareCompand & 3) << 2) | (pChanConfig->EcanEnableB << 1) | (pChanConfig->EcanEnableA & 1) - ); + ); MsgBuffer[7] = (DSP_WORD) pChanConfig->EcanParametersA.EcanTapLength; @@ -733,7 +694,22 @@ gpakConfigChanStatus_t gpakConfigureChannel( MsgBuffer[34] = (DSP_WORD) pChanConfig->EcanParametersB.EcanFirSegmentLen; - MsgLength = 70; // byte number == 35*2 + MsgBuffer[35] = (DSP_WORD) + ( + ((pChanConfig->EcanParametersB.EcanReconvergenceCheckEnable <<5) & 0x20) | + ((pChanConfig->EcanParametersA.EcanReconvergenceCheckEnable <<4) & 0x10) | + ((pChanConfig->EcanParametersB.EcanTandemOperationEnable <<3) & 0x8) | + ((pChanConfig->EcanParametersA.EcanTandemOperationEnable <<2) & 0x4) | + ((pChanConfig->EcanParametersB.EcanMixedFourWireMode << 1) & 0x2) | + (pChanConfig->EcanParametersA.EcanMixedFourWireMode & 1) + ); + MsgBuffer[36] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanMaxDoubleTalkThres; + + MsgBuffer[37] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanMaxDoubleTalkThres; + + MsgLength = 76; // byte number == 38*2 break; @@ -760,6 +736,7 @@ gpakConfigChanStatus_t gpakConfigureChannel( else return (CcsParmError); } +EXPORT_SYMBOL(gpakConfigureChannel); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. @@ -852,6 +829,7 @@ gpakAlgControlStat_t gpakAlgControl( return (AcParmError); } +EXPORT_SYMBOL(gpakAlgControl); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo @@ -889,9 +867,6 @@ gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( DSP_WORD TakeIndex; /* event fifo take index */ DSP_WORD WordsReady; /* number words ready for read out of event fifo */ DSP_WORD EventError; /* flag indicating error with event fifo msg */ -#if 0 - DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ -#endif /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) @@ -911,7 +886,7 @@ gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( EventInfoAddress = pEventFifoAddress[DspId]; gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, WordBuffer); - RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); + RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); BufrSize = WordBuffer[CB_BUFR_SIZE]; PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; @@ -1025,6 +1000,7 @@ gpakPingDspStat_t gpakPingDsp( else return (PngDspCommFailure); } +EXPORT_SYMBOL(gpakPingDsp); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot @@ -1249,7 +1225,7 @@ gpakReadFramingStatsStatus_t gpakReadFramingStats( *pFramingError3Count = ReadBuffer[2]; *pDmaStopErrorCount = ReadBuffer[3]; - if(pDmaSlipStatsBuffer != NULL) + if(pDmaSlipStatsBuffer != 0) // If users want to get the DMA slips count { pDmaSlipStatsBuffer[0] = ReadBuffer[4]; @@ -1612,4 +1588,3 @@ gpakReadSysParmsStatus_t gpakReadSystemParms( /* Return with an indication that System Parameters info was obtained. */ return (RspSuccess); } -#endif diff --git a/drivers/dahdi/wctdm24xxp/GpakApi.h b/drivers/dahdi/voicebus/GpakApi.h index 2e55e64..91aade0 100644 --- a/drivers/dahdi/wctdm24xxp/GpakApi.h +++ b/drivers/dahdi/voicebus/GpakApi.h @@ -14,23 +14,6 @@ * Revision History: * 06/15/05 - Initial release. * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. */ #ifndef _GPAKAPI_H /* prevent multiple inclusion */ @@ -67,6 +50,7 @@ typedef struct short int EcanAdaptEnable; // Echo Can Adapt Enable flag short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag short int EcanDblTalkThresh; // Echo Can Double Talk threshold + short int EcanMaxDoubleTalkThres; // Maximum double-talk threshold short int EcanNlpThreshold; // Echo Can NLP threshold short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet @@ -76,10 +60,13 @@ typedef struct short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit short int EcanNumFirSegments; // Echo Can Num FIR Segments short int EcanFirSegmentLen; // Echo Can FIR Segment Length + short int EcanTandemOperationEnable; //Enable tandem operation + short int EcanMixedFourWireMode; // Handle possible 4-wire (echo-free) lines + short int EcanReconvergenceCheckEnable; // Handle possible 4-wire (echo-free) lines } GpakEcanParms_t; /* Definition of a Channel Configuration information structure. */ -typedef struct +typedef struct GpakChannelConfig { GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id unsigned short int PcmInSlotA; // A side PCM Input Time Slot @@ -106,7 +93,7 @@ typedef struct /* Definition of a Serial Port Configuration Structure */ -typedef struct +typedef struct GpakPortConfig { GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection unsigned short int FirstBlockNum1; // port 1 first group Block Number @@ -302,7 +289,7 @@ typedef enum */ extern gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, // DSP identifier - GpakPortConfig_t *pPortConfig, // pointer to Port Config info + const GpakPortConfig_t *pPortConfig, // pointer to Port Config info GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status ); diff --git a/drivers/dahdi/voicebus/GpakCust.c b/drivers/dahdi/voicebus/GpakCust.c new file mode 100644 index 0000000..386c916 --- /dev/null +++ b/drivers/dahdi/voicebus/GpakCust.c @@ -0,0 +1,682 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * Copyright (c) 2005-2009, Digium Incorporated + * + * File Name: GpakCust.c + * + * Description: + * This file contains host system dependent functions to support generic + * G.PAK API functions. The file is integrated into the host processor + * connected to C55x G.PAK DSPs via a Host Port Interface. + * + * Note: This file is supplied by Adaptive Digital Technologies and + * modified by Digium in order to support the VPMADT032 modules. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. + * + */ + +/* + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2 as published by the + * Free Software Foundation. See the LICENSE file included with + * this program for more details. + */ + +#include <linux/version.h> +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/pci.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include <linux/semaphore.h> +#else +#include <asm/semaphore.h> +#endif + +#include <dahdi/kernel.h> +#include <dahdi/user.h> + +#include "GpakCust.h" +#include "GpakApi.h" + +#include "adt_lec.h" +#include "voicebus.h" +#include "vpmadtreg.h" + +static rwlock_t ifacelock; +static struct vpmadt032 *ifaces[MAX_DSP_CORES]; + +static inline struct vpmadt032 *find_iface(const unsigned short dspid) +{ + struct vpmadt032 *ret; + + read_lock(&ifacelock); + if (ifaces[dspid]) { + ret = ifaces[dspid]; + } else { + ret = NULL; + } + read_unlock(&ifacelock); + return ret; +} + +static struct vpmadt032_cmd *vpmadt032_get_free_cmd(struct vpmadt032 *vpm) +{ + unsigned long flags; + struct vpmadt032_cmd *cmd; + might_sleep(); + spin_lock_irqsave(&vpm->list_lock, flags); + if (list_empty(&vpm->free_cmds)) { + spin_unlock_irqrestore(&vpm->list_lock, flags); + cmd = kmalloc(sizeof(struct vpmadt032_cmd), GFP_KERNEL); + if (unlikely(!cmd)) + return NULL; + memset(cmd, 0, sizeof(*cmd)); + } else { + cmd = list_entry(vpm->free_cmds.next, struct vpmadt032_cmd, node); + list_del_init(&cmd->node); + spin_unlock_irqrestore(&vpm->list_lock, flags); + } + init_completion(&cmd->complete); + return cmd; +} + +/* Wait for any outstanding commands to the VPMADT032 to complete */ +static inline int vpmadt032_io_wait(struct vpmadt032 *vpm) +{ + unsigned long flags; + int empty; + while (1) { + spin_lock_irqsave(&vpm->list_lock, flags); + empty = list_empty(&vpm->pending_cmds) && list_empty(&vpm->active_cmds); + spin_unlock_irqrestore(&vpm->list_lock, flags); + if (empty) { + break; + } else { + msleep(1); + } + } + return 0; +} + +/* Issue a read command to a register on the VPMADT032. We'll get the results + * later. */ +static struct vpmadt032_cmd *vpmadt032_getreg_full_async(struct vpmadt032 *vpm, int pagechange, + unsigned short addr) +{ + unsigned long flags; + struct vpmadt032_cmd *cmd; + cmd = vpmadt032_get_free_cmd(vpm); + if (!cmd) + return NULL; + cmd->desc = (pagechange) ? __VPM150M_RWPAGE | __VPM150M_RD : __VPM150M_RD; + cmd->address = addr; + cmd->data = 0; + spin_lock_irqsave(&vpm->list_lock, flags); + list_add_tail(&cmd->node, &vpm->pending_cmds); + spin_unlock_irqrestore(&vpm->list_lock, flags); + return cmd; +} + +/* Get the results from a previous call to vpmadt032_getreg_full_async. */ +int vpmadt032_getreg_full_return(struct vpmadt032 *vpm, int pagechange, + u16 addr, u16 *outbuf, struct vpmadt032_cmd *cmd) +{ + unsigned long flags; + int ret = -EIO; + BUG_ON(!cmd); + wait_for_completion(&cmd->complete); + if (cmd->desc & __VPM150M_FIN) { + *outbuf = cmd->data; + cmd->desc = 0; + ret = 0; + } + + /* Just throw this command back on the ready list. */ + spin_lock_irqsave(&vpm->list_lock, flags); + list_add_tail(&cmd->node, &vpm->free_cmds); + spin_unlock_irqrestore(&vpm->list_lock, flags); + return ret; +} + +/* Read one of the registers on the VPMADT032 */ +static int vpmadt032_getreg_full(struct vpmadt032 *vpm, int pagechange, u16 addr, u16 *outbuf) +{ + struct vpmadt032_cmd *cmd; + cmd = vpmadt032_getreg_full_async(vpm, pagechange, addr); + if (unlikely(!cmd)) { + return -ENOMEM; + } + return vpmadt032_getreg_full_return(vpm, pagechange, addr, outbuf, cmd); +} + +static int vpmadt032_setreg_full(struct vpmadt032 *vpm, int pagechange, unsigned int addr, + u16 data) +{ + unsigned long flags; + struct vpmadt032_cmd *cmd; + cmd = vpmadt032_get_free_cmd(vpm); + if (!cmd) + return -ENOMEM; + cmd->desc = cpu_to_le16((pagechange) ? (__VPM150M_WR|__VPM150M_RWPAGE) : __VPM150M_WR); + cmd->address = cpu_to_le16(addr); + cmd->data = cpu_to_le16(data); + spin_lock_irqsave(&vpm->list_lock, flags); + list_add_tail(&cmd->node, &vpm->pending_cmds); + spin_unlock_irqrestore(&vpm->list_lock, flags); + return 0; +} + + +static int vpmadt032_setpage(struct vpmadt032 *vpm, u16 addr) +{ + addr &= 0xf; + /* We do not need to set the page if we're already on the page we're + * interested in. */ + if (vpm->curpage == addr) + return 0; + else + vpm->curpage = addr; + + return vpmadt032_setreg_full(vpm, 1, 0, addr); +} + +static unsigned char vpmadt032_getpage(struct vpmadt032 *vpm) +{ + unsigned short res; + const int pagechange = 1; + vpmadt032_getreg_full(vpm, pagechange, 0, &res); + return res; +} + +static int vpmadt032_getreg(struct vpmadt032 *vpm, unsigned int addr, u16 *data) +{ + unsigned short res; + vpmadt032_setpage(vpm, addr >> 16); + res = vpmadt032_getreg_full(vpm, 0, addr & 0xffff, data); + return res; +} + +static int vpmadt032_setreg(struct vpmadt032 *vpm, unsigned int addr, u16 data) +{ + int res; + vpmadt032_setpage(vpm, addr >> 16); + res = vpmadt032_setreg_full(vpm, 0, addr & 0xffff, data); + return res; +} + +/** + * vpmadt032_bh - Changes the echocan parameters on the vpmadt032 module. + * + * This function is typically scheduled to run in the workqueue by the + * vpmadt032_echocan_with_params function. This is because communicating with + * the hardware can take some time while messages are sent to the VPMADT032 + * module and the driver waits for the responses. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void vpmadt032_bh(void *data) +{ + struct vpmadt032 *vpm = data; +#else +static void vpmadt032_bh(struct work_struct *data) +{ + struct vpmadt032 *vpm = container_of(data, struct vpmadt032, work); +#endif + struct adt_lec_params *curstate, *desiredstate; + int channel; + + /* Sweep through all the echo can channels on the VPMADT032 module, + * looking for ones where the desired state does not match the current + * state. + */ + for (channel = 0; channel < vpm->span->channels; channel++) { + GPAK_AlgControlStat_t pstatus; + int res = 1; + curstate = &vpm->curecstate[channel]; + desiredstate = &vpm->desiredecstate[channel]; + + if ((desiredstate->nlp_type != curstate->nlp_type) || + (desiredstate->nlp_threshold != curstate->nlp_threshold) || + (desiredstate->nlp_max_suppress != curstate->nlp_max_suppress)) { + + GPAK_ChannelConfigStat_t cstatus; + GPAK_TearDownChanStat_t tstatus; + GpakChannelConfig_t chanconfig; + + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", channel + 1, vpm->desiredecstate[channel].nlp_type, + desiredstate->nlp_threshold, desiredstate->nlp_max_suppress); + + vpm->setchanconfig_from_state(vpm, channel, &chanconfig); + + res = gpakTearDownChannel(vpm->dspid, channel, &tstatus); + if (res) + goto vpm_bh_out; + + res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, &chanconfig, &cstatus); + if (res) + goto vpm_bh_out; + + if (!desiredstate->tap_length) { + res = gpakAlgControl(vpm->dspid, channel, BypassSwCompanding, &pstatus); + if (res) + printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", channel, res); + res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus); + } + + } else if (desiredstate->tap_length != curstate->tap_length) { + if (desiredstate->tap_length) { + printk(KERN_DEBUG "Enabling ecan on channel: %d\n", channel); + res = gpakAlgControl(vpm->dspid, channel, EnableMuLawSwCompanding, &pstatus); + if (res) + printk("Unable to set SW Companding on channel %d (reason %d)\n", channel, res); + res = gpakAlgControl(vpm->dspid, channel, EnableEcanA, &pstatus); + } else { + printk(KERN_DEBUG "Disabling ecan on channel: %d\n", channel); + res = gpakAlgControl(vpm->dspid, channel, BypassSwCompanding, &pstatus); + if (res) + printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", channel, res); + res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus); + } + } +vpm_bh_out: + if (!res) + *curstate = *desiredstate; + } + return; +} +#include "adt_lec.c" +int vpmadt032_echocan_with_params(struct vpmadt032 *vpm, int channo, + struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) +{ + int update; + unsigned int ret; + + ret = adt_lec_parse_params(&vpm->desiredecstate[channo], ecp, p); + if (ret) + return ret; + + /* The driver cannot control the number of taps on the VPMADT032 + * module. Instead, it uses tap_length to enable or disable the echo + * cancellation. */ + vpm->desiredecstate[channo].tap_length = (ecp->tap_length) ? 1 : 0; + + /* Only update the parameters if the new state of the echo canceller + * is different than the current state. */ + update = memcmp(&vpm->curecstate[channo], + &vpm->desiredecstate[channo], + sizeof(vpm->curecstate[channo])); + if (update && test_bit(VPM150M_ACTIVE, &vpm->control)) { + /* Since updating the parameters can take a bit of time while + * the driver sends messages to the VPMADT032 and waits for + * their responses, we'll push the work of updating the + * parameters to a work queue so the caller can continue to + * proceed with setting up the call. + */ + schedule_work(&vpm->work); + } + + return 0; +} +EXPORT_SYMBOL(vpmadt032_echocan_with_params); + +struct vpmadt032 *vpmadt032_alloc(struct vpmadt032_options *options) +{ + struct vpmadt032 *vpm; + int i; + might_sleep(); + + vpm = kzalloc(sizeof(*vpm), GFP_KERNEL); + if (!vpm) + return NULL; + + /* Init our vpmadt032 struct */ + memcpy(&vpm->options, options, sizeof(*options)); + spin_lock_init(&vpm->list_lock); + INIT_LIST_HEAD(&vpm->free_cmds); + INIT_LIST_HEAD(&vpm->pending_cmds); + INIT_LIST_HEAD(&vpm->active_cmds); + sema_init(&vpm->sem, 1); + vpm->curpage = 0x80; + vpm->dspid = -1; + + /* Place this structure in the ifaces array so that the DspId from the + * Gpak Library can be used to locate it. */ + write_lock(&ifacelock); + for (i=0; i<MAX_DSP_CORES; ++i) { + if (NULL == ifaces[i]) { + ifaces[i] = vpm; + vpm->dspid = i; + break; + } + } + write_unlock(&ifacelock); + + if (-1 == vpm->dspid) { + kfree(vpm); + printk(KERN_NOTICE "Unable to initialize another vpmadt032 modules\n"); + vpm = NULL; + } else if (vpm->options.debug & DEBUG_ECHOCAN) { + printk(KERN_DEBUG "Setting VPMADT032 DSP ID to %d\n", vpm->dspid); + } + + return vpm; +} +EXPORT_SYMBOL(vpmadt032_alloc); + +int +vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb) +{ + int i; + u16 reg; + int res = -EFAULT; + gpakPingDspStat_t pingstatus; + + BUG_ON(!vpm->setchanconfig_from_state); + might_sleep(); + + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "VPMADT032 Testing page access: "); + + for (i = 0; i < 0xf; i++) { + int x; + for (x = 0; x < 3; x++) { + vpmadt032_setpage(vpm, i); + reg = vpmadt032_getpage(vpm); + if (reg != i) { + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg); + res = -ENODEV; + goto failed_exit; + } + } + } + + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "Passed\n"); + + set_bit(VPM150M_HPIRESET, &vpm->control); + msleep(2000); + while (test_bit(VPM150M_HPIRESET, &vpm->control)) + msleep(1); + + /* Set us up to page 0 */ + vpmadt032_setpage(vpm, 0); + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "VPMADT032 now doing address test: "); + + for (i = 0; i < 16; i++) { + int x; + for (x = 0; x < 2; x++) { + vpmadt032_setreg(vpm, 0x1000, i); + vpmadt032_getreg(vpm, 0x1000, ®); + if (reg != i) { + printk("VPMADT032 Failed address test\n"); + goto failed_exit; + } + + } + } + + if (vpm->options.debug & DEBUG_ECHOCAN) + printk("Passed\n"); + + set_bit(VPM150M_HPIRESET, &vpm->control); + while (test_bit(VPM150M_HPIRESET, &vpm->control)) + msleep(1); + + res = vpmadtreg_loadfirmware(vb); + if (res) { + struct pci_dev *pdev = voicebus_get_pci_dev(vb); + dev_printk(KERN_INFO, &pdev->dev, "Failed to load the firmware.\n"); + return res; + } + vpm->curpage = -1; + set_bit(VPM150M_SWRESET, &vpm->control); + + while (test_bit(VPM150M_SWRESET, &vpm->control)) + msleep(1); + + pingstatus = gpakPingDsp(vpm->dspid, &vpm->version); + + if (!pingstatus) { + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "Version of DSP is %x\n", vpm->version); + } else { + printk(KERN_NOTICE "VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); + res = -1; + goto failed_exit; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&vpm->work, vpmadt032_bh, vpm); +#else + INIT_WORK(&vpm->work, vpmadt032_bh); +#endif + + return 0; + +failed_exit: + return res; +} +EXPORT_SYMBOL(vpmadt032_init); + + +void vpmadt032_free(struct vpmadt032 *vpm) +{ + unsigned long flags; + struct vpmadt032_cmd *cmd; + LIST_HEAD(local_list); + + BUG_ON(!vpm); + + /* Move all the commands onto the local list protected by the locks */ + spin_lock_irqsave(&vpm->list_lock, flags); + list_splice(&vpm->pending_cmds, &local_list); + list_splice(&vpm->active_cmds, &local_list); + list_splice(&vpm->free_cmds, &local_list); + spin_unlock_irqrestore(&vpm->list_lock, flags); + + while (!list_empty(&local_list)) { + cmd = list_entry(local_list.next, struct vpmadt032_cmd, node); + list_del(&cmd->node); + kfree(cmd); + } + + BUG_ON(ifaces[vpm->dspid] != vpm); + write_lock(&ifacelock); + ifaces[vpm->dspid] = NULL; + write_unlock(&ifacelock); + kfree(vpm); +} +EXPORT_SYMBOL(vpmadt032_free); + +int vpmadt032_module_init(void) +{ + rwlock_init(&ifacelock); + memset(ifaces, 0, sizeof(ifaces)); + return 0; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadDspMemory - Read DSP memory. + * + * FUNCTION + * This function reads a contiguous block of words from DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ) +{ + struct vpmadt032 *vpm = find_iface(DspId); + int i; + int ret; + + vpmadt032_io_wait(vpm); + if ( NumWords < VPM150M_MAX_COMMANDS ) { + struct vpmadt032_cmd *cmds[VPM150M_MAX_COMMANDS] = {0}; + vpmadt032_setpage(vpm, DspAddress >> 16); + DspAddress &= 0xffff; + for (i=0; i < NumWords; ++i) { + if (!(cmds[i] = vpmadt032_getreg_full_async(vpm,0,DspAddress+i))) { + return; + } + } + for (i=NumWords-1; i >=0; --i) { + ret = vpmadt032_getreg_full_return(vpm,0,DspAddress+i,&pWordValues[i], + cmds[i]); + if (0 != ret) { + return; + } + } + } + else { + for (i=0; i<NumWords; ++i) { + vpmadt032_getreg(vpm, DspAddress + i, &pWordValues[i]); + } + } + return; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteDspMemory - Write DSP memory. + * + * FUNCTION + * This function writes a contiguous block of words to DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ) +{ + + struct vpmadt032 *vpm = find_iface(DspId); + int i; + + //printk(KERN_DEBUG "Writing %d words to memory\n", NumWords); + if (vpm) { + for (i = 0; i < NumWords; ++i) { + vpmadt032_setreg(vpm, DspAddress + i, pWordValues[i]); + } +#if 0 + for (i = 0; i < NumWords; i++) { + if (wctdm_vpmadt032_getreg(wc, DspAddress + i) != pWordValues[i]) { + printk(KERN_NOTICE "Error in write. Address %x is not %x\n", DspAddress + i, pWordValues[i]); + } + } +#endif + } + return; + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakHostDelay - Delay for a fixed time interval. + * + * FUNCTION + * This function delays for a fixed time interval before returning. The time + * interval is the Host Port Interface sampling period when polling a DSP for + * replies to command messages. + * + * RETURNS + * nothing + * + */ +void gpakHostDelay(void) +{ +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakLockAccess - Lock access to the specified DSP. + * + * FUNCTION + * This function aquires exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakLockAccess(unsigned short DspId) +{ + struct vpmadt032 *vpm; + + vpm = find_iface(DspId); + + if (vpm) { + if (down_interruptible(&vpm->sem)) { + return; + } + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakUnlockAccess - Unlock access to the specified DSP. + * + * FUNCTION + * This function releases exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakUnlockAccess(unsigned short DspId) +{ + struct vpmadt032 *vpm; + + vpm = find_iface(DspId); + + if (vpm) { + up(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFile - Read a block of bytes from a G.PAK Download file. + * + * FUNCTION + * This function reads a contiguous block of bytes from a G.PAK Download file + * starting at the current file position. + * + * RETURNS + * The number of bytes read from the file. + * -1 indicates an error occurred. + * 0 indicates all bytes have been read (end of file) + * + */ +int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ) +{ + /* The firmware is loaded into the part by a closed-source firmware + * loader, and therefore this function should never be called. */ + WARN_ON(1); + return -1; +} diff --git a/drivers/dahdi/wctdm24xxp/GpakCust.h b/drivers/dahdi/voicebus/GpakCust.h index f2b729f..befdabc 100644 --- a/drivers/dahdi/wctdm24xxp/GpakCust.h +++ b/drivers/dahdi/voicebus/GpakCust.h @@ -16,7 +16,7 @@ * 06/15/05 - Initial release. * * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. + * permission of Adaptive Digital Technologies, Inc. * */ @@ -36,31 +36,120 @@ #ifndef _GPAKCUST_H /* prevent multiple inclusion */ #define _GPAKCUST_H -#include "wctdm24xxp.h" -#ifdef VPM150M_SUPPORT #include <linux/device.h> -#include <linux/firmware.h> -#endif +#include <linux/completion.h> +#include <linux/workqueue.h> + #include "gpakenum.h" +#include "adt_lec.h" + +#define DEBUG_ECHOCAN (1 << 1) + +/* Host and DSP system dependent related definitions. */ +#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ +#define MAX_CHANNELS 32 /* maximum number of channels */ +#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ +#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ +#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ + +#define VPM150M_MAX_COMMANDS 8 + +#define __VPM150M_RWPAGE (1 << 4) +#define __VPM150M_RD (1 << 3) +#define __VPM150M_WR (1 << 2) +#define __VPM150M_FIN (1 << 1) +#define __VPM150M_TX (1 << 0) +#define __VPM150M_RWPAGE (1 << 4) +#define __VPM150M_RD (1 << 3) +#define __VPM150M_WR (1 << 2) +#define __VPM150M_FIN (1 << 1) +#define __VPM150M_TX (1 << 0) + +/* Some Bit ops for different operations */ +#define VPM150M_SPIRESET 0 +#define VPM150M_HPIRESET 1 +#define VPM150M_SWRESET 2 +#define VPM150M_DTMFDETECT 3 +#define VPM150M_ACTIVE 4 -struct wctdm_firmware { - const struct firmware *fw; - unsigned int offset; +struct vpmadt032_cmd { + struct list_head node; + __le32 address; + __le16 data; + u8 desc; + u8 txident; + struct completion complete; }; -/* Host and DSP system dependent related definitions. */ -#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ -//#define MAX_CONFS 1 /* maximum number of conferences */ -//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ -#define MAX_CHANNELS 32 /* maximum number of channels */ -#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ -#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ -#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ -//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ -typedef unsigned short DSP_WORD; /* 16 bit DSP word */ -typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ -typedef struct wctdm_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ +/* Contains the options used when initializing the vpmadt032 module */ +struct vpmadt032_options { + int vpmnlptype; + int vpmnlpthresh; + int vpmnlpmaxsupp; + u32 debug; + u32 channels; +}; + +struct GpakChannelConfig; + +#define MAX_CHANNELS_PER_SPAN 32 +struct vpmadt032 { + void *context; + const struct dahdi_span *span; + struct work_struct work; + int dspid; + struct semaphore sem; + unsigned long control; + unsigned char curpage; + unsigned short version; + struct adt_lec_params curecstate[MAX_CHANNELS_PER_SPAN]; + struct adt_lec_params desiredecstate[MAX_CHANNELS_PER_SPAN]; + spinlock_t list_lock; + /* Commands that are ready to be used. */ + struct list_head free_cmds; + /* Commands that are waiting to be processed. */ + struct list_head pending_cmds; + /* Commands that are currently in progress by the VPM module */ + struct list_head active_cmds; + unsigned char curtone[MAX_CHANNELS_PER_SPAN]; + struct vpmadt032_options options; + void (*setchanconfig_from_state)(struct vpmadt032 *vpm, int channel, struct GpakChannelConfig *chanconfig); +}; + +struct voicebus; +struct dahdi_echocanparams; +struct dahdi_echocanparam; + +char vpmadt032tone_to_zaptone(GpakToneCodes_t tone); +int vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb); +struct vpmadt032 *vpmadt032_alloc(struct vpmadt032_options *options); +void vpmadt032_free(struct vpmadt032 *vpm); +int vpmadt032_echocan_with_params(struct vpmadt032 *vpm, int channo, + struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p); + +/* If there is a command ready to go to the VPMADT032, return it, otherwise NULL */ +static inline struct vpmadt032_cmd *vpmadt032_get_ready_cmd(struct vpmadt032 *vpm) +{ + unsigned long flags; + struct vpmadt032_cmd *cmd; + + spin_lock_irqsave(&vpm->list_lock, flags); + if (list_empty(&vpm->pending_cmds)) { + spin_unlock_irqrestore(&vpm->list_lock, flags); + return NULL; + } + cmd = list_entry(vpm->pending_cmds.next, struct vpmadt032_cmd, node); + list_move_tail(&cmd->node, &vpm->active_cmds); + spin_unlock_irqrestore(&vpm->list_lock, flags); + return cmd; +} + +int vpmadt032_module_init(void); + +typedef __u16 DSP_WORD; /* 16 bit DSP word */ +typedef __u32 DSP_ADDRESS; /* 32 bit DSP address */ +typedef __u32 GPAK_FILE_ID; /* G.PAK Download file identifier */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. @@ -74,7 +163,7 @@ typedef struct wctdm_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier * * */ extern void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ @@ -129,7 +218,6 @@ extern void gpakLockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. * @@ -144,7 +232,6 @@ extern void gpakUnlockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. * @@ -165,16 +252,6 @@ extern int gpakReadFile( ); -unsigned char wctdm_vpm150m_getpage(struct wctdm *wc); - -int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr); - -int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); - -unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); - -char vpm150mtone_to_zaptone(GpakToneCodes_t tone); - #endif /* prevent multiple inclusion */ diff --git a/drivers/dahdi/wctdm24xxp/GpakHpi.h b/drivers/dahdi/voicebus/GpakHpi.h index ffbf349..ffbf349 100644 --- a/drivers/dahdi/wctdm24xxp/GpakHpi.h +++ b/drivers/dahdi/voicebus/GpakHpi.h diff --git a/drivers/dahdi/voicebus/Kbuild b/drivers/dahdi/voicebus/Kbuild new file mode 100644 index 0000000..7b33956 --- /dev/null +++ b/drivers/dahdi/voicebus/Kbuild @@ -0,0 +1,5 @@ +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += dahdi_voicebus.o + +dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o + +EXTRA_CFLAGS := -I$(src)/.. -Wno-undef diff --git a/drivers/dahdi/wctdm24xxp/gpakErrs.h b/drivers/dahdi/voicebus/gpakErrs.h index c36a1b7..c36a1b7 100644 --- a/drivers/dahdi/wctdm24xxp/gpakErrs.h +++ b/drivers/dahdi/voicebus/gpakErrs.h diff --git a/drivers/dahdi/wctdm24xxp/gpakenum.h b/drivers/dahdi/voicebus/gpakenum.h index f488a81..f488a81 100644 --- a/drivers/dahdi/wctdm24xxp/gpakenum.h +++ b/drivers/dahdi/voicebus/gpakenum.h diff --git a/drivers/dahdi/voicebus.c b/drivers/dahdi/voicebus/voicebus.c index c67be25..d794365 100644 --- a/drivers/dahdi/voicebus.c +++ b/drivers/dahdi/voicebus/voicebus.c @@ -34,8 +34,12 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/timer.h> +#include <linux/module.h> +#include <dahdi/kernel.h> #include "voicebus.h" +#include "vpmadtreg.h" +#include "GpakCust.h" #define assert(__x__) BUG_ON(!(__x__)) @@ -365,6 +369,42 @@ voicebus_set_minlatency(struct voicebus *vb, unsigned int ms) VBUNLOCK(vb); return 0; } +EXPORT_SYMBOL(voicebus_set_minlatency); + +void +voicebus_get_handlers(struct voicebus *vb, void **handle_receive, + void **handle_transmit, void **context) +{ + LOCKS_VOICEBUS; + BUG_ON(!handle_receive); + BUG_ON(!handle_transmit); + BUG_ON(!context); + VBLOCK(vb); + *handle_receive = vb->handle_receive; + *handle_transmit = vb->handle_transmit; + *context = vb->context; + VBUNLOCK(vb); + return; +} +EXPORT_SYMBOL(voicebus_get_handlers); + +void +voicebus_set_handlers(struct voicebus *vb, + void (*handle_receive)(void *buffer, void *context), + void (*handle_transmit)(void *buffer, void *context), + void *context) +{ + LOCKS_VOICEBUS; + BUG_ON(!handle_receive); + BUG_ON(!handle_transmit); + BUG_ON(!context); + VBLOCK(vb); + vb->handle_receive = handle_receive; + vb->handle_transmit = handle_transmit; + vb->context = context; + VBUNLOCK(vb); +} +EXPORT_SYMBOL(voicebus_set_handlers); /*! \brief Returns the number of buffers currently on the transmit queue. */ int @@ -377,6 +417,7 @@ voicebus_current_latency(struct voicebus *vb) VBUNLOCK(vb); return latency; } +EXPORT_SYMBOL(voicebus_current_latency); /*! * \brief Read one of the hardware control registers without acquiring locks. @@ -549,12 +590,14 @@ voicebus_setdebuglevel(struct voicebus *vb, u32 level) { atomic_set(&vb->debuglevel, level); } +EXPORT_SYMBOL(voicebus_setdebuglevel); int voicebus_getdebuglevel(struct voicebus *vb) { return atomic_read(&vb->debuglevel); } +EXPORT_SYMBOL(voicebus_getdebuglevel); /*! \brief Resets the voicebus hardware interface. */ static int @@ -732,6 +775,7 @@ voicebus_transmit(struct voicebus *vb, void *vbb) { return vb_submit(vb, &vb->txd, vbb); } +EXPORT_SYMBOL(voicebus_transmit); /*! * \brief Give a frame to the hardware to use for receiving. @@ -931,6 +975,7 @@ voicebus_start(struct voicebus *vb) return 0; } +EXPORT_SYMBOL(voicebus_start); static void vb_clear_start_transmit_bit(struct voicebus *vb) @@ -1016,6 +1061,7 @@ voicebus_stop(struct voicebus *vb) return 0; } +EXPORT_SYMBOL(voicebus_stop); /*! * \brief Prepare the interface for module unload. @@ -1051,6 +1097,7 @@ voicebus_release(struct voicebus *vb) pci_disable_device(vb->pdev); kfree(vb); } +EXPORT_SYMBOL(voicebus_release); static void __vb_increase_latency(struct voicebus *vb) @@ -1467,6 +1514,7 @@ cleanup: assert(0 != retval); return retval; } +EXPORT_SYMBOL(voicebus_init); /*! \brief Return the pci_dev in use by this voicebus interface. */ @@ -1475,3 +1523,106 @@ voicebus_get_pci_dev(struct voicebus *vb) { return vb->pdev; } +EXPORT_SYMBOL(voicebus_get_pci_dev); + +static spinlock_t loader_list_lock; +static struct list_head binary_loader_list; + +/** + * vpmadtreg_loadfirmware - Load the vpmadt032 firmware. + * @vb: The voicebus device to load. + */ +int vpmadtreg_loadfirmware(struct voicebus *vb) +{ + struct vpmadt_loader *loader; + int ret = 0; + int loader_present = 0; + might_sleep(); + + /* First check to see if a loader is already loaded into memory. */ + spin_lock(&loader_list_lock); + loader_present = !(list_empty(&binary_loader_list)); + spin_unlock(&loader_list_lock); + + if (!loader_present) { + ret = request_module("dahdi_vpmadt032_loader"); + if (ret) + return ret; + } + + spin_lock(&loader_list_lock); + if (!list_empty(&binary_loader_list)) { + loader = list_entry(binary_loader_list.next, + struct vpmadt_loader, node); + if (try_module_get(loader->owner)) { + spin_unlock(&loader_list_lock); + ret = loader->load(vb); + module_put(loader->owner); + } else { + spin_unlock(&loader_list_lock); + printk(KERN_INFO "Failed to find a registered loader after loading module.\n"); + ret = -ENODEV; + } + } else { + spin_unlock(&loader_list_lock); + printk(KERN_INFO "Failed to find a registered loader after loading module.\n"); + ret = -1; + } + return ret; +} + +/* Called by the binary loader module when it is ready to start loading + * firmware. */ +int vpmadtreg_register(struct vpmadt_loader *loader) +{ + spin_lock(&loader_list_lock); + list_add_tail(&loader->node, &binary_loader_list); + spin_unlock(&loader_list_lock); + return 0; +} +EXPORT_SYMBOL(vpmadtreg_register); + +int vpmadtreg_unregister(struct vpmadt_loader *loader) +{ + int removed = 0; + struct vpmadt_loader *cur, *temp; + list_for_each_entry_safe(cur, temp, &binary_loader_list, node) { + if (loader == cur) { + list_del_init(&cur->node); + removed = 1; + break; + } + } + WARN_ON(!removed); + return 0; +} +EXPORT_SYMBOL(vpmadtreg_unregister); + +int __init voicebus_module_init(void) +{ + int res; + /* This registration with dahdi.ko will fail since the span is not + * defined, but it will make sure that this module is a dependency of + * dahdi.ko, so that when it is being unloded, this module will be + * unloaded as well. + */ + dahdi_register(0, 0); + INIT_LIST_HEAD(&binary_loader_list); + spin_lock_init(&loader_list_lock); + res = vpmadt032_module_init(); + if (res) + return res; + return 0; +} + +void __exit voicebus_module_cleanup(void) +{ + WARN_ON(!list_empty(&binary_loader_list)); +} + +MODULE_DESCRIPTION("Voicebus Interface w/VPMADT032 support"); +MODULE_AUTHOR("Digium Incorporated <support@digium.com>"); +MODULE_LICENSE("GPL"); + +module_init(voicebus_module_init); +module_exit(voicebus_module_cleanup); diff --git a/drivers/dahdi/voicebus.h b/drivers/dahdi/voicebus/voicebus.h index f3be573..eaa51e6 100644 --- a/drivers/dahdi/voicebus.h +++ b/drivers/dahdi/voicebus/voicebus.h @@ -6,7 +6,7 @@ * Matthew Fredrickson <creslin@digium.com>, and * Michael Spiceland <mspiceland@digium.com> * - * Copyright (C) 2007-2008 Digium, Inc. + * Copyright (C) 2007-2009 Digium, Inc. * * All rights reserved. * @@ -43,6 +43,12 @@ int voicebus_init(struct pci_dev* pdev, u32 framesize, void *context, u32 debuglevel, struct voicebus **vb_p); +void voicebus_get_handlers(struct voicebus *vb, void **handle_receive, + void **handle_transmit, void **context); +void voicebus_set_handlers(struct voicebus *vb, + void (*handle_receive)(void *buffer, void *context), + void (*handle_transmit)(void *buffer, void *context), + void *context); void voicebus_release(struct voicebus *vb); int voicebus_start(struct voicebus *vb); int voicebus_stop(struct voicebus *vb); diff --git a/drivers/dahdi/voicebus/vpmadtreg.c b/drivers/dahdi/voicebus/vpmadtreg.c new file mode 100644 index 0000000..33390d8 --- /dev/null +++ b/drivers/dahdi/voicebus/vpmadtreg.c @@ -0,0 +1,29 @@ +/* + * vpmadtreg.c - Registration utility for firmware loaders. + * + * Allows drivers for boards that host VPMAD032 modules to initiate firmware + * loads. + * + * Written by Digium Incorporated <support@digium.com> + * + * Copyright (C) 2008-2009 Digium, Inc. All rights reserved. + * + * See http://www.asterisk.org for more information about the Asterisk + * project. Please do not directly contact any of the maintainers of this + * project for assistance; the project provides a web site, mailing lists and + * IRC channels for your use. + * + * This program is free software, distributed under the terms of the GNU + * General Public License Version 2 as published by the Free Software + * Foundation. See the LICENSE file included with this program for more + * details. + */ + +#include <linux/spinlock.h> +#include <linux/module.h> +#include <linux/list.h> + +#include "voicebus.h" +#include "GpakCust.h" +#include "vpmadtreg.h" + diff --git a/drivers/dahdi/voicebus/vpmadtreg.h b/drivers/dahdi/voicebus/vpmadtreg.h new file mode 100644 index 0000000..f3a5b8c --- /dev/null +++ b/drivers/dahdi/voicebus/vpmadtreg.h @@ -0,0 +1,36 @@ +/* + * vpmadtreg.h - Registration utility for firmware loaders. + * + * Allows drivers for boards that host VPMAD032 modules to initiate firmware + * loads. + * + * Written by Digium Incorporated <support@digium.com> + * + * Copyright (C) 2008-2009 Digium, Inc. All rights reserved. + * + * See http://www.asterisk.org for more information about the Asterisk + * project. Please do not directly contact any of the maintainers of this + * project for assistance; the project provides a web site, mailing lists and + * IRC channels for your use. + * + * This program is free software, distributed under the terms of the GNU + * General Public License Version 2 as published by the Free Software + * Foundation. See the LICENSE file included with this program for more + * details. + */ +#ifndef __VPMADTREG_H__ +#define __VPMADTREG_H__ + +struct vpmadt032; +struct voicebus; + +struct vpmadt_loader { + struct module *owner; + struct list_head node; + int (*load)(struct voicebus *); +}; + +int vpmadtreg_register(struct vpmadt_loader *loader); +int vpmadtreg_unregister(struct vpmadt_loader *loader); +int vpmadtreg_loadfirmware(struct voicebus *vb); +#endif diff --git a/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c b/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c new file mode 100644 index 0000000..b43ae83 --- /dev/null +++ b/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c @@ -0,0 +1,154 @@ +/* + * DAHDI Telephony Interface to VPMADT032 Firmware Loader + * + * Copyright (C) 2008-2009 Digium, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/moduleparam.h> +#include <linux/pci.h> + +#include <dahdi/kernel.h> + +static int debug; + +#define module_printk(level, fmt, args...) \ + printk(level "%s: " fmt, THIS_MODULE->name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) \ + printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, \ + __func__, ## args) + +#include "voicebus/voicebus.h" +#include "voicebus/vpmadtreg.h" +#include "vpmadt032_loader.h" + +vpmlinkage static int __attribute__((format (printf, 1, 2))) +logger(const char *format, ...) +{ + int res; + va_list args; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9) + va_start(args, format); + res = vprintk(format, args); + va_end(args); +#else + char buf[256]; + + va_start(args, format); + res = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + printk(KERN_INFO "%s" buf); +#endif + + return res; +} + +vpmlinkage static void *memalloc(size_t len) +{ + return kmalloc(len, GFP_KERNEL); +} + +vpmlinkage static void memfree(void *ptr) +{ + kfree(ptr); +} + +struct private_context { + struct voicebus *vb; + void *old_rx; + void *old_tx; + void *old_context; + void *pvt; + struct completion done; +}; + +static void init_private_context(struct private_context *ctx) +{ + memset(ctx, 0, sizeof(ctx)); + init_completion(&ctx->done); +} + +static void handle_receive(void *vbb, void *context) +{ + struct private_context *ctx = context; + __vpmadt032_receive(ctx->pvt, vbb); + if (__vpmadt032_done(ctx->pvt)) + complete(&ctx->done); +} + +static void handle_transmit(void *vbb, void *context) +{ + struct private_context *ctx = context; + __vpmadt032_transmit(ctx->pvt, vbb); + voicebus_transmit(ctx->vb, vbb); +} + +static int vpmadt032_load_firmware(struct voicebus *vb) +{ + int ret = 0; + struct private_context *ctx; + struct pci_dev *pdev = voicebus_get_pci_dev(vb); + might_sleep(); + ctx = kmalloc(sizeof(struct private_context), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + init_private_context(ctx); + ctx->vb = vb; + ret = __vpmadt032_start_load( + 0, pdev->vendor << 16 | pdev->device, + &ctx->pvt); + if (ret) + goto error_exit; + voicebus_get_handlers(vb, &ctx->old_rx, &ctx->old_tx, + &ctx->old_context); + voicebus_set_handlers(vb, handle_receive, handle_transmit, ctx); + wait_for_completion(&ctx->done); + voicebus_set_handlers(vb, ctx->old_rx, ctx->old_tx, ctx->old_context); + __vpmadt032_cleanup(ctx->pvt); +error_exit: + kfree(ctx); + return 0; +} + +static struct vpmadt_loader loader = { + .owner = THIS_MODULE, + .load = vpmadt032_load_firmware, +}; + +static int __init vpmadt032_loader_init(void) +{ + __vpmadt032_init(logger, debug, memalloc, memfree); + vpmadtreg_register(&loader); + return 0; +} + +static void __exit vpmadt032_loader_exit(void) +{ + vpmadtreg_unregister(&loader); + return; +} + +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_DESCRIPTION("DAHDI VPMADT032 (Hardware Echo Canceller) Firmware Loader"); +MODULE_AUTHOR("Digium Incorporated <support@digium.com>"); +MODULE_LICENSE("Digium Commercial"); + +module_init(vpmadt032_loader_init); +module_exit(vpmadt032_loader_exit); diff --git a/drivers/dahdi/wctdm24xxp/GpakApi.c b/drivers/dahdi/wctdm24xxp/GpakApi.c deleted file mode 100644 index 1f1bb0b..0000000 --- a/drivers/dahdi/wctdm24xxp/GpakApi.c +++ /dev/null @@ -1,1630 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakApi.c - * - * Description: - * This file contains user API functions to communicate with DSPs executing - * G.PAK software. The file is integrated into the host processor connected - * to C55X G.PAK DSPs via a Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include <linux/semaphore.h> -#else -#include <asm/semaphore.h> -#endif - -#include <dahdi/kernel.h> - -#include "GpakHpi.h" -#include "GpakCust.h" -#include "GpakApi.h" -#include "gpakenum.h" - -/* DSP to Host interface block offsets. */ -#define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ -#define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ -#define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ -#define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ -#define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ -#define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ -#define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ -#define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ -#define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ -#define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ -#define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ -#define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ -//#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ -#define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ -//#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ -#define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ - -//#define GPAK_RELEASE_Rate rate10ms -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -// Macro to reconstruct a 32-bit value from two 16-bit values. -// Parameter p32: 32-bit-wide destination -// Parameter p16: 16-bit-wide source array of length 2 words -#define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ - p32 |= (unsigned long)p16[1] -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = - -/* DSP Status value definitions. */ -#define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ -#define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ - -/* Circular packet buffer information structure offsets. */ -#define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ -#define CB_BUFR_SIZE 2 /* size of buffer (words) */ -#define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ -#define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ -#define CIRC_BUFFER_INFO_STRUCT_SIZE 6 - -/* Miscellaneous definitions. */ -#define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ -#define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ - -#ifdef __TMS320C55XX__ // debug sections if not on host -#pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") -#endif - -/* Host variables related to Host to DSP interface. */ -static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ -static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ -static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ - -//static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ -//static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ -//static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ -//static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ -static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ - -static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ -static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CheckDspReset - Check if the DSP was reset. - * - * FUNCTION - * This function determines if the DSP was reset and is ready. If reset - * occurred, it reads interface parameters and calculates DSP addresses. - * - * RETURNS - * -1 = DSP is not ready. - * 0 = Reset did not occur. - * 1 = Reset occurred. - * - */ -static int CheckDspReset( - int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ - ) -{ - DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ - DSP_WORD DspStatus; /* DSP Status */ - DSP_WORD DspChannels; /* number of DSP channels */ - DSP_WORD Temp[2]; -#if 0 - DSP_WORD DspConfs; /* number of DSP conferences */ - DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ - unsigned short int i; /* loop index / counter */ -#endif - - /* Read the pointer to the Interface Block. */ - gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); - RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); - - /* If the pointer is zero, return with an indication the DSP is not - ready. */ - if (IfBlockPntr == 0) - return (-1); - - /* Read the DSP's Status. */ - gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); - - /* If status indicates the DSP was reset, read the DSP's interface - parameters and calculate DSP addresses. */ - if (DspStatus == DSP_INIT_STATUS || - ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) - { - /* Save the address of the DSP's Interface Block. */ - pDspIfBlk[DspId] = IfBlockPntr; - - /* Read the DSP's interface parameters. */ - gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, - &(MaxCmdMsgLen[DspId])); - - /* read the number of configured DSP channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_CHANNELS) - MaxChannels[DspId] = MAX_CHANNELS; - else - MaxChannels[DspId] = (unsigned short int) DspChannels; -#if 0 - /* read the number of configured DSP conferences */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, - &DspConfs); - if (DspConfs > MAX_CONFS) - MaxConfs[DspId] = MAX_CONFS; - else - MaxConfs[DspId] = (unsigned short int) DspConfs; - - - /* read the number of configured DSP packet channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_PKT_CHANNELS) - MaxPktChannels[DspId] = MAX_PKT_CHANNELS; - else - MaxPktChannels[DspId] = (unsigned short int) DspChannels; - - - /* read the pointer to the circular buffer infor struct table */ - gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(PktBufrMem, Temp); - - - /* Determine the addresses of each channel's Packet buffers. */ - for (i = 0; i < MaxPktChannels[DspId]; i++) - { - pPktInBufr[DspId][i] = PktBufrMem; - pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; - PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); - } -#endif - - /* read the pointer to the event fifo info struct */ - gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); - - /* Set the DSP Status to indicate the host recognized the reset. */ - DspStatus = HOST_INIT_STATUS; - gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, - &DspStatus); - - /* Return with an indication that a reset occurred. */ - return (1); - } - - /* If status doesn't indicate the host recognized a reset, return with an - indication the DSP is not ready. */ - if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) - return (-1); - - /* Return with an indication that a reset did not occur. */ - return (0); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * WriteDspCmdMessage - Write a Host Command/Request message to DSP. - * - * FUNCTION - * This function writes a Host Command/Request message into DSP memory and - * informs the DSP of the presence of the message. - * - * RETURNS - * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) - * 0 = Temporarily unable to write message (previous Cmd Msg busy) - * 1 = Message written successfully - * - */ -static int WriteDspCmdMessage( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMessage, /* pointer to Command message */ - DSP_WORD MsgLength /* length of message (octets) */ - ) -{ - DSP_WORD CmdMsgLength; /* current Cmd message length */ - DSP_WORD Temp[2]; - DSP_ADDRESS BufferPointer; /* message buffer pointer */ - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (-1); - - /* Make sure the message length is valid. */ - if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) - return (-1); - - /* Make sure a previous Command message is not in use by the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - if (CmdMsgLength != 0) - return (0); - - /* Purge any previous Reply message that wasn't read. */ - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - - /* Copy the Command message into DSP memory. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(BufferPointer, Temp); - gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); - - /* Store the message length in DSP's Command message length (flags DSP that - a Command message is ready). */ - CmdMsgLength = MsgLength; - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - - /* Return with an indication the message was written. */ - return (1); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadDspReplyMessage - Read a DSP Reply message from DSP. - * - * FUNCTION - * This function reads a DSP Reply message from DSP memory. - * - * RETURNS - * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) - * 0 = No message available (DSP Reply message empty) - * 1 = Message read successfully (message and length stored in variables) - * - */ -static int ReadDspReplyMessage( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMessage, /* pointer to Reply message buffer */ - DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ - ) -{ - DSP_WORD MsgLength; /* message length */ - DSP_ADDRESS BufferPointer; /* message buffer pointer */ - DSP_WORD Temp[2]; - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (-1); - - /* Check if a Reply message is ready. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &MsgLength); - if (MsgLength == 0) - return (0); - - /* Make sure the message length is valid. */ - if (MsgLength > *pMsgLength) - return (-1); - - /* Copy the Reply message from DSP memory. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(BufferPointer, Temp); - gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); - - /* Store the message length in the message length variable. */ - *pMsgLength = MsgLength; - - /* Indicate a Reply message is not ready. */ - MsgLength = 0; - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &MsgLength); - - /* Return with an indication the message was read. */ - return (1); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadCircBuffer - Read from a DSP circular buffer. - * - * FUNCTION - * This function reads a block of words from a DSP circular buffer. The Take - * address is incremented by the number of words read adjusting for buffer - * wrap. - * - * RETURNS - * nothing - * - */ -static void ReadCircBuffer( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ - DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ - DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ - DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ - DSP_WORD NumWords /* number of words to read */ - ) -{ - DSP_WORD WordsTillEnd; /* number of words until end of buffer */ - - /* Determine the number of words from the start address until the end of the - buffer. */ - WordsTillEnd = BufrLastAddress - *TakeAddress + 1; - - /* If a buffer wrap will occur, read the first part at the end of the - buffer followed by the second part at the beginning of the buffer. */ - if (NumWords > WordsTillEnd) - { - gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); - gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, - &(pWordBuffer[WordsTillEnd])); - *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; - } - - /* If a buffer wrap will not occur, read all words starting at the current - take address in the buffer. */ - else - { - gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); - if (NumWords == WordsTillEnd) - *TakeAddress = BufrBaseAddress; - else - *TakeAddress = *TakeAddress + NumWords; - } - return; -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * VerifyReply - Verify the reply message is correct for the command sent. - * - * FUNCTION - * This function verifies correct reply message content for the command that - * was just sent. - * - * RETURNS - * 0 = Incorrect - * 1 = Correct - * - */ -static int VerifyReply( - DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ - int CheckType, /* reply check type */ - DSP_WORD CheckValue /* reply check value */ - ) -{ - - /* Verify Channel or Conference Id. */ - if (CheckType == 1) - { - if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) - return (0); - } - - /* Verify Test Mode Id. */ - else if (CheckType == 2) - { - if (pMsgBufr[1] != CheckValue) - return (0); - } - - /* Return with an indication of correct reply. */ - return (1); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * TransactCmd - Send a command to the DSP and receive it's reply. - * - * FUNCTION - * This function sends the specified command to the DSP and receives the DSP's - * reply. - * - * RETURNS - * Length of reply message (0 = Failure) - * - */ -static unsigned int TransactCmd( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ - DSP_WORD CmdLength, /* length of command message (octets) */ - DSP_WORD ReplyType, /* required type of reply message */ - DSP_WORD ReplyLength, /* required length of reply message (octets) */ - int ReplyCheckType, /* reply check type */ - DSP_WORD ReplyCheckValue /* reply check value */ - ) -{ - int FuncStatus; /* function status */ - int LoopCount; /* wait loop counter */ - DSP_WORD RcvReplyLength; /* received Reply message length */ - DSP_WORD RcvReplyType; /* received Reply message type code */ - DSP_WORD RetValue; /* return value */ - - /* Default the return value to indicate a failure. */ - RetValue = 0; - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Attempt to write the command message to the DSP. */ - LoopCount = 0; - while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) - { - if (FuncStatus == -1) - break; - if (++LoopCount > MAX_WAIT_LOOPS) - break; - gpakHostDelay(); - } - - /* Attempt to read the reply message from the DSP if the command message was - sent successfully. */ - if (FuncStatus == 1) - { - for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) - { - RcvReplyLength = MSG_BUFFER_SIZE * 2; - FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); - if (FuncStatus == 1) - { - RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; - if ((RcvReplyLength >= ReplyLength) && - (RcvReplyType == ReplyType) && - VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) - { - RetValue = RcvReplyLength; - break; - } - else if (RcvReplyType == MSG_NULL_REPLY) - break; - } - else if (FuncStatus == -1) - break; - gpakHostDelay(); - } - } - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Return the length of the reply message (0 = failure). */ - return (RetValue); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigurePorts - Configure a DSP's serial ports. - * - * FUNCTION - * This function configures a DSP's serial ports. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakConfigPortStatus_t gpakConfigurePorts( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ - GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (CpsInvalidDsp); - - /* Build the Configure Serial Ports message. */ - MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; - MsgBuffer[1] = (DSP_WORD) - ((pPortConfig->SlotsSelect1 << 12) | - ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); - MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; - MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; - MsgBuffer[4] = (DSP_WORD) - ((pPortConfig->SlotsSelect2 << 12) | - ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); - MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; - MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; - MsgBuffer[7] = (DSP_WORD) - ((pPortConfig->SlotsSelect3 << 12) | - ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); - MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; - MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; - - MsgBuffer[10] = (DSP_WORD) - (((pPortConfig->DxDelay1 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | - ((pPortConfig->CompandingMode1 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); - - MsgBuffer[11] = (DSP_WORD) - (((pPortConfig->DxDelay2 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | - ((pPortConfig->CompandingMode2 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); - - MsgBuffer[12] = (DSP_WORD) - (((pPortConfig->DxDelay3 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | - ((pPortConfig->CompandingMode3 << 1) & 0x0006) | - (pPortConfig->SerialWordSize3 & 0x0001)); - - MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; - MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; - MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; - MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; - MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; - MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; - - MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; - MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; - MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; - MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; - MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; - MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; - - MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; - MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; - MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; - MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; - MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; - MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; - - - /* Attempt to send the Configure Serial Ports message to the DSP and receive - it's reply. */ - if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) - return (CpsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Pc_Success) - return (CpsSuccess); - else - return (CpsParmError); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigureChannel - Configure a DSP's Channel. - * - * FUNCTION - * This function configures a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakConfigChanStatus_t gpakConfigureChannel( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ - GpakChanType ChannelType, /* Channel Type */ - GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ - GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD MsgLength; /* message length */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (CcsInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (CcsInvalidChannel); - - /* Build the Configure Channel message based on the Channel Type. */ - switch (ChannelType) - { - - /* PCM to Packet channel type. */ - case tdmToTdm: - - MsgBuffer[2] = (DSP_WORD) - ((pChanConfig->PcmInPortA << 8) | - (pChanConfig->PcmInSlotA & 0xFF)); - MsgBuffer[3] = (DSP_WORD) - ((pChanConfig->PcmOutPortA << 8) | - (pChanConfig->PcmOutSlotA & 0xFF)); - - MsgBuffer[4] = (DSP_WORD) - ((pChanConfig->PcmInPortB << 8) | - (pChanConfig->PcmInSlotB & 0xFF)); - MsgBuffer[5] = (DSP_WORD) - ((pChanConfig->PcmOutPortB << 8) | - (pChanConfig->PcmOutSlotB & 0xFF)); - - MsgBuffer[6] = (DSP_WORD) - ( - ((pChanConfig->FaxCngDetB <<11) & 0x0800) | - ((pChanConfig->FaxCngDetA <<10) & 0x0400) | - ((pChanConfig->MuteToneB << 9) & 0x0200) | - ((pChanConfig->MuteToneA << 8) & 0x0100) | - ((pChanConfig->FrameRate << 6) & 0x00C0) | - ((pChanConfig->ToneTypesB << 5) & 0x0020) | - ((pChanConfig->ToneTypesA << 4) & 0x0010) | - ((pChanConfig->SoftwareCompand & 3) << 2) | - (pChanConfig->EcanEnableB << 1) | - (pChanConfig->EcanEnableA & 1) - ); - - MsgBuffer[7] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanTapLength; - MsgBuffer[8] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpType; - MsgBuffer[9] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanAdaptEnable; - MsgBuffer[10] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanG165DetEnable; - MsgBuffer[11] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanDblTalkThresh; - MsgBuffer[12] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpThreshold; - MsgBuffer[13] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpConv; - MsgBuffer[14] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpUnConv; - MsgBuffer[15] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpMaxSuppress; - - MsgBuffer[16] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanCngThreshold; - MsgBuffer[17] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanAdaptLimit; - MsgBuffer[18] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanCrossCorrLimit; - MsgBuffer[19] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNumFirSegments; - MsgBuffer[20] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanFirSegmentLen; - - MsgBuffer[21] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanTapLength; - MsgBuffer[22] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpType; - MsgBuffer[23] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanAdaptEnable; - MsgBuffer[24] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanG165DetEnable; - MsgBuffer[25] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanDblTalkThresh; - MsgBuffer[26] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpThreshold; - MsgBuffer[27] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpConv; - MsgBuffer[28] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpUnConv; - MsgBuffer[29] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpMaxSuppress; - MsgBuffer[30] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanCngThreshold; - MsgBuffer[31] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanAdaptLimit; - MsgBuffer[32] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanCrossCorrLimit; - MsgBuffer[33] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNumFirSegments; - MsgBuffer[34] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanFirSegmentLen; - - MsgLength = 70; // byte number == 35*2 - break; - - - /* Unknown (invalid) channel type. */ - default: - *pStatus = Cc_InvalidChannelType; - return (CcsParmError); - } - - MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); - - /* Attempt to send the Configure Channel message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (CcsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Cc_Success) - return (CcsSuccess); - else - return (CcsParmError); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. - * - * FUNCTION - * This function tears down a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakTearDownStatus_t gpakTearDownChannel( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ - GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (TdsInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (TdsInvalidChannel); - - /* Build the Tear Down Channel message. */ - MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; - MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); - - /* Attempt to send the Tear Down Channel message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (TdsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Td_Success) - return (TdsSuccess); - else - return (TdsError); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. - * - * FUNCTION - * This function controls an Algorithm - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakAlgControlStat_t gpakAlgControl( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakAlgCtrl_t ControlCode, // algorithm control code - GPAK_AlgControlStat_t *pStatus // pointer to return status - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (AcInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (AcInvalidChannel); - - MsgBuffer[0] = MSG_ALG_CONTROL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); - - /* Attempt to send the Tear Down Channel message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (AcDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Ac_Success) - return (AcSuccess); - else - return (AcParmError); - -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo - * - * FUNCTION - * This function reads a single event from the event fifo if one is available - * - * RETURNS - * Status code indicating success or a specific error. - * - * Notes: This function should be called in a loop until the return status - * indicates that the fifo is empty. - * - * If the event code equals "EventLoopbackTeardownComplete", then the - * contents of *pChannelId hold the coderBlockId that was assigned to - * the loopback coder that was torn down. - */ -gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( - unsigned short int DspId, // DSP identifier - unsigned short int *pChannelId, // pointer to channel identifier - GpakAsyncEventCode_t *pEventCode, // pointer to Event Code - GpakAsyncEventData_t *pEventData // pointer to Event Data Struct - ) -{ - DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ - GpakAsyncEventCode_t EventCode; /* DSP's event code */ - DSP_WORD EventDataLength; /* Length of event to read */ - DSP_WORD ChannelId; /* DSP's channel Id */ - DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ - DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ - DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ - DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ - DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ - DSP_WORD PutIndex; /* event fifo put index */ - DSP_WORD TakeIndex; /* event fifo take index */ - DSP_WORD WordsReady; /* number words ready for read out of event fifo */ - DSP_WORD EventError; /* flag indicating error with event fifo msg */ -#if 0 - DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ -#endif - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RefInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - { - gpakUnlockAccess(DspId); - return (RefDspCommFailure); - } - - /* Check if an event message is ready in the DSP. */ - EventInfoAddress = pEventFifoAddress[DspId]; - gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, - WordBuffer); - RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); - BufrSize = WordBuffer[CB_BUFR_SIZE]; - PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; - TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; - if (PutIndex >= TakeIndex) - WordsReady = PutIndex - TakeIndex; - else - WordsReady = PutIndex + BufrSize - TakeIndex; - - if (WordsReady < 2) - { - gpakUnlockAccess(DspId); - return (RefNoEventAvail); - } - - /* Read the event header from the DSP's Event FIFO. */ - TakeAddress = BufrBaseAddress + TakeIndex; - BufrLastAddress = BufrBaseAddress + BufrSize - 1; - ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, - WordBuffer, 2); - TakeIndex += 2; - if (TakeIndex >= BufrSize) - TakeIndex -= BufrSize; - - ChannelId = (WordBuffer[0] >> 8) & 0xFF; - EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); - EventDataLength = WordBuffer[1]; - EventError = 0; - - switch (EventCode) - { - case EventToneDetect: - if (EventDataLength > WORD_BUFFER_SIZE) - { - gpakUnlockAccess(DspId); -#if 0 - printk(KERN_DEBUG "EventDataLength > WORD_BUFFER_SIZE (%d)\n", EventDataLength); -#endif - return (RefInvalidEvent); - } - ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, - WordBuffer, EventDataLength); - pEventData->toneEvent.ToneCode = (GpakToneCodes_t) - (WordBuffer[0] & 0xFF); - pEventData->toneEvent.ToneDuration = WordBuffer[1]; - pEventData->toneEvent.Direction = WordBuffer[2]; - pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; - TakeIndex += EventDataLength; - if (TakeIndex >= BufrSize) - TakeIndex -= BufrSize; - if (EventDataLength != 4) { -#if 0 - printk(KERN_DEBUG "EventDataLength != 4 it's %d\n", EventDataLength); -#endif - EventError = 1; - } - break; - - default: -#if 0 - printk(KERN_DEBUG "Event Code not in switch\n"); -#endif - EventError = 1; - break; - }; - - /* Update the Take index in the DSP's Packet Out buffer information. */ - gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, - &TakeIndex); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - if (EventError) - return(RefInvalidEvent); - - *pChannelId = ChannelId; - *pEventCode = EventCode; - return(RefEventAvail); - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive - * - * FUNCTION - * This function checks if the DSP is still communicating with the host - * and returns the DSP SW version - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakPingDspStat_t gpakPingDsp( - unsigned short int DspId, // DSP identifier - unsigned short int *pDspSwVersion // DSP software version - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (PngInvalidDsp); - - /* send value of 1, DSP increments it */ - MsgBuffer[0] = (MSG_PING << 8); - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) - return (PngDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - { - *pDspSwVersion = MsgBuffer[2]; - return (PngSuccess); - } - else - return (PngDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot - * - * FUNCTION - * This function controls transmission of a fixed value out onto a serial - * port's timeslot. - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id - unsigned short int PcmOutSlot, // PCM Output Time Slot - unsigned short int Value, // 16-bit value - GpakActivation State // activation state - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (TfvInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (TfvInvalidChannel); - - - /* Build the message. */ - MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); - MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); - MsgBuffer[3] = (DSP_WORD) Value; - - /* Attempt to send the message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, - 1, ChannelId)) - return (TfvDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (TfvSuccess); - else - return (TfvDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state - * - * FUNCTION - * This function enables/disables the tdm input to output looback mode on a - * serial port - * - * RETURNS - * Status code indicating success or a specific error. - */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( - unsigned short int DspId, // DSP identifier - GpakSerialPort_t SerialPort, // Serial Port Id - GpakActivation LoopBackState // Loopback State - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (ClbInvalidDsp); - - /* Build the message. */ - MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; - MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); - - /* Attempt to send the message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) - return (ClbDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (ClbSuccess); - else - return (ClbDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. - * - * FUNCTION - * This function reads the CPU usage statistics from a DSP's memory. The - * average CPU usage in units of .1 percent are obtained for each of the frame - * rates. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadCpuUsageStat_t gpakReadCpuUsage( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pPeakUsage, // pointer to peak usage variable - unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second - ) -{ - DSP_WORD ReadBuffer[2]; /* DSP read buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RcuInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (RcuDspCommFailure); - - /* Read the CPU Usage statistics from the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, - ReadBuffer); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Store the usage statistics in the specified variables. */ - *pPrev1SecPeakUsage = ReadBuffer[0]; - *pPeakUsage = ReadBuffer[1]; - - /* Return with an indication the usage staistics were read successfully. */ - return (RcuSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics - * - * FUNCTION - * This function resets the cpu utilization statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakResetCpuUsageStat_t gpakResetCpuUsageStats( - unsigned short int DspId // DSP identifier - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RstcInvalidDsp); - - MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); - - /* Attempt to send the message to the DSP and receive it's reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) - return (RstcDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (RstcSuccess); - else - return (RstcDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats - * - * FUNCTION - * This function reads a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakReadFramingStatsStatus_t gpakReadFramingStats( - unsigned short int DspId, // DSP identifier - unsigned short int *pFramingError1Count, // port 1 Framing error count - unsigned short int *pFramingError2Count, // port 2 Framing error count - unsigned short int *pFramingError3Count, // port 3 Framing error count - unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count - unsigned short int *pDmaSlipStatsBuffer // DMA slips count - ) -{ - DSP_WORD ReadBuffer[10]; /* DSP read buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RfsInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (RfsDspCommFailure); - - /* Read the framing interrupt statistics from the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, - ReadBuffer); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Store the framing statistics in the specified variables. */ - *pFramingError1Count = ReadBuffer[0]; - *pFramingError2Count = ReadBuffer[1]; - *pFramingError3Count = ReadBuffer[2]; - *pDmaStopErrorCount = ReadBuffer[3]; - - if(pDmaSlipStatsBuffer != NULL) - // If users want to get the DMA slips count - { - pDmaSlipStatsBuffer[0] = ReadBuffer[4]; - pDmaSlipStatsBuffer[1] = ReadBuffer[5]; - pDmaSlipStatsBuffer[2] = ReadBuffer[6]; - pDmaSlipStatsBuffer[3] = ReadBuffer[7]; - pDmaSlipStatsBuffer[4] = ReadBuffer[8]; - pDmaSlipStatsBuffer[5] = ReadBuffer[9]; - - } - /* Return with an indication the statistics were read successfully. */ - return (RfsSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakResetFramingStatsStatus_t gpakResetFramingStats( - unsigned short int DspId // DSP identifier - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RstfInvalidDsp); - - MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); - - /* Attempt to send the message to the DSP and receive it's reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) - return (RstfDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (RstfSuccess); - else - return (RstfDspCommFailure); -} - -/* - * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. - * - * FUNCTION - * This function reads a DSP's Program and Data memory image from the - * specified file and writes the image to the DSP's memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakDownloadStatus_t gpakDownloadDsp( - unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ - ) -{ - gpakDownloadStatus_t RetStatus; /* function return status */ - int NumRead; /* number of file bytes read */ - DSP_ADDRESS Address; /* DSP address */ - unsigned int WordCount; /* number of words in record */ - unsigned int NumWords; /* number of words to read/write */ - unsigned int i; /* loop index / counter */ - unsigned int j; /* loop index */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (GdlInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - RetStatus = GdlSuccess; - while (RetStatus == GdlSuccess) - { - - /* Read a record header from the file. */ - NumRead = gpakReadFile(FileId, DlByteBufr, 6); - if (NumRead == -1) - { - RetStatus = GdlFileReadError; - break; - } - if (NumRead != 6) - { - RetStatus = GdlInvalidFile; - break; - } - Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | - (((DSP_ADDRESS) DlByteBufr[2]) << 8) | - ((DSP_ADDRESS) DlByteBufr[3]); - WordCount = (((unsigned int) DlByteBufr[4]) << 8) | - ((unsigned int) DlByteBufr[5]); - - /* Check for the End Of File record. */ - if (DlByteBufr[0] == 0xFF) - break; - - /* Verify the record is for a valid memory type. */ - if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) - { - RetStatus = GdlInvalidFile; - break; - } - - /* Read a block of words at a time from the file and write to the - DSP's memory .*/ - while (WordCount != 0) - { - if (WordCount < DOWNLOAD_BLOCK_SIZE) - NumWords = WordCount; - else - NumWords = DOWNLOAD_BLOCK_SIZE; - WordCount -= NumWords; - NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); - if (NumRead == -1) - { - RetStatus = GdlFileReadError; - break; - } - if (NumRead != (NumWords * 2)) - { - RetStatus = GdlInvalidFile; - break; - } - for (i = 0, j = 0; i < NumWords; i++, j += 2) - DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | - ((DSP_WORD) DlByteBufr[j + 1]); - gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); - Address += ((DSP_ADDRESS) NumWords); - } - } - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Return with an indication of success or failure. */ - return (RetStatus); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. - * - * FUNCTION - * This function reads the memory map register section of DSP memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pDest, // Buffer on host to hold DSP memory map - DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out - unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP reply's status */ - int i; /* loop index / counter */ - - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RmmInvalidDsp); - - /* Verify the message buffer is large enough */ - if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) - return (RmmSizeTooBig); - - MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; - MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); - MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); - MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; - - /* Attempt to send the Read memory section message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, - (MemoryLength_Word16+2)*2, 0, 0) ) - return (RmmInvalidAddress); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus != 0) - return (RmmFailure); - - for (i = 0; i < MemoryLength_Word16; i++) - pDest[i] = (short int) MsgBuffer[2 + i]; - - - return (RmmSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAccessGPIO - change Direction/read/write the GPIO on DSP - * - * FUNCTION - * This function read/write GPIO and change the GPIO direction - * - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakAccessGPIOStat_t gpakAccessGPIO( - unsigned short int DspId, // DSP identifier - GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read - unsigned short int *pGPIOValue // DSP software version - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (GPIOInvalidDsp); - - /* send value of 1, DSP increments it */ - MsgBuffer[0] = (MSG_ACCESSGPIO << 8); - MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) - return (GPIODspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - { - *pGPIOValue = MsgBuffer[2]; - return (GPIOSuccess); - } - else - return (GPIODspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteSystemParms - Write a DSP's System Parameters. - * - * FUNCTION - * This function writes a DSP's System Parameters information. - * - * Note: - * Or-together the desired bit-mask #defines that are listed below. Only - * those algorithm parameters whose bit-mask is selected in the UpdateBits - * function parameter will be updated. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ - -gpakWriteSysParmsStatus_t gpakWriteSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ - unsigned short int UpdateBits, /* input: flags indicating which parms to update */ - GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (WspInvalidDsp); - - /* Build the Write System Parameters message. */ - MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; - - if (UpdateBits & DTMF_UPDATE_MASK) - { - MsgBuffer[1] |= DTMF_UPDATE_MASK; - MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; - MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); - if (pSysParms->SNRFlag) - MsgBuffer[9] |= (1<<8); - } - - MsgBuffer[10] = (DSP_WORD) 0; - if (UpdateBits & DTMF_TWIST_UPDATE_MASK) - { - MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; - MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); - MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); - } - - - if (UpdateBits & DTMF_VALID_MASK) - { - MsgBuffer[1] |= DTMF_VALID_MASK; - MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); - } - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) - return (WspDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); - - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (WspSuccess); - else - return (WspDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadSystemParms - Read a DSP's System Parameters. - * - * FUNCTION - * This function reads a DSP's System Parameters information. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadSysParmsStatus_t gpakReadSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ - ) -{ - - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RspInvalidDsp); - - /* Build the Read System Parameters message. */ - MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) - return (RspDspCommFailure); - - /* Extract the System Parameters information from the message. */ - pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; - - pSysParms->MinSigLevel = (short int)MsgBuffer[8]; - pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); - pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); - pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; - pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; - - /* Return with an indication that System Parameters info was obtained. */ - return (RspSuccess); -} diff --git a/drivers/dahdi/wctdm24xxp/GpakCust.c b/drivers/dahdi/wctdm24xxp/GpakCust.c deleted file mode 100644 index a32fb96..0000000 --- a/drivers/dahdi/wctdm24xxp/GpakCust.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakCust.c - * - * Description: - * This file contains host system dependent functions to support generic - * G.PAK API functions. The file is integrated into the host processor - * connected to C55x G.PAK DSPs via a Host Port Interface. - * - * Note: This file needs to be modified by the G.PAK system integrator. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#include <linux/version.h> -#include <linux/delay.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include <linux/semaphore.h> -#else -#include <asm/semaphore.h> -#endif - -#include <dahdi/kernel.h> - -#include "wctdm24xxp.h" -#include "GpakCust.h" - -char vpm150mtone_to_zaptone(GpakToneCodes_t tone) -{ - switch (tone) { - case DtmfDigit0: - return '0'; - case DtmfDigit1: - return '1'; - case DtmfDigit2: - return '2'; - case DtmfDigit3: - return '3'; - case DtmfDigit4: - return '4'; - case DtmfDigit5: - return '5'; - case DtmfDigit6: - return '6'; - case DtmfDigit7: - return '7'; - case DtmfDigit8: - return '8'; - case DtmfDigit9: - return '9'; - case DtmfDigitPnd: - return '#'; - case DtmfDigitSt: - return '*'; - case DtmfDigitA: - return 'A'; - case DtmfDigitB: - return 'B'; - case DtmfDigitC: - return 'C'; - case DtmfDigitD: - return 'D'; - case EndofCngDigit: - return 'f'; - default: - return 0; - } -} - -static inline struct wctdm * wc_find_iface(unsigned short dspid) -{ - int i; - struct wctdm *ret = NULL; - unsigned long flags; - - spin_lock_irqsave(&ifacelock, flags); - for (i = 0; i < WC_MAX_IFACES; i++) - if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) - ret = ifaces[i]; - spin_unlock_irqrestore(&ifacelock, flags); - - return ret; -} - -static inline struct vpm150m_cmd * vpm150m_empty_slot(struct wctdm *wc) -{ - int x; - - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) - if (!wc->vpm150m->cmdq[x].desc) { - return &wc->vpm150m->cmdq[x]; - } - return NULL; -} - -/* Wait for any outstanding commands to be completed. */ -static inline int vpm150m_io_wait(struct wctdm *wc) -{ - int x; - int ret=0; - for (x=0; x < VPM150M_MAX_COMMANDS;) { - if (wc->vpm150m->cmdq[x].desc) { - if ((ret=schluffen(&wc->regq))) { - return ret; - } - x=0; - } - else { - ++x; - } - } - return ret; -} - -static int wctdm_vpm150m_getreg_full_async(struct wctdm *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret=0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - (*hit_p) = vpm150m_empty_slot(wc); - if (*hit_p) { - (*hit_p)->desc = __VPM150M_RD; - if (pagechange) { - (*hit_p)->desc |= __VPM150M_RWPAGE; - } - (*hit_p)->datalen = len; - (*hit_p)->addr = addr; - memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); - } - else { - ret = -EBUSY; - } - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static int wctdm_vpm150m_getreg_full_return(struct wctdm *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret = 0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - do { - if ((*hit_p)->desc & __VPM150M_FIN) { - memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); - (*hit_p)->desc = 0; - (*hit_p) = NULL; - ret = 0; - } - else { - spin_unlock_irqrestore(&wc->reglock, flags); - if ((ret=schluffen(&wc->regq))) { - return ret; - } - spin_lock_irqsave(&wc->reglock, flags); - ret = -EBUSY; - } - } while (-EBUSY == ret); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static int wctdm_vpm150m_getreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) -{ - struct vpm150m_cmd *hit = NULL; - int ret = 0; - do { - ret = wctdm_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); - if (!hit) { - if ( -EBUSY == ret ) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - BUG_ON(0 != ret); - } - } while (!hit); - ret = wctdm_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); - return ret; -} - -static int wctdm_vpm150m_setreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned long flags; - struct vpm150m_cmd *hit; - int ret, i; - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = vpm150m_empty_slot(wc); - if (hit) { - hit->desc = __VPM150M_WR; - if (pagechange) - hit->desc |= __VPM150M_RWPAGE; - hit->addr = addr; - hit->datalen = len; - for (i = 0; i < len; i++) - hit->data[i] = data[i]; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (!hit) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (!hit); - return (hit) ? 0 : -1; -} - -int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr) -{ - addr &= 0xf; - /* Let's optimize this a little bit */ - if (wc->vpm150m->curpage == addr) - return 0; - else { - wc->vpm150m->curpage = addr; - } - - return wctdm_vpm150m_setreg_full(wc, 1, 1, 0, &addr); -} - -unsigned char wctdm_vpm150m_getpage(struct wctdm *wc) -{ - unsigned short res; - wctdm_vpm150m_getreg_full(wc, 1, 1, 0, &res); - return res; -} - -unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned short res; - wctdm_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - printk(KERN_INFO "getreg: You found it!\n"); - res = wctdm_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - int res; - wctdm_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - printk(KERN_INFO "getreg: You found it!\n"); - res = wctdm_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. - * - * FUNCTION - * This function reads a contiguous block of words from DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ) -{ - struct wctdm *wc = wc_find_iface(DspId); - int i; - int transcount; - int ret; - - vpm150m_io_wait(wc); - if ( NumWords < VPM150M_MAX_COMMANDS ) { - struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = { NULL }; - wctdm_vpm150m_setpage(wc, DspAddress >> 16); - DspAddress &= 0xffff; - for (i=0; i < NumWords; ++i) { - ret = wctdm_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - for (i=NumWords-1; i >=0; --i) { - ret = wctdm_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - } - else { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - wctdm_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } - } - return; -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. - * - * FUNCTION - * This function writes a contiguous block of words to DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ) -{ - - struct wctdm *wc = wc_find_iface(DspId); - int i; - int transcount; - - //printk(KERN_DEBUG "Writing %d words to memory\n", NumWords); - if (wc && wc->vpm150m) { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - - wctdm_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } -#if 0 - for (i = 0; i < NumWords; i++) { - if (wctdm_vpm150m_getreg(wc, DspAddress + i) != pWordValues[i]) { - printk(KERN_NOTICE "Error in write. Address %x is not %x\n", DspAddress + i, pWordValues[i]); - } - } -#endif - } - return; - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. - * - * FUNCTION - * This function delays for a fixed time interval before returning. The time - * interval is the Host Port Interface sampling period when polling a DSP for - * replies to command messages. - * - * RETURNS - * nothing - * - */ -void gpakHostDelay(void) -{ -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. - * - * FUNCTION - * This function aquires exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakLockAccess(unsigned short DspId) -{ - struct wctdm *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) { - if (down_interruptible(&vpm->sem)) { - return; - } - } - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. - * - * FUNCTION - * This function releases exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakUnlockAccess(unsigned short DspId) -{ - struct wctdm *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - up(&vpm->sem); - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. - * - * FUNCTION - * This function reads a contiguous block of bytes from a G.PAK Download file - * starting at the current file position. - * - * RETURNS - * The number of bytes read from the file. - * -1 indicates an error occurred. - * 0 indicates all bytes have been read (end of file) - * - */ -int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ) -{ -#ifdef VPM150M_SUPPORT - struct wctdm_firmware *fw = FileId; - unsigned int i, count; - - if (!fw || !fw->fw) - return -1; - - if (NumBytes > (fw->fw->size - fw->offset)) - count = fw->fw->size - fw->offset; - else - count = NumBytes; - - for (i = 0; i < count; i++) - pBuffer[i] = fw->fw->data[fw->offset + i]; - - fw->offset += count; - - return count; -#endif -} diff --git a/drivers/dahdi/wctdm24xxp/Kbuild b/drivers/dahdi/wctdm24xxp/Kbuild index 69eddc3..6b1d0e7 100644 --- a/drivers/dahdi/wctdm24xxp/Kbuild +++ b/drivers/dahdi/wctdm24xxp/Kbuild @@ -1,18 +1,5 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp.o -FIRM_DIR := ../firmware - EXTRA_CFLAGS += -I$(src)/.. -Wno-undef -ifeq ($(HOTPLUG_FIRMWARE),yes) - EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE -endif - -wctdm24xxp-objs := base.o GpakCust.o GpakApi.o voicebus.o - -ifneq ($(HOTPLUG_FIRMWARE),yes) -wctdm24xxp-objs += $(FIRM_DIR)/dahdi-fw-vpmadt032.o -endif - -$(obj)/$(FIRM_DIR)/dahdi-fw-vpmadt032.o: $(obj)/base.o - $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-vpmadt032.o +wctdm24xxp-objs := base.o diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c index da48cfe..9a6a8ce 100644 --- a/drivers/dahdi/wctdm24xxp/base.c +++ b/drivers/dahdi/wctdm24xxp/base.c @@ -4,7 +4,7 @@ * Written by Mark Spencer <markster@digium.com> * Support for TDM800P and VPM150M by Matthew Fredrickson <creslin@digium.com> * - * Copyright (C) 2005 - 2008 Digium, Inc. + * Copyright (C) 2005 - 2009 Digium, Inc. * All rights reserved. * * Sections for QRV cards written by Jim Dixon <jim@lambdatel.com> @@ -58,12 +58,10 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db #include "wctdm24xxp.h" -#ifdef VPM150M_SUPPORT #include "adt_lec.h" -#endif -#include "GpakCust.h" -#include "GpakApi.h" +#include "voicebus/GpakCust.h" +#include "voicebus/GpakApi.h" /* Experimental max loop current limit for the proslic @@ -213,11 +211,8 @@ static int neonmwi_envelope = 10; static int neonmwi_offlimit = 16000; /* Time in milliseconds the monitor is checked before saying no message is waiting */ static int neonmwi_offlimit_cycles; /* Time in milliseconds the monitor is checked before saying no message is waiting */ -#ifdef VPM_SUPPORT static int vpmsupport = 1; -static int vpmdtmfsupport = 0; -#define VPM_DEFAULT_DTMFTHRESHOLD 1250 -static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; + /* * This parameter is used to adjust the NLP type used. The options are: * 0 : None @@ -232,7 +227,6 @@ static int vpmnlptype = 1; static int vpmnlpthresh = 24; /* See vpmnlptype = 4 for more info */ static int vpmnlpmaxsupp = 0; -#endif static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); @@ -276,12 +270,193 @@ static inline int empty_slot(struct wctdm *wc, int card) return -1; } -#ifdef VPM_SUPPORT -static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char *writechunk, int whichframe) +void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelConfig_t *chanconfig) +{ + const struct vpmadt032_options *options; + + BUG_ON(!vpm); + + options = &vpm->options; + + chanconfig->PcmInPortA = 3; + chanconfig->PcmInSlotA = channel; + chanconfig->PcmOutPortA = SerialPortNull; + chanconfig->PcmOutSlotA = channel; + chanconfig->PcmInPortB = 2; + chanconfig->PcmInSlotB = channel; + chanconfig->PcmOutPortB = 3; + chanconfig->PcmOutSlotB = channel; + chanconfig->ToneTypesA = Null_tone; + chanconfig->MuteToneA = Disabled; + chanconfig->FaxCngDetA = Disabled; + chanconfig->ToneTypesB = Null_tone; + chanconfig->EcanEnableA = Enabled; + chanconfig->EcanEnableB = Disabled; + chanconfig->MuteToneB = Disabled; + chanconfig->FaxCngDetB = Disabled; + + switch (vpm->span->deflaw) { + case DAHDI_LAW_MULAW: + chanconfig->SoftwareCompand = cmpPCMU; + break; + case DAHDI_LAW_ALAW: + chanconfig->SoftwareCompand = cmpPCMA; + break; + default: + chanconfig->SoftwareCompand = cmpPCMU; + break; + } + + chanconfig->FrameRate = rate2ms; + chanconfig->EcanParametersA.EcanTapLength = 1024; + chanconfig->EcanParametersA.EcanNlpType = vpm->curecstate[channel].nlp_type; + chanconfig->EcanParametersA.EcanAdaptEnable = 1; + chanconfig->EcanParametersA.EcanG165DetEnable = 1; + chanconfig->EcanParametersA.EcanDblTalkThresh = 6; + chanconfig->EcanParametersA.EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; + chanconfig->EcanParametersA.EcanNlpConv = 0; + chanconfig->EcanParametersA.EcanNlpUnConv = 0; + chanconfig->EcanParametersA.EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; + chanconfig->EcanParametersA.EcanCngThreshold = 43; + chanconfig->EcanParametersA.EcanAdaptLimit = 50; + chanconfig->EcanParametersA.EcanCrossCorrLimit = 15; + chanconfig->EcanParametersA.EcanNumFirSegments = 3; + chanconfig->EcanParametersA.EcanFirSegmentLen = 48; + + memcpy(&chanconfig->EcanParametersB, + &chanconfig->EcanParametersA, + sizeof(chanconfig->EcanParametersB)); +} + +static int config_vpmadt032(struct vpmadt032 *vpm) +{ + int res, i; + GpakPortConfig_t portconfig = {0}; + gpakConfigPortStatus_t configportstatus; + GPAK_PortConfigStat_t pstatus; + GpakChannelConfig_t chanconfig; + GPAK_ChannelConfigStat_t cstatus; + GPAK_AlgControlStat_t algstatus; + + /* First Serial Port config */ + portconfig.SlotsSelect1 = SlotCfgNone; + portconfig.FirstBlockNum1 = 0; + portconfig.FirstSlotMask1 = 0x0000; + portconfig.SecBlockNum1 = 1; + portconfig.SecSlotMask1 = 0x0000; + portconfig.SerialWordSize1 = SerWordSize8; + portconfig.CompandingMode1 = cmpNone; + portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.TxClockPolarity1 = SerClockActHigh; + portconfig.RxClockPolarity1 = SerClockActHigh; + portconfig.TxDataDelay1 = DataDelay0; + portconfig.RxDataDelay1 = DataDelay0; + portconfig.DxDelay1 = Disabled; + portconfig.ThirdSlotMask1 = 0x0000; + portconfig.FouthSlotMask1 = 0x0000; + portconfig.FifthSlotMask1 = 0x0000; + portconfig.SixthSlotMask1 = 0x0000; + portconfig.SevenSlotMask1 = 0x0000; + portconfig.EightSlotMask1 = 0x0000; + + /* Second Serial Port config */ + portconfig.SlotsSelect2 = SlotCfg2Groups; + portconfig.FirstBlockNum2 = 0; + portconfig.FirstSlotMask2 = 0xffff; + portconfig.SecBlockNum2 = 1; + portconfig.SecSlotMask2 = 0xffff; + portconfig.SerialWordSize2 = SerWordSize8; + portconfig.CompandingMode2 = cmpNone; + portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.TxClockPolarity2 = SerClockActHigh; + portconfig.RxClockPolarity2 = SerClockActLow; + portconfig.TxDataDelay2 = DataDelay0; + portconfig.RxDataDelay2 = DataDelay0; + portconfig.DxDelay2 = Disabled; + portconfig.ThirdSlotMask2 = 0x0000; + portconfig.FouthSlotMask2 = 0x0000; + portconfig.FifthSlotMask2 = 0x0000; + portconfig.SixthSlotMask2 = 0x0000; + portconfig.SevenSlotMask2 = 0x0000; + portconfig.EightSlotMask2 = 0x0000; + + /* Third Serial Port Config */ + portconfig.SlotsSelect3 = SlotCfg2Groups; + portconfig.FirstBlockNum3 = 0; + portconfig.FirstSlotMask3 = 0xffff; + portconfig.SecBlockNum3 = 1; + portconfig.SecSlotMask3 = 0xffff; + portconfig.SerialWordSize3 = SerWordSize8; + portconfig.CompandingMode3 = cmpNone; + portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.TxClockPolarity3 = SerClockActHigh; + portconfig.RxClockPolarity3 = SerClockActLow; + portconfig.TxDataDelay3 = DataDelay0; + portconfig.RxDataDelay3 = DataDelay0; + portconfig.DxDelay3 = Disabled; + portconfig.ThirdSlotMask3 = 0x0000; + portconfig.FouthSlotMask3 = 0x0000; + portconfig.FifthSlotMask3 = 0x0000; + portconfig.SixthSlotMask3 = 0x0000; + portconfig.SevenSlotMask3 = 0x0000; + portconfig.EightSlotMask3 = 0x0000; + + if ((configportstatus = gpakConfigurePorts(vpm->dspid, &portconfig, &pstatus))) { + printk(KERN_NOTICE "Configuration of ports failed (%d)!\n", configportstatus); + return -1; + } else { + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "Configured McBSP ports successfully\n"); + } + + if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { + printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); + return -1; + } + + for (i = 0; i < vpm->span->channels; ++i) { + vpm->curecstate[i].tap_length = 0; + vpm->curecstate[i].nlp_type = vpm->options.vpmnlptype; + vpm->curecstate[i].nlp_threshold = vpm->options.vpmnlpthresh; + vpm->curecstate[i].nlp_max_suppress = vpm->options.vpmnlpmaxsupp; + memcpy(&vpm->desiredecstate[i], &vpm->curecstate[i], sizeof(vpm->curecstate[i])); + + /* set_vpmadt032_chanconfig_from_state(&vpm->curecstate[i], &vpm->options, i, &chanconfig); !!! */ + vpm->setchanconfig_from_state(vpm, i, &chanconfig); + if ((res = gpakConfigureChannel(vpm->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { + printk(KERN_NOTICE "Unable to configure channel #%d (%d)", i, res); + if (res == 1) { + printk(", reason %d", cstatus); + } + printk("\n"); + return -1; + } + + if ((res = gpakAlgControl(vpm->dspid, i, BypassEcanA, &algstatus))) { + printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + } + + if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { + printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); + return -1; + } + + set_bit(VPM150M_ACTIVE, &vpm->control); + + return 0; +} + + +static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, unsigned char *writechunk, int whichframe) { unsigned long flags; - struct vpm150m_cmd *curcmd = NULL; - struct vpm150m *vpm150m = wc->vpm150m; + struct vpmadt032_cmd *curcmd = NULL; + struct vpmadt032 *vpmadt032 = wc->vpmadt032; int x; unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; @@ -290,14 +465,14 @@ static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char spin_lock_irqsave(&wc->reglock, flags); - if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { + if (test_bit(VPM150M_SPIRESET, &vpmadt032->control) || test_bit(VPM150M_HPIRESET, &vpmadt032->control)) { if (debug & DEBUG_ECHOCAN) printk(KERN_INFO "HW Resetting VPMADT032...\n"); for (x = 24; x < 28; x++) { if (x == 24) { - if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) + if (test_and_clear_bit(VPM150M_SPIRESET, &vpmadt032->control)) writechunk[CMD_BYTE(x, 0, 0)] = 0x08; - else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) + else if (test_and_clear_bit(VPM150M_HPIRESET, &vpmadt032->control)) writechunk[CMD_BYTE(x, 0, 0)] = 0x0b; } else writechunk[CMD_BYTE(x, 0, 0)] = 0x00 | leds; @@ -308,20 +483,11 @@ static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char return; } - - /* Search for something waiting to transmit */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && - !(vpm150m->cmdq[x].desc & (__VPM150M_FIN | __VPM150M_TX))) { - curcmd = &vpm150m->cmdq[x]; - curcmd->txident = wc->txident; - curcmd->desc |= __VPM150M_TX; - break; - } - } - if (curcmd) { + if ((curcmd = vpmadt032_get_ready_cmd(vpmadt032))) { + curcmd->txident = wc->txident; #if 0 - printk(KERN_DEBUG "Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); + // if (printk_ratelimit()) + printk(KERN_DEBUG "Transmitting txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->address, curcmd->data); #endif if (curcmd->desc & __VPM150M_RWPAGE) { /* Set CTRL access to page*/ @@ -336,7 +502,7 @@ static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4 | 0x1) << 4); writechunk[CMD_BYTE(25, 1, 0)] = 0; if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xf; + writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data & 0xf; else writechunk[CMD_BYTE(25, 2, 0)] = 0; @@ -353,54 +519,25 @@ static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char } else { /* Set address */ writechunk[CMD_BYTE(24, 0, 0)] = ((0x8 | 0x4) << 4); - writechunk[CMD_BYTE(24, 1, 0)] = (curcmd->addr >> 8) & 0xff; - writechunk[CMD_BYTE(24, 2, 0)] = curcmd->addr & 0xff; + writechunk[CMD_BYTE(24, 1, 0)] = (curcmd->address >> 8) & 0xff; + writechunk[CMD_BYTE(24, 2, 0)] = curcmd->address & 0xff; /* Send/Get our data */ - if (curcmd->desc & __VPM150M_WR) { - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1)) << 4); - } else - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - else - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(25, 1, 0)] = (curcmd->data[0] >> 8) & 0xff; - writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xff; + writechunk[CMD_BYTE(25, 0, 0)] = (curcmd->desc & __VPM150M_WR) ? + ((0x8 | (0x3 << 1)) << 4) : ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(25, 1, 0)] = (curcmd->data >> 8) & 0xff; + writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data & 0xff; - if (curcmd->datalen > 1) { - if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(26, 1, 0)] = (curcmd->data[1] >> 8) & 0xff; - writechunk[CMD_BYTE(26, 2, 0)] = curcmd->data[1] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(26, 0, 0)] = 0; - writechunk[CMD_BYTE(26, 1, 0)] = 0; - writechunk[CMD_BYTE(26, 2, 0)] = 0; - } - - if (curcmd->datalen > 2) { - if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(27, 1, 0)] = (curcmd->data[2] >> 8) & 0xff; - writechunk[CMD_BYTE(27, 2, 0)] = curcmd->data[2] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(27, 0, 0)] = 0; - writechunk[CMD_BYTE(27, 1, 0)] = 0; - writechunk[CMD_BYTE(27, 2, 0)] = 0; - } - + writechunk[CMD_BYTE(26, 0, 0)] = 0; + writechunk[CMD_BYTE(26, 1, 0)] = 0; + writechunk[CMD_BYTE(26, 2, 0)] = 0; + /* Fill in the rest */ + writechunk[CMD_BYTE(27, 0, 0)] = 0; + writechunk[CMD_BYTE(27, 1, 0)] = 0; + writechunk[CMD_BYTE(27, 2, 0)] = 0; } - } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { + } else if (test_and_clear_bit(VPM150M_SWRESET, &vpmadt032->control)) { printk(KERN_INFO "Booting VPMADT032\n"); for (x = 24; x < 28; x++) { if (x == 24) @@ -421,19 +558,18 @@ static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char } } -#ifdef VPM150M_SUPPORT /* Add our leds in */ - for (x = 24; x < 28; x++) + for (x = 24; x < 28; x++) { writechunk[CMD_BYTE(x, 0, 0)] |= leds; + } /* Now let's figure out if we need to check for DTMF */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) - queue_work(vpm150m->wq, &vpm150m->work); -#endif + if (test_bit(VPM150M_ACTIVE, &vpmadt032->control) && !whichframe && !(wc->intcount % 100)) { + schedule_work(&vpmadt032->work); + } spin_unlock_irqrestore(&wc->reglock, flags); } -#endif /* VPM_SUPPORT */ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writechunk, int card, int pos) { @@ -519,7 +655,6 @@ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writech writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80; else writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; -#ifdef VPM_SUPPORT } else if (wc->modtype[card] == MOD_TYPE_VPM) { if (curcmd & __CMD_WR) writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1); @@ -528,7 +663,7 @@ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writech writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; } else if (wc->modtype[card] == MOD_TYPE_VPM150M) { -#endif + ; } else if (wc->modtype[card] == MOD_TYPE_QRV) { writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; @@ -562,42 +697,52 @@ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writech #endif } -#ifdef VPM_SUPPORT -static inline void cmd_decifer_vpm150m(struct wctdm *wc, volatile unsigned char *readchunk) +static inline void cmd_decipher_vpmadt032(struct wctdm *wc, unsigned char *readchunk) { unsigned long flags; - unsigned char ident; - int x, i; + struct vpmadt032 *vpm = wc->vpmadt032; + struct vpmadt032_cmd *cmd; + + BUG_ON(!vpm); + + /* If the hardware is not processing any commands currently, then + * there is nothing for us to do here. */ + if (list_empty(&vpm->active_cmds)) { + return; + } + + spin_lock_irqsave(&vpm->list_lock, flags); + cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node); + if (wc->rxident == cmd->txident) { + list_del_init(&cmd->node); + } else { + cmd = NULL; + } + spin_unlock_irqrestore(&vpm->list_lock, flags); + + if (!cmd) { + return; + } /* Skip audio */ readchunk += 24; - spin_lock_irqsave(&wc->reglock, flags); - /* Search for any pending results */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((wc->vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && - (wc->vpm150m->cmdq[x].desc & (__VPM150M_TX)) && - !(wc->vpm150m->cmdq[x].desc & (__VPM150M_FIN))) { - ident = wc->vpm150m->cmdq[x].txident; - if (ident == wc->rxident) { - /* Store result */ - for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { - wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((25 + i), 1, 0)]) << 8; - wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((25 + i), 2, 0)]; - } - if (wc->vpm150m->cmdq[x].desc & __VPM150M_WR) { - /* Go ahead and clear out writes since they need no acknowledgement */ - wc->vpm150m->cmdq[x].desc = 0; - } else - wc->vpm150m->cmdq[x].desc |= __VPM150M_FIN; - break; - } - } + /* Store result */ + cmd->data = (0xff & readchunk[CMD_BYTE(25, 1, 0)]) << 8; + cmd->data |= readchunk[CMD_BYTE(25, 2, 0)]; + if (cmd->desc & __VPM150M_WR) { + /* Writes do not need any acknowledgement */ + list_add_tail(&cmd->node, &vpm->free_cmds); + } else { + cmd->desc |= __VPM150M_FIN; + complete(&cmd->complete); } - spin_unlock_irqrestore(&wc->reglock, flags); +#if 0 + // if (printk_ratelimit()) + printk(KERN_DEBUG "Received txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", cmd->txident, cmd->desc, cmd->address, cmd->data); +#endif } -#endif /* VPM_SUPPORT */ -static inline void cmd_decifer(struct wctdm *wc, volatile unsigned char *readchunk, int card) +static inline void cmd_decipher(struct wctdm *wc, volatile unsigned char *readchunk, int card) { unsigned long flags; unsigned char ident; @@ -700,10 +845,9 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *writechun } cmd_dequeue(wc, writechunk, y, x); } -#ifdef VPM_SUPPORT if (!x) wc->blinktimer++; - if (wc->vpm) { + if (wc->vpm100) { for (y=24;y<28;y++) { if (!x) { cmd_checkisr(wc, y); @@ -711,19 +855,19 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *writechun cmd_dequeue(wc, writechunk, y, x); } #ifdef FANCY_ECHOCAN - if (wc->vpm && wc->blinktimer >= 0xf) { + if (wc->vpm100 && wc->blinktimer >= 0xf) { wc->blinktimer = -1; wc->echocanpos++; } #endif - } else if (wc->vpm150m) { - cmd_dequeue_vpm150m(wc, writechunk, x); + } else if (wc->vpmadt032) { + cmd_dequeue_vpmadt032(wc, writechunk, x); } -#endif + if (x < DAHDI_CHUNKSIZE - 1) { writechunk[EFRAME_SIZE] = wc->ctlreg; writechunk[EFRAME_SIZE + 1] = wc->txident++; -#if 1 + if ((wc->type == 4) && ((wc->ctlreg & 0x10) || (wc->modtype[NUM_CARDS] == MOD_TYPE_NONE))) { writechunk[EFRAME_SIZE + 2] = 0; for (y = 0; y < 4; y++) { @@ -732,7 +876,6 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *writechun } } else writechunk[EFRAME_SIZE + 2] = 0xf; -#endif } writechunk += (EFRAME_SIZE + EFRAME_GAP); } @@ -814,7 +957,6 @@ static inline int wctdm_getreg(struct wctdm *wc, int card, int addr) return ret; } -#ifdef VPM_SUPPORT static inline unsigned char wctdm_vpm_in(struct wctdm *wc, int unit, const unsigned int addr) { return wctdm_getreg(wc, unit + NUM_CARDS, addr); @@ -825,22 +967,24 @@ static inline void wctdm_vpm_out(struct wctdm *wc, int unit, const unsigned int wctdm_setreg(wc, unit + NUM_CARDS, addr, val); } -static inline void cmd_vpm150m_retransmit(struct wctdm *wc) +/* TODO: this should go in the dahdi_voicebus module... */ +static inline void cmd_vpmadt032_retransmit(struct wctdm *wc) { unsigned long flags; - int x; + struct vpmadt032 *vpmadt032 = wc->vpmadt032; + struct vpmadt032_cmd *cmd, *temp; - spin_lock_irqsave(&wc->reglock, flags); - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if (!(wc->vpm150m->cmdq[x].desc & __VPM150M_FIN)) { - //printk(KERN_DEBUG "Retransmit!\n"); - wc->vpm150m->cmdq[x].desc &= ~(__VPM150M_TX); - } - } - spin_unlock_irqrestore(&wc->reglock, flags); + BUG_ON(!vpmadt032); + /* By moving the commands back to the pending list, they will be + * transmitted when room is available */ + spin_lock_irqsave(&vpmadt032->list_lock, flags); + list_for_each_entry_safe(cmd, temp, &vpmadt032->active_cmds, node) { + cmd->desc &= ~(__VPM150M_TX); + list_move_tail(&cmd->node, &vpmadt032->pending_cmds); + } + spin_unlock_irqrestore(&vpmadt032->list_lock, flags); } -#endif static inline void cmd_retransmit(struct wctdm *wc) { @@ -856,8 +1000,8 @@ static inline void cmd_retransmit(struct wctdm *wc) } spin_unlock_irqrestore(&wc->reglock, flags); #ifdef VPM_SUPPORT - if (wc->vpm150m) - cmd_vpm150m_retransmit(wc); + if (wc->vpmadt032) + cmd_vpmadt032_retransmit(wc); #endif } @@ -883,15 +1027,14 @@ static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char *readchunk) wc->chans[y]->readchunk[x] = readchunk[y]; } } - cmd_decifer(wc, readchunk, y); + cmd_decipher(wc, readchunk, y); } -#ifdef VPM_SUPPORT - if (wc->vpm) { + if (wc->vpm100) { for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++) - cmd_decifer(wc, readchunk, y); - } else if (wc->vpm150m) - cmd_decifer_vpm150m(wc, readchunk); -#endif + cmd_decipher(wc, readchunk, y); + } else if (wc->vpmadt032) { + cmd_decipher_vpmadt032(wc, readchunk); + } readchunk += (EFRAME_SIZE + EFRAME_GAP); } @@ -1466,7 +1609,6 @@ static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) } -#ifdef VPM_SUPPORT static inline void wctdm_vpm_check(struct wctdm *wc, int x) { if (wc->cmdq[x].isrshadow[0]) { @@ -1486,19 +1628,18 @@ static inline void wctdm_vpm_check(struct wctdm *wc, int x) } } -#include "adt_lec.c" - -static int wctdm_echocan_with_params(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) +static int wctdm_echocan_with_params(struct dahdi_chan *chan, + struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) { struct wctdm *wc = chan->pvt; - if (wc->vpm) { + if (wc->vpm100) { int channel; int unit; channel = (chan->chanpos - 1); unit = (chan->chanpos - 1) & 0x3; - if (wc->vpm < 2) + if (wc->vpm100 < 2) channel >>= 2; if(debug & DEBUG_ECHOCAN) @@ -1510,27 +1651,13 @@ static int wctdm_echocan_with_params(struct dahdi_chan *chan, struct dahdi_echoc wctdm_vpm_out(wc,unit,channel,0x01); return 0; -#ifdef VPM150M_SUPPORT - } else if (wc->vpm150m) { - struct vpm150m *vpm150m = wc->vpm150m; - unsigned int ret; - int channo = chan->chanpos - 1; - - if ((ret = adt_lec_parse_params(&vpm150m->desiredecstate[channo], ecp, p))) - return ret; - - vpm150m->desiredecstate[channo].tap_length = ecp->tap_length; - - if (memcmp(&vpm150m->curecstate[channo], &vpm150m->desiredecstate[channo], sizeof(vpm150m->curecstate[channo])) - && test_bit(VPM150M_ACTIVE, &vpm150m->control)) - queue_work(vpm150m->wq, &vpm150m->work); - - return 0; -#endif - } else + } else if (wc->vpmadt032) { + return vpmadt032_echocan_with_params(wc->vpmadt032, + chan->chanpos-1, ecp, p); + } else { return -ENODEV; + } } -#endif static inline void wctdm_isr_misc(struct wctdm *wc) { @@ -1581,13 +1708,11 @@ static inline void wctdm_isr_misc(struct wctdm *wc) } } } -#ifdef VPM_SUPPORT - if (wc->vpm > 0) { + if (wc->vpm100 > 0) { for (x=NUM_CARDS;x<NUM_CARDS+NUM_EC;x++) { wctdm_vpm_check(wc, x); } } -#endif } static void handle_receive(void* vbb, void* context) @@ -2598,27 +2723,8 @@ static int wctdm_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long break; #ifdef VPM_SUPPORT case DAHDI_TONEDETECT: - if (get_user(x, (__user int *) data)) - return -EFAULT; - if (!wc->vpm && !wc->vpm150m) - return -ENOSYS; - if ((wc->vpm || wc->vpm150m) && (x && !vpmdtmfsupport)) - return -ENOSYS; - if (x & DAHDI_TONEDETECT_ON) { - set_bit(chan->chanpos - 1, &wc->dtmfmask); - } else { - clear_bit(chan->chanpos - 1, &wc->dtmfmask); - } - if (x & DAHDI_TONEDETECT_MUTE) { - if (wc->vpm150m) { - set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } - } else { - if (wc->vpm150m) { - clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } - } - return 0; + /* Hardware DTMF detection is not supported. */ + return -ENOSYS; #endif case DAHDI_SETPOLARITY: if (get_user(x, (__user int *) data)) @@ -3107,589 +3213,14 @@ static void wctdm_post_initialize(struct wctdm *wc) } } - if (wc->vpm) + if (wc->vpm100) { strncat(wc->span.devicetype, " with VPM100M", sizeof(wc->span.devicetype) - 1); - else if (wc->vpm150m) + } else if (wc->vpmadt032) { strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); -} - -#ifdef VPM_SUPPORT - -#ifdef VPM150M_SUPPORT - -static void vpm150m_set_chanconfig_from_state(struct adt_lec_params * parms, int channum, GpakChannelConfig_t *chanconfig) -{ - chanconfig->PcmInPortA = 3; - chanconfig->PcmInSlotA = channum; - chanconfig->PcmOutPortA = SerialPortNull; - chanconfig->PcmOutSlotA = channum; - chanconfig->PcmInPortB = 2; - chanconfig->PcmInSlotB = channum; - chanconfig->PcmOutPortB = 3; - chanconfig->PcmOutSlotB = channum; - if (vpmdtmfsupport) { - chanconfig->ToneTypesA = DTMF_tone; - chanconfig->MuteToneA = Enabled; - chanconfig->FaxCngDetA = Enabled; - } else { - chanconfig->ToneTypesA = Null_tone; - chanconfig->MuteToneA = Disabled; - chanconfig->FaxCngDetA = Disabled; } - chanconfig->ToneTypesB = Null_tone; - chanconfig->EcanEnableA = Enabled; - chanconfig->EcanEnableB = Disabled; - chanconfig->MuteToneB = Disabled; - chanconfig->FaxCngDetB = Disabled; - - if (alawoverride) - chanconfig->SoftwareCompand = cmpPCMA; - else - chanconfig->SoftwareCompand = cmpPCMU; - - chanconfig->FrameRate = rate2ms; - chanconfig->EcanParametersA.EcanTapLength = 1024; - chanconfig->EcanParametersA.EcanNlpType = parms->nlp_type; - chanconfig->EcanParametersA.EcanAdaptEnable = 1; - chanconfig->EcanParametersA.EcanG165DetEnable = 1; - chanconfig->EcanParametersA.EcanDblTalkThresh = 6; - chanconfig->EcanParametersA.EcanNlpThreshold = parms->nlp_threshold; - chanconfig->EcanParametersA.EcanNlpConv = 0; - chanconfig->EcanParametersA.EcanNlpUnConv = 0; - chanconfig->EcanParametersA.EcanNlpMaxSuppress = parms->nlp_max_suppress; - chanconfig->EcanParametersA.EcanCngThreshold = 43; - chanconfig->EcanParametersA.EcanAdaptLimit = 50; - chanconfig->EcanParametersA.EcanCrossCorrLimit = 15; - chanconfig->EcanParametersA.EcanNumFirSegments = 3; - chanconfig->EcanParametersA.EcanFirSegmentLen = 64; - - chanconfig->EcanParametersB.EcanTapLength = 1024; - chanconfig->EcanParametersB.EcanNlpType = parms->nlp_type; - chanconfig->EcanParametersB.EcanAdaptEnable = 1; - chanconfig->EcanParametersB.EcanG165DetEnable = 1; - chanconfig->EcanParametersB.EcanDblTalkThresh = 6; - chanconfig->EcanParametersB.EcanNlpThreshold = parms->nlp_threshold; - chanconfig->EcanParametersB.EcanNlpConv = 0; - chanconfig->EcanParametersB.EcanNlpUnConv = 0; - chanconfig->EcanParametersB.EcanNlpMaxSuppress = parms->nlp_max_suppress; - chanconfig->EcanParametersB.EcanCngThreshold = 43; - chanconfig->EcanParametersB.EcanAdaptLimit = 50; - chanconfig->EcanParametersB.EcanCrossCorrLimit = 15; - chanconfig->EcanParametersB.EcanNumFirSegments = 3; - chanconfig->EcanParametersB.EcanFirSegmentLen = 64; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work); -#endif - struct wctdm *wc = vpm150m->wc; - int i; - - for (i = 0; i < wc->type; i++) { - int enable = -1; - if (test_bit(i, &vpm150m->desireddtmfmutestate)) { - if (!test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 1; - } - } else { - if (test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 0; - } - } - if (enable > -1) { - unsigned int start = wc->intcount; - GPAK_AlgControlStat_t pstatus; - int res; - - if (enable) { - res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "DTMF mute enable took %d ms\n", wc->intcount - start); - } else { - res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "DTMF mute disable took %d ms\n", wc->intcount - start); - } - if (!res) - change_bit(i, &vpm150m->curdtmfmutestate); - } - } - - if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { - unsigned short channel; - GpakAsyncEventCode_t eventcode; - GpakAsyncEventData_t eventdata; - gpakReadEventFIFOMessageStat_t res; - unsigned int start = wc->intcount; - - do { - res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); - - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "ReadEventFIFOMessage took %d ms\n", wc->intcount - start); - - if (res == RefInvalidEvent || res == RefDspCommFailure) { - printk(KERN_NOTICE "VPM Comm Error\n"); - continue; - } - - if (res == RefNoEventAvail) { - continue; - } - - if (eventcode == EventToneDetect) { - GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; - int duration = eventdata.toneEvent.ToneDuration; - char zaptone = vpm150mtone_to_zaptone(tone); - - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Channel %d: Detected DTMF tone %d of duration %d!!!\n", channel + 1, tone, duration); - - if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { - struct dahdi_chan *chan = wc->chans[channel]; - - if ((tone != EndofMFDigit) && (zaptone != 0)) { - vpm150m->curtone[channel] = tone; - - if (test_bit(channel, &vpm150m->curdtmfmutestate)) { - unsigned long flags; - int y; - - /* Mute the audio data buffers */ - spin_lock_irqsave(&chan->lock, flags); - for (y = 0; y < chan->numbufs; y++) { - if ((chan->inreadbuf > -1) && (chan->readidx[y])) - memset(chan->readbuf[chan->inreadbuf], DAHDI_XLAW(0, chan), chan->readidx[y]); - } - spin_unlock_irqrestore(&chan->lock, flags); - } - if (!test_bit(channel, &wc->dtmfactive)) { - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Queuing DTMFDOWN %c\n", zaptone); - set_bit(channel, &wc->dtmfactive); - dahdi_qevent_lock(chan, (DAHDI_EVENT_DTMFDOWN | zaptone)); - } - } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); - dahdi_qevent_lock(chan, (DAHDI_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); - clear_bit(channel, &wc->dtmfactive); - } - } - } - } while ((res != RefNoEventAvail) && (res != RefInvalidEvent) && (res != RefDspCommFailure)); - } - - for (i = 0; i < wc->type; i++) { - unsigned int start = wc->intcount; - GPAK_AlgControlStat_t pstatus; - int res = 1; - - if ((vpm150m->desiredecstate[i].nlp_type != vpm150m->curecstate[i].nlp_type) - || (vpm150m->desiredecstate[i].nlp_threshold != vpm150m->curecstate[i].nlp_threshold) - || (vpm150m->desiredecstate[i].nlp_max_suppress != vpm150m->curecstate[i].nlp_max_suppress)) { - - GPAK_ChannelConfigStat_t cstatus; - GPAK_TearDownChanStat_t tstatus; - GpakChannelConfig_t chanconfig; - - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", i + 1, vpm150m->desiredecstate[i].nlp_type, - vpm150m->desiredecstate[i].nlp_threshold, vpm150m->desiredecstate[i].nlp_max_suppress); - - vpm150m_set_chanconfig_from_state(&vpm150m->desiredecstate[i], i, &chanconfig); - - if ((res = gpakTearDownChannel(vpm150m->dspid, i, &tstatus))) { - goto vpm_bh_out; - } - - if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { - goto vpm_bh_out; - } - - if (!vpm150m->desiredecstate[i].tap_length) - res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); - - } else if (vpm150m->desiredecstate[i].tap_length != vpm150m->curecstate[i].tap_length) { - if (vpm150m->desiredecstate[i].tap_length) { - res = gpakAlgControl(vpm150m->dspid, i, EnableEcanA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Echocan enable took %d ms\n", wc->intcount - start); - } else { - res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Echocan disable took %d ms\n", wc->intcount - start); - } - } - -vpm_bh_out: - if (!res) - vpm150m->curecstate[i] = vpm150m->desiredecstate[i]; - } - - return; -} - -static int vpm150m_config_hw(struct wctdm *wc) -{ - struct vpm150m *vpm150m = wc->vpm150m; - gpakConfigPortStatus_t configportstatus; - GpakPortConfig_t portconfig; - GPAK_PortConfigStat_t pstatus; - GpakChannelConfig_t chanconfig; - GPAK_ChannelConfigStat_t cstatus; - GPAK_AlgControlStat_t algstatus; - - int res, i; - - memset(&portconfig, 0, sizeof(GpakPortConfig_t)); - - /* First Serial Port config */ - portconfig.SlotsSelect1 = SlotCfgNone; - portconfig.FirstBlockNum1 = 0; - portconfig.FirstSlotMask1 = 0x0000; - portconfig.SecBlockNum1 = 1; - portconfig.SecSlotMask1 = 0x0000; - portconfig.SerialWordSize1 = SerWordSize8; - portconfig.CompandingMode1 = cmpNone; - portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.TxClockPolarity1 = SerClockActHigh; - portconfig.RxClockPolarity1 = SerClockActHigh; - portconfig.TxDataDelay1 = DataDelay0; - portconfig.RxDataDelay1 = DataDelay0; - portconfig.DxDelay1 = Disabled; - portconfig.ThirdSlotMask1 = 0x0000; - portconfig.FouthSlotMask1 = 0x0000; - portconfig.FifthSlotMask1 = 0x0000; - portconfig.SixthSlotMask1 = 0x0000; - portconfig.SevenSlotMask1 = 0x0000; - portconfig.EightSlotMask1 = 0x0000; - - /* Second Serial Port config */ - portconfig.SlotsSelect2 = SlotCfg2Groups; - portconfig.FirstBlockNum2 = 0; - portconfig.FirstSlotMask2 = 0xffff; - portconfig.SecBlockNum2 = 1; - portconfig.SecSlotMask2 = 0xffff; - portconfig.SerialWordSize2 = SerWordSize8; - portconfig.CompandingMode2 = cmpNone; - portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.TxClockPolarity2 = SerClockActHigh; - portconfig.RxClockPolarity2 = SerClockActLow; - portconfig.TxDataDelay2 = DataDelay0; - portconfig.RxDataDelay2 = DataDelay0; - portconfig.DxDelay2 = Disabled; - portconfig.ThirdSlotMask2 = 0x0000; - portconfig.FouthSlotMask2 = 0x0000; - portconfig.FifthSlotMask2 = 0x0000; - portconfig.SixthSlotMask2 = 0x0000; - portconfig.SevenSlotMask2 = 0x0000; - portconfig.EightSlotMask2 = 0x0000; - - /* Third Serial Port Config */ - portconfig.SlotsSelect3 = SlotCfg2Groups; - portconfig.FirstBlockNum3 = 0; - portconfig.FirstSlotMask3 = 0xffff; - portconfig.SecBlockNum3 = 1; - portconfig.SecSlotMask3 = 0xffff; - portconfig.SerialWordSize3 = SerWordSize8; - portconfig.CompandingMode3 = cmpNone; - portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.TxClockPolarity3 = SerClockActHigh; - portconfig.RxClockPolarity3 = SerClockActLow; - portconfig.TxDataDelay3 = DataDelay0; - portconfig.RxDataDelay3 = DataDelay0; - portconfig.DxDelay3 = Disabled; - portconfig.ThirdSlotMask3 = 0x0000; - portconfig.FouthSlotMask3 = 0x0000; - portconfig.FifthSlotMask3 = 0x0000; - portconfig.SixthSlotMask3 = 0x0000; - portconfig.SevenSlotMask3 = 0x0000; - portconfig.EightSlotMask3 = 0x0000; - - if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { - printk(KERN_NOTICE "Configuration of ports failed (%d)!\n", configportstatus); - return -1; - } else { - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Configured McBSP ports successfully\n"); - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); - return -1; - } - - for (i = 0; i < wc->type; i++) { - vpm150m->curecstate[i].tap_length = 0; - vpm150m->curecstate[i].nlp_type = vpmnlptype; - vpm150m->curecstate[i].nlp_threshold = vpmnlpthresh; - vpm150m->curecstate[i].nlp_max_suppress = vpmnlpmaxsupp; - - vpm150m->desiredecstate[i].tap_length = 0; - vpm150m->desiredecstate[i].nlp_type = vpmnlptype; - vpm150m->desiredecstate[i].nlp_threshold = vpmnlpthresh; - vpm150m->desiredecstate[i].nlp_max_suppress = vpmnlpmaxsupp; - - vpm150m_set_chanconfig_from_state(&vpm150m->curecstate[i], i, &chanconfig); - - if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { - printk(KERN_NOTICE "Unable to configure channel (%d)", res); - if (res == 1) { - printk(", reason %d", cstatus); - } - printk("\n"); - - return -1; - } - - if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { - printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - - if (vpmdtmfsupport) { - if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { - printk(KERN_NOTICE "Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - } - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); - return -1; - } - - vpm150m->wq = create_singlethread_workqueue("wctdm24xxp"); - vpm150m->wc = wc; - - if (!vpm150m->wq) { - printk(KERN_NOTICE "Unable to create work queue!\n"); - return -1; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&vpm150m->work, vpm150m_bh, vpm150m); -#else - INIT_WORK(&vpm150m->work, vpm150m_bh); -#endif - - /* Turn on DTMF detection */ - if (vpmdtmfsupport) - set_bit(VPM150M_DTMFDETECT, &vpm150m->control); - - set_bit(VPM150M_ACTIVE, &vpm150m->control); - - return 0; -} -#endif /* VPM150M_SUPPORT */ - -enum vpmadt032_init_result { - VPMADT032_SUCCESS, - VPMADT032_NOT_FOUND, - VPMADT032_FAILED, - VPMADT032_DISABLED, -}; - -static enum vpmadt032_init_result wctdm_vpm150m_init(struct wctdm *wc) -{ - unsigned short i; - struct vpm150m *vpm150m; - unsigned short reg; - unsigned long flags; - enum vpmadt032_init_result res = VPMADT032_FAILED; - -#ifdef VPM150M_SUPPORT - struct wctdm_firmware fw; - struct firmware embedded_firmware; - const struct firmware *firmware = &embedded_firmware; -#if !defined(HOTPLUG_FIRMWARE) - extern void _binary_dahdi_fw_vpmadt032_bin_size; - extern u8 _binary_dahdi_fw_vpmadt032_bin_start[]; -#else - static const char vpmadt032_firmware[] = "dahdi-fw-vpmadt032.bin"; - struct pci_dev *pdev = voicebus_get_pci_dev(wc->vb); -#endif - gpakDownloadStatus_t downloadstatus; - gpakPingDspStat_t pingstatus; -#endif - - if (!vpmsupport) { - printk(KERN_NOTICE "VPM: Support Disabled\n"); - wc->vpm150m = NULL; - return VPMADT032_DISABLED; - } - - vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); - - if (!vpm150m) { - printk(KERN_NOTICE "Unable to allocate VPM150M!\n"); - return VPMADT032_FAILED; - } - - memset(vpm150m, 0, sizeof(struct vpm150m)); - - /* Init our vpm150m struct */ - sema_init(&vpm150m->sem, 1); - vpm150m->curpage = 0x80; - - for (i = 0; i < WC_MAX_IFACES; i++) { - if (ifaces[i] == wc) - vpm150m->dspid = i; - } - - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); - - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = vpm150m; - spin_unlock_irqrestore(&wc->reglock, flags); - - for (i = 0; i < 10; i++) - schluffen(&wc->regq); - - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "VPMADT032 Testing page access: "); - for (i = 0; i < 0xf; i++) { - int x; - for (x = 0; x < 3; x++) { - wctdm_vpm150m_setpage(wc, i); - reg = wctdm_vpm150m_getpage(wc); - if (reg != i) { - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg); - res = VPMADT032_NOT_FOUND; - goto failed_exit; - } - } - } - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Passed\n"); - - /* Set us up to page 0 */ - wctdm_vpm150m_setpage(wc, 0); - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "VPMADT032 now doing address test: "); - for (i = 0; i < 16; i++) { - int x; - for (x = 0; x < 2; x++) { - wctdm_vpm150m_setreg(wc, 1, 0x1000, &i); - wctdm_vpm150m_getreg(wc, 1, 0x1000, ®); - if (reg != i) { - printk("VPMADT032 Failed address test\n"); - goto failed_exit; - } - - } - } - if (debug & DEBUG_ECHOCAN) - printk("Passed\n"); - -#ifndef VPM150M_SUPPORT - printk(KERN_NOTICE "Found VPMADT032 module but it is not able to function in anything less than a version 2.6 kernel\n"); - printk(KERN_NOTICE "Please update your kernel to a 2.6 or later kernel to enable it\n"); - goto failed_exit; -#else - -#if 0 - /* Load the firmware */ - set_bit(VPM150M_SPIRESET, &vpm150m->control); - - /* Wait for it to boot */ - msleep(7000); - - pingstatus = gpakPingDsp(vpm150m->dspid, &version); - - if (pingstatus || (version != 0x106)) { -#endif -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, vpmadt032_firmware, &pdev->dev) != 0) || - !firmware) { - printk(KERN_NOTICE "VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); - goto failed_exit; - } -#else - embedded_firmware.data = _binary_dahdi_fw_vpmadt032_bin_start; - embedded_firmware.size = (size_t) &_binary_dahdi_fw_vpmadt032_bin_size; -#endif - fw.fw = firmware; - fw.offset = 0; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - - while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) - schluffen(&wc->regq); - - printk(KERN_INFO "VPMADT032 Loading firmware... "); - downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); - - if (firmware != &embedded_firmware) - release_firmware(firmware); - - if (downloadstatus != 0) { - printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); - goto failed_exit; - } else { - printk("Success\n"); - } - - set_bit(VPM150M_SWRESET, &vpm150m->control); - - while (test_bit(VPM150M_SWRESET, &vpm150m->control)) - schluffen(&wc->regq); - -#if 0 - } -#endif - - pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); - - if (!pingstatus) { - if (debug & DEBUG_ECHOCAN) - printk(KERN_DEBUG "Version of DSP is %x\n", vpm150m->version); - } else { - printk(KERN_NOTICE "VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); - goto failed_exit; - } - - if (vpm150m_config_hw(wc)) { - goto failed_exit; - } - - return VPMADT032_SUCCESS; -#endif /* VPM150M_SUPPORT */ - -failed_exit: - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(vpm150m); - - return res; -} - -static void wctdm_vpm_set_dtmf_threshold(struct wctdm *wc, unsigned int threshold) -{ - unsigned int x; - - for (x = 0; x < 4; x++) { - wctdm_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF); - wctdm_vpm_out(wc, x, 0xC5, (threshold & 0xFF)); - } - printk(KERN_INFO "VPM: DTMF threshold set to %d\n", threshold); -} - -static void wctdm_vpm_init(struct wctdm *wc) +static int wctdm_vpm_init(struct wctdm *wc) { unsigned char reg; unsigned int mask; @@ -3697,20 +3228,14 @@ static void wctdm_vpm_init(struct wctdm *wc) unsigned char vpmver=0; unsigned int i, x, y; - if (!vpmsupport) { - printk(KERN_INFO "VPM: Support Disabled\n"); - wc->vpm = 0; - return; - } - for (x=0;x<NUM_EC;x++) { ver = wctdm_vpm_in(wc, x, 0x1a0); /* revision */ if (debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "VPM100: Chip %d: ver %02x\n", x, ver); if (ver != 0x33) { printk(KERN_DEBUG "VPM100: %s\n", x ? "Inoperable" : "Not Present"); - wc->vpm = 0; - return; + wc->vpm100 = 0; + return -ENODEV; } if (!x) { @@ -3801,13 +3326,13 @@ static void wctdm_vpm_init(struct wctdm *wc) wctdm_vpm_out(wc, x, i, 0xff); } - /* set DTMF detection threshold */ - wctdm_vpm_set_dtmf_threshold(wc, dtmfthreshold); - if (vpmver == 0x01) - wc->vpm = 2; - else - wc->vpm = 1; + /* TODO: What do the different values for vpm100 mean? */ + if (vpmver == 0x01) { + wc->vpm100 = 2; + } else { + wc->vpm100 = 1; + } printk(KERN_INFO "Enabling VPM100 gain adjustments on any FXO ports found\n"); for (i = 0; i < wc->type; i++) { @@ -3822,9 +3347,79 @@ static void wctdm_vpm_init(struct wctdm *wc) } } + return 0; } -#endif +static void get_default_portconfig(GpakPortConfig_t *portconfig) +{ + memset(portconfig, 0, sizeof(GpakPortConfig_t)); + + /* First Serial Port config */ + portconfig->SlotsSelect1 = SlotCfgNone; + portconfig->FirstBlockNum1 = 0; + portconfig->FirstSlotMask1 = 0x0000; + portconfig->SecBlockNum1 = 1; + portconfig->SecSlotMask1 = 0x0000; + portconfig->SerialWordSize1 = SerWordSize8; + portconfig->CompandingMode1 = cmpNone; + portconfig->TxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig->RxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig->TxClockPolarity1 = SerClockActHigh; + portconfig->RxClockPolarity1 = SerClockActHigh; + portconfig->TxDataDelay1 = DataDelay0; + portconfig->RxDataDelay1 = DataDelay0; + portconfig->DxDelay1 = Disabled; + portconfig->ThirdSlotMask1 = 0x0000; + portconfig->FouthSlotMask1 = 0x0000; + portconfig->FifthSlotMask1 = 0x0000; + portconfig->SixthSlotMask1 = 0x0000; + portconfig->SevenSlotMask1 = 0x0000; + portconfig->EightSlotMask1 = 0x0000; + + /* Second Serial Port config */ + portconfig->SlotsSelect2 = SlotCfg2Groups; + portconfig->FirstBlockNum2 = 0; + portconfig->FirstSlotMask2 = 0xffff; + portconfig->SecBlockNum2 = 1; + portconfig->SecSlotMask2 = 0xffff; + portconfig->SerialWordSize2 = SerWordSize8; + portconfig->CompandingMode2 = cmpNone; + portconfig->TxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig->RxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig->TxClockPolarity2 = SerClockActHigh; + portconfig->RxClockPolarity2 = SerClockActLow; + portconfig->TxDataDelay2 = DataDelay0; + portconfig->RxDataDelay2 = DataDelay0; + portconfig->DxDelay2 = Disabled; + portconfig->ThirdSlotMask2 = 0x0000; + portconfig->FouthSlotMask2 = 0x0000; + portconfig->FifthSlotMask2 = 0x0000; + portconfig->SixthSlotMask2 = 0x0000; + portconfig->SevenSlotMask2 = 0x0000; + portconfig->EightSlotMask2 = 0x0000; + + /* Third Serial Port Config */ + portconfig->SlotsSelect3 = SlotCfg2Groups; + portconfig->FirstBlockNum3 = 0; + portconfig->FirstSlotMask3 = 0xffff; + portconfig->SecBlockNum3 = 1; + portconfig->SecSlotMask3 = 0xffff; + portconfig->SerialWordSize3 = SerWordSize8; + portconfig->CompandingMode3 = cmpNone; + portconfig->TxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig->RxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig->TxClockPolarity3 = SerClockActHigh; + portconfig->RxClockPolarity3 = SerClockActLow; + portconfig->TxDataDelay3 = DataDelay0; + portconfig->RxDataDelay3 = DataDelay0; + portconfig->DxDelay3 = Disabled; + portconfig->ThirdSlotMask3 = 0x0000; + portconfig->FouthSlotMask3 = 0x0000; + portconfig->FifthSlotMask3 = 0x0000; + portconfig->SixthSlotMask3 = 0x0000; + portconfig->SevenSlotMask3 = 0x0000; + portconfig->EightSlotMask3 = 0x0000; +} static int wctdm_locate_modules(struct wctdm *wc) { @@ -3838,11 +3433,9 @@ static int wctdm_locate_modules(struct wctdm *wc) wc->span.irqmisses = 0; for (x=0;x<wc->cards;x++) wc->modtype[x] = MOD_TYPE_FXSINIT; -#ifdef VPM_SUPPORT - wc->vpm = -1; + wc->vpm100 = -1; for (x = wc->cards; x < wc->cards+NUM_EC; x++) wc->modtype[x] = MOD_TYPE_VPM; -#endif spin_unlock_irqrestore(&wc->reglock, flags); /* Wait just a bit */ for (x=0;x<10;x++) @@ -3926,40 +3519,61 @@ retry: } } } -#ifdef VPM_SUPPORT - wctdm_vpm_init(wc); - if (wc->vpm) { - printk(KERN_INFO "VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm - 1); + + if (!vpmsupport) { + printk(KERN_NOTICE "VPM: Support Disabled\n"); + } else if (!wctdm_vpm_init(wc)) { + printk(KERN_INFO "VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm100 - 1); wc->ctlreg |= 0x10; } else { - enum vpmadt032_init_result res; + int res; + struct vpmadt032_options options; + GpakPortConfig_t portconfig; + spin_lock_irqsave(&wc->reglock, flags); for (x = NUM_CARDS; x < NUM_CARDS + NUM_EC; x++) wc->modtype[x] = MOD_TYPE_NONE; spin_unlock_irqrestore(&wc->reglock, flags); - res = wctdm_vpm150m_init(wc); + + options.debug = debug; + options.vpmnlptype = vpmnlptype; + options.vpmnlpthresh = vpmnlpthresh; + options.vpmnlpmaxsupp = vpmnlpmaxsupp; + + if (!(wc->vpmadt032=vpmadt032_alloc(&options))) { + return -ENOMEM; + } + wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state; + wc->vpmadt032->context = wc; + wc->vpmadt032->span = &wc->span; + get_default_portconfig(&portconfig); + res = vpmadt032_init(wc->vpmadt032, wc->vb); /* In case there was an error while we were loading the VPM module. */ if (voicebus_current_latency(wc->vb) > startinglatency) { + vpmadt032_free(wc->vpmadt032); + wc->vpmadt032 = NULL; return -EAGAIN; } - switch (res) { - case VPMADT032_SUCCESS: - printk(KERN_INFO "VPMADT032: Present and operational (Firmware version %x)\n", wc->vpm150m->version); - wc->ctlreg |= 0x10; - break; - case VPMADT032_DISABLED: - case VPMADT032_NOT_FOUND: - /* nothing */ - break; - default: - return -EIO; + if (res) { + vpmadt032_free(wc->vpmadt032); + wc->vpmadt032 = NULL; + return res; + } + + /* Now we need to configure the VPMADT032 module for this + * particular board. */ + res = config_vpmadt032(wc->vpmadt032); + if (res) { + vpmadt032_free(wc->vpmadt032); + wc->vpmadt032 = NULL; + return res; } + + printk(KERN_INFO "VPMADT032: Present and operational (Firmware version %x)\n", wc->vpmadt032->version); + /* TODO what is 0x10 in this context? */ + wc->ctlreg |= 0x10; } -#endif - /* In case there was an error while we were loading the VPM module. */ - if (voicebus_current_latency(wc->vb) > startinglatency) { - return -EAGAIN; - } + return 0; } @@ -4112,40 +3726,30 @@ static void wctdm_release(struct wctdm *wc) static void __devexit wctdm_remove_one(struct pci_dev *pdev) { struct wctdm *wc = pci_get_drvdata(pdev); - -#ifdef VPM150M_SUPPORT - unsigned long flags; - struct vpm150m *vpm150m = wc->vpm150m; -#endif + struct vpmadt032 *vpm = wc->vpmadt032; if (wc) { - -#ifdef VPM150M_SUPPORT - if (vpm150m) { - clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); - clear_bit(VPM150M_ACTIVE, &vpm150m->control); - flush_workqueue(vpm150m->wq); - destroy_workqueue(vpm150m->wq); + if (vpm) { + clear_bit(VPM150M_DTMFDETECT, &vpm->control); + clear_bit(VPM150M_ACTIVE, &vpm->control); + flush_scheduled_work(); } -#endif + voicebus_stop(wc->vb); -#ifdef VPM150M_SUPPORT - if (vpm150m) { - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - vpm150m->wc = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(wc->vpm150m); + if (vpm) { + vpmadt032_free(wc->vpmadt032); + wc->vpmadt032 = NULL; } -#endif + /* Release span, possibly delayed */ if (!wc->usecount) { wctdm_release(wc); printk(KERN_INFO "Freed a Wildcard\n"); } - else + else { wc->dead = 1; + } } } @@ -4245,8 +3849,6 @@ module_param(neonmwi_envelope, int, 0600); module_param(neonmwi_offlimit, int, 0600); #ifdef VPM_SUPPORT module_param(vpmsupport, int, 0600); -module_param(vpmdtmfsupport, int, 0600); -module_param(dtmfthreshold, int, 0600); module_param(vpmnlptype, int, 0600); module_param(vpmnlpthresh, int, 0600); module_param(vpmnlpmaxsupp, int, 0600); diff --git a/drivers/dahdi/wctdm24xxp/voicebus.c b/drivers/dahdi/wctdm24xxp/voicebus.c deleted file mode 120000 index 6653619..0000000 --- a/drivers/dahdi/wctdm24xxp/voicebus.c +++ /dev/null @@ -1 +0,0 @@ -../voicebus.c
\ No newline at end of file diff --git a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h index f8da786..4bb90b7 100644 --- a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h +++ b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h @@ -4,7 +4,7 @@ * Written by Mark Spencer <markster@digium.com> * Support for TDM800P and VPM150M by Matthew Fredrickson <creslin@digium.com> * - * Copyright (C) 2005, 2006, Digium, Inc. + * Copyright (C) 2005-2009 Digium, Inc. * * All rights reserved. * @@ -28,7 +28,6 @@ #include <dahdi/kernel.h> -#include "../voicebus.h" #include <linux/version.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include <linux/semaphore.h> @@ -36,6 +35,8 @@ #include <asm/semaphore.h> #endif +#include "voicebus/voicebus.h" + #define NUM_FXO_REGS 60 #define WC_MAX_IFACES 128 @@ -76,8 +77,6 @@ #define SDI_DREAD (0x00040000) #define SDI_DIN (0x00080000) -#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) - #define __CMD_RD (1 << 20) /* Read Operation */ #define __CMD_WR (1 << 21) /* Write Operation */ #define __CMD_FIN (1 << 22) /* Has finished receive */ @@ -103,26 +102,11 @@ #define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS) -#define __VPM150M_RWPAGE (1 << 4) -#define __VPM150M_RD (1 << 3) -#define __VPM150M_WR (1 << 2) -#define __VPM150M_FIN (1 << 1) -#define __VPM150M_TX (1 << 0) #define VPM150M_HPI_CONTROL 0x00 #define VPM150M_HPI_ADDRESS 0x02 #define VPM150M_HPI_DATA 0x03 -#define VPM150M_MAX_COMMANDS 8 - -/* Some Bit ops for different operations */ -#define VPM150M_SPIRESET 0 -#define VPM150M_HPIRESET 1 -#define VPM150M_SWRESET 2 -#define VPM150M_DTMFDETECT 3 -#define VPM150M_ACTIVE 4 - -#define VPM150M_MAX_DATA 1 #define VPM_SUPPORT @@ -138,36 +122,8 @@ #endif #ifdef VPM150M_SUPPORT -#include "adt_lec.h" -#endif - -struct vpm150m_cmd { - unsigned int addr; - unsigned char datalen; - unsigned char desc; - unsigned char txident; - unsigned short data[VPM150M_MAX_DATA]; -}; - -struct vpm150m { -#ifdef VPM150M_SUPPORT - struct workqueue_struct *wq; - struct work_struct work; +#include "voicebus/GpakCust.h" #endif - struct wctdm *wc; - - int dspid; - struct semaphore sem; - unsigned long control; - unsigned char curpage; - unsigned short version; - struct adt_lec_params curecstate[24]; - struct adt_lec_params desiredecstate[24]; - unsigned long curdtmfmutestate; - unsigned long desireddtmfmutestate; - struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; - unsigned char curtone[24]; -}; struct calregs { unsigned char vals[NUM_CAL_REGS]; @@ -261,22 +217,22 @@ struct wctdm { /* Set hook */ int sethook[NUM_CARDS + NUM_EC]; int dacssrc[NUM_CARDS]; + /* Type is the maximum number of FXO/FXS ports supported */ int type; -#ifdef VPM_SUPPORT - int vpm; + int vpm100; + unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; short dtmfenergy[NUM_CARDS]; short dtmfdigit[NUM_CARDS]; - struct vpm150m *vpm150m; + struct vpmadt032 *vpmadt032; #ifdef FANCY_ECHOCAN int echocanpos; int blinktimer; #endif -#endif struct voicebus *vb; struct dahdi_chan *chans[NUM_CARDS]; int initialized; diff --git a/drivers/dahdi/wcte12xp/GpakApi.h b/drivers/dahdi/wcte12xp/GpakApi.h deleted file mode 100644 index ebd440e..0000000 --- a/drivers/dahdi/wcte12xp/GpakApi.h +++ /dev/null @@ -1,636 +0,0 @@ -/* - * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. - * - * File Name: GpakApi.h - * - * Description: - * This file contains the function prototypes and data types for the user - * API functions that communicate with DSPs executing G.PAK software. The - * file is used by application software in the host processor connected to - * C55X G.PAK DSPs via a Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#ifndef _GPAKAPI_H /* prevent multiple inclusion */ -#define _GPAKAPI_H -#include "GpakErrs.h" -#include "gpakenum.h" - -// Bit masks to select which algorithm's parameters to update: Or-together the -// desired masks into the UpdateBits function parameter. -#define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq -#define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params -#define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params - -#define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words - -/* Definition of an Asynchronous Event Data Structure */ -typedef union -{ - struct - { - GpakToneCodes_t ToneCode; // detected tone code - unsigned short int ToneDuration; // tone duration - GpakTdmDirection Direction; // detected on A r B side - short int DebugToneStatus;// reserved for debug info - } toneEvent; - -} GpakAsyncEventData_t; - -/* Definition of an Echo Canceller Parameters information structure. */ -typedef struct -{ - short int EcanTapLength; // Echo Can Num Taps (tail length) - short int EcanNlpType; // Echo Can NLP Type - short int EcanAdaptEnable; // Echo Can Adapt Enable flag - short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag - short int EcanDblTalkThresh; // Echo Can Double Talk threshold - short int EcanNlpThreshold; // Echo Can NLP threshold - short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged - short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet - short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode - short int EcanCngThreshold; // Echo Can CNG Noise threshold - short int EcanAdaptLimit; // Echo Can Max Adapts per frame - short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit - short int EcanNumFirSegments; // Echo Can Num FIR Segments - short int EcanFirSegmentLen; // Echo Can FIR Segment Length -} GpakEcanParms_t; - -/* Definition of a Channel Configuration information structure. */ -typedef struct -{ - GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id - unsigned short int PcmInSlotA; // A side PCM Input Time Slot - GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id - unsigned short int PcmOutSlotA; // A side PCM Output Time Slot - GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id - unsigned short int PcmInSlotB; // B side PCM Input Time Slot - GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id - unsigned short int PcmOutSlotB; // B side PCM Output Time Slot - GpakToneTypes ToneTypesA; // A side Tone Detect Types - GpakToneTypes ToneTypesB; // B side Tone Detect Types - GpakActivation EcanEnableA; // Echo Cancel A Enabled - GpakActivation EcanEnableB; // Echo Cancel B Enabled - GpakEcanParms_t EcanParametersA; // Echo Cancel parameters - GpakEcanParms_t EcanParametersB; // Echo Cancel parameters - GpakCompandModes SoftwareCompand; // software companding - GpakRate_t FrameRate; // Gpak Frame Rate - GpakActivation MuteToneA; // A side mute DTMF Enabled - GpakActivation MuteToneB; // B side mute DTMF Enabled - GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled - GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled - -} GpakChannelConfig_t; - - -/* Definition of a Serial Port Configuration Structure */ -typedef struct -{ - GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection - unsigned short int FirstBlockNum1; // port 1 first group Block Number - unsigned short int FirstSlotMask1; // port 1 first group Slot Mask - unsigned short int SecBlockNum1; // port 1 second group Block Number - unsigned short int SecSlotMask1; // port 1 second group Slot Mask - - GpakSerWordSize_t SerialWordSize1; // port 1 serial word size - GpakCompandModes CompandingMode1; // port 1 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay - GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay - GpakActivation DxDelay1; // port 1 DX Delay - - unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask - unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask - unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask - unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask - unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask - unsigned short int EightSlotMask1; // port 1 8th group Slot Mask - - - GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection - unsigned short int FirstBlockNum2; // port 2 first group Block Number - unsigned short int FirstSlotMask2; // port 2 first group Slot Mask - unsigned short int SecBlockNum2; // port 2 second group Block Number - unsigned short int SecSlotMask2; // port 2 second group Slot Mask - GpakSerWordSize_t SerialWordSize2; // port 2 serial word size - GpakCompandModes CompandingMode2; // port 2 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay - GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay - GpakActivation DxDelay2; // port 2 DX Delay - - unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask - unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask - unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask - unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask - unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask - unsigned short int EightSlotMask2; // port 2 8th group Slot Mask - - GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection - unsigned short int FirstBlockNum3; // port 3 first group Block Number - unsigned short int FirstSlotMask3; // port 3 first group Slot Mask - unsigned short int SecBlockNum3; // port 3 second group Block Number - unsigned short int SecSlotMask3; // port 3 second group Slot Mask - GpakSerWordSize_t SerialWordSize3; // port 3 serial word size - GpakCompandModes CompandingMode3; // port 3 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay - GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay - GpakActivation DxDelay3; // port 3 DX Delay - - unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask - unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask - unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask - unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask - unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask - unsigned short int EightSlotMask3; // port 3 8th group Slot Mask - -} GpakPortConfig_t; - -/* Definition of a Tone Generation Parameter Structure */ -/* -typedef struct -{ - GpakToneGenType_t ToneType; // Tone Type - unsigned short int Frequency[4]; // Frequency (Hz) - short int Level[4]; // Frequency's Level (1 dBm) - unsigned short int OnTime[4]; // On Times (msecs) - unsigned short int OffTime[4]; // Off Times (msecs) -} GpakToneGenParms_t; -*/ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakConfigureChannel return status. */ -typedef enum -{ - CcsSuccess = 0, /* Channel Configured successfully */ - CcsParmError = 1, /* Channel Config Parameter error */ - CcsInvalidChannel = 2, /* invalid channel */ - CcsInvalidDsp = 3, /* invalid DSP */ - CcsDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakConfigChanStatus_t; - -/* - * gpakConfigureChannel - Configure a DSP's Channel. - * - * FUNCTION - * This function configures a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakConfigChanStatus_t gpakConfigureChannel( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakChanType ChannelType, // channel type - GpakChannelConfig_t *pChanConfig, // pointer to channel config info - GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakTearDownChannel return status. */ -typedef enum -{ - TdsSuccess = 0, /* Channel Tear Down successful */ - TdsError = 1, /* Channel Tear Down error */ - TdsInvalidChannel = 2, /* invalid channel */ - TdsInvalidDsp = 3, /* invalid DSP */ - TdsDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakTearDownStatus_t; - -/* - * gpakTearDownChannel - Tear Down a DSP's Channel. - * - * FUNCTION - * This function tears down a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ - -extern gpakTearDownStatus_t gpakTearDownChannel( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakAlgControl return status. */ -typedef enum -{ - AcSuccess = 0, /* control successful */ - AcInvalidChannel = 1, /* invalid channel identifier */ - AcInvalidDsp = 2, /* invalid DSP */ - AcParmError = 3, /* invalid control parameter */ - AcDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakAlgControlStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. - * - * FUNCTION - * This function controls an Algorithm - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakAlgControlStat_t gpakAlgControl( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakAlgCtrl_t ControlCode, // algorithm control code - GPAK_AlgControlStat_t *pStatus // pointer to return status - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakConfigurePorts return status. */ -typedef enum -{ - CpsSuccess = 0, /* Serial Ports configured successfully */ - CpsParmError = 1, /* Configure Ports Parameter error */ - CpsInvalidDsp = 2, /* invalid DSP */ - CpsDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakConfigPortStatus_t; - -/* - * gpakConfigurePorts - Configure a DSP's serial ports. - * - * FUNCTION - * This function configures a DSP's serial ports. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakConfigPortStatus_t gpakConfigurePorts( - unsigned short int DspId, // DSP identifier - GpakPortConfig_t *pPortConfig, // pointer to Port Config info - GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakDownloadDsp return status. */ -typedef enum -{ - GdlSuccess = 0, /* DSP download successful */ - GdlFileReadError = 1, /* error reading Download file */ - GdlInvalidFile = 2, /* invalid Download file content */ - GdlInvalidDsp = 3 /* invalid DSP */ -} gpakDownloadStatus_t; - -/* - * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. - * - * FUNCTION - * This function reads a DSP's Program and Data memory image from the - * specified file and writes the image to the DSP's memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakDownloadStatus_t gpakDownloadDsp( - unsigned short int DspId, // DSP identifier - GPAK_FILE_ID FileId // G.PAK download file identifier - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakReadEventFIFOMessage return status */ -typedef enum -{ - RefEventAvail = 0, /* an event was successfully read from the fifo */ - RefNoEventAvail = 1, /* no event was in the fifo */ - RefInvalidDsp = 2, /* invalid DSP identifier */ - RefInvalidEvent = 3, /* invalid event */ - RefDspCommFailure = 4 /* error communicating with DSP */ -} gpakReadEventFIFOMessageStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo - * - * FUNCTION - * This function reads a single event from the event fifo if one is available - * - * RETURNS - * Status code indicating success or a specific error. - * - * Note: This function should be called in a loop until the return status - * indicates that the fifo is empty. - */ -extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( - unsigned short int DspId, // DSP identifier - unsigned short int *pChannelId, // pointer to channel identifier - GpakAsyncEventCode_t *pEventCode, // pointer to Event Code - GpakAsyncEventData_t *pEventData // pointer to Event Data Struct - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakPingDsp return status values */ -typedef enum -{ - PngSuccess = 0, /* DSP responded successfully */ - PngInvalidDsp = 1, /* invalid DSP identifier */ - PngDspCommFailure = 2 /* error communicating with DSP */ -} gpakPingDspStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive - * - * FUNCTION - * This function checks if the DSP is still communicating with the host - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakPingDspStat_t gpakPingDsp( - unsigned short int DspId, // DSP identifier - unsigned short int *pDspSwVersion // DSP software version - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakSerialTxFixedValue return status values */ -typedef enum -{ - TfvSuccess = 0, /* operation successful */ - TfvInvalidChannel = 1, /* invalid channel identifier */ - TfvInvalidDsp = 2, /* invalid DSP identifier */ - TfvDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakSerialTxFixedValueStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot - * - * FUNCTION - * This function controls transmission of a fixed value out onto a serial - * port's timeslot. - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id - unsigned short int PcmOutSlot, // PCM Output Time Slot - unsigned short int Value, // 16-bit value - GpakActivation State // activation state - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakControlTdmLoopBack return status values */ -typedef enum -{ - ClbSuccess = 0, /* operation successful */ - ClbSerPortInactive = 1, /* serial port is inactive */ - ClbInvalidDsp = 2, /* invalid DSP identifier */ - ClbDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakControlTdmLoopBackStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state - * - * FUNCTION - * This function enables/disables the tdm input to output looback mode on a - * serial port - * - * RETURNS - * Status code indicating success or a specific error. - */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( - unsigned short int DspId, // DSP identifier - GpakSerialPort_t SerialPort, // Serial Port Id - GpakActivation LoopBackState // Loopback State - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakReadCpuUsage return status values */ -typedef enum -{ - RcuSuccess = 0, /* operation successful */ - RcuInvalidDsp = 1, /* invalid DSP identifier */ - RcuDspCommFailure = 2 /* communication failure */ -} gpakReadCpuUsageStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - read the cpu usage statistics - * - * FUNCTION - * This function reads cpu utilization from the DSP. - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakReadCpuUsageStat_t gpakReadCpuUsage( - unsigned short int DspId, // DSP identifier - unsigned short int *pPeakUsage, // pointer to peak usage variable - unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakResetCpuUsageStats return status values */ -typedef enum -{ - RstcSuccess = 0, /* operation successful */ - RstcInvalidDsp = 1, /* invalid DSP identifier */ - RstcDspCommFailure = 2 /* communication failure */ -} gpakResetCpuUsageStat_t; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics - * - * FUNCTION - * This function resets the cpu utilization statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( - unsigned short int DspId // DSP identifier - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakReadFramingStats return status values */ -typedef enum -{ - RfsSuccess = 0, /* operation successful */ - RfsInvalidDsp = 1, /* invalid DSP identifier */ - RfsDspCommFailure = 2 /* communication failure */ -} gpakReadFramingStatsStatus_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats - * - * FUNCTION - * This function reads a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakReadFramingStatsStatus_t gpakReadFramingStats( - unsigned short int DspId, // DSP identifier - unsigned short int *pFramingError1Count, // port 1 Framing error count - unsigned short int *pFramingError2Count, // port 2 Framing error count - unsigned short int *pFramingError3Count, // port 3 Framing error count - unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count - unsigned short int *pDmaSlipStatsBuffer // DMA slips count - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakResetFramingStats return values */ -typedef enum -{ - RstfSuccess = 0, /* operation successful */ - RstfInvalidDsp = 1, /* invalid DSP identifier */ - RstfDspCommFailure = 2 /* communication failure */ -} gpakResetFramingStatsStatus_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakResetFramingStatsStatus_t gpakResetFramingStats( - unsigned short int DspId // DSP identifier - ); - - -typedef enum -{ - RmmSuccess =0, - RmmInvalidDsp = 1, - RmmSizeTooBig = 2, - RmmFailure = 3, - RmmInvalidAddress = 4 - -} gpakReadDSPMemoryStat_t; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - read a section of DSP memory - * to get access DSP registers, since 0x00--0x60 not HPI-accessable - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ - -extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pDest, // Buffer on host to hold DSP memory map - DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out - unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word - ); - -typedef enum -{ - GPIOSuccess =0, - GPIOInvalidDsp = 1, - GPIODspCommFailure = 2 -}gpakAccessGPIOStat_t; - -extern gpakAccessGPIOStat_t gpakAccessGPIO( - unsigned short int DspId, // DSP identifier - GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read - unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask - ); - -/* gpakWriteSystemParms return status. */ -typedef enum -{ - WspSuccess = 0, /* System Parameters written successfully */ - WspParmError = 1, /* Write System Parms's Parameter error */ - WspInvalidDsp = 2, /* invalid DSP */ - WspDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakWriteSysParmsStatus_t; - -/* Definition of a System Parameters information structure. */ -typedef struct -{ - /* DTMF Parameters */ - short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ - short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ - short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ - short int DtmfFwdTwist; /* 0 to 8 db */ - short int DtmfRevTwist; /* 0 to 8 db */ - - short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ - -} GpakSystemParms_t; -/* gpakReadSystemParms return status. */ -typedef enum -{ - RspSuccess = 0, /* System Parameters read successfully */ - RspInvalidDsp = 1, /* invalid DSP */ - RspDspCommFailure = 2 /* failed to communicate with DSP */ -} gpakReadSysParmsStatus_t; - -extern gpakReadSysParmsStatus_t gpakReadSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ - ); - -extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ - unsigned short int UpdateBits, /* input: flags indicating which parms to update */ - GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ - ); - -#endif // end multiple inclusion - diff --git a/drivers/dahdi/wcte12xp/GpakErrs.h b/drivers/dahdi/wcte12xp/GpakErrs.h deleted file mode 100644 index 2f5083b..0000000 --- a/drivers/dahdi/wcte12xp/GpakErrs.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. - * - * File Name: GpakErrs.h - * - * Description: - * This file contains DSP reply status codes used by G.PAK API functions to - * indicate specific errors. - * - * Version: 1.0 - * - * Revision History: - * 10/17/01 - Initial release. - * 07/03/02 - Updates for conferencing. - * 06/15/04 - Tone type updates. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#ifndef _GPAKERRS_H /* prevent multiple inclusion */ -#define _GPAKERRS_H - -/* Configure Serial Ports reply status codes. */ -typedef enum -{ - Pc_Success = 0, /* serial ports configured successfully */ - Pc_ChannelsActive = 1, /* unable to configure while channels active */ - Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ - Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ - Pc_NoSlots1 = 4, /* no slots selected for port 1 */ - Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ - Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ - Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ - Pc_NoSlots2 = 8, /* no slots selected for port 2 */ - Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ - Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ - Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ - Pc_NoSlots3 = 12, /* no slots selected for port 3 */ - Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ -} GPAK_PortConfigStat_t; - -/* Configure Channel reply status codes. */ -typedef enum -{ - Cc_Success = 0, /* channel configured successfully */ - Cc_InvalidChannelType = 1, /* invalid Channel Type */ - Cc_InvalidChannel = 2, /* invalid Channel A Id */ - Cc_ChannelActiveA = 3, /* Channel A is currently active */ - Cc_InvalidInputPortA = 4, /* invalid Input A Port */ - Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ - Cc_BusyInputSlotA = 6, /* busy Input A Slot */ - Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ - Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ - Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ - Cc_InvalidInputPortB = 10, /* invalid Input B Port */ - Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ - Cc_BusyInputSlotB = 12, /* busy Input B Slot */ - Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ - Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ - Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ - Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ - - Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ - Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ - Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ - - Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ - Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ - - Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ - Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ - Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ - Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ - Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ - Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ - Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ - Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ - Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ - - /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ - Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ - Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ - - Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ - Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ - Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ - -} GPAK_ChannelConfigStat_t; - -/* Tear Down Channel reply status codes. */ -typedef enum -{ - Td_Success = 0, /* channel torn down successfully */ - Td_InvalidChannel = 1, /* invalid Channel Id */ - Td_ChannelNotActive = 2 /* channel is not active */ -} GPAK_TearDownChanStat_t; - - -typedef enum -{ - Ac_Success = 0, /* algorithm control is successfull */ - Ac_InvalidChannel = 1, /* invalid channel identifier */ - Ac_InvalidCode = 2, /* invalid algorithm control code */ - Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ - Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ - Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ - Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ - Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ - Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ - Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ -} GPAK_AlgControlStat_t; - -/* Write System Parameters reply status codes. */ -typedef enum -{ - Sp_Success = 0, /* System Parameters written successfully */ - Sp_BadTwistThresh = 29 /* invalid twist threshold */ - -} GPAK_SysParmsStat_t; - -#endif /* prevent multiple inclusion */ - - - - - - - - - - - - - - - - - - - diff --git a/drivers/dahdi/wcte12xp/Kbuild b/drivers/dahdi/wcte12xp/Kbuild index c462a32..77efd7d 100644 --- a/drivers/dahdi/wcte12xp/Kbuild +++ b/drivers/dahdi/wcte12xp/Kbuild @@ -1,18 +1,5 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp.o -FIRM_DIR := ../firmware - EXTRA_CFLAGS += -I$(src)/.. -Wno-undef -ifeq ($(HOTPLUG_FIRMWARE),yes) - EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE -endif - -wcte12xp-objs := base.o vpmadt032.o GpakApi.o voicebus.o - -ifneq ($(HOTPLUG_FIRMWARE),yes) -wcte12xp-objs += $(FIRM_DIR)/dahdi-fw-vpmadt032.o -endif - -$(obj)/$(FIRM_DIR)/dahdi-fw-vpmadt032.o: $(obj)/base.o - $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-vpmadt032.o +wcte12xp-objs := base.o diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index 9294350..30f89e9 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -41,15 +41,13 @@ #include <dahdi/kernel.h> -#include "../wct4xxp/wct4xxp.h" /* For certain definitions */ +#include "wct4xxp/wct4xxp.h" /* For certain definitions */ -#include "../voicebus.h" +#include "voicebus/voicebus.h" #include "wcte12xp.h" -#if defined(VPM_SUPPORT) -#include "vpmadt032.h" -#include "GpakApi.h" -#endif +#include "voicebus/GpakCust.h" +#include "voicebus/GpakApi.h" struct pci_driver te12xp_driver; @@ -60,14 +58,11 @@ static int loopback = 0; static int t1e1override = -1; static int unchannelized = 0; static int latency = VOICEBUS_DEFAULT_LATENCY; -#ifdef VPM_SUPPORT int vpmsupport = 1; -int vpmdtmfsupport = 0; static int vpmtsisupport = 0; -int vpmnlptype = 1; +int vpmnlptype = 3; int vpmnlpthresh = 24; int vpmnlpmaxsupp = 0; -#endif struct t1 *ifaces[WC_MAX_IFACES]; spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; @@ -205,6 +200,329 @@ static inline void cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk spin_unlock_irqrestore(&wc->cmd_list_lock, flags); } +inline void cmd_decipher_vpmadt032(struct t1 *wc, unsigned char *readchunk) +{ + unsigned long flags; + struct vpmadt032 *vpm = wc->vpmadt032; + struct vpmadt032_cmd *cmd; + + BUG_ON(!vpm); + + /* If the hardware is not processing any commands currently, then + * there is nothing for us to do here. */ + if (list_empty(&vpm->active_cmds)) { + return; + } + + spin_lock_irqsave(&vpm->list_lock, flags); + cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node); + if (wc->rxident == cmd->txident) { + list_del_init(&cmd->node); + } else { + cmd = NULL; + } + spin_unlock_irqrestore(&vpm->list_lock, flags); + + if (!cmd) { + return; + } + + /* Skip audio */ + readchunk += 66; + + /* Store result */ + cmd->data = (0xff & readchunk[CMD_BYTE(2, 1, 1)]) << 8; + cmd->data |= readchunk[CMD_BYTE(2, 2, 1)]; + if (cmd->desc & __VPM150M_WR) { + /* Writes do not need any acknowledgement */ + list_add_tail(&cmd->node, &vpm->free_cmds); + } else { + cmd->desc |= __VPM150M_FIN; + complete(&cmd->complete); + } +} + +static int config_vpmadt032(struct vpmadt032 *vpm) +{ + int res, channel; + GpakPortConfig_t portconfig = {0}; + gpakConfigPortStatus_t configportstatus; + GPAK_PortConfigStat_t pstatus; + GpakChannelConfig_t chanconfig; + GPAK_ChannelConfigStat_t cstatus; + GPAK_AlgControlStat_t algstatus; + + /* First Serial Port config */ + portconfig.SlotsSelect1 = SlotCfgNone; + portconfig.FirstBlockNum1 = 0; + portconfig.FirstSlotMask1 = 0x0000; + portconfig.SecBlockNum1 = 1; + portconfig.SecSlotMask1 = 0x0000; + portconfig.SerialWordSize1 = SerWordSize8; + portconfig.CompandingMode1 = cmpNone; + portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.TxClockPolarity1 = SerClockActHigh; + portconfig.RxClockPolarity1 = SerClockActHigh; + portconfig.TxDataDelay1 = DataDelay0; + portconfig.RxDataDelay1 = DataDelay0; + portconfig.DxDelay1 = Disabled; + portconfig.ThirdSlotMask1 = 0x0000; + portconfig.FouthSlotMask1 = 0x0000; + portconfig.FifthSlotMask1 = 0x0000; + portconfig.SixthSlotMask1 = 0x0000; + portconfig.SevenSlotMask1 = 0x0000; + portconfig.EightSlotMask1 = 0x0000; + + /* Second Serial Port config */ + portconfig.SlotsSelect2 = SlotCfg8Groups; + portconfig.FirstBlockNum2 = 0; + portconfig.FirstSlotMask2 = 0x5554; + portconfig.SecBlockNum2 = 1; + portconfig.SecSlotMask2 = 0x5555; + portconfig.ThirdSlotMask2 = 0x5555; + portconfig.FouthSlotMask2 = 0x5555; + portconfig.SerialWordSize2 = SerWordSize8; + portconfig.CompandingMode2 = cmpNone; + portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.TxClockPolarity2 = SerClockActHigh; + portconfig.RxClockPolarity2 = SerClockActHigh; + portconfig.TxDataDelay2 = DataDelay0; + portconfig.RxDataDelay2 = DataDelay0; + portconfig.DxDelay2 = Disabled; + portconfig.FifthSlotMask2 = 0x0001; + portconfig.SixthSlotMask2 = 0x0000; + portconfig.SevenSlotMask2 = 0x0000; + portconfig.EightSlotMask2 = 0x0000; + + /* Third Serial Port Config */ + portconfig.SlotsSelect3 = SlotCfg8Groups; + portconfig.FirstBlockNum3 = 0; + portconfig.FirstSlotMask3 = 0x5554; + portconfig.SecBlockNum3 = 1; + portconfig.SecSlotMask3 = 0x5555; + portconfig.SerialWordSize3 = SerWordSize8; + portconfig.CompandingMode3 = cmpNone; + portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.TxClockPolarity3 = SerClockActHigh; + portconfig.RxClockPolarity3 = SerClockActLow; + portconfig.TxDataDelay3 = DataDelay0; + portconfig.RxDataDelay3 = DataDelay0; + portconfig.DxDelay3 = Disabled; + portconfig.ThirdSlotMask3 = 0x5555; + portconfig.FouthSlotMask3 = 0x5555; + portconfig.FifthSlotMask3 = 0x0001; + portconfig.SixthSlotMask3 = 0x0000; + portconfig.SevenSlotMask3 = 0x0000; + portconfig.EightSlotMask3 = 0x0000; + + if ((configportstatus = gpakConfigurePorts(vpm->dspid, &portconfig, &pstatus))) { + printk(KERN_NOTICE "Configuration of ports failed (%d)!\n", configportstatus); + return -1; + } else { + if (vpm->options.debug & DEBUG_ECHOCAN) + printk(KERN_DEBUG "Configured McBSP ports successfully\n"); + } + + if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { + printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); + return -1; + } + + for (channel = 0; channel < MAX_CHANNELS_PER_SPAN; ++channel) { + vpm->curecstate[channel].tap_length = 0; + vpm->curecstate[channel].nlp_type = vpm->options.vpmnlptype; + vpm->curecstate[channel].nlp_threshold = vpm->options.vpmnlpthresh; + vpm->curecstate[channel].nlp_max_suppress = vpm->options.vpmnlpmaxsupp; + memcpy(&vpm->desiredecstate[channel], &vpm->curecstate[channel], sizeof(vpm->curecstate[channel])); + + vpm->setchanconfig_from_state(vpm, channel, &chanconfig); + if ((res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, &chanconfig, &cstatus))) { + printk(KERN_NOTICE "Unable to configure channel #%d (%d)", channel, res); + if (res == 1) { + printk(", reason %d", cstatus); + } + printk("\n"); + return -1; + } + + if ((res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &algstatus))) { + printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", channel + 1, res, algstatus); + return -1; + } + } + + if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { + printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); + return -1; + } + + set_bit(VPM150M_ACTIVE, &vpm->control); + + return 0; +} + +static void cmd_dequeue_vpmadt032(struct t1 *wc, unsigned char *writechunk, int whichframe) +{ + struct vpmadt032_cmd *cmd; + struct vpmadt032 *vpm = wc->vpmadt032; + int x; + unsigned char leds = ~((atomic_read(&wc->txints) / 1000) % 8) & 0x7; + + /* Skip audio */ + writechunk += 66; + + if (test_bit(VPM150M_SPIRESET, &vpm->control) || test_bit(VPM150M_HPIRESET, &vpm->control)) { + debug_printk(1, "HW Resetting VPMADT032 ...\n"); + for (x = 0; x < 4; x++) { + if (!x) { + if (test_and_clear_bit(VPM150M_SPIRESET, &vpm->control)) + writechunk[CMD_BYTE(x, 0, 1)] = 0x08; + else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm->control)) + writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; + } else + writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; + writechunk[CMD_BYTE(x, 1, 1)] = 0; + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + return; + } + + if ((cmd = vpmadt032_get_ready_cmd(vpm))) { + cmd->txident = wc->txident; +#if 0 + printk(KERN_DEBUG "Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", cmd->txident, cmd->desc, cmd->address, cmd->data); +#endif + if (cmd->desc & __VPM150M_RWPAGE) { + /* Set CTRL access to page*/ + writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); + writechunk[CMD_BYTE(0, 1, 1)] = 0; + writechunk[CMD_BYTE(0, 2, 1)] = 0x20; + + /* Do a page write */ + if (cmd->desc & __VPM150M_WR) { + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); + } else { + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); + } + writechunk[CMD_BYTE(1, 1, 1)] = 0; + if (cmd->desc & __VPM150M_WR) { + writechunk[CMD_BYTE(1, 2, 1)] = cmd->data & 0xf; + } else { + writechunk[CMD_BYTE(1, 2, 1)] = 0; + } + + if (cmd->desc & __VPM150M_WR) { + /* Fill in buffer to size */ + writechunk[CMD_BYTE(2, 0, 1)] = 0; + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } else { + /* Do reads twice b/c of vpmadt032 bug */ + writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } + + /* Clear XADD */ + writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); + writechunk[CMD_BYTE(3, 1, 1)] = 0; + writechunk[CMD_BYTE(3, 2, 1)] = 0; + + /* Fill in buffer to size */ + writechunk[CMD_BYTE(4, 0, 1)] = 0; + writechunk[CMD_BYTE(4, 1, 1)] = 0; + writechunk[CMD_BYTE(4, 2, 1)] = 0; + + } else { + /* Set address */ + writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); + writechunk[CMD_BYTE(0, 1, 1)] = (cmd->address >> 8) & 0xff; + writechunk[CMD_BYTE(0, 2, 1)] = cmd->address & 0xff; + + /* Send/Get our data */ + if (cmd->desc & __VPM150M_WR) { + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); + } else { + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + } + writechunk[CMD_BYTE(1, 1, 1)] = (cmd->data >> 8) & 0xff; + writechunk[CMD_BYTE(1, 2, 1)] = cmd->data & 0xff; + + if (cmd->desc & __VPM150M_WR) { + /* Fill in */ + writechunk[CMD_BYTE(2, 0, 1)] = 0; + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } else { + /* Do this again for reads b/c of the bug in vpmadt032 */ + writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(2, 1, 1)] = (cmd->data >> 8) & 0xff; + writechunk[CMD_BYTE(2, 2, 1)] = cmd->data & 0xff; + } + + /* Fill in the rest */ + writechunk[CMD_BYTE(3, 0, 1)] = 0; + writechunk[CMD_BYTE(3, 1, 1)] = 0; + writechunk[CMD_BYTE(3, 2, 1)] = 0; + + /* Fill in the rest */ + writechunk[CMD_BYTE(4, 0, 1)] = 0; + writechunk[CMD_BYTE(4, 1, 1)] = 0; + writechunk[CMD_BYTE(4, 2, 1)] = 0; + } + } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm->control)) { + debug_printk(1, "Booting VPMADT032\n"); + for (x = 0; x < 7; x++) { + if (0 == x) { + writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); + } else { + writechunk[CMD_BYTE(x, 0, 1)] = 0x00; + } + writechunk[CMD_BYTE(x, 1, 1)] = 0; + if (0 == x) { + writechunk[CMD_BYTE(x, 2, 1)] = 0x01; + } else { + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + } + } else { + for (x = 0; x < 7; x++) { + writechunk[CMD_BYTE(x, 0, 1)] = 0x00; + writechunk[CMD_BYTE(x, 1, 1)] = 0x00; + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + } + + /* Add our leds in */ + for (x = 0; x < 7; x++) + writechunk[CMD_BYTE(x, 0, 1)] |= leds; + +#if 0 + int y; + for (x = 0; x < 7; x++) { + for (y = 0; y < 3; y++) { + if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { + module_printk("the test bit is high for byte %d\n", y); + } + } + } +#endif + + /* Now let's figure out if we need to check for DTMF */ + /* polling */ + if (test_bit(VPM150M_ACTIVE, &vpm->control) && !whichframe && !(atomic_read(&wc->txints) % 100)) + schedule_work(&vpm->work); + +#if 0 + /* This may be needed sometime in the future to troubleshoot ADT related issues. */ + if (test_bit(VPM150M_ACTIVE, &vpm->control) && !whichframe && !(atomic_read(&wc->txints) % 10000)) + queue_work(vpm->wq, &vpm->work_debug); +#endif +} + static inline int t1_setreg_full(struct t1 *wc, int addr, int val, int vpm_num) { struct command *cmd; @@ -817,9 +1135,6 @@ static int t1xxp_close(struct dahdi_chan *chan) static int t1xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { - unsigned int x; - struct t1 *wc = chan->pvt; - switch (cmd) { case WCT4_GET_REGS: /* Since all register access was moved into the voicebus @@ -829,78 +1144,22 @@ static int t1xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long WARN_ON(1); return -ENOSYS; break; -#ifdef VPM_SUPPORT - case DAHDI_TONEDETECT: - if (get_user(x, (__user int *) data)) - return -EFAULT; - if (!wc->vpm150m) - return -ENOSYS; - if (wc->vpm150m && (x && !vpmdtmfsupport)) - return -ENOSYS; - if (x & DAHDI_TONEDETECT_ON) { - set_bit(chan->chanpos - 1, &wc->dtmfmask); - module_printk("turning on tone detection\n"); - } else { - clear_bit(chan->chanpos - 1, &wc->dtmfmask); - module_printk("turning off tone detection\n"); - } - if (x & DAHDI_TONEDETECT_MUTE) { - if(wc->vpm150m) - set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } else { - if(wc->vpm150m) - clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } - return 0; -#endif default: return -ENOTTY; } return 0; } -#ifdef VPM_SUPPORT - -#include "adt_lec.c" - -static int t1xxp_echocan_with_params(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) +static int t1xxp_echocan_with_params(struct dahdi_chan *chan, + struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) { - struct adt_lec_params params; struct t1 *wc = chan->pvt; - struct vpm150m *vpm150m = wc->vpm150m; - unsigned long flags; - struct vpm150m_workentry *work; - unsigned int ret; - - if (!wc->vpm150m) + if (!wc->vpmadt032) { return -ENODEV; - - adt_lec_init_defaults(¶ms, 32); - - if ((ret = adt_lec_parse_params(¶ms, ecp, p))) - return ret; - - /* we can't really control the tap length, but the value is used - to control whether the ec is on or off, so translate it */ - params.tap_length = ecp->tap_length ? 1 : 0; - - if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) - return -ENOMEM; - - work->params = params; - work->wc = wc; - work->chan = chan; - spin_lock_irqsave(&vpm150m->lock, flags); - list_add_tail(&work->list, &vpm150m->worklist); - spin_unlock_irqrestore(&vpm150m->lock, flags); - - /* we must do this later since we cannot sleep in the echocan function */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control)) - queue_work(vpm150m->wq, &vpm150m->work_echocan); - - return 0; /* how do I return the status since it is done later by the workqueue? */ + } + return vpmadt032_echocan_with_params(wc->vpmadt032, chan->chanpos - 1, + ecp, p); } -#endif static int t1_software_init(struct t1 *wc) { @@ -930,7 +1189,7 @@ static int t1_software_init(struct t1 *wc) strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); #if defined(VPM_SUPPORT) - if (wc->vpm150m) + if (wc->vpmadt032) strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); #endif @@ -1001,9 +1260,64 @@ static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned i #endif +static void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelConfig_t *chanconfig) +{ + const struct vpmadt032_options *options; + + BUG_ON(!vpm); + + options = &vpm->options; + + chanconfig->PcmInPortA = 3; + chanconfig->PcmInSlotA = (channel + 1) * 2; + chanconfig->PcmOutPortA = 2; + chanconfig->PcmOutSlotA = (channel + 1) * 2; + chanconfig->PcmInPortB = 2; + chanconfig->PcmInSlotB = (channel + 1) * 2; + chanconfig->PcmOutPortB = 3; + chanconfig->PcmOutSlotB = (channel + 1) * 2; + chanconfig->ToneTypesA = Null_tone; + chanconfig->MuteToneA = Disabled; + chanconfig->FaxCngDetA = Disabled; + chanconfig->ToneTypesB = Null_tone; + chanconfig->EcanEnableA = Enabled; + chanconfig->EcanEnableB = Disabled; + chanconfig->MuteToneB = Disabled; + chanconfig->FaxCngDetB = Disabled; + + chanconfig->SoftwareCompand = cmpPCMU; + + chanconfig->FrameRate = rate10ms; + chanconfig->EcanParametersA.EcanTapLength = 1024; + chanconfig->EcanParametersA.EcanNlpType = vpm->curecstate[channel].nlp_type; + chanconfig->EcanParametersA.EcanAdaptEnable = 1; + chanconfig->EcanParametersA.EcanG165DetEnable = 1; + chanconfig->EcanParametersA.EcanDblTalkThresh = 6; + chanconfig->EcanParametersA.EcanMaxDoubleTalkThres = 40; + chanconfig->EcanParametersA.EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; + chanconfig->EcanParametersA.EcanNlpConv = 0; + chanconfig->EcanParametersA.EcanNlpUnConv = 12; + chanconfig->EcanParametersA.EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; + chanconfig->EcanParametersA.EcanCngThreshold = 43; + chanconfig->EcanParametersA.EcanAdaptLimit = 50; + chanconfig->EcanParametersA.EcanCrossCorrLimit = 15; + chanconfig->EcanParametersA.EcanNumFirSegments = 3; + chanconfig->EcanParametersA.EcanFirSegmentLen = 48; + chanconfig->EcanParametersA.EcanReconvergenceCheckEnable = 1; + chanconfig->EcanParametersA.EcanTandemOperationEnable = 1; + chanconfig->EcanParametersA.EcanMixedFourWireMode = 1; + + + memcpy(&chanconfig->EcanParametersB, + &chanconfig->EcanParametersA, + sizeof(chanconfig->EcanParametersB)); +} + static int t1_hardware_post_init(struct t1 *wc) { + struct vpmadt032_options options; unsigned int reg; + int res; int x; /* T1 or E1 */ @@ -1036,17 +1350,41 @@ static int t1_hardware_post_init(struct t1 *wc) t1_setleds(wc, wc->ledstate); #ifdef VPM_SUPPORT - t1_vpm150m_init(wc); - if (wc->vpm150m) { - module_printk("VPM present and operational (Firmware version %x)\n", wc->vpm150m->version); - set_bit(4, &wc->ctlreg); /* turn on vpm (RX audio from vpm module) */ + if (vpmsupport) { + memset(&options, 0, sizeof(options)); + options.debug = debug; + options.vpmnlptype = vpmnlptype; + options.vpmnlpthresh = vpmnlpthresh; + options.vpmnlpmaxsupp = vpmnlpmaxsupp; + + wc->vpmadt032 = vpmadt032_alloc(&options); + if (!wc->vpmadt032) + return -ENOMEM; + + wc->vpmadt032->context = wc; + wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state; + wc->vpmadt032->span = &wc->span; + + res = vpmadt032_init(wc->vpmadt032, wc->vb); + if (res) { + vpmadt032_free(wc->vpmadt032); + wc->vpmadt032=NULL; + return -EIO; + } + + config_vpmadt032(wc->vpmadt032); + + module_printk("VPM present and operational (Firmware version %x)\n", wc->vpmadt032->version); + wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ if (vpmtsisupport) { debug_printk(1, "enabling VPM TSI pin\n"); - set_bit(0, &wc->ctlreg); /* turn on vpm timeslot interchange pin */ + wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ } + } else { + module_printk("VPM Support Disabled\n"); + wc->vpmadt032 = NULL; } #endif - return 0; } @@ -1234,9 +1572,9 @@ static inline void t1_transmitprep(struct t1 *wc, unsigned char* writechunk) cmd_dequeue(wc, writechunk, x, y); } #ifdef VPM_SUPPORT - if(likely(wc->vpm150m)) { + if(likely(wc->vpmadt032)) { spin_lock(&wc->reglock); - vpm150m_cmd_dequeue(wc, writechunk, x); + cmd_dequeue_vpmadt032(wc, writechunk, x); spin_unlock(&wc->reglock); } #endif @@ -1273,9 +1611,9 @@ static inline void t1_receiveprep(struct t1 *wc, unsigned char* readchunk) } cmd_decipher(wc, readchunk); #ifdef VPM_SUPPORT - if (wc->vpm150m) { + if (wc->vpmadt032) { spin_lock(&wc->reglock); - vpm150m_cmd_decipher(wc, readchunk); + cmd_decipher_vpmadt032(wc, readchunk); spin_unlock(&wc->reglock); } #endif @@ -1445,17 +1783,16 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev) struct t1 *wc = pci_get_drvdata(pdev); #ifdef VPM_SUPPORT unsigned long flags; - struct vpm150m *vpm150m = wc->vpm150m; + struct vpmadt032 *vpm = wc->vpmadt032; #endif if (!wc) return; #ifdef VPM_SUPPORT - if(vpm150m) { - clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); - clear_bit(VPM150M_ACTIVE, &vpm150m->control); - flush_workqueue(vpm150m->wq); - destroy_workqueue(vpm150m->wq); + if(vpm) { + wc->vpmadt032 = NULL; + clear_bit(VPM150M_DTMFDETECT, &vpm->control); + clear_bit(VPM150M_ACTIVE, &vpm->control); } #endif clear_bit(INITIALIZED, &wc->bit_flags); @@ -1468,12 +1805,10 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev) wc->vb = NULL; #ifdef VPM_SUPPORT - if(vpm150m) { + if(vpm) { spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - vpm150m->wc = NULL; spin_unlock_irqrestore(&wc->reglock, flags); - kfree(wc->vpm150m); + vpmadt032_free(vpm); } #endif t1_release(wc); @@ -1537,7 +1872,6 @@ module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); module_param(latency, int, S_IRUGO | S_IWUSR); #ifdef VPM_SUPPORT module_param(vpmsupport, int, S_IRUGO | S_IWUSR); -module_param(vpmdtmfsupport, int, S_IRUGO | S_IWUSR); module_param(vpmtsisupport, int, S_IRUGO | S_IWUSR); #endif diff --git a/drivers/dahdi/wcte12xp/gpakenum.h b/drivers/dahdi/wcte12xp/gpakenum.h deleted file mode 100644 index c2a5175..0000000 --- a/drivers/dahdi/wcte12xp/gpakenum.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: gpakenum.h - * - * Description: - * This file contains common enumerations related to G.PAK application - * software. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#ifndef _GPAKENUM_H /* prevent multiple inclusion */ -#define _GPAKENUM_H - -/* G.PAK Serial Port Word Size */ -typedef enum -{ - SerWordSize8 = 0, // 8-bit seial word - SerWordSize16 = 1 // 16-bit serial word -} GpakSerWordSize_t; - -/* G.PAK Serial Port FrameSync Polarity */ -typedef enum -{ - FrameSyncActLow = 0, // active low frame sync signal - FrameSyncActHigh = 1 // active high frame sync signal -} GpakSerFrameSyncPol_t; - -/* G.PAK Serial Port Clock Polarity */ -typedef enum -{ - SerClockActLow = 0, // active low serial clock - SerClockActHigh = 1 // active high serial clock -} GpakSerClockPol_t; - -/* G.PAK Serial Port Data Delay */ -typedef enum -{ - DataDelay0 = 0, // no data delay - DataDelay1 = 1, // 1-bit data delay - DataDelay2 = 2 // 2-bit data delay -} GpakSerDataDelay_t; - -/* G.PAK Serial Port Ids. */ -typedef enum -{ - SerialPortNull = 0, // null serial port - SerialPort1 = 1, // first PCM serial stream port (McBSP0) - SerialPort2 = 2, // second PCM serial stream port (McBSP1) - SerialPort3 = 3 // third PCM serial stream port (McBSP2) -} GpakSerialPort_t; - -/* G.PAK serial port Slot Configuration selection codes. */ -typedef enum -{ - SlotCfgNone = 0, // no time slots used - SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system - SlotCfg8Groups = 8 // 8-partition mode for 128-channel system -} GpakSlotCfg_t; - -/* G.PAK serial port Companding Mode codes. */ -typedef enum -{ - cmpPCMU=0, // u-Law - cmpPCMA=1, // A-Law - cmpNone=2 // none -} GpakCompandModes; - -/* G.PAK Active/Inactive selection codes. */ -typedef enum -{ - Disabled=0, // Inactive - Enabled=1 // Active -} GpakActivation; - -/* G.PAK Channel Type codes. */ -typedef enum -{ - inactive=0, // channel inactive - tdmToTdm=1 // tdmToTdm -} GpakChanType; - -/* G.PAK Algorithm control commands */ -typedef enum -{ - EnableEcanA = 0, // Enable A side echo canceller - BypassEcanA = 1, // Bypass A side echo canceller - ResetEcanA = 2, // Reset A side echo canceller - EnableEcanB = 3, // Enable B side echo canceller - BypassEcanB = 4, // Bypass B side echo canceller - ResetEcanB = 5, // Reset B side echo canceller - - EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding - EnableALawSwCompanding = 7, // Enable Mu-law Software companding - BypassSwCompanding = 8, // Bypass Software companding - EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected - DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected - EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected - DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected - EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already - DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already - EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already - DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already -} GpakAlgCtrl_t; - -/* G.PAK Tone types. */ -typedef enum -{ - Null_tone = 0, // no tone detection - DTMF_tone = 1 // DTMF tone -} GpakToneTypes; - -/* G.PAK direction. */ -typedef enum -{ - TDMAToB = 0, // A to B - TDMBToA = 1 // B to A -} GpakTdmDirection; - - -typedef enum -{ - rate1ms=0, - rate2ms=1, - rate10ms=2 -} GpakRate_t; - -/* G.PAK Asynchronous Event Codes */ -typedef enum -{ - EventToneDetect = 0, // Tone detection event - EventDSPDebug = 7 // DSP debug data event -} GpakAsyncEventCode_t; - -/* G.PAK MF Tone Code Indices */ -typedef enum -{ - DtmfDigit1 = 0, // DTMF Digit 1 - DtmfDigit2 = 1, // DTMF Digit 2 - DtmfDigit3 = 2, // DTMF Digit 3 - DtmfDigitA = 3, // DTMF Digit A - DtmfDigit4 = 4, // DTMF Digit 4 - DtmfDigit5 = 5, // DTMF Digit 5 - DtmfDigit6 = 6, // DTMF Digit 6 - DtmfDigitB = 7, // DTMF Digit B - DtmfDigit7 = 8, // DTMF Digit 7 - DtmfDigit8 = 9, // DTMF Digit 8 - DtmfDigit9 = 10, // DTMF Digit 9 - DtmfDigitC = 11, // DTMF Digit C - DtmfDigitSt = 12, // DTMF Digit * - DtmfDigit0 = 13, // DTMF Digit 0 - DtmfDigitPnd = 14, // DTMF Digit # - DtmfDigitD = 15, // DTMF Digit D - - FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) - - EndofMFDigit = 100, // End of MF digit - EndofCngDigit = 101 // End of Cng Digit -} GpakToneCodes_t; - -/* GPIO control code*/ -typedef enum -{ - GPIO_READ = 0, - GPIO_WRITE = 1, - GPIO_DIR = 2 -} GpakGPIOCotrol_t; - -#endif // end multiple inclusion diff --git a/drivers/dahdi/wcte12xp/voicebus.c b/drivers/dahdi/wcte12xp/voicebus.c deleted file mode 120000 index 6653619..0000000 --- a/drivers/dahdi/wcte12xp/voicebus.c +++ /dev/null @@ -1 +0,0 @@ -../voicebus.c
\ No newline at end of file diff --git a/drivers/dahdi/wcte12xp/vpmadt032.c b/drivers/dahdi/wcte12xp/vpmadt032.c deleted file mode 100644 index 2424f67..0000000 --- a/drivers/dahdi/wcte12xp/vpmadt032.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* - * Digium, Inc. Wildcard TE12xP T1/E1 card Driver - * - * Written by Michael Spiceland <mspiceland@digium.com> - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer <markster@digium.com> - * Matthew Fredrickson <creslin@digium.com> - * William Meadows <wmeadows@digium.com> - * - * Copyright (C) 2007, Digium, Inc. - * - * All rights reserved. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#include <linux/delay.h> -#include <linux/version.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include <linux/semaphore.h> -#else -#include <asm/semaphore.h> -#endif -#include <linux/pci.h> -#include <linux/firmware.h> -#include <linux/list.h> - -#include <dahdi/kernel.h> - -#include "voicebus.h" - -#include "wcte12xp.h" -#include "vpmadt032.h" -#include "GpakApi.h" - -#ifdef VPM_SUPPORT - -inline void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe) -{ - struct vpm150m_cmd *curcmd = NULL; - struct vpm150m *vpm150m = wc->vpm150m; - int x; - unsigned char leds = ~((atomic_read(&wc->txints) / 1000) % 8) & 0x7; - - /* Skip audio */ - writechunk += 66; - - if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { - debug_printk(1, "HW Resetting VPMADT032 ...\n"); - for (x = 0; x < 4; x++) { - if (!x) { - if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) - writechunk[CMD_BYTE(x, 0, 1)] = 0x08; - else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) - writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; - } else - writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; - writechunk[CMD_BYTE(x, 1, 1)] = 0; - writechunk[CMD_BYTE(x, 2, 1)] = 0x00; - } - return; - } - - /* Search for something waiting to transmit */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && - !(vpm150m->cmdq[x].flags & (__VPM150M_FIN | __VPM150M_TX))) { - curcmd = &vpm150m->cmdq[x]; - curcmd->ident = wc->txident; - curcmd->flags |= __VPM150M_TX; - break; - } - } - if (curcmd) { -#if 0 - printk(KERN_DEBUG "Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); -#endif - if (curcmd->flags & __VPM150M_RWPAGE) { - /* Set CTRL access to page*/ - writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); - writechunk[CMD_BYTE(0, 1, 1)] = 0; - writechunk[CMD_BYTE(0, 2, 1)] = 0x20; - - /* Do a page write */ - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); - else - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); - writechunk[CMD_BYTE(1, 1, 1)] = 0; - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xf; - else - writechunk[CMD_BYTE(1, 2, 1)] = 0; - - if (curcmd->flags & __VPM150M_WR) { - /* Fill in buffer to size */ - writechunk[CMD_BYTE(2, 0, 1)] = 0; - writechunk[CMD_BYTE(2, 1, 1)] = 0; - writechunk[CMD_BYTE(2, 2, 1)] = 0; - } else { - /* Do reads twice b/c of vpmadt032 bug */ - writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); - writechunk[CMD_BYTE(2, 1, 1)] = 0; - writechunk[CMD_BYTE(2, 2, 1)] = 0; - } - - /* Clear XADD */ - writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); - writechunk[CMD_BYTE(3, 1, 1)] = 0; - writechunk[CMD_BYTE(3, 2, 1)] = 0; - - /* Fill in buffer to size */ - writechunk[CMD_BYTE(4, 0, 1)] = 0; - writechunk[CMD_BYTE(4, 1, 1)] = 0; - writechunk[CMD_BYTE(4, 2, 1)] = 0; - - } else { - /* Set address */ - writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); - writechunk[CMD_BYTE(0, 1, 1)] = (curcmd->address >> 8) & 0xff; - writechunk[CMD_BYTE(0, 2, 1)] = curcmd->address & 0xff; - - /* Send/Get our data */ - if (curcmd->flags & __VPM150M_WR) { - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); - } else - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - else - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(1, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; - writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xff; - - if (curcmd->flags & __VPM150M_WR) { - /* Fill in */ - writechunk[CMD_BYTE(2, 0, 1)] = 0; - writechunk[CMD_BYTE(2, 1, 1)] = 0; - writechunk[CMD_BYTE(2, 2, 1)] = 0; - } else { - /* Do this again for reads b/c of the bug in vpmadt032 */ - writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(2, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; - writechunk[CMD_BYTE(2, 2, 1)] = curcmd->data[0] & 0xff; - } - - if (curcmd->datalen > 1) { - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(3, 1, 1)] = (curcmd->data[1] >> 8) & 0xff; - writechunk[CMD_BYTE(3, 2, 1)] = curcmd->data[1] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(3, 0, 1)] = 0; - writechunk[CMD_BYTE(3, 1, 1)] = 0; - writechunk[CMD_BYTE(3, 2, 1)] = 0; - } - - if (curcmd->datalen > 2) { - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(4, 1, 1)] = (curcmd->data[2] >> 8) & 0xff; - writechunk[CMD_BYTE(4, 2, 1)] = curcmd->data[2] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(4, 0, 1)] = 0; - writechunk[CMD_BYTE(4, 1, 1)] = 0; - writechunk[CMD_BYTE(4, 2, 1)] = 0; - } - } - } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { - debug_printk(1, "Booting VPMADT032\n"); - for (x = 0; x < 7; x++) { - if (x == 0) - writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); - else - writechunk[CMD_BYTE(x, 0, 1)] = 0x00; - writechunk[CMD_BYTE(x, 1, 1)] = 0; - if (x == 0) - writechunk[CMD_BYTE(x, 2, 1)] = 0x01; - else - writechunk[CMD_BYTE(x, 2, 1)] = 0x00; - } - } else { - for (x = 0; x < 7; x++) { - writechunk[CMD_BYTE(x, 0, 1)] = 0x00; - writechunk[CMD_BYTE(x, 1, 1)] = 0x00; - writechunk[CMD_BYTE(x, 2, 1)] = 0x00; - } - } - - /* Add our leds in */ - for (x = 0; x < 7; x++) - writechunk[CMD_BYTE(x, 0, 1)] |= leds; - -#if 0 - int y; - for (x = 0; x < 7; x++) { - for (y = 0; y < 3; y++) { - if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { - module_printk("the test bit is high for byte %d\n", y); - } - } - } -#endif - - /* Now let's figure out if we need to check for DTMF */ - /* polling */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(atomic_read(&wc->txints) % 100)) - queue_work(vpm150m->wq, &vpm150m->work_dtmf); - -#if 0 - /* This may be needed sometime in the future to troubleshoot ADT related issues. */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 10000)) - queue_work(vpm150m->wq, &vpm150m->work_debug); -#endif -} - -inline void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) -{ - unsigned char ident; - int x, i; - - /* Skip audio */ - readchunk += 66; - /* Search for any pending results */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((wc->vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && - (wc->vpm150m->cmdq[x].flags & (__VPM150M_TX)) && - !(wc->vpm150m->cmdq[x].flags & (__VPM150M_FIN))) { - ident = wc->vpm150m->cmdq[x].ident; - if (ident == wc->rxident) { - /* Store result */ - for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { - wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((2 + i), 1, 1)]) << 8; - wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((2 + i), 2, 1)]; - } - if (wc->vpm150m->cmdq[x].flags & __VPM150M_WR) { - /* Go ahead and clear out writes since they need no acknowledgement */ - wc->vpm150m->cmdq[x].flags = 0; - } else - wc->vpm150m->cmdq[x].flags |= __VPM150M_FIN; - break; - } - } - } -} - -static inline struct t1 * wc_find_iface(unsigned short dspid) -{ - int i; - struct t1 *ret = NULL; - unsigned long flags; - - spin_lock_irqsave(&ifacelock, flags); - for (i = 0; i < WC_MAX_IFACES; i++) - if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) - ret = ifaces[i]; - spin_unlock_irqrestore(&ifacelock, flags); - - return ret; -} - -static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) -{ - unsigned int x; - - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if (!wc->vpm150m->cmdq[x].flags) { - return &wc->vpm150m->cmdq[x]; - } - } - return NULL; -} - -/* Wait for any outstanding commands to be completed. */ -static inline int vpm150m_io_wait(struct t1 *wc) -{ - int x; - for (x=0; x < VPM150M_MAX_COMMANDS;) { - if (wc->vpm150m->cmdq[x].flags) { - if (msleep_interruptible(1)) { - return -EINTR; - } - x=0; - } - else { - ++x; - } - } - return 0; -} - -static int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret=0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - (*hit_p) = vpm150m_empty_slot(wc); - if (*hit_p) { - (*hit_p)->flags = __VPM150M_RD; - if (pagechange) { - (*hit_p)->flags |= __VPM150M_RWPAGE; - } - (*hit_p)->datalen = len; - (*hit_p)->address = addr; - memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); - } - else { - ret = -EBUSY; - } - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret = 0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - do { - if ((*hit_p)->flags & __VPM150M_FIN) { - memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); - (*hit_p)->flags = 0; - (*hit_p) = NULL; - ret = 0; - } - else { - spin_unlock_irqrestore(&wc->reglock, flags); - if (msleep_interruptible(1)) { - return -EINTR; - } - spin_lock_irqsave(&wc->reglock, flags); - ret = -EBUSY; - } - } while (-EBUSY == ret); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) -{ - struct vpm150m_cmd *hit = NULL; - int ret = 0; - do { - ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); - if (!hit) { - if ( -EBUSY == ret ) { - if (msleep_interruptible(1)) - return -EINTR; - } - BUG_ON( 0 != ret); - } - } while (!hit); - - ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); - return ret; -} - -static int t1_vpm150m_setreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned long flags; - struct vpm150m_cmd *hit; - int i; - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = vpm150m_empty_slot(wc); - if (hit) { - hit->flags = __VPM150M_WR; - if (pagechange) - hit->flags |= __VPM150M_RWPAGE; - hit->address = addr; - hit->datalen = len; - for (i = 0; i < len; i++) - hit->data[i] = data[i]; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (!hit) { - if (msleep_interruptible(1)) - return -EINTR; - } - } while (!hit); - return (hit) ? 0 : -1; -} - -static int t1_vpm150m_setpage(struct t1 *wc, unsigned short addr) -{ - addr &= 0xf; - /* Let's optimize this a little bit */ - if (wc->vpm150m->curpage == addr) - return 0; - else { - wc->vpm150m->curpage = addr; - } - - return t1_vpm150m_setreg_full(wc, 1, 1, 0, &addr); -} - -static unsigned char t1_vpm150m_getpage(struct t1 *wc) -{ - unsigned short res; - t1_vpm150m_getreg_full(wc, 1, 1, 0, &res); - return res; -} - -static int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - int res; - t1_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - module_printk("setreg: You found it!\n"); - res = t1_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -static unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned short res; - t1_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - module_printk("getreg: You found it!\n"); - res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -static char vpm150mtone_to_zaptone(GpakToneCodes_t tone) -{ - switch (tone) { - case DtmfDigit0: - return '0'; - case DtmfDigit1: - return '1'; - case DtmfDigit2: - return '2'; - case DtmfDigit3: - return '3'; - case DtmfDigit4: - return '4'; - case DtmfDigit5: - return '5'; - case DtmfDigit6: - return '6'; - case DtmfDigit7: - return '7'; - case DtmfDigit8: - return '8'; - case DtmfDigit9: - return '9'; - case DtmfDigitPnd: - return '#'; - case DtmfDigitSt: - return '*'; - case DtmfDigitA: - return 'A'; - case DtmfDigitB: - return 'B'; - case DtmfDigitC: - return 'C'; - case DtmfDigitD: - return 'D'; - case EndofCngDigit: - return 'f'; - default: - return 0; - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_echocan_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_echocan_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_echocan); -#endif - struct t1 *wc = vpm150m->wc; - unsigned long flags; - struct vpm150m_workentry *we; - struct dahdi_chan *chan; - int deflaw; - int res; - GPAK_AlgControlStat_t pstatus; - - while (!list_empty(&vpm150m->worklist)) { - we = list_entry(vpm150m->worklist.next, struct vpm150m_workentry, list); - - spin_lock_irqsave(&vpm150m->lock, flags); - list_del(&we->list); - spin_unlock_irqrestore(&vpm150m->lock, flags); - - chan = we->chan; - - if (we->params.tap_length) { - /* configure channel for the ulaw/alaw */ - unsigned int start = atomic_read(&wc->txints); - - if (memcmp(&we->params, &vpm150m->chan_params[chan->chanpos - 1], sizeof(we->params))) { - /* set parameters */ - vpm150m->chan_params[chan->chanpos - 1] = we->params; - } - - deflaw = chan->span->deflaw; - debug_printk(1, "Enabling EC on channel %d (law %d)\n", chan->chanpos, deflaw); - if (deflaw == 2) /* alaw */ - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableALawSwCompanding, &pstatus); - else if (deflaw == 1) /* alaw */ - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableMuLawSwCompanding, &pstatus); - else { - module_printk("Undefined law for channel %d.\n", chan->chanpos); - res = -1; - } - - if (res) { - module_printk("Unable to set SW Companding on channel %d (reason %d)\n", chan->chanpos, res); - } - - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableEcanA, &pstatus); - debug_printk(2, "Echo can enable took %d ms\n", atomic_read(&wc->txints) - start); - } else { - unsigned int start = atomic_read(&wc->txints); - debug_printk(1, "Disabling EC on channel %d\n", chan->chanpos); - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassSwCompanding, &pstatus); - if (res) - module_printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", chan->chanpos, res); - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassEcanA, &pstatus); - if (res) - module_printk("Unable to disable echo can on channel %d (reason %d)\n", chan->chanpos, res); - debug_printk(2, "Echocan disable took %d ms\n", atomic_read(&wc->txints) - start); - } - if (res) { - module_printk("Unable to toggle echo cancellation on channel %d (reason %d)\n", chan->chanpos, res); - } - - kfree(we); - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_debug_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_debug_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_debug); -#endif - unsigned short int FrammingError1Count, FramingError2Count, FramingError3Count, - DmaStopErrorCount, DmaSlipStatsBuffer; - - if (gpakReadFramingStats(vpm150m->dspid, &FrammingError1Count, &FramingError2Count, &FramingError3Count, - &DmaStopErrorCount, &DmaSlipStatsBuffer)) - { - module_printk("There was an error getting framing stats.\n"); - } - if (FrammingError1Count||FramingError2Count||FramingError3Count||DmaStopErrorCount||DmaSlipStatsBuffer) - { - module_printk("FramingStats Error: %d %d %d %d %d\n", - FrammingError1Count, FramingError2Count, FramingError3Count, DmaStopErrorCount, DmaSlipStatsBuffer); - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_dtmf_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_dtmf_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_dtmf); -#endif - struct t1 *wc = vpm150m->wc; - int i; - - for (i = 0; i < wc->span.channels; i++) { - int enable = -1; - if (test_bit(i, &vpm150m->desireddtmfmutestate)) { - if (!test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 1; - } - } else { - if (test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 0; - } - } - if (enable > -1) { - unsigned int start = atomic_read(&wc->txints); - GPAK_AlgControlStat_t pstatus; - int res; - - if (enable) { - res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); - debug_printk(2, "DTMF mute enable took %d ms\n", atomic_read(&wc->txints) - start); - } else { - res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); - debug_printk(2, "DTMF mute disable took %d ms\n", atomic_read(&wc->txints) - start); - } - if (!res) - change_bit(i, &vpm150m->curdtmfmutestate); - } - } - - if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { - unsigned short channel; - GpakAsyncEventCode_t eventcode; - GpakAsyncEventData_t eventdata; - gpakReadEventFIFOMessageStat_t res; - unsigned int start = atomic_read(&wc->txints); - - do { - res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); - debug_printk(3, "ReadEventFIFOMessage took %d ms\n", atomic_read(&wc->txints) - start); - - if (res == RefInvalidEvent || res == RefDspCommFailure) { - module_printk("Uh oh (%d)\n", res); - continue; - } - - if (eventcode == EventToneDetect) { - GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; - int duration = eventdata.toneEvent.ToneDuration; - char zaptone = vpm150mtone_to_zaptone(tone); - - debug_printk(1, "Channel %d: Detected DTMF tone %d of duration %d\n", channel + 1, tone, duration); - - if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { - struct dahdi_chan *chan = wc->chans[channel]; - - module_printk("DTMF detected channel=%d tone=%d duration=%d\n", channel + 1, tone, duration); - - if ((tone != EndofMFDigit) && (zaptone != 0)) { - vpm150m->curtone[channel] = tone; - - if (test_bit(channel, &vpm150m->curdtmfmutestate)) { - unsigned long flags; - int y; - - /* Mute the audio data buffers */ - spin_lock_irqsave(&chan->lock, flags); - for (y = 0; y < chan->numbufs; y++) { - if ((chan->inreadbuf > -1) && (chan->readidx[y])) - memset(chan->readbuf[chan->inreadbuf], DAHDI_XLAW(0, chan), chan->readidx[y]); - } - spin_unlock_irqrestore(&chan->lock, flags); - } - if (!test_bit(channel, &wc->dtmfactive)) { - debug_printk(1,"Queuing DTMFDOWN %c\n", zaptone); - set_bit(channel, &wc->dtmfactive); - dahdi_qevent_lock(chan, (DAHDI_EVENT_DTMFDOWN | zaptone)); - } - } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { - debug_printk(1,"Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); - dahdi_qevent_lock(chan, (DAHDI_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); - clear_bit(channel, &wc->dtmfactive); - } - } - } - } while ((res == RefEventAvail)); - } - - return; -} - -void t1_vpm150m_init(struct t1 *wc) { - struct vpm150m *vpm150m; - unsigned short i; - unsigned short reg; - unsigned long flags; - gpakPingDspStat_t pingstatus; - gpakDownloadStatus_t downloadstatus; - struct t1_firmware fw; - struct firmware embedded_firmware; - const struct firmware *firmware = &embedded_firmware; -#if !defined(HOTPLUG_FIRMWARE) - extern void _binary_dahdi_fw_vpmadt032_bin_size; - extern u8 _binary_dahdi_fw_vpmadt032_bin_start[]; -#else - static const char vpmadt032_firmware[] = "dahdi-fw-vpmadt032.bin"; - struct pci_dev* pdev = voicebus_get_pci_dev(wc->vb); -#endif - -#if 0 - unsigned short omsg[4] = { 0xdead, 0xbeef, 0x1111, 0x2222}; - unsigned short imsg[4]; -#endif - - if (!vpmsupport) { - module_printk("VPM Support Disabled\n"); - wc->vpm150m = NULL; - return; - } - - vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); - - if (!vpm150m) { - module_printk("Unable to allocate VPMADT032!\n"); - return; - } - memset(vpm150m, 0, sizeof(struct vpm150m)); - - /* Init our vpm150m struct */ - sema_init(&vpm150m->sem, 1); - vpm150m->curpage = 0x80; - - for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) { - if (ifaces[i] == wc) - vpm150m->dspid = i; - } - - debug_printk(1, "Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = vpm150m; - spin_unlock_irqrestore(&wc->reglock, flags); - - for (i = 0; i < 10; i++) - msleep_interruptible(1); - - debug_printk(1, "Looking for VPMADT032 by testing page access: "); - for (i = 0; i < 0xf; i++) { - int x; - for (x = 0; x < 3; x++) { - t1_vpm150m_setpage(wc, i); - reg = t1_vpm150m_getpage(wc); - if (reg != i) { - /* If they have debug turned on we want them to be able to - * report where in the code the module failed to come up. */ - debug_printk(1, "Either no VPMADT032 module present or the module failed VPM page access test (%x != %x)\n", i, reg); - goto failed_exit; - } - } - } - debug_printk(1, "Passed\n"); - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - msleep(2000); - - /* Set us up to page 0 */ - t1_vpm150m_setpage(wc, 0); - debug_printk(1, "VPMADT032 now doing address test: "); - for (i = 0; i < 16; i++) { - int x; - for (x = 0; x < 2; x++) { - t1_vpm150m_setreg(wc, 1, 0x1000, &i); - t1_vpm150m_getreg(wc, 1, 0x1000, ®); - if (reg != i) { - module_printk("VPMADT032 Failed address test: sent %x != %x on try %d\n", i, reg, x); - goto failed_exit; - } - } - } - debug_printk(1, "Passed\n"); - -#define TEST_SIZE 2 - if (debug) { - unsigned short msg[TEST_SIZE]; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - msleep(2000); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0xdead; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0xbeef; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0x1111; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0x2222; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - debug_printk(1, ""); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - } - -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, vpmadt032_firmware, &pdev->dev) != 0) || - !firmware) { - printk(KERN_NOTICE "VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); - goto failed_exit; - } -#else - embedded_firmware.data = _binary_dahdi_fw_vpmadt032_bin_start; - embedded_firmware.size = (size_t) &_binary_dahdi_fw_vpmadt032_bin_size; -#endif - fw.fw = firmware; - fw.offset = 0; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - - while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) - msleep(1); - - module_printk("VPMADT032 Loading firmware... "); - downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); - - if (firmware != &embedded_firmware) - release_firmware(firmware); - - if (downloadstatus != 0) { - module_printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); - goto failed_exit; - } else { - module_printk("Success\n"); - } - - set_bit(VPM150M_SWRESET, &vpm150m->control); - - while (test_bit(VPM150M_SWRESET, &vpm150m->control)) - msleep(1); - - msleep(700); -#if 0 - } -#endif - - pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); - - if (!pingstatus) { - debug_printk(1, "Version of DSP is %x\n", vpm150m->version); - } else { - module_printk("Unable to ping the DSP (%d)!\n", pingstatus); - goto failed_exit; - } - - /* workqueue for DTMF and wc->span functions that cannot sleep */ - spin_lock_init(&vpm150m->lock); - vpm150m->wq = create_singlethread_workqueue("wcte12xp"); - vpm150m->wc = wc; - if (!vpm150m->wq) { - module_printk("Unable to create work queue!\n"); - goto failed_exit; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh, vpm150m); - INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh, vpm150m); - INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh, vpm150m); -#else - INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh); - INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh); - INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh); -#endif - INIT_LIST_HEAD(&wc->vpm150m->worklist); /* list of echocan tasks */ - - if (vpm150m_config_hw(wc)) { - goto failed_exit; - } - - return; - -failed_exit: - if (vpm150m->wq) { - destroy_workqueue(vpm150m->wq); - } - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(vpm150m); - - return; -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. - * - * FUNCTION - * This function reads a contiguous block of words from DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ) -{ - struct t1 *wc = wc_find_iface(DspId); - int i; - int transcount; - int ret; - - vpm150m_io_wait(wc); - if ( NumWords < VPM150M_MAX_COMMANDS ) { - struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = { NULL }; - t1_vpm150m_setpage(wc, DspAddress >> 16); - DspAddress &= 0xffff; - for (i=0; i < NumWords; ++i) { - ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - for (i=NumWords-1; i >=0; --i) { - ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - } - else { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - t1_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } - } - return; -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. - * - * FUNCTION - * This function writes a contiguous block of words to DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ) -{ - - struct t1 *wc = wc_find_iface(DspId); - int i; - int transcount; - - if (wc && wc->vpm150m) { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - t1_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } - } - return; - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. - * - * FUNCTION - * This function delays for a fixed time interval before returning. The time - * interval is the Host Port Interface sampling period when polling a DSP for - * replies to command messages. - * - * RETURNS - * nothing - * - */ -void gpakHostDelay(void) -{ -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. - * - * FUNCTION - * This function aquires exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakLockAccess(unsigned short DspId) -{ - struct t1 *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - if (down_interruptible(&vpm->sem)) { - return; - } - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. - * - * FUNCTION - * This function releases exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakUnlockAccess(unsigned short DspId) -{ - struct t1 *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - up(&vpm->sem); - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. - * - * FUNCTION - * This function reads a contiguous block of bytes from a G.PAK Download file - * starting at the current file position. - * - * RETURNS - * The number of bytes read from the file. - * -1 indicates an error occurred. - * 0 indicates all bytes have been read (end of file) - * - */ -int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ) -{ - struct t1_firmware *fw = FileId; - unsigned int i, count; - - if (!fw || !fw->fw) - return -1; - - if (NumBytes > (fw->fw->size - fw->offset)) - count = fw->fw->size - fw->offset; - else - count = NumBytes; - - for (i = 0; i < count; i++) - pBuffer[i] = fw->fw->data[fw->offset + i]; - - fw->offset += count; - - return count; -} - -int vpm150m_config_hw(struct t1 *wc) -{ - struct vpm150m *vpm150m = wc->vpm150m; - gpakConfigPortStatus_t configportstatus; - GpakPortConfig_t portconfig; - GPAK_PortConfigStat_t pstatus; - GpakChannelConfig_t chanconfig; - GPAK_ChannelConfigStat_t cstatus; - GPAK_AlgControlStat_t algstatus; - - int res, i; - - memset(&portconfig, 0, sizeof(GpakPortConfig_t)); - - /* First Serial Port config */ - portconfig.SlotsSelect1 = SlotCfgNone; - portconfig.FirstBlockNum1 = 0; - portconfig.FirstSlotMask1 = 0x0000; - portconfig.SecBlockNum1 = 1; - portconfig.SecSlotMask1 = 0x0000; - portconfig.SerialWordSize1 = SerWordSize8; - portconfig.CompandingMode1 = cmpNone; - portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.TxClockPolarity1 = SerClockActHigh; - portconfig.RxClockPolarity1 = SerClockActHigh; - portconfig.TxDataDelay1 = DataDelay0; - portconfig.RxDataDelay1 = DataDelay0; - portconfig.DxDelay1 = Disabled; - portconfig.ThirdSlotMask1 = 0x0000; - portconfig.FouthSlotMask1 = 0x0000; - portconfig.FifthSlotMask1 = 0x0000; - portconfig.SixthSlotMask1 = 0x0000; - portconfig.SevenSlotMask1 = 0x0000; - portconfig.EightSlotMask1 = 0x0000; - - /* Second Serial Port config */ - portconfig.SlotsSelect2 = SlotCfg8Groups; - portconfig.FirstBlockNum2 = 0; - portconfig.FirstSlotMask2 = 0x5554; - portconfig.SecBlockNum2 = 1; - portconfig.SecSlotMask2 = 0x5555; - portconfig.ThirdSlotMask2 = 0x5555; - portconfig.FouthSlotMask2 = 0x5555; - portconfig.SerialWordSize2 = SerWordSize8; - portconfig.CompandingMode2 = cmpNone; - portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.TxClockPolarity2 = SerClockActHigh; - portconfig.RxClockPolarity2 = SerClockActHigh; - portconfig.TxDataDelay2 = DataDelay0; - portconfig.RxDataDelay2 = DataDelay0; - portconfig.DxDelay2 = Disabled; - portconfig.FifthSlotMask2 = 0x0001; - portconfig.SixthSlotMask2 = 0x0000; - portconfig.SevenSlotMask2 = 0x0000; - portconfig.EightSlotMask2 = 0x0000; - - /* Third Serial Port Config */ - portconfig.SlotsSelect3 = SlotCfg8Groups; - portconfig.FirstBlockNum3 = 0; - portconfig.FirstSlotMask3 = 0x5554; - portconfig.SecBlockNum3 = 1; - portconfig.SecSlotMask3 = 0x5555; - portconfig.SerialWordSize3 = SerWordSize8; - portconfig.CompandingMode3 = cmpNone; - portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.TxClockPolarity3 = SerClockActHigh; - portconfig.RxClockPolarity3 = SerClockActLow; - portconfig.TxDataDelay3 = DataDelay0; - portconfig.RxDataDelay3 = DataDelay0; - portconfig.DxDelay3 = Disabled; - portconfig.ThirdSlotMask3 = 0x5555; - portconfig.FouthSlotMask3 = 0x5555; - portconfig.FifthSlotMask3 = 0x0001; - portconfig.SixthSlotMask3 = 0x0000; - portconfig.SevenSlotMask3 = 0x0000; - portconfig.EightSlotMask3 = 0x0000; - - if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { - module_printk("Configuration of ports failed (%d)!\n", configportstatus); - return -1; - } else { - debug_printk(1, "Configured McBSP ports successfully\n"); - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - module_printk("Error pinging DSP (%d)\n", res); - return -1; - } - - for (i = 0; i < 32; i++) { - /* Let's configure a channel */ - chanconfig.PcmInPortA = 3; - chanconfig.PcmInSlotA = (i + 1) * 2; - chanconfig.PcmOutPortA = 2; - chanconfig.PcmOutSlotA = (i + 1) * 2; - chanconfig.PcmInPortB = 2; - chanconfig.PcmInSlotB = (i + 1) * 2; - chanconfig.PcmOutPortB = 3; - chanconfig.PcmOutSlotB = (i + 1) * 2; - if (vpmdtmfsupport) { - chanconfig.ToneTypesA = DTMF_tone; - chanconfig.MuteToneA = Enabled; - chanconfig.FaxCngDetA = Enabled; - } else { - chanconfig.ToneTypesA = Null_tone; - chanconfig.MuteToneA = Disabled; - chanconfig.FaxCngDetA = Disabled; - } - chanconfig.ToneTypesB = Null_tone; - chanconfig.EcanEnableA = Enabled; - chanconfig.EcanEnableB = Disabled; - chanconfig.MuteToneB = Disabled; - chanconfig.FaxCngDetB = Disabled; - - chanconfig.SoftwareCompand = cmpNone; - - chanconfig.FrameRate = rate10ms; - - chanconfig.EcanParametersA.EcanTapLength = 1024; - chanconfig.EcanParametersA.EcanNlpType = vpmnlptype; - chanconfig.EcanParametersA.EcanAdaptEnable = 1; - chanconfig.EcanParametersA.EcanG165DetEnable = 1; - chanconfig.EcanParametersA.EcanDblTalkThresh = 6; - chanconfig.EcanParametersA.EcanNlpThreshold = vpmnlpthresh; - chanconfig.EcanParametersA.EcanNlpConv = 0; - chanconfig.EcanParametersA.EcanNlpUnConv = 0; - chanconfig.EcanParametersA.EcanNlpMaxSuppress = vpmnlpmaxsupp; - chanconfig.EcanParametersA.EcanCngThreshold = 43; - chanconfig.EcanParametersA.EcanAdaptLimit = 50; - chanconfig.EcanParametersA.EcanCrossCorrLimit = 15; - chanconfig.EcanParametersA.EcanNumFirSegments = 3; - chanconfig.EcanParametersA.EcanFirSegmentLen = 64; - - chanconfig.EcanParametersB.EcanTapLength = 1024; - chanconfig.EcanParametersB.EcanNlpType = vpmnlptype; - chanconfig.EcanParametersB.EcanAdaptEnable = 1; - chanconfig.EcanParametersB.EcanG165DetEnable = 1; - chanconfig.EcanParametersB.EcanDblTalkThresh = 6; - chanconfig.EcanParametersB.EcanNlpThreshold = vpmnlpthresh; - chanconfig.EcanParametersB.EcanNlpConv = 0; - chanconfig.EcanParametersB.EcanNlpUnConv = 0; - chanconfig.EcanParametersB.EcanNlpMaxSuppress = vpmnlpmaxsupp; - chanconfig.EcanParametersB.EcanCngThreshold = 43; - chanconfig.EcanParametersB.EcanAdaptLimit = 50; - chanconfig.EcanParametersB.EcanCrossCorrLimit = 15; - chanconfig.EcanParametersB.EcanNumFirSegments = 3; - chanconfig.EcanParametersB.EcanFirSegmentLen = 64; - - if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { - module_printk("Unable to configure channel (%d)\n", res); - if (res == 1) { - module_printk("Reason %d\n", cstatus); - } - - return -1; - } - - if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { - module_printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - - if (vpmdtmfsupport) { - if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { - module_printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - } - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - module_printk("Error pinging DSP (%d)\n", res); - return -1; - } - - /* Turn on DTMF detection */ - if (vpmdtmfsupport) - set_bit(VPM150M_DTMFDETECT, &vpm150m->control); - set_bit(VPM150M_ACTIVE, &vpm150m->control); - - return 0; -} - -#endif diff --git a/drivers/dahdi/wcte12xp/vpmadt032.h b/drivers/dahdi/wcte12xp/vpmadt032.h deleted file mode 100644 index da50d6a..0000000 --- a/drivers/dahdi/wcte12xp/vpmadt032.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Digium, Inc. Wildcard TE12xP T1/E1 card Driver - * - * Written by Michael Spiceland <mspiceland@digium.com> - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer <markster@digium.com> - * Matthew Fredrickson <creslin@digium.com> - * William Meadows <wmeadows@digium.com> - * - * Copyright (C) 2007, Digium, Inc. - * - * All rights reserved. - * - */ - -/* - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2 as published by the - * Free Software Foundation. See the LICENSE file included with - * this program for more details. - */ - -#ifndef _VPM150M_H -#define _VPM150M_H - -#include "wcte12xp.h" -#include "adt_lec.h" - -struct t1_firmware { - const struct firmware *fw; - unsigned int offset; -}; - -/* Host and DSP system dependent related definitions. */ -#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ -//#define MAX_CONFS 1 /* maximum number of conferences */ -//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ -#define MAX_CHANNELS 32 /* maximum number of channels */ -#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ -#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ -#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ -//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ -typedef unsigned short DSP_WORD; /* 16 bit DSP word */ -typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ -typedef struct t1_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ - -#define __VPM150M_RWPAGE (1 << 4) -#define __VPM150M_RD (1 << 3) -#define __VPM150M_WR (1 << 2) -#define __VPM150M_FIN (1 << 1) -#define __VPM150M_TX (1 << 0) - -#define VPM150M_HPI_CONTROL 0x00 -#define VPM150M_HPI_ADDRESS 0x02 -#define VPM150M_HPI_DATA 0x03 - -#define VPM150M_MAX_COMMANDS 8 - -/* Some Bit ops for different operations */ -#define VPM150M_SPIRESET 0 -#define VPM150M_HPIRESET 1 -#define VPM150M_SWRESET 2 -#define VPM150M_DTMFDETECT 3 -#define VPM150M_ACTIVE 4 -#define VPM150M_MAX_DATA 1 - -struct vpm150m_cmd { - unsigned short address; - unsigned short data[VPM150M_MAX_DATA]; - unsigned char ident; - unsigned char datalen; - unsigned int flags; - unsigned char cs_slot; -}; - -struct vpm150m { - unsigned short dspid; - unsigned long control; - unsigned char curpage; - unsigned short version; - struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; - spinlock_t lock; /* control access to list of bottom half tasks */ - struct semaphore sem; - struct workqueue_struct *wq; - struct work_struct work_dtmf; - struct work_struct work_debug; - struct work_struct work_echocan; - struct list_head worklist; - unsigned char curtone[32]; - unsigned long curdtmfmutestate; - unsigned long desireddtmfmutestate; - struct adt_lec_params chan_params[32]; - struct t1 *wc; -}; - -/* linked list for vpm echocan workqueue*/ -struct vpm150m_workentry { - struct list_head list; - struct t1 *wc; /* what card are we dealing with? */ - struct dahdi_chan *chan; /* what channels are we going to deal with? */ - struct adt_lec_params params; /* how should we behave? */ -}; - -extern int debug; -extern int vpmsupport; -extern int vpmdtmfsupport; -extern struct pci_driver te12xp_driver; -extern struct t1 *ifaces[WC_MAX_IFACES]; -extern int vpmnlptype; -extern int vpmnlpthresh; -extern int vpmnlpmaxsupp; - -void t1_vpm150m_init(struct t1 *wc); -void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe); -void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk); -int vpm150m_config_hw(struct t1 *wc); - -/* gpak API functions */ -void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ); -void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ); -void gpakHostDelay(void); -void gpakLockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); -void gpakUnlockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); -int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ); - -#endif diff --git a/drivers/dahdi/wcte12xp/wcte12xp.h b/drivers/dahdi/wcte12xp/wcte12xp.h index 655ac30..a93df54 100644 --- a/drivers/dahdi/wcte12xp/wcte12xp.h +++ b/drivers/dahdi/wcte12xp/wcte12xp.h @@ -8,7 +8,7 @@ * Matthew Fredrickson <creslin@digium.com> * William Meadows <wmeadows@digium.com> * - * Copyright (C) 2007, Digium, Inc. + * Copyright (C) 2007-2009, Digium, Inc. * * All rights reserved. * @@ -130,13 +130,11 @@ struct t1 { unsigned long ctlreg; struct voicebus* vb; atomic_t txints; -#ifdef VPM_SUPPORT - int vpm; - struct vpm150m *vpm150m; + int vpm100; + struct vpmadt032 *vpmadt032; unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; -#endif spinlock_t cmd_list_lock; struct list_head pending_cmds; |