From 0eab8786edae3a7cc06d9f37793aefb712358cd3 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Wed, 29 Apr 2009 17:48:39 +0000 Subject: voicebus: Move common vpmadt032 interface into voicebus module. The voicebus library was previously linked into both the wcte12xp and wctdm24xxp drivers. It is now broken out into it's own module and the common parts of the vpmadt032 interface are now located in that module to reduce duplication between the wcte12xp and wctdm24xxp drivers. git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@6527 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- Makefile | 10 +- drivers/dahdi/Kbuild | 27 + drivers/dahdi/Kconfig | 19 +- drivers/dahdi/adt_lec.c | 5 +- drivers/dahdi/firmware/Makefile | 37 +- drivers/dahdi/voicebus.c | 1477 ------------------ drivers/dahdi/voicebus.h | 55 - drivers/dahdi/voicebus/GpakApi.c | 1590 +++++++++++++++++++ drivers/dahdi/voicebus/GpakApi.h | 623 ++++++++ drivers/dahdi/voicebus/GpakCust.c | 682 ++++++++ drivers/dahdi/voicebus/GpakCust.h | 257 +++ drivers/dahdi/voicebus/GpakHpi.h | 79 + drivers/dahdi/voicebus/Kbuild | 5 + drivers/dahdi/voicebus/gpakErrs.h | 154 ++ drivers/dahdi/voicebus/gpakenum.h | 191 +++ drivers/dahdi/voicebus/voicebus.c | 1628 +++++++++++++++++++ drivers/dahdi/voicebus/voicebus.h | 61 + drivers/dahdi/voicebus/vpmadtreg.c | 29 + drivers/dahdi/voicebus/vpmadtreg.h | 36 + .../vpmadt032_loader/dahdi_vpmadt032_loader.c | 154 ++ drivers/dahdi/wctdm24xxp/GpakApi.c | 1630 -------------------- drivers/dahdi/wctdm24xxp/GpakApi.h | 636 -------- drivers/dahdi/wctdm24xxp/GpakCust.c | 482 ------ drivers/dahdi/wctdm24xxp/GpakCust.h | 180 --- drivers/dahdi/wctdm24xxp/GpakHpi.h | 79 - drivers/dahdi/wctdm24xxp/Kbuild | 15 +- drivers/dahdi/wctdm24xxp/base.c | 1274 ++++++--------- drivers/dahdi/wctdm24xxp/gpakErrs.h | 154 -- drivers/dahdi/wctdm24xxp/gpakenum.h | 191 --- drivers/dahdi/wctdm24xxp/voicebus.c | 1 - drivers/dahdi/wctdm24xxp/wctdm24xxp.h | 60 +- drivers/dahdi/wcte12xp/GpakApi.c | 1615 ------------------- drivers/dahdi/wcte12xp/GpakApi.h | 636 -------- drivers/dahdi/wcte12xp/GpakErrs.h | 155 -- drivers/dahdi/wcte12xp/Kbuild | 15 +- drivers/dahdi/wcte12xp/base.c | 528 +++++-- drivers/dahdi/wcte12xp/gpakenum.h | 190 --- drivers/dahdi/wcte12xp/voicebus.c | 1 - drivers/dahdi/wcte12xp/vpmadt032.c | 1317 ---------------- drivers/dahdi/wcte12xp/vpmadt032.h | 151 -- drivers/dahdi/wcte12xp/wcte12xp.h | 8 +- 41 files changed, 6440 insertions(+), 9997 deletions(-) delete mode 100644 drivers/dahdi/voicebus.c delete mode 100644 drivers/dahdi/voicebus.h create mode 100644 drivers/dahdi/voicebus/GpakApi.c create mode 100644 drivers/dahdi/voicebus/GpakApi.h create mode 100644 drivers/dahdi/voicebus/GpakCust.c create mode 100644 drivers/dahdi/voicebus/GpakCust.h create mode 100644 drivers/dahdi/voicebus/GpakHpi.h create mode 100644 drivers/dahdi/voicebus/Kbuild create mode 100644 drivers/dahdi/voicebus/gpakErrs.h create mode 100644 drivers/dahdi/voicebus/gpakenum.h create mode 100644 drivers/dahdi/voicebus/voicebus.c create mode 100644 drivers/dahdi/voicebus/voicebus.h create mode 100644 drivers/dahdi/voicebus/vpmadtreg.c create mode 100644 drivers/dahdi/voicebus/vpmadtreg.h create mode 100644 drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c delete mode 100644 drivers/dahdi/wctdm24xxp/GpakApi.c delete mode 100644 drivers/dahdi/wctdm24xxp/GpakApi.h delete mode 100644 drivers/dahdi/wctdm24xxp/GpakCust.c delete mode 100644 drivers/dahdi/wctdm24xxp/GpakCust.h delete mode 100644 drivers/dahdi/wctdm24xxp/GpakHpi.h delete mode 100644 drivers/dahdi/wctdm24xxp/gpakErrs.h delete mode 100644 drivers/dahdi/wctdm24xxp/gpakenum.h delete mode 120000 drivers/dahdi/wctdm24xxp/voicebus.c delete mode 100644 drivers/dahdi/wcte12xp/GpakApi.c delete mode 100644 drivers/dahdi/wcte12xp/GpakApi.h delete mode 100644 drivers/dahdi/wcte12xp/GpakErrs.h delete mode 100644 drivers/dahdi/wcte12xp/gpakenum.h delete mode 120000 drivers/dahdi/wcte12xp/voicebus.c delete mode 100644 drivers/dahdi/wcte12xp/vpmadt032.c delete mode 100644 drivers/dahdi/wcte12xp/vpmadt032.h diff --git a/Makefile b/Makefile index 5a7dbdc..7a2be68 100644 --- a/Makefile +++ b/Makefile @@ -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 * @@ -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 # @@ -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--- or dahdi-fw-- # 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/voicebus.c b/drivers/dahdi/voicebus.c deleted file mode 100644 index c67be25..0000000 --- a/drivers/dahdi/voicebus.c +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * VoiceBus(tm) Interface Library. - * - * Written by Shaun Ruffell - * and based on previous work by Mark Spencer , - * Matthew Fredrickson , and - * Michael Spiceland - * - * Copyright (C) 2007-2009 Digium, Inc. - * - * All rights reserved. - - * VoiceBus is a registered trademark of Digium. - * - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include - -#include "voicebus.h" - -#define assert(__x__) BUG_ON(!(__x__)) - -#define INTERRUPT 0 /* Run the deferred processing in the ISR. */ -#define TASKLET 1 /* Run in a tasklet. */ -#define TIMER 2 /* Run in a system timer. */ -#define WORKQUEUE 3 /* Run in a workqueue. */ -#ifndef VOICEBUS_DEFERRED -#define VOICEBUS_DEFERRED INTERRUPT -#endif -#if VOICEBUS_DEFERRED == WORKQUEUE -#define VOICEBUS_ALLOC_FLAGS GFP_KERNEL -#else -#define VOICEBUS_ALLOC_FLAGS GFP_ATOMIC -#endif - -#if VOICEBUS_DEFERRED == TIMER -#if HZ < 1000 -/* \todo Put an error message here. */ -#endif -#endif - -/*! The number of descriptors in both the tx and rx descriptor ring. */ -#define DRING_SIZE (1 << 5) /* Must be a power of 2 */ -#define DRING_MASK (DRING_SIZE-1) - -/* Interrupt status' reported in SR_CSR5 */ -#define TX_COMPLETE_INTERRUPT 0x00000001 -#define TX_STOPPED_INTERRUPT 0x00000002 -#define TX_UNAVAILABLE_INTERRUPT 0x00000004 -#define TX_JABBER_TIMEOUT_INTERRUPT 0x00000008 -#define TX_UNDERFLOW_INTERRUPT 0x00000020 -#define RX_COMPLETE_INTERRUPT 0x00000040 -#define RX_UNAVAILABLE_INTERRUPT 0x00000080 -#define RX_STOPPED_INTERRUPT 0x00000100 -#define RX_WATCHDOG_TIMEOUT_INTERRUPT 0x00000200 -#define TIMER_INTERRUPT 0x00000800 -#define FATAL_BUS_ERROR_INTERRUPT 0x00002000 -#define ABNORMAL_INTERRUPT_SUMMARY 0x00008000 -#define NORMAL_INTERRUPT_SUMMARY 0x00010000 - -#define SR_CSR5 0x0028 -#define NAR_CSR6 0x0030 - -#define IER_CSR7 0x0038 -#define CSR7_TCIE 0x00000001 /* tx complete */ -#define CSR7_TPSIE 0x00000002 /* tx processor stopped */ -#define CSR7_TDUIE 0x00000004 /* tx desc unavailable */ -#define CSR7_TUIE 0x00000020 /* tx underflow */ -#define CSR7_RCIE 0x00000040 /* rx complete */ -#define CSR7_RUIE 0x00000080 /* rx desc unavailable */ -#define CSR7_RSIE 0x00000100 /* rx processor stopped */ -#define CSR7_FBEIE 0x00002000 /* fatal bus error */ -#define CSR7_AIE 0x00008000 /* abnormal enable */ -#define CSR7_NIE 0x00010000 /* normal enable */ - -#define DEFAULT_INTERRUPTS (CSR7_TCIE | CSR7_TPSIE | CSR7_TDUIE | \ - CSR7_RUIE | CSR7_RSIE | CSR7_FBEIE | \ - CSR7_AIE | CSR7_NIE) - -#define CSR9 0x0048 -#define CSR9_MDC 0x00010000 -#define CSR9_MDO 0x00020000 -#define CSR9_MMC 0x00040000 -#define CSR9_MDI 0x00080000 - -#define OWN_BIT (1 << 31) - -/* In memory structure shared by the host and the adapter. */ -struct voicebus_descriptor { - u32 des0; - u32 des1; - u32 buffer1; - u32 container; /* Unused */ -} __attribute__((packed)); - -struct voicebus_descriptor_list { - /* Pointer to an array of descriptors to give to hardware. */ - struct voicebus_descriptor *desc; - /* Read completed buffers from the head. */ - unsigned int head; - /* Write ready buffers to the tail. */ - unsigned int tail; - /* Array to save the kernel virtual address of pending buffers. */ - void *pending[DRING_SIZE]; - /* PCI Bus address of the descriptor list. */ - dma_addr_t desc_dma; - /*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */ - unsigned int direction; - /*! The number of buffers currently submitted to the hardware. */ - atomic_t count; - /*! The number of bytes to pad each descriptor for cache alignment. */ - unsigned int padding; -}; - - -/*! * \brief Represents a VoiceBus interface on a Digium telephony card. - */ -struct voicebus { - /*! Name of this card. */ - const char *board_name; - /*! The system pci device for this VoiceBus interface. */ - struct pci_dev *pdev; - /*! Protects access to card registers and this structure. You should - * hold this lock before accessing most of the members of this data - * structure or the card registers. */ - spinlock_t lock; - /*! The size of the transmit and receive buffers for this card. */ - u32 framesize; - /*! The number of u32s in the host system cache line. */ - u8 cache_line_size; - /*! Pool to allocate memory for the tx and rx descriptor rings. */ - struct voicebus_descriptor_list rxd; - struct voicebus_descriptor_list txd; - /*! Level of debugging information. 0=None, 5=Insane. */ - atomic_t debuglevel; - /*! Cache of buffer objects. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - kmem_cache_t *buffer_cache; -#else - struct kmem_cache *buffer_cache; -#endif - /*! Base address of the VoiceBus interface registers in I/O space. */ - u32 iobase; - /*! The IRQ line for this VoiceBus interface. */ - unsigned int irq; -#if VOICEBUS_DEFERRED == WORKQUEUE - /*! Process buffers in the context of this workqueue. */ - struct workqueue_struct *workqueue; - /*! Work item to process tx / rx buffers. */ - struct work_struct workitem; -#elif VOICEBUS_DEFERRED == TASKLET - /*! Process buffers in the context of a tasklet. */ - struct tasklet_struct tasklet; -#elif VOICEBUS_DEFERRED == TIMER - /*! Process buffers in a timer without generating interrupts. */ - struct timer_list timer; -#endif - /*! Callback function to board specific module to process frames. */ - void (*handle_receive)(void *vbb, void *context); - void (*handle_transmit)(void *vbb, void *context); - /*! Data to pass to the receive and transmit callback. */ - void *context; - struct completion stopped_completion; - /*! Flags */ - unsigned long flags; - /* \todo see about removing this... */ - u32 sdi; - /*! Number of tx buffers to queue up before enabling interrupts. */ - unsigned int min_tx_buffer_count; -}; - -/* - * Use the following macros to lock the VoiceBus interface, and it won't - * matter if the deferred processing is running inside the interrupt handler, - * in a tasklet, or in a workqueue. - */ -#if VOICEBUS_DEFERRED == WORKQUEUE -/* - * When the deferred processing is running in a workqueue, voicebus will never - * be locked from the context of the interrupt handler, and therefore we do - * not need to lock interrupts. - */ -#define LOCKS_VOICEBUS -#define LOCKS_FROM_DEFERRED -#define VBLOCK(_vb_) spin_lock(&((_vb_)->lock)) -#define VBUNLOCK(_vb_) spin_unlock(&((_vb_)->lock)) -#define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) -#define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) -#else -#define LOCKS_VOICEBUS unsigned long _irqflags -#define LOCKS_FROM_DEFERRED -#define VBLOCK(_vb_) spin_lock_irqsave(&((_vb_)->lock), _irqflags) -#define VBUNLOCK(_vb_) spin_unlock_irqrestore(&((_vb_)->lock), _irqflags) -#define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) -#define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) -#endif - -#define VB_PRINTK(_vb, _lvl, _fmt, _args...) \ - printk(KERN_##_lvl "%s: " _fmt, (_vb)->board_name, ## _args) - -/* Bit definitions for struct voicebus.flags */ -#define TX_UNDERRUN 1 -#define RX_UNDERRUN 2 -#define IN_DEFERRED_PROCESSING 3 -#define STOP 4 -#define STOPPED 5 - -#if VOICEBUS_DEFERRED == WORKQUEUE -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -/*! \brief Make the current task real-time. */ -static void -vb_setup_deferred(void *data) -#else -static void -vb_setup_deferred(struct work_struct *work) -#endif -{ - struct sched_param param = { .sched_priority = 99 }; - sched_setscheduler(current, SCHED_FIFO, ¶m); -} -/*! \brief Schedule a work item to make the voicebus workqueue real-time. */ -static void -vb_set_workqueue_priority(struct voicebus *vb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - DECLARE_WORK(deferred_setup, vb_setup_deferred, NULL); -#else - DECLARE_WORK(deferred_setup, vb_setup_deferred); -#endif - queue_work(vb->workqueue, &deferred_setup); - flush_workqueue(vb->workqueue); -} -#endif -#endif - -#ifdef DBG -static inline int -assert_in_vb_deferred(struct voicebus *vb) -{ - assert(test_bit(IN_DEFERRED_PROCESSING, &vb->flags)); -} - -static inline void -start_vb_deferred(struct voicebus *vb) -{ - set_bit(IN_DEFERRED_PROCESSING, &vb->flags); -} - -static inline void -stop_vb_deferred(struct voicebus *vb) -{ - clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); -} -#else -#define assert_in_vb_deferred(_x_) do {; } while (0) -#define start_vb_deferred(_x_) do {; } while (0) -#define stop_vb_deferred(_x_) do {; } while (0) -#endif - -static inline struct voicebus_descriptor * -vb_descriptor(struct voicebus_descriptor_list *dl, int index) -{ - struct voicebus_descriptor *d; - d = (struct voicebus_descriptor *)((u8*)dl->desc + - ((sizeof(*d) + dl->padding) * index)); - return d; -} - -static int -vb_initialize_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl, - u32 des1, unsigned int direction) -{ - int i; - struct voicebus_descriptor *d; - const u32 END_OF_RING = 0x02000000; - - assert(dl); - - /* - * Add some padding to each descriptor to ensure that they are - * aligned on host system cache-line boundaries, but only for the - * cache-line sizes that we support. - * - */ - if ((0x08 == vb->cache_line_size) || (0x10 == vb->cache_line_size) || - (0x20 == vb->cache_line_size)) { - dl->padding = (vb->cache_line_size*sizeof(u32)) - sizeof(*d); - } else { - dl->padding = 0; - } - - dl->desc = pci_alloc_consistent(vb->pdev, - (sizeof(*d) + dl->padding) * DRING_SIZE, &dl->desc_dma); - if (!dl->desc) - return -ENOMEM; - - memset(dl->desc, 0, (sizeof(*d) + dl->padding) * DRING_SIZE); - for (i = 0; i < DRING_SIZE; ++i) { - d = vb_descriptor(dl, i); - d->des1 = des1; - } - d->des1 |= cpu_to_le32(END_OF_RING); - dl->direction = direction; - atomic_set(&dl->count, 0); - return 0; -} - -static int -vb_initialize_tx_descriptors(struct voicebus *vb) -{ - return vb_initialize_descriptors( - vb, &vb->txd, 0xe4800000 | vb->framesize, DMA_TO_DEVICE); -} - -static int -vb_initialize_rx_descriptors(struct voicebus *vb) -{ - return vb_initialize_descriptors( - vb, &vb->rxd, vb->framesize, DMA_FROM_DEVICE); -} - -/*! \brief Use to set the minimum number of buffers queued to the hardware - * before enabling interrupts. - */ -int -voicebus_set_minlatency(struct voicebus *vb, unsigned int ms) -{ - LOCKS_VOICEBUS; - /* - * One millisecond of latency means that we have 3 buffers pending, - * since two are always going to be waiting in the TX fifo on the - * interface chip. - * - */ -#define MESSAGE "%d ms is an invalid value for minumum latency. Setting to %d ms.\n" - if (DRING_SIZE < ms) { - VB_PRINTK(vb, WARNING, MESSAGE, ms, DRING_SIZE); - return -EINVAL; - } else if (VOICEBUS_DEFAULT_LATENCY > ms) { - VB_PRINTK(vb, WARNING, MESSAGE, ms, VOICEBUS_DEFAULT_LATENCY); - return -EINVAL; - } - VBLOCK(vb); - vb->min_tx_buffer_count = ms; - VBUNLOCK(vb); - return 0; -} - -/*! \brief Returns the number of buffers currently on the transmit queue. */ -int -voicebus_current_latency(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - int latency; - VBLOCK(vb); - latency = vb->min_tx_buffer_count; - VBUNLOCK(vb); - return latency; -} - -/*! - * \brief Read one of the hardware control registers without acquiring locks. - */ -static inline u32 -__vb_getctl(struct voicebus *vb, u32 addr) -{ - return le32_to_cpu(inl(vb->iobase + addr)); -} - -/*! - * \brief Read one of the hardware control registers with locks held. - */ -static inline u32 -vb_getctl(struct voicebus *vb, u32 addr) -{ - LOCKS_VOICEBUS; - u32 val; - VBLOCK(vb); - val = __vb_getctl(vb, addr); - VBUNLOCK(vb); - return val; -} - -/*! - * \brief Returns whether or not the interface is running. - * - * NOTE: Running in this case means whether or not the hardware reports the - * transmit processor in any state but stopped. - * - * \return 1 of the process is stopped, 0 if running. - */ -static int -vb_is_stopped(struct voicebus *vb) -{ - u32 reg; - reg = vb_getctl(vb, SR_CSR5); - reg = (reg >> 17) & 0x38; - return (0 == reg) ? 1 : 0; -} - -static void -vb_cleanup_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) -{ - unsigned int i; - struct voicebus_descriptor *d; - - assert(vb_is_stopped(vb)); - - for (i = 0; i < DRING_SIZE; ++i) { - d = vb_descriptor(dl, i); - if (d->buffer1) { - d->buffer1 = 0; - assert(dl->pending[i]); - voicebus_free(vb, dl->pending[i]); - dl->pending[i] = NULL; - } - d->des0 &= ~OWN_BIT; - } - dl->head = 0; - dl->tail = 0; - atomic_set(&dl->count, 0); -} - -static void -vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) -{ - if (NULL == dl->desc) { - WARN_ON(1); - return; - } - vb_cleanup_descriptors(vb, dl); - pci_free_consistent( - vb->pdev, - (sizeof(struct voicebus_descriptor)+dl->padding)*DRING_SIZE, - dl->desc, dl->desc_dma); -} - -/*! - * \brief Write one of the hardware control registers without acquiring locks. - */ -static inline void -__vb_setctl(struct voicebus *vb, u32 addr, u32 val) -{ - wmb(); - outl(cpu_to_le32(val), vb->iobase + addr); -} - -/*! - * \brief Write one of the hardware control registers with locks held. - */ -static inline void -vb_setctl(struct voicebus *vb, u32 addr, u32 val) -{ - LOCKS_VOICEBUS; - VBLOCK(vb); - __vb_setctl(vb, addr, val); - VBUNLOCK(vb); -} - -static int -__vb_sdi_clk(struct voicebus *vb) -{ - unsigned int ret; - vb->sdi &= ~CSR9_MDC; - __vb_setctl(vb, 0x0048, vb->sdi); - ret = __vb_getctl(vb, 0x0048); - vb->sdi |= CSR9_MDC; - __vb_setctl(vb, 0x0048, vb->sdi); - return (ret & CSR9_MDI) ? 1 : 0; -} - -static void -__vb_sdi_sendbits(struct voicebus *vb, u32 bits, int count) -{ - vb->sdi &= ~CSR9_MMC; - __vb_setctl(vb, 0x0048, vb->sdi); - while (count--) { - - if (bits & (1 << count)) - vb->sdi |= CSR9_MDO; - else - vb->sdi &= ~CSR9_MDO; - - __vb_sdi_clk(vb); - } -} - -static void -vb_setsdi(struct voicebus *vb, int addr, u16 val) -{ - LOCKS_VOICEBUS; - u32 bits; - /* Send preamble */ - bits = 0xffffffff; - VBLOCK(vb); - __vb_sdi_sendbits(vb, bits, 32); - bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; - __vb_sdi_sendbits(vb, bits, 16); - __vb_sdi_sendbits(vb, val, 16); - VBUNLOCK(vb); -} - -static void -vb_enable_io_access(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - u32 reg; - assert(vb->pdev); - VBLOCK(vb); - pci_read_config_dword(vb->pdev, 0x0004, ®); - reg |= 0x00000007; - pci_write_config_dword(vb->pdev, 0x0004, reg); - VBUNLOCK(vb); -} - -/*! \todo Insert comments... - * context: !in_interrupt() - */ -void* -voicebus_alloc(struct voicebus *vb) -{ - void *vbb; - vbb = kmem_cache_alloc(vb->buffer_cache, VOICEBUS_ALLOC_FLAGS); - return vbb; -} - -void -voicebus_setdebuglevel(struct voicebus *vb, u32 level) -{ - atomic_set(&vb->debuglevel, level); -} - -int -voicebus_getdebuglevel(struct voicebus *vb) -{ - return atomic_read(&vb->debuglevel); -} - -/*! \brief Resets the voicebus hardware interface. */ -static int -vb_reset_interface(struct voicebus *vb) -{ - unsigned long timeout; - u32 reg; - u32 pci_access; - const u32 DEFAULT_PCI_ACCESS = 0xfff80002; - BUG_ON(in_interrupt()); - - switch (vb->cache_line_size) { - case 0x08: - pci_access = DEFAULT_PCI_ACCESS | (0x1 << 14); - break; - case 0x10: - pci_access = DEFAULT_PCI_ACCESS | (0x2 << 14); - break; - case 0x20: - pci_access = DEFAULT_PCI_ACCESS | (0x3 << 14); - break; - default: - if (atomic_read(&vb->debuglevel)) - VB_PRINTK(vb, WARNING, "Host system set a cache size "\ - "of %d which is not supported. " \ - "Disabling memory write line and memory read line.\n", - vb->cache_line_size); - pci_access = 0xfe584202; - break; - } - - /* The transmit and receive descriptors will have the same padding. */ - pci_access |= ((vb->txd.padding / sizeof(u32)) << 2) & 0x7c; - - vb_setctl(vb, 0x0000, pci_access | 1); - - timeout = jiffies + HZ/10; /* 100ms interval */ - do { - reg = vb_getctl(vb, 0x0000); - } while ((reg & 0x00000001) && time_before(jiffies, timeout)); - - if (reg & 0x00000001) { - VB_PRINTK(vb, ERR, "Hardware did not come out of reset "\ - "within 100ms!"); - return -EIO; - } - - vb_setctl(vb, 0x0000, pci_access); - - return 0; -} - -static int -vb_initialize_interface(struct voicebus *vb) -{ - u32 reg; - - vb_cleanup_descriptors(vb, &vb->txd); - vb_cleanup_descriptors(vb, &vb->rxd); - - /* Pass bad packets, runt packets, disable SQE function, - * store-and-forward */ - vb_setctl(vb, 0x0030, 0x00280048); - /* ...disable jabber and the receive watchdog. */ - vb_setctl(vb, 0x0078, 0x00000013); - - /* Tell the card where the descriptors are in host memory. */ - vb_setctl(vb, 0x0020, (u32)vb->txd.desc_dma); - vb_setctl(vb, 0x0018, (u32)vb->rxd.desc_dma); - - reg = vb_getctl(vb, 0x00fc); - vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x7); - vb_setsdi(vb, 0x00, 0x0100); - vb_setsdi(vb, 0x16, 0x2100); - - reg = vb_getctl(vb, 0x00fc); - - vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x4); - vb_setsdi(vb, 0x00, 0x0100); - vb_setsdi(vb, 0x16, 0x2100); - reg = vb_getctl(vb, 0x00fc); - - /* - * The calls to setsdi above toggle the reset line of the CPLD. Wait - * here to give the CPLD time to stabilize after reset. - */ - msleep(10); - - return ((reg&0x7) == 0x4) ? 0 : -EIO; -} - -#define OWNED(_d_) (((_d_)->des0)&OWN_BIT) -#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb(); } while (0) - -#ifdef DBG -static void -dump_descriptor(struct voicebus *vb, volatile struct voicebus_descriptor *d) -{ - VB_PRINTK(vb, DEBUG, "Displaying descriptor at address %08x\n", (unsigned int)d); - VB_PRINTK(vb, DEBUG, " des0: %08x\n", d->des0); - VB_PRINTK(vb, DEBUG, " des1: %08x\n", d->des1); - VB_PRINTK(vb, DEBUG, " buffer1: %08x\n", d->buffer1); - VB_PRINTK(vb, DEBUG, " container: %08x\n", d->container); -} - -static void -show_buffer(struct voicebus *vb, void *vbb) -{ - int x; - unsigned char *c; - c = vbb; - printk(KERN_DEBUG "Packet %d\n", count); - printk(KERN_DEBUG ""); - for (x = 1; x <= vb->framesize; ++x) { - printk("%02x ", c[x]); - if (x % 16 == 0) - printk("\n"); - } - printk(KERN_DEBUG "\n\n"); -} -#endif - -static inline int -vb_submit(struct voicebus *vb, struct voicebus_descriptor_list *dl, void *vbb) -{ - volatile struct voicebus_descriptor *d; - unsigned int tail = dl->tail; - assert_in_vb_deferred(vb); - - d = vb_descriptor(dl, tail); - - if (unlikely(d->buffer1)) { - /* Do not overwrite a buffer that is still in progress. */ - WARN_ON(1); - voicebus_free(vb, vbb); - return -EBUSY; - } - - dl->pending[tail] = vbb; - dl->tail = (++tail) & DRING_MASK; - d->buffer1 = dma_map_single( - &vb->pdev->dev, vbb, vb->framesize, dl->direction); - SET_OWNED(d); /* That's it until the hardware is done with it. */ - atomic_inc(&dl->count); - return 0; -} - -static inline void* -vb_retrieve(struct voicebus *vb, struct voicebus_descriptor_list *dl) -{ - volatile struct voicebus_descriptor *d; - void *vbb; - unsigned int head = dl->head; - assert_in_vb_deferred(vb); - d = vb_descriptor(dl, head); - if (d->buffer1 && !OWNED(d)) { - dma_unmap_single(&vb->pdev->dev, d->buffer1, - vb->framesize, dl->direction); - vbb = dl->pending[head]; - dl->head = (++head) & DRING_MASK; - d->buffer1 = 0; - atomic_dec(&dl->count); - return vbb; - } else { - return NULL; - } -} - -/*! - * \brief Give a frame to the hardware to transmit. - * - */ -int -voicebus_transmit(struct voicebus *vb, void *vbb) -{ - return vb_submit(vb, &vb->txd, vbb); -} - -/*! - * \brief Give a frame to the hardware to use for receiving. - * - */ -static inline int -vb_submit_rxb(struct voicebus *vb, void *vbb) -{ - return vb_submit(vb, &vb->rxd, vbb); -} - -/*! - * \brief Remove the next completed transmit buffer (txb) from the tx - * descriptor ring. - * - * NOTE: This function doesn't need any locking because only one instance is - * ever running on the deferred processing routine and it only looks at - * the head pointer. The deferred routine should only ever be running - * on one processor at a time (no multithreaded workqueues allowed!) - * - * Context: Must be called from the voicebus deferred workqueue. - * - * \return Pointer to buffer, or NULL if not available. - */ -static inline void * -vb_get_completed_txb(struct voicebus *vb) -{ - return vb_retrieve(vb, &vb->txd); -} - -static inline void * -vb_get_completed_rxb(struct voicebus *vb) -{ - return vb_retrieve(vb, &vb->rxd); -} - -/*! - * \brief Free a buffer for reuse. - * - */ -void -voicebus_free(struct voicebus *vb, void *vbb) -{ - kmem_cache_free(vb->buffer_cache, vbb); -} - -/*! - * \brief Instruct the hardware to check for a new tx descriptor. - */ -static inline void -__vb_tx_demand_poll(struct voicebus *vb) -{ - __vb_setctl(vb, 0x0008, 0x00000000); -} - -/*! - * \brief Command the hardware to check if it owns the next transmit - * descriptor. - */ -static void -vb_tx_demand_poll(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - VBLOCK(vb); - __vb_tx_demand_poll(vb); - VBUNLOCK(vb); -} - -/*! - * \brief Command the hardware to check if it owns the next receive - * descriptor. - */ -static inline void -__vb_rx_demand_poll(struct voicebus *vb) -{ - __vb_setctl(vb, 0x0010, 0x00000000); -} - -static void -vb_rx_demand_poll(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - VBLOCK(vb); - __vb_rx_demand_poll(vb); - VBUNLOCK(vb); -} - -static void -__vb_enable_interrupts(struct voicebus *vb) -{ - __vb_setctl(vb, IER_CSR7, DEFAULT_INTERRUPTS); -} - -static void -__vb_disable_interrupts(struct voicebus *vb) -{ - __vb_setctl(vb, IER_CSR7, 0); -} - -static void -vb_disable_interrupts(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - VBLOCK(vb); - __vb_disable_interrupts(vb); - VBUNLOCK(vb); -} - -/*! - * \brief Starts the VoiceBus interface. - * - * When the VoiceBus interface is started, it is actively transferring - * frames to and from the backend of the card. This means the card will - * generate interrupts. - * - * This function should only be called from process context, with interrupts - * enabled, since it can sleep while running the self checks. - * - * \return zero on success. -EBUSY if device is already running. - */ -int -voicebus_start(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - u32 reg; - int i; - void *vbb; - int ret; - - assert(!in_interrupt()); - - if (!vb_is_stopped(vb)) - return -EBUSY; - - ret = vb_reset_interface(vb); - if (ret) - return ret; - ret = vb_initialize_interface(vb); - if (ret) - return ret; - - /* We must set up a minimum of three buffers to start with, since two - * are immediately read into the TX FIFO, and the descriptor of the - * third is read as soon as the first buffer is done. - */ - - /* - * NOTE: handle_transmit is normally only called in the context of the - * deferred processing thread. Since the deferred processing thread - * is known to not be running at this point, it is safe to call the - * handle transmit as if it were. - */ - start_vb_deferred(vb); - /* Ensure that all the rx slots are ready for a buffer. */ - for (i = 0; i < DRING_SIZE; ++i) { - vbb = voicebus_alloc(vb); - if (unlikely(NULL == vbb)) { - BUG_ON(1); - /* \todo I need to make sure the driver can recover - * from this condition. .... */ - } else { - vb_submit_rxb(vb, vbb); - } - } - - for (i = 0; i < vb->min_tx_buffer_count; ++i) { - vbb = voicebus_alloc(vb); - - if (unlikely(NULL == vbb)) - BUG_ON(1); - else - vb->handle_transmit(vbb, vb->context); - - } - stop_vb_deferred(vb); - - VBLOCK(vb); - clear_bit(STOP, &vb->flags); - clear_bit(STOPPED, &vb->flags); -#if VOICEBUS_DEFERRED == TIMER - vb->timer.expires = jiffies + HZ/1000; - add_timer(&vb->timer); -#else - /* Clear the interrupt status register. */ - __vb_setctl(vb, SR_CSR5, 0xffffffff); - __vb_enable_interrupts(vb); -#endif - /* Start the transmit and receive processors. */ - reg = __vb_getctl(vb, 0x0030); - __vb_setctl(vb, 0x0030, reg|0x00002002); - /* Tell the interface to poll the tx and rx descriptors. */ - __vb_rx_demand_poll(vb); - __vb_tx_demand_poll(vb); - VBUNLOCK(vb); - - assert(!vb_is_stopped(vb)); - - return 0; -} - -static void -vb_clear_start_transmit_bit(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - u32 reg; - VBLOCK(vb); - reg = __vb_getctl(vb, NAR_CSR6); - reg &= ~0x00002000; - __vb_setctl(vb, NAR_CSR6, reg); - VBUNLOCK(vb); -} - -static void -vb_clear_start_receive_bit(struct voicebus *vb) -{ - LOCKS_VOICEBUS; - u32 reg; - VBLOCK(vb); - reg = __vb_getctl(vb, NAR_CSR6); - reg &= ~0x00000002; - __vb_setctl(vb, NAR_CSR6, reg); - VBUNLOCK(vb); -} - -static unsigned long -vb_wait_for_completion_timeout(struct completion *x, unsigned long timeout) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) - /* There is a race condition here. If x->done is reset to 0 - * before the call to wait_for_completion after this thread wakes. - */ - timeout = wait_event_timeout(x->wait, x->done, timeout); - if (timeout) - wait_for_completion(x); - - return timeout; -#else - return wait_for_completion_timeout(x, timeout); -#endif -} - -/*! - * \brief Stops the VoiceBus interface. - * - * Stops the VoiceBus interface and waits for any outstanding DMA transactions - * to complete. When this functions returns the VoiceBus interface tx and rx - * states will both be suspended. - * - * Only call this function from process context, with interrupt enabled, - * without any locks held since it sleeps. - * - * \return zero on success, -1 on error. - */ -int -voicebus_stop(struct voicebus *vb) -{ - assert(!in_interrupt()); - - if (vb_is_stopped(vb)) - return 0; - - INIT_COMPLETION(vb->stopped_completion); - set_bit(STOP, &vb->flags); - vb_clear_start_transmit_bit(vb); - vb_clear_start_receive_bit(vb); - if (vb_wait_for_completion_timeout(&vb->stopped_completion, HZ)) { - assert(vb_is_stopped(vb)); - } else { - VB_PRINTK(vb, WARNING, "Timeout while waiting for board to "\ - "stop.\n"); - - - vb_clear_start_transmit_bit(vb); - vb_clear_start_receive_bit(vb); - set_bit(STOPPED, &vb->flags); - vb_disable_interrupts(vb); - } - -#if VOICEBUS_DEFERRED == TIMER - del_timer_sync(&vb->timer); -#endif - - return 0; -} - -/*! - * \brief Prepare the interface for module unload. - * - * Stop the interface and free all the resources allocated by the driver. The - * caller should have returned all VoiceBus buffers to the VoiceBus layer - * before calling this function. - * - * context: !in_interrupt() - */ -void -voicebus_release(struct voicebus *vb) -{ - assert(!in_interrupt()); - - /* quiesce the hardware */ - voicebus_stop(vb); -#if VOICEBUS_DEFERRED == WORKQUEUE - destroy_workqueue(vb->workqueue); -#elif VOICEBUS_DEFERRED == TASKLET - tasklet_kill(&vb->tasklet); -#endif - vb_reset_interface(vb); -#if VOICEBUS_DEFERRED != TIMER - free_irq(vb->pdev->irq, vb); -#endif - - /* Cleanup memory and software resources. */ - vb_free_descriptors(vb, &vb->txd); - vb_free_descriptors(vb, &vb->rxd); - kmem_cache_destroy(vb->buffer_cache); - release_region(vb->iobase, 0xff); - pci_disable_device(vb->pdev); - kfree(vb); -} - -static void -__vb_increase_latency(struct voicebus *vb) -{ - static int __warn_once = 1; - void *vbb; - int latency; - - assert_in_vb_deferred(vb); - - latency = atomic_read(&vb->txd.count); - if (DRING_SIZE == latency) { - if (__warn_once) { - /* We must subtract two from this number since there - * are always two buffers in the TX FIFO. - */ - VB_PRINTK(vb, ERR, - "ERROR: Unable to service card within %d ms "\ - "and unable to further increase latency.\n", - DRING_SIZE-2); - __warn_once = 0; - } - } else { - /* Because there are 2 buffers in the transmit FIFO on the - * hardware, setting 3 ms of latency means that the host needs - * to be able to service the cards within 1ms. This is because - * the interface will load up 2 buffers into the TX FIFO then - * attempt to read the 3rd descriptor. If the OWN bit isn't - * set, then the hardware will set the TX descriptor not - * available interrupt. - */ - VB_PRINTK(vb, INFO, "Missed interrupt. " \ - "Increasing latency to %d ms in order to compensate.\n", - latency+1); - /* Set the minimum latency in case we're restarted...we don't - * want to wait for the buffer to grow to this depth again in - * that case. - */ - voicebus_set_minlatency(vb, latency+1); - vbb = voicebus_alloc(vb); - - if (unlikely(NULL == vbb)) - BUG_ON(1); - else - vb->handle_transmit(vbb, vb->context); - - } -} - -/*! - * \brief Actually process the completed transmit and receive buffers. - * - * NOTE: This function may be called either from a tasklet, workqueue, or - * directly in the interrupt service routine depending on - * VOICEBUS_DEFERRED. - */ -static inline void -vb_deferred(struct voicebus *vb) -{ - void *vbb; -#ifdef DBG - static int count; -#endif - int underrun = test_bit(TX_UNDERRUN, &vb->flags); - - - start_vb_deferred(vb); - if (unlikely(underrun)) { - /* When we've underrun our FIFO, for some reason we're not - * able to keep enough transmit descriptors pending. This can - * happen if either interrupts or this deferred processing - * function is not run soon enough (within 1ms when using the - * default 3 transmit buffers to start). In this case, we'll - * insert an additional transmit buffer onto the descriptor - * list which decreases the sensitivity to latency, but also - * adds more delay to the TDM and SPI data. - */ - __vb_increase_latency(vb); - } - - /* Always handle the transmit buffers first. */ - while ((vbb = vb_get_completed_txb(vb))) - vb->handle_transmit(vbb, vb->context); - - if (unlikely(underrun)) { - vb_rx_demand_poll(vb); - vb_tx_demand_poll(vb); - clear_bit(TX_UNDERRUN, &vb->flags); - } - - while ((vbb = vb_get_completed_rxb(vb))) { - vb->handle_receive(vbb, vb->context); - vb_submit_rxb(vb, vbb); - } - - stop_vb_deferred(vb); -} - - -/*! - * \brief Interrupt handler for VoiceBus interface. - * - * NOTE: This handler is optimized for the case where only a single interrupt - * condition will be generated at a time. - * - * ALSO NOTE: Only access the interrupt status register from this function - * since it doesn't employ any locking on the voicebus interface. - */ -static irqreturn_t -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -vb_isr(int irq, void *dev_id, struct pt_regs *regs) -#else -vb_isr(int irq, void *dev_id) -#endif -{ - struct voicebus *vb = dev_id; - u32 int_status; - - int_status = __vb_getctl(vb, SR_CSR5); - /* Mask out the reserved bits. */ - int_status &= ~(0xfc004010); - int_status &= 0x7fff; - - if (!int_status) - return IRQ_NONE; - - if (likely(int_status & TX_COMPLETE_INTERRUPT)) { - /* ******************************************************** */ - /* NORMAL INTERRUPT CASE */ - /* ******************************************************** */ -# if VOICEBUS_DEFERRED == WORKQUEUE - queue_work(vb->workqueue, &vb->workitem); -# elif VOICEBUS_DEFERRED == TASKLET - tasklet_schedule(&vb->tasklet); -# else - vb_deferred(vb); -# endif - __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT); - } else { - /* ******************************************************** */ - /* ABNORMAL / ERROR CONDITIONS */ - /* ******************************************************** */ - if ((int_status & TX_UNAVAILABLE_INTERRUPT)) { - /* This can happen if the host fails to service the - * interrupt within the required time interval (1ms - * for each buffer on the queue). Increasing the - * depth of the tx queue (up to a maximum of - * DRING_SIZE) can make the driver / system more - * tolerant of interrupt latency under periods of - * heavy system load, but also increases the general - * latency that the driver adds to the voice - * conversations. - */ - set_bit(TX_UNDERRUN, &vb->flags); -# if VOICEBUS_DEFERRED == WORKQUEUE - queue_work(vb->workqueue, &vb->workitem); -# elif VOICEBUS_DEFERRED == TASKLET - tasklet_schedule(&vb->tasklet); -# else - vb_deferred(vb); -# endif - } - - if (int_status & FATAL_BUS_ERROR_INTERRUPT) - VB_PRINTK(vb, ERR, "Fatal Bus Error detected!\n"); - - if (int_status & TX_STOPPED_INTERRUPT) { - assert(test_bit(STOP, &vb->flags)); - __vb_disable_interrupts(vb); - complete(&vb->stopped_completion); - } - if (int_status & RX_STOPPED_INTERRUPT) { - assert(test_bit(STOP, &vb->flags)); - if (vb_is_stopped(vb)) { - __vb_disable_interrupts(vb); - complete(&vb->stopped_completion); - } - } - - /* Clear the interrupt(s) */ - __vb_setctl(vb, SR_CSR5, int_status); - } - - return IRQ_HANDLED; -} - -#if VOICEBUS_DEFERRED == TIMER -/*! \brief Called if the deferred processing is to happen in the context of - * the timer. - */ -static void -vb_timer(unsigned long data) -{ - unsigned long start = jiffies; - struct voicebus *vb = (struct voicebus *)data; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - vb_isr(0, vb, 0); -#else - vb_isr(0, vb); -#endif - if (!test_bit(STOPPED, &vb->flags)) { - vb->timer.expires = start + HZ/1000; - add_timer(&vb->timer); - } -} -#endif - -#if VOICEBUS_DEFERRED == WORKQUEUE -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -vb_workfunc(void *data) -{ - struct voicebus *vb = data; -#else -vb_workfunc(struct work_struct *work) -{ - struct voicebus *vb = container_of(work, struct voicebus, workitem); -#endif - vb_deferred(vb); -} -#elif VOICEBUS_DEFERRED == TASKLET -static void -vb_tasklet(unsigned long data) -{ - struct voicebus *vb = (struct voicebus *)data; - vb_deferred(vb); -} -#endif /* #if VOICEBUS_DEFERRED == WORKQUEUE */ - -/*! - * \brief Initalize the voicebus interface. - * - * This function must be called in process context since it may sleep. - * \todo Complete this description. - */ -int -voicebus_init(struct pci_dev *pdev, u32 framesize, - const char *board_name, - void (*handle_receive)(void *vbb, void *context), - void (*handle_transmit)(void *vbb, void *context), - void *context, - u32 debuglevel, - struct voicebus **vbp - ) -{ - int retval = 0; - struct voicebus *vb; - - assert(NULL != pdev); - assert(NULL != board_name); - assert(framesize); - assert(NULL != handle_receive); - assert(NULL != handle_transmit); - - /* ---------------------------------------------------------------- - Initialize the pure software constructs. - ---------------------------------------------------------------- */ - *vbp = NULL; - vb = kmalloc(sizeof(*vb), GFP_KERNEL); - if (NULL == vb) { - VB_PRINTK(vb, DEBUG, "Failed to allocate memory for voicebus "\ - "interface.\n"); - retval = -ENOMEM; - goto cleanup; - } - memset(vb, 0, sizeof(*vb)); - voicebus_setdebuglevel(vb, debuglevel); - /* \todo make sure there is a note that the caller needs to make sure - * board_name stays in memory until voicebus_release is called. - */ - vb->board_name = board_name; - spin_lock_init(&vb->lock); - init_completion(&vb->stopped_completion); - vb->pdev = pdev; - set_bit(STOP, &vb->flags); - clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); - vb->framesize = framesize; - vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY; - -#if VOICEBUS_DEFERRED == WORKQUEUE - /* NOTE: This workqueue must be single threaded because locking is not - * used when buffers are removed or added to the descriptor list, and - * there should only be one producer / consumer (the hardware or the - * deferred processing function). */ - vb->workqueue = create_singlethread_workqueue(board_name); -# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - INIT_WORK(&vb->workitem, vb_workfunc, vb); -# else - INIT_WORK(&vb->workitem, vb_workfunc); -# endif -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - vb_set_workqueue_priority(vb); -# endif -#elif VOICEBUS_DEFERRED == TASKLET - tasklet_init(&vb->tasklet, vb_tasklet, (unsigned long)vb); -#elif VOICEBUS_DEFERRED == TIMER - init_timer(&vb->timer); - vb->timer.function = vb_timer; - vb->timer.data = (unsigned long)vb; -#endif - - vb->handle_receive = handle_receive; - vb->handle_transmit = handle_transmit; - vb->context = context; - - /* \todo This cache should be shared by all instances supported by - * this driver. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22) - SLAB_HWCACHE_ALIGN | SLAB_STORE_USER, NULL, NULL); -#else - SLAB_HWCACHE_ALIGN, NULL, NULL); -#endif -#else - vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, - SLAB_HWCACHE_ALIGN, NULL); -#endif - if (NULL == vb->buffer_cache) { - VB_PRINTK(vb, ERR, "Failed to allocate buffer cache.\n"); - goto cleanup; - } - - - /* ---------------------------------------------------------------- - Configure the hardware / kernel module interfaces. - ---------------------------------------------------------------- */ - if (pci_read_config_byte(vb->pdev, 0x0c, &vb->cache_line_size)) { - VB_PRINTK(vb, ERR, "Failed read of cache line " \ - "size from PCI configuration space.\n"); - goto cleanup; - } - - if (pci_enable_device(pdev)) { - VB_PRINTK(vb, ERR, "Failed call to pci_enable_device.\n"); - retval = -EIO; - goto cleanup; - } - - /* \todo This driver should be modified to use the memory mapped I/O - as opposed to IO space for portability and performance. */ - if (0 == (pci_resource_flags(pdev, 0)&IORESOURCE_IO)) { - VB_PRINTK(vb, ERR, "BAR0 is not IO Memory.\n"); - retval = -EIO; - goto cleanup; - } - vb->iobase = pci_resource_start(pdev, 0); - if (NULL == request_region(vb->iobase, 0xff, board_name)) { - VB_PRINTK(vb, ERR, "IO Registers are in use by another " \ - "module.\n"); - retval = -EIO; - goto cleanup; - } - - retval = vb_initialize_tx_descriptors(vb); - if (retval) - goto cleanup; - - retval = vb_initialize_rx_descriptors(vb); - if (retval) - goto cleanup; - - /* ---------------------------------------------------------------- - Configure the hardware interface. - ---------------------------------------------------------------- */ - pci_set_master(pdev); - vb_enable_io_access(vb); - -#if VOICEBUS_DEFERRED != TIMER -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) -# define VB_IRQ_SHARED SA_SHIRQ -#else -# define VB_IRQ_SHARED IRQF_SHARED -#endif - if (request_irq(pdev->irq, vb_isr, VB_IRQ_SHARED, vb->board_name, - vb)) { - assert(0); - goto cleanup; - } -#endif - - *vbp = vb; - return retval; -cleanup: - if (NULL == vb) - return retval; - -#if VOICEBUS_DEFERRED == WORKQUEUE - - if (vb->workqueue) - destroy_workqueue(vb->workqueue); - -#elif VOICEBUS_DEFERRED == TASKLET - tasklet_kill(&vb->tasklet); -#endif - /* Cleanup memory and software resources. */ - - if (vb->txd.desc) - vb_free_descriptors(vb, &vb->txd); - - if (vb->rxd.desc) - vb_free_descriptors(vb, &vb->rxd); - - if (vb->buffer_cache) - kmem_cache_destroy(vb->buffer_cache); - - if (vb->iobase) - release_region(vb->iobase, 0xff); - - if (vb->pdev) - pci_disable_device(vb->pdev); - - kfree(vb); - assert(0 != retval); - return retval; -} - - -/*! \brief Return the pci_dev in use by this voicebus interface. */ -struct pci_dev * -voicebus_get_pci_dev(struct voicebus *vb) -{ - return vb->pdev; -} diff --git a/drivers/dahdi/voicebus.h b/drivers/dahdi/voicebus.h deleted file mode 100644 index f3be573..0000000 --- a/drivers/dahdi/voicebus.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * VoiceBus(tm) Interface Library. - * - * Written by Shaun Ruffell - * and based on previous work by Mark Spencer , - * Matthew Fredrickson , and - * Michael Spiceland - * - * Copyright (C) 2007-2008 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 __VOICEBUS_H__ -#define __VOICEBUS_H__ - -struct voicebus; - -#define VOICEBUS_DEFAULT_LATENCY 3 - -void voicebus_setdebuglevel(struct voicebus *vb, u32 level); -int voicebus_getdebuglevel(struct voicebus *vb); -struct pci_dev * voicebus_get_pci_dev(struct voicebus *vb); -int voicebus_init(struct pci_dev* pdev, u32 framesize, - const char *board_name, - void (*handle_receive)(void *buffer, void *context), - void (*handle_transmit)(void *buffer, void *context), - void *context, - u32 debuglevel, - struct voicebus **vb_p); -void voicebus_release(struct voicebus *vb); -int voicebus_start(struct voicebus *vb); -int voicebus_stop(struct voicebus *vb); -void * voicebus_alloc(struct voicebus* vb); -void voicebus_free(struct voicebus *vb, void *vbb); -int voicebus_transmit(struct voicebus *vb, void *vbb); -int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds); -int voicebus_current_latency(struct voicebus *vb) ; - -#endif /* __VOICEBUS_H__ */ diff --git a/drivers/dahdi/voicebus/GpakApi.c b/drivers/dahdi/voicebus/GpakApi.c new file mode 100644 index 0000000..4b480ab --- /dev/null +++ b/drivers/dahdi/voicebus/GpakApi.c @@ -0,0 +1,1590 @@ +/* + * 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 "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]; + + /* 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; + + /* 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) */ + const 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->SerialWordSize2 & 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); +} +EXPORT_SYMBOL(gpakConfigurePorts); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * 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; + + 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; + + + /* 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); +} +EXPORT_SYMBOL(gpakConfigureChannel); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * 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); + +} +EXPORT_SYMBOL(gpakAlgControl); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * 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 */ + + /* 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); + 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) + EventError = 1; + break; + + default: + 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); +} +EXPORT_SYMBOL(gpakPingDsp); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * 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 != 0) + // 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/voicebus/GpakApi.h b/drivers/dahdi/voicebus/GpakApi.h new file mode 100644 index 0000000..91aade0 --- /dev/null +++ b/drivers/dahdi/voicebus/GpakApi.h @@ -0,0 +1,623 @@ +/* + * 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 + */ + +#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 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 + 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 + 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 GpakChannelConfig +{ + 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 GpakPortConfig +{ + 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 + const 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/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 +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else +#include +#endif + +#include +#include + +#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; idspid = 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; isem)) { + 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/voicebus/GpakCust.h b/drivers/dahdi/voicebus/GpakCust.h new file mode 100644 index 0000000..befdabc --- /dev/null +++ b/drivers/dahdi/voicebus/GpakCust.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: GpakCust.h + * + * Description: + * This file contains host system dependent definitions and prototypes of + * functions to support generic G.PAK API functions. The file is used when + * integrating G.PAK API functions in a specific host processor environment. + * + * Note: This file may need 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. + */ + +#ifndef _GPAKCUST_H /* prevent multiple inclusion */ +#define _GPAKCUST_H + +#include +#include +#include + +#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 vpmadt032_cmd { + struct list_head node; + __le32 address; + __le16 data; + u8 desc; + u8 txident; + struct completion complete; +}; + +/* 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. + * + * FUNCTION + * This function reads a contiguous block of words from DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +extern 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 */ + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteDspMemory - Write DSP memory. + * + * FUNCTION + * This function writes a contiguous block of words to DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +extern 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 */ + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * 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 + * + */ +extern void gpakHostDelay(void); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakLockAccess - Lock access to the specified DSP. + * + * FUNCTION + * This function aquires exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +extern void gpakLockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakUnlockAccess - Unlock access to the specified DSP. + * + * FUNCTION + * This function releases exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +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. + * + * 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) + * + */ +extern 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 /* prevent multiple inclusion */ + + diff --git a/drivers/dahdi/voicebus/GpakHpi.h b/drivers/dahdi/voicebus/GpakHpi.h new file mode 100644 index 0000000..ffbf349 --- /dev/null +++ b/drivers/dahdi/voicebus/GpakHpi.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001, Adaptive Digital Technologies, Inc. + * + * File Name: GpakHpi.h + * + * Description: + * This file contains common definitions related to the G.PAK interface + * between a host processor and a DSP processor via the Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - 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 _GPAKHPI_H /* prevent multiple inclusion */ +#define _GPAKHPI_H + + +/* Definition of G.PAK Command/Reply message type codes. */ +#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ +#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ +#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ +#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ +#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ +#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ +#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ +#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ +#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ +#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ +#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ +#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ +#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ +#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ +#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ + +#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ +#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ + +#define MSG_ALG_CONTROL 27 /* algorithm control */ +#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ +#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ +#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ + +#define MSG_PING 35 /* ping command */ +#define MSG_PING_REPLY 36 /* ping command reply */ +#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ +#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ +#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ +#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ +#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ +#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ + +#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ +#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ + +#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ +#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ + +#define MSG_ACCESSGPIO 51 +#define MSG_ACCESSGPIO_REPLY 52 +#endif /* prevent multiple inclusion */ 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/voicebus/gpakErrs.h b/drivers/dahdi/voicebus/gpakErrs.h new file mode 100644 index 0000000..c36a1b7 --- /dev/null +++ b/drivers/dahdi/voicebus/gpakErrs.h @@ -0,0 +1,154 @@ +/* + * 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/voicebus/gpakenum.h b/drivers/dahdi/voicebus/gpakenum.h new file mode 100644 index 0000000..f488a81 --- /dev/null +++ b/drivers/dahdi/voicebus/gpakenum.h @@ -0,0 +1,191 @@ +/* + * 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/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c new file mode 100644 index 0000000..d794365 --- /dev/null +++ b/drivers/dahdi/voicebus/voicebus.c @@ -0,0 +1,1628 @@ +/* + * VoiceBus(tm) Interface Library. + * + * Written by Shaun Ruffell + * and based on previous work by Mark Spencer , + * Matthew Fredrickson , and + * Michael Spiceland + * + * Copyright (C) 2007-2009 Digium, Inc. + * + * All rights reserved. + + * VoiceBus is a registered trademark of Digium. + * + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include "voicebus.h" +#include "vpmadtreg.h" +#include "GpakCust.h" + +#define assert(__x__) BUG_ON(!(__x__)) + +#define INTERRUPT 0 /* Run the deferred processing in the ISR. */ +#define TASKLET 1 /* Run in a tasklet. */ +#define TIMER 2 /* Run in a system timer. */ +#define WORKQUEUE 3 /* Run in a workqueue. */ +#ifndef VOICEBUS_DEFERRED +#define VOICEBUS_DEFERRED INTERRUPT +#endif +#if VOICEBUS_DEFERRED == WORKQUEUE +#define VOICEBUS_ALLOC_FLAGS GFP_KERNEL +#else +#define VOICEBUS_ALLOC_FLAGS GFP_ATOMIC +#endif + +#if VOICEBUS_DEFERRED == TIMER +#if HZ < 1000 +/* \todo Put an error message here. */ +#endif +#endif + +/*! The number of descriptors in both the tx and rx descriptor ring. */ +#define DRING_SIZE (1 << 5) /* Must be a power of 2 */ +#define DRING_MASK (DRING_SIZE-1) + +/* Interrupt status' reported in SR_CSR5 */ +#define TX_COMPLETE_INTERRUPT 0x00000001 +#define TX_STOPPED_INTERRUPT 0x00000002 +#define TX_UNAVAILABLE_INTERRUPT 0x00000004 +#define TX_JABBER_TIMEOUT_INTERRUPT 0x00000008 +#define TX_UNDERFLOW_INTERRUPT 0x00000020 +#define RX_COMPLETE_INTERRUPT 0x00000040 +#define RX_UNAVAILABLE_INTERRUPT 0x00000080 +#define RX_STOPPED_INTERRUPT 0x00000100 +#define RX_WATCHDOG_TIMEOUT_INTERRUPT 0x00000200 +#define TIMER_INTERRUPT 0x00000800 +#define FATAL_BUS_ERROR_INTERRUPT 0x00002000 +#define ABNORMAL_INTERRUPT_SUMMARY 0x00008000 +#define NORMAL_INTERRUPT_SUMMARY 0x00010000 + +#define SR_CSR5 0x0028 +#define NAR_CSR6 0x0030 + +#define IER_CSR7 0x0038 +#define CSR7_TCIE 0x00000001 /* tx complete */ +#define CSR7_TPSIE 0x00000002 /* tx processor stopped */ +#define CSR7_TDUIE 0x00000004 /* tx desc unavailable */ +#define CSR7_TUIE 0x00000020 /* tx underflow */ +#define CSR7_RCIE 0x00000040 /* rx complete */ +#define CSR7_RUIE 0x00000080 /* rx desc unavailable */ +#define CSR7_RSIE 0x00000100 /* rx processor stopped */ +#define CSR7_FBEIE 0x00002000 /* fatal bus error */ +#define CSR7_AIE 0x00008000 /* abnormal enable */ +#define CSR7_NIE 0x00010000 /* normal enable */ + +#define DEFAULT_INTERRUPTS (CSR7_TCIE | CSR7_TPSIE | CSR7_TDUIE | \ + CSR7_RUIE | CSR7_RSIE | CSR7_FBEIE | \ + CSR7_AIE | CSR7_NIE) + +#define CSR9 0x0048 +#define CSR9_MDC 0x00010000 +#define CSR9_MDO 0x00020000 +#define CSR9_MMC 0x00040000 +#define CSR9_MDI 0x00080000 + +#define OWN_BIT (1 << 31) + +/* In memory structure shared by the host and the adapter. */ +struct voicebus_descriptor { + u32 des0; + u32 des1; + u32 buffer1; + u32 container; /* Unused */ +} __attribute__((packed)); + +struct voicebus_descriptor_list { + /* Pointer to an array of descriptors to give to hardware. */ + struct voicebus_descriptor *desc; + /* Read completed buffers from the head. */ + unsigned int head; + /* Write ready buffers to the tail. */ + unsigned int tail; + /* Array to save the kernel virtual address of pending buffers. */ + void *pending[DRING_SIZE]; + /* PCI Bus address of the descriptor list. */ + dma_addr_t desc_dma; + /*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */ + unsigned int direction; + /*! The number of buffers currently submitted to the hardware. */ + atomic_t count; + /*! The number of bytes to pad each descriptor for cache alignment. */ + unsigned int padding; +}; + + +/*! * \brief Represents a VoiceBus interface on a Digium telephony card. + */ +struct voicebus { + /*! Name of this card. */ + const char *board_name; + /*! The system pci device for this VoiceBus interface. */ + struct pci_dev *pdev; + /*! Protects access to card registers and this structure. You should + * hold this lock before accessing most of the members of this data + * structure or the card registers. */ + spinlock_t lock; + /*! The size of the transmit and receive buffers for this card. */ + u32 framesize; + /*! The number of u32s in the host system cache line. */ + u8 cache_line_size; + /*! Pool to allocate memory for the tx and rx descriptor rings. */ + struct voicebus_descriptor_list rxd; + struct voicebus_descriptor_list txd; + /*! Level of debugging information. 0=None, 5=Insane. */ + atomic_t debuglevel; + /*! Cache of buffer objects. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + kmem_cache_t *buffer_cache; +#else + struct kmem_cache *buffer_cache; +#endif + /*! Base address of the VoiceBus interface registers in I/O space. */ + u32 iobase; + /*! The IRQ line for this VoiceBus interface. */ + unsigned int irq; +#if VOICEBUS_DEFERRED == WORKQUEUE + /*! Process buffers in the context of this workqueue. */ + struct workqueue_struct *workqueue; + /*! Work item to process tx / rx buffers. */ + struct work_struct workitem; +#elif VOICEBUS_DEFERRED == TASKLET + /*! Process buffers in the context of a tasklet. */ + struct tasklet_struct tasklet; +#elif VOICEBUS_DEFERRED == TIMER + /*! Process buffers in a timer without generating interrupts. */ + struct timer_list timer; +#endif + /*! Callback function to board specific module to process frames. */ + void (*handle_receive)(void *vbb, void *context); + void (*handle_transmit)(void *vbb, void *context); + /*! Data to pass to the receive and transmit callback. */ + void *context; + struct completion stopped_completion; + /*! Flags */ + unsigned long flags; + /* \todo see about removing this... */ + u32 sdi; + /*! Number of tx buffers to queue up before enabling interrupts. */ + unsigned int min_tx_buffer_count; +}; + +/* + * Use the following macros to lock the VoiceBus interface, and it won't + * matter if the deferred processing is running inside the interrupt handler, + * in a tasklet, or in a workqueue. + */ +#if VOICEBUS_DEFERRED == WORKQUEUE +/* + * When the deferred processing is running in a workqueue, voicebus will never + * be locked from the context of the interrupt handler, and therefore we do + * not need to lock interrupts. + */ +#define LOCKS_VOICEBUS +#define LOCKS_FROM_DEFERRED +#define VBLOCK(_vb_) spin_lock(&((_vb_)->lock)) +#define VBUNLOCK(_vb_) spin_unlock(&((_vb_)->lock)) +#define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) +#define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) +#else +#define LOCKS_VOICEBUS unsigned long _irqflags +#define LOCKS_FROM_DEFERRED +#define VBLOCK(_vb_) spin_lock_irqsave(&((_vb_)->lock), _irqflags) +#define VBUNLOCK(_vb_) spin_unlock_irqrestore(&((_vb_)->lock), _irqflags) +#define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) +#define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) +#endif + +#define VB_PRINTK(_vb, _lvl, _fmt, _args...) \ + printk(KERN_##_lvl "%s: " _fmt, (_vb)->board_name, ## _args) + +/* Bit definitions for struct voicebus.flags */ +#define TX_UNDERRUN 1 +#define RX_UNDERRUN 2 +#define IN_DEFERRED_PROCESSING 3 +#define STOP 4 +#define STOPPED 5 + +#if VOICEBUS_DEFERRED == WORKQUEUE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +/*! \brief Make the current task real-time. */ +static void +vb_setup_deferred(void *data) +#else +static void +vb_setup_deferred(struct work_struct *work) +#endif +{ + struct sched_param param = { .sched_priority = 99 }; + sched_setscheduler(current, SCHED_FIFO, ¶m); +} +/*! \brief Schedule a work item to make the voicebus workqueue real-time. */ +static void +vb_set_workqueue_priority(struct voicebus *vb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + DECLARE_WORK(deferred_setup, vb_setup_deferred, NULL); +#else + DECLARE_WORK(deferred_setup, vb_setup_deferred); +#endif + queue_work(vb->workqueue, &deferred_setup); + flush_workqueue(vb->workqueue); +} +#endif +#endif + +#ifdef DBG +static inline int +assert_in_vb_deferred(struct voicebus *vb) +{ + assert(test_bit(IN_DEFERRED_PROCESSING, &vb->flags)); +} + +static inline void +start_vb_deferred(struct voicebus *vb) +{ + set_bit(IN_DEFERRED_PROCESSING, &vb->flags); +} + +static inline void +stop_vb_deferred(struct voicebus *vb) +{ + clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); +} +#else +#define assert_in_vb_deferred(_x_) do {; } while (0) +#define start_vb_deferred(_x_) do {; } while (0) +#define stop_vb_deferred(_x_) do {; } while (0) +#endif + +static inline struct voicebus_descriptor * +vb_descriptor(struct voicebus_descriptor_list *dl, int index) +{ + struct voicebus_descriptor *d; + d = (struct voicebus_descriptor *)((u8*)dl->desc + + ((sizeof(*d) + dl->padding) * index)); + return d; +} + +static int +vb_initialize_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl, + u32 des1, unsigned int direction) +{ + int i; + struct voicebus_descriptor *d; + const u32 END_OF_RING = 0x02000000; + + assert(dl); + + /* + * Add some padding to each descriptor to ensure that they are + * aligned on host system cache-line boundaries, but only for the + * cache-line sizes that we support. + * + */ + if ((0x08 == vb->cache_line_size) || (0x10 == vb->cache_line_size) || + (0x20 == vb->cache_line_size)) { + dl->padding = (vb->cache_line_size*sizeof(u32)) - sizeof(*d); + } else { + dl->padding = 0; + } + + dl->desc = pci_alloc_consistent(vb->pdev, + (sizeof(*d) + dl->padding) * DRING_SIZE, &dl->desc_dma); + if (!dl->desc) + return -ENOMEM; + + memset(dl->desc, 0, (sizeof(*d) + dl->padding) * DRING_SIZE); + for (i = 0; i < DRING_SIZE; ++i) { + d = vb_descriptor(dl, i); + d->des1 = des1; + } + d->des1 |= cpu_to_le32(END_OF_RING); + dl->direction = direction; + atomic_set(&dl->count, 0); + return 0; +} + +static int +vb_initialize_tx_descriptors(struct voicebus *vb) +{ + return vb_initialize_descriptors( + vb, &vb->txd, 0xe4800000 | vb->framesize, DMA_TO_DEVICE); +} + +static int +vb_initialize_rx_descriptors(struct voicebus *vb) +{ + return vb_initialize_descriptors( + vb, &vb->rxd, vb->framesize, DMA_FROM_DEVICE); +} + +/*! \brief Use to set the minimum number of buffers queued to the hardware + * before enabling interrupts. + */ +int +voicebus_set_minlatency(struct voicebus *vb, unsigned int ms) +{ + LOCKS_VOICEBUS; + /* + * One millisecond of latency means that we have 3 buffers pending, + * since two are always going to be waiting in the TX fifo on the + * interface chip. + * + */ +#define MESSAGE "%d ms is an invalid value for minumum latency. Setting to %d ms.\n" + if (DRING_SIZE < ms) { + VB_PRINTK(vb, WARNING, MESSAGE, ms, DRING_SIZE); + return -EINVAL; + } else if (VOICEBUS_DEFAULT_LATENCY > ms) { + VB_PRINTK(vb, WARNING, MESSAGE, ms, VOICEBUS_DEFAULT_LATENCY); + return -EINVAL; + } + VBLOCK(vb); + vb->min_tx_buffer_count = 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 +voicebus_current_latency(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + int latency; + VBLOCK(vb); + latency = vb->min_tx_buffer_count; + VBUNLOCK(vb); + return latency; +} +EXPORT_SYMBOL(voicebus_current_latency); + +/*! + * \brief Read one of the hardware control registers without acquiring locks. + */ +static inline u32 +__vb_getctl(struct voicebus *vb, u32 addr) +{ + return le32_to_cpu(inl(vb->iobase + addr)); +} + +/*! + * \brief Read one of the hardware control registers with locks held. + */ +static inline u32 +vb_getctl(struct voicebus *vb, u32 addr) +{ + LOCKS_VOICEBUS; + u32 val; + VBLOCK(vb); + val = __vb_getctl(vb, addr); + VBUNLOCK(vb); + return val; +} + +/*! + * \brief Returns whether or not the interface is running. + * + * NOTE: Running in this case means whether or not the hardware reports the + * transmit processor in any state but stopped. + * + * \return 1 of the process is stopped, 0 if running. + */ +static int +vb_is_stopped(struct voicebus *vb) +{ + u32 reg; + reg = vb_getctl(vb, SR_CSR5); + reg = (reg >> 17) & 0x38; + return (0 == reg) ? 1 : 0; +} + +static void +vb_cleanup_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) +{ + unsigned int i; + struct voicebus_descriptor *d; + + assert(vb_is_stopped(vb)); + + for (i = 0; i < DRING_SIZE; ++i) { + d = vb_descriptor(dl, i); + if (d->buffer1) { + d->buffer1 = 0; + assert(dl->pending[i]); + voicebus_free(vb, dl->pending[i]); + dl->pending[i] = NULL; + } + d->des0 &= ~OWN_BIT; + } + dl->head = 0; + dl->tail = 0; + atomic_set(&dl->count, 0); +} + +static void +vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) +{ + if (NULL == dl->desc) { + WARN_ON(1); + return; + } + vb_cleanup_descriptors(vb, dl); + pci_free_consistent( + vb->pdev, + (sizeof(struct voicebus_descriptor)+dl->padding)*DRING_SIZE, + dl->desc, dl->desc_dma); +} + +/*! + * \brief Write one of the hardware control registers without acquiring locks. + */ +static inline void +__vb_setctl(struct voicebus *vb, u32 addr, u32 val) +{ + wmb(); + outl(cpu_to_le32(val), vb->iobase + addr); +} + +/*! + * \brief Write one of the hardware control registers with locks held. + */ +static inline void +vb_setctl(struct voicebus *vb, u32 addr, u32 val) +{ + LOCKS_VOICEBUS; + VBLOCK(vb); + __vb_setctl(vb, addr, val); + VBUNLOCK(vb); +} + +static int +__vb_sdi_clk(struct voicebus *vb) +{ + unsigned int ret; + vb->sdi &= ~CSR9_MDC; + __vb_setctl(vb, 0x0048, vb->sdi); + ret = __vb_getctl(vb, 0x0048); + vb->sdi |= CSR9_MDC; + __vb_setctl(vb, 0x0048, vb->sdi); + return (ret & CSR9_MDI) ? 1 : 0; +} + +static void +__vb_sdi_sendbits(struct voicebus *vb, u32 bits, int count) +{ + vb->sdi &= ~CSR9_MMC; + __vb_setctl(vb, 0x0048, vb->sdi); + while (count--) { + + if (bits & (1 << count)) + vb->sdi |= CSR9_MDO; + else + vb->sdi &= ~CSR9_MDO; + + __vb_sdi_clk(vb); + } +} + +static void +vb_setsdi(struct voicebus *vb, int addr, u16 val) +{ + LOCKS_VOICEBUS; + u32 bits; + /* Send preamble */ + bits = 0xffffffff; + VBLOCK(vb); + __vb_sdi_sendbits(vb, bits, 32); + bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; + __vb_sdi_sendbits(vb, bits, 16); + __vb_sdi_sendbits(vb, val, 16); + VBUNLOCK(vb); +} + +static void +vb_enable_io_access(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + u32 reg; + assert(vb->pdev); + VBLOCK(vb); + pci_read_config_dword(vb->pdev, 0x0004, ®); + reg |= 0x00000007; + pci_write_config_dword(vb->pdev, 0x0004, reg); + VBUNLOCK(vb); +} + +/*! \todo Insert comments... + * context: !in_interrupt() + */ +void* +voicebus_alloc(struct voicebus *vb) +{ + void *vbb; + vbb = kmem_cache_alloc(vb->buffer_cache, VOICEBUS_ALLOC_FLAGS); + return vbb; +} + +void +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 +vb_reset_interface(struct voicebus *vb) +{ + unsigned long timeout; + u32 reg; + u32 pci_access; + const u32 DEFAULT_PCI_ACCESS = 0xfff80002; + BUG_ON(in_interrupt()); + + switch (vb->cache_line_size) { + case 0x08: + pci_access = DEFAULT_PCI_ACCESS | (0x1 << 14); + break; + case 0x10: + pci_access = DEFAULT_PCI_ACCESS | (0x2 << 14); + break; + case 0x20: + pci_access = DEFAULT_PCI_ACCESS | (0x3 << 14); + break; + default: + if (atomic_read(&vb->debuglevel)) + VB_PRINTK(vb, WARNING, "Host system set a cache size "\ + "of %d which is not supported. " \ + "Disabling memory write line and memory read line.\n", + vb->cache_line_size); + pci_access = 0xfe584202; + break; + } + + /* The transmit and receive descriptors will have the same padding. */ + pci_access |= ((vb->txd.padding / sizeof(u32)) << 2) & 0x7c; + + vb_setctl(vb, 0x0000, pci_access | 1); + + timeout = jiffies + HZ/10; /* 100ms interval */ + do { + reg = vb_getctl(vb, 0x0000); + } while ((reg & 0x00000001) && time_before(jiffies, timeout)); + + if (reg & 0x00000001) { + VB_PRINTK(vb, ERR, "Hardware did not come out of reset "\ + "within 100ms!"); + return -EIO; + } + + vb_setctl(vb, 0x0000, pci_access); + + return 0; +} + +static int +vb_initialize_interface(struct voicebus *vb) +{ + u32 reg; + + vb_cleanup_descriptors(vb, &vb->txd); + vb_cleanup_descriptors(vb, &vb->rxd); + + /* Pass bad packets, runt packets, disable SQE function, + * store-and-forward */ + vb_setctl(vb, 0x0030, 0x00280048); + /* ...disable jabber and the receive watchdog. */ + vb_setctl(vb, 0x0078, 0x00000013); + + /* Tell the card where the descriptors are in host memory. */ + vb_setctl(vb, 0x0020, (u32)vb->txd.desc_dma); + vb_setctl(vb, 0x0018, (u32)vb->rxd.desc_dma); + + reg = vb_getctl(vb, 0x00fc); + vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x7); + vb_setsdi(vb, 0x00, 0x0100); + vb_setsdi(vb, 0x16, 0x2100); + + reg = vb_getctl(vb, 0x00fc); + + vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x4); + vb_setsdi(vb, 0x00, 0x0100); + vb_setsdi(vb, 0x16, 0x2100); + reg = vb_getctl(vb, 0x00fc); + + /* + * The calls to setsdi above toggle the reset line of the CPLD. Wait + * here to give the CPLD time to stabilize after reset. + */ + msleep(10); + + return ((reg&0x7) == 0x4) ? 0 : -EIO; +} + +#define OWNED(_d_) (((_d_)->des0)&OWN_BIT) +#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb(); } while (0) + +#ifdef DBG +static void +dump_descriptor(struct voicebus *vb, volatile struct voicebus_descriptor *d) +{ + VB_PRINTK(vb, DEBUG, "Displaying descriptor at address %08x\n", (unsigned int)d); + VB_PRINTK(vb, DEBUG, " des0: %08x\n", d->des0); + VB_PRINTK(vb, DEBUG, " des1: %08x\n", d->des1); + VB_PRINTK(vb, DEBUG, " buffer1: %08x\n", d->buffer1); + VB_PRINTK(vb, DEBUG, " container: %08x\n", d->container); +} + +static void +show_buffer(struct voicebus *vb, void *vbb) +{ + int x; + unsigned char *c; + c = vbb; + printk(KERN_DEBUG "Packet %d\n", count); + printk(KERN_DEBUG ""); + for (x = 1; x <= vb->framesize; ++x) { + printk("%02x ", c[x]); + if (x % 16 == 0) + printk("\n"); + } + printk(KERN_DEBUG "\n\n"); +} +#endif + +static inline int +vb_submit(struct voicebus *vb, struct voicebus_descriptor_list *dl, void *vbb) +{ + volatile struct voicebus_descriptor *d; + unsigned int tail = dl->tail; + assert_in_vb_deferred(vb); + + d = vb_descriptor(dl, tail); + + if (unlikely(d->buffer1)) { + /* Do not overwrite a buffer that is still in progress. */ + WARN_ON(1); + voicebus_free(vb, vbb); + return -EBUSY; + } + + dl->pending[tail] = vbb; + dl->tail = (++tail) & DRING_MASK; + d->buffer1 = dma_map_single( + &vb->pdev->dev, vbb, vb->framesize, dl->direction); + SET_OWNED(d); /* That's it until the hardware is done with it. */ + atomic_inc(&dl->count); + return 0; +} + +static inline void* +vb_retrieve(struct voicebus *vb, struct voicebus_descriptor_list *dl) +{ + volatile struct voicebus_descriptor *d; + void *vbb; + unsigned int head = dl->head; + assert_in_vb_deferred(vb); + d = vb_descriptor(dl, head); + if (d->buffer1 && !OWNED(d)) { + dma_unmap_single(&vb->pdev->dev, d->buffer1, + vb->framesize, dl->direction); + vbb = dl->pending[head]; + dl->head = (++head) & DRING_MASK; + d->buffer1 = 0; + atomic_dec(&dl->count); + return vbb; + } else { + return NULL; + } +} + +/*! + * \brief Give a frame to the hardware to transmit. + * + */ +int +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. + * + */ +static inline int +vb_submit_rxb(struct voicebus *vb, void *vbb) +{ + return vb_submit(vb, &vb->rxd, vbb); +} + +/*! + * \brief Remove the next completed transmit buffer (txb) from the tx + * descriptor ring. + * + * NOTE: This function doesn't need any locking because only one instance is + * ever running on the deferred processing routine and it only looks at + * the head pointer. The deferred routine should only ever be running + * on one processor at a time (no multithreaded workqueues allowed!) + * + * Context: Must be called from the voicebus deferred workqueue. + * + * \return Pointer to buffer, or NULL if not available. + */ +static inline void * +vb_get_completed_txb(struct voicebus *vb) +{ + return vb_retrieve(vb, &vb->txd); +} + +static inline void * +vb_get_completed_rxb(struct voicebus *vb) +{ + return vb_retrieve(vb, &vb->rxd); +} + +/*! + * \brief Free a buffer for reuse. + * + */ +void +voicebus_free(struct voicebus *vb, void *vbb) +{ + kmem_cache_free(vb->buffer_cache, vbb); +} + +/*! + * \brief Instruct the hardware to check for a new tx descriptor. + */ +static inline void +__vb_tx_demand_poll(struct voicebus *vb) +{ + __vb_setctl(vb, 0x0008, 0x00000000); +} + +/*! + * \brief Command the hardware to check if it owns the next transmit + * descriptor. + */ +static void +vb_tx_demand_poll(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + VBLOCK(vb); + __vb_tx_demand_poll(vb); + VBUNLOCK(vb); +} + +/*! + * \brief Command the hardware to check if it owns the next receive + * descriptor. + */ +static inline void +__vb_rx_demand_poll(struct voicebus *vb) +{ + __vb_setctl(vb, 0x0010, 0x00000000); +} + +static void +vb_rx_demand_poll(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + VBLOCK(vb); + __vb_rx_demand_poll(vb); + VBUNLOCK(vb); +} + +static void +__vb_enable_interrupts(struct voicebus *vb) +{ + __vb_setctl(vb, IER_CSR7, DEFAULT_INTERRUPTS); +} + +static void +__vb_disable_interrupts(struct voicebus *vb) +{ + __vb_setctl(vb, IER_CSR7, 0); +} + +static void +vb_disable_interrupts(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + VBLOCK(vb); + __vb_disable_interrupts(vb); + VBUNLOCK(vb); +} + +/*! + * \brief Starts the VoiceBus interface. + * + * When the VoiceBus interface is started, it is actively transferring + * frames to and from the backend of the card. This means the card will + * generate interrupts. + * + * This function should only be called from process context, with interrupts + * enabled, since it can sleep while running the self checks. + * + * \return zero on success. -EBUSY if device is already running. + */ +int +voicebus_start(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + u32 reg; + int i; + void *vbb; + int ret; + + assert(!in_interrupt()); + + if (!vb_is_stopped(vb)) + return -EBUSY; + + ret = vb_reset_interface(vb); + if (ret) + return ret; + ret = vb_initialize_interface(vb); + if (ret) + return ret; + + /* We must set up a minimum of three buffers to start with, since two + * are immediately read into the TX FIFO, and the descriptor of the + * third is read as soon as the first buffer is done. + */ + + /* + * NOTE: handle_transmit is normally only called in the context of the + * deferred processing thread. Since the deferred processing thread + * is known to not be running at this point, it is safe to call the + * handle transmit as if it were. + */ + start_vb_deferred(vb); + /* Ensure that all the rx slots are ready for a buffer. */ + for (i = 0; i < DRING_SIZE; ++i) { + vbb = voicebus_alloc(vb); + if (unlikely(NULL == vbb)) { + BUG_ON(1); + /* \todo I need to make sure the driver can recover + * from this condition. .... */ + } else { + vb_submit_rxb(vb, vbb); + } + } + + for (i = 0; i < vb->min_tx_buffer_count; ++i) { + vbb = voicebus_alloc(vb); + + if (unlikely(NULL == vbb)) + BUG_ON(1); + else + vb->handle_transmit(vbb, vb->context); + + } + stop_vb_deferred(vb); + + VBLOCK(vb); + clear_bit(STOP, &vb->flags); + clear_bit(STOPPED, &vb->flags); +#if VOICEBUS_DEFERRED == TIMER + vb->timer.expires = jiffies + HZ/1000; + add_timer(&vb->timer); +#else + /* Clear the interrupt status register. */ + __vb_setctl(vb, SR_CSR5, 0xffffffff); + __vb_enable_interrupts(vb); +#endif + /* Start the transmit and receive processors. */ + reg = __vb_getctl(vb, 0x0030); + __vb_setctl(vb, 0x0030, reg|0x00002002); + /* Tell the interface to poll the tx and rx descriptors. */ + __vb_rx_demand_poll(vb); + __vb_tx_demand_poll(vb); + VBUNLOCK(vb); + + assert(!vb_is_stopped(vb)); + + return 0; +} +EXPORT_SYMBOL(voicebus_start); + +static void +vb_clear_start_transmit_bit(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + u32 reg; + VBLOCK(vb); + reg = __vb_getctl(vb, NAR_CSR6); + reg &= ~0x00002000; + __vb_setctl(vb, NAR_CSR6, reg); + VBUNLOCK(vb); +} + +static void +vb_clear_start_receive_bit(struct voicebus *vb) +{ + LOCKS_VOICEBUS; + u32 reg; + VBLOCK(vb); + reg = __vb_getctl(vb, NAR_CSR6); + reg &= ~0x00000002; + __vb_setctl(vb, NAR_CSR6, reg); + VBUNLOCK(vb); +} + +static unsigned long +vb_wait_for_completion_timeout(struct completion *x, unsigned long timeout) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) + /* There is a race condition here. If x->done is reset to 0 + * before the call to wait_for_completion after this thread wakes. + */ + timeout = wait_event_timeout(x->wait, x->done, timeout); + if (timeout) + wait_for_completion(x); + + return timeout; +#else + return wait_for_completion_timeout(x, timeout); +#endif +} + +/*! + * \brief Stops the VoiceBus interface. + * + * Stops the VoiceBus interface and waits for any outstanding DMA transactions + * to complete. When this functions returns the VoiceBus interface tx and rx + * states will both be suspended. + * + * Only call this function from process context, with interrupt enabled, + * without any locks held since it sleeps. + * + * \return zero on success, -1 on error. + */ +int +voicebus_stop(struct voicebus *vb) +{ + assert(!in_interrupt()); + + if (vb_is_stopped(vb)) + return 0; + + INIT_COMPLETION(vb->stopped_completion); + set_bit(STOP, &vb->flags); + vb_clear_start_transmit_bit(vb); + vb_clear_start_receive_bit(vb); + if (vb_wait_for_completion_timeout(&vb->stopped_completion, HZ)) { + assert(vb_is_stopped(vb)); + } else { + VB_PRINTK(vb, WARNING, "Timeout while waiting for board to "\ + "stop.\n"); + + + vb_clear_start_transmit_bit(vb); + vb_clear_start_receive_bit(vb); + set_bit(STOPPED, &vb->flags); + vb_disable_interrupts(vb); + } + +#if VOICEBUS_DEFERRED == TIMER + del_timer_sync(&vb->timer); +#endif + + return 0; +} +EXPORT_SYMBOL(voicebus_stop); + +/*! + * \brief Prepare the interface for module unload. + * + * Stop the interface and free all the resources allocated by the driver. The + * caller should have returned all VoiceBus buffers to the VoiceBus layer + * before calling this function. + * + * context: !in_interrupt() + */ +void +voicebus_release(struct voicebus *vb) +{ + assert(!in_interrupt()); + + /* quiesce the hardware */ + voicebus_stop(vb); +#if VOICEBUS_DEFERRED == WORKQUEUE + destroy_workqueue(vb->workqueue); +#elif VOICEBUS_DEFERRED == TASKLET + tasklet_kill(&vb->tasklet); +#endif + vb_reset_interface(vb); +#if VOICEBUS_DEFERRED != TIMER + free_irq(vb->pdev->irq, vb); +#endif + + /* Cleanup memory and software resources. */ + vb_free_descriptors(vb, &vb->txd); + vb_free_descriptors(vb, &vb->rxd); + kmem_cache_destroy(vb->buffer_cache); + release_region(vb->iobase, 0xff); + pci_disable_device(vb->pdev); + kfree(vb); +} +EXPORT_SYMBOL(voicebus_release); + +static void +__vb_increase_latency(struct voicebus *vb) +{ + static int __warn_once = 1; + void *vbb; + int latency; + + assert_in_vb_deferred(vb); + + latency = atomic_read(&vb->txd.count); + if (DRING_SIZE == latency) { + if (__warn_once) { + /* We must subtract two from this number since there + * are always two buffers in the TX FIFO. + */ + VB_PRINTK(vb, ERR, + "ERROR: Unable to service card within %d ms "\ + "and unable to further increase latency.\n", + DRING_SIZE-2); + __warn_once = 0; + } + } else { + /* Because there are 2 buffers in the transmit FIFO on the + * hardware, setting 3 ms of latency means that the host needs + * to be able to service the cards within 1ms. This is because + * the interface will load up 2 buffers into the TX FIFO then + * attempt to read the 3rd descriptor. If the OWN bit isn't + * set, then the hardware will set the TX descriptor not + * available interrupt. + */ + VB_PRINTK(vb, INFO, "Missed interrupt. " \ + "Increasing latency to %d ms in order to compensate.\n", + latency+1); + /* Set the minimum latency in case we're restarted...we don't + * want to wait for the buffer to grow to this depth again in + * that case. + */ + voicebus_set_minlatency(vb, latency+1); + vbb = voicebus_alloc(vb); + + if (unlikely(NULL == vbb)) + BUG_ON(1); + else + vb->handle_transmit(vbb, vb->context); + + } +} + +/*! + * \brief Actually process the completed transmit and receive buffers. + * + * NOTE: This function may be called either from a tasklet, workqueue, or + * directly in the interrupt service routine depending on + * VOICEBUS_DEFERRED. + */ +static inline void +vb_deferred(struct voicebus *vb) +{ + void *vbb; +#ifdef DBG + static int count; +#endif + int underrun = test_bit(TX_UNDERRUN, &vb->flags); + + + start_vb_deferred(vb); + if (unlikely(underrun)) { + /* When we've underrun our FIFO, for some reason we're not + * able to keep enough transmit descriptors pending. This can + * happen if either interrupts or this deferred processing + * function is not run soon enough (within 1ms when using the + * default 3 transmit buffers to start). In this case, we'll + * insert an additional transmit buffer onto the descriptor + * list which decreases the sensitivity to latency, but also + * adds more delay to the TDM and SPI data. + */ + __vb_increase_latency(vb); + } + + /* Always handle the transmit buffers first. */ + while ((vbb = vb_get_completed_txb(vb))) + vb->handle_transmit(vbb, vb->context); + + if (unlikely(underrun)) { + vb_rx_demand_poll(vb); + vb_tx_demand_poll(vb); + clear_bit(TX_UNDERRUN, &vb->flags); + } + + while ((vbb = vb_get_completed_rxb(vb))) { + vb->handle_receive(vbb, vb->context); + vb_submit_rxb(vb, vbb); + } + + stop_vb_deferred(vb); +} + + +/*! + * \brief Interrupt handler for VoiceBus interface. + * + * NOTE: This handler is optimized for the case where only a single interrupt + * condition will be generated at a time. + * + * ALSO NOTE: Only access the interrupt status register from this function + * since it doesn't employ any locking on the voicebus interface. + */ +static irqreturn_t +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +vb_isr(int irq, void *dev_id, struct pt_regs *regs) +#else +vb_isr(int irq, void *dev_id) +#endif +{ + struct voicebus *vb = dev_id; + u32 int_status; + + int_status = __vb_getctl(vb, SR_CSR5); + /* Mask out the reserved bits. */ + int_status &= ~(0xfc004010); + int_status &= 0x7fff; + + if (!int_status) + return IRQ_NONE; + + if (likely(int_status & TX_COMPLETE_INTERRUPT)) { + /* ******************************************************** */ + /* NORMAL INTERRUPT CASE */ + /* ******************************************************** */ +# if VOICEBUS_DEFERRED == WORKQUEUE + queue_work(vb->workqueue, &vb->workitem); +# elif VOICEBUS_DEFERRED == TASKLET + tasklet_schedule(&vb->tasklet); +# else + vb_deferred(vb); +# endif + __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT); + } else { + /* ******************************************************** */ + /* ABNORMAL / ERROR CONDITIONS */ + /* ******************************************************** */ + if ((int_status & TX_UNAVAILABLE_INTERRUPT)) { + /* This can happen if the host fails to service the + * interrupt within the required time interval (1ms + * for each buffer on the queue). Increasing the + * depth of the tx queue (up to a maximum of + * DRING_SIZE) can make the driver / system more + * tolerant of interrupt latency under periods of + * heavy system load, but also increases the general + * latency that the driver adds to the voice + * conversations. + */ + set_bit(TX_UNDERRUN, &vb->flags); +# if VOICEBUS_DEFERRED == WORKQUEUE + queue_work(vb->workqueue, &vb->workitem); +# elif VOICEBUS_DEFERRED == TASKLET + tasklet_schedule(&vb->tasklet); +# else + vb_deferred(vb); +# endif + } + + if (int_status & FATAL_BUS_ERROR_INTERRUPT) + VB_PRINTK(vb, ERR, "Fatal Bus Error detected!\n"); + + if (int_status & TX_STOPPED_INTERRUPT) { + assert(test_bit(STOP, &vb->flags)); + __vb_disable_interrupts(vb); + complete(&vb->stopped_completion); + } + if (int_status & RX_STOPPED_INTERRUPT) { + assert(test_bit(STOP, &vb->flags)); + if (vb_is_stopped(vb)) { + __vb_disable_interrupts(vb); + complete(&vb->stopped_completion); + } + } + + /* Clear the interrupt(s) */ + __vb_setctl(vb, SR_CSR5, int_status); + } + + return IRQ_HANDLED; +} + +#if VOICEBUS_DEFERRED == TIMER +/*! \brief Called if the deferred processing is to happen in the context of + * the timer. + */ +static void +vb_timer(unsigned long data) +{ + unsigned long start = jiffies; + struct voicebus *vb = (struct voicebus *)data; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + vb_isr(0, vb, 0); +#else + vb_isr(0, vb); +#endif + if (!test_bit(STOPPED, &vb->flags)) { + vb->timer.expires = start + HZ/1000; + add_timer(&vb->timer); + } +} +#endif + +#if VOICEBUS_DEFERRED == WORKQUEUE +static void +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +vb_workfunc(void *data) +{ + struct voicebus *vb = data; +#else +vb_workfunc(struct work_struct *work) +{ + struct voicebus *vb = container_of(work, struct voicebus, workitem); +#endif + vb_deferred(vb); +} +#elif VOICEBUS_DEFERRED == TASKLET +static void +vb_tasklet(unsigned long data) +{ + struct voicebus *vb = (struct voicebus *)data; + vb_deferred(vb); +} +#endif /* #if VOICEBUS_DEFERRED == WORKQUEUE */ + +/*! + * \brief Initalize the voicebus interface. + * + * This function must be called in process context since it may sleep. + * \todo Complete this description. + */ +int +voicebus_init(struct pci_dev *pdev, u32 framesize, + const char *board_name, + void (*handle_receive)(void *vbb, void *context), + void (*handle_transmit)(void *vbb, void *context), + void *context, + u32 debuglevel, + struct voicebus **vbp + ) +{ + int retval = 0; + struct voicebus *vb; + + assert(NULL != pdev); + assert(NULL != board_name); + assert(framesize); + assert(NULL != handle_receive); + assert(NULL != handle_transmit); + + /* ---------------------------------------------------------------- + Initialize the pure software constructs. + ---------------------------------------------------------------- */ + *vbp = NULL; + vb = kmalloc(sizeof(*vb), GFP_KERNEL); + if (NULL == vb) { + VB_PRINTK(vb, DEBUG, "Failed to allocate memory for voicebus "\ + "interface.\n"); + retval = -ENOMEM; + goto cleanup; + } + memset(vb, 0, sizeof(*vb)); + voicebus_setdebuglevel(vb, debuglevel); + /* \todo make sure there is a note that the caller needs to make sure + * board_name stays in memory until voicebus_release is called. + */ + vb->board_name = board_name; + spin_lock_init(&vb->lock); + init_completion(&vb->stopped_completion); + vb->pdev = pdev; + set_bit(STOP, &vb->flags); + clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); + vb->framesize = framesize; + vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY; + +#if VOICEBUS_DEFERRED == WORKQUEUE + /* NOTE: This workqueue must be single threaded because locking is not + * used when buffers are removed or added to the descriptor list, and + * there should only be one producer / consumer (the hardware or the + * deferred processing function). */ + vb->workqueue = create_singlethread_workqueue(board_name); +# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&vb->workitem, vb_workfunc, vb); +# else + INIT_WORK(&vb->workitem, vb_workfunc); +# endif +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) + vb_set_workqueue_priority(vb); +# endif +#elif VOICEBUS_DEFERRED == TASKLET + tasklet_init(&vb->tasklet, vb_tasklet, (unsigned long)vb); +#elif VOICEBUS_DEFERRED == TIMER + init_timer(&vb->timer); + vb->timer.function = vb_timer; + vb->timer.data = (unsigned long)vb; +#endif + + vb->handle_receive = handle_receive; + vb->handle_transmit = handle_transmit; + vb->context = context; + + /* \todo This cache should be shared by all instances supported by + * this driver. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22) + SLAB_HWCACHE_ALIGN | SLAB_STORE_USER, NULL, NULL); +#else + SLAB_HWCACHE_ALIGN, NULL, NULL); +#endif +#else + vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, + SLAB_HWCACHE_ALIGN, NULL); +#endif + if (NULL == vb->buffer_cache) { + VB_PRINTK(vb, ERR, "Failed to allocate buffer cache.\n"); + goto cleanup; + } + + + /* ---------------------------------------------------------------- + Configure the hardware / kernel module interfaces. + ---------------------------------------------------------------- */ + if (pci_read_config_byte(vb->pdev, 0x0c, &vb->cache_line_size)) { + VB_PRINTK(vb, ERR, "Failed read of cache line " \ + "size from PCI configuration space.\n"); + goto cleanup; + } + + if (pci_enable_device(pdev)) { + VB_PRINTK(vb, ERR, "Failed call to pci_enable_device.\n"); + retval = -EIO; + goto cleanup; + } + + /* \todo This driver should be modified to use the memory mapped I/O + as opposed to IO space for portability and performance. */ + if (0 == (pci_resource_flags(pdev, 0)&IORESOURCE_IO)) { + VB_PRINTK(vb, ERR, "BAR0 is not IO Memory.\n"); + retval = -EIO; + goto cleanup; + } + vb->iobase = pci_resource_start(pdev, 0); + if (NULL == request_region(vb->iobase, 0xff, board_name)) { + VB_PRINTK(vb, ERR, "IO Registers are in use by another " \ + "module.\n"); + retval = -EIO; + goto cleanup; + } + + retval = vb_initialize_tx_descriptors(vb); + if (retval) + goto cleanup; + + retval = vb_initialize_rx_descriptors(vb); + if (retval) + goto cleanup; + + /* ---------------------------------------------------------------- + Configure the hardware interface. + ---------------------------------------------------------------- */ + pci_set_master(pdev); + vb_enable_io_access(vb); + +#if VOICEBUS_DEFERRED != TIMER +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +# define VB_IRQ_SHARED SA_SHIRQ +#else +# define VB_IRQ_SHARED IRQF_SHARED +#endif + if (request_irq(pdev->irq, vb_isr, VB_IRQ_SHARED, vb->board_name, + vb)) { + assert(0); + goto cleanup; + } +#endif + + *vbp = vb; + return retval; +cleanup: + if (NULL == vb) + return retval; + +#if VOICEBUS_DEFERRED == WORKQUEUE + + if (vb->workqueue) + destroy_workqueue(vb->workqueue); + +#elif VOICEBUS_DEFERRED == TASKLET + tasklet_kill(&vb->tasklet); +#endif + /* Cleanup memory and software resources. */ + + if (vb->txd.desc) + vb_free_descriptors(vb, &vb->txd); + + if (vb->rxd.desc) + vb_free_descriptors(vb, &vb->rxd); + + if (vb->buffer_cache) + kmem_cache_destroy(vb->buffer_cache); + + if (vb->iobase) + release_region(vb->iobase, 0xff); + + if (vb->pdev) + pci_disable_device(vb->pdev); + + kfree(vb); + assert(0 != retval); + return retval; +} +EXPORT_SYMBOL(voicebus_init); + + +/*! \brief Return the pci_dev in use by this voicebus interface. */ +struct pci_dev * +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 "); +MODULE_LICENSE("GPL"); + +module_init(voicebus_module_init); +module_exit(voicebus_module_cleanup); diff --git a/drivers/dahdi/voicebus/voicebus.h b/drivers/dahdi/voicebus/voicebus.h new file mode 100644 index 0000000..eaa51e6 --- /dev/null +++ b/drivers/dahdi/voicebus/voicebus.h @@ -0,0 +1,61 @@ +/* + * VoiceBus(tm) Interface Library. + * + * Written by Shaun Ruffell + * and based on previous work by Mark Spencer , + * Matthew Fredrickson , and + * Michael Spiceland + * + * Copyright (C) 2007-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 __VOICEBUS_H__ +#define __VOICEBUS_H__ + +struct voicebus; + +#define VOICEBUS_DEFAULT_LATENCY 3 + +void voicebus_setdebuglevel(struct voicebus *vb, u32 level); +int voicebus_getdebuglevel(struct voicebus *vb); +struct pci_dev * voicebus_get_pci_dev(struct voicebus *vb); +int voicebus_init(struct pci_dev* pdev, u32 framesize, + const char *board_name, + void (*handle_receive)(void *buffer, void *context), + void (*handle_transmit)(void *buffer, void *context), + 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); +void * voicebus_alloc(struct voicebus* vb); +void voicebus_free(struct voicebus *vb, void *vbb); +int voicebus_transmit(struct voicebus *vb, void *vbb); +int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds); +int voicebus_current_latency(struct voicebus *vb) ; + +#endif /* __VOICEBUS_H__ */ 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 + * + * 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 +#include +#include + +#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 + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +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 "); +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 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else -#include -#endif - -#include - -#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/GpakApi.h b/drivers/dahdi/wctdm24xxp/GpakApi.h deleted file mode 100644 index 2e55e64..0000000 --- a/drivers/dahdi/wctdm24xxp/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/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 -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else -#include -#endif - -#include - -#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/GpakCust.h b/drivers/dahdi/wctdm24xxp/GpakCust.h deleted file mode 100644 index f2b729f..0000000 --- a/drivers/dahdi/wctdm24xxp/GpakCust.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakCust.h - * - * Description: - * This file contains host system dependent definitions and prototypes of - * functions to support generic G.PAK API functions. The file is used when - * integrating G.PAK API functions in a specific host processor environment. - * - * Note: This file may need 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. - */ - -#ifndef _GPAKCUST_H /* prevent multiple inclusion */ -#define _GPAKCUST_H - -#include "wctdm24xxp.h" -#ifdef VPM150M_SUPPORT -#include -#include -#endif -#include "gpakenum.h" - - -struct wctdm_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 wctdm_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. - * - * FUNCTION - * This function reads a contiguous block of words from DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -extern 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 */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. - * - * FUNCTION - * This function writes a contiguous block of words to DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -extern 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 */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * 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 - * - */ -extern void gpakHostDelay(void); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. - * - * FUNCTION - * This function aquires exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -extern void gpakLockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. - * - * FUNCTION - * This function releases exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -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. - * - * 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) - * - */ -extern 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 */ - ); - - -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/wctdm24xxp/GpakHpi.h deleted file mode 100644 index ffbf349..0000000 --- a/drivers/dahdi/wctdm24xxp/GpakHpi.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2001, Adaptive Digital Technologies, Inc. - * - * File Name: GpakHpi.h - * - * Description: - * This file contains common definitions related to the G.PAK interface - * between a host processor and a DSP processor via the Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 10/17/01 - 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 _GPAKHPI_H /* prevent multiple inclusion */ -#define _GPAKHPI_H - - -/* Definition of G.PAK Command/Reply message type codes. */ -#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ -#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ -#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ -#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ -#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ -#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ -#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ -#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ -#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ -#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ -#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ -#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ -#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ -#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ -#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ - -#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ -#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ - -#define MSG_ALG_CONTROL 27 /* algorithm control */ -#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ -#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ -#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ - -#define MSG_PING 35 /* ping command */ -#define MSG_PING_REPLY 36 /* ping command reply */ -#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ -#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ -#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ -#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ -#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ -#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ - -#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ -#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ - -#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ -#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ - -#define MSG_ACCESSGPIO 51 -#define MSG_ACCESSGPIO_REPLY 52 -#endif /* prevent multiple inclusion */ 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 * Support for TDM800P and VPM150M by Matthew Fredrickson * - * Copyright (C) 2005 - 2008 Digium, Inc. + * Copyright (C) 2005 - 2009 Digium, Inc. * All rights reserved. * * Sections for QRV cards written by Jim Dixon @@ -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;xvpm && !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,601 +3213,20 @@ 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) +static int wctdm_vpm_init(struct wctdm *wc) { - 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) -{ - unsigned char reg; - unsigned int mask; - unsigned int ver; - unsigned char vpmver=0; - unsigned int i, x, y; - - if (!vpmsupport) { - printk(KERN_INFO "VPM: Support Disabled\n"); - wc->vpm = 0; - return; - } + unsigned char reg; + unsigned int mask; + unsigned int ver; + unsigned char vpmver=0; + unsigned int i, x, y; for (x=0;xvpm = 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;xcards;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/gpakErrs.h b/drivers/dahdi/wctdm24xxp/gpakErrs.h deleted file mode 100644 index c36a1b7..0000000 --- a/drivers/dahdi/wctdm24xxp/gpakErrs.h +++ /dev/null @@ -1,154 +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/wctdm24xxp/gpakenum.h b/drivers/dahdi/wctdm24xxp/gpakenum.h deleted file mode 100644 index f488a81..0000000 --- a/drivers/dahdi/wctdm24xxp/gpakenum.h +++ /dev/null @@ -1,191 +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/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 * Support for TDM800P and VPM150M by Matthew Fredrickson * - * Copyright (C) 2005, 2006, Digium, Inc. + * Copyright (C) 2005-2009 Digium, Inc. * * All rights reserved. * @@ -28,7 +28,6 @@ #include -#include "../voicebus.h" #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include @@ -36,6 +35,8 @@ #include #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.c b/drivers/dahdi/wcte12xp/GpakApi.c deleted file mode 100644 index 748cc94..0000000 --- a/drivers/dahdi/wcte12xp/GpakApi.c +++ /dev/null @@ -1,1615 +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 - -#include "GpakHpi.h" -#include "vpmadt032.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 */ -#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); - 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) - EventError = 1; - break; - - default: - 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); -} -#endif 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 -#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 - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * 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 -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#else -#include -#endif -#include -#include -#include - -#include - -#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 - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * 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 * William Meadows * - * 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; -- cgit v1.2.3